From 53270e70f81c6a260e4358d7b79754544ed1406e Mon Sep 17 00:00:00 2001 From: Jerry <707344974@qq.com> Date: Fri, 25 Sep 2020 10:45:02 +0800 Subject: [PATCH] =?UTF-8?q?commit=EF=BC=9A=E6=B7=BB=E5=8A=A0=E5=8D=95?= =?UTF-8?q?=E4=BD=93=E5=B7=A5=E7=A8=8B=E5=BC=80=E6=BA=90=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- orange-demo-service/zz-orange-demo.sql | 10 +- orange-demo-single-service/.DS_Store | Bin 0 -> 6148 bytes orange-demo-single-service/.gitignore | 26 + orange-demo-single-service/README.md | 3 + .../application-common/pom.xml | 24 + .../common/constant/DeviceType.java | 49 + .../application/common/constant/ExpLevel.java | 49 + .../application/common/constant/Gender.java | 44 + .../common/constant/StudentActionType.java | 89 + .../common/constant/StudentStatus.java | 49 + .../application/common/constant/Subject.java | 49 + .../application/pom.xml | 67 + .../java/com/orange/demo/MyApplication.java | 18 + .../app/controller/AreaCodeController.java | 56 + .../demo/app/controller/CourseController.java | 253 + .../CourseTransStatsController.java | 99 + .../demo/app/controller/GradeController.java | 114 + .../app/controller/SchoolInfoController.java | 167 + .../StudentActionStatsController.java | 99 + .../StudentActionTransController.java | 152 + .../controller/StudentClassController.java | 429 ++ .../app/controller/StudentController.java | 167 + .../orange/demo/app/dao/AreaCodeMapper.java | 13 + .../demo/app/dao/ClassCourseMapper.java | 13 + .../demo/app/dao/ClassStudentMapper.java | 13 + .../com/orange/demo/app/dao/CourseMapper.java | 52 + .../demo/app/dao/CourseTransStatsMapper.java | 41 + .../com/orange/demo/app/dao/GradeMapper.java | 13 + .../demo/app/dao/MaterialEditionMapper.java | 13 + .../orange/demo/app/dao/SchoolInfoMapper.java | 26 + .../app/dao/StudentActionStatsMapper.java | 41 + .../app/dao/StudentActionTransMapper.java | 26 + .../demo/app/dao/StudentClassMapper.java | 26 + .../orange/demo/app/dao/StudentMapper.java | 52 + .../demo/app/dao/mapper/AreaCodeMapper.xml | 10 + .../demo/app/dao/mapper/ClassCourseMapper.xml | 9 + .../app/dao/mapper/ClassStudentMapper.xml | 8 + .../demo/app/dao/mapper/CourseMapper.xml | 95 + .../app/dao/mapper/CourseTransStatsMapper.xml | 60 + .../demo/app/dao/mapper/GradeMapper.xml | 9 + .../app/dao/mapper/MaterialEditionMapper.xml | 9 + .../demo/app/dao/mapper/SchoolInfoMapper.xml | 35 + .../dao/mapper/StudentActionStatsMapper.xml | 86 + .../dao/mapper/StudentActionTransMapper.xml | 57 + .../app/dao/mapper/StudentClassMapper.xml | 40 + .../demo/app/dao/mapper/StudentMapper.xml | 101 + .../com/orange/demo/app/model/AreaCode.java | 41 + .../orange/demo/app/model/ClassCourse.java | 40 + .../orange/demo/app/model/ClassStudent.java | 33 + .../com/orange/demo/app/model/Course.java | 163 + .../demo/app/model/CourseTransStats.java | 122 + .../java/com/orange/demo/app/model/Grade.java | 42 + .../demo/app/model/MaterialEdition.java | 39 + .../com/orange/demo/app/model/SchoolInfo.java | 67 + .../com/orange/demo/app/model/Student.java | 224 + .../demo/app/model/StudentActionStats.java | 207 + .../demo/app/model/StudentActionTrans.java | 168 + .../orange/demo/app/model/StudentClass.java | 113 + .../demo/app/model/constant/ClassLevel.java | 49 + .../demo/app/model/constant/ClassStatus.java | 44 + .../app/model/constant/CourseDifficult.java | 49 + .../demo/app/service/AreaCodeService.java | 57 + .../demo/app/service/CourseService.java | 175 + .../app/service/CourseTransStatsService.java | 83 + .../orange/demo/app/service/GradeService.java | 88 + .../demo/app/service/SchoolInfoService.java | 129 + .../service/StudentActionStatsService.java | 85 + .../service/StudentActionTransService.java | 131 + .../demo/app/service/StudentClassService.java | 259 + .../demo/app/service/StudentService.java | 202 + .../orange/demo/config/ApplicationConfig.java | 46 + .../orange/demo/config/DataSourceConfig.java | 30 + .../com/orange/demo/config/FilterConfig.java | 57 + .../orange/demo/config/InterceptorConfig.java | 21 + .../AuthenticationInterceptor.java | 134 + .../demo/upms/controller/LoginController.java | 151 + .../upms/controller/SysMenuController.java | 160 + .../controller/SysPermCodeController.java | 180 + .../upms/controller/SysPermController.java | 197 + .../controller/SysPermModuleController.java | 157 + .../upms/controller/SysRoleController.java | 323 ++ .../upms/controller/SysUserController.java | 176 + .../orange/demo/upms/dao/SysMenuMapper.java | 23 + .../demo/upms/dao/SysMenuPermCodeMapper.java | 13 + .../demo/upms/dao/SysPermCodeMapper.java | 43 + .../demo/upms/dao/SysPermCodePermMapper.java | 13 + .../orange/demo/upms/dao/SysPermMapper.java | 61 + .../demo/upms/dao/SysPermModuleMapper.java | 22 + .../demo/upms/dao/SysPermWhitelistMapper.java | 13 + .../orange/demo/upms/dao/SysRoleMapper.java | 41 + .../demo/upms/dao/SysRoleMenuMapper.java | 13 + .../orange/demo/upms/dao/SysUserMapper.java | 52 + .../demo/upms/dao/SysUserRoleMapper.java | 22 + .../demo/upms/dao/mapper/SysMenuMapper.xml | 35 + .../upms/dao/mapper/SysMenuPermCodeMapper.xml | 8 + .../upms/dao/mapper/SysPermCodeMapper.xml | 84 + .../upms/dao/mapper/SysPermCodePermMapper.xml | 8 + .../demo/upms/dao/mapper/SysPermMapper.xml | 134 + .../upms/dao/mapper/SysPermModuleMapper.xml | 42 + .../dao/mapper/SysPermWhitelistMapper.xml | 9 + .../demo/upms/dao/mapper/SysRoleMapper.xml | 67 + .../upms/dao/mapper/SysRoleMenuMapper.xml | 8 + .../demo/upms/dao/mapper/SysUserMapper.xml | 79 + .../upms/dao/mapper/SysUserRoleMapper.xml | 15 + .../com/orange/demo/upms/model/SysMenu.java | 93 + .../demo/upms/model/SysMenuPermCode.java | 30 + .../com/orange/demo/upms/model/SysPerm.java | 81 + .../orange/demo/upms/model/SysPermCode.java | 89 + .../demo/upms/model/SysPermCodePerm.java | 30 + .../orange/demo/upms/model/SysPermModule.java | 77 + .../demo/upms/model/SysPermWhitelist.java | 35 + .../com/orange/demo/upms/model/SysRole.java | 83 + .../orange/demo/upms/model/SysRoleMenu.java | 30 + .../com/orange/demo/upms/model/SysUser.java | 145 + .../orange/demo/upms/model/SysUserRole.java | 30 + .../demo/upms/model/constant/SysMenuType.java | 54 + .../upms/model/constant/SysPermCodeType.java | 49 + .../model/constant/SysPermModuleType.java | 44 + .../upms/model/constant/SysUserStatus.java | 44 + .../demo/upms/model/constant/SysUserType.java | 49 + .../demo/upms/service/SysMenuService.java | 234 + .../demo/upms/service/SysPermCodeService.java | 204 + .../upms/service/SysPermModuleService.java | 118 + .../demo/upms/service/SysPermService.java | 257 + .../upms/service/SysPermWhitelistService.java | 32 + .../demo/upms/service/SysRoleService.java | 221 + .../demo/upms/service/SysUserService.java | 252 + .../src/main/resources/application.yml | 193 + .../application/src/main/resources/log4j2.xml | 70 + .../resources/template/views/print_error.ftl | 329 ++ .../common/common-core/pom.xml | 110 + .../core/advice/MyControllerAdvice.java | 30 + .../core/advice/MyExceptionHandler.java | 128 + .../core/annotation/DeletedFlagColumn.java | 16 + .../core/annotation/JobUpdateTimeColumn.java | 16 + .../common/core/annotation/MyDataSource.java | 21 + .../common/core/annotation/MyRequestBody.java | 31 + .../core/annotation/NoAuthInterface.java | 15 + .../core/annotation/RelationConstDict.java | 29 + .../common/core/annotation/RelationDict.java | 60 + .../core/annotation/RelationManyToMany.java | 36 + .../RelationManyToManyAggregation.java | 85 + .../RelationOneToManyAggregation.java | 57 + .../core/annotation/RelationOneToOne.java | 50 + .../demo/common/core/aop/AccessLogAspect.java | 84 + .../common/core/base/dao/BaseDaoMapper.java | 90 + .../core/base/mapper/BaseModelMapper.java | 124 + .../core/base/mapper/DummyModelMapper.java | 58 + .../core/base/service/BaseDictService.java | 149 + .../common/core/base/service/BaseService.java | 1380 +++++ .../demo/common/core/cache/CacheConfig.java | 90 + .../common/core/cache/DictionaryCache.java | 88 + .../common/core/cache/MapDictionaryCache.java | 176 + .../core/cache/MapTreeDictionaryCache.java | 142 + .../common/core/cache/SessionCacheHelper.java | 97 + .../core/config/CommonWebMvcConfig.java | 67 + .../common/core/config/EncryptConfig.java | 20 + .../core/config/RestTemplateConfig.java | 64 + .../demo/common/core/config/TomcatConfig.java | 39 + .../common/core/constant/AggregationType.java | 81 + .../core/constant/ApplicationConstant.java | 55 + .../common/core/constant/ErrorCodeEnum.java | 78 + .../core/constant/GlobalDeletedFlag.java | 25 + .../exception/DataValidationException.java | 26 + .../exception/InvalidClassFieldException.java | 30 + .../exception/InvalidDataFieldException.java | 30 + .../exception/InvalidDataModelException.java | 27 + .../core/exception/MyRuntimeException.java | 36 + .../core/exception/NoDataAffectException.java | 26 + .../core/exception/NoDataPermException.java | 26 + .../exception/RedisCacheAccessException.java | 20 + .../MyRequestArgumentResolver.java | 226 + .../core/listener/LoadCachedDataListener.java | 28 + .../listener/LoadServiceRelationListener.java | 28 + .../demo/common/core/object/CallResult.java | 87 + .../common/core/object/MyGroupCriteria.java | 24 + .../demo/common/core/object/MyGroupParam.java | 168 + .../demo/common/core/object/MyOrderParam.java | 258 + .../demo/common/core/object/MyPageParam.java | 58 + .../common/core/object/MyRelationParam.java | 84 + .../common/core/object/MyWhereCriteria.java | 308 + .../common/core/object/ResponseResult.java | 157 + .../demo/common/core/object/TokenData.java | 59 + .../demo/common/core/object/Tuple2.java | 50 + .../demo/common/core/util/AopTargetUtil.java | 58 + .../core/util/ApplicationContextHolder.java | 74 + .../demo/common/core/util/ContextUtil.java | 49 + .../demo/common/core/util/ExportUtil.java | 95 + .../demo/common/core/util/ImportUtil.java | 214 + .../orange/demo/common/core/util/IpUtil.java | 101 + .../orange/demo/common/core/util/JwtUtil.java | 110 + .../demo/common/core/util/LogMessageUtil.java | 33 + .../demo/common/core/util/MyCommonUtil.java | 144 + .../demo/common/core/util/MyDateUtil.java | 181 + .../demo/common/core/util/MyModelUtil.java | 437 ++ .../demo/common/core/util/MyPageUtil.java | 72 + .../orange/demo/common/core/util/RsaUtil.java | 114 + .../demo/common/core/util/TreeNode.java | 93 + .../demo/common/core/util/UpDownloadUtil.java | 180 + .../demo/common/core/validator/AddGroup.java | 10 + .../common/core/validator/ConstDictRef.java | 48 + .../core/validator/ConstDictValidator.java | 33 + .../common/core/validator/TextLength.java | 55 + .../core/validator/TextLengthValidator.java | 39 + .../common/core/validator/UpdateGroup.java | 11 + .../common/common-sequence/pom.xml | 24 + .../config/IdGeneratorAutoConfigure.java | 14 + .../config/IdGeneratorProperties.java | 20 + .../sequence/generator/BasicIdGenerator.java | 48 + .../sequence/generator/MyIdGenerator.java | 24 + .../sequence/wrapper/IdGeneratorWrapper.java | 52 + .../main/resources/META-INF/spring.factories | 2 + orange-demo-single-service/common/pom.xml | 18 + orange-demo-single-service/pom.xml | 149 + orange-demo-single-service/zz-orange-demo.sql | 5043 +++++++++++++++++ .../eef356943ce74b7b809dcce178cb92d2.png | Bin 0 -> 806 bytes orange-demo-single-web/.browserslistrc | 2 + orange-demo-single-web/.editorconfig | 5 + orange-demo-single-web/.eslintrc.js | 40 + orange-demo-single-web/.gitignore | 21 + orange-demo-single-web/README.md | 15 + orange-demo-single-web/babel.config.js | 5 + orange-demo-single-web/jest.config.js | 3 + orange-demo-single-web/package.json | 61 + orange-demo-single-web/public/favicon.ico | Bin 0 -> 4286 bytes .../img/icons/android-chrome-192x192.png | Bin 0 -> 9416 bytes .../img/icons/android-chrome-512x512.png | Bin 0 -> 29808 bytes .../icons/android-chrome-maskable-192x192.png | Bin 0 -> 6401 bytes .../icons/android-chrome-maskable-512x512.png | Bin 0 -> 23038 bytes .../img/icons/apple-touch-icon-120x120.png | Bin 0 -> 3369 bytes .../img/icons/apple-touch-icon-152x152.png | Bin 0 -> 4046 bytes .../img/icons/apple-touch-icon-180x180.png | Bin 0 -> 4678 bytes .../img/icons/apple-touch-icon-60x60.png | Bin 0 -> 1491 bytes .../img/icons/apple-touch-icon-76x76.png | Bin 0 -> 1823 bytes .../public/img/icons/apple-touch-icon.png | Bin 0 -> 4678 bytes .../public/img/icons/favicon-16x16.png | Bin 0 -> 799 bytes .../public/img/icons/favicon-32x32.png | Bin 0 -> 1271 bytes .../img/icons/msapplication-icon-144x144.png | Bin 0 -> 1169 bytes .../public/img/icons/mstile-150x150.png | Bin 0 -> 4282 bytes .../public/img/icons/safari-pinned-tab.svg | 149 + orange-demo-single-web/public/index.html | 17 + orange-demo-single-web/public/robots.txt | 2 + orange-demo-single-web/src/App.vue | 19 + .../src/api/Controller/CourseController.js | 25 + .../Controller/CourseTransStatsController.js | 17 + .../api/Controller/DictionaryController.js | 155 + .../api/Controller/SchoolInfoController.js | 25 + .../StudentActionStatsController.js | 17 + .../StudentActionTransController.js | 25 + .../api/Controller/StudentClassController.js | 65 + .../src/api/Controller/StudentController.js | 25 + .../api/Controller/SysDataPermController.js | 61 + .../src/api/Controller/SysUserController.js | 25 + .../src/api/Controller/SystemController.js | 201 + orange-demo-single-web/src/api/index.js | 25 + .../src/assets/img/default-header.jpg | Bin 0 -> 14882 bytes .../src/assets/img/login_bg.jpg | Bin 0 -> 494030 bytes .../src/assets/img/logo.jpg | Bin 0 -> 19013 bytes .../src/assets/img/orange-group1.png | Bin 0 -> 10894 bytes .../src/assets/style/base.scss | 593 ++ .../src/assets/style/element-color.scss | 25 + .../src/assets/style/form-style.scss | 112 + .../src/assets/style/index.scss | 3 + .../src/assets/style/transition.scss | 31 + .../src/assets/theme/fonts/element-icons.ttf | Bin 0 -> 55956 bytes .../src/assets/theme/fonts/element-icons.woff | Bin 0 -> 28200 bytes .../src/assets/theme/index.css | 1 + .../src/components/DateRange/index.vue | 305 + .../src/components/Dialog/index.js | 77 + .../src/components/FilterBox/index.vue | 134 + .../src/components/Hamburger/index.vue | 44 + .../src/components/IconSelect/icon.json | 280 + .../src/components/IconSelect/index.vue | 104 + .../src/components/InputNumberRange/index.vue | 226 + .../src/components/Progress/index.vue | 44 + .../src/components/RichEditor/index.vue | 129 + .../components/TableProgressColumn/index.vue | 119 + .../src/components/TreeSelect/index.vue | 300 + .../src/core/config/development.js | 4 + .../src/core/config/index.js | 12 + .../src/core/config/production.js | 4 + .../src/core/directive/sortable.js | 14 + .../src/core/directive/sortableData.js | 60 + orange-demo-single-web/src/core/http/index.js | 185 + .../src/core/http/request.js | 73 + .../src/core/http/requestUrl.js | 27 + .../src/core/mixins/global.js | 117 + .../src/core/mixins/index.js | 293 + orange-demo-single-web/src/main.js | 36 + .../src/registerServiceWorker.js | 32 + .../src/router/import-development.js | 1 + .../src/router/import-production.js | 1 + orange-demo-single-web/src/router/index.js | 30 + .../src/router/systemRouters.js | 52 + .../src/staticDict/index.js | 351 ++ orange-demo-single-web/src/store/actions.js | 1 + orange-demo-single-web/src/store/getters.js | 80 + orange-demo-single-web/src/store/index.js | 15 + orange-demo-single-web/src/store/mutations.js | 145 + orange-demo-single-web/src/store/state.js | 25 + .../src/store/utils/index.js | 36 + .../src/utils/chartOption.js | 56 + orange-demo-single-web/src/utils/index.js | 222 + orange-demo-single-web/src/utils/validate.js | 33 + orange-demo-single-web/src/utils/widget.js | 297 + .../src/views/generated/formClass/index.vue | 290 + .../views/generated/formClassCourse/index.vue | 175 + .../generated/formClassStudent/index.vue | 169 + .../src/views/generated/formCourse/index.vue | 308 + .../views/generated/formCourseStats/index.vue | 314 + .../views/generated/formCreateClass/index.vue | 276 + .../generated/formCreateCourse/index.vue | 310 + .../generated/formCreateSchool/index.vue | 197 + .../generated/formCreateStudent/index.vue | 429 ++ .../views/generated/formEditClass/index.vue | 280 + .../views/generated/formEditCourse/index.vue | 345 ++ .../views/generated/formEditSchool/index.vue | 225 + .../views/generated/formEditStudent/index.vue | 519 ++ .../src/views/generated/formSchool/index.vue | 263 + .../generated/formSetClassCourse/index.vue | 281 + .../generated/formSetClassStudent/index.vue | 207 + .../src/views/generated/formStudent/index.vue | 327 ++ .../formStudentActionDetail/index.vue | 240 + .../formStudentActionStats/index.vue | 315 + .../layout/components/breadcrumb/index.vue | 53 + .../components/formModifyPassword/index.vue | 95 + .../layout/components/sidebar/menu-item.vue | 59 + .../layout/components/sidebar/sidebar.vue | 72 + .../views/layout/components/tags/tagItem.vue | 70 + .../views/layout/components/tags/tagPanel.vue | 213 + .../src/views/layout/index.vue | 168 + .../src/views/login/index.vue | 102 + .../views/upms/formDictManagement/index.vue | 128 + .../src/views/upms/formEditDict/index.vue | 82 + .../views/upms/formEditSysMenu/editColumn.vue | 108 + .../src/views/upms/formEditSysMenu/index.vue | 283 + .../src/views/upms/formEditSysPerm/index.vue | 169 + .../views/upms/formEditSysPermCode/index.vue | 221 + .../upms/formEditSysPermModule/index.vue | 185 + .../src/views/upms/formEditSysRole/index.vue | 157 + .../src/views/upms/formEditSysUser/index.vue | 167 + .../src/views/upms/formMenuPerm/index.vue | 150 + .../src/views/upms/formPermQuery/index.vue | 416 ++ .../src/views/upms/formSetRoleUsers/index.vue | 216 + .../upms/formSysMenu/formSysColumnMenu.vue | 305 + .../src/views/upms/formSysMenu/index.vue | 239 + .../src/views/upms/formSysPerm/index.vue | 398 ++ .../src/views/upms/formSysPermCode/index.vue | 254 + .../src/views/upms/formSysRole/index.vue | 455 ++ .../src/views/upms/formSysRoleUser/index.vue | 224 + .../src/views/upms/formSysUser/index.vue | 253 + .../src/views/welcome/index.vue | 156 + orange-demo-single-web/static/.gitkeep | 0 orange-demo-single-web/vue.config.js | 5 + 354 files changed, 40271 insertions(+), 9 deletions(-) create mode 100644 orange-demo-single-service/.DS_Store create mode 100644 orange-demo-single-service/.gitignore create mode 100644 orange-demo-single-service/README.md create mode 100644 orange-demo-single-service/application-common/pom.xml create mode 100644 orange-demo-single-service/application-common/src/main/java/com/orange/demo/application/common/constant/DeviceType.java create mode 100644 orange-demo-single-service/application-common/src/main/java/com/orange/demo/application/common/constant/ExpLevel.java create mode 100644 orange-demo-single-service/application-common/src/main/java/com/orange/demo/application/common/constant/Gender.java create mode 100644 orange-demo-single-service/application-common/src/main/java/com/orange/demo/application/common/constant/StudentActionType.java create mode 100644 orange-demo-single-service/application-common/src/main/java/com/orange/demo/application/common/constant/StudentStatus.java create mode 100644 orange-demo-single-service/application-common/src/main/java/com/orange/demo/application/common/constant/Subject.java create mode 100644 orange-demo-single-service/application/pom.xml create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/MyApplication.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/controller/AreaCodeController.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/controller/CourseController.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/controller/CourseTransStatsController.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/controller/GradeController.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/controller/SchoolInfoController.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/controller/StudentActionStatsController.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/controller/StudentActionTransController.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/controller/StudentClassController.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/controller/StudentController.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/AreaCodeMapper.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/ClassCourseMapper.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/ClassStudentMapper.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/CourseMapper.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/CourseTransStatsMapper.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/GradeMapper.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/MaterialEditionMapper.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/SchoolInfoMapper.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/StudentActionStatsMapper.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/StudentActionTransMapper.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/StudentClassMapper.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/StudentMapper.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/mapper/AreaCodeMapper.xml create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/mapper/ClassCourseMapper.xml create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/mapper/ClassStudentMapper.xml create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/mapper/CourseMapper.xml create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/mapper/CourseTransStatsMapper.xml create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/mapper/GradeMapper.xml create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/mapper/MaterialEditionMapper.xml create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/mapper/SchoolInfoMapper.xml create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/mapper/StudentActionStatsMapper.xml create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/mapper/StudentActionTransMapper.xml create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/mapper/StudentClassMapper.xml create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/mapper/StudentMapper.xml create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/AreaCode.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/ClassCourse.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/ClassStudent.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/Course.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/CourseTransStats.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/Grade.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/MaterialEdition.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/SchoolInfo.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/Student.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/StudentActionStats.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/StudentActionTrans.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/StudentClass.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/constant/ClassLevel.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/constant/ClassStatus.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/constant/CourseDifficult.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/service/AreaCodeService.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/service/CourseService.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/service/CourseTransStatsService.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/service/GradeService.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/service/SchoolInfoService.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/service/StudentActionStatsService.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/service/StudentActionTransService.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/service/StudentClassService.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/app/service/StudentService.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/config/ApplicationConfig.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/config/DataSourceConfig.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/config/FilterConfig.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/config/InterceptorConfig.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/interceptor/AuthenticationInterceptor.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/upms/controller/LoginController.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/upms/controller/SysMenuController.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/upms/controller/SysPermCodeController.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/upms/controller/SysPermController.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/upms/controller/SysPermModuleController.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/upms/controller/SysRoleController.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/upms/controller/SysUserController.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/SysMenuMapper.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/SysMenuPermCodeMapper.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/SysPermCodeMapper.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/SysPermCodePermMapper.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/SysPermMapper.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/SysPermModuleMapper.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/SysPermWhitelistMapper.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/SysRoleMapper.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/SysRoleMenuMapper.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/SysUserMapper.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/SysUserRoleMapper.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/mapper/SysMenuMapper.xml create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/mapper/SysMenuPermCodeMapper.xml create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/mapper/SysPermCodeMapper.xml create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/mapper/SysPermCodePermMapper.xml create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/mapper/SysPermMapper.xml create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/mapper/SysPermModuleMapper.xml create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/mapper/SysPermWhitelistMapper.xml create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/mapper/SysRoleMapper.xml create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/mapper/SysRoleMenuMapper.xml create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/mapper/SysUserMapper.xml create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/mapper/SysUserRoleMapper.xml create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/SysMenu.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/SysMenuPermCode.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/SysPerm.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/SysPermCode.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/SysPermCodePerm.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/SysPermModule.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/SysPermWhitelist.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/SysRole.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/SysRoleMenu.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/SysUser.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/SysUserRole.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/constant/SysMenuType.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/constant/SysPermCodeType.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/constant/SysPermModuleType.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/constant/SysUserStatus.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/constant/SysUserType.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/upms/service/SysMenuService.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/upms/service/SysPermCodeService.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/upms/service/SysPermModuleService.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/upms/service/SysPermService.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/upms/service/SysPermWhitelistService.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/upms/service/SysRoleService.java create mode 100644 orange-demo-single-service/application/src/main/java/com/orange/demo/upms/service/SysUserService.java create mode 100644 orange-demo-single-service/application/src/main/resources/application.yml create mode 100644 orange-demo-single-service/application/src/main/resources/log4j2.xml create mode 100644 orange-demo-single-service/application/src/main/resources/template/views/print_error.ftl create mode 100644 orange-demo-single-service/common/common-core/pom.xml create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/advice/MyControllerAdvice.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/advice/MyExceptionHandler.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/annotation/DeletedFlagColumn.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/annotation/JobUpdateTimeColumn.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/annotation/MyDataSource.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/annotation/MyRequestBody.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/annotation/NoAuthInterface.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/annotation/RelationConstDict.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/annotation/RelationDict.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/annotation/RelationManyToMany.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/annotation/RelationManyToManyAggregation.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/annotation/RelationOneToManyAggregation.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/annotation/RelationOneToOne.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/aop/AccessLogAspect.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/base/dao/BaseDaoMapper.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/base/mapper/BaseModelMapper.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/base/mapper/DummyModelMapper.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/base/service/BaseDictService.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/base/service/BaseService.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/cache/CacheConfig.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/cache/DictionaryCache.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/cache/MapDictionaryCache.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/cache/MapTreeDictionaryCache.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/cache/SessionCacheHelper.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/config/CommonWebMvcConfig.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/config/EncryptConfig.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/config/RestTemplateConfig.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/config/TomcatConfig.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/constant/AggregationType.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/constant/ApplicationConstant.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/constant/ErrorCodeEnum.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/constant/GlobalDeletedFlag.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/exception/DataValidationException.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/exception/InvalidClassFieldException.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/exception/InvalidDataFieldException.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/exception/InvalidDataModelException.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/exception/MyRuntimeException.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/exception/NoDataAffectException.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/exception/NoDataPermException.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/exception/RedisCacheAccessException.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/interceptor/MyRequestArgumentResolver.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/listener/LoadCachedDataListener.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/listener/LoadServiceRelationListener.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/object/CallResult.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/object/MyGroupCriteria.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/object/MyGroupParam.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/object/MyOrderParam.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/object/MyPageParam.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/object/MyRelationParam.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/object/MyWhereCriteria.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/object/ResponseResult.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/object/TokenData.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/object/Tuple2.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/AopTargetUtil.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/ApplicationContextHolder.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/ContextUtil.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/ExportUtil.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/ImportUtil.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/IpUtil.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/JwtUtil.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/LogMessageUtil.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/MyCommonUtil.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/MyDateUtil.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/MyModelUtil.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/MyPageUtil.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/RsaUtil.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/TreeNode.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/UpDownloadUtil.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/validator/AddGroup.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/validator/ConstDictRef.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/validator/ConstDictValidator.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/validator/TextLength.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/validator/TextLengthValidator.java create mode 100644 orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/validator/UpdateGroup.java create mode 100644 orange-demo-single-service/common/common-sequence/pom.xml create mode 100644 orange-demo-single-service/common/common-sequence/src/main/java/com/orange/demo/common/sequence/config/IdGeneratorAutoConfigure.java create mode 100644 orange-demo-single-service/common/common-sequence/src/main/java/com/orange/demo/common/sequence/config/IdGeneratorProperties.java create mode 100644 orange-demo-single-service/common/common-sequence/src/main/java/com/orange/demo/common/sequence/generator/BasicIdGenerator.java create mode 100644 orange-demo-single-service/common/common-sequence/src/main/java/com/orange/demo/common/sequence/generator/MyIdGenerator.java create mode 100644 orange-demo-single-service/common/common-sequence/src/main/java/com/orange/demo/common/sequence/wrapper/IdGeneratorWrapper.java create mode 100644 orange-demo-single-service/common/common-sequence/src/main/resources/META-INF/spring.factories create mode 100644 orange-demo-single-service/common/pom.xml create mode 100644 orange-demo-single-service/pom.xml create mode 100644 orange-demo-single-service/zz-orange-demo.sql create mode 100644 orange-demo-single-service/zz-resource/upload-files/app/image/Course/pictureUrl/eef356943ce74b7b809dcce178cb92d2.png create mode 100644 orange-demo-single-web/.browserslistrc create mode 100644 orange-demo-single-web/.editorconfig create mode 100644 orange-demo-single-web/.eslintrc.js create mode 100644 orange-demo-single-web/.gitignore create mode 100644 orange-demo-single-web/README.md create mode 100644 orange-demo-single-web/babel.config.js create mode 100644 orange-demo-single-web/jest.config.js create mode 100644 orange-demo-single-web/package.json create mode 100644 orange-demo-single-web/public/favicon.ico create mode 100644 orange-demo-single-web/public/img/icons/android-chrome-192x192.png create mode 100644 orange-demo-single-web/public/img/icons/android-chrome-512x512.png create mode 100644 orange-demo-single-web/public/img/icons/android-chrome-maskable-192x192.png create mode 100644 orange-demo-single-web/public/img/icons/android-chrome-maskable-512x512.png create mode 100644 orange-demo-single-web/public/img/icons/apple-touch-icon-120x120.png create mode 100644 orange-demo-single-web/public/img/icons/apple-touch-icon-152x152.png create mode 100644 orange-demo-single-web/public/img/icons/apple-touch-icon-180x180.png create mode 100644 orange-demo-single-web/public/img/icons/apple-touch-icon-60x60.png create mode 100644 orange-demo-single-web/public/img/icons/apple-touch-icon-76x76.png create mode 100644 orange-demo-single-web/public/img/icons/apple-touch-icon.png create mode 100644 orange-demo-single-web/public/img/icons/favicon-16x16.png create mode 100644 orange-demo-single-web/public/img/icons/favicon-32x32.png create mode 100644 orange-demo-single-web/public/img/icons/msapplication-icon-144x144.png create mode 100644 orange-demo-single-web/public/img/icons/mstile-150x150.png create mode 100644 orange-demo-single-web/public/img/icons/safari-pinned-tab.svg create mode 100644 orange-demo-single-web/public/index.html create mode 100644 orange-demo-single-web/public/robots.txt create mode 100644 orange-demo-single-web/src/App.vue create mode 100644 orange-demo-single-web/src/api/Controller/CourseController.js create mode 100644 orange-demo-single-web/src/api/Controller/CourseTransStatsController.js create mode 100644 orange-demo-single-web/src/api/Controller/DictionaryController.js create mode 100644 orange-demo-single-web/src/api/Controller/SchoolInfoController.js create mode 100644 orange-demo-single-web/src/api/Controller/StudentActionStatsController.js create mode 100644 orange-demo-single-web/src/api/Controller/StudentActionTransController.js create mode 100644 orange-demo-single-web/src/api/Controller/StudentClassController.js create mode 100644 orange-demo-single-web/src/api/Controller/StudentController.js create mode 100644 orange-demo-single-web/src/api/Controller/SysDataPermController.js create mode 100644 orange-demo-single-web/src/api/Controller/SysUserController.js create mode 100644 orange-demo-single-web/src/api/Controller/SystemController.js create mode 100644 orange-demo-single-web/src/api/index.js create mode 100644 orange-demo-single-web/src/assets/img/default-header.jpg create mode 100644 orange-demo-single-web/src/assets/img/login_bg.jpg create mode 100644 orange-demo-single-web/src/assets/img/logo.jpg create mode 100644 orange-demo-single-web/src/assets/img/orange-group1.png create mode 100644 orange-demo-single-web/src/assets/style/base.scss create mode 100644 orange-demo-single-web/src/assets/style/element-color.scss create mode 100644 orange-demo-single-web/src/assets/style/form-style.scss create mode 100644 orange-demo-single-web/src/assets/style/index.scss create mode 100644 orange-demo-single-web/src/assets/style/transition.scss create mode 100644 orange-demo-single-web/src/assets/theme/fonts/element-icons.ttf create mode 100644 orange-demo-single-web/src/assets/theme/fonts/element-icons.woff create mode 100644 orange-demo-single-web/src/assets/theme/index.css create mode 100644 orange-demo-single-web/src/components/DateRange/index.vue create mode 100644 orange-demo-single-web/src/components/Dialog/index.js create mode 100644 orange-demo-single-web/src/components/FilterBox/index.vue create mode 100644 orange-demo-single-web/src/components/Hamburger/index.vue create mode 100644 orange-demo-single-web/src/components/IconSelect/icon.json create mode 100644 orange-demo-single-web/src/components/IconSelect/index.vue create mode 100644 orange-demo-single-web/src/components/InputNumberRange/index.vue create mode 100644 orange-demo-single-web/src/components/Progress/index.vue create mode 100644 orange-demo-single-web/src/components/RichEditor/index.vue create mode 100644 orange-demo-single-web/src/components/TableProgressColumn/index.vue create mode 100644 orange-demo-single-web/src/components/TreeSelect/index.vue create mode 100644 orange-demo-single-web/src/core/config/development.js create mode 100644 orange-demo-single-web/src/core/config/index.js create mode 100644 orange-demo-single-web/src/core/config/production.js create mode 100644 orange-demo-single-web/src/core/directive/sortable.js create mode 100644 orange-demo-single-web/src/core/directive/sortableData.js create mode 100644 orange-demo-single-web/src/core/http/index.js create mode 100644 orange-demo-single-web/src/core/http/request.js create mode 100644 orange-demo-single-web/src/core/http/requestUrl.js create mode 100644 orange-demo-single-web/src/core/mixins/global.js create mode 100644 orange-demo-single-web/src/core/mixins/index.js create mode 100644 orange-demo-single-web/src/main.js create mode 100644 orange-demo-single-web/src/registerServiceWorker.js create mode 100644 orange-demo-single-web/src/router/import-development.js create mode 100644 orange-demo-single-web/src/router/import-production.js create mode 100644 orange-demo-single-web/src/router/index.js create mode 100644 orange-demo-single-web/src/router/systemRouters.js create mode 100644 orange-demo-single-web/src/staticDict/index.js create mode 100644 orange-demo-single-web/src/store/actions.js create mode 100644 orange-demo-single-web/src/store/getters.js create mode 100644 orange-demo-single-web/src/store/index.js create mode 100644 orange-demo-single-web/src/store/mutations.js create mode 100644 orange-demo-single-web/src/store/state.js create mode 100644 orange-demo-single-web/src/store/utils/index.js create mode 100644 orange-demo-single-web/src/utils/chartOption.js create mode 100644 orange-demo-single-web/src/utils/index.js create mode 100644 orange-demo-single-web/src/utils/validate.js create mode 100644 orange-demo-single-web/src/utils/widget.js create mode 100644 orange-demo-single-web/src/views/generated/formClass/index.vue create mode 100644 orange-demo-single-web/src/views/generated/formClassCourse/index.vue create mode 100644 orange-demo-single-web/src/views/generated/formClassStudent/index.vue create mode 100644 orange-demo-single-web/src/views/generated/formCourse/index.vue create mode 100644 orange-demo-single-web/src/views/generated/formCourseStats/index.vue create mode 100644 orange-demo-single-web/src/views/generated/formCreateClass/index.vue create mode 100644 orange-demo-single-web/src/views/generated/formCreateCourse/index.vue create mode 100644 orange-demo-single-web/src/views/generated/formCreateSchool/index.vue create mode 100644 orange-demo-single-web/src/views/generated/formCreateStudent/index.vue create mode 100644 orange-demo-single-web/src/views/generated/formEditClass/index.vue create mode 100644 orange-demo-single-web/src/views/generated/formEditCourse/index.vue create mode 100644 orange-demo-single-web/src/views/generated/formEditSchool/index.vue create mode 100644 orange-demo-single-web/src/views/generated/formEditStudent/index.vue create mode 100644 orange-demo-single-web/src/views/generated/formSchool/index.vue create mode 100644 orange-demo-single-web/src/views/generated/formSetClassCourse/index.vue create mode 100644 orange-demo-single-web/src/views/generated/formSetClassStudent/index.vue create mode 100644 orange-demo-single-web/src/views/generated/formStudent/index.vue create mode 100644 orange-demo-single-web/src/views/generated/formStudentActionDetail/index.vue create mode 100644 orange-demo-single-web/src/views/generated/formStudentActionStats/index.vue create mode 100644 orange-demo-single-web/src/views/layout/components/breadcrumb/index.vue create mode 100644 orange-demo-single-web/src/views/layout/components/formModifyPassword/index.vue create mode 100644 orange-demo-single-web/src/views/layout/components/sidebar/menu-item.vue create mode 100644 orange-demo-single-web/src/views/layout/components/sidebar/sidebar.vue create mode 100644 orange-demo-single-web/src/views/layout/components/tags/tagItem.vue create mode 100644 orange-demo-single-web/src/views/layout/components/tags/tagPanel.vue create mode 100644 orange-demo-single-web/src/views/layout/index.vue create mode 100644 orange-demo-single-web/src/views/login/index.vue create mode 100644 orange-demo-single-web/src/views/upms/formDictManagement/index.vue create mode 100644 orange-demo-single-web/src/views/upms/formEditDict/index.vue create mode 100644 orange-demo-single-web/src/views/upms/formEditSysMenu/editColumn.vue create mode 100644 orange-demo-single-web/src/views/upms/formEditSysMenu/index.vue create mode 100644 orange-demo-single-web/src/views/upms/formEditSysPerm/index.vue create mode 100644 orange-demo-single-web/src/views/upms/formEditSysPermCode/index.vue create mode 100644 orange-demo-single-web/src/views/upms/formEditSysPermModule/index.vue create mode 100644 orange-demo-single-web/src/views/upms/formEditSysRole/index.vue create mode 100644 orange-demo-single-web/src/views/upms/formEditSysUser/index.vue create mode 100644 orange-demo-single-web/src/views/upms/formMenuPerm/index.vue create mode 100644 orange-demo-single-web/src/views/upms/formPermQuery/index.vue create mode 100644 orange-demo-single-web/src/views/upms/formSetRoleUsers/index.vue create mode 100644 orange-demo-single-web/src/views/upms/formSysMenu/formSysColumnMenu.vue create mode 100644 orange-demo-single-web/src/views/upms/formSysMenu/index.vue create mode 100644 orange-demo-single-web/src/views/upms/formSysPerm/index.vue create mode 100644 orange-demo-single-web/src/views/upms/formSysPermCode/index.vue create mode 100644 orange-demo-single-web/src/views/upms/formSysRole/index.vue create mode 100644 orange-demo-single-web/src/views/upms/formSysRoleUser/index.vue create mode 100644 orange-demo-single-web/src/views/upms/formSysUser/index.vue create mode 100644 orange-demo-single-web/src/views/welcome/index.vue create mode 100644 orange-demo-single-web/static/.gitkeep create mode 100644 orange-demo-single-web/vue.config.js diff --git a/orange-demo-service/zz-orange-demo.sql b/orange-demo-service/zz-orange-demo.sql index 34057e46..9e113342 100644 --- a/orange-demo-service/zz-orange-demo.sql +++ b/orange-demo-service/zz-orange-demo.sql @@ -266,7 +266,7 @@ CREATE TABLE `zz_student` ( `birthday` date NOT NULL COMMENT '生日', `experience_level` tinyint(4) NOT NULL COMMENT '经验等级 (0: 初级 1: 中级 2: 高级 3: 资深)', `total_coin` int(11) NOT NULL DEFAULT '0' COMMENT '总共充值学币数量', - `left_coin` int(11) NOT NULL COMMENT '可用学币数量', + `left_coin` int(11) NOT NULL DEFAULT '0' COMMENT '可用学币数量', `grade_id` int(11) NOT NULL COMMENT '年级Id', `school_id` bigint(20) NOT NULL COMMENT '校区Id', `register_time` datetime NOT NULL COMMENT '注册时间', @@ -648,10 +648,6 @@ INSERT INTO `zz_sys_menu` VALUES (1093809448598376533, 1093376634916704256, '新 INSERT INTO `zz_sys_menu` VALUES (1093809448598376534, 1093376634916704256, '编辑', 3, NULL, 3, NULL, CURDATE(), 1); INSERT INTO `zz_sys_menu` VALUES (1093809448598376535, 1093376634916704256, '删除', 3, NULL, 4, NULL, CURDATE(), 1); INSERT INTO `zz_sys_menu` VALUES (1093809448598376536, 1093376634916704256, '重置密码', 3, NULL, 5, NULL, CURDATE(), 1); -INSERT INTO `zz_sys_menu` VALUES (1093809448598376544, 1093376634916704257, '显示', 3, NULL, 1, NULL, CURDATE(), 1); -INSERT INTO `zz_sys_menu` VALUES (1093809448598376545, 1093376634916704257, '新增', 3, NULL, 2, NULL, CURDATE(), 1); -INSERT INTO `zz_sys_menu` VALUES (1093809448598376546, 1093376634916704257, '编辑', 3, NULL, 3, NULL, CURDATE(), 1); -INSERT INTO `zz_sys_menu` VALUES (1093809448598376547, 1093376634916704257, '删除', 3, NULL, 4, NULL, CURDATE(), 1); INSERT INTO `zz_sys_menu` VALUES (1093809448598376554, 1093376634916704258, '角色管理', 2, NULL, 1, NULL, CURDATE(), 1); INSERT INTO `zz_sys_menu` VALUES (1093809448598376555, 1093376634916704258, '用户授权', 2, NULL, 2, NULL, CURDATE(), 1); INSERT INTO `zz_sys_menu` VALUES (1093809448598376556, 1093809448598376554, '显示', 3, NULL, 1, NULL, CURDATE(), 1); @@ -822,10 +818,6 @@ INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376533, 109380944859837 INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376534, 1093809448598376540); INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376535, 1093809448598376541); INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376536, 1093809448598376542); -INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376544, 1093809448598376549); -INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376545, 1093809448598376550); -INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376546, 1093809448598376551); -INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376547, 1093809448598376552); INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376556, 1093809448598376564); INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376560, 1093809448598376565); INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376557, 1093809448598376566); diff --git a/orange-demo-single-service/.DS_Store b/orange-demo-single-service/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5008ddfcf53c02e82d7eee2e57c38e5672ef89f6 GIT binary patch literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0 + + + com.orange.demo + OrangeSingleDemo + 1.0.0 + + 4.0.0 + + application-common + 1.0.0 + application-common + jar + + + + com.orange.demo + common-core + 1.0.0 + + + \ No newline at end of file diff --git a/orange-demo-single-service/application-common/src/main/java/com/orange/demo/application/common/constant/DeviceType.java b/orange-demo-single-service/application-common/src/main/java/com/orange/demo/application/common/constant/DeviceType.java new file mode 100644 index 00000000..afdada25 --- /dev/null +++ b/orange-demo-single-service/application-common/src/main/java/com/orange/demo/application/common/constant/DeviceType.java @@ -0,0 +1,49 @@ +package com.orange.demo.application.common.constant; + +import java.util.HashMap; +import java.util.Map; + +/** + * 设备类型常量字典对象。 + * + * @author Jerry + * @date 2020-09-25 + */ +public final class DeviceType { + + /** + * iOS。 + */ + public static final int IOS = 0; + /** + * Android。 + */ + public static final int ANDROID = 1; + /** + * PC。 + */ + public static final int PC = 2; + + private static final Map DICT_MAP = new HashMap<>(3); + static { + DICT_MAP.put(IOS, "iOS"); + DICT_MAP.put(ANDROID, "Android"); + DICT_MAP.put(PC, "PC"); + } + + /** + * 判断参数是否为当前常量字典的合法值。 + * + * @param value 待验证的参数值。 + * @return 合法返回true,否则false。 + */ + public static boolean isValid(Integer value) { + return value != null && DICT_MAP.containsKey(value); + } + + /** + * 私有构造函数,明确标识该常量类的作用。 + */ + private DeviceType() { + } +} diff --git a/orange-demo-single-service/application-common/src/main/java/com/orange/demo/application/common/constant/ExpLevel.java b/orange-demo-single-service/application-common/src/main/java/com/orange/demo/application/common/constant/ExpLevel.java new file mode 100644 index 00000000..a9bb8d8e --- /dev/null +++ b/orange-demo-single-service/application-common/src/main/java/com/orange/demo/application/common/constant/ExpLevel.java @@ -0,0 +1,49 @@ +package com.orange.demo.application.common.constant; + +import java.util.HashMap; +import java.util.Map; + +/** + * 经验等级常量字典对象。 + * + * @author Jerry + * @date 2020-09-25 + */ +public final class ExpLevel { + + /** + * 初级学员。 + */ + public static final int LOWER = 0; + /** + * 中级学员。 + */ + public static final int MIDDLE = 1; + /** + * 高级学员。 + */ + public static final int HIGH = 2; + + private static final Map DICT_MAP = new HashMap<>(3); + static { + DICT_MAP.put(LOWER, "初级学员"); + DICT_MAP.put(MIDDLE, "中级学员"); + DICT_MAP.put(HIGH, "高级学员"); + } + + /** + * 判断参数是否为当前常量字典的合法值。 + * + * @param value 待验证的参数值。 + * @return 合法返回true,否则false。 + */ + public static boolean isValid(Integer value) { + return value != null && DICT_MAP.containsKey(value); + } + + /** + * 私有构造函数,明确标识该常量类的作用。 + */ + private ExpLevel() { + } +} diff --git a/orange-demo-single-service/application-common/src/main/java/com/orange/demo/application/common/constant/Gender.java b/orange-demo-single-service/application-common/src/main/java/com/orange/demo/application/common/constant/Gender.java new file mode 100644 index 00000000..30a33f9f --- /dev/null +++ b/orange-demo-single-service/application-common/src/main/java/com/orange/demo/application/common/constant/Gender.java @@ -0,0 +1,44 @@ +package com.orange.demo.application.common.constant; + +import java.util.HashMap; +import java.util.Map; + +/** + * 性别常量字典对象。 + * + * @author Jerry + * @date 2020-09-25 + */ +public final class Gender { + + /** + * 男。 + */ + public static final int MALE = 1; + /** + * 女。 + */ + public static final int FEMALE = 0; + + private static final Map DICT_MAP = new HashMap<>(2); + static { + DICT_MAP.put(MALE, "男"); + DICT_MAP.put(FEMALE, "女"); + } + + /** + * 判断参数是否为当前常量字典的合法值。 + * + * @param value 待验证的参数值。 + * @return 合法返回true,否则false。 + */ + public static boolean isValid(Integer value) { + return value != null && DICT_MAP.containsKey(value); + } + + /** + * 私有构造函数,明确标识该常量类的作用。 + */ + private Gender() { + } +} diff --git a/orange-demo-single-service/application-common/src/main/java/com/orange/demo/application/common/constant/StudentActionType.java b/orange-demo-single-service/application-common/src/main/java/com/orange/demo/application/common/constant/StudentActionType.java new file mode 100644 index 00000000..3cf8ea83 --- /dev/null +++ b/orange-demo-single-service/application-common/src/main/java/com/orange/demo/application/common/constant/StudentActionType.java @@ -0,0 +1,89 @@ +package com.orange.demo.application.common.constant; + +import java.util.HashMap; +import java.util.Map; + +/** + * 学生行为常量字典对象。 + * + * @author Jerry + * @date 2020-09-25 + */ +public final class StudentActionType { + + /** + * 充值。 + */ + public static final int RECHARGE = 0; + /** + * 购课。 + */ + public static final int BUY_COURSE = 1; + /** + * 上课签到。 + */ + public static final int SIGNIN_COURSE = 2; + /** + * 上课签退。 + */ + public static final int SIGNOUT_COURSE = 3; + /** + * 看视频课。 + */ + public static final int WATCH_VIDEO = 4; + /** + * 做作业。 + */ + public static final int DO_PAPER = 5; + /** + * 刷题。 + */ + public static final int REFRESH_EXERCISE = 6; + /** + * 献花。 + */ + public static final int PRESENT_FLOWER = 7; + /** + * 购买视频。 + */ + public static final int BUY_VIDEO_COURSE = 8; + /** + * 购买鲜花。 + */ + public static final int BUY_FLOWER = 9; + /** + * 购买作业。 + */ + public static final int BUY_PAPER = 10; + + private static final Map DICT_MAP = new HashMap<>(11); + static { + DICT_MAP.put(RECHARGE, "充值"); + DICT_MAP.put(BUY_COURSE, "购课"); + DICT_MAP.put(SIGNIN_COURSE, "上课签到"); + DICT_MAP.put(SIGNOUT_COURSE, "上课签退"); + DICT_MAP.put(WATCH_VIDEO, "看视频课"); + DICT_MAP.put(DO_PAPER, "做作业"); + DICT_MAP.put(REFRESH_EXERCISE, "刷题"); + DICT_MAP.put(PRESENT_FLOWER, "献花"); + DICT_MAP.put(BUY_VIDEO_COURSE, "购买视频"); + DICT_MAP.put(BUY_FLOWER, "购买鲜花"); + DICT_MAP.put(BUY_PAPER, "购买作业"); + } + + /** + * 判断参数是否为当前常量字典的合法值。 + * + * @param value 待验证的参数值。 + * @return 合法返回true,否则false。 + */ + public static boolean isValid(Integer value) { + return value != null && DICT_MAP.containsKey(value); + } + + /** + * 私有构造函数,明确标识该常量类的作用。 + */ + private StudentActionType() { + } +} diff --git a/orange-demo-single-service/application-common/src/main/java/com/orange/demo/application/common/constant/StudentStatus.java b/orange-demo-single-service/application-common/src/main/java/com/orange/demo/application/common/constant/StudentStatus.java new file mode 100644 index 00000000..fb05587b --- /dev/null +++ b/orange-demo-single-service/application-common/src/main/java/com/orange/demo/application/common/constant/StudentStatus.java @@ -0,0 +1,49 @@ +package com.orange.demo.application.common.constant; + +import java.util.HashMap; +import java.util.Map; + +/** + * 学生状态常量字典对象。 + * + * @author Jerry + * @date 2020-09-25 + */ +public final class StudentStatus { + + /** + * 正常。 + */ + public static final int NORMAL = 0; + /** + * 锁定。 + */ + public static final int LOCKED = 1; + /** + * 注销。 + */ + public static final int DELETED = 2; + + private static final Map DICT_MAP = new HashMap<>(3); + static { + DICT_MAP.put(NORMAL, "正常"); + DICT_MAP.put(LOCKED, "锁定"); + DICT_MAP.put(DELETED, "注销"); + } + + /** + * 判断参数是否为当前常量字典的合法值。 + * + * @param value 待验证的参数值。 + * @return 合法返回true,否则false。 + */ + public static boolean isValid(Integer value) { + return value != null && DICT_MAP.containsKey(value); + } + + /** + * 私有构造函数,明确标识该常量类的作用。 + */ + private StudentStatus() { + } +} diff --git a/orange-demo-single-service/application-common/src/main/java/com/orange/demo/application/common/constant/Subject.java b/orange-demo-single-service/application-common/src/main/java/com/orange/demo/application/common/constant/Subject.java new file mode 100644 index 00000000..1408cb93 --- /dev/null +++ b/orange-demo-single-service/application-common/src/main/java/com/orange/demo/application/common/constant/Subject.java @@ -0,0 +1,49 @@ +package com.orange.demo.application.common.constant; + +import java.util.HashMap; +import java.util.Map; + +/** + * 学科常量字典对象。 + * + * @author Jerry + * @date 2020-09-25 + */ +public final class Subject { + + /** + * 语文。 + */ + public static final int CHINESE = 0; + /** + * 数学。 + */ + public static final int MATCH = 1; + /** + * 英语。 + */ + public static final int ENGLISH = 2; + + private static final Map DICT_MAP = new HashMap<>(3); + static { + DICT_MAP.put(CHINESE, "语文"); + DICT_MAP.put(MATCH, "数学"); + DICT_MAP.put(ENGLISH, "英语"); + } + + /** + * 判断参数是否为当前常量字典的合法值。 + * + * @param value 待验证的参数值。 + * @return 合法返回true,否则false。 + */ + public static boolean isValid(Integer value) { + return value != null && DICT_MAP.containsKey(value); + } + + /** + * 私有构造函数,明确标识该常量类的作用。 + */ + private Subject() { + } +} diff --git a/orange-demo-single-service/application/pom.xml b/orange-demo-single-service/application/pom.xml new file mode 100644 index 00000000..3c561be6 --- /dev/null +++ b/orange-demo-single-service/application/pom.xml @@ -0,0 +1,67 @@ + + + + com.orange.demo + OrangeSingleDemo + 1.0.0 + + 4.0.0 + + application + 1.0.0 + application + jar + + + + + com.orange.demo + common-core + 1.0.0 + + + com.orange.demo + application-common + 1.0.0 + + + com.orange.demo + common-sequence + 1.0.0 + + + + + + + src/main/resources + + **/*.* + + false + + + src/main/java + + **/*.xml + + false + + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring-boot.version} + + + + repackage + + + + + + + diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/MyApplication.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/MyApplication.java new file mode 100644 index 00000000..a3f6a435 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/MyApplication.java @@ -0,0 +1,18 @@ +package com.orange.demo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * 应用服务启动类。 + * + * @author Jerry + * @date 2020-09-25 + */ +@SpringBootApplication +public class MyApplication { + + public static void main(String[] args) { + SpringApplication.run(MyApplication.class, args); + } +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/controller/AreaCodeController.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/controller/AreaCodeController.java new file mode 100644 index 00000000..c492fb5a --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/controller/AreaCodeController.java @@ -0,0 +1,56 @@ +package com.orange.demo.app.controller; + +import cn.jimmyshi.beanquery.BeanQuery; +import com.orange.demo.app.model.AreaCode; +import com.orange.demo.app.service.AreaCodeService; +import com.orange.demo.common.core.object.ResponseResult; +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.util.*; + +/** + * 行政区划数据访问接口类。 + * + * @author Jerry + * @date 2020-09-25 + */ +@RestController +@RequestMapping("/admin/app/areaCode") +public class AreaCodeController { + + @Autowired + private AreaCodeService areaCodeService; + + /** + * 按照字典的形式返回行政区划列表。 + * + * @return 字典形式的行政区划列表。 + */ + @GetMapping("/listDictAreaCode") + public ResponseResult>> listDictAreaCode() { + List resultList = areaCodeService.getAllList(); + return ResponseResult.success(BeanQuery.select( + "parentId as parentId", "areaId as id", "areaName as name").executeFrom(resultList)); + } + + /** + * 根据上级行政区划Id获取其下级行政区划列表。 + * + * @param parentId 上级行政区划Id。 + * @return 按照字典的形式返回下级行政区划列表。 + */ + @GetMapping("/listDictAreaCodeByParentId") + public ResponseResult>> listDictAreaCodeByParentId(@RequestParam(required = false) Long parentId) { + Collection resultList = areaCodeService.getListByParentId(parentId); + if (CollectionUtils.isEmpty(resultList)) { + return ResponseResult.success(new LinkedList<>()); + } + return ResponseResult.success(BeanQuery.select( + "parentId as parentId", "areaId as id", "areaName as name").executeFrom(resultList)); + } +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/controller/CourseController.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/controller/CourseController.java new file mode 100644 index 00000000..38e0b385 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/controller/CourseController.java @@ -0,0 +1,253 @@ +package com.orange.demo.app.controller; + +import cn.hutool.core.util.ReflectUtil; +import cn.jimmyshi.beanquery.BeanQuery; +import com.github.pagehelper.page.PageMethod; +import com.orange.demo.app.model.*; +import com.orange.demo.app.service.*; +import com.orange.demo.common.core.object.*; +import com.orange.demo.common.core.util.*; +import com.orange.demo.common.core.constant.ErrorCodeEnum; +import com.orange.demo.common.core.annotation.MyRequestBody; +import com.orange.demo.common.core.validator.UpdateGroup; +import com.orange.demo.common.core.cache.SessionCacheHelper; +import com.orange.demo.config.ApplicationConfig; +import lombok.extern.slf4j.Slf4j; +import com.alibaba.fastjson.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.*; +import javax.validation.groups.Default; + +/** + * 课程数据操作控制器类。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Slf4j +@RestController +@RequestMapping("/admin/app/course") +public class CourseController { + + @Autowired + private CourseService courseService; + @Autowired + private ApplicationConfig appConfig; + @Autowired + private SessionCacheHelper cacheHelper; + + /** + * 新增课程数据数据。 + * + * @param course 新增对象。 + * @return 应答结果对象,包含新增对象主键Id。 + */ + @PostMapping("/add") + public ResponseResult add(@MyRequestBody Course course) { + String errorMessage = MyCommonUtil.getModelValidationError(course); + if (errorMessage != null) { + return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATAED_FAILED, errorMessage); + } + // 验证关联Id的数据合法性 + CallResult callResult = courseService.verifyRelatedData(course, null); + if (!callResult.isSuccess()) { + errorMessage = callResult.getErrorMessage(); + return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATAED_FAILED, errorMessage); + } + course = courseService.saveNew(course); + JSONObject responseData = new JSONObject(); + responseData.put("courseId", course.getCourseId()); + return ResponseResult.success(responseData); + } + + /** + * 更新课程数据数据。 + * + * @param course 更新对象。 + * @return 应答结果对象。 + */ + @PostMapping("/update") + public ResponseResult update(@MyRequestBody Course course) { + String errorMessage = MyCommonUtil.getModelValidationError(course, Default.class, UpdateGroup.class); + if (errorMessage != null) { + return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATAED_FAILED, errorMessage); + } + // 验证关联Id的数据合法性 + Course originalCourse = courseService.getById(course.getCourseId()); + if (originalCourse == null) { + //NOTE: 修改下面方括号中的话述 + errorMessage = "数据验证失败,当前 [数据] 并不存在,请刷新后重试!"; + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage); + } + // 验证关联Id的数据合法性 + CallResult callResult = courseService.verifyRelatedData(course, originalCourse); + if (!callResult.isSuccess()) { + errorMessage = callResult.getErrorMessage(); + return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATAED_FAILED, errorMessage); + } + if (!courseService.update(course, originalCourse)) { + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST); + } + return ResponseResult.success(); + } + + /** + * 删除课程数据数据。 + * + * @param courseId 删除对象主键Id。 + * @return 应答结果对象。 + */ + @PostMapping("/delete") + public ResponseResult delete(@MyRequestBody Long courseId) { + String errorMessage; + if (MyCommonUtil.existBlankArgument(courseId)) { + return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST); + } + // 验证关联Id的数据合法性 + Course originalCourse = courseService.getById(courseId); + if (originalCourse == null) { + // NOTE: 修改下面方括号中的话述 + errorMessage = "数据验证失败,当前 [对象] 并不存在,请刷新后重试!"; + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage); + } + if (!courseService.remove(courseId)) { + errorMessage = "数据操作失败,删除的对象不存在,请刷新后重试!"; + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage); + } + return ResponseResult.success(); + } + + /** + * 列出符合过滤条件的课程数据列表。 + * + * @param courseFilter 过滤对象。 + * @param orderParam 排序参数。 + * @param pageParam 分页参数。 + * @return 应答结果对象,包含查询结果集。 + */ + @PostMapping("/list") + public ResponseResult list( + @MyRequestBody Course courseFilter, + @MyRequestBody MyOrderParam orderParam, + @MyRequestBody MyPageParam pageParam) { + if (pageParam != null) { + PageMethod.startPage(pageParam.getPageNum(), pageParam.getPageSize()); + } + String orderBy = MyOrderParam.buildOrderBy(orderParam, Course.class); + List resultList = courseService.getCourseListWithRelation(courseFilter, orderBy); + return ResponseResult.success(MyPageUtil.makeResponseData(resultList)); + } + + /** + * 查看指定课程数据对象详情。 + * + * @param courseId 指定对象主键Id。 + * @return 应答结果对象,包含对象详情。 + */ + @GetMapping("/view") + public ResponseResult view(@RequestParam Long courseId) { + if (MyCommonUtil.existBlankArgument(courseId)) { + return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST); + } + Course course = courseService.getByIdWithRelation(courseId, MyRelationParam.full()); + if (course == null) { + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST); + } + return ResponseResult.success(course); + } + + /** + * 附件文件下载。 + * 这里将图片和其他类型的附件文件放到不同的父目录下,主要为了便于今后图片文件的迁移。 + * + * @param courseId 附件所在记录的主键Id。 + * @param fieldName 附件所属的字段名。 + * @param filename 文件名。如果没有提供该参数,就从当前记录的指定字段中读取。 + * @param asImage 下载文件是否为图片。 + * @param response Http 应答对象。 + */ + @GetMapping("/download") + public void download( + @RequestParam(required = false) Long courseId, + @RequestParam String fieldName, + @RequestParam String filename, + @RequestParam Boolean asImage, + HttpServletResponse response) { + if (MyCommonUtil.existBlankArgument(fieldName, filename, asImage)) { + response.setStatus(HttpServletResponse.SC_BAD_REQUEST); + return; + } + // 使用try来捕获异常,是为了保证一旦出现异常可以返回500的错误状态,便于调试。 + // 否则有可能给前端返回的是200的错误码。 + try { + // 如果请求参数中没有包含主键Id,就判断该文件是否为当前session上传的。 + if (courseId == null) { + if (!cacheHelper.existSessionUploadFile(filename)) { + response.setStatus(HttpServletResponse.SC_FORBIDDEN); + return; + } + } else { + Course course = courseService.getById(courseId); + if (course == null) { + response.setStatus(HttpServletResponse.SC_NOT_FOUND); + return; + } + String fieldJsonData = (String) ReflectUtil.getFieldValue(course, fieldName); + if (fieldJsonData == null) { + response.setStatus(HttpServletResponse.SC_BAD_REQUEST); + return; + } + if (!UpDownloadUtil.containFile(fieldJsonData, filename)) { + response.setStatus(HttpServletResponse.SC_FORBIDDEN); + return; + } + } + UpDownloadUtil.doDownload(appConfig.getUploadFileBaseDir(), + Course.class.getSimpleName(), fieldName, filename, asImage, response); + } catch (Exception e) { + response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + log.error(e.getMessage(), e); + } + } + + /** + * 文件上传操作。 + * + * @param fieldName 上传文件名。 + * @param asImage 是否作为图片上传。如果是图片,今后下载的时候无需权限验证。否则就是附件上传,下载时需要权限验证。 + * @param uploadFile 上传文件对象。 + * @param response Http 应答对象。 + * @throws IOException 文件读写错误。 + */ + @PostMapping("/upload") + public void upload( + @RequestParam String fieldName, + @RequestParam Boolean asImage, + @RequestParam("uploadFile") MultipartFile uploadFile, + HttpServletResponse response) throws IOException { + String filename = UpDownloadUtil.doUpload(appConfig.getUploadFileBaseDir(), + Course.class.getSimpleName(), fieldName, asImage, uploadFile, response); + if (filename != null) { + cacheHelper.putSessionUploadFile(filename); + } + } + + /** + * 以字典形式返回全部课程数据数据集合。字典的键值为[courseId, courseName]。 + * 白名单接口,登录用户均可访问。 + * + * @param filter 过滤对象。 + * @return 应答结果对象,包含的数据为 List>,map中包含两条记录,key的值分别是id和name,value对应具体数据。 + */ + @GetMapping("/listDictCourse") + public ResponseResult>> listDictCourse(Course filter) { + List resultList = courseService.getListByFilter(filter, null); + return ResponseResult.success(BeanQuery.select( + "courseId as id", "courseName as name").executeFrom(resultList)); + } +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/controller/CourseTransStatsController.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/controller/CourseTransStatsController.java new file mode 100644 index 00000000..4e6d7ce3 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/controller/CourseTransStatsController.java @@ -0,0 +1,99 @@ +package com.orange.demo.app.controller; + +import com.github.pagehelper.page.PageMethod; +import com.orange.demo.app.model.*; +import com.orange.demo.app.service.*; +import com.orange.demo.common.core.object.*; +import com.orange.demo.common.core.util.*; +import com.orange.demo.common.core.constant.ErrorCodeEnum; +import com.orange.demo.common.core.annotation.MyRequestBody; +import lombok.extern.slf4j.Slf4j; +import com.alibaba.fastjson.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.*; + +/** + * 课程统计操作控制器类。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Slf4j +@RestController +@RequestMapping("/admin/app/courseTransStats") +public class CourseTransStatsController { + + @Autowired + private CourseTransStatsService courseTransStatsService; + + /** + * 列出符合过滤条件的课程统计列表。 + * + * @param courseTransStatsFilter 过滤对象。 + * @param orderParam 排序参数。 + * @param pageParam 分页参数。 + * @return 应答结果对象,包含查询结果集。 + */ + @PostMapping("/list") + public ResponseResult list( + @MyRequestBody CourseTransStats courseTransStatsFilter, + @MyRequestBody MyOrderParam orderParam, + @MyRequestBody MyPageParam pageParam) { + if (pageParam != null) { + PageMethod.startPage(pageParam.getPageNum(), pageParam.getPageSize()); + } + String orderBy = MyOrderParam.buildOrderBy(orderParam, CourseTransStats.class); + List resultList = courseTransStatsService.getCourseTransStatsListWithRelation(courseTransStatsFilter, orderBy); + return ResponseResult.success(MyPageUtil.makeResponseData(resultList)); + } + + /** + * 分组列出符合过滤条件的课程统计列表。 + * + * @param courseTransStatsFilter 过滤对象。 + * @param groupParam 分组参数。 + * @param orderParam 排序参数。 + * @param pageParam 分页参数。 + * @return 应答结果对象,包含查询结果集。 + */ + @PostMapping("/listWithGroup") + public ResponseResult listWithGroup( + @MyRequestBody CourseTransStats courseTransStatsFilter, + @MyRequestBody MyGroupParam groupParam, + @MyRequestBody MyOrderParam orderParam, + @MyRequestBody MyPageParam pageParam) { + String orderBy = MyOrderParam.buildOrderBy(orderParam, CourseTransStats.class); + groupParam = MyGroupParam.buildGroupBy(groupParam, CourseTransStats.class); + if (groupParam == null) { + return ResponseResult.error( + ErrorCodeEnum.INVALID_ARGUMENT_FORMAT, "数据参数错误,分组参数不能为空!"); + } + if (pageParam != null) { + PageMethod.startPage(pageParam.getPageNum(), pageParam.getPageSize()); + } + MyGroupCriteria criteria = groupParam.getGroupCriteria(); + List resultList = courseTransStatsService.getGroupedCourseTransStatsListWithRelation( + courseTransStatsFilter, criteria.getGroupSelect(), criteria.getGroupBy(), orderBy); + return ResponseResult.success(MyPageUtil.makeResponseData(resultList)); + } + + /** + * 查看指定课程统计对象详情。 + * + * @param statsId 指定对象主键Id。 + * @return 应答结果对象,包含对象详情。 + */ + @GetMapping("/view") + public ResponseResult view(@RequestParam Long statsId) { + if (MyCommonUtil.existBlankArgument(statsId)) { + return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST); + } + CourseTransStats courseTransStats = courseTransStatsService.getByIdWithRelation(statsId, MyRelationParam.full()); + if (courseTransStats == null) { + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST); + } + return ResponseResult.success(courseTransStats); + } +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/controller/GradeController.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/controller/GradeController.java new file mode 100644 index 00000000..ab66a6fb --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/controller/GradeController.java @@ -0,0 +1,114 @@ +package com.orange.demo.app.controller; + +import com.orange.demo.app.model.*; +import com.orange.demo.app.service.*; +import com.orange.demo.common.core.constant.ErrorCodeEnum; +import com.orange.demo.common.core.util.MyCommonUtil; +import com.orange.demo.common.core.object.ResponseResult; +import com.orange.demo.common.core.annotation.MyRequestBody; +import com.orange.demo.common.core.validator.UpdateGroup; + +import com.alibaba.fastjson.JSONObject; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import cn.jimmyshi.beanquery.BeanQuery; + +import javax.validation.groups.Default; +import java.util.*; + +/** + * 年级操作控制器类。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Slf4j +@RestController +@RequestMapping("/admin/app/grade") +public class GradeController { + + @Autowired + private GradeService gradeService; + + /** + * 新增年级数据。 + * + * @param grade 新增对象。 + * @return 应答结果对象,包含新增对象主键Id。 + */ + @PostMapping("/add") + public ResponseResult add(@MyRequestBody Grade grade) { + String errorMessage = MyCommonUtil.getModelValidationError(grade); + if (errorMessage != null) { + return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATAED_FAILED, errorMessage); + } + grade = gradeService.saveNew(grade); + JSONObject responseData = new JSONObject(); + responseData.put("gradeId", grade.getGradeId()); + return ResponseResult.success(responseData); + } + + /** + * 更新年级数据。 + * + * @param grade 更新对象。 + * @return 应答结果对象。 + */ + @PostMapping("/update") + public ResponseResult update(@MyRequestBody Grade grade) { + String errorMessage = MyCommonUtil.getModelValidationError(grade, Default.class, UpdateGroup.class); + if (errorMessage != null) { + return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATAED_FAILED, errorMessage); + } + Grade originalGrade = gradeService.getById(grade.getGradeId()); + if (originalGrade == null) { + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST); + } + if (!gradeService.update(grade, originalGrade)) { + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST); + } + return ResponseResult.success(); + } + + /** + * 删除年级数据。 + * + * @param gradeId 删除对象主键Id。 + * @return 应答结果对象。 + */ + @PostMapping("/delete") + public ResponseResult delete(@MyRequestBody Integer gradeId) { + if (MyCommonUtil.existBlankArgument(gradeId)) { + return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST); + } + if (!gradeService.remove(gradeId)) { + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST); + } + return ResponseResult.success(); + } + + /** + * 以字典形式返回全部年级数据集合。 + * 白名单接口,登录用户均可访问。 + * + * @return 应答结果对象,包含字典形式的数据集合。 + */ + @GetMapping("/listDictGrade") + public ResponseResult>> listDictGrade() { + List resultList = gradeService.getAllList(); + return ResponseResult.success(BeanQuery.select( + "gradeId as id", "gradeName as name").executeFrom(resultList)); + } + + /** + * 将当前字典表的数据重新加载到缓存中。 + * 由于缓存的数据更新,在add/update/delete等接口均有同步处理。因此该接口仅当同步过程中出现问题时, + * 可手工调用,或者每天晚上定时同步一次。 + */ + @GetMapping("/reloadCachedData") + public ResponseResult reloadCachedData() { + gradeService.reloadCachedData(true); + return ResponseResult.success(true); + } +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/controller/SchoolInfoController.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/controller/SchoolInfoController.java new file mode 100644 index 00000000..ac59f081 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/controller/SchoolInfoController.java @@ -0,0 +1,167 @@ +package com.orange.demo.app.controller; + +import cn.jimmyshi.beanquery.BeanQuery; +import com.github.pagehelper.page.PageMethod; +import com.orange.demo.app.model.*; +import com.orange.demo.app.service.*; +import com.orange.demo.common.core.object.*; +import com.orange.demo.common.core.util.*; +import com.orange.demo.common.core.constant.ErrorCodeEnum; +import com.orange.demo.common.core.annotation.MyRequestBody; +import com.orange.demo.common.core.validator.UpdateGroup; +import lombok.extern.slf4j.Slf4j; +import com.alibaba.fastjson.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.*; +import javax.validation.groups.Default; + +/** + * 校区数据操作控制器类。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Slf4j +@RestController +@RequestMapping("/admin/app/schoolInfo") +public class SchoolInfoController { + + @Autowired + private SchoolInfoService schoolInfoService; + + /** + * 新增校区数据数据。 + * + * @param schoolInfo 新增对象。 + * @return 应答结果对象,包含新增对象主键Id。 + */ + @PostMapping("/add") + public ResponseResult add(@MyRequestBody SchoolInfo schoolInfo) { + String errorMessage = MyCommonUtil.getModelValidationError(schoolInfo); + if (errorMessage != null) { + return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATAED_FAILED, errorMessage); + } + // 验证关联Id的数据合法性 + CallResult callResult = schoolInfoService.verifyRelatedData(schoolInfo, null); + if (!callResult.isSuccess()) { + errorMessage = callResult.getErrorMessage(); + return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATAED_FAILED, errorMessage); + } + schoolInfo = schoolInfoService.saveNew(schoolInfo); + JSONObject responseData = new JSONObject(); + responseData.put("schoolId", schoolInfo.getSchoolId()); + return ResponseResult.success(responseData); + } + + /** + * 更新校区数据数据。 + * + * @param schoolInfo 更新对象。 + * @return 应答结果对象。 + */ + @PostMapping("/update") + public ResponseResult update(@MyRequestBody SchoolInfo schoolInfo) { + String errorMessage = MyCommonUtil.getModelValidationError(schoolInfo, Default.class, UpdateGroup.class); + if (errorMessage != null) { + return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATAED_FAILED, errorMessage); + } + // 验证关联Id的数据合法性 + SchoolInfo originalSchoolInfo = schoolInfoService.getById(schoolInfo.getSchoolId()); + if (originalSchoolInfo == null) { + //NOTE: 修改下面方括号中的话述 + errorMessage = "数据验证失败,当前 [数据] 并不存在,请刷新后重试!"; + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage); + } + // 验证关联Id的数据合法性 + CallResult callResult = schoolInfoService.verifyRelatedData(schoolInfo, originalSchoolInfo); + if (!callResult.isSuccess()) { + errorMessage = callResult.getErrorMessage(); + return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATAED_FAILED, errorMessage); + } + if (!schoolInfoService.update(schoolInfo, originalSchoolInfo)) { + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST); + } + return ResponseResult.success(); + } + + /** + * 删除校区数据数据。 + * + * @param schoolId 删除对象主键Id。 + * @return 应答结果对象。 + */ + @PostMapping("/delete") + public ResponseResult delete(@MyRequestBody Long schoolId) { + String errorMessage; + if (MyCommonUtil.existBlankArgument(schoolId)) { + return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST); + } + // 验证关联Id的数据合法性 + SchoolInfo originalSchoolInfo = schoolInfoService.getById(schoolId); + if (originalSchoolInfo == null) { + // NOTE: 修改下面方括号中的话述 + errorMessage = "数据验证失败,当前 [对象] 并不存在,请刷新后重试!"; + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage); + } + if (!schoolInfoService.remove(schoolId)) { + errorMessage = "数据操作失败,删除的对象不存在,请刷新后重试!"; + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage); + } + return ResponseResult.success(); + } + + /** + * 列出符合过滤条件的校区数据列表。 + * + * @param schoolInfoFilter 过滤对象。 + * @param orderParam 排序参数。 + * @param pageParam 分页参数。 + * @return 应答结果对象,包含查询结果集。 + */ + @PostMapping("/list") + public ResponseResult list( + @MyRequestBody SchoolInfo schoolInfoFilter, + @MyRequestBody MyOrderParam orderParam, + @MyRequestBody MyPageParam pageParam) { + if (pageParam != null) { + PageMethod.startPage(pageParam.getPageNum(), pageParam.getPageSize()); + } + String orderBy = MyOrderParam.buildOrderBy(orderParam, SchoolInfo.class); + List resultList = schoolInfoService.getSchoolInfoListWithRelation(schoolInfoFilter, orderBy); + return ResponseResult.success(MyPageUtil.makeResponseData(resultList)); + } + + /** + * 查看指定校区数据对象详情。 + * + * @param schoolId 指定对象主键Id。 + * @return 应答结果对象,包含对象详情。 + */ + @GetMapping("/view") + public ResponseResult view(@RequestParam Long schoolId) { + if (MyCommonUtil.existBlankArgument(schoolId)) { + return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST); + } + SchoolInfo schoolInfo = schoolInfoService.getByIdWithRelation(schoolId, MyRelationParam.full()); + if (schoolInfo == null) { + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST); + } + return ResponseResult.success(schoolInfo); + } + + /** + * 以字典形式返回全部校区数据数据集合。字典的键值为[schoolId, schoolName]。 + * 白名单接口,登录用户均可访问。 + * + * @param filter 过滤对象。 + * @return 应答结果对象,包含的数据为 List>,map中包含两条记录,key的值分别是id和name,value对应具体数据。 + */ + @GetMapping("/listDictSchoolInfo") + public ResponseResult>> listDictSchoolInfo(SchoolInfo filter) { + List resultList = schoolInfoService.getListByFilter(filter, null); + return ResponseResult.success(BeanQuery.select( + "schoolId as id", "schoolName as name").executeFrom(resultList)); + } +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/controller/StudentActionStatsController.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/controller/StudentActionStatsController.java new file mode 100644 index 00000000..487a7aa2 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/controller/StudentActionStatsController.java @@ -0,0 +1,99 @@ +package com.orange.demo.app.controller; + +import com.github.pagehelper.page.PageMethod; +import com.orange.demo.app.model.*; +import com.orange.demo.app.service.*; +import com.orange.demo.common.core.object.*; +import com.orange.demo.common.core.util.*; +import com.orange.demo.common.core.constant.ErrorCodeEnum; +import com.orange.demo.common.core.annotation.MyRequestBody; +import lombok.extern.slf4j.Slf4j; +import com.alibaba.fastjson.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.*; + +/** + * 学生行为统计操作控制器类。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Slf4j +@RestController +@RequestMapping("/admin/app/studentActionStats") +public class StudentActionStatsController { + + @Autowired + private StudentActionStatsService studentActionStatsService; + + /** + * 列出符合过滤条件的学生行为统计列表。 + * + * @param studentActionStatsFilter 过滤对象。 + * @param orderParam 排序参数。 + * @param pageParam 分页参数。 + * @return 应答结果对象,包含查询结果集。 + */ + @PostMapping("/list") + public ResponseResult list( + @MyRequestBody StudentActionStats studentActionStatsFilter, + @MyRequestBody MyOrderParam orderParam, + @MyRequestBody MyPageParam pageParam) { + if (pageParam != null) { + PageMethod.startPage(pageParam.getPageNum(), pageParam.getPageSize()); + } + String orderBy = MyOrderParam.buildOrderBy(orderParam, StudentActionStats.class); + List resultList = studentActionStatsService.getStudentActionStatsListWithRelation(studentActionStatsFilter, orderBy); + return ResponseResult.success(MyPageUtil.makeResponseData(resultList)); + } + + /** + * 分组列出符合过滤条件的学生行为统计列表。 + * + * @param studentActionStatsFilter 过滤对象。 + * @param groupParam 分组参数。 + * @param orderParam 排序参数。 + * @param pageParam 分页参数。 + * @return 应答结果对象,包含查询结果集。 + */ + @PostMapping("/listWithGroup") + public ResponseResult listWithGroup( + @MyRequestBody StudentActionStats studentActionStatsFilter, + @MyRequestBody MyGroupParam groupParam, + @MyRequestBody MyOrderParam orderParam, + @MyRequestBody MyPageParam pageParam) { + String orderBy = MyOrderParam.buildOrderBy(orderParam, StudentActionStats.class); + groupParam = MyGroupParam.buildGroupBy(groupParam, StudentActionStats.class); + if (groupParam == null) { + return ResponseResult.error( + ErrorCodeEnum.INVALID_ARGUMENT_FORMAT, "数据参数错误,分组参数不能为空!"); + } + if (pageParam != null) { + PageMethod.startPage(pageParam.getPageNum(), pageParam.getPageSize()); + } + MyGroupCriteria criteria = groupParam.getGroupCriteria(); + List resultList = studentActionStatsService.getGroupedStudentActionStatsListWithRelation( + studentActionStatsFilter, criteria.getGroupSelect(), criteria.getGroupBy(), orderBy); + return ResponseResult.success(MyPageUtil.makeResponseData(resultList)); + } + + /** + * 查看指定学生行为统计对象详情。 + * + * @param statsId 指定对象主键Id。 + * @return 应答结果对象,包含对象详情。 + */ + @GetMapping("/view") + public ResponseResult view(@RequestParam Long statsId) { + if (MyCommonUtil.existBlankArgument(statsId)) { + return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST); + } + StudentActionStats studentActionStats = studentActionStatsService.getByIdWithRelation(statsId, MyRelationParam.full()); + if (studentActionStats == null) { + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST); + } + return ResponseResult.success(studentActionStats); + } +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/controller/StudentActionTransController.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/controller/StudentActionTransController.java new file mode 100644 index 00000000..957156f8 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/controller/StudentActionTransController.java @@ -0,0 +1,152 @@ +package com.orange.demo.app.controller; + +import com.github.pagehelper.page.PageMethod; +import com.orange.demo.app.model.*; +import com.orange.demo.app.service.*; +import com.orange.demo.common.core.object.*; +import com.orange.demo.common.core.util.*; +import com.orange.demo.common.core.constant.ErrorCodeEnum; +import com.orange.demo.common.core.annotation.MyRequestBody; +import com.orange.demo.common.core.validator.UpdateGroup; +import lombok.extern.slf4j.Slf4j; +import com.alibaba.fastjson.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.*; +import javax.validation.groups.Default; + +/** + * 学生行为流水操作控制器类。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Slf4j +@RestController +@RequestMapping("/admin/app/studentActionTrans") +public class StudentActionTransController { + + @Autowired + private StudentActionTransService studentActionTransService; + + /** + * 新增学生行为流水数据。 + * + * @param studentActionTrans 新增对象。 + * @return 应答结果对象,包含新增对象主键Id。 + */ + @PostMapping("/add") + public ResponseResult add(@MyRequestBody StudentActionTrans studentActionTrans) { + String errorMessage = MyCommonUtil.getModelValidationError(studentActionTrans); + if (errorMessage != null) { + return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATAED_FAILED, errorMessage); + } + // 验证关联Id的数据合法性 + CallResult callResult = studentActionTransService.verifyRelatedData(studentActionTrans, null); + if (!callResult.isSuccess()) { + errorMessage = callResult.getErrorMessage(); + return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATAED_FAILED, errorMessage); + } + studentActionTrans = studentActionTransService.saveNew(studentActionTrans); + JSONObject responseData = new JSONObject(); + responseData.put("transId", studentActionTrans.getTransId()); + return ResponseResult.success(responseData); + } + + /** + * 更新学生行为流水数据。 + * + * @param studentActionTrans 更新对象。 + * @return 应答结果对象。 + */ + @PostMapping("/update") + public ResponseResult update(@MyRequestBody StudentActionTrans studentActionTrans) { + String errorMessage = MyCommonUtil.getModelValidationError(studentActionTrans, Default.class, UpdateGroup.class); + if (errorMessage != null) { + return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATAED_FAILED, errorMessage); + } + // 验证关联Id的数据合法性 + StudentActionTrans originalStudentActionTrans = studentActionTransService.getById(studentActionTrans.getTransId()); + if (originalStudentActionTrans == null) { + //NOTE: 修改下面方括号中的话述 + errorMessage = "数据验证失败,当前 [数据] 并不存在,请刷新后重试!"; + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage); + } + // 验证关联Id的数据合法性 + CallResult callResult = studentActionTransService.verifyRelatedData(studentActionTrans, originalStudentActionTrans); + if (!callResult.isSuccess()) { + errorMessage = callResult.getErrorMessage(); + return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATAED_FAILED, errorMessage); + } + if (!studentActionTransService.update(studentActionTrans, originalStudentActionTrans)) { + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST); + } + return ResponseResult.success(); + } + + /** + * 删除学生行为流水数据。 + * + * @param transId 删除对象主键Id。 + * @return 应答结果对象。 + */ + @PostMapping("/delete") + public ResponseResult delete(@MyRequestBody Long transId) { + String errorMessage; + if (MyCommonUtil.existBlankArgument(transId)) { + return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST); + } + // 验证关联Id的数据合法性 + StudentActionTrans originalStudentActionTrans = studentActionTransService.getById(transId); + if (originalStudentActionTrans == null) { + // NOTE: 修改下面方括号中的话述 + errorMessage = "数据验证失败,当前 [对象] 并不存在,请刷新后重试!"; + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage); + } + if (!studentActionTransService.remove(transId)) { + errorMessage = "数据操作失败,删除的对象不存在,请刷新后重试!"; + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage); + } + return ResponseResult.success(); + } + + /** + * 列出符合过滤条件的学生行为流水列表。 + * + * @param studentActionTransFilter 过滤对象。 + * @param orderParam 排序参数。 + * @param pageParam 分页参数。 + * @return 应答结果对象,包含查询结果集。 + */ + @PostMapping("/list") + public ResponseResult list( + @MyRequestBody StudentActionTrans studentActionTransFilter, + @MyRequestBody MyOrderParam orderParam, + @MyRequestBody MyPageParam pageParam) { + if (pageParam != null) { + PageMethod.startPage(pageParam.getPageNum(), pageParam.getPageSize()); + } + String orderBy = MyOrderParam.buildOrderBy(orderParam, StudentActionTrans.class); + List resultList = studentActionTransService.getStudentActionTransListWithRelation(studentActionTransFilter, orderBy); + return ResponseResult.success(MyPageUtil.makeResponseData(resultList)); + } + + /** + * 查看指定学生行为流水对象详情。 + * + * @param transId 指定对象主键Id。 + * @return 应答结果对象,包含对象详情。 + */ + @GetMapping("/view") + public ResponseResult view(@RequestParam Long transId) { + if (MyCommonUtil.existBlankArgument(transId)) { + return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST); + } + StudentActionTrans studentActionTrans = studentActionTransService.getByIdWithRelation(transId, MyRelationParam.full()); + if (studentActionTrans == null) { + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST); + } + return ResponseResult.success(studentActionTrans); + } +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/controller/StudentClassController.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/controller/StudentClassController.java new file mode 100644 index 00000000..c8440825 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/controller/StudentClassController.java @@ -0,0 +1,429 @@ +package com.orange.demo.app.controller; + +import com.github.pagehelper.page.PageMethod; +import com.orange.demo.app.model.*; +import com.orange.demo.app.service.*; +import com.orange.demo.common.core.object.*; +import com.orange.demo.common.core.util.*; +import com.orange.demo.common.core.constant.ErrorCodeEnum; +import com.orange.demo.common.core.annotation.MyRequestBody; +import com.orange.demo.common.core.validator.UpdateGroup; +import lombok.extern.slf4j.Slf4j; +import com.alibaba.fastjson.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.*; +import javax.validation.groups.Default; +import java.util.stream.Collectors; + +/** + * 班级数据操作控制器类。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Slf4j +@RestController +@RequestMapping("/admin/app/studentClass") +public class StudentClassController { + + @Autowired + private StudentClassService studentClassService; + @Autowired + private CourseService courseService; + @Autowired + private StudentService studentService; + + /** + * 新增班级数据数据。 + * + * @param studentClass 新增对象。 + * @return 应答结果对象,包含新增对象主键Id。 + */ + @PostMapping("/add") + public ResponseResult add(@MyRequestBody StudentClass studentClass) { + String errorMessage = MyCommonUtil.getModelValidationError(studentClass); + if (errorMessage != null) { + return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATAED_FAILED, errorMessage); + } + // 验证关联Id的数据合法性 + CallResult callResult = studentClassService.verifyRelatedData(studentClass, null); + if (!callResult.isSuccess()) { + errorMessage = callResult.getErrorMessage(); + return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATAED_FAILED, errorMessage); + } + studentClass = studentClassService.saveNew(studentClass); + JSONObject responseData = new JSONObject(); + responseData.put("classId", studentClass.getClassId()); + return ResponseResult.success(responseData); + } + + /** + * 更新班级数据数据。 + * + * @param studentClass 更新对象。 + * @return 应答结果对象。 + */ + @PostMapping("/update") + public ResponseResult update(@MyRequestBody StudentClass studentClass) { + String errorMessage = MyCommonUtil.getModelValidationError(studentClass, Default.class, UpdateGroup.class); + if (errorMessage != null) { + return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATAED_FAILED, errorMessage); + } + // 验证关联Id的数据合法性 + StudentClass originalStudentClass = studentClassService.getById(studentClass.getClassId()); + if (originalStudentClass == null) { + //NOTE: 修改下面方括号中的话述 + errorMessage = "数据验证失败,当前 [数据] 并不存在,请刷新后重试!"; + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage); + } + // 验证关联Id的数据合法性 + CallResult callResult = studentClassService.verifyRelatedData(studentClass, originalStudentClass); + if (!callResult.isSuccess()) { + errorMessage = callResult.getErrorMessage(); + return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATAED_FAILED, errorMessage); + } + if (!studentClassService.update(studentClass, originalStudentClass)) { + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST); + } + return ResponseResult.success(); + } + + /** + * 删除班级数据数据。 + * + * @param classId 删除对象主键Id。 + * @return 应答结果对象。 + */ + @PostMapping("/delete") + public ResponseResult delete(@MyRequestBody Long classId) { + String errorMessage; + if (MyCommonUtil.existBlankArgument(classId)) { + return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST); + } + // 验证关联Id的数据合法性 + StudentClass originalStudentClass = studentClassService.getById(classId); + if (originalStudentClass == null) { + // NOTE: 修改下面方括号中的话述 + errorMessage = "数据验证失败,当前 [对象] 并不存在,请刷新后重试!"; + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage); + } + if (!studentClassService.remove(classId)) { + errorMessage = "数据操作失败,删除的对象不存在,请刷新后重试!"; + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage); + } + return ResponseResult.success(); + } + + /** + * 列出符合过滤条件的班级数据列表。 + * + * @param studentClassFilter 过滤对象。 + * @param orderParam 排序参数。 + * @param pageParam 分页参数。 + * @return 应答结果对象,包含查询结果集。 + */ + @PostMapping("/list") + public ResponseResult list( + @MyRequestBody StudentClass studentClassFilter, + @MyRequestBody MyOrderParam orderParam, + @MyRequestBody MyPageParam pageParam) { + if (pageParam != null) { + PageMethod.startPage(pageParam.getPageNum(), pageParam.getPageSize()); + } + String orderBy = MyOrderParam.buildOrderBy(orderParam, StudentClass.class); + List resultList = studentClassService.getStudentClassListWithRelation(studentClassFilter, orderBy); + return ResponseResult.success(MyPageUtil.makeResponseData(resultList)); + } + + /** + * 查看指定班级数据对象详情。 + * + * @param classId 指定对象主键Id。 + * @return 应答结果对象,包含对象详情。 + */ + @GetMapping("/view") + public ResponseResult view(@RequestParam Long classId) { + if (MyCommonUtil.existBlankArgument(classId)) { + return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST); + } + StudentClass studentClass = studentClassService.getByIdWithRelation(classId, MyRelationParam.full()); + if (studentClass == null) { + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST); + } + return ResponseResult.success(studentClass); + } + + /** + * 列出不与指定班级数据存在多对多关系的 [课程数据] 列表数据。通常用于查看添加新 [课程数据] 对象的候选列表。 + * + * @param classId 主表关联字段。 + * @param courseFilter [课程数据] 过滤对象。 + * @param orderParam 排序参数。 + * @param pageParam 分页参数。 + * @return 应答结果对象,返回符合条件的数据列表。 + */ + @PostMapping("/listNotInClassCourse") + public ResponseResult listNotInClassCourse( + @MyRequestBody Long classId, + @MyRequestBody Course courseFilter, + @MyRequestBody MyOrderParam orderParam, + @MyRequestBody MyPageParam pageParam) { + ResponseResult verifyResult = this.doClassCourseVerify(classId); + if (!verifyResult.isSuccess()) { + return ResponseResult.errorFrom(verifyResult); + } + if (pageParam != null) { + PageMethod.startPage(pageParam.getPageNum(), pageParam.getPageSize()); + } + String orderBy = MyOrderParam.buildOrderBy(orderParam, Course.class); + List resultList = + courseService.getNotInCourseListByClassId(classId, courseFilter, orderBy); + JSONObject responseData = MyPageUtil.makeResponseData(resultList); + return ResponseResult.success(responseData); + } + + /** + * 列出与指定班级数据存在多对多关系的 [课程数据] 列表数据。 + * + * @param classId 主表关联字段。 + * @param courseFilter [课程数据] 过滤对象。 + * @param orderParam 排序参数。 + * @param pageParam 分页参数。 + * @return 应答结果对象,返回符合条件的数据列表。 + */ + @PostMapping("/listClassCourse") + public ResponseResult listClassCourse( + @MyRequestBody Long classId, + @MyRequestBody Course courseFilter, + @MyRequestBody MyOrderParam orderParam, + @MyRequestBody MyPageParam pageParam) { + ResponseResult verifyResult = this.doClassCourseVerify(classId); + if (!verifyResult.isSuccess()) { + return ResponseResult.errorFrom(verifyResult); + } + if (pageParam != null) { + PageMethod.startPage(pageParam.getPageNum(), pageParam.getPageSize()); + } + String orderBy = MyOrderParam.buildOrderBy(orderParam, Course.class); + List resultList = + courseService.getCourseListByClassId(classId, courseFilter, orderBy); + JSONObject responseData = MyPageUtil.makeResponseData(resultList); + return ResponseResult.success(responseData); + } + + private ResponseResult doClassCourseVerify(Long classId) { + if (MyCommonUtil.existBlankArgument(classId)) { + return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST); + } + if (!studentClassService.existId(classId)) { + return ResponseResult.error(ErrorCodeEnum.INVALID_RELATED_RECORD_ID); + } + return ResponseResult.success(); + } + + /** + * 批量添加班级数据和 [课程数据] 对象的多对多关联关系数据。 + * + * @param classId 主表主键Id。 + * @param classCourseList 关联对象列表。 + * @return 应答结果对象。 + */ + @PostMapping("/addClassCourse") + public ResponseResult addClassCourse( + @MyRequestBody Long classId, + @MyRequestBody(elementType = ClassCourse.class) List classCourseList) { + if (MyCommonUtil.existBlankArgument(classId, classCourseList)) { + return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST); + } + for (ClassCourse classCourse : classCourseList) { + String errorMessage = MyCommonUtil.getModelValidationError(classCourse); + if (errorMessage != null) { + return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATAED_FAILED, errorMessage); + } + } + Set courseIdSet = + classCourseList.stream().map(ClassCourse::getCourseId).collect(Collectors.toSet()); + if (!studentClassService.existId(classId) + || !courseService.existUniqueKeyList("courseId", courseIdSet)) { + return ResponseResult.error(ErrorCodeEnum.INVALID_RELATED_RECORD_ID); + } + studentClassService.addClassCourseList(classCourseList, classId); + return ResponseResult.success(); + } + + /** + * 更新指定班级数据和指定 [课程数据] 的多对多关联数据。 + * + * @param classCourse 对多对中间表对象。 + * @return 应答结果对象。 + */ + @PostMapping("/updateClassCourse") + public ResponseResult updateClassCourse(@MyRequestBody ClassCourse classCourse) { + String errorMessage = MyCommonUtil.getModelValidationError(classCourse); + if (errorMessage != null) { + return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATAED_FAILED, errorMessage); + } + if (!studentClassService.updateClassCourse(classCourse)) { + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST); + } + return ResponseResult.success(); + } + + /** + * 显示班级数据和指定 [课程数据] 的多对多关联详情数据。 + * + * @param classId 主表主键Id。 + * @param courseId 从表主键Id。 + * @return 应答结果对象,包括中间表详情。 + */ + @GetMapping("/viewClassCourse") + public ResponseResult viewClassCourse( + @RequestParam Long classId, @RequestParam Long courseId) { + if (MyCommonUtil.existBlankArgument(classId, courseId)) { + return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST); + } + ClassCourse classCourse = studentClassService.getClassCourse(classId, courseId); + if (classCourse == null) { + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST); + } + return ResponseResult.success(classCourse); + } + + /** + * 移除指定班级数据和指定 [课程数据] 的多对多关联关系。 + * + * @param classId 主表主键Id。 + * @param courseId 从表主键Id。 + * @return 应答结果对象。 + */ + @PostMapping("/deleteClassCourse") + public ResponseResult deleteClassCourse( + @MyRequestBody Long classId, @MyRequestBody Long courseId) { + if (MyCommonUtil.existBlankArgument(classId, courseId)) { + return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST); + } + if (!studentClassService.removeClassCourse(classId, courseId)) { + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST); + } + return ResponseResult.success(); + } + + /** + * 列出不与指定班级数据存在多对多关系的 [学生数据] 列表数据。通常用于查看添加新 [学生数据] 对象的候选列表。 + * + * @param classId 主表关联字段。 + * @param studentFilter [学生数据] 过滤对象。 + * @param orderParam 排序参数。 + * @param pageParam 分页参数。 + * @return 应答结果对象,返回符合条件的数据列表。 + */ + @PostMapping("/listNotInClassStudent") + public ResponseResult listNotInClassStudent( + @MyRequestBody Long classId, + @MyRequestBody Student studentFilter, + @MyRequestBody MyOrderParam orderParam, + @MyRequestBody MyPageParam pageParam) { + ResponseResult verifyResult = this.doClassStudentVerify(classId); + if (!verifyResult.isSuccess()) { + return ResponseResult.errorFrom(verifyResult); + } + if (pageParam != null) { + PageMethod.startPage(pageParam.getPageNum(), pageParam.getPageSize()); + } + String orderBy = MyOrderParam.buildOrderBy(orderParam, Student.class); + List resultList = + studentService.getNotInStudentListByClassId(classId, studentFilter, orderBy); + JSONObject responseData = MyPageUtil.makeResponseData(resultList); + return ResponseResult.success(responseData); + } + + /** + * 列出与指定班级数据存在多对多关系的 [学生数据] 列表数据。 + * + * @param classId 主表关联字段。 + * @param studentFilter [学生数据] 过滤对象。 + * @param orderParam 排序参数。 + * @param pageParam 分页参数。 + * @return 应答结果对象,返回符合条件的数据列表。 + */ + @PostMapping("/listClassStudent") + public ResponseResult listClassStudent( + @MyRequestBody Long classId, + @MyRequestBody Student studentFilter, + @MyRequestBody MyOrderParam orderParam, + @MyRequestBody MyPageParam pageParam) { + ResponseResult verifyResult = this.doClassStudentVerify(classId); + if (!verifyResult.isSuccess()) { + return ResponseResult.errorFrom(verifyResult); + } + if (pageParam != null) { + PageMethod.startPage(pageParam.getPageNum(), pageParam.getPageSize()); + } + String orderBy = MyOrderParam.buildOrderBy(orderParam, Student.class); + List resultList = + studentService.getStudentListByClassId(classId, studentFilter, orderBy); + JSONObject responseData = MyPageUtil.makeResponseData(resultList); + return ResponseResult.success(responseData); + } + + private ResponseResult doClassStudentVerify(Long classId) { + if (MyCommonUtil.existBlankArgument(classId)) { + return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST); + } + if (!studentClassService.existId(classId)) { + return ResponseResult.error(ErrorCodeEnum.INVALID_RELATED_RECORD_ID); + } + return ResponseResult.success(); + } + + /** + * 批量添加班级数据和 [学生数据] 对象的多对多关联关系数据。 + * + * @param classId 主表主键Id。 + * @param classStudentList 关联对象列表。 + * @return 应答结果对象。 + */ + @PostMapping("/addClassStudent") + public ResponseResult addClassStudent( + @MyRequestBody Long classId, + @MyRequestBody(elementType = ClassStudent.class) List classStudentList) { + if (MyCommonUtil.existBlankArgument(classId, classStudentList)) { + return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST); + } + for (ClassStudent classStudent : classStudentList) { + String errorMessage = MyCommonUtil.getModelValidationError(classStudent); + if (errorMessage != null) { + return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATAED_FAILED, errorMessage); + } + } + Set studentIdSet = + classStudentList.stream().map(ClassStudent::getStudentId).collect(Collectors.toSet()); + if (!studentClassService.existId(classId) + || !studentService.existUniqueKeyList("studentId", studentIdSet)) { + return ResponseResult.error(ErrorCodeEnum.INVALID_RELATED_RECORD_ID); + } + studentClassService.addClassStudentList(classStudentList, classId); + return ResponseResult.success(); + } + + /** + * 移除指定班级数据和指定 [学生数据] 的多对多关联关系。 + * + * @param classId 主表主键Id。 + * @param studentId 从表主键Id。 + * @return 应答结果对象。 + */ + @PostMapping("/deleteClassStudent") + public ResponseResult deleteClassStudent( + @MyRequestBody Long classId, @MyRequestBody Long studentId) { + if (MyCommonUtil.existBlankArgument(classId, studentId)) { + return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST); + } + if (!studentClassService.removeClassStudent(classId, studentId)) { + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST); + } + return ResponseResult.success(); + } +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/controller/StudentController.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/controller/StudentController.java new file mode 100644 index 00000000..37133747 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/controller/StudentController.java @@ -0,0 +1,167 @@ +package com.orange.demo.app.controller; + +import cn.jimmyshi.beanquery.BeanQuery; +import com.github.pagehelper.page.PageMethod; +import com.orange.demo.app.model.*; +import com.orange.demo.app.service.*; +import com.orange.demo.common.core.object.*; +import com.orange.demo.common.core.util.*; +import com.orange.demo.common.core.constant.ErrorCodeEnum; +import com.orange.demo.common.core.annotation.MyRequestBody; +import com.orange.demo.common.core.validator.UpdateGroup; +import lombok.extern.slf4j.Slf4j; +import com.alibaba.fastjson.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.*; +import javax.validation.groups.Default; + +/** + * 学生数据操作控制器类。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Slf4j +@RestController +@RequestMapping("/admin/app/student") +public class StudentController { + + @Autowired + private StudentService studentService; + + /** + * 新增学生数据数据。 + * + * @param student 新增对象。 + * @return 应答结果对象,包含新增对象主键Id。 + */ + @PostMapping("/add") + public ResponseResult add(@MyRequestBody Student student) { + String errorMessage = MyCommonUtil.getModelValidationError(student); + if (errorMessage != null) { + return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATAED_FAILED, errorMessage); + } + // 验证关联Id的数据合法性 + CallResult callResult = studentService.verifyRelatedData(student, null); + if (!callResult.isSuccess()) { + errorMessage = callResult.getErrorMessage(); + return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATAED_FAILED, errorMessage); + } + student = studentService.saveNew(student); + JSONObject responseData = new JSONObject(); + responseData.put("studentId", student.getStudentId()); + return ResponseResult.success(responseData); + } + + /** + * 更新学生数据数据。 + * + * @param student 更新对象。 + * @return 应答结果对象。 + */ + @PostMapping("/update") + public ResponseResult update(@MyRequestBody Student student) { + String errorMessage = MyCommonUtil.getModelValidationError(student, Default.class, UpdateGroup.class); + if (errorMessage != null) { + return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATAED_FAILED, errorMessage); + } + // 验证关联Id的数据合法性 + Student originalStudent = studentService.getById(student.getStudentId()); + if (originalStudent == null) { + //NOTE: 修改下面方括号中的话述 + errorMessage = "数据验证失败,当前 [数据] 并不存在,请刷新后重试!"; + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage); + } + // 验证关联Id的数据合法性 + CallResult callResult = studentService.verifyRelatedData(student, originalStudent); + if (!callResult.isSuccess()) { + errorMessage = callResult.getErrorMessage(); + return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATAED_FAILED, errorMessage); + } + if (!studentService.update(student, originalStudent)) { + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST); + } + return ResponseResult.success(); + } + + /** + * 删除学生数据数据。 + * + * @param studentId 删除对象主键Id。 + * @return 应答结果对象。 + */ + @PostMapping("/delete") + public ResponseResult delete(@MyRequestBody Long studentId) { + String errorMessage; + if (MyCommonUtil.existBlankArgument(studentId)) { + return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST); + } + // 验证关联Id的数据合法性 + Student originalStudent = studentService.getById(studentId); + if (originalStudent == null) { + // NOTE: 修改下面方括号中的话述 + errorMessage = "数据验证失败,当前 [对象] 并不存在,请刷新后重试!"; + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage); + } + if (!studentService.remove(studentId)) { + errorMessage = "数据操作失败,删除的对象不存在,请刷新后重试!"; + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage); + } + return ResponseResult.success(); + } + + /** + * 列出符合过滤条件的学生数据列表。 + * + * @param studentFilter 过滤对象。 + * @param orderParam 排序参数。 + * @param pageParam 分页参数。 + * @return 应答结果对象,包含查询结果集。 + */ + @PostMapping("/list") + public ResponseResult list( + @MyRequestBody Student studentFilter, + @MyRequestBody MyOrderParam orderParam, + @MyRequestBody MyPageParam pageParam) { + if (pageParam != null) { + PageMethod.startPage(pageParam.getPageNum(), pageParam.getPageSize()); + } + String orderBy = MyOrderParam.buildOrderBy(orderParam, Student.class); + List resultList = studentService.getStudentListWithRelation(studentFilter, orderBy); + return ResponseResult.success(MyPageUtil.makeResponseData(resultList)); + } + + /** + * 查看指定学生数据对象详情。 + * + * @param studentId 指定对象主键Id。 + * @return 应答结果对象,包含对象详情。 + */ + @GetMapping("/view") + public ResponseResult view(@RequestParam Long studentId) { + if (MyCommonUtil.existBlankArgument(studentId)) { + return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST); + } + Student student = studentService.getByIdWithRelation(studentId, MyRelationParam.full()); + if (student == null) { + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST); + } + return ResponseResult.success(student); + } + + /** + * 以字典形式返回全部学生数据数据集合。字典的键值为[studentId, studentName]。 + * 白名单接口,登录用户均可访问。 + * + * @param filter 过滤对象。 + * @return 应答结果对象,包含的数据为 List>,map中包含两条记录,key的值分别是id和name,value对应具体数据。 + */ + @GetMapping("/listDictStudent") + public ResponseResult>> listDictStudent(Student filter) { + List resultList = studentService.getListByFilter(filter, null); + return ResponseResult.success(BeanQuery.select( + "studentId as id", "studentName as name").executeFrom(resultList)); + } +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/AreaCodeMapper.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/AreaCodeMapper.java new file mode 100644 index 00000000..61ffbdbb --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/AreaCodeMapper.java @@ -0,0 +1,13 @@ +package com.orange.demo.app.dao; + +import com.orange.demo.common.core.base.dao.BaseDaoMapper; +import com.orange.demo.app.model.AreaCode; + +/** + * 行政区划数据操作访问接口。 + * + * @author Jerry + * @date 2020-09-25 + */ +public interface AreaCodeMapper extends BaseDaoMapper { +} \ No newline at end of file diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/ClassCourseMapper.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/ClassCourseMapper.java new file mode 100644 index 00000000..b4917a20 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/ClassCourseMapper.java @@ -0,0 +1,13 @@ +package com.orange.demo.app.dao; + +import com.orange.demo.common.core.base.dao.BaseDaoMapper; +import com.orange.demo.app.model.ClassCourse; + +/** + * 数据操作访问接口。 + * + * @author Jerry + * @date 2020-09-25 + */ +public interface ClassCourseMapper extends BaseDaoMapper { +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/ClassStudentMapper.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/ClassStudentMapper.java new file mode 100644 index 00000000..0ee06698 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/ClassStudentMapper.java @@ -0,0 +1,13 @@ +package com.orange.demo.app.dao; + +import com.orange.demo.common.core.base.dao.BaseDaoMapper; +import com.orange.demo.app.model.ClassStudent; + +/** + * 数据操作访问接口。 + * + * @author Jerry + * @date 2020-09-25 + */ +public interface ClassStudentMapper extends BaseDaoMapper { +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/CourseMapper.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/CourseMapper.java new file mode 100644 index 00000000..9a88b9a9 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/CourseMapper.java @@ -0,0 +1,52 @@ +package com.orange.demo.app.dao; + +import com.orange.demo.common.core.base.dao.BaseDaoMapper; +import com.orange.demo.app.model.Course; +import org.apache.ibatis.annotations.Param; + +import java.util.*; + +/** + * 课程数据数据操作访问接口。 + * + * @author Jerry + * @date 2020-09-25 + */ +public interface CourseMapper extends BaseDaoMapper { + + /** + * 获取过滤后的对象列表。 + * + * @param courseFilter 主表过滤对象。 + * @param orderBy 排序字符串,order by从句的参数。 + * @return 对象列表。 + */ + List getCourseList( + @Param("courseFilter") Course courseFilter, @Param("orderBy") String orderBy); + + /** + * 根据关联主表Id,获取关联从表数据列表。 + * + * @param classId 关联主表Id。 + * @param courseFilter 从表过滤对象。 + * @param orderBy 排序字符串,order by从句的参数。 + * @return 从表数据列表。 + */ + List getCourseListByClassId( + @Param("classId") Long classId, + @Param("courseFilter") Course courseFilter, + @Param("orderBy") String orderBy); + + /** + * 根据关联主表Id,获取关联从表中没有和主表建立关联关系的数据列表。 + * + * @param classId 关联主表Id。 + * @param courseFilter 过滤对象。 + * @param orderBy 排序字符串,order by从句的参数。 + * @return 与主表没有建立关联的从表数据列表。 + */ + List getNotInCourseListByClassId( + @Param("classId") Long classId, + @Param("courseFilter") Course courseFilter, + @Param("orderBy") String orderBy); +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/CourseTransStatsMapper.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/CourseTransStatsMapper.java new file mode 100644 index 00000000..f249b8a6 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/CourseTransStatsMapper.java @@ -0,0 +1,41 @@ +package com.orange.demo.app.dao; + +import com.orange.demo.common.core.base.dao.BaseDaoMapper; +import com.orange.demo.app.model.CourseTransStats; +import org.apache.ibatis.annotations.Param; + +import java.util.*; + +/** + * 课程统计数据操作访问接口。 + * + * @author Jerry + * @date 2020-09-25 + */ +public interface CourseTransStatsMapper extends BaseDaoMapper { + + /** + * 获取分组计算后的数据对象列表。 + * + * @param courseTransStatsFilter 主表过滤对象。 + * @param groupSelect 分组显示字段列表字符串,SELECT从句的参数。 + * @param groupBy 分组字段列表字符串,GROUP BY从句的参数。 + * @param orderBy 排序字符串,ORDER BY从句的参数。 + * @return 对象列表。 + */ + List getGroupedCourseTransStatsList( + @Param("courseTransStatsFilter") CourseTransStats courseTransStatsFilter, + @Param("groupSelect") String groupSelect, + @Param("groupBy") String groupBy, + @Param("orderBy") String orderBy); + + /** + * 获取过滤后的对象列表。 + * + * @param courseTransStatsFilter 主表过滤对象。 + * @param orderBy 排序字符串,order by从句的参数。 + * @return 对象列表。 + */ + List getCourseTransStatsList( + @Param("courseTransStatsFilter") CourseTransStats courseTransStatsFilter, @Param("orderBy") String orderBy); +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/GradeMapper.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/GradeMapper.java new file mode 100644 index 00000000..657dcdbf --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/GradeMapper.java @@ -0,0 +1,13 @@ +package com.orange.demo.app.dao; + +import com.orange.demo.common.core.base.dao.BaseDaoMapper; +import com.orange.demo.app.model.Grade; + +/** + * 年级数据操作访问接口。 + * + * @author Jerry + * @date 2020-09-25 + */ +public interface GradeMapper extends BaseDaoMapper { +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/MaterialEditionMapper.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/MaterialEditionMapper.java new file mode 100644 index 00000000..7d4f6106 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/MaterialEditionMapper.java @@ -0,0 +1,13 @@ +package com.orange.demo.app.dao; + +import com.orange.demo.common.core.base.dao.BaseDaoMapper; +import com.orange.demo.app.model.MaterialEdition; + +/** + * 数据操作访问接口。 + * + * @author Jerry + * @date 2020-09-25 + */ +public interface MaterialEditionMapper extends BaseDaoMapper { +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/SchoolInfoMapper.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/SchoolInfoMapper.java new file mode 100644 index 00000000..fa57e4c5 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/SchoolInfoMapper.java @@ -0,0 +1,26 @@ +package com.orange.demo.app.dao; + +import com.orange.demo.common.core.base.dao.BaseDaoMapper; +import com.orange.demo.app.model.SchoolInfo; +import org.apache.ibatis.annotations.Param; + +import java.util.*; + +/** + * 校区数据数据操作访问接口。 + * + * @author Jerry + * @date 2020-09-25 + */ +public interface SchoolInfoMapper extends BaseDaoMapper { + + /** + * 获取过滤后的对象列表。 + * + * @param schoolInfoFilter 主表过滤对象。 + * @param orderBy 排序字符串,order by从句的参数。 + * @return 对象列表。 + */ + List getSchoolInfoList( + @Param("schoolInfoFilter") SchoolInfo schoolInfoFilter, @Param("orderBy") String orderBy); +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/StudentActionStatsMapper.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/StudentActionStatsMapper.java new file mode 100644 index 00000000..792286b8 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/StudentActionStatsMapper.java @@ -0,0 +1,41 @@ +package com.orange.demo.app.dao; + +import com.orange.demo.common.core.base.dao.BaseDaoMapper; +import com.orange.demo.app.model.StudentActionStats; +import org.apache.ibatis.annotations.Param; + +import java.util.*; + +/** + * 学生行为统计数据操作访问接口。 + * + * @author Jerry + * @date 2020-09-25 + */ +public interface StudentActionStatsMapper extends BaseDaoMapper { + + /** + * 获取分组计算后的数据对象列表。 + * + * @param studentActionStatsFilter 主表过滤对象。 + * @param groupSelect 分组显示字段列表字符串,SELECT从句的参数。 + * @param groupBy 分组字段列表字符串,GROUP BY从句的参数。 + * @param orderBy 排序字符串,ORDER BY从句的参数。 + * @return 对象列表。 + */ + List getGroupedStudentActionStatsList( + @Param("studentActionStatsFilter") StudentActionStats studentActionStatsFilter, + @Param("groupSelect") String groupSelect, + @Param("groupBy") String groupBy, + @Param("orderBy") String orderBy); + + /** + * 获取过滤后的对象列表。 + * + * @param studentActionStatsFilter 主表过滤对象。 + * @param orderBy 排序字符串,order by从句的参数。 + * @return 对象列表。 + */ + List getStudentActionStatsList( + @Param("studentActionStatsFilter") StudentActionStats studentActionStatsFilter, @Param("orderBy") String orderBy); +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/StudentActionTransMapper.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/StudentActionTransMapper.java new file mode 100644 index 00000000..a131f60f --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/StudentActionTransMapper.java @@ -0,0 +1,26 @@ +package com.orange.demo.app.dao; + +import com.orange.demo.common.core.base.dao.BaseDaoMapper; +import com.orange.demo.app.model.StudentActionTrans; +import org.apache.ibatis.annotations.Param; + +import java.util.*; + +/** + * 学生行为流水数据操作访问接口。 + * + * @author Jerry + * @date 2020-09-25 + */ +public interface StudentActionTransMapper extends BaseDaoMapper { + + /** + * 获取过滤后的对象列表。 + * + * @param studentActionTransFilter 主表过滤对象。 + * @param orderBy 排序字符串,order by从句的参数。 + * @return 对象列表。 + */ + List getStudentActionTransList( + @Param("studentActionTransFilter") StudentActionTrans studentActionTransFilter, @Param("orderBy") String orderBy); +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/StudentClassMapper.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/StudentClassMapper.java new file mode 100644 index 00000000..29aaf450 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/StudentClassMapper.java @@ -0,0 +1,26 @@ +package com.orange.demo.app.dao; + +import com.orange.demo.common.core.base.dao.BaseDaoMapper; +import com.orange.demo.app.model.StudentClass; +import org.apache.ibatis.annotations.Param; + +import java.util.*; + +/** + * 班级数据数据操作访问接口。 + * + * @author Jerry + * @date 2020-09-25 + */ +public interface StudentClassMapper extends BaseDaoMapper { + + /** + * 获取过滤后的对象列表。 + * + * @param studentClassFilter 主表过滤对象。 + * @param orderBy 排序字符串,order by从句的参数。 + * @return 对象列表。 + */ + List getStudentClassList( + @Param("studentClassFilter") StudentClass studentClassFilter, @Param("orderBy") String orderBy); +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/StudentMapper.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/StudentMapper.java new file mode 100644 index 00000000..e8ba5dc9 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/StudentMapper.java @@ -0,0 +1,52 @@ +package com.orange.demo.app.dao; + +import com.orange.demo.common.core.base.dao.BaseDaoMapper; +import com.orange.demo.app.model.Student; +import org.apache.ibatis.annotations.Param; + +import java.util.*; + +/** + * 学生数据数据操作访问接口。 + * + * @author Jerry + * @date 2020-09-25 + */ +public interface StudentMapper extends BaseDaoMapper { + + /** + * 获取过滤后的对象列表。 + * + * @param studentFilter 主表过滤对象。 + * @param orderBy 排序字符串,order by从句的参数。 + * @return 对象列表。 + */ + List getStudentList( + @Param("studentFilter") Student studentFilter, @Param("orderBy") String orderBy); + + /** + * 根据关联主表Id,获取关联从表数据列表。 + * + * @param classId 关联主表Id。 + * @param studentFilter 从表过滤对象。 + * @param orderBy 排序字符串,order by从句的参数。 + * @return 从表数据列表。 + */ + List getStudentListByClassId( + @Param("classId") Long classId, + @Param("studentFilter") Student studentFilter, + @Param("orderBy") String orderBy); + + /** + * 根据关联主表Id,获取关联从表中没有和主表建立关联关系的数据列表。 + * + * @param classId 关联主表Id。 + * @param studentFilter 过滤对象。 + * @param orderBy 排序字符串,order by从句的参数。 + * @return 与主表没有建立关联的从表数据列表。 + */ + List getNotInStudentListByClassId( + @Param("classId") Long classId, + @Param("studentFilter") Student studentFilter, + @Param("orderBy") String orderBy); +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/mapper/AreaCodeMapper.xml b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/mapper/AreaCodeMapper.xml new file mode 100644 index 00000000..a65ab49a --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/mapper/AreaCodeMapper.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/mapper/ClassCourseMapper.xml b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/mapper/ClassCourseMapper.xml new file mode 100644 index 00000000..7fd02629 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/mapper/ClassCourseMapper.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/mapper/ClassStudentMapper.xml b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/mapper/ClassStudentMapper.xml new file mode 100644 index 00000000..7e0a0952 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/mapper/ClassStudentMapper.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/mapper/CourseMapper.xml b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/mapper/CourseMapper.xml new file mode 100644 index 00000000..41f2ae23 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/mapper/CourseMapper.xml @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + + + + + + + + + + AND zz_course.course_name LIKE #{safeCourseName} + + + AND zz_course.price >= #{courseFilter.priceStart} + + + AND zz_course.price <= #{courseFilter.priceEnd} + + + AND zz_course.difficulty = #{courseFilter.difficulty} + + + AND zz_course.grade_id = #{courseFilter.gradeId} + + + AND zz_course.subject_id = #{courseFilter.subjectId} + + + AND zz_course.class_hour >= #{courseFilter.classHourStart} + + + AND zz_course.class_hour <= #{courseFilter.classHourEnd} + + + AND zz_course.create_time >= #{courseFilter.createTimeStart} + + + AND zz_course.create_time <= #{courseFilter.createTimeEnd} + + + + + + + + + + diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/mapper/CourseTransStatsMapper.xml b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/mapper/CourseTransStatsMapper.xml new file mode 100644 index 00000000..cc20e41f --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/mapper/CourseTransStatsMapper.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + AND zz_course_trans_stats.stats_date >= #{courseTransStatsFilter.statsDateStart} + + + AND zz_course_trans_stats.stats_date <= #{courseTransStatsFilter.statsDateEnd} + + + AND zz_course_trans_stats.subject_id = #{courseTransStatsFilter.subjectId} + + + AND zz_course_trans_stats.grade_id = #{courseTransStatsFilter.gradeId} + + + + + + + + diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/mapper/GradeMapper.xml b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/mapper/GradeMapper.xml new file mode 100644 index 00000000..0ed23888 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/mapper/GradeMapper.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/mapper/MaterialEditionMapper.xml b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/mapper/MaterialEditionMapper.xml new file mode 100644 index 00000000..75c26ef4 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/mapper/MaterialEditionMapper.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/mapper/SchoolInfoMapper.xml b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/mapper/SchoolInfoMapper.xml new file mode 100644 index 00000000..a7db22d2 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/mapper/SchoolInfoMapper.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + AND zz_school_info.school_name LIKE #{safeSchoolName} + + + AND zz_school_info.province_id = #{schoolInfoFilter.provinceId} + + + AND zz_school_info.city_id = #{schoolInfoFilter.cityId} + + + + + + diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/mapper/StudentActionStatsMapper.xml b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/mapper/StudentActionStatsMapper.xml new file mode 100644 index 00000000..fdd1e8e9 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/mapper/StudentActionStatsMapper.xml @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AND zz_student_action_stats.stats_date >= #{studentActionStatsFilter.statsDateStart} + + + AND zz_student_action_stats.stats_date <= #{studentActionStatsFilter.statsDateEnd} + + + AND zz_student_action_stats.grade_id = #{studentActionStatsFilter.gradeId} + + + AND zz_student_action_stats.province_id = #{studentActionStatsFilter.provinceId} + + + AND zz_student_action_stats.city_id = #{studentActionStatsFilter.cityId} + + + + + + + + diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/mapper/StudentActionTransMapper.xml b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/mapper/StudentActionTransMapper.xml new file mode 100644 index 00000000..4375e6d3 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/mapper/StudentActionTransMapper.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + AND zz_student_action_trans.student_id = #{studentActionTransFilter.studentId} + + + AND zz_student_action_trans.school_id = #{studentActionTransFilter.schoolId} + + + AND zz_student_action_trans.grade_id = #{studentActionTransFilter.gradeId} + + + AND zz_student_action_trans.action_type = #{studentActionTransFilter.actionType} + + + AND zz_student_action_trans.device_type = #{studentActionTransFilter.deviceType} + + + AND zz_student_action_trans.create_time >= #{studentActionTransFilter.createTimeStart} + + + AND zz_student_action_trans.create_time <= #{studentActionTransFilter.createTimeEnd} + + + + + + diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/mapper/StudentClassMapper.xml b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/mapper/StudentClassMapper.xml new file mode 100644 index 00000000..a32e79b0 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/mapper/StudentClassMapper.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + AND zz_class.class_name = #{studentClassFilter.className} + + + AND zz_class.school_id = #{studentClassFilter.schoolId} + + + AND zz_class.class_level = #{studentClassFilter.classLevel} + + + AND zz_class.status = ${@com.orange.demo.common.core.constant.GlobalDeletedFlag@NORMAL} + + + + diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/mapper/StudentMapper.xml b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/mapper/StudentMapper.xml new file mode 100644 index 00000000..81ee2f42 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/dao/mapper/StudentMapper.xml @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + AND zz_student.province_id = #{studentFilter.provinceId} + + + AND zz_student.city_id = #{studentFilter.cityId} + + + AND zz_student.district_id = #{studentFilter.districtId} + + + AND zz_student.birthday >= #{studentFilter.birthdayStart} + + + AND zz_student.birthday <= #{studentFilter.birthdayEnd} + + + AND zz_student.grade_id = #{studentFilter.gradeId} + + + AND zz_student.school_id = #{studentFilter.schoolId} + + + AND zz_student.register_time >= #{studentFilter.registerTimeStart} + + + AND zz_student.register_time <= #{studentFilter.registerTimeEnd} + + + AND zz_student.status = #{studentFilter.status} + + + + AND CONCAT(IFNULL(zz_student.login_mobile,''), IFNULL(zz_student.student_name,'')) LIKE #{safeSearchString} + + + + + + + + + + diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/AreaCode.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/AreaCode.java new file mode 100644 index 00000000..5f9450ab --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/AreaCode.java @@ -0,0 +1,41 @@ +package com.orange.demo.app.model; + +import lombok.Data; + +import javax.persistence.*; + +/** + * 行政区划实体对象。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Data +@Table(name = "zz_area_code") +public class AreaCode { + + /** + * 行政区划主键Id + */ + @Id + @Column(name = "area_id") + private Long areaId; + + /** + * 行政区划名称 + */ + @Column(name = "area_name") + private String areaName; + + /** + * 行政区划级别 (1: 省级别 2: 市级别 3: 区级别) + */ + @Column(name = "area_level") + private Integer areaLevel; + + /** + * 父级行政区划Id + */ + @Column(name = "parent_id") + private Long parentId; +} \ No newline at end of file diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/ClassCourse.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/ClassCourse.java new file mode 100644 index 00000000..0b45e248 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/ClassCourse.java @@ -0,0 +1,40 @@ +package com.orange.demo.app.model; + +import com.orange.demo.common.core.validator.UpdateGroup; +import lombok.Data; +import javax.persistence.*; +import javax.validation.constraints.*; + +/** + * ClassCourse实体对象。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Data +@Table(name = "zz_class_course") +public class ClassCourse { + + /** + * 班级Id。 + */ + @NotNull(message = "数据验证失败,班级Id不能为空!", groups = {UpdateGroup.class}) + @Id + @Column(name = "class_id") + private Long classId; + + /** + * 课程Id。 + */ + @NotNull(message = "数据验证失败,课程Id不能为空!", groups = {UpdateGroup.class}) + @Id + @Column(name = "course_id") + private Long courseId; + + /** + * 课程顺序(数值越小越靠前)。 + */ + @NotNull(message = "数据验证失败,课程顺序(数值越小越靠前)不能为空!", groups = {UpdateGroup.class}) + @Column(name = "course_order") + private Integer courseOrder; +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/ClassStudent.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/ClassStudent.java new file mode 100644 index 00000000..f08ea947 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/ClassStudent.java @@ -0,0 +1,33 @@ +package com.orange.demo.app.model; + +import com.orange.demo.common.core.validator.UpdateGroup; +import lombok.Data; +import javax.persistence.*; +import javax.validation.constraints.*; + +/** + * ClassStudent实体对象。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Data +@Table(name = "zz_class_student") +public class ClassStudent { + + /** + * 班级Id。 + */ + @NotNull(message = "数据验证失败,班级Id不能为空!", groups = {UpdateGroup.class}) + @Id + @Column(name = "class_id") + private Long classId; + + /** + * 学生Id。 + */ + @NotNull(message = "数据验证失败,学生Id不能为空!", groups = {UpdateGroup.class}) + @Id + @Column(name = "student_id") + private Long studentId; +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/Course.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/Course.java new file mode 100644 index 00000000..d70160f1 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/Course.java @@ -0,0 +1,163 @@ +package com.orange.demo.app.model; + +import com.orange.demo.app.model.constant.CourseDifficult; +import com.orange.demo.application.common.constant.Subject; +import com.orange.demo.common.core.annotation.RelationDict; +import com.orange.demo.common.core.annotation.RelationConstDict; +import com.orange.demo.common.core.validator.UpdateGroup; +import com.orange.demo.common.core.validator.ConstDictRef; +import lombok.Data; +import javax.persistence.*; +import javax.validation.constraints.*; + +import java.math.BigDecimal; +import java.util.Date; +import java.util.Map; + +/** + * Course实体对象。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Data +@Table(name = "zz_course") +public class Course { + + /** + * 主键Id。 + */ + @NotNull(message = "数据验证失败,主键Id不能为空!", groups = {UpdateGroup.class}) + @Id + @Column(name = "course_id") + private Long courseId; + + /** + * 课程名称。 + */ + @NotBlank(message = "数据验证失败,课程名称不能为空!") + @Column(name = "course_name") + private String courseName; + + /** + * 课程价格。 + */ + @NotNull(message = "数据验证失败,课程价格不能为空!") + private BigDecimal price; + + /** + * 课程描述。 + */ + private String description; + + /** + * 课程难度(0: 容易 1: 普通 2: 很难)。 + */ + @NotNull(message = "数据验证失败,课程难度不能为空!") + @ConstDictRef(constDictClass = CourseDifficult.class, message = "数据验证失败,课程难度为无效值!") + private Integer difficulty; + + /** + * 年级Id。 + */ + @NotNull(message = "数据验证失败,所属年级不能为空!") + @Column(name = "grade_id") + private Integer gradeId; + + /** + * 学科Id。 + */ + @NotNull(message = "数据验证失败,所属学科不能为空!") + @ConstDictRef(constDictClass = Subject.class, message = "数据验证失败,所属学科为无效值!") + @Column(name = "subject_id") + private Integer subjectId; + + /** + * 课时数量。 + */ + @NotNull(message = "数据验证失败,课时数量不能为空!") + @Column(name = "class_hour") + private Integer classHour; + + /** + * 多张课程图片地址。 + */ + @NotBlank(message = "数据验证失败,课程图片不能为空!") + @Column(name = "picture_url") + private String pictureUrl; + + /** + * 创建用户Id。 + */ + @Column(name = "create_user_id") + private Long createUserId; + + /** + * 创建时间。 + */ + @Column(name = "create_time") + private Date createTime; + + /** + * 最后修改时间。 + */ + @Column(name = "update_time") + private Date updateTime; + + /** + * price 范围过滤起始值(>=)。 + */ + @Transient + private BigDecimal priceStart; + + /** + * price 范围过滤结束值(<=)。 + */ + @Transient + private BigDecimal priceEnd; + + /** + * classHour 范围过滤起始值(>=)。 + */ + @Transient + private Integer classHourStart; + + /** + * classHour 范围过滤结束值(<=)。 + */ + @Transient + private Integer classHourEnd; + + /** + * createTime 范围过滤起始值(>=)。 + */ + @Transient + private String createTimeStart; + + /** + * createTime 范围过滤结束值(<=)。 + */ + @Transient + private String createTimeEnd; + + @RelationDict( + masterIdField = "gradeId", + slaveServiceName = "gradeService", + slaveModelClass = Grade.class, + slaveIdField = "gradeId", + slaveNameField = "gradeName") + @Transient + private Map gradeIdDictMap; + + @RelationConstDict( + masterIdField = "difficulty", + constantDictClass = CourseDifficult.class) + @Transient + private Map difficultyDictMap; + + @RelationConstDict( + masterIdField = "subjectId", + constantDictClass = Subject.class) + @Transient + private Map subjectIdDictMap; +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/CourseTransStats.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/CourseTransStats.java new file mode 100644 index 00000000..63839cd3 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/CourseTransStats.java @@ -0,0 +1,122 @@ +package com.orange.demo.app.model; + +import com.orange.demo.application.common.constant.Subject; +import com.orange.demo.common.core.annotation.RelationDict; +import com.orange.demo.common.core.annotation.RelationConstDict; +import com.orange.demo.common.core.validator.UpdateGroup; +import com.orange.demo.common.core.validator.ConstDictRef; +import lombok.Data; +import javax.persistence.*; +import javax.validation.constraints.*; + +import java.util.Date; +import java.util.Map; + +/** + * CourseTransStats实体对象。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Data +@Table(name = "zz_course_trans_stats") +public class CourseTransStats { + + /** + * 主键Id。 + */ + @NotNull(message = "数据验证失败,主键Id不能为空!", groups = {UpdateGroup.class}) + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "stats_id") + private Long statsId; + + /** + * 统计日期。 + */ + @NotNull(message = "数据验证失败,统计日期不能为空!") + @Column(name = "stats_date") + private Date statsDate; + + /** + * 科目Id。 + */ + @NotNull(message = "数据验证失败,所属科目不能为空!") + @ConstDictRef(constDictClass = Subject.class, message = "数据验证失败,所属科目为无效值!") + @Column(name = "subject_id") + private Integer subjectId; + + /** + * 年级Id。 + */ + @NotNull(message = "数据验证失败,所属年级不能为空!") + @Column(name = "grade_id") + private Integer gradeId; + + /** + * 年级名称。 + */ + @Column(name = "grade_name") + private String gradeName; + + /** + * 课程Id。 + */ + @NotNull(message = "数据验证失败,课程Id不能为空!") + @Column(name = "course_id") + private Long courseId; + + /** + * 课程名称。 + */ + @Column(name = "course_name") + private String courseName; + + /** + * 学生上课次数。 + */ + @NotNull(message = "数据验证失败,上课次数不能为空!") + @Column(name = "student_attend_count") + private Integer studentAttendCount; + + /** + * 学生献花数量。 + */ + @NotNull(message = "数据验证失败,献花数量不能为空!") + @Column(name = "student_flower_amount") + private Integer studentFlowerAmount; + + /** + * 学生献花次数。 + */ + @NotNull(message = "数据验证失败,献花次数不能为空!") + @Column(name = "student_flower_count") + private Integer studentFlowerCount; + + /** + * statsDate 范围过滤起始值(>=)。 + */ + @Transient + private String statsDateStart; + + /** + * statsDate 范围过滤结束值(<=)。 + */ + @Transient + private String statsDateEnd; + + @RelationDict( + masterIdField = "gradeId", + slaveServiceName = "gradeService", + slaveModelClass = Grade.class, + slaveIdField = "gradeId", + slaveNameField = "gradeName") + @Transient + private Map gradeIdDictMap; + + @RelationConstDict( + masterIdField = "subjectId", + constantDictClass = Subject.class) + @Transient + private Map subjectIdDictMap; +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/Grade.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/Grade.java new file mode 100644 index 00000000..af1849cb --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/Grade.java @@ -0,0 +1,42 @@ +package com.orange.demo.app.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.orange.demo.common.core.annotation.DeletedFlagColumn; +import com.orange.demo.common.core.validator.UpdateGroup; +import lombok.Data; +import javax.persistence.*; +import javax.validation.constraints.*; + +/** + * Grade实体对象。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Data +@Table(name = "zz_grade") +public class Grade { + + /** + * 主键Id。 + */ + @NotNull(message = "数据验证失败,主键Id不能为空!", groups = {UpdateGroup.class}) + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "grade_id") + private Integer gradeId; + + /** + * 年级名称。 + */ + @NotBlank(message = "数据验证失败,年级名称不能为空!") + @Column(name = "grade_name") + private String gradeName; + + /** + * 逻辑删除标记字段(1: 正常 -1: 已删除)。 + */ + @JSONField(serialize = false) + @DeletedFlagColumn + private Integer status; +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/MaterialEdition.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/MaterialEdition.java new file mode 100644 index 00000000..681e9d54 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/MaterialEdition.java @@ -0,0 +1,39 @@ +package com.orange.demo.app.model; + +import com.orange.demo.common.core.validator.UpdateGroup; +import lombok.Data; +import javax.persistence.*; +import javax.validation.constraints.*; + +/** + * MaterialEdition实体对象。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Data +@Table(name = "zz_material_edition") +public class MaterialEdition { + + /** + * 主键Id。 + */ + @NotNull(message = "数据验证失败,主键Id不能为空!", groups = {UpdateGroup.class}) + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "edition_id") + private Integer editionId; + + /** + * 教材版本名称。 + */ + @NotBlank(message = "数据验证失败,教材版本名称不能为空!") + @Column(name = "edition_name") + private String editionName; + + /** + * 是否正在使用(0:不是,1:是)。 + */ + @NotNull(message = "数据验证失败,是否正在使用(0:不是,1:是)不能为空!") + private Integer status; +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/SchoolInfo.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/SchoolInfo.java new file mode 100644 index 00000000..dc7096e2 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/SchoolInfo.java @@ -0,0 +1,67 @@ +package com.orange.demo.app.model; + +import com.orange.demo.common.core.annotation.RelationDict; +import com.orange.demo.common.core.validator.UpdateGroup; +import lombok.Data; +import javax.persistence.*; +import javax.validation.constraints.*; + +import java.util.Map; + +/** + * SchoolInfo实体对象。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Data +@Table(name = "zz_school_info") +public class SchoolInfo { + + /** + * 学校Id。 + */ + @NotNull(message = "数据验证失败,学校Id不能为空!", groups = {UpdateGroup.class}) + @Id + @Column(name = "school_id") + private Long schoolId; + + /** + * 学校名称。 + */ + @NotBlank(message = "数据验证失败,学校名称不能为空!") + @Column(name = "school_name") + private String schoolName; + + /** + * 所在省Id。 + */ + @NotNull(message = "数据验证失败,所在省份不能为空!") + @Column(name = "province_id") + private Long provinceId; + + /** + * 所在城市Id。 + */ + @NotNull(message = "数据验证失败,所在城市不能为空!") + @Column(name = "city_id") + private Long cityId; + + @RelationDict( + masterIdField = "provinceId", + slaveServiceName = "areaCodeService", + slaveModelClass = AreaCode.class, + slaveIdField = "areaId", + slaveNameField = "areaName") + @Transient + private Map provinceIdDictMap; + + @RelationDict( + masterIdField = "cityId", + slaveServiceName = "areaCodeService", + slaveModelClass = AreaCode.class, + slaveIdField = "areaId", + slaveNameField = "areaName") + @Transient + private Map cityIdDictMap; +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/Student.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/Student.java new file mode 100644 index 00000000..ea66a23e --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/Student.java @@ -0,0 +1,224 @@ +package com.orange.demo.app.model; + +import com.orange.demo.application.common.constant.Gender; +import com.orange.demo.application.common.constant.ExpLevel; +import com.orange.demo.application.common.constant.StudentStatus; +import com.orange.demo.common.core.annotation.RelationDict; +import com.orange.demo.common.core.annotation.RelationConstDict; +import com.orange.demo.common.core.validator.UpdateGroup; +import com.orange.demo.common.core.validator.ConstDictRef; +import lombok.Data; +import javax.persistence.*; +import javax.validation.constraints.*; + +import java.util.Date; +import java.util.Map; + +/** + * Student实体对象。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Data +@Table(name = "zz_student") +public class Student { + + /** + * 学生Id。 + */ + @NotNull(message = "数据验证失败,学生Id不能为空!", groups = {UpdateGroup.class}) + @Id + @Column(name = "student_id") + private Long studentId; + + /** + * 登录手机。 + */ + @NotBlank(message = "数据验证失败,手机号码不能为空!") + @Column(name = "login_mobile") + private String loginMobile; + + /** + * 学生姓名。 + */ + @NotBlank(message = "数据验证失败,学生姓名不能为空!") + @Column(name = "student_name") + private String studentName; + + /** + * 所在省份Id。 + */ + @NotNull(message = "数据验证失败,所在省份不能为空!") + @Column(name = "province_id") + private Long provinceId; + + /** + * 所在城市Id。 + */ + @NotNull(message = "数据验证失败,所在城市不能为空!") + @Column(name = "city_id") + private Long cityId; + + /** + * 区县Id。 + */ + @NotNull(message = "数据验证失败,所在区县不能为空!") + @Column(name = "district_id") + private Long districtId; + + /** + * 学生性别 (0: 女生 1: 男生)。 + */ + @NotNull(message = "数据验证失败,学生性别不能为空!") + @ConstDictRef(constDictClass = Gender.class, message = "数据验证失败,学生性别为无效值!") + private Integer gender; + + /** + * 生日。 + */ + @NotNull(message = "数据验证失败,出生日期不能为空!") + private Date birthday; + + /** + * 经验等级 (0: 初级 1: 中级 2: 高级 3: 资深)。 + */ + @NotNull(message = "数据验证失败,经验等级不能为空!") + @ConstDictRef(constDictClass = ExpLevel.class, message = "数据验证失败,经验等级为无效值!") + @Column(name = "experience_level") + private Integer experienceLevel; + + /** + * 总共充值学币数量。 + */ + @NotNull(message = "数据验证失败,充值学币不能为空!", groups = {UpdateGroup.class}) + @Column(name = "total_coin") + private Integer totalCoin; + + /** + * 可用学币数量。 + */ + @NotNull(message = "数据验证失败,剩余学币不能为空!") + @Column(name = "left_coin") + private Integer leftCoin; + + /** + * 年级Id。 + */ + @NotNull(message = "数据验证失败,年级不能为空!") + @Column(name = "grade_id") + private Integer gradeId; + + /** + * 校区Id。 + */ + @NotNull(message = "数据验证失败,所属校区不能为空!") + @Column(name = "school_id") + private Long schoolId; + + /** + * 注册时间。 + */ + @Column(name = "register_time") + private Date registerTime; + + /** + * 学生状态 (0: 正常 1: 锁定 2: 注销)。 + */ + @NotNull(message = "数据验证失败,学生状态不能为空!", groups = {UpdateGroup.class}) + @ConstDictRef(constDictClass = StudentStatus.class, message = "数据验证失败,学生状态为无效值!") + private Integer status; + + /** + * birthday 范围过滤起始值(>=)。 + */ + @Transient + private String birthdayStart; + + /** + * birthday 范围过滤结束值(<=)。 + */ + @Transient + private String birthdayEnd; + + /** + * registerTime 范围过滤起始值(>=)。 + */ + @Transient + private String registerTimeStart; + + /** + * registerTime 范围过滤结束值(<=)。 + */ + @Transient + private String registerTimeEnd; + + /** + * login_mobile / student_name LIKE搜索字符串。 + */ + @Transient + private String searchString; + + @RelationDict( + masterIdField = "provinceId", + slaveServiceName = "areaCodeService", + slaveModelClass = AreaCode.class, + slaveIdField = "areaId", + slaveNameField = "areaName") + @Transient + private Map provinceIdDictMap; + + @RelationDict( + masterIdField = "cityId", + slaveServiceName = "areaCodeService", + slaveModelClass = AreaCode.class, + slaveIdField = "areaId", + slaveNameField = "areaName") + @Transient + private Map cityIdDictMap; + + @RelationDict( + masterIdField = "districtId", + slaveServiceName = "areaCodeService", + slaveModelClass = AreaCode.class, + slaveIdField = "areaId", + slaveNameField = "areaName") + @Transient + private Map districtIdDictMap; + + @RelationDict( + masterIdField = "gradeId", + slaveServiceName = "gradeService", + slaveModelClass = Grade.class, + slaveIdField = "gradeId", + slaveNameField = "gradeName") + @Transient + private Map gradeIdDictMap; + + @RelationDict( + masterIdField = "schoolId", + slaveServiceName = "schoolInfoService", + slaveModelClass = SchoolInfo.class, + slaveIdField = "schoolId", + slaveNameField = "schoolName") + @Transient + private Map schoolIdDictMap; + + @RelationConstDict( + masterIdField = "gender", + constantDictClass = Gender.class) + @Transient + private Map genderDictMap; + + @RelationConstDict( + masterIdField = "experienceLevel", + constantDictClass = ExpLevel.class) + @Transient + private Map experienceLevelDictMap; + + @RelationConstDict( + masterIdField = "status", + constantDictClass = StudentStatus.class) + @Transient + private Map statusDictMap; +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/StudentActionStats.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/StudentActionStats.java new file mode 100644 index 00000000..d027a297 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/StudentActionStats.java @@ -0,0 +1,207 @@ +package com.orange.demo.app.model; + +import com.orange.demo.common.core.annotation.RelationDict; +import com.orange.demo.common.core.validator.UpdateGroup; +import lombok.Data; +import javax.persistence.*; +import javax.validation.constraints.*; + +import java.util.Date; +import java.util.Map; + +/** + * StudentActionStats实体对象。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Data +@Table(name = "zz_student_action_stats") +public class StudentActionStats { + + /** + * 主键Id。 + */ + @NotNull(message = "数据验证失败,主键Id不能为空!", groups = {UpdateGroup.class}) + @Id + @Column(name = "stats_id") + private Long statsId; + + /** + * 统计日期。 + */ + @NotNull(message = "数据验证失败,统计日期不能为空!") + @Column(name = "stats_date") + private Date statsDate; + + /** + * 统计小时。 + */ + @Column(name = "stats_month") + private Date statsMonth; + + /** + * 年级Id。 + */ + @NotNull(message = "数据验证失败,所属年级不能为空!") + @Column(name = "grade_id") + private Integer gradeId; + + /** + * 学生所在省Id。 + */ + @NotNull(message = "数据验证失败,所在省份不能为空!") + @Column(name = "province_id") + private Long provinceId; + + /** + * 学生所在城市Id。 + */ + @NotNull(message = "数据验证失败,所在城市不能为空!", groups = {UpdateGroup.class}) + @Column(name = "city_id") + private Long cityId; + + /** + * 购课学币数量。 + */ + @NotNull(message = "数据验证失败,购课学币数量不能为空!", groups = {UpdateGroup.class}) + @Column(name = "buy_course_amount") + private Integer buyCourseAmount; + + /** + * 购买课程次数。 + */ + @NotNull(message = "数据验证失败,购买课程次数不能为空!", groups = {UpdateGroup.class}) + @Column(name = "buy_course_count") + private Integer buyCourseCount; + + /** + * 购买视频学币数量。 + */ + @NotNull(message = "数据验证失败,购买视频学币数量不能为空!", groups = {UpdateGroup.class}) + @Column(name = "buy_video_amount") + private Integer buyVideoAmount; + + /** + * 购买视频次数。 + */ + @NotNull(message = "数据验证失败,购买视频次数不能为空!", groups = {UpdateGroup.class}) + @Column(name = "buy_video_count") + private Integer buyVideoCount; + + /** + * 购买作业学币数量。 + */ + @NotNull(message = "数据验证失败,购买作业学币数量不能为空!", groups = {UpdateGroup.class}) + @Column(name = "buy_paper_amount") + private Integer buyPaperAmount; + + /** + * 购买作业次数。 + */ + @NotNull(message = "数据验证失败,购买作业次数不能为空!", groups = {UpdateGroup.class}) + @Column(name = "buy_paper_count") + private Integer buyPaperCount; + + /** + * 购买献花数量。 + */ + @NotNull(message = "数据验证失败,购买献花数量不能为空!", groups = {UpdateGroup.class}) + @Column(name = "buy_flower_amount") + private Integer buyFlowerAmount; + + /** + * 购买献花次数。 + */ + @NotNull(message = "数据验证失败,购买献花次数不能为空!", groups = {UpdateGroup.class}) + @Column(name = "buy_flower_count") + private Integer buyFlowerCount; + + /** + * 充值学币数量。 + */ + @NotNull(message = "数据验证失败,充值学币数量不能为空!", groups = {UpdateGroup.class}) + @Column(name = "recharge_coin_amount") + private Integer rechargeCoinAmount; + + /** + * 充值学币次数。 + */ + @NotNull(message = "数据验证失败,充值学币次数不能为空!", groups = {UpdateGroup.class}) + @Column(name = "recharge_coin_count") + private Integer rechargeCoinCount; + + /** + * 线下课程上课次数。 + */ + @NotNull(message = "数据验证失败,线下课程上课次数不能为空!") + @Column(name = "do_course_count") + private Integer doCourseCount; + + /** + * 观看视频次数。 + */ + @NotNull(message = "数据验证失败,观看视频次数不能为空!", groups = {UpdateGroup.class}) + @Column(name = "watch_video_count") + private Integer watchVideoCount; + + /** + * 购买献花消费学币数量。 + */ + @NotNull(message = "数据验证失败,购买献花消费学币数量不能为空!") + @Column(name = "watch_video_total_second") + private Integer watchVideoTotalSecond; + + /** + * 做题数量。 + */ + @NotNull(message = "数据验证失败,做题数量不能为空!", groups = {UpdateGroup.class}) + @Column(name = "do_exercise_count") + private Integer doExerciseCount; + + /** + * 做题正确的数量。 + */ + @NotNull(message = "数据验证失败,做题正确的数量不能为空!", groups = {UpdateGroup.class}) + @Column(name = "do_exercise_correct_count") + private Integer doExerciseCorrectCount; + + /** + * statsDate 范围过滤起始值(>=)。 + */ + @Transient + private String statsDateStart; + + /** + * statsDate 范围过滤结束值(<=)。 + */ + @Transient + private String statsDateEnd; + + @RelationDict( + masterIdField = "gradeId", + slaveServiceName = "gradeService", + slaveModelClass = Grade.class, + slaveIdField = "gradeId", + slaveNameField = "gradeName") + @Transient + private Map gradeIdDictMap; + + @RelationDict( + masterIdField = "provinceId", + slaveServiceName = "areaCodeService", + slaveModelClass = AreaCode.class, + slaveIdField = "areaId", + slaveNameField = "areaName") + @Transient + private Map provinceIdDictMap; + + @RelationDict( + masterIdField = "cityId", + slaveServiceName = "areaCodeService", + slaveModelClass = AreaCode.class, + slaveIdField = "areaId", + slaveNameField = "areaName") + @Transient + private Map cityIdDictMap; +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/StudentActionTrans.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/StudentActionTrans.java new file mode 100644 index 00000000..b2e36071 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/StudentActionTrans.java @@ -0,0 +1,168 @@ +package com.orange.demo.app.model; + +import com.orange.demo.application.common.constant.StudentActionType; +import com.orange.demo.application.common.constant.DeviceType; +import com.orange.demo.common.core.annotation.RelationDict; +import com.orange.demo.common.core.annotation.RelationConstDict; +import com.orange.demo.common.core.validator.UpdateGroup; +import com.orange.demo.common.core.validator.ConstDictRef; +import lombok.Data; +import javax.persistence.*; +import javax.validation.constraints.*; + +import java.util.Date; +import java.util.Map; + +/** + * StudentActionTrans实体对象。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Data +@Table(name = "zz_student_action_trans") +public class StudentActionTrans { + + /** + * 主键Id。 + */ + @NotNull(message = "数据验证失败,主键Id不能为空!", groups = {UpdateGroup.class}) + @Id + @Column(name = "trans_id") + private Long transId; + + /** + * 学生Id。 + */ + @NotNull(message = "数据验证失败,学生Id不能为空!") + @Column(name = "student_id") + private Long studentId; + + /** + * 学生名称。 + */ + @NotBlank(message = "数据验证失败,学生名称不能为空!") + @Column(name = "student_name") + private String studentName; + + /** + * 学生校区。 + */ + @NotNull(message = "数据验证失败,学生校区不能为空!") + @Column(name = "school_id") + private Long schoolId; + + /** + * 年级Id。 + */ + @NotNull(message = "数据验证失败,学生年级不能为空!") + @Column(name = "grade_id") + private Integer gradeId; + + /** + * 行为类型(0: 充值 1: 购课 2: 上课签到 3: 上课签退 4: 看视频课 5: 做作业 6: 刷题 7: 献花)。 + */ + @NotNull(message = "数据验证失败,行为类型不能为空!") + @ConstDictRef(constDictClass = StudentActionType.class, message = "数据验证失败,行为类型为无效值!") + @Column(name = "action_type") + private Integer actionType; + + /** + * 设备类型(0: iOS 1: Android 2: PC)。 + */ + @NotNull(message = "数据验证失败,设备类型不能为空!") + @ConstDictRef(constDictClass = DeviceType.class, message = "数据验证失败,设备类型为无效值!") + @Column(name = "device_type") + private Integer deviceType; + + /** + * 看视频秒数。 + */ + @Column(name = "watch_video_seconds") + private Integer watchVideoSeconds; + + /** + * 购买献花数量。 + */ + @Column(name = "flower_count") + private Integer flowerCount; + + /** + * 购买作业数量。 + */ + @Column(name = "paper_count") + private Integer paperCount; + + /** + * 购买视频数量。 + */ + @Column(name = "video_count") + private Integer videoCount; + + /** + * 购买课程数量。 + */ + @Column(name = "course_count") + private Integer courseCount; + + /** + * 充值学币数量。 + */ + @Column(name = "coin_count") + private Integer coinCount; + + /** + * 做题是否正确标记。 + */ + @Column(name = "exercise_correct_flag") + private Integer exerciseCorrectFlag; + + /** + * 发生时间。 + */ + @NotNull(message = "数据验证失败,发生时间不能为空!") + @Column(name = "create_time") + private Date createTime; + + /** + * createTime 范围过滤起始值(>=)。 + */ + @Transient + private String createTimeStart; + + /** + * createTime 范围过滤结束值(<=)。 + */ + @Transient + private String createTimeEnd; + + @RelationDict( + masterIdField = "schoolId", + slaveServiceName = "schoolInfoService", + slaveModelClass = SchoolInfo.class, + slaveIdField = "schoolId", + slaveNameField = "schoolName") + @Transient + private Map schoolIdDictMap; + + @RelationDict( + masterIdField = "gradeId", + slaveServiceName = "gradeService", + slaveModelClass = Grade.class, + slaveIdField = "gradeId", + slaveNameField = "gradeName") + @Transient + private Map gradeIdDictMap; + + @RelationConstDict( + masterIdField = "actionType", + constantDictClass = StudentActionType.class) + @Transient + private Map actionTypeDictMap; + + @RelationConstDict( + masterIdField = "deviceType", + constantDictClass = DeviceType.class) + @Transient + private Map deviceTypeDictMap; +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/StudentClass.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/StudentClass.java new file mode 100644 index 00000000..7bcec6fc --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/StudentClass.java @@ -0,0 +1,113 @@ +package com.orange.demo.app.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.orange.demo.app.model.constant.ClassLevel; +import com.orange.demo.common.core.annotation.RelationDict; +import com.orange.demo.common.core.annotation.RelationConstDict; +import com.orange.demo.common.core.annotation.DeletedFlagColumn; +import com.orange.demo.common.core.validator.UpdateGroup; +import com.orange.demo.common.core.validator.ConstDictRef; +import lombok.Data; +import javax.persistence.*; +import javax.validation.constraints.*; + +import java.util.Date; +import java.util.Map; + +/** + * StudentClass实体对象。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Data +@Table(name = "zz_class") +public class StudentClass { + + /** + * 班级Id。 + */ + @NotNull(message = "数据验证失败,班级Id不能为空!", groups = {UpdateGroup.class}) + @Id + @Column(name = "class_id") + private Long classId; + + /** + * 班级名称。 + */ + @NotBlank(message = "数据验证失败,班级名称不能为空!") + @Column(name = "class_name") + private String className; + + /** + * 学校Id。 + */ + @NotNull(message = "数据验证失败,所属校区不能为空!") + @Column(name = "school_id") + private Long schoolId; + + /** + * 学生班长Id。 + */ + @NotNull(message = "数据验证失败,学生班长不能为空!") + @Column(name = "leader_id") + private Long leaderId; + + /** + * 已完成课时数量。 + */ + @NotNull(message = "数据验证失败,已完成课时不能为空!", groups = {UpdateGroup.class}) + @Column(name = "finish_class_hour") + private Integer finishClassHour; + + /** + * 班级级别(0: 初级班 1: 培优班 2: 冲刺提分班 3: 竞赛班)。 + */ + @NotNull(message = "数据验证失败,班级级别不能为空!") + @ConstDictRef(constDictClass = ClassLevel.class, message = "数据验证失败,班级级别为无效值!") + @Column(name = "class_level") + private Integer classLevel; + + /** + * 创建用户。 + */ + @Column(name = "create_user_id") + private Long createUserId; + + /** + * 班级创建时间。 + */ + @Column(name = "create_time") + private Date createTime; + + /** + * 逻辑删除标记字段(1: 正常 -1: 已删除)。 + */ + @JSONField(serialize = false) + @DeletedFlagColumn + private Integer status; + + @RelationDict( + masterIdField = "schoolId", + slaveServiceName = "schoolInfoService", + slaveModelClass = SchoolInfo.class, + slaveIdField = "schoolId", + slaveNameField = "schoolName") + @Transient + private Map schoolIdDictMap; + + @RelationDict( + masterIdField = "leaderId", + slaveServiceName = "studentService", + slaveModelClass = Student.class, + slaveIdField = "studentId", + slaveNameField = "studentName") + @Transient + private Map leaderIdDictMap; + + @RelationConstDict( + masterIdField = "classLevel", + constantDictClass = ClassLevel.class) + @Transient + private Map classLevelDictMap; +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/constant/ClassLevel.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/constant/ClassLevel.java new file mode 100644 index 00000000..aa2f694b --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/constant/ClassLevel.java @@ -0,0 +1,49 @@ +package com.orange.demo.app.model.constant; + +import java.util.HashMap; +import java.util.Map; + +/** + * 班级级别常量字典对象。 + * + * @author Jerry + * @date 2020-09-25 + */ +public final class ClassLevel { + + /** + * 初级班。 + */ + public static final int NORMAL = 0; + /** + * 中级班。 + */ + public static final int MIDDLE = 1; + /** + * 高级班。 + */ + public static final int HIGH = 2; + + private static final Map DICT_MAP = new HashMap<>(3); + static { + DICT_MAP.put(NORMAL, "初级班"); + DICT_MAP.put(MIDDLE, "中级班"); + DICT_MAP.put(HIGH, "高级班"); + } + + /** + * 判断参数是否为当前常量字典的合法值。 + * + * @param value 待验证的参数值。 + * @return 合法返回true,否则false。 + */ + public static boolean isValid(Integer value) { + return value != null && DICT_MAP.containsKey(value); + } + + /** + * 私有构造函数,明确标识该常量类的作用。 + */ + private ClassLevel() { + } +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/constant/ClassStatus.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/constant/ClassStatus.java new file mode 100644 index 00000000..754c4d8c --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/constant/ClassStatus.java @@ -0,0 +1,44 @@ +package com.orange.demo.app.model.constant; + +import java.util.HashMap; +import java.util.Map; + +/** + * 班级状态常量字典对象。 + * + * @author Jerry + * @date 2020-09-25 + */ +public final class ClassStatus { + + /** + * 正常。 + */ + public static final int NORAML = 1; + /** + * 解散。 + */ + public static final int DELETED = -1; + + private static final Map DICT_MAP = new HashMap<>(2); + static { + DICT_MAP.put(NORAML, "正常"); + DICT_MAP.put(DELETED, "解散"); + } + + /** + * 判断参数是否为当前常量字典的合法值。 + * + * @param value 待验证的参数值。 + * @return 合法返回true,否则false。 + */ + public static boolean isValid(Integer value) { + return value != null && DICT_MAP.containsKey(value); + } + + /** + * 私有构造函数,明确标识该常量类的作用。 + */ + private ClassStatus() { + } +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/constant/CourseDifficult.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/constant/CourseDifficult.java new file mode 100644 index 00000000..8ffbeacf --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/model/constant/CourseDifficult.java @@ -0,0 +1,49 @@ +package com.orange.demo.app.model.constant; + +import java.util.HashMap; +import java.util.Map; + +/** + * 课程难度常量字典对象。 + * + * @author Jerry + * @date 2020-09-25 + */ +public final class CourseDifficult { + + /** + * 容易。 + */ + public static final int NORMAL = 0; + /** + * 普通。 + */ + public static final int MIDDLE = 1; + /** + * 困难。 + */ + public static final int HIGH = 2; + + private static final Map DICT_MAP = new HashMap<>(3); + static { + DICT_MAP.put(NORMAL, "容易"); + DICT_MAP.put(MIDDLE, "普通"); + DICT_MAP.put(HIGH, "困难"); + } + + /** + * 判断参数是否为当前常量字典的合法值。 + * + * @param value 待验证的参数值。 + * @return 合法返回true,否则false。 + */ + public static boolean isValid(Integer value) { + return value != null && DICT_MAP.containsKey(value); + } + + /** + * 私有构造函数,明确标识该常量类的作用。 + */ + private CourseDifficult() { + } +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/service/AreaCodeService.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/service/AreaCodeService.java new file mode 100644 index 00000000..45975e85 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/service/AreaCodeService.java @@ -0,0 +1,57 @@ +package com.orange.demo.app.service; + +import com.orange.demo.app.dao.AreaCodeMapper; +import com.orange.demo.app.model.AreaCode; +import com.orange.demo.common.core.cache.MapTreeDictionaryCache; +import com.orange.demo.common.core.base.service.BaseDictService; +import com.orange.demo.common.core.base.dao.BaseDaoMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import tk.mybatis.mapper.entity.Example; + +import java.util.Collection; +import java.util.List; + +/** + * 行政区划的Service类。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Service +public class AreaCodeService extends BaseDictService { + + @Autowired + private AreaCodeMapper areaCodeMapper; + + public AreaCodeService() { + super(); + this.dictionaryCache = MapTreeDictionaryCache.create(AreaCode::getAreaId, AreaCode::getParentId); + } + + @Override + protected BaseDaoMapper mapper() { + return areaCodeMapper; + } + + /** + * 加载数据库数据到内存缓存。 + */ + @Override + public void loadCachedData() { + Example e = new Example(AreaCode.class); + e.orderBy("areaLevel"); + List areaCodeList = areaCodeMapper.selectByExample(e); + dictionaryCache.putAll(areaCodeList); + } + + /** + * 根据上级行政区划Id,获取其下级行政区划列表。 + * + * @param parentId 上级行政区划Id。 + * @return 下级行政区划列表。 + */ + public Collection getListByParentId(Long parentId) { + return ((MapTreeDictionaryCache) dictionaryCache).getListByParentId(parentId); + } +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/service/CourseService.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/service/CourseService.java new file mode 100644 index 00000000..e438c5ed --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/service/CourseService.java @@ -0,0 +1,175 @@ +package com.orange.demo.app.service; + +import com.orange.demo.app.dao.*; +import com.orange.demo.app.model.*; +import com.orange.demo.common.core.base.dao.BaseDaoMapper; +import com.orange.demo.common.core.object.TokenData; +import com.orange.demo.common.core.object.MyWhereCriteria; +import com.orange.demo.common.core.object.MyRelationParam; +import com.orange.demo.common.core.object.CallResult; +import com.orange.demo.common.core.base.service.BaseService; +import com.orange.demo.common.sequence.wrapper.IdGeneratorWrapper; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.*; + +/** + * 课程数据数据操作服务类。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Service +public class CourseService extends BaseService { + + @Autowired + private CourseMapper courseMapper; + @Autowired + private ClassCourseMapper classCourseMapper; + @Autowired + private GradeService gradeService; + @Autowired + private IdGeneratorWrapper idGenerator; + + /** + * 返回当前Service的主表Mapper对象。 + * + * @return 主表Mapper对象。 + */ + @Override + protected BaseDaoMapper mapper() { + return courseMapper; + } + + /** + * 保存新增对象。 + * + * @param course 新增对象。 + * @return 返回新增对象。 + */ + @Transactional(rollbackFor = Exception.class) + public Course saveNew(Course course) { + course.setCourseId(idGenerator.nextLongId()); + TokenData tokenData = TokenData.takeFromRequest(); + course.setCreateUserId(tokenData.getUserId()); + Date now = new Date(); + course.setCreateTime(now); + course.setUpdateTime(now); + courseMapper.insert(course); + return course; + } + + /** + * 更新数据对象。 + * + * @param course 更新的对象。 + * @param originalCourse 原有数据对象。 + * @return 成功返回true,否则false。 + */ + @Transactional(rollbackFor = Exception.class) + public boolean update(Course course, Course originalCourse) { + course.setCreateUserId(originalCourse.getCreateUserId()); + course.setCreateTime(originalCourse.getCreateTime()); + course.setUpdateTime(new Date()); + // 这里重点提示,在执行主表数据更新之前,如果有哪些字段不支持修改操作,请用原有数据对象字段替换当前数据字段。 + return courseMapper.updateByPrimaryKey(course) == 1; + } + + /** + * 删除指定数据。 + * + * @param courseId 主键Id。 + * @return 成功返回true,否则false。 + */ + @Transactional(rollbackFor = Exception.class) + public boolean remove(Long courseId) { + // 这里先删除主数据 + if (courseMapper.deleteByPrimaryKey(courseId) == 0) { + return false; + } + // 这里可继续删除关联数据。 + // 开始删除多对多父表的关联 + ClassCourse classCourse = new ClassCourse(); + classCourse.setCourseId(courseId); + classCourseMapper.delete(classCourse); + return true; + } + + /** + * 获取单表查询结果。由于没有关联数据查询,因此在仅仅获取单表数据的场景下,效率更高。 + * 如果需要同时获取关联数据,请移步(getCourseListWithRelation)方法。 + * + * @param filter 过滤对象。 + * @param orderBy 排序参数。 + * @return 查询结果集。 + */ + public List getCourseList(Course filter, String orderBy) { + return courseMapper.getCourseList(filter, orderBy); + } + + /** + * 获取主表的查询结果,以及主表关联的字典数据和一对一从表数据,以及一对一从表的字典数据。 + * 如果仅仅需要获取主表数据,请移步(getCourseList),以便获取更好的查询性能。 + * + * @param filter 主表过滤对象。 + * @param orderBy 排序参数。 + * @return 查询结果集。 + */ + public List getCourseListWithRelation(Course filter, String orderBy) { + List resultList = courseMapper.getCourseList(filter, orderBy); + Map> criteriaMap = buildAggregationAdditionalWhereCriteria(); + this.buildRelationForDataList(resultList, MyRelationParam.normal(), criteriaMap); + return resultList; + } + + /** + * 在多对多关系中,当前Service的数据表为从表,返回不与指定主表主键Id存在对多对关系的列表。 + * + * @param classId 主表主键Id。 + * @param filter 从表的过滤对象。 + * @param orderBy 排序参数。 + * @return 查询结果集。 + */ + public List getNotInCourseListByClassId( + Long classId, Course filter, String orderBy) { + List resultList = + courseMapper.getNotInCourseListByClassId(classId, filter, orderBy); + this.buildRelationForDataList(resultList, MyRelationParam.dictOnly(), null); + return resultList; + } + + /** + * 在多对多关系中,当前Service的数据表为从表,返回与指定主表主键Id存在对多对关系的列表。 + * + * @param classId 主表主键Id。 + * @param filter 从表的过滤对象。 + * @param orderBy 排序参数。 + * @return 查询结果集。 + */ + public List getCourseListByClassId( + Long classId, Course filter, String orderBy) { + List resultList = + courseMapper.getCourseListByClassId(classId, filter, orderBy); + this.buildRelationForDataList(resultList, MyRelationParam.dictOnly(), null); + return resultList; + } + + /** + * 根据最新对象和原有对象的数据对比,判断关联的字典数据和多对一主表数据是否都是合法数据。 + * + * @param course 最新数据对象。 + * @param originalCourse 原有数据对象。 + * @return 数据全部正确返回true,否则false。 + */ + public CallResult verifyRelatedData(Course course, Course originalCourse) { + String errorMessageFormat = "数据验证失败,关联的%s并不存在,请刷新后重试!"; + //这里是基于字典的验证。 + if (this.needToVerify(course, originalCourse, Course::getGradeId) + && !gradeService.existId(course.getGradeId())) { + return CallResult.error(String.format(errorMessageFormat, "所属年级")); + } + return CallResult.ok(); + } +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/service/CourseTransStatsService.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/service/CourseTransStatsService.java new file mode 100644 index 00000000..aa24fb43 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/service/CourseTransStatsService.java @@ -0,0 +1,83 @@ +package com.orange.demo.app.service; + +import com.orange.demo.app.dao.*; +import com.orange.demo.app.model.*; +import com.orange.demo.common.core.base.dao.BaseDaoMapper; +import com.orange.demo.common.core.object.MyWhereCriteria; +import com.orange.demo.common.core.object.MyRelationParam; +import com.orange.demo.common.core.base.service.BaseService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.*; + +/** + * 课程统计数据操作服务类。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Service +public class CourseTransStatsService extends BaseService { + + @Autowired + private CourseTransStatsMapper courseTransStatsMapper; + @Autowired + private GradeService gradeService; + + /** + * 返回当前Service的主表Mapper对象。 + * + * @return 主表Mapper对象。 + */ + @Override + protected BaseDaoMapper mapper() { + return courseTransStatsMapper; + } + + /** + * 获取单表查询结果。由于没有关联数据查询,因此在仅仅获取单表数据的场景下,效率更高。 + * 如果需要同时获取关联数据,请移步(getCourseTransStatsListWithRelation)方法。 + * + * @param filter 过滤对象。 + * @param orderBy 排序参数。 + * @return 查询结果集。 + */ + public List getCourseTransStatsList(CourseTransStats filter, String orderBy) { + return courseTransStatsMapper.getCourseTransStatsList(filter, orderBy); + } + + /** + * 获取主表的查询结果,以及主表关联的字典数据和一对一从表数据,以及一对一从表的字典数据。 + * 如果仅仅需要获取主表数据,请移步(getCourseTransStatsList),以便获取更好的查询性能。 + * + * @param filter 主表过滤对象。 + * @param orderBy 排序参数。 + * @return 查询结果集。 + */ + public List getCourseTransStatsListWithRelation(CourseTransStats filter, String orderBy) { + List resultList = courseTransStatsMapper.getCourseTransStatsList(filter, orderBy); + Map> criteriaMap = buildAggregationAdditionalWhereCriteria(); + this.buildRelationForDataList(resultList, MyRelationParam.normal(), criteriaMap); + return resultList; + } + + /** + * 获取分组过滤后的数据查询结果,以及关联的字典数据和一对一从表数据,以及一对一从表的字典数据。 + * + * @param filter 过滤对象。 + * @param groupSelect 分组显示列表参数。位于SQL语句SELECT的后面。 + * @param groupBy 分组参数。位于SQL语句的GROUP BY后面。 + * @param orderBy 排序字符串,ORDER BY从句的参数。 + * @return 分组过滤结果集。 + */ + public List getGroupedCourseTransStatsListWithRelation( + CourseTransStats filter, String groupSelect, String groupBy, String orderBy) { + List resultList = + courseTransStatsMapper.getGroupedCourseTransStatsList(filter, groupSelect, groupBy, orderBy); + // NOTE: 这里只是包含了关联数据,聚合计算数据没有包含。 + // 主要原因是,由于聚合字段通常被视为普通字段使用,不会在group by的从句中出现,语义上也不会在此关联。 + this.buildRelationForDataList(resultList, MyRelationParam.normal(), null); + return resultList; + } +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/service/GradeService.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/service/GradeService.java new file mode 100644 index 00000000..f5de3fd5 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/service/GradeService.java @@ -0,0 +1,88 @@ +package com.orange.demo.app.service; + +import com.orange.demo.common.core.base.service.BaseDictService; +import com.orange.demo.common.core.base.dao.BaseDaoMapper; +import com.orange.demo.common.core.cache.MapDictionaryCache; +import com.orange.demo.common.core.constant.GlobalDeletedFlag; +import com.orange.demo.app.dao.GradeMapper; +import com.orange.demo.app.model.Grade; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + * 年级数据操作服务类。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Service +public class GradeService extends BaseDictService { + + @Autowired + private GradeMapper gradeMapper; + + public GradeService() { + super(); + this.dictionaryCache = MapDictionaryCache.create(Grade::getGradeId); + } + + /** + * 返回当前Service的主表Mapper对象。 + * + * @return 主表Mapper对象。 + */ + @Override + protected BaseDaoMapper mapper() { + return gradeMapper; + } + + /** + * 保存新增对象。 + * + * @param grade 新增对象。 + * @return 返回新增对象。 + */ + @Transactional(rollbackFor = Exception.class) + public Grade saveNew(Grade grade) { + grade.setStatus(GlobalDeletedFlag.NORMAL); + gradeMapper.insert(grade); + dictionaryCache.put(grade.getGradeId(), grade); + return grade; + } + + /** + * 更新数据对象。 + * + * @param grade 更新的对象。 + * @param originalGrade 原有数据对象。 + * @return 成功返回true,否则false。 + */ + @Transactional(rollbackFor = Exception.class) + public boolean update(Grade grade, Grade originalGrade) { + grade.setStatus(GlobalDeletedFlag.NORMAL); + if (gradeMapper.updateByPrimaryKey(grade) != 1) { + return false; + } + dictionaryCache.put(grade.getGradeId(), grade); + return true; + } + + /** + * 删除指定数据。 + * + * @param gradeId 主键Id。 + * @return 成功返回true,否则false。 + */ + @Transactional(rollbackFor = Exception.class) + public boolean remove(Integer gradeId) { + Grade deletedObject = new Grade(); + deletedObject.setGradeId(gradeId); + deletedObject.setStatus(GlobalDeletedFlag.DELETED); + if (gradeMapper.updateByPrimaryKeySelective(deletedObject) != 1) { + return false; + } + dictionaryCache.invalidate(gradeId); + return true; + } +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/service/SchoolInfoService.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/service/SchoolInfoService.java new file mode 100644 index 00000000..d588b113 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/service/SchoolInfoService.java @@ -0,0 +1,129 @@ +package com.orange.demo.app.service; + +import com.orange.demo.app.dao.*; +import com.orange.demo.app.model.*; +import com.orange.demo.common.core.base.dao.BaseDaoMapper; +import com.orange.demo.common.core.object.MyWhereCriteria; +import com.orange.demo.common.core.object.MyRelationParam; +import com.orange.demo.common.core.object.CallResult; +import com.orange.demo.common.core.base.service.BaseService; +import com.orange.demo.common.sequence.wrapper.IdGeneratorWrapper; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.*; + +/** + * 校区数据数据操作服务类。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Service +public class SchoolInfoService extends BaseService { + + @Autowired + private SchoolInfoMapper schoolInfoMapper; + @Autowired + private AreaCodeService areaCodeService; + @Autowired + private IdGeneratorWrapper idGenerator; + + /** + * 返回当前Service的主表Mapper对象。 + * + * @return 主表Mapper对象。 + */ + @Override + protected BaseDaoMapper mapper() { + return schoolInfoMapper; + } + + /** + * 保存新增对象。 + * + * @param schoolInfo 新增对象。 + * @return 返回新增对象。 + */ + @Transactional(rollbackFor = Exception.class) + public SchoolInfo saveNew(SchoolInfo schoolInfo) { + schoolInfo.setSchoolId(idGenerator.nextLongId()); + schoolInfoMapper.insert(schoolInfo); + return schoolInfo; + } + + /** + * 更新数据对象。 + * + * @param schoolInfo 更新的对象。 + * @param originalSchoolInfo 原有数据对象。 + * @return 成功返回true,否则false。 + */ + @Transactional(rollbackFor = Exception.class) + public boolean update(SchoolInfo schoolInfo, SchoolInfo originalSchoolInfo) { + // 这里重点提示,在执行主表数据更新之前,如果有哪些字段不支持修改操作,请用原有数据对象字段替换当前数据字段。 + return schoolInfoMapper.updateByPrimaryKey(schoolInfo) == 1; + } + + /** + * 删除指定数据。 + * + * @param schoolId 主键Id。 + * @return 成功返回true,否则false。 + */ + @Transactional(rollbackFor = Exception.class) + public boolean remove(Long schoolId) { + return schoolInfoMapper.deleteByPrimaryKey(schoolId) != 0; + // 这里可继续删除关联数据。 + } + + /** + * 获取单表查询结果。由于没有关联数据查询,因此在仅仅获取单表数据的场景下,效率更高。 + * 如果需要同时获取关联数据,请移步(getSchoolInfoListWithRelation)方法。 + * + * @param filter 过滤对象。 + * @param orderBy 排序参数。 + * @return 查询结果集。 + */ + public List getSchoolInfoList(SchoolInfo filter, String orderBy) { + return schoolInfoMapper.getSchoolInfoList(filter, orderBy); + } + + /** + * 获取主表的查询结果,以及主表关联的字典数据和一对一从表数据,以及一对一从表的字典数据。 + * 如果仅仅需要获取主表数据,请移步(getSchoolInfoList),以便获取更好的查询性能。 + * + * @param filter 主表过滤对象。 + * @param orderBy 排序参数。 + * @return 查询结果集。 + */ + public List getSchoolInfoListWithRelation(SchoolInfo filter, String orderBy) { + List resultList = schoolInfoMapper.getSchoolInfoList(filter, orderBy); + Map> criteriaMap = buildAggregationAdditionalWhereCriteria(); + this.buildRelationForDataList(resultList, MyRelationParam.normal(), criteriaMap); + return resultList; + } + + /** + * 根据最新对象和原有对象的数据对比,判断关联的字典数据和多对一主表数据是否都是合法数据。 + * + * @param schoolInfo 最新数据对象。 + * @param originalSchoolInfo 原有数据对象。 + * @return 数据全部正确返回true,否则false。 + */ + public CallResult verifyRelatedData(SchoolInfo schoolInfo, SchoolInfo originalSchoolInfo) { + String errorMessageFormat = "数据验证失败,关联的%s并不存在,请刷新后重试!"; + //这里是基于字典的验证。 + if (this.needToVerify(schoolInfo, originalSchoolInfo, SchoolInfo::getProvinceId) + && !areaCodeService.existId(schoolInfo.getProvinceId())) { + return CallResult.error(String.format(errorMessageFormat, "所在省份")); + } + //这里是基于字典的验证。 + if (this.needToVerify(schoolInfo, originalSchoolInfo, SchoolInfo::getCityId) + && !areaCodeService.existId(schoolInfo.getCityId())) { + return CallResult.error(String.format(errorMessageFormat, "所在城市")); + } + return CallResult.ok(); + } +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/service/StudentActionStatsService.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/service/StudentActionStatsService.java new file mode 100644 index 00000000..36daf831 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/service/StudentActionStatsService.java @@ -0,0 +1,85 @@ +package com.orange.demo.app.service; + +import com.orange.demo.app.dao.*; +import com.orange.demo.app.model.*; +import com.orange.demo.common.core.base.dao.BaseDaoMapper; +import com.orange.demo.common.core.object.MyWhereCriteria; +import com.orange.demo.common.core.object.MyRelationParam; +import com.orange.demo.common.core.base.service.BaseService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.*; + +/** + * 学生行为统计数据操作服务类。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Service +public class StudentActionStatsService extends BaseService { + + @Autowired + private StudentActionStatsMapper studentActionStatsMapper; + @Autowired + private GradeService gradeService; + @Autowired + private AreaCodeService areaCodeService; + + /** + * 返回当前Service的主表Mapper对象。 + * + * @return 主表Mapper对象。 + */ + @Override + protected BaseDaoMapper mapper() { + return studentActionStatsMapper; + } + + /** + * 获取单表查询结果。由于没有关联数据查询,因此在仅仅获取单表数据的场景下,效率更高。 + * 如果需要同时获取关联数据,请移步(getStudentActionStatsListWithRelation)方法。 + * + * @param filter 过滤对象。 + * @param orderBy 排序参数。 + * @return 查询结果集。 + */ + public List getStudentActionStatsList(StudentActionStats filter, String orderBy) { + return studentActionStatsMapper.getStudentActionStatsList(filter, orderBy); + } + + /** + * 获取主表的查询结果,以及主表关联的字典数据和一对一从表数据,以及一对一从表的字典数据。 + * 如果仅仅需要获取主表数据,请移步(getStudentActionStatsList),以便获取更好的查询性能。 + * + * @param filter 主表过滤对象。 + * @param orderBy 排序参数。 + * @return 查询结果集。 + */ + public List getStudentActionStatsListWithRelation(StudentActionStats filter, String orderBy) { + List resultList = studentActionStatsMapper.getStudentActionStatsList(filter, orderBy); + Map> criteriaMap = buildAggregationAdditionalWhereCriteria(); + this.buildRelationForDataList(resultList, MyRelationParam.normal(), criteriaMap); + return resultList; + } + + /** + * 获取分组过滤后的数据查询结果,以及关联的字典数据和一对一从表数据,以及一对一从表的字典数据。 + * + * @param filter 过滤对象。 + * @param groupSelect 分组显示列表参数。位于SQL语句SELECT的后面。 + * @param groupBy 分组参数。位于SQL语句的GROUP BY后面。 + * @param orderBy 排序字符串,ORDER BY从句的参数。 + * @return 分组过滤结果集。 + */ + public List getGroupedStudentActionStatsListWithRelation( + StudentActionStats filter, String groupSelect, String groupBy, String orderBy) { + List resultList = + studentActionStatsMapper.getGroupedStudentActionStatsList(filter, groupSelect, groupBy, orderBy); + // NOTE: 这里只是包含了关联数据,聚合计算数据没有包含。 + // 主要原因是,由于聚合字段通常被视为普通字段使用,不会在group by的从句中出现,语义上也不会在此关联。 + this.buildRelationForDataList(resultList, MyRelationParam.normal(), null); + return resultList; + } +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/service/StudentActionTransService.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/service/StudentActionTransService.java new file mode 100644 index 00000000..4e1ea4eb --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/service/StudentActionTransService.java @@ -0,0 +1,131 @@ +package com.orange.demo.app.service; + +import com.orange.demo.app.dao.*; +import com.orange.demo.app.model.*; +import com.orange.demo.common.core.base.dao.BaseDaoMapper; +import com.orange.demo.common.core.object.MyWhereCriteria; +import com.orange.demo.common.core.object.MyRelationParam; +import com.orange.demo.common.core.object.CallResult; +import com.orange.demo.common.core.base.service.BaseService; +import com.orange.demo.common.sequence.wrapper.IdGeneratorWrapper; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.*; + +/** + * 学生行为流水数据操作服务类。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Service +public class StudentActionTransService extends BaseService { + + @Autowired + private StudentActionTransMapper studentActionTransMapper; + @Autowired + private SchoolInfoService schoolInfoService; + @Autowired + private GradeService gradeService; + @Autowired + private IdGeneratorWrapper idGenerator; + + /** + * 返回当前Service的主表Mapper对象。 + * + * @return 主表Mapper对象。 + */ + @Override + protected BaseDaoMapper mapper() { + return studentActionTransMapper; + } + + /** + * 保存新增对象。 + * + * @param studentActionTrans 新增对象。 + * @return 返回新增对象。 + */ + @Transactional(rollbackFor = Exception.class) + public StudentActionTrans saveNew(StudentActionTrans studentActionTrans) { + studentActionTrans.setTransId(idGenerator.nextLongId()); + studentActionTransMapper.insert(studentActionTrans); + return studentActionTrans; + } + + /** + * 更新数据对象。 + * + * @param studentActionTrans 更新的对象。 + * @param originalStudentActionTrans 原有数据对象。 + * @return 成功返回true,否则false。 + */ + @Transactional(rollbackFor = Exception.class) + public boolean update(StudentActionTrans studentActionTrans, StudentActionTrans originalStudentActionTrans) { + // 这里重点提示,在执行主表数据更新之前,如果有哪些字段不支持修改操作,请用原有数据对象字段替换当前数据字段。 + return studentActionTransMapper.updateByPrimaryKey(studentActionTrans) == 1; + } + + /** + * 删除指定数据。 + * + * @param transId 主键Id。 + * @return 成功返回true,否则false。 + */ + @Transactional(rollbackFor = Exception.class) + public boolean remove(Long transId) { + return studentActionTransMapper.deleteByPrimaryKey(transId) != 0; + // 这里可继续删除关联数据。 + } + + /** + * 获取单表查询结果。由于没有关联数据查询,因此在仅仅获取单表数据的场景下,效率更高。 + * 如果需要同时获取关联数据,请移步(getStudentActionTransListWithRelation)方法。 + * + * @param filter 过滤对象。 + * @param orderBy 排序参数。 + * @return 查询结果集。 + */ + public List getStudentActionTransList(StudentActionTrans filter, String orderBy) { + return studentActionTransMapper.getStudentActionTransList(filter, orderBy); + } + + /** + * 获取主表的查询结果,以及主表关联的字典数据和一对一从表数据,以及一对一从表的字典数据。 + * 如果仅仅需要获取主表数据,请移步(getStudentActionTransList),以便获取更好的查询性能。 + * + * @param filter 主表过滤对象。 + * @param orderBy 排序参数。 + * @return 查询结果集。 + */ + public List getStudentActionTransListWithRelation(StudentActionTrans filter, String orderBy) { + List resultList = studentActionTransMapper.getStudentActionTransList(filter, orderBy); + Map> criteriaMap = buildAggregationAdditionalWhereCriteria(); + this.buildRelationForDataList(resultList, MyRelationParam.normal(), criteriaMap); + return resultList; + } + + /** + * 根据最新对象和原有对象的数据对比,判断关联的字典数据和多对一主表数据是否都是合法数据。 + * + * @param studentActionTrans 最新数据对象。 + * @param originalStudentActionTrans 原有数据对象。 + * @return 数据全部正确返回true,否则false。 + */ + public CallResult verifyRelatedData(StudentActionTrans studentActionTrans, StudentActionTrans originalStudentActionTrans) { + String errorMessageFormat = "数据验证失败,关联的%s并不存在,请刷新后重试!"; + //这里是基于字典的验证。 + if (this.needToVerify(studentActionTrans, originalStudentActionTrans, StudentActionTrans::getSchoolId) + && !schoolInfoService.existId(studentActionTrans.getSchoolId())) { + return CallResult.error(String.format(errorMessageFormat, "学生校区")); + } + //这里是基于字典的验证。 + if (this.needToVerify(studentActionTrans, originalStudentActionTrans, StudentActionTrans::getGradeId) + && !gradeService.existId(studentActionTrans.getGradeId())) { + return CallResult.error(String.format(errorMessageFormat, "学生年级")); + } + return CallResult.ok(); + } +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/service/StudentClassService.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/service/StudentClassService.java new file mode 100644 index 00000000..91ce2cd4 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/service/StudentClassService.java @@ -0,0 +1,259 @@ +package com.orange.demo.app.service; + +import com.orange.demo.app.dao.*; +import com.orange.demo.app.model.*; +import com.orange.demo.common.core.base.dao.BaseDaoMapper; +import com.orange.demo.common.core.constant.GlobalDeletedFlag; +import com.orange.demo.common.core.object.TokenData; +import com.orange.demo.common.core.object.MyWhereCriteria; +import com.orange.demo.common.core.object.MyRelationParam; +import com.orange.demo.common.core.object.CallResult; +import com.orange.demo.common.core.base.service.BaseService; +import com.orange.demo.common.sequence.wrapper.IdGeneratorWrapper; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import tk.mybatis.mapper.entity.Example; + +import java.util.*; + +/** + * 班级数据数据操作服务类。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Service +public class StudentClassService extends BaseService { + + @Autowired + private StudentClassMapper studentClassMapper; + @Autowired + private ClassCourseMapper classCourseMapper; + @Autowired + private ClassStudentMapper classStudentMapper; + @Autowired + private SchoolInfoService schoolInfoService; + @Autowired + private StudentService studentService; + @Autowired + private IdGeneratorWrapper idGenerator; + + /** + * 返回当前Service的主表Mapper对象。 + * + * @return 主表Mapper对象。 + */ + @Override + protected BaseDaoMapper mapper() { + return studentClassMapper; + } + + /** + * 保存新增对象。 + * + * @param studentClass 新增对象。 + * @return 返回新增对象。 + */ + @Transactional(rollbackFor = Exception.class) + public StudentClass saveNew(StudentClass studentClass) { + studentClass.setClassId(idGenerator.nextLongId()); + TokenData tokenData = TokenData.takeFromRequest(); + studentClass.setCreateUserId(tokenData.getUserId()); + studentClass.setCreateTime(new Date()); + studentClass.setStatus(GlobalDeletedFlag.NORMAL); + if (studentClass.getFinishClassHour() == null) { + studentClass.setFinishClassHour(0); + } + if (studentClass.getStatus() == null) { + studentClass.setStatus(0); + } + studentClassMapper.insert(studentClass); + return studentClass; + } + + /** + * 更新数据对象。 + * + * @param studentClass 更新的对象。 + * @param originalStudentClass 原有数据对象。 + * @return 成功返回true,否则false。 + */ + @Transactional(rollbackFor = Exception.class) + public boolean update(StudentClass studentClass, StudentClass originalStudentClass) { + studentClass.setCreateUserId(originalStudentClass.getCreateUserId()); + studentClass.setCreateTime(originalStudentClass.getCreateTime()); + studentClass.setStatus(GlobalDeletedFlag.NORMAL); + // 这里重点提示,在执行主表数据更新之前,如果有哪些字段不支持修改操作,请用原有数据对象字段替换当前数据字段。 + return studentClassMapper.updateByPrimaryKey(studentClass) == 1; + } + + /** + * 删除指定数据。 + * + * @param classId 主键Id。 + * @return 成功返回true,否则false。 + */ + @Transactional(rollbackFor = Exception.class) + public boolean remove(Long classId) { + Example studentClassExample = new Example(StudentClass.class); + Example.Criteria c = studentClassExample.createCriteria(); + c.andEqualTo(super.idFieldName, classId); + c.andEqualTo(super.deletedFlagFieldName, GlobalDeletedFlag.NORMAL); + // 这里先删除主数据 + StudentClass deletedObject = new StudentClass(); + deletedObject.setStatus(GlobalDeletedFlag.DELETED); + if (studentClassMapper.updateByExampleSelective(deletedObject, studentClassExample) == 0) { + return false; + } + // 这里可继续删除关联数据。 + // 开始删除多对多子表的关联 + ClassCourse classCourse = new ClassCourse(); + classCourse.setClassId(classId); + classCourseMapper.delete(classCourse); + ClassStudent classStudent = new ClassStudent(); + classStudent.setClassId(classId); + classStudentMapper.delete(classStudent); + return true; + } + + /** + * 获取单表查询结果。由于没有关联数据查询,因此在仅仅获取单表数据的场景下,效率更高。 + * 如果需要同时获取关联数据,请移步(getStudentClassListWithRelation)方法。 + * + * @param filter 过滤对象。 + * @param orderBy 排序参数。 + * @return 查询结果集。 + */ + public List getStudentClassList(StudentClass filter, String orderBy) { + return studentClassMapper.getStudentClassList(filter, orderBy); + } + + /** + * 获取主表的查询结果,以及主表关联的字典数据和一对一从表数据,以及一对一从表的字典数据。 + * 如果仅仅需要获取主表数据,请移步(getStudentClassList),以便获取更好的查询性能。 + * + * @param filter 主表过滤对象。 + * @param orderBy 排序参数。 + * @return 查询结果集。 + */ + public List getStudentClassListWithRelation(StudentClass filter, String orderBy) { + List resultList = studentClassMapper.getStudentClassList(filter, orderBy); + Map> criteriaMap = buildAggregationAdditionalWhereCriteria(); + this.buildRelationForDataList(resultList, MyRelationParam.normal(), criteriaMap); + return resultList; + } + + /** + * 批量添加多对多关联关系。 + * + * @param classCourseList 多对多关联表对象集合。 + * @param classId 主表Id。 + */ + @Transactional(rollbackFor = Exception.class) + public void addClassCourseList(List classCourseList, Long classId) { + for (ClassCourse classCourse : classCourseList) { + classCourse.setClassId(classId); + if (classCourse.getCourseOrder() == null) { + classCourse.setCourseOrder(0); + } + } + classCourseMapper.insertList(classCourseList); + } + + /** + * 更新中间表数据。 + * + * @param classCourse 中间表对象。 + * @return 更新成功与否。 + */ + @Transactional(rollbackFor = Exception.class) + public boolean updateClassCourse(ClassCourse classCourse) { + Example e = new Example(ClassCourse.class); + e.createCriteria() + .andEqualTo("classId", classCourse.getClassId()) + .andEqualTo("courseId", classCourse.getCourseId()); + return classCourseMapper.updateByExample(classCourse, e) > 0; + } + + /** + * 获取中间表数据。 + * + * @param classId 主表Id。 + * @param courseId 从表Id。 + * @return 中间表对象。 + */ + public ClassCourse getClassCourse(Long classId, Long courseId) { + Example e = new Example(ClassCourse.class); + e.createCriteria() + .andEqualTo("classId", classId) + .andEqualTo("courseId", courseId); + return classCourseMapper.selectOneByExample(e); + } + + /** + * 移除单条多对多关系。 + * + * @param classId 主表Id。 + * @param courseId 从表Id。 + * @return 成功返回true,否则false。 + */ + @Transactional(rollbackFor = Exception.class) + public boolean removeClassCourse(Long classId, Long courseId) { + ClassCourse classCourse = new ClassCourse(); + classCourse.setClassId(classId); + classCourse.setCourseId(courseId); + return classCourseMapper.delete(classCourse) > 0; + } + + /** + * 批量添加多对多关联关系。 + * + * @param classStudentList 多对多关联表对象集合。 + * @param classId 主表Id。 + */ + @Transactional(rollbackFor = Exception.class) + public void addClassStudentList(List classStudentList, Long classId) { + for (ClassStudent classStudent : classStudentList) { + classStudent.setClassId(classId); + } + classStudentMapper.insertList(classStudentList); + } + + /** + * 移除单条多对多关系。 + * + * @param classId 主表Id。 + * @param studentId 从表Id。 + * @return 成功返回true,否则false。 + */ + @Transactional(rollbackFor = Exception.class) + public boolean removeClassStudent(Long classId, Long studentId) { + ClassStudent classStudent = new ClassStudent(); + classStudent.setClassId(classId); + classStudent.setStudentId(studentId); + return classStudentMapper.delete(classStudent) > 0; + } + + /** + * 根据最新对象和原有对象的数据对比,判断关联的字典数据和多对一主表数据是否都是合法数据。 + * + * @param studentClass 最新数据对象。 + * @param originalStudentClass 原有数据对象。 + * @return 数据全部正确返回true,否则false。 + */ + public CallResult verifyRelatedData(StudentClass studentClass, StudentClass originalStudentClass) { + String errorMessageFormat = "数据验证失败,关联的%s并不存在,请刷新后重试!"; + //这里是基于字典的验证。 + if (this.needToVerify(studentClass, originalStudentClass, StudentClass::getSchoolId) + && !schoolInfoService.existId(studentClass.getSchoolId())) { + return CallResult.error(String.format(errorMessageFormat, "所属校区")); + } + //这里是基于字典的验证。 + if (this.needToVerify(studentClass, originalStudentClass, StudentClass::getLeaderId) + && !studentService.existId(studentClass.getLeaderId())) { + return CallResult.error(String.format(errorMessageFormat, "学生班长")); + } + return CallResult.ok(); + } +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/app/service/StudentService.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/service/StudentService.java new file mode 100644 index 00000000..435a0c9d --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/app/service/StudentService.java @@ -0,0 +1,202 @@ +package com.orange.demo.app.service; + +import com.orange.demo.application.common.constant.StudentStatus; +import com.orange.demo.app.dao.*; +import com.orange.demo.app.model.*; +import com.orange.demo.common.core.base.dao.BaseDaoMapper; +import com.orange.demo.common.core.object.MyWhereCriteria; +import com.orange.demo.common.core.object.MyRelationParam; +import com.orange.demo.common.core.object.CallResult; +import com.orange.demo.common.core.base.service.BaseService; +import com.orange.demo.common.sequence.wrapper.IdGeneratorWrapper; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.*; + +/** + * 学生数据数据操作服务类。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Service +public class StudentService extends BaseService { + + @Autowired + private StudentMapper studentMapper; + @Autowired + private ClassStudentMapper classStudentMapper; + @Autowired + private AreaCodeService areaCodeService; + @Autowired + private GradeService gradeService; + @Autowired + private SchoolInfoService schoolInfoService; + @Autowired + private IdGeneratorWrapper idGenerator; + + /** + * 返回当前Service的主表Mapper对象。 + * + * @return 主表Mapper对象。 + */ + @Override + protected BaseDaoMapper mapper() { + return studentMapper; + } + + /** + * 保存新增对象。 + * + * @param student 新增对象。 + * @return 返回新增对象。 + */ + @Transactional(rollbackFor = Exception.class) + public Student saveNew(Student student) { + student.setStudentId(idGenerator.nextLongId()); + student.setRegisterTime(new Date()); + if (student.getTotalCoin() == null) { + student.setTotalCoin(0); + } + if (student.getLeftCoin() == null) { + student.setLeftCoin(0); + } + if (student.getStatus() == null) { + student.setStatus(StudentStatus.NORMAL); + } + studentMapper.insert(student); + return student; + } + + /** + * 更新数据对象。 + * + * @param student 更新的对象。 + * @param originalStudent 原有数据对象。 + * @return 成功返回true,否则false。 + */ + @Transactional(rollbackFor = Exception.class) + public boolean update(Student student, Student originalStudent) { + student.setRegisterTime(originalStudent.getRegisterTime()); + // 这里重点提示,在执行主表数据更新之前,如果有哪些字段不支持修改操作,请用原有数据对象字段替换当前数据字段。 + return studentMapper.updateByPrimaryKey(student) == 1; + } + + /** + * 删除指定数据。 + * + * @param studentId 主键Id。 + * @return 成功返回true,否则false。 + */ + @Transactional(rollbackFor = Exception.class) + public boolean remove(Long studentId) { + // 这里先删除主数据 + if (studentMapper.deleteByPrimaryKey(studentId) == 0) { + return false; + } + // 这里可继续删除关联数据。 + // 开始删除多对多父表的关联 + ClassStudent classStudent = new ClassStudent(); + classStudent.setStudentId(studentId); + classStudentMapper.delete(classStudent); + return true; + } + + /** + * 获取单表查询结果。由于没有关联数据查询,因此在仅仅获取单表数据的场景下,效率更高。 + * 如果需要同时获取关联数据,请移步(getStudentListWithRelation)方法。 + * + * @param filter 过滤对象。 + * @param orderBy 排序参数。 + * @return 查询结果集。 + */ + public List getStudentList(Student filter, String orderBy) { + return studentMapper.getStudentList(filter, orderBy); + } + + /** + * 获取主表的查询结果,以及主表关联的字典数据和一对一从表数据,以及一对一从表的字典数据。 + * 如果仅仅需要获取主表数据,请移步(getStudentList),以便获取更好的查询性能。 + * + * @param filter 主表过滤对象。 + * @param orderBy 排序参数。 + * @return 查询结果集。 + */ + public List getStudentListWithRelation(Student filter, String orderBy) { + List resultList = studentMapper.getStudentList(filter, orderBy); + Map> criteriaMap = buildAggregationAdditionalWhereCriteria(); + this.buildRelationForDataList(resultList, MyRelationParam.normal(), criteriaMap); + return resultList; + } + + /** + * 在多对多关系中,当前Service的数据表为从表,返回不与指定主表主键Id存在对多对关系的列表。 + * + * @param classId 主表主键Id。 + * @param filter 从表的过滤对象。 + * @param orderBy 排序参数。 + * @return 查询结果集。 + */ + public List getNotInStudentListByClassId( + Long classId, Student filter, String orderBy) { + List resultList = + studentMapper.getNotInStudentListByClassId(classId, filter, orderBy); + this.buildRelationForDataList(resultList, MyRelationParam.dictOnly(), null); + return resultList; + } + + /** + * 在多对多关系中,当前Service的数据表为从表,返回与指定主表主键Id存在对多对关系的列表。 + * + * @param classId 主表主键Id。 + * @param filter 从表的过滤对象。 + * @param orderBy 排序参数。 + * @return 查询结果集。 + */ + public List getStudentListByClassId( + Long classId, Student filter, String orderBy) { + List resultList = + studentMapper.getStudentListByClassId(classId, filter, orderBy); + this.buildRelationForDataList(resultList, MyRelationParam.dictOnly(), null); + return resultList; + } + + /** + * 根据最新对象和原有对象的数据对比,判断关联的字典数据和多对一主表数据是否都是合法数据。 + * + * @param student 最新数据对象。 + * @param originalStudent 原有数据对象。 + * @return 数据全部正确返回true,否则false。 + */ + public CallResult verifyRelatedData(Student student, Student originalStudent) { + String errorMessageFormat = "数据验证失败,关联的%s并不存在,请刷新后重试!"; + //这里是基于字典的验证。 + if (this.needToVerify(student, originalStudent, Student::getProvinceId) + && !areaCodeService.existId(student.getProvinceId())) { + return CallResult.error(String.format(errorMessageFormat, "所在省份")); + } + //这里是基于字典的验证。 + if (this.needToVerify(student, originalStudent, Student::getCityId) + && !areaCodeService.existId(student.getCityId())) { + return CallResult.error(String.format(errorMessageFormat, "所在城市")); + } + //这里是基于字典的验证。 + if (this.needToVerify(student, originalStudent, Student::getDistrictId) + && !areaCodeService.existId(student.getDistrictId())) { + return CallResult.error(String.format(errorMessageFormat, "所在区县")); + } + //这里是基于字典的验证。 + if (this.needToVerify(student, originalStudent, Student::getGradeId) + && !gradeService.existId(student.getGradeId())) { + return CallResult.error(String.format(errorMessageFormat, "年级")); + } + //这里是基于字典的验证。 + if (this.needToVerify(student, originalStudent, Student::getSchoolId) + && !schoolInfoService.existId(student.getSchoolId())) { + return CallResult.error(String.format(errorMessageFormat, "所属校区")); + } + return CallResult.ok(); + } +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/config/ApplicationConfig.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/config/ApplicationConfig.java new file mode 100644 index 00000000..86f8e4da --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/config/ApplicationConfig.java @@ -0,0 +1,46 @@ +package com.orange.demo.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +/** + * 应用程序自定义的程序属性配置文件。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Data +@Configuration +@ConfigurationProperties(prefix = "application") +public class ApplicationConfig { + + /** + * token的Http Request Header的key + */ + private String tokenHeaderKey; + /** + * token在过期之前,但是已经需要被刷新时,response返回的header信息的key。 + */ + private String refreshedTokenHeaderKey; + /** + * token 加密用的密钥 + */ + private String tokenSigningKey; + /** + * 令牌的过期时间,单位毫秒 + */ + private Long expiration; + /** + * 用户密码被重置之后的缺省密码 + */ + private String defaultUserPassword; + /** + * 上传文件的基础目录 + */ + private String uploadFileBaseDir; + /** + * 授信ip列表,没有填写表示全部信任。多个ip之间逗号分隔,如: http://10.10.10.1:8080,http://10.10.10.2:8080 + */ + private String credentialIpList; +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/config/DataSourceConfig.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/config/DataSourceConfig.java new file mode 100644 index 00000000..38b69b93 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/config/DataSourceConfig.java @@ -0,0 +1,30 @@ +package com.orange.demo.config; + +import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.transaction.annotation.EnableTransactionManagement; +import tk.mybatis.spring.annotation.MapperScan; + +import javax.sql.DataSource; + +/** + * 数据源配置Bean对象。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Configuration +@EnableTransactionManagement +@MapperScan(value = {"com.orange.demo.*.dao"}) +public class DataSourceConfig { + + @Bean(initMethod = "init", destroyMethod = "close") + @Primary + @ConfigurationProperties(prefix = "spring.datasource.druid") + public DataSource druidDataSource() { + return DruidDataSourceBuilder.create().build(); + } +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/config/FilterConfig.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/config/FilterConfig.java new file mode 100644 index 00000000..b42db88c --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/config/FilterConfig.java @@ -0,0 +1,57 @@ +package com.orange.demo.config; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +import org.springframework.web.filter.CorsFilter; + +import javax.servlet.Filter; +import java.nio.charset.StandardCharsets; + +/** + * 这里主要配置Web的各种过滤器和监听器等Servlet容器组件。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Configuration +public class FilterConfig { + + /** + * 配置Ajax跨域过滤器。 + */ + @Bean + public CorsFilter corsFilterRegistration(ApplicationConfig applicationConfig) { + UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource(); + CorsConfiguration corsConfiguration = new CorsConfiguration(); + if (StringUtils.isNotBlank(applicationConfig.getCredentialIpList())) { + String[] credentialIpList = StringUtils.split(applicationConfig.getCredentialIpList(), ","); + if (credentialIpList.length > 0) { + for (String ip : credentialIpList) { + corsConfiguration.addAllowedOrigin(ip); + } + } + corsConfiguration.addAllowedHeader("*"); + corsConfiguration.addAllowedMethod("*"); + corsConfiguration.addExposedHeader(applicationConfig.getRefreshedTokenHeaderKey()); + corsConfiguration.setAllowCredentials(true); + configSource.registerCorsConfiguration("/**", corsConfiguration); + } + return new CorsFilter(configSource); + } + + @Bean + public FilterRegistrationBean characterEncodingFilterRegistration() { + FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean<>( + new org.springframework.web.filter.CharacterEncodingFilter()); + filterRegistrationBean.addUrlPatterns("/*"); + filterRegistrationBean.addInitParameter("encoding", StandardCharsets.UTF_8.name()); + // forceEncoding强制response也被编码,另外即使request中已经设置encoding,forceEncoding也会重新设置 + filterRegistrationBean.addInitParameter("forceEncoding", "true"); + filterRegistrationBean.setAsyncSupported(true); + return filterRegistrationBean; + } +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/config/InterceptorConfig.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/config/InterceptorConfig.java new file mode 100644 index 00000000..7ac7d8b0 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/config/InterceptorConfig.java @@ -0,0 +1,21 @@ +package com.orange.demo.config; + +import com.orange.demo.interceptor.AuthenticationInterceptor; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +/** + * 所有的项目拦截器都在这里集中配置 + * + * @author Jerry + * @date 2020-09-25 + */ +@Configuration +public class InterceptorConfig implements WebMvcConfigurer { + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(new AuthenticationInterceptor()).addPathPatterns("/**"); + } +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/interceptor/AuthenticationInterceptor.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/interceptor/AuthenticationInterceptor.java new file mode 100644 index 00000000..2ecfc15b --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/interceptor/AuthenticationInterceptor.java @@ -0,0 +1,134 @@ +package com.orange.demo.interceptor; + +import com.orange.demo.config.ApplicationConfig; +import com.orange.demo.upms.model.SysPermWhitelist; +import com.orange.demo.upms.service.SysPermWhitelistService; +import com.orange.demo.upms.service.SysPermService; +import com.orange.demo.common.core.annotation.NoAuthInterface; +import com.orange.demo.common.core.constant.ErrorCodeEnum; +import com.orange.demo.common.core.object.ResponseResult; +import com.orange.demo.common.core.object.TokenData; +import com.orange.demo.common.core.util.ApplicationContextHolder; +import com.orange.demo.common.core.util.JwtUtil; +import com.orange.demo.common.core.cache.SessionCacheHelper; +import com.alibaba.fastjson.JSONObject; +import io.jsonwebtoken.Claims; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.HandlerInterceptor; +import org.springframework.web.servlet.ModelAndView; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.Set; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 登录用户Token验证、生成和权限验证的拦截器。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Slf4j +public class AuthenticationInterceptor implements HandlerInterceptor { + + private ApplicationConfig appConfig = + ApplicationContextHolder.getBean("applicationConfig"); + + private SessionCacheHelper cacheHelper = + ApplicationContextHolder.getBean("sessionCacheHelper"); + + private SysPermService sysPermService = + ApplicationContextHolder.getBean("sysPermService"); + + private static SysPermWhitelistService sysPermWhilelistService = + ApplicationContextHolder.getBean("sysPermWhitelistService"); + + private static Set whitelistPermSet; + + static { + List sysPermWhitelistList = sysPermWhilelistService.getAllList(); + whitelistPermSet = sysPermWhitelistList.stream() + .map(SysPermWhitelist::getPermUrl).collect(Collectors.toSet()); + } + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) + throws Exception { + String url = request.getRequestURI(); + // 如果接口方法标记NoAuthInterface注解,可以直接跳过Token鉴权验证,这里主要为了测试接口方便 + if (handler instanceof HandlerMethod) { + HandlerMethod hm = (HandlerMethod) handler; + if (hm.getBeanType().getAnnotation(NoAuthInterface.class) != null + || hm.getMethodAnnotation(NoAuthInterface.class) != null) { + return true; + } + } + String token = request.getHeader(appConfig.getTokenHeaderKey()); + if (StringUtils.isBlank(token)) { + token = request.getParameter(appConfig.getTokenHeaderKey()); + } + Claims c = JwtUtil.parseToken(token, appConfig.getTokenSigningKey()); + if (JwtUtil.isNullOrExpired(c)) { + response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + this.outputResponseMessage(response, + ResponseResult.error(ErrorCodeEnum.UNAUTHORIZED_LOGIN, "用户会话已过期,请重新登录!")); + return false; + } + String sessionId = (String) c.get("sessionId"); + TokenData tokenData = cacheHelper.getTokenData(sessionId); + if (tokenData == null) { + response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + this.outputResponseMessage(response, + ResponseResult.error(ErrorCodeEnum.UNAUTHORIZED_LOGIN, "用户会话已失效,请重新登录!")); + return false; + } + TokenData.addToRequest(tokenData); + // 如果url在权限资源白名单中,则不需要进行鉴权操作 + if (!tokenData.getIsAdmin() && !whitelistPermSet.contains(url)) { + Set urlSet = sysPermService.getCacheableSysPermSetByUserId( + tokenData.getSessionId(), tokenData.getUserId()); + if (!urlSet.contains(url)) { + response.setStatus(HttpServletResponse.SC_FORBIDDEN); + this.outputResponseMessage(response, + ResponseResult.error(ErrorCodeEnum.NO_OPERATION_PERMISSION)); + return false; + } + } + if (JwtUtil.needToRefresh(c)) { + String refreshedToken = JwtUtil.generateToken(c, appConfig.getExpiration(), appConfig.getTokenSigningKey()); + response.addHeader(appConfig.getRefreshedTokenHeaderKey(), refreshedToken); + } + return true; + } + + @Override + public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, + ModelAndView modelAndView) throws Exception { + // 这里需要空注解,否则sonar会不happy。 + } + + @Override + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) + throws Exception { + // 这里需要空注解,否则sonar会不happy。 + } + + private void outputResponseMessage(HttpServletResponse response, ResponseResult respObj) { + PrintWriter out; + try { + out = response.getWriter(); + } catch (IOException e) { + log.error("Failed to call OutputResponseMessage.", e); + return; + } + response.setContentType("application/json; charset=utf-8"); + out.print(JSONObject.toJSONString(respObj)); + out.flush(); + out.close(); + } +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/controller/LoginController.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/controller/LoginController.java new file mode 100644 index 00000000..408d19b9 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/controller/LoginController.java @@ -0,0 +1,151 @@ +package com.orange.demo.upms.controller; + +import com.alibaba.fastjson.JSONObject; +import lombok.extern.slf4j.Slf4j; +import com.orange.demo.config.ApplicationConfig; +import com.orange.demo.upms.service.*; +import com.orange.demo.upms.model.SysMenu; +import com.orange.demo.upms.model.SysUser; +import com.orange.demo.upms.model.constant.SysUserStatus; +import com.orange.demo.upms.model.constant.SysUserType; +import com.orange.demo.common.core.annotation.MyRequestBody; +import com.orange.demo.common.core.annotation.NoAuthInterface; +import com.orange.demo.common.core.constant.ApplicationConstant; +import com.orange.demo.common.core.constant.ErrorCodeEnum; +import com.orange.demo.common.core.object.ResponseResult; +import com.orange.demo.common.core.object.TokenData; +import com.orange.demo.common.core.util.*; +import com.orange.demo.common.core.cache.SessionCacheHelper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.web.bind.annotation.*; + +import java.net.URLDecoder; +import java.nio.charset.StandardCharsets; +import java.util.*; + +/** + * 登录接口控制器类。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Slf4j +@RestController +@RequestMapping("/admin/login") +public class LoginController { + + @Autowired + private SysUserService sysUserService; + @Autowired + private SysMenuService sysMenuService; + @Autowired + private SysPermCodeService sysPermCodeService; + @Autowired + private SysPermService sysPermService; + @Autowired + private ApplicationConfig appConfig; + @Autowired + private SessionCacheHelper cacheHelper; + @Autowired + private PasswordEncoder passwordEncoder; + + /** + * 登录接口。 + * + * @param loginName 登录名。 + * @param password 密码。 + * @return 应答结果对象,其中包括JWT的Token数据,以及菜单列表。 + */ + @NoAuthInterface + @GetMapping("/doLogin") + public ResponseResult doLogin( + @RequestParam String loginName, @RequestParam String password) throws Exception { + if (MyCommonUtil.existBlankArgument(loginName, password)) { + return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST); + } + SysUser user = sysUserService.getSysUserByLoginName(loginName); + password = URLDecoder.decode(password, StandardCharsets.UTF_8.name()); + //NOTE: 第一次使用时,请务必阅读ApplicationConstant.PRIVATE_KEY的代码注释。 + //执行RsaUtil工具类中的main函数,可以生成新的公钥和私钥。 + password = RsaUtil.decrypt(password, ApplicationConstant.PRIVATE_KEY); + if (user == null || !passwordEncoder.matches(password, user.getPassword())) { + return ResponseResult.error(ErrorCodeEnum.INVALID_USERNAME_PASSWORD); + } + String errorMessage; + if (user.getUserStatus() == SysUserStatus.STATUS_LOCKED) { + errorMessage = "登录失败,用户账号被锁定!"; + return ResponseResult.error(ErrorCodeEnum.INVALID_USER_STATUS, errorMessage); + } + boolean isAdmin = user.getUserType() == SysUserType.TYPE_ADMIN; + Map claims = new HashMap<>(3); + String sessionId = MyCommonUtil.generateUuid(); + claims.put("sessionId", sessionId); + String token = JwtUtil.generateToken(claims, appConfig.getExpiration(), appConfig.getTokenSigningKey()); + JSONObject jsonData = new JSONObject(); + jsonData.put(TokenData.REQUEST_ATTRIBUTE_NAME, token); + jsonData.put("showName", user.getShowName()); + jsonData.put("isAdmin", isAdmin); + TokenData tokenData = new TokenData(); + tokenData.setSessionId(sessionId); + tokenData.setUserId(user.getUserId()); + tokenData.setShowName(user.getShowName()); + tokenData.setIsAdmin(isAdmin); + cacheHelper.putTokenData(sessionId, tokenData); + List menuList; + if (isAdmin) { + menuList = sysMenuService.getAllMenuList(); + } else { + menuList = sysMenuService.getMenuListByUserId(user.getUserId()); + List permCodeList = sysPermCodeService.getPermCodeListByUserId(user.getUserId()); + jsonData.put("permCodeList", permCodeList); + } + jsonData.put("menuList", menuList); + if (user.getUserType() != SysUserType.TYPE_ADMIN) { + // 缓存用户的权限资源 + sysPermService.putUserSysPermCache(sessionId, user.getUserId(), isAdmin); + } + return ResponseResult.success(jsonData); + } + + /** + * 登出操作。同时将Session相关的信息从缓存中删除。 + * + * @return 应答结果对象。 + */ + @PostMapping("/doLogout") + public ResponseResult doLogout() { + cacheHelper.removeAllSessionCache(); + return ResponseResult.success(); + } + + /** + * 用户修改自己的密码。 + * + * @param oldPass 原有密码。 + * @param newPass 新密码。 + * @return 应答结果对象。 + */ + @PostMapping("/changePassword") + public ResponseResult changePassword( + @MyRequestBody String oldPass, @MyRequestBody String newPass) throws Exception { + if (MyCommonUtil.existBlankArgument(oldPass, oldPass)) { + return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST); + } + TokenData tokenData = TokenData.takeFromRequest(); + SysUser user = sysUserService.getById(tokenData.getUserId()); + oldPass = URLDecoder.decode(oldPass, StandardCharsets.UTF_8.name()); + //NOTE: 第一次使用时,请务必阅读ApplicationConstant.PRIVATE_KEY的代码注释。 + //执行RsaUtil工具类中的main函数,可以生成新的公钥和私钥。 + oldPass = RsaUtil.decrypt(oldPass, ApplicationConstant.PRIVATE_KEY); + if (user == null || !passwordEncoder.matches(oldPass, user.getPassword())) { + return ResponseResult.error(ErrorCodeEnum.INVALID_USERNAME_PASSWORD); + } + newPass = URLDecoder.decode(newPass, StandardCharsets.UTF_8.name()); + newPass = RsaUtil.decrypt(newPass, ApplicationConstant.PRIVATE_KEY); + if (!sysUserService.changePassword(tokenData.getUserId(), newPass)) { + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST); + } + return ResponseResult.success(); + } +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/controller/SysMenuController.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/controller/SysMenuController.java new file mode 100644 index 00000000..8ac13a44 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/controller/SysMenuController.java @@ -0,0 +1,160 @@ +package com.orange.demo.upms.controller; + +import com.alibaba.fastjson.JSONObject; +import lombok.extern.slf4j.Slf4j; +import com.orange.demo.upms.model.SysMenu; +import com.orange.demo.upms.service.SysMenuService; +import com.orange.demo.upms.service.SysPermCodeService; +import com.orange.demo.common.core.constant.ErrorCodeEnum; +import com.orange.demo.common.core.object.CallResult; +import com.orange.demo.common.core.object.ResponseResult; +import com.orange.demo.common.core.object.MyRelationParam; +import com.orange.demo.common.core.util.MyCommonUtil; +import com.orange.demo.common.core.validator.UpdateGroup; +import com.orange.demo.common.core.annotation.MyRequestBody; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import javax.validation.groups.Default; +import java.util.*; + +/** + * 菜单管理接口控制器类。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Slf4j +@RestController +@RequestMapping("/admin/upms/sysMenu") +public class SysMenuController { + + @Autowired + private SysMenuService sysMenuService; + @Autowired + private SysPermCodeService sysPermCodeService; + + /** + * 添加新菜单操作。 + * + * @param sysMenu 新菜单对象。 + * @param permCodeIdListString 与当前菜单Id绑定的权限Id列表,多个权限之间逗号分隔。 + * @return 应答结果对象,包含新增菜单的主键Id。 + */ + @SuppressWarnings("unchecked") + @PostMapping("/add") + public ResponseResult add(@MyRequestBody SysMenu sysMenu, @MyRequestBody String permCodeIdListString) { + String errorMessage = MyCommonUtil.getModelValidationError(sysMenu); + if (errorMessage != null) { + return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATAED_FAILED, errorMessage); + } + CallResult result = sysMenuService.verifyRelatedData(sysMenu, null, permCodeIdListString); + if (!result.isSuccess()) { + return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATAED_FAILED, result.getErrorMessage()); + } + Set permCodeIdSet = null; + if (result.getData() != null) { + permCodeIdSet = (Set) result.getData().get("permCodeIdSet"); + } + sysMenuService.saveNew(sysMenu, permCodeIdSet); + JSONObject responseData = new JSONObject(); + responseData.put("sysMenuId", sysMenu.getMenuId()); + return ResponseResult.success(responseData); + } + + /** + * 更新菜单数据操作。 + * + * @param sysMenu 更新菜单对象。 + * @param permCodeIdListString 与当前菜单Id绑定的权限Id列表,多个权限之间逗号分隔。 + * @return 应答结果对象。 + */ + @SuppressWarnings("unchecked") + @PostMapping("/update") + public ResponseResult update(@MyRequestBody SysMenu sysMenu, @MyRequestBody String permCodeIdListString) { + String errorMessage = MyCommonUtil.getModelValidationError(sysMenu, Default.class, UpdateGroup.class); + if (errorMessage != null) { + return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATAED_FAILED, errorMessage); + } + SysMenu originalSysMenu = sysMenuService.getById(sysMenu.getMenuId()); + if (originalSysMenu == null) { + errorMessage = "数据验证失败,当前菜单并不存在,请刷新后重试!"; + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage); + } + CallResult result = sysMenuService.verifyRelatedData(sysMenu, originalSysMenu, permCodeIdListString); + if (!result.isSuccess()) { + return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATAED_FAILED, result.getErrorMessage()); + } + Set permCodeIdSet = null; + if (result.getData() != null) { + permCodeIdSet = (Set) result.getData().get("permCodeIdSet"); + } + if (!sysMenuService.update(sysMenu, originalSysMenu, permCodeIdSet)) { + errorMessage = "数据验证失败,当前权限字并不存在,请刷新后重试!"; + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage); + } + return ResponseResult.success(); + } + + /** + * 删除指定菜单操作。 + * + * @param menuId 指定菜单主键Id。 + * @return 应答结果对象。 + */ + @PostMapping("/delete") + public ResponseResult delete(@MyRequestBody Long menuId) { + if (MyCommonUtil.existBlankArgument(menuId)) { + return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST); + } + String errorMessage; + if (sysMenuService.hasChildren(menuId)) { + errorMessage = "数据验证失败,当前菜单存在下级菜单!"; + return ResponseResult.error(ErrorCodeEnum.HAS_CHILDREN_DATA, errorMessage); + } + if (!sysMenuService.remove(menuId)) { + errorMessage = "数据操作失败,菜单不存在,请刷新后重试!"; + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage); + } + return ResponseResult.success(); + } + + /** + * 获取全部菜单列表。 + * + * @return 应答结果对象,包含全部菜单数据列表。 + */ + @GetMapping("/list") + public ResponseResult> list() { + return ResponseResult.success(sysMenuService.getAllListByOrder("showOrder")); + } + + /** + * 查看指定菜单数据详情。 + * + * @param menuId 指定菜单主键Id。 + * @return 应答结果对象,包含菜单详情。 + */ + @GetMapping("/view") + public ResponseResult view(@RequestParam Long menuId) { + if (MyCommonUtil.existBlankArgument(menuId)) { + return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST); + } + SysMenu sysMenu = sysMenuService.getByIdWithRelation(menuId, MyRelationParam.full()); + if (sysMenu == null) { + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST); + } + return ResponseResult.success(sysMenu); + } + + /** + * 列出与指定菜单关联的权限字和权限资源,便于管理员排查配置中的错误。 + * + * @param menuId 菜单Id。 + * @return 与菜单关联的权限字和权限资源列表。 + */ + @GetMapping("/listMenuPerm") + public ResponseResult>> listMenuPerm(@RequestParam Long menuId) { + return ResponseResult.success(sysPermCodeService.getPermCodeListByMenuId(menuId)); + } +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/controller/SysPermCodeController.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/controller/SysPermCodeController.java new file mode 100644 index 00000000..14339f8c --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/controller/SysPermCodeController.java @@ -0,0 +1,180 @@ +package com.orange.demo.upms.controller; + +import com.alibaba.fastjson.JSONObject; +import com.github.pagehelper.page.PageMethod; +import lombok.extern.slf4j.Slf4j; +import com.orange.demo.upms.model.SysPermCode; +import com.orange.demo.upms.service.SysPermCodeService; +import com.orange.demo.common.core.constant.ErrorCodeEnum; +import com.orange.demo.common.core.object.ResponseResult; +import com.orange.demo.common.core.object.CallResult; +import com.orange.demo.common.core.object.MyPageParam; +import com.orange.demo.common.core.object.MyRelationParam; +import com.orange.demo.common.core.util.MyCommonUtil; +import com.orange.demo.common.core.util.MyPageUtil; +import com.orange.demo.common.core.validator.UpdateGroup; +import com.orange.demo.common.core.annotation.MyRequestBody; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DuplicateKeyException; +import org.springframework.web.bind.annotation.*; + +import javax.validation.groups.Default; +import java.util.*; + +/** + * 权限字管理接口控制器类。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Slf4j +@RestController +@RequestMapping("/admin/upms/sysPermCode") +public class SysPermCodeController { + + @Autowired + private SysPermCodeService sysPermCodeService; + + /** + * 新增权限字操作。 + * + * @param sysPermCode 新增权限字对象。 + * @param permIdListString 与当前权限Id绑定的权限资源Id列表,多个权限资源之间逗号分隔。 + * @return 应答结果对象,包含新增权限字的主键Id。 + */ + @SuppressWarnings("unchecked") + @PostMapping("/add") + public ResponseResult add(@MyRequestBody SysPermCode sysPermCode, @MyRequestBody String permIdListString) { + String errorMessage = MyCommonUtil.getModelValidationError(sysPermCode); + if (errorMessage != null) { + return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATAED_FAILED); + } + CallResult result = sysPermCodeService.verifyRelatedData(sysPermCode, null, permIdListString); + if (!result.isSuccess()) { + return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATAED_FAILED, result.getErrorMessage()); + } + Set permIdSet = null; + if (result.getData() != null) { + permIdSet = (Set) result.getData().get("permIdSet"); + } + sysPermCode = sysPermCodeService.saveNew(sysPermCode, permIdSet); + JSONObject responseData = new JSONObject(); + responseData.put("sysPermCodeId", sysPermCode.getPermCodeId()); + return ResponseResult.success(responseData); + } + + /** + * 更新权限字操作。 + * + * @param sysPermCode 更新权限字对象。 + * @param permIdListString 与当前权限Id绑定的权限资源Id列表,多个权限资源之间逗号分隔。 + * @return 应答结果对象。 + */ + @SuppressWarnings("unchecked") + @PostMapping("/update") + public ResponseResult update(@MyRequestBody SysPermCode sysPermCode, @MyRequestBody String permIdListString) { + String errorMessage = MyCommonUtil.getModelValidationError(sysPermCode, Default.class, UpdateGroup.class); + if (errorMessage != null) { + return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATAED_FAILED, errorMessage); + } + SysPermCode originalSysPermCode = sysPermCodeService.getById(sysPermCode.getPermCodeId()); + if (originalSysPermCode == null) { + errorMessage = "数据验证失败,当前权限字并不存在,请刷新后重试!"; + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage); + } + CallResult result = sysPermCodeService.verifyRelatedData(sysPermCode, originalSysPermCode, permIdListString); + if (!result.isSuccess()) { + return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATAED_FAILED, result.getErrorMessage()); + } + Set permIdSet = null; + if (result.getData() != null) { + permIdSet = (Set) result.getData().get("permIdSet"); + } + try { + if (!sysPermCodeService.update(sysPermCode, originalSysPermCode, permIdSet)) { + errorMessage = "数据验证失败,当前权限字并不存在,请刷新后重试!"; + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage); + } + } catch (DuplicateKeyException e) { + errorMessage = "数据操作失败,权限字编码已经存在!"; + return ResponseResult.error(ErrorCodeEnum.DUPLICATED_UNIQUE_KEY, errorMessage); + } + return ResponseResult.success(); + } + + /** + * 删除指定权限字操作。 + * + * @param permCodeId 指定的权限字主键Id。 + * @return 应答结果对象。 + */ + @PostMapping("/delete") + public ResponseResult delete(@MyRequestBody Long permCodeId) { + if (MyCommonUtil.existBlankArgument(permCodeId)) { + return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST); + } + String errorMessage; + if (sysPermCodeService.hasChildren(permCodeId)) { + errorMessage = "数据验证失败,当前权限字存在下级权限字!"; + return ResponseResult.error(ErrorCodeEnum.HAS_CHILDREN_DATA, errorMessage); + } + if (!sysPermCodeService.remove(permCodeId)) { + errorMessage = "数据操作失败,权限字不存在,请刷新后重试!"; + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage); + } + return ResponseResult.success(); + } + + /** + * 查看权限字列表。 + * + * @return 应答结果对象,包含权限字列表。 + */ + @PostMapping("/list") + public ResponseResult> list() { + return ResponseResult.success(sysPermCodeService.getAllListByOrder("permCodeType", "showOrder")); + } + + /** + * 查看权限字对象详情。 + * + * @param permCodeId 指定权限字主键Id。 + * @return 应答结果对象,包含权限字对象详情。 + */ + @GetMapping("/view") + public ResponseResult view(@RequestParam Long permCodeId) { + if (MyCommonUtil.existBlankArgument(permCodeId)) { + return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST); + } + SysPermCode sysPermCode = sysPermCodeService.getByIdWithRelation(permCodeId, MyRelationParam.full()); + if (sysPermCode == null) { + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST); + } + return ResponseResult.success(sysPermCode); + } + + /** + * 查看用户关联的权限字列表。 + * + * @param loginName 精确匹配用户登录名。 + * @param permCode 模糊匹配的权限字名,LIKE %permCode%。 + * @param pageParam 分页对象。 + * @return 应答结果对象,包含该用户的全部权限资源列表。 + */ + @PostMapping("/listAllPermCodesByUserFilter") + public ResponseResult listAllPermCodesByUserFilter( + @MyRequestBody String loginName, + @MyRequestBody String permCode, + @MyRequestBody MyPageParam pageParam) { + if (MyCommonUtil.existBlankArgument(loginName)) { + return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST); + } + if (pageParam != null) { + PageMethod.startPage(pageParam.getPageNum(), pageParam.getPageSize()); + } + List permCodeList = + sysPermCodeService.getUserPermCodeListByFilter(loginName, permCode); + JSONObject responseData = MyPageUtil.makeResponseData(permCodeList); + return ResponseResult.success(responseData); + } +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/controller/SysPermController.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/controller/SysPermController.java new file mode 100644 index 00000000..4a83e032 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/controller/SysPermController.java @@ -0,0 +1,197 @@ +package com.orange.demo.upms.controller; + +import com.alibaba.fastjson.JSONObject; +import com.github.pagehelper.page.PageMethod; +import lombok.extern.slf4j.Slf4j; +import com.orange.demo.upms.model.SysPerm; +import com.orange.demo.upms.model.SysPermModule; +import com.orange.demo.upms.service.SysPermService; +import com.orange.demo.common.core.constant.ErrorCodeEnum; +import com.orange.demo.common.core.object.ResponseResult; +import com.orange.demo.common.core.object.CallResult; +import com.orange.demo.common.core.object.MyPageParam; +import com.orange.demo.common.core.util.MyCommonUtil; +import com.orange.demo.common.core.util.MyPageUtil; +import com.orange.demo.common.core.validator.UpdateGroup; +import com.orange.demo.common.core.annotation.MyRequestBody; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import javax.validation.groups.Default; +import java.util.List; +import java.util.Map; + +/** + * 权限资源管理接口控制器类。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Slf4j +@RestController +@RequestMapping("/admin/upms/sysPerm") +public class SysPermController { + + @Autowired + private SysPermService sysPermService; + + /** + * 新增权限资源操作。 + * + * @param sysPerm 新增权限资源对象。 + * @return 应答结果对象,包含新增权限资源的主键Id。 + */ + @PostMapping("/add") + public ResponseResult add(@MyRequestBody SysPerm sysPerm) { + String errorMessage = MyCommonUtil.getModelValidationError(sysPerm); + if (errorMessage != null) { + return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATAED_FAILED, errorMessage); + } + CallResult result = sysPermService.verifyRelatedData(sysPerm, null); + if (!result.isSuccess()) { + return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATAED_FAILED, result.getErrorMessage()); + } + sysPerm = sysPermService.saveNew(sysPerm); + JSONObject responseData = new JSONObject(); + responseData.put("permId", sysPerm.getPermId()); + return ResponseResult.success(responseData); + } + + /** + * 更新权限资源操作。 + * + * @param sysPerm 更新权限资源对象。 + * @return 应答结果对象,包含更新权限资源的主键Id。 + */ + @PostMapping("/update") + public ResponseResult update(@MyRequestBody SysPerm sysPerm) { + String errorMessage = MyCommonUtil.getModelValidationError(sysPerm, Default.class, UpdateGroup.class); + if (errorMessage != null) { + return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATAED_FAILED, errorMessage); + } + SysPerm originalPerm = sysPermService.getById(sysPerm.getPermId()); + if (originalPerm == null) { + errorMessage = "数据验证失败,当前权限资源并不存在,请刷新后重试!"; + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage); + } + CallResult result = sysPermService.verifyRelatedData(sysPerm, originalPerm); + if (!result.isSuccess()) { + return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATAED_FAILED, result.getErrorMessage()); + } + if (result.getData() != null) { + SysPermModule permModule = (SysPermModule) result.getData().get("permModule"); + sysPerm.setModuleId(permModule.getModuleId()); + } + sysPermService.update(sysPerm, originalPerm); + return ResponseResult.success(); + } + + /** + * 删除指定权限资源操作。 + * + * @param permId 指定的权限资源主键Id。 + * @return 应答结果对象。 + */ + @PostMapping("/delete") + public ResponseResult delete(@MyRequestBody Long permId) { + if (MyCommonUtil.existBlankArgument(permId)) { + return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST); + } + if (!sysPermService.remove(permId)) { + String errorMessage = "数据操作失败,权限不存在,请刷新后重试!"; + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage); + } + return ResponseResult.success(); + } + + /** + * 查看权限资源对象详情。 + * + * @param permId 指定权限资源主键Id。 + * @return 应答结果对象,包含权限资源对象详情。 + */ + @GetMapping("/view") + public ResponseResult view(@RequestParam Long permId) { + if (MyCommonUtil.existBlankArgument(permId)) { + return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST); + } + SysPerm perm = sysPermService.getById(permId); + if (perm == null) { + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST); + } + return ResponseResult.success(perm); + } + + /** + * 查看权限资源列表。 + * + * @param sysPermFilter 过滤对象。 + * @param pageParam 分页参数。 + * @return 应答结果对象,包含权限资源列表。 + */ + @PostMapping("/list") + public ResponseResult list(@MyRequestBody SysPerm sysPermFilter, @MyRequestBody MyPageParam pageParam) { + if (pageParam != null) { + PageMethod.startPage(pageParam.getPageNum(), pageParam.getPageSize()); + } + List resultList = sysPermService.getPermListWithRelation(sysPermFilter); + return ResponseResult.success(MyPageUtil.makeResponseData(resultList)); + } + + /** + * 查看用户关联的权限资源列表。 + * + * @param loginName 精确匹配用户登录名。 + * @param moduleId 精确匹配权限模块Id。 + * @param url 模糊匹配的url过滤条件。 + * @param pageParam 分页对象。 + * @return 应答结果对象,包含该用户的全部权限资源列表。 + */ + @PostMapping("/listAllPermsByUserFilter") + public ResponseResult listAllPermsByUserFilter( + @MyRequestBody String loginName, + @MyRequestBody Long moduleId, + @MyRequestBody String url, + @MyRequestBody MyPageParam pageParam) { + if (MyCommonUtil.existBlankArgument(loginName)) { + return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST); + } + if (pageParam != null) { + PageMethod.startPage(pageParam.getPageNum(), pageParam.getPageSize()); + } + List> userPermMapList = + sysPermService.getUserPermListByFilter(loginName, moduleId, url); + JSONObject responseData = MyPageUtil.makeResponseData(userPermMapList); + return ResponseResult.success(responseData); + } + + /** + * 查看拥有指定权限资源的所有用户数据列表。 + * + * @param permId 指定权限资源主键Id。 + * @return 应答结果对象,包含用户数据列表。 + */ + @PostMapping("/listAllUsers") + public ResponseResult>> listAllUsers(@MyRequestBody Long permId) { + if (MyCommonUtil.existBlankArgument(permId)) { + return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST); + } + List> permUserMapList = sysPermService.getPermUserListById(permId); + return ResponseResult.success(permUserMapList); + } + + /** + * 查看拥有指定权限资源的所有角色数据列表。 + * + * @param permId 指定权限资源主键Id。 + * @return 应答结果对象,包含角色数据列表。 + */ + @PostMapping("/listAllRoles") + public ResponseResult>> listAllRoles(@MyRequestBody Long permId) { + if (MyCommonUtil.existBlankArgument(permId)) { + return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST); + } + List> permRoleMapList = sysPermService.getPermRoleListById(permId); + return ResponseResult.success(permRoleMapList); + } +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/controller/SysPermModuleController.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/controller/SysPermModuleController.java new file mode 100644 index 00000000..373ecb24 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/controller/SysPermModuleController.java @@ -0,0 +1,157 @@ +package com.orange.demo.upms.controller; + +import com.alibaba.fastjson.JSONObject; +import lombok.extern.slf4j.Slf4j; +import com.orange.demo.upms.model.SysPerm; +import com.orange.demo.upms.model.SysPermModule; +import com.orange.demo.upms.service.SysPermModuleService; +import com.orange.demo.common.core.constant.ErrorCodeEnum; +import com.orange.demo.common.core.object.ResponseResult; +import com.orange.demo.common.core.util.MyCommonUtil; +import com.orange.demo.common.core.validator.UpdateGroup; +import com.orange.demo.common.core.annotation.MyRequestBody; +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import javax.validation.groups.Default; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +/** + * 权限资源模块管理接口控制器类。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Slf4j +@RestController +@RequestMapping("/admin/upms/sysPermModule") +public class SysPermModuleController { + + @Autowired + private SysPermModuleService sysPermModuleService; + + /** + * 新增权限资源模块操作。 + * + * @param sysPermModule 新增权限资源模块对象。 + * @return 应答结果对象,包含新增权限资源模块的主键Id。 + */ + @PostMapping("/add") + public ResponseResult add(@MyRequestBody SysPermModule sysPermModule) { + String errorMessage = MyCommonUtil.getModelValidationError(sysPermModule); + if (errorMessage != null) { + return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATAED_FAILED, errorMessage); + } + if (sysPermModule.getParentId() != null + && sysPermModuleService.getById(sysPermModule.getParentId()) == null) { + errorMessage = "数据验证失败,关联的上级权限模块并不存在,请刷新后重试!"; + return ResponseResult.error(ErrorCodeEnum.DATA_PARENT_ID_NOT_EXIST, errorMessage); + } + sysPermModuleService.saveNew(sysPermModule); + JSONObject responseData = new JSONObject(); + responseData.put("permModuleId", sysPermModule.getModuleId()); + return ResponseResult.success(responseData); + } + + /** + * 更新权限资源模块操作。 + * + * @param sysPermModule 更新权限资源模块对象。 + * @return 应答结果对象,包含新增权限资源模块的主键Id。 + */ + @PostMapping("/update") + public ResponseResult update(@MyRequestBody SysPermModule sysPermModule) { + String errorMessage = MyCommonUtil.getModelValidationError(sysPermModule, Default.class, UpdateGroup.class); + if (errorMessage != null) { + return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATAED_FAILED, errorMessage); + } + SysPermModule originalPermModule = sysPermModuleService.getById(sysPermModule.getModuleId()); + if (originalPermModule == null) { + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST); + } + if (sysPermModule.getParentId() != null + && !sysPermModule.getParentId().equals(originalPermModule.getParentId())) { + if (sysPermModuleService.getById(sysPermModule.getParentId()) == null) { + errorMessage = "数据验证失败,关联的上级权限模块并不存在,请刷新后重试!"; + return ResponseResult.error(ErrorCodeEnum.DATA_PARENT_ID_NOT_EXIST, errorMessage); + } + } + if (!sysPermModuleService.update(sysPermModule, originalPermModule)) { + errorMessage = "数据验证失败,当前模块并不存在,请刷新后重试!"; + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage); + } + return ResponseResult.success(); + } + + /** + * 删除指定权限资源模块操作。 + * + * @param moduleId 指定的权限资源模块主键Id。 + * @return 应答结果对象。 + */ + @PostMapping("/delete") + public ResponseResult delete(@MyRequestBody Long moduleId) { + if (MyCommonUtil.existBlankArgument(moduleId)) { + return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST); + } + String errorMessage; + if (sysPermModuleService.hasChildren(moduleId) + || sysPermModuleService.hasModulePerms(moduleId)) { + errorMessage = "数据验证失败,当前权限模块存在子模块或权限资源,请先删除关联数据!"; + return ResponseResult.error(ErrorCodeEnum.HAS_CHILDREN_DATA, errorMessage); + } + if (!sysPermModuleService.remove(moduleId)) { + errorMessage = "数据操作失败,权限模块不存在,请刷新后重试!"; + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage); + } + return ResponseResult.success(); + } + + /** + * 查看全部权限资源模块列表。 + * + * @return 应答结果对象,包含权限资源模块列表。 + */ + @GetMapping("/list") + public ResponseResult> list() { + return ResponseResult.success(sysPermModuleService.getAllListByOrder("showOrder")); + } + + /** + * 列出全部权限资源模块及其下级关联的权限资源列表。 + * + * @return 应答结果对象,包含树状列表,结构为权限资源模块和权限资源之间的树状关系。 + */ + @GetMapping("/listAll") + public ResponseResult>> listAll() { + List sysPermModuleList = sysPermModuleService.getPermModuleAndPermList(); + List> resultList = new LinkedList<>(); + for (SysPermModule sysPermModule : sysPermModuleList) { + Map permModuleMap = new HashMap<>(5); + permModuleMap.put("id", sysPermModule.getModuleId()); + permModuleMap.put("name", sysPermModule.getModuleName()); + permModuleMap.put("type", sysPermModule.getModuleType()); + permModuleMap.put("isPerm", false); + if (MyCommonUtil.isNotBlankOrNull(sysPermModule.getParentId())) { + permModuleMap.put("parentId", sysPermModule.getParentId()); + } + resultList.add(permModuleMap); + if (CollectionUtils.isNotEmpty(sysPermModule.getSysPermList())) { + for (SysPerm sysPerm : sysPermModule.getSysPermList()) { + Map permMap = new HashMap<>(4); + permMap.put("id", sysPerm.getPermId()); + permMap.put("name", sysPerm.getPermName()); + permMap.put("isPerm", true); + permMap.put("url", sysPerm.getUrl()); + permMap.put("parentId", sysPermModule.getModuleId()); + resultList.add(permMap); + } + } + } + return ResponseResult.success(resultList); + } +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/controller/SysRoleController.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/controller/SysRoleController.java new file mode 100644 index 00000000..396e1af3 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/controller/SysRoleController.java @@ -0,0 +1,323 @@ +package com.orange.demo.upms.controller; + +import com.alibaba.fastjson.JSONObject; +import com.github.pagehelper.page.PageMethod; +import lombok.extern.slf4j.Slf4j; +import com.orange.demo.upms.model.SysRole; +import com.orange.demo.upms.model.SysUser; +import com.orange.demo.upms.model.SysUserRole; +import com.orange.demo.upms.service.SysRoleService; +import com.orange.demo.upms.service.SysUserService; +import com.orange.demo.common.core.validator.UpdateGroup; +import com.orange.demo.common.core.util.MyCommonUtil; +import com.orange.demo.common.core.constant.ErrorCodeEnum; +import com.orange.demo.common.core.object.MyOrderParam; +import com.orange.demo.common.core.object.MyPageParam; +import com.orange.demo.common.core.object.ResponseResult; +import com.orange.demo.common.core.object.CallResult; +import com.orange.demo.common.core.object.MyRelationParam; +import com.orange.demo.common.core.util.MyPageUtil; +import com.orange.demo.common.core.annotation.MyRequestBody; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import javax.validation.groups.Default; +import java.util.*; +import java.util.stream.Collectors; + +/** + * 角色管理接口控制器类。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Slf4j +@RestController +@RequestMapping("/admin/upms/sysRole") +public class SysRoleController { + + @Autowired + private SysRoleService sysRoleService; + @Autowired + private SysUserService sysUserService; + + /** + * 新增角色操作。 + * + * @param sysRole 新增角色对象。 + * @param menuIdListString 与当前角色Id绑定的menuId列表,多个menuId之间逗号分隔。 + * @return 应答结果对象,包含新增角色的主键Id。 + */ + @SuppressWarnings("unchecked") + @PostMapping("/add") + public ResponseResult add(@MyRequestBody SysRole sysRole, @MyRequestBody String menuIdListString) { + String errorMessage = MyCommonUtil.getModelValidationError(sysRole); + if (errorMessage != null) { + return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATAED_FAILED, errorMessage); + } + CallResult result = sysRoleService.verifyRelatedData(sysRole, null, menuIdListString); + if (!result.isSuccess()) { + return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATAED_FAILED, result.getErrorMessage()); + } + Set menuIdSet = null; + if (result.getData() != null) { + menuIdSet = (Set) result.getData().get("menuIdSet"); + } + sysRoleService.saveNew(sysRole, menuIdSet); + JSONObject responseData = new JSONObject(); + responseData.put("roleId", sysRole.getRoleId()); + return ResponseResult.success(responseData); + } + + /** + * 更新角色操作。 + * + * @param sysRole 更新角色对象。 + * @param menuIdListString 与当前角色Id绑定的menuId列表,多个menuId之间逗号分隔。 + * @return 应答结果对象。 + */ + @SuppressWarnings("unchecked") + @PostMapping("/update") + public ResponseResult update(@MyRequestBody SysRole sysRole, @MyRequestBody String menuIdListString) { + String errorMessage = MyCommonUtil.getModelValidationError(sysRole, Default.class, UpdateGroup.class); + if (errorMessage != null) { + return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATAED_FAILED, errorMessage); + } + SysRole originalSysRole = sysRoleService.getById(sysRole.getRoleId()); + if (originalSysRole == null) { + errorMessage = "数据验证失败,当前角色并不存在,请刷新后重试!"; + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage); + } + CallResult result = sysRoleService.verifyRelatedData(sysRole, originalSysRole, menuIdListString); + if (!result.isSuccess()) { + return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATAED_FAILED, result.getErrorMessage()); + } + Set menuIdSet = null; + if (result.getData() != null) { + menuIdSet = (Set) result.getData().get("menuIdSet"); + } + if (!sysRoleService.update(sysRole, originalSysRole, menuIdSet)) { + errorMessage = "更新失败,数据不存在,请刷新后重试!"; + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage); + } + return ResponseResult.success(); + } + + /** + * 删除指定角色操作。 + * + * @param roleId 指定角色主键Id。 + * @return 应答结果对象。 + */ + @PostMapping("/delete") + public ResponseResult delete(@MyRequestBody Long roleId) { + if (MyCommonUtil.existBlankArgument(roleId)) { + return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST); + } + if (!sysRoleService.remove(roleId)) { + String errorMessage = "数据操作失败,角色不存在,请刷新后重试!"; + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage); + } + return ResponseResult.success(); + } + + /** + * 查看角色列表。 + * + * @param sysRoleFilter 角色过滤对象。 + * @param orderParam 排序参数。 + * @param pageParam 分页参数。 + * @return 应答结果对象,包含角色列表。 + */ + @PostMapping("/list") + public ResponseResult list( + @MyRequestBody SysRole sysRoleFilter, + @MyRequestBody MyOrderParam orderParam, + @MyRequestBody MyPageParam pageParam) { + if (pageParam != null) { + PageMethod.startPage(pageParam.getPageNum(), pageParam.getPageSize()); + } + List roleList = sysRoleService.getSysRoleList( + sysRoleFilter, MyOrderParam.buildOrderBy(orderParam, SysRole.class)); + return ResponseResult.success(MyPageUtil.makeResponseData(roleList)); + } + + /** + * 查看角色详情。 + * + * @param roleId 指定角色主键Id。 + * @return 应答结果对象,包含角色详情对象。 + */ + @GetMapping("/view") + public ResponseResult view(@RequestParam Long roleId) { + if (MyCommonUtil.existBlankArgument(roleId)) { + return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST); + } + SysRole sysRole = sysRoleService.getByIdWithRelation(roleId, MyRelationParam.full()); + if (sysRole == null) { + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST); + } + return ResponseResult.success(sysRole); + } + + /** + * 获取不包含指定角色Id的用户列表。 + * 用户和角色是多对多关系,当前接口将返回没有赋值指定RoleId的用户列表。可用于给角色添加新用户。 + * + * @param roleId 角色主键Id。 + * @param sysUserFilter 用户过滤对象。 + * @param orderParam 排序参数。 + * @param pageParam 分页参数。 + * @return 应答结果对象,包含用户列表数据。 + */ + @PostMapping("/listNotInUserRole") + public ResponseResult listNotInUserRole( + @MyRequestBody Long roleId, + @MyRequestBody SysUser sysUserFilter, + @MyRequestBody MyOrderParam orderParam, + @MyRequestBody MyPageParam pageParam) { + ResponseResult verifyResult = this.doRoleUserVerify(roleId); + if (!verifyResult.isSuccess()) { + return ResponseResult.errorFrom(verifyResult); + } + if (pageParam != null) { + PageMethod.startPage(pageParam.getPageNum(), pageParam.getPageSize()); + } + String orderBy = MyOrderParam.buildOrderBy(orderParam, SysUser.class); + List resultList = + sysUserService.getNotInSysUserListByRoleId(roleId, sysUserFilter, orderBy); + JSONObject responseData = MyPageUtil.makeResponseData(resultList); + return ResponseResult.success(responseData); + } + + /** + * 拥有指定角色的用户列表。 + * + * @param roleId 角色主键Id。 + * @param sysUserFilter 用户过滤对象。 + * @param orderParam 排序参数。 + * @param pageParam 分页参数。 + * @return 应答结果对象,包含用户列表数据。 + */ + @PostMapping("/listUserRole") + public ResponseResult listUserRole( + @MyRequestBody Long roleId, + @MyRequestBody SysUser sysUserFilter, + @MyRequestBody MyOrderParam orderParam, + @MyRequestBody MyPageParam pageParam) { + ResponseResult verifyResult = this.doRoleUserVerify(roleId); + if (!verifyResult.isSuccess()) { + return ResponseResult.errorFrom(verifyResult); + } + if (pageParam != null) { + PageMethod.startPage(pageParam.getPageNum(), pageParam.getPageSize()); + } + String orderBy = MyOrderParam.buildOrderBy(orderParam, SysUser.class); + List resultList = sysUserService.getSysUserListByRoleId(roleId, sysUserFilter, orderBy); + JSONObject responseData = MyPageUtil.makeResponseData(resultList); + return ResponseResult.success(responseData); + } + + private ResponseResult doRoleUserVerify(Long roleId) { + if (MyCommonUtil.existBlankArgument(roleId)) { + return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST); + } + if (!sysRoleService.existId(roleId)) { + return ResponseResult.error(ErrorCodeEnum.INVALID_RELATED_RECORD_ID); + } + return ResponseResult.success(); + } + + /** + * 为指定角色添加用户列表。该操作可同时给一批用户赋值角色,并在同一事务内完成。 + * + * @param roleId 角色主键Id。 + * @param userIdListString 逗号分隔的用户Id列表。 + * @return 应答结果对象。 + */ + @PostMapping("/addUserRole") + public ResponseResult addUserRole( + @MyRequestBody Long roleId, @MyRequestBody String userIdListString) { + if (MyCommonUtil.existBlankArgument(roleId, userIdListString)) { + return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST); + } + Set userIdSet = Arrays.stream( + userIdListString.split(",")).map(Long::valueOf).collect(Collectors.toSet()); + if (!sysRoleService.existId(roleId) + || !sysUserService.existUniqueKeyList("userId", userIdSet)) { + return ResponseResult.error(ErrorCodeEnum.INVALID_RELATED_RECORD_ID); + } + List userRoleList = new LinkedList<>(); + for (Long userId : userIdSet) { + SysUserRole userRole = new SysUserRole(); + userRole.setRoleId(roleId); + userRole.setUserId(userId); + userRoleList.add(userRole); + } + sysRoleService.addUserRoleList(userRoleList); + return ResponseResult.success(); + } + + /** + * 为指定用户移除指定角色。 + * + * @param roleId 指定角色主键Id。 + * @param userId 指定用户主键Id。 + * @return 应答数据结果。 + */ + @PostMapping("/deleteUserRole") + public ResponseResult deleteUserRole( + @MyRequestBody Long roleId, @MyRequestBody Long userId) { + if (MyCommonUtil.existBlankArgument(roleId, userId)) { + return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST); + } + if (!sysRoleService.removeUserRole(roleId, userId)) { + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST); + } + return ResponseResult.success(); + } + + /** + * 通过权限字Id获取拥有改权限的所有角色。 + * 开发人员调试用接口。 + * + * @param permCodeId 查询的权限字Id。 + * @param pageParam 分页对象。 + * @return 符合条件的角色列表。 + */ + @PostMapping("/listAllRolesByPermCode") + public ResponseResult listAllRolesByPermCode( + @MyRequestBody Long permCodeId, @MyRequestBody MyPageParam pageParam) { + if (MyCommonUtil.existBlankArgument(permCodeId)) { + return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST); + } + if (pageParam != null) { + PageMethod.startPage(pageParam.getPageNum(), pageParam.getPageSize()); + } + List roleList = sysRoleService.getSysRoleListByPermCodeId(permCodeId); + JSONObject responseData = MyPageUtil.makeResponseData(roleList); + return ResponseResult.success(responseData); + } + + /** + * 通过权限资源url,模糊搜索拥有改权限的所有角色。 + * 开发人员调试用接口。 + * + * @param url 用于模糊搜索的url。 + * @param pageParam 分页对象。 + * @return 符合条件的角色列表。 + */ + @PostMapping("/listAllRolesByPerm") + public ResponseResult listAllRolesByPerm( + @MyRequestBody String url, @MyRequestBody MyPageParam pageParam) { + if (MyCommonUtil.existBlankArgument(url)) { + return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST); + } + if (pageParam != null) { + PageMethod.startPage(pageParam.getPageNum(), pageParam.getPageSize()); + } + List roleList = sysRoleService.getSysRoleListByPerm(url); + JSONObject responseData = MyPageUtil.makeResponseData(roleList); + return ResponseResult.success(responseData); + } +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/controller/SysUserController.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/controller/SysUserController.java new file mode 100644 index 00000000..0546a8d4 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/controller/SysUserController.java @@ -0,0 +1,176 @@ +package com.orange.demo.upms.controller; + +import com.github.pagehelper.page.PageMethod; +import com.orange.demo.upms.model.*; +import com.orange.demo.upms.service.*; +import com.orange.demo.common.core.object.*; +import com.orange.demo.common.core.util.*; +import com.orange.demo.common.core.constant.ErrorCodeEnum; +import com.orange.demo.common.core.annotation.MyRequestBody; +import com.orange.demo.common.core.validator.AddGroup; +import com.orange.demo.common.core.validator.UpdateGroup; +import com.orange.demo.config.ApplicationConfig; +import lombok.extern.slf4j.Slf4j; +import com.alibaba.fastjson.JSONObject; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.*; +import javax.validation.groups.Default; + +/** + * 用户管理操作控制器类。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Slf4j +@RestController +@RequestMapping("/admin/upms/sysUser") +public class SysUserController { + + @Autowired + private SysUserService sysUserService; + @Autowired + private PasswordEncoder passwordEncoder; + @Autowired + private ApplicationConfig appConfig; + + /** + * 新增用户操作。 + * + * @param sysUser 新增用户对象。 + * @param roleIdListString 逗号分隔的角色Id列表。 + * @return 应答结果对象,包含新增用户的主键Id。 + */ + @SuppressWarnings("unchecked") + @PostMapping("/add") + public ResponseResult add(@MyRequestBody SysUser sysUser, @MyRequestBody String roleIdListString) { + String errorMessage = MyCommonUtil.getModelValidationError(sysUser, Default.class, AddGroup.class); + if (errorMessage != null) { + return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATAED_FAILED, errorMessage); + } + CallResult result = sysUserService.verifyRelatedData(sysUser, null, roleIdListString); + if (!result.isSuccess()) { + return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATAED_FAILED, result.getErrorMessage()); + } + Set roleIdSet = (Set) result.getData().get("roleIdSet"); + sysUserService.saveNew(sysUser, roleIdSet); + JSONObject responseData = new JSONObject(); + responseData.put("userId", sysUser.getUserId()); + return ResponseResult.success(responseData); + } + + /** + * 更新用户操作。 + * + * @param sysUser 更新用户对象。 + * @param roleIdListString 逗号分隔的角色Id列表。 + * @return 应答结果对象。 + */ + @SuppressWarnings("unchecked") + @PostMapping("/update") + public ResponseResult update(@MyRequestBody SysUser sysUser, @MyRequestBody String roleIdListString) { + String errorMessage = MyCommonUtil.getModelValidationError(sysUser, Default.class, UpdateGroup.class); + if (errorMessage != null) { + return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATAED_FAILED, errorMessage); + } + SysUser originalUser = sysUserService.getById(sysUser.getUserId()); + if (originalUser == null) { + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST); + } + CallResult result = sysUserService.verifyRelatedData(sysUser, originalUser, roleIdListString); + if (!result.isSuccess()) { + return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATAED_FAILED, result.getErrorMessage()); + } + Set roleIdSet = (Set) result.getData().get("roleIdSet"); + if (!sysUserService.update(sysUser, originalUser, roleIdSet)) { + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST); + } + return ResponseResult.success(); + } + + /** + * 重置密码操作。 + * + * @param userId 指定用户主键Id。 + * @return 应答结果对象。 + */ + @PostMapping("/resetPassword") + public ResponseResult resetPassword(@MyRequestBody Long userId) { + if (MyCommonUtil.existBlankArgument(userId)) { + return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST); + } + if (!sysUserService.changePassword(userId, appConfig.getDefaultUserPassword())) { + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST); + } + return ResponseResult.success(); + } + + /** + * 删除用户管理数据。 + * + * @param userId 删除对象主键Id。 + * @return 应答结果对象。 + */ + @PostMapping("/delete") + public ResponseResult delete(@MyRequestBody Long userId) { + String errorMessage; + if (MyCommonUtil.existBlankArgument(userId)) { + return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST); + } + // 验证关联Id的数据合法性 + SysUser originalSysUser = sysUserService.getById(userId); + if (originalSysUser == null) { + // NOTE: 修改下面方括号中的话述 + errorMessage = "数据验证失败,当前 [对象] 并不存在,请刷新后重试!"; + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage); + } + if (!sysUserService.remove(userId)) { + errorMessage = "数据操作失败,删除的对象不存在,请刷新后重试!"; + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage); + } + return ResponseResult.success(); + } + + /** + * 列出符合过滤条件的用户管理列表。 + * + * @param sysUserFilter 过滤对象。 + * @param orderParam 排序参数。 + * @param pageParam 分页参数。 + * @return 应答结果对象,包含查询结果集。 + */ + @PostMapping("/list") + public ResponseResult list( + @MyRequestBody SysUser sysUserFilter, + @MyRequestBody MyOrderParam orderParam, + @MyRequestBody MyPageParam pageParam) { + if (pageParam != null) { + PageMethod.startPage(pageParam.getPageNum(), pageParam.getPageSize()); + } + String orderBy = MyOrderParam.buildOrderBy(orderParam, SysUser.class); + List resultList = sysUserService.getSysUserListWithRelation(sysUserFilter, orderBy); + return ResponseResult.success(MyPageUtil.makeResponseData(resultList)); + } + + /** + * 查看指定用户管理对象详情。 + * + * @param userId 指定对象主键Id。 + * @return 应答结果对象,包含对象详情。 + */ + @GetMapping("/view") + public ResponseResult view(@RequestParam Long userId) { + if (MyCommonUtil.existBlankArgument(userId)) { + return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST); + } + // 这里查看用户数据时候,需要把用户多对多关联的角色和数据权限Id一并查出。 + SysUser sysUser = sysUserService.getByIdWithRelation(userId, MyRelationParam.full()); + if (sysUser == null) { + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST); + } + return ResponseResult.success(sysUser); + } +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/SysMenuMapper.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/SysMenuMapper.java new file mode 100644 index 00000000..59f04e31 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/SysMenuMapper.java @@ -0,0 +1,23 @@ +package com.orange.demo.upms.dao; + +import com.orange.demo.common.core.base.dao.BaseDaoMapper; +import com.orange.demo.upms.model.SysMenu; + +import java.util.List; + +/** + * 菜单数据访问操作接口。 + * + * @author Jerry + * @date 2020-09-25 + */ +public interface SysMenuMapper extends BaseDaoMapper { + + /** + * 获取登录用户的菜单列表。 + * + * @param userId 登录用户。 + * @return 菜单列表。 + */ + List getMenuListByUserId(Long userId); +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/SysMenuPermCodeMapper.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/SysMenuPermCodeMapper.java new file mode 100644 index 00000000..c4837b37 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/SysMenuPermCodeMapper.java @@ -0,0 +1,13 @@ +package com.orange.demo.upms.dao; + +import com.orange.demo.common.core.base.dao.BaseDaoMapper; +import com.orange.demo.upms.model.SysMenuPermCode; + +/** + * 菜单与权限字关系数据访问操作接口。 + * + * @author Jerry + * @date 2020-09-25 + */ +public interface SysMenuPermCodeMapper extends BaseDaoMapper { +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/SysPermCodeMapper.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/SysPermCodeMapper.java new file mode 100644 index 00000000..96ce0f3c --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/SysPermCodeMapper.java @@ -0,0 +1,43 @@ +package com.orange.demo.upms.dao; + +import com.orange.demo.common.core.base.dao.BaseDaoMapper; +import com.orange.demo.upms.model.SysPermCode; +import org.apache.ibatis.annotations.Param; + +import java.util.List; +import java.util.Map; + +/** + * 权限字数据访问操作接口。 + * + * @author Jerry + * @date 2020-09-25 + */ +public interface SysPermCodeMapper extends BaseDaoMapper { + + /** + * 获取用户的所有权限字列表。 + * + * @param userId 用户Id。 + * @return 该用户的权限字列表。 + */ + List getPermCodeListByUserId(Long userId); + + /** + * 获取该菜单的权限字和关联的权限资源列表。 + * + * @param menuId 菜单Id。 + * @return 权限字和关联的权限资源列表。 + */ + List> getPermCodeListByMenuId(Long menuId); + + /** + * 获取指定用户的权限字列表。 + * + * @param loginName 精确匹配用户登录名。 + * @param permCode 模糊匹配的权限字名,LIKE %permCode%。 + * @return 权限字列表。 + */ + List getUserPermCodeListByFilter( + @Param("loginName") String loginName, @Param("permCode") String permCode); +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/SysPermCodePermMapper.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/SysPermCodePermMapper.java new file mode 100644 index 00000000..cd55d331 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/SysPermCodePermMapper.java @@ -0,0 +1,13 @@ +package com.orange.demo.upms.dao; + +import com.orange.demo.common.core.base.dao.BaseDaoMapper; +import com.orange.demo.upms.model.SysPermCodePerm; + +/** + * 权限字与权限资源关系数据访问操作接口。 + * + * @author Jerry + * @date 2020-09-25 + */ +public interface SysPermCodePermMapper extends BaseDaoMapper { +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/SysPermMapper.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/SysPermMapper.java new file mode 100644 index 00000000..57de97e1 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/SysPermMapper.java @@ -0,0 +1,61 @@ +package com.orange.demo.upms.dao; + +import com.orange.demo.common.core.base.dao.BaseDaoMapper; +import com.orange.demo.upms.model.SysPerm; +import org.apache.ibatis.annotations.Param; + +import java.util.List; +import java.util.Map; + +/** + * 权限资源数据访问操作接口。 + * + * @author Jerry + * @date 2020-09-25 + */ +public interface SysPermMapper extends BaseDaoMapper { + + /** + * 获取用户的权限列表。 + * + * @param userId 用户Id。 + * @return 该用户的权限标识列表。 + */ + List getPermListByUserId(@Param("userId") Long userId); + + /** + * 获取指定用户Id的权限列表。 + * + * @param loginName 精确匹配用户登录名。 + * @param moduleId 精确匹配权限模块Id。 + * @param url 权限的url过滤条件,LIKE %url%。 + * @return 权限列表。 + */ + List> getUserPermListByFilter( + @Param("loginName") String loginName, @Param("moduleId") Long moduleId, @Param("url") String url); + + /** + * 根据关联权限字主键Id,获取权限资源数据列表。 + * + * @param permCodeId 关联权限字主键Id。 + * @param orderBy 排序字符串,ORDER BY从句的参数。 + * @return 从表数据列表。 + */ + List getPermListByPermCodeId(@Param("permCodeId") Long permCodeId, @Param("orderBy") String orderBy); + + /** + * 获取指定权限的用户列表。 + * + * @param permId 指定权限。 + * @return 用户列表。 + */ + List> getPermUserListById(@Param("permId") Long permId); + + /** + * 获取指定权限的角色列表。 + * + * @param permId 指定权限。 + * @return 角色列表。 + */ + List> getPermRoleListById(@Param("permId") Long permId); +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/SysPermModuleMapper.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/SysPermModuleMapper.java new file mode 100644 index 00000000..80a4d90e --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/SysPermModuleMapper.java @@ -0,0 +1,22 @@ +package com.orange.demo.upms.dao; + +import com.orange.demo.common.core.base.dao.BaseDaoMapper; +import com.orange.demo.upms.model.SysPermModule; + +import java.util.List; + +/** + * 权限资源模块数据访问操作接口。 + * + * @author Jerry + * @date 2020-09-25 + */ +public interface SysPermModuleMapper extends BaseDaoMapper { + + /** + * 获取整个权限模块和权限关联后的全部数据。 + * + * @return 关联的权限模块和权限资源列表。 + */ + List getPermModuleAndPermList(); +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/SysPermWhitelistMapper.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/SysPermWhitelistMapper.java new file mode 100644 index 00000000..e2d3b618 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/SysPermWhitelistMapper.java @@ -0,0 +1,13 @@ +package com.orange.demo.upms.dao; + +import com.orange.demo.common.core.base.dao.BaseDaoMapper; +import com.orange.demo.upms.model.SysPermWhitelist; + +/** + * 权限资源白名单数据访问操作接口。 + * + * @author Jerry + * @date 2020-09-25 + */ +public interface SysPermWhitelistMapper extends BaseDaoMapper { +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/SysRoleMapper.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/SysRoleMapper.java new file mode 100644 index 00000000..c15ee2fb --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/SysRoleMapper.java @@ -0,0 +1,41 @@ +package com.orange.demo.upms.dao; + +import com.orange.demo.common.core.base.dao.BaseDaoMapper; +import com.orange.demo.upms.model.SysRole; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 角色数据访问操作接口。 + * + * @author Jerry + * @date 2020-09-25 + */ +public interface SysRoleMapper extends BaseDaoMapper { + + /** + * 获取对象列表,过滤条件中包含like和between条件。 + * + * @param sysRoleFilter 过滤对象。 + * @param orderBy 排序字符串,order by从句的参数。 + * @return 对象列表。 + */ + List getSysRoleList(@Param("sysRoleFilter") SysRole sysRoleFilter, @Param("orderBy") String orderBy); + + /** + * 根据权限字Id获取关联的角色列表。 + * + * @param permCodeId 权限字Id。 + * @return 关联的角色列表。 + */ + List getSysRoleListByPermCodeId(@Param("permCodeId") Long permCodeId); + + /** + * 根据url模糊查询关联的角色列表。 + * + * @param url url片段。 + * @return 关联的角色列表。 + */ + List getSysRoleListByPerm(@Param("url") String url); +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/SysRoleMenuMapper.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/SysRoleMenuMapper.java new file mode 100644 index 00000000..891bc0c8 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/SysRoleMenuMapper.java @@ -0,0 +1,13 @@ +package com.orange.demo.upms.dao; + +import com.orange.demo.common.core.base.dao.BaseDaoMapper; +import com.orange.demo.upms.model.SysRoleMenu; + +/** + * 角色与菜单操作关联关系数据访问操作接口。 + * + * @author Jerry + * @date 2020-09-25 + */ +public interface SysRoleMenuMapper extends BaseDaoMapper { +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/SysUserMapper.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/SysUserMapper.java new file mode 100644 index 00000000..b08bc925 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/SysUserMapper.java @@ -0,0 +1,52 @@ +package com.orange.demo.upms.dao; + +import com.orange.demo.common.core.base.dao.BaseDaoMapper; +import com.orange.demo.upms.model.SysUser; +import org.apache.ibatis.annotations.Param; + +import java.util.*; + +/** + * 用户管理数据操作访问接口。 + * + * @author Jerry + * @date 2020-09-25 + */ +public interface SysUserMapper extends BaseDaoMapper { + + /** + * 获取过滤后的对象列表。 + * + * @param sysUserFilter 主表过滤对象。 + * @param orderBy 排序字符串,order by从句的参数。 + * @return 对象列表。 + */ + List getSysUserList( + @Param("sysUserFilter") SysUser sysUserFilter, @Param("orderBy") String orderBy); + + /** + * 根据角色Id,获取关联的用户Id列表。 + * + * @param roleId 关联的角色Id。 + * @param sysUserFilter 用户过滤条件对象。 + * @param orderBy order by从句的参数。 + * @return 和RoleId关联的用户列表。 + */ + List getSysUserListByRoleId( + @Param("roleId") Long roleId, + @Param("sysUserFilter") SysUser sysUserFilter, + @Param("orderBy") String orderBy); + + /** + * 根据角色Id,获取和当前角色Id没有建立多对多关联关系的用户Id列表。 + * + * @param roleId 关联的角色Id。 + * @param sysUserFilter 用户过滤条件对象。 + * @param orderBy order by从句的参数。 + * @return 和RoleId没有建立关联关系的用户列表。 + */ + List getNotInSysUserListByRoleId( + @Param("roleId") Long roleId, + @Param("sysUserFilter") SysUser sysUserFilter, + @Param("orderBy") String orderBy); +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/SysUserRoleMapper.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/SysUserRoleMapper.java new file mode 100644 index 00000000..320a6bf9 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/SysUserRoleMapper.java @@ -0,0 +1,22 @@ +package com.orange.demo.upms.dao; + +import com.orange.demo.common.core.base.dao.BaseDaoMapper; +import com.orange.demo.upms.model.SysUserRole; + +import java.util.List; + +/** + * 用户与角色关联关系数据访问操作接口。 + * + * @author Jerry + * @date 2020-09-25 + */ +public interface SysUserRoleMapper extends BaseDaoMapper { + + /** + * 批量插入用户角色信息,如果用户角色已经存在,则不会重复插入。 + * + * @param userRoleList 待插入的角色用户列表。 + */ + void addUserRoleList(List userRoleList); +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/mapper/SysMenuMapper.xml b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/mapper/SysMenuMapper.xml new file mode 100644 index 00000000..60db0f8c --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/mapper/SysMenuMapper.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/mapper/SysMenuPermCodeMapper.xml b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/mapper/SysMenuPermCodeMapper.xml new file mode 100644 index 00000000..23965546 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/mapper/SysMenuPermCodeMapper.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/mapper/SysPermCodeMapper.xml b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/mapper/SysPermCodeMapper.xml new file mode 100644 index 00000000..989a2bcf --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/mapper/SysPermCodeMapper.xml @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/mapper/SysPermCodePermMapper.xml b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/mapper/SysPermCodePermMapper.xml new file mode 100644 index 00000000..e93dc650 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/mapper/SysPermCodePermMapper.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/mapper/SysPermMapper.xml b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/mapper/SysPermMapper.xml new file mode 100644 index 00000000..f1987410 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/mapper/SysPermMapper.xml @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/mapper/SysPermModuleMapper.xml b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/mapper/SysPermModuleMapper.xml new file mode 100644 index 00000000..265dba8c --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/mapper/SysPermModuleMapper.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/mapper/SysPermWhitelistMapper.xml b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/mapper/SysPermWhitelistMapper.xml new file mode 100644 index 00000000..e5bd6be9 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/mapper/SysPermWhitelistMapper.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/mapper/SysRoleMapper.xml b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/mapper/SysRoleMapper.xml new file mode 100644 index 00000000..495e41ad --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/mapper/SysRoleMapper.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/mapper/SysRoleMenuMapper.xml b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/mapper/SysRoleMenuMapper.xml new file mode 100644 index 00000000..62b6cc83 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/mapper/SysRoleMenuMapper.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/mapper/SysUserMapper.xml b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/mapper/SysUserMapper.xml new file mode 100644 index 00000000..0ded7457 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/mapper/SysUserMapper.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + AND zz_sys_user.login_name LIKE #{safeLoginName} + + + + AND zz_sys_user.show_name LIKE #{safeShowName} + + + AND zz_sys_user.user_status = #{sysUserFilter.userStatus} + + + AND zz_sys_user.create_time >= #{sysUserFilter.createTimeStart} + + + AND zz_sys_user.create_time <= #{sysUserFilter.createTimeEnd} + + + AND zz_sys_user.deleted_flag = ${@com.orange.demo.common.core.constant.GlobalDeletedFlag@NORMAL} + + + + + + + + diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/mapper/SysUserRoleMapper.xml b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/mapper/SysUserRoleMapper.xml new file mode 100644 index 00000000..b8e5f287 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/dao/mapper/SysUserRoleMapper.xml @@ -0,0 +1,15 @@ + + + + + + + + + + REPLACE INTO zz_sys_user_role(user_id, role_id) VALUES + + (#{item.userId}, #{item.roleId}) + + + diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/SysMenu.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/SysMenu.java new file mode 100644 index 00000000..a622f775 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/SysMenu.java @@ -0,0 +1,93 @@ +package com.orange.demo.upms.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.orange.demo.common.core.annotation.DeletedFlagColumn; +import com.orange.demo.common.core.annotation.RelationManyToMany; +import com.orange.demo.common.core.validator.ConstDictRef; +import com.orange.demo.common.core.validator.UpdateGroup; +import com.orange.demo.upms.model.constant.SysMenuType; +import lombok.Data; + +import javax.persistence.*; +import javax.validation.constraints.*; +import java.util.Date; +import java.util.List; + +/** + * 菜单实体对象。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Data +@Table(name = "zz_sys_menu") +public class SysMenu { + + /** + * 主键Id。 + */ + @NotNull(message = "菜单Id不能为空!", groups = {UpdateGroup.class}) + @Id + @Column(name = "menu_id") + private Long menuId; + + /** + * 父菜单Id,目录菜单的父菜单为null。 + */ + @Column(name = "parent_id") + private Long parentId; + + /** + * 菜单显示名称。 + */ + @NotBlank(message = "菜单显示名称不能为空!") + @Column(name = "menu_name") + private String menuName; + + /** + * 菜单类型(0: 目录 1: 菜单 2: 按钮 3: UI片段)。 + */ + @NotNull(message = "菜单类型不能为空!") + @ConstDictRef(constDictClass = SysMenuType.class, message = "数据验证失败,菜单类型为无效值!") + @Column(name = "menu_type") + private Integer menuType; + + /** + * 前端表单路由名称,仅用于menu_type为1的菜单类型。 + */ + @Column(name = "form_router_name") + private String formRouterName; + + /** + * 菜单显示顺序 (值越小,排序越靠前)。 + */ + @NotNull(message = "菜单显示顺序不能为空!") + @Column(name = "show_order") + private Integer showOrder; + + /** + * 菜单图标。 + */ + private String icon; + + /** + * 创建时间。 + */ + @Column(name = "create_time") + private Date createTime; + + /** + * 逻辑删除标记字段(1: 正常 -1: 已删除)。 + */ + @JSONField(serialize = false) + @DeletedFlagColumn + @Column(name = "deleted_flag") + private Integer deletedFlag; + + @RelationManyToMany( + relationMapperName = "sysMenuPermCodeMapper", + relationMasterIdField = "menuId", + relationModelClass = SysMenuPermCode.class) + @Transient + private List sysMenuPermCodeList; +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/SysMenuPermCode.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/SysMenuPermCode.java new file mode 100644 index 00000000..27460ab5 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/SysMenuPermCode.java @@ -0,0 +1,30 @@ +package com.orange.demo.upms.model; + +import lombok.Data; + +import javax.persistence.*; + +/** + * 菜单与权限字关联实体对象。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Data +@Table(name = "zz_sys_menu_perm_code") +public class SysMenuPermCode { + + /** + * 关联菜单Id。 + */ + @Id + @Column(name = "menu_id") + private Long menuId; + + /** + * 关联权限字Id。 + */ + @Id + @Column(name = "perm_code_id") + private Long permCodeId; +} \ No newline at end of file diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/SysPerm.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/SysPerm.java new file mode 100644 index 00000000..3e9e7401 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/SysPerm.java @@ -0,0 +1,81 @@ +package com.orange.demo.upms.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.orange.demo.common.core.annotation.DeletedFlagColumn; +import com.orange.demo.common.core.annotation.RelationDict; +import com.orange.demo.common.core.validator.UpdateGroup; +import lombok.Data; + +import javax.persistence.*; +import javax.validation.constraints.*; +import java.util.Date; +import java.util.Map; + +/** + * 权限资源实体对象。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Data +@Table(name = "zz_sys_perm") +public class SysPerm { + + /** + * 权限Id。 + */ + @NotNull(message = "权限Id不能为空!", groups = {UpdateGroup.class}) + @Id + @Column(name = "perm_id") + private Long permId; + + /** + * 权限所在的权限模块Id。 + */ + @NotNull(message = "权限模块Id不能为空!") + @Column(name = "module_id") + private Long moduleId; + + /** + * 权限名称。 + */ + @NotBlank(message = "权限名称不能为空!") + @Column(name = "perm_name") + private String permName; + + /** + * 关联的URL。 + */ + @NotBlank(message = "权限关联的url不能为空!") + private String url; + + /** + * 权限在当前模块下的顺序,由小到大。 + */ + @NotNull(message = "权限显示顺序不能为空!") + @Column(name = "show_order") + private Integer showOrder; + + /** + * 创建时间。 + */ + @Column(name = "create_time") + private Date createTime; + + /** + * 逻辑删除标记字段(1: 正常 -1: 已删除)。 + */ + @JSONField(serialize = false) + @DeletedFlagColumn + @Column(name = "deleted_flag") + private Integer deletedFlag; + + @RelationDict( + masterIdField = "moduleId", + slaveServiceName = "SysPermModuleService", + slaveModelClass = SysPermModule.class, + slaveIdField = "moduleId", + slaveNameField = "moduleName") + @Transient + private Map moduleIdDictMap; +} \ No newline at end of file diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/SysPermCode.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/SysPermCode.java new file mode 100644 index 00000000..25fb48bc --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/SysPermCode.java @@ -0,0 +1,89 @@ +package com.orange.demo.upms.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.orange.demo.common.core.annotation.DeletedFlagColumn; +import com.orange.demo.common.core.annotation.RelationManyToMany; +import com.orange.demo.common.core.validator.ConstDictRef; +import com.orange.demo.common.core.validator.UpdateGroup; +import com.orange.demo.upms.model.constant.SysPermCodeType; +import lombok.Data; + +import javax.persistence.*; +import javax.validation.constraints.*; +import java.util.Date; +import java.util.List; + +/** + * 权限字实体对象。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Data +@Table(name = "zz_sys_perm_code") +public class SysPermCode { + + /** + * 主键Id。 + */ + @NotNull(message = "权限字Id不能为空!", groups = {UpdateGroup.class}) + @Id + @Column(name = "perm_code_id") + private Long permCodeId; + + /** + * 上级权限字Id。 + */ + @Column(name = "parent_id") + private Long parentId; + + /** + * 权限字标识(一般为有含义的英文字符串)。 + */ + @NotBlank(message = "权限字编码不能为空!") + @Column(name = "perm_code") + private String permCode; + + /** + * 权限类型(0: 表单 1: UI片段 2: 操作)。 + */ + @NotNull(message = "权限字类型不能为空!") + @ConstDictRef(constDictClass = SysPermCodeType.class, message = "数据验证失败,权限类型为无效值!") + @Column(name = "perm_code_type") + private Integer permCodeType; + + /** + * 显示名称。 + */ + @NotBlank(message = "权限字显示名称不能为空!") + @Column(name = "show_name") + private String showName; + + /** + * 显示顺序(数值越小,越靠前)。 + */ + @NotNull(message = "权限字显示顺序不能为空!") + @Column(name = "show_order") + private Integer showOrder; + + /** + * 创建时间。 + */ + @Column(name = "create_time") + private Date createTime; + + /** + * 逻辑删除标记字段(1: 正常 -1: 已删除)。 + */ + @JSONField(serialize = false) + @DeletedFlagColumn + @Column(name = "deleted_flag") + private Integer deletedFlag; + + @RelationManyToMany( + relationMapperName = "sysPermCodePermMapper", + relationMasterIdField = "permCodeId", + relationModelClass = SysPermCodePerm.class) + @Transient + private List sysPermCodePermList; +} \ No newline at end of file diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/SysPermCodePerm.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/SysPermCodePerm.java new file mode 100644 index 00000000..befa7caf --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/SysPermCodePerm.java @@ -0,0 +1,30 @@ +package com.orange.demo.upms.model; + +import lombok.Data; + +import javax.persistence.*; + +/** + * 权限字与权限资源关联实体对象。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Data +@Table(name = "zz_sys_perm_code_perm") +public class SysPermCodePerm { + + /** + * 权限字Id。 + */ + @Id + @Column(name = "perm_code_id") + private Long permCodeId; + + /** + * 权限Id。 + */ + @Id + @Column(name = "perm_id") + private Long permId; +} \ No newline at end of file diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/SysPermModule.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/SysPermModule.java new file mode 100644 index 00000000..9ad50c2e --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/SysPermModule.java @@ -0,0 +1,77 @@ +package com.orange.demo.upms.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.orange.demo.common.core.annotation.DeletedFlagColumn; +import com.orange.demo.common.core.validator.ConstDictRef; +import com.orange.demo.common.core.validator.UpdateGroup; +import com.orange.demo.upms.model.constant.SysPermModuleType; +import lombok.Data; + +import javax.persistence.*; +import javax.validation.constraints.*; +import java.util.Date; +import java.util.List; + +/** + * 权限模块实体对象。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Data +@Table(name = "zz_sys_perm_module") +public class SysPermModule { + + /** + * 权限模块Id。 + */ + @NotNull(message = "权限模块Id不能为空!", groups = {UpdateGroup.class}) + @Id + @Column(name = "module_id") + private Long moduleId; + + /** + * 上级权限模块Id。 + */ + @Column(name = "parent_id") + private Long parentId; + + /** + * 权限模块名称。 + */ + @NotBlank(message = "权限模块名称不能为空!") + @Column(name = "module_name") + private String moduleName; + + /** + * 权限模块类型(0: 普通模块 1: Controller模块)。 + */ + @NotNull(message = "模块类型不能为空!") + @ConstDictRef(constDictClass = SysPermModuleType.class, message = "数据验证失败,权限模块类型为无效值!") + @Column(name = "module_type") + private Integer moduleType; + + /** + * 权限模块在当前层级下的顺序,由小到大。 + */ + @NotNull(message = "权限模块显示顺序不能为空!") + @Column(name = "show_order") + private Integer showOrder; + + /** + * 创建时间。 + */ + @Column(name = "create_time") + private Date createTime; + + /** + * 逻辑删除标记字段(1: 正常 -1: 已删除)。 + */ + @JSONField(serialize = false) + @DeletedFlagColumn + @Column(name = "deleted_flag") + private Integer deletedFlag; + + @Transient + private List sysPermList; +} \ No newline at end of file diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/SysPermWhitelist.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/SysPermWhitelist.java new file mode 100644 index 00000000..d60ac331 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/SysPermWhitelist.java @@ -0,0 +1,35 @@ +package com.orange.demo.upms.model; + +import lombok.Data; + +import javax.persistence.*; + +/** + * 白名单实体对象。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Data +@Table(name = "zz_sys_perm_whitelist") +public class SysPermWhitelist { + + /** + * 权限资源的URL。 + */ + @Id + @Column(name = "perm_url") + private String permUrl; + + /** + * 权限资源所属模块名字(通常是Controller的名字)。 + */ + @Column(name = "module_name") + private String moduleName; + + /** + * 权限的名称。 + */ + @Column(name = "perm_name") + private String permName; +} \ No newline at end of file diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/SysRole.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/SysRole.java new file mode 100644 index 00000000..77195cf4 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/SysRole.java @@ -0,0 +1,83 @@ +package com.orange.demo.upms.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.orange.demo.common.core.annotation.DeletedFlagColumn; +import com.orange.demo.common.core.annotation.RelationManyToMany; +import com.orange.demo.common.core.validator.UpdateGroup; +import lombok.Data; + +import javax.persistence.*; +import javax.validation.constraints.*; +import java.util.Date; +import java.util.List; + +/** + * 角色实体对象。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Data +@Table(name = "zz_sys_role") +public class SysRole { + + /** + * 主键Id。 + */ + @NotNull(message = "角色Id不能为空!", groups = {UpdateGroup.class}) + @Id + @Column(name = "role_id") + private Long roleId; + + /** + * 角色名称。 + */ + @NotBlank(message = "角色名称不能为空!") + @Column(name = "role_name") + private String roleName; + + /** + * 创建者。 + */ + @Column(name = "create_user_id") + private Long createUserId; + + /** + * 创建者显示名称。 + */ + @Column(name = "create_username") + private String createUsername; + + /** + * 创建时间。 + */ + @Column(name = "create_time") + private Date createTime; + + /** + * 更新时间。 + */ + @Column(name = "update_time") + private Date updateTime; + + /** + * 逻辑删除标记字段(1: 正常 -1: 已删除)。 + */ + @JSONField(serialize = false) + @DeletedFlagColumn + @Column(name = "deleted_flag") + private Integer deletedFlag; + + @RelationManyToMany( + relationMapperName = "sysRoleMenuMapper", + relationMasterIdField = "roleId", + relationModelClass = SysRoleMenu.class) + @Transient + private List sysRoleMenuList; + + @Transient + private String createTimeStart; + + @Transient + private String createTimeEnd; +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/SysRoleMenu.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/SysRoleMenu.java new file mode 100644 index 00000000..e5a4e1d8 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/SysRoleMenu.java @@ -0,0 +1,30 @@ +package com.orange.demo.upms.model; + +import lombok.Data; + +import javax.persistence.*; + +/** + * 角色菜单实体对象。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Data +@Table(name = "zz_sys_role_menu") +public class SysRoleMenu { + + /** + * 角色Id。 + */ + @Id + @Column(name = "role_id") + private Long roleId; + + /** + * 菜单Id。 + */ + @Id + @Column(name = "menu_id") + private Long menuId; +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/SysUser.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/SysUser.java new file mode 100644 index 00000000..1b62008b --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/SysUser.java @@ -0,0 +1,145 @@ +package com.orange.demo.upms.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.orange.demo.upms.model.constant.SysUserType; +import com.orange.demo.upms.model.constant.SysUserStatus; +import com.orange.demo.common.core.annotation.RelationConstDict; +import com.orange.demo.common.core.annotation.RelationManyToMany; +import com.orange.demo.common.core.annotation.DeletedFlagColumn; +import com.orange.demo.common.core.validator.AddGroup; +import com.orange.demo.common.core.validator.UpdateGroup; +import com.orange.demo.common.core.validator.ConstDictRef; +import lombok.Data; +import javax.persistence.*; +import javax.validation.constraints.*; + +import java.util.Date; +import java.util.Map; +import java.util.List; + +/** + * SysUser实体对象。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Data +@Table(name = "zz_sys_user") +public class SysUser { + + /** + * 用户Id。 + */ + @NotNull(message = "数据验证失败,用户Id不能为空!", groups = {UpdateGroup.class}) + @Id + @Column(name = "user_id") + private Long userId; + + /** + * 登录用户名。 + */ + @NotBlank(message = "数据验证失败,登录用户名不能为空!") + @Column(name = "login_name") + private String loginName; + + /** + * 用户密码。 + */ + @NotBlank(message = "数据验证失败,用户密码不能为空!", groups = {AddGroup.class}) + private String password; + + /** + * 用户显示名称。 + */ + @NotBlank(message = "数据验证失败,用户显示名称不能为空!") + @Column(name = "show_name") + private String showName; + + /** + * 用户类型(0: 管理员 1: 系统管理用户 2: 系统业务用户)。 + */ + @NotNull(message = "数据验证失败,用户类型(0: 管理员 1: 系统管理用户 2: 系统业务用户)不能为空!") + @ConstDictRef(constDictClass = SysUserType.class, message = "数据验证失败,用户类型(0: 管理员 1: 系统管理用户 2: 系统业务用户)为无效值!") + @Column(name = "user_type") + private Integer userType; + + /** + * 用户头像的Url。 + */ + @Column(name = "head_image_url") + private String headImageUrl; + + /** + * 用户状态(0: 正常 1: 锁定)。 + */ + @NotNull(message = "数据验证失败,用户状态(0: 正常 1: 锁定)不能为空!") + @ConstDictRef(constDictClass = SysUserStatus.class, message = "数据验证失败,用户状态(0: 正常 1: 锁定)为无效值!") + @Column(name = "user_status") + private Integer userStatus; + + /** + * 逻辑删除标记字段(1: 正常 -1: 已删除)。 + */ + @JSONField(serialize = false) + @DeletedFlagColumn + @Column(name = "deleted_flag") + private Integer deletedFlag; + + /** + * 创建用户Id。 + */ + @Column(name = "create_user_id") + private Long createUserId; + + /** + * 创建用户名。 + */ + @Column(name = "create_username") + private String createUsername; + + /** + * 创建时间。 + */ + @Column(name = "create_time") + private Date createTime; + + /** + * 更新时间。 + */ + @Column(name = "update_time") + private Date updateTime; + + /** + * createTime 范围过滤起始值(>=)。 + */ + @Transient + private String createTimeStart; + + /** + * createTime 范围过滤结束值(<=)。 + */ + @Transient + private String createTimeEnd; + + /** + * 多对多用户角色数据集合。 + */ + @RelationManyToMany( + relationMapperName = "sysUserRoleMapper", + relationMasterIdField = "userId", + relationModelClass = SysUserRole.class) + @Transient + private List sysUserRoleList; + + @RelationConstDict( + masterIdField = "userType", + constantDictClass = SysUserType.class) + @Transient + private Map userTypeDictMap; + + @RelationConstDict( + masterIdField = "userStatus", + constantDictClass = SysUserStatus.class) + @Transient + private Map userStatusDictMap; +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/SysUserRole.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/SysUserRole.java new file mode 100644 index 00000000..e1ecb088 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/SysUserRole.java @@ -0,0 +1,30 @@ +package com.orange.demo.upms.model; + +import lombok.Data; + +import javax.persistence.*; + +/** + * 用户角色实体对象。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Data +@Table(name = "zz_sys_user_role") +public class SysUserRole { + + /** + * 用户Id。 + */ + @Id + @Column(name = "user_id") + private Long userId; + + /** + * 角色Id。 + */ + @Id + @Column(name = "role_id") + private Long roleId; +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/constant/SysMenuType.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/constant/SysMenuType.java new file mode 100644 index 00000000..9aa83c68 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/constant/SysMenuType.java @@ -0,0 +1,54 @@ +package com.orange.demo.upms.model.constant; + +import java.util.HashMap; +import java.util.Map; + +/** + * 菜单类型常量对象。 + * + * @author Jerry + * @date 2020-09-25 + */ +public final class SysMenuType { + + /** + * 目录菜单。 + */ + public static final int TYPE_DIRECTORY = 0; + /** + * 普通菜单。 + */ + public static final int TYPE_MENU = 1; + /** + * 表单片段类型。 + */ + public static final int TYPE_UI_FRAGMENT = 2; + /** + * 按钮类型。 + */ + public static final int TYPE_BUTTON = 3; + + private static final Map DICT_MAP = new HashMap<>(4); + static { + DICT_MAP.put(0, "目录菜单"); + DICT_MAP.put(1, "普通菜单"); + DICT_MAP.put(2, "表单片段类型"); + DICT_MAP.put(3, "按钮类型"); + } + + /** + * 判断参数是否为当前常量字典的合法值。 + * + * @param value 待验证的参数值。 + * @return 合法返回true,否则false。 + */ + public static boolean isValid(Integer value) { + return value != null && DICT_MAP.containsKey(value); + } + + /** + * 私有构造函数,明确标识该常量类的作用。 + */ + private SysMenuType() { + } +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/constant/SysPermCodeType.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/constant/SysPermCodeType.java new file mode 100644 index 00000000..2906a0d4 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/constant/SysPermCodeType.java @@ -0,0 +1,49 @@ +package com.orange.demo.upms.model.constant; + +import java.util.HashMap; +import java.util.Map; + +/** + * 权限字类型常量对象。 + * + * @author Jerry + * @date 2020-09-25 + */ +public final class SysPermCodeType { + + /** + * 表单权限字。 + */ + public static final int TYPE_FORM = 0; + /** + * 表单片段布局权限字。 + */ + public static final int TYPE_FRAGMENT = 1; + /** + * 操作权限字。 + */ + public static final int TYPE_OPERATION = 2; + + private static final Map DICT_MAP = new HashMap<>(3); + static { + DICT_MAP.put(0, "表单权限字"); + DICT_MAP.put(1, "表单片段布局权限字"); + DICT_MAP.put(2, "操作权限字"); + } + + /** + * 判断参数是否为当前常量字典的合法值。 + * + * @param value 待验证的参数值。 + * @return 合法返回true,否则false。 + */ + public static boolean isValid(Integer value) { + return value != null && DICT_MAP.containsKey(value); + } + + /** + * 私有构造函数,明确标识该常量类的作用。 + */ + private SysPermCodeType() { + } +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/constant/SysPermModuleType.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/constant/SysPermModuleType.java new file mode 100644 index 00000000..0a92d0cd --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/constant/SysPermModuleType.java @@ -0,0 +1,44 @@ +package com.orange.demo.upms.model.constant; + +import java.util.HashMap; +import java.util.Map; + +/** + * 权限资源模块类型常量对象。 + * + * @author Jerry + * @date 2020-09-25 + */ +public final class SysPermModuleType { + + /** + * 普通模块。 + */ + public static final int TYPE_NORMAL = 0; + /** + * controller接口模块。 + */ + public static final int TYPE_CONTROLLER = 1; + + private static final Map DICT_MAP = new HashMap<>(2); + static { + DICT_MAP.put(0, "普通模块"); + DICT_MAP.put(1, "controller接口模块"); + } + + /** + * 判断参数是否为当前常量字典的合法值。 + * + * @param value 待验证的参数值。 + * @return 合法返回true,否则false。 + */ + public static boolean isValid(Integer value) { + return value != null && DICT_MAP.containsKey(value); + } + + /** + * 私有构造函数,明确标识该常量类的作用。 + */ + private SysPermModuleType() { + } +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/constant/SysUserStatus.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/constant/SysUserStatus.java new file mode 100644 index 00000000..7e30b773 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/constant/SysUserStatus.java @@ -0,0 +1,44 @@ +package com.orange.demo.upms.model.constant; + +import java.util.HashMap; +import java.util.Map; + +/** + * 用户状态常量字典对象。 + * + * @author Jerry + * @date 2020-09-25 + */ +public final class SysUserStatus { + + /** + * 正常状态。 + */ + public static final int STATUS_NORMAL = 0; + /** + * 锁定状态。 + */ + public static final int STATUS_LOCKED = 1; + + private static final Map DICT_MAP = new HashMap<>(2); + static { + DICT_MAP.put(STATUS_NORMAL, "正常状态"); + DICT_MAP.put(STATUS_LOCKED, "锁定状态"); + } + + /** + * 判断参数是否为当前常量字典的合法值。 + * + * @param value 待验证的参数值。 + * @return 合法返回true,否则false。 + */ + public static boolean isValid(Integer value) { + return value != null && DICT_MAP.containsKey(value); + } + + /** + * 私有构造函数,明确标识该常量类的作用。 + */ + private SysUserStatus() { + } +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/constant/SysUserType.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/constant/SysUserType.java new file mode 100644 index 00000000..28444e4a --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/model/constant/SysUserType.java @@ -0,0 +1,49 @@ +package com.orange.demo.upms.model.constant; + +import java.util.HashMap; +import java.util.Map; + +/** + * 用户类型常量字典对象。 + * + * @author Jerry + * @date 2020-09-25 + */ +public final class SysUserType { + + /** + * 管理员。 + */ + public static final int TYPE_ADMIN = 0; + /** + * 系统操作员。 + */ + public static final int TYPE_SYSTEM = 1; + /** + * 普通操作员。 + */ + public static final int TYPE_OPERATOR = 2; + + private static final Map DICT_MAP = new HashMap<>(3); + static { + DICT_MAP.put(TYPE_ADMIN, "管理员"); + DICT_MAP.put(TYPE_SYSTEM, "系统操作员"); + DICT_MAP.put(TYPE_OPERATOR, "普通操作员"); + } + + /** + * 判断参数是否为当前常量字典的合法值。 + * + * @param value 待验证的参数值。 + * @return 合法返回true,否则false。 + */ + public static boolean isValid(Integer value) { + return value != null && DICT_MAP.containsKey(value); + } + + /** + * 私有构造函数,明确标识该常量类的作用。 + */ + private SysUserType() { + } +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/service/SysMenuService.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/service/SysMenuService.java new file mode 100644 index 00000000..a19fa91f --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/service/SysMenuService.java @@ -0,0 +1,234 @@ +package com.orange.demo.upms.service; + +import com.alibaba.fastjson.JSONObject; +import com.orange.demo.common.core.base.service.BaseService; +import com.orange.demo.common.sequence.wrapper.IdGeneratorWrapper; +import com.orange.demo.common.core.base.dao.BaseDaoMapper; +import com.orange.demo.common.core.constant.GlobalDeletedFlag; +import com.orange.demo.common.core.object.CallResult; +import com.orange.demo.upms.dao.SysMenuMapper; +import com.orange.demo.upms.dao.SysMenuPermCodeMapper; +import com.orange.demo.upms.dao.SysRoleMenuMapper; +import com.orange.demo.upms.model.SysMenu; +import com.orange.demo.upms.model.SysMenuPermCode; +import com.orange.demo.upms.model.SysRoleMenu; +import com.orange.demo.upms.model.constant.SysMenuType; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import tk.mybatis.mapper.entity.Example; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * 菜单数据服务类。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Service +public class SysMenuService extends BaseService { + + @Autowired + private SysMenuMapper sysMenuMapper; + @Autowired + private SysRoleMenuMapper sysRoleMenuMapper; + @Autowired + private SysMenuPermCodeMapper sysMenuPermCodeMapper; + @Autowired + private SysPermCodeService sysPermCodeService; + @Autowired + private IdGeneratorWrapper idGenerator; + + /** + * 返回主对象的Mapper对象。 + * + * @return 主对象的Mapper对象。 + */ + @Override + protected BaseDaoMapper mapper() { + return sysMenuMapper; + } + + /** + * 保存新增的菜单对象。 + * + * @param sysMenu 新增的菜单对象。 + * @param permCodeIdSet 权限字Id列表。 + * @return 新增后的菜单对象。 + */ + @Transactional(rollbackFor = Exception.class) + public SysMenu saveNew(SysMenu sysMenu, Set permCodeIdSet) { + sysMenu.setMenuId(idGenerator.nextLongId()); + sysMenu.setCreateTime(new Date()); + sysMenu.setDeletedFlag(GlobalDeletedFlag.NORMAL); + sysMenuMapper.insert(sysMenu); + if (permCodeIdSet != null) { + List sysMenuPermCodeList = new LinkedList<>(); + for (Long permCodeId : permCodeIdSet) { + SysMenuPermCode menuPermCode = new SysMenuPermCode(); + menuPermCode.setMenuId(sysMenu.getMenuId()); + menuPermCode.setPermCodeId(permCodeId); + sysMenuPermCodeList.add(menuPermCode); + } + sysMenuPermCodeMapper.insertList(sysMenuPermCodeList); + } + return sysMenu; + } + + /** + * 更新菜单对象。 + * + * @param sysMenu 更新的菜单对象。 + * @param originalSysMenu 原有的菜单对象。 + * @param permCodeIdSet 权限字Id列表。 + * @return 更新成功返回true,否则false。 + */ + @Transactional(rollbackFor = Exception.class) + public boolean update(SysMenu sysMenu, SysMenu originalSysMenu, Set permCodeIdSet) { + sysMenu.setCreateTime(originalSysMenu.getCreateTime()); + sysMenu.setMenuType(originalSysMenu.getMenuType()); + sysMenu.setDeletedFlag(GlobalDeletedFlag.NORMAL); + if (sysMenuMapper.updateByPrimaryKey(sysMenu) != 1) { + return false; + } + SysMenuPermCode deletedMenuPermCode = new SysMenuPermCode(); + deletedMenuPermCode.setMenuId(sysMenu.getMenuId()); + sysMenuPermCodeMapper.delete(deletedMenuPermCode); + if (permCodeIdSet != null) { + List sysMenuPermCodeList = new LinkedList<>(); + for (Long permCodeId : permCodeIdSet) { + SysMenuPermCode menuPermCode = new SysMenuPermCode(); + menuPermCode.setMenuId(sysMenu.getMenuId()); + menuPermCode.setPermCodeId(permCodeId); + sysMenuPermCodeList.add(menuPermCode); + } + sysMenuPermCodeMapper.insertList(sysMenuPermCodeList); + } + return true; + } + + /** + * 删除指定的菜单。 + * + * @param menuId 菜单主键Id。 + * @return 删除成功返回true,否则false。 + */ + @Transactional(rollbackFor = Exception.class) + public boolean remove(Long menuId) { + SysMenu menu = new SysMenu(); + menu.setMenuId(menuId); + menu.setDeletedFlag(GlobalDeletedFlag.DELETED); + if (sysMenuMapper.updateByPrimaryKeySelective(menu) != 1) { + return false; + } + SysRoleMenu roleMenu = new SysRoleMenu(); + roleMenu.setMenuId(menuId); + sysRoleMenuMapper.delete(roleMenu); + SysMenuPermCode menuPermCode = new SysMenuPermCode(); + menuPermCode.setMenuId(menuId); + sysMenuPermCodeMapper.delete(menuPermCode); + return true; + } + + /** + * 获取全部菜单列表。 + * + * @return 全部菜单列表。 + */ + public List getAllMenuList() { + Example e = new Example(SysMenu.class); + e.orderBy("showOrder"); + Example.Criteria c = e.createCriteria(); + c.andIn("menuType", Arrays.asList(SysMenuType.TYPE_MENU, SysMenuType.TYPE_DIRECTORY)); + c.andEqualTo("deletedFlag", GlobalDeletedFlag.NORMAL); + return sysMenuMapper.selectByExample(e); + } + + /** + * 获取指定用户Id的菜单列表。 + * + * @param userId 用户主键Id。 + * @return 用户关联的菜单列表。 + */ + public List getMenuListByUserId(Long userId) { + return sysMenuMapper.getMenuListByUserId(userId); + } + + /** + * 判断当前菜单是否存在子菜单。 + * + * @param menuId 菜单主键Id。 + * @return 存在返回true,否则false。 + */ + public boolean hasChildren(Long menuId) { + SysMenu menu = new SysMenu(); + menu.setParentId(menuId); + return this.getCountByFilter(menu) > 0; + } + + /** + * 验证菜单对象关联的数据是否都合法。 + * + * @param sysMenu 当前操作的对象。 + * @param originalSysMenu 原有对象。 + * @param permCodeIdListString 逗号分隔的权限Id列表。 + * @return 验证结果。 + */ + public CallResult verifyRelatedData(SysMenu sysMenu, SysMenu originalSysMenu, String permCodeIdListString) { + JSONObject jsonObject = null; + if (this.needToVerify(sysMenu, originalSysMenu, SysMenu::getParentId)) { + // menu、ui fragment和button类型的menu不能没有parentId + if (sysMenu.getParentId() == null) { + if (sysMenu.getMenuType() != SysMenuType.TYPE_DIRECTORY) { + return CallResult.error("数据验证失败,当前类型菜单项的上级菜单不能为空!"); + } + } else { + String errorMessage = checkErrorOfNonDirectoryMenu(sysMenu); + if (errorMessage != null) { + return CallResult.error(errorMessage); + } + } + } + if (StringUtils.isNotBlank(permCodeIdListString)) { + Set permCodeIdSet = Arrays.stream( + permCodeIdListString.split(",")).map(Long::valueOf).collect(Collectors.toSet()); + if (!sysPermCodeService.existAllPrimaryKeys(permCodeIdSet)) { + return CallResult.error("数据验证失败,存在不合法的权限字,请刷新后重试!"); + } + jsonObject = new JSONObject(); + jsonObject.put("permCodeIdSet", permCodeIdSet); + } + return CallResult.ok(jsonObject); + } + + private String checkErrorOfNonDirectoryMenu(SysMenu sysMenu) { + // 判断父节点是否存在 + SysMenu parentSysMenu = getById(sysMenu.getParentId()); + if (parentSysMenu == null) { + return "数据验证失败,关联的上级菜单并不存在,请刷新后重试!"; + } + // 逐个判断每种类型的菜单,他的父菜单的合法性,先从目录类型和菜单类型开始 + if (sysMenu.getMenuType() == SysMenuType.TYPE_DIRECTORY + || sysMenu.getMenuType() == SysMenuType.TYPE_MENU) { + // 他们的上级只能是目录 + if (parentSysMenu.getMenuType() != SysMenuType.TYPE_DIRECTORY) { + return "数据验证失败,当前类型菜单项的上级菜单只能是目录类型!"; + } + } else if (sysMenu.getMenuType() == SysMenuType.TYPE_UI_FRAGMENT) { + // ui fragment的上级只能是menu类型 + if (parentSysMenu.getMenuType() != SysMenuType.TYPE_MENU) { + return "数据验证失败,当前类型菜单项的上级菜单只能是菜单类型和按钮类型!"; + } + } else if (sysMenu.getMenuType() == SysMenuType.TYPE_BUTTON) { + // button的上级只能是menu和ui fragment + if (parentSysMenu.getMenuType() != SysMenuType.TYPE_MENU + && parentSysMenu.getMenuType() != SysMenuType.TYPE_UI_FRAGMENT) { + return "数据验证失败,当前类型菜单项的上级菜单只能是菜单类型和UI片段类型!"; + } + } + return null; + } +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/service/SysPermCodeService.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/service/SysPermCodeService.java new file mode 100644 index 00000000..44a0644b --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/service/SysPermCodeService.java @@ -0,0 +1,204 @@ +package com.orange.demo.upms.service; + +import com.alibaba.fastjson.JSONObject; +import com.orange.demo.common.core.base.service.BaseService; +import com.orange.demo.common.sequence.wrapper.IdGeneratorWrapper; +import com.orange.demo.common.core.base.dao.BaseDaoMapper; +import com.orange.demo.common.core.constant.GlobalDeletedFlag; +import com.orange.demo.common.core.object.CallResult; +import com.orange.demo.upms.dao.SysMenuPermCodeMapper; +import com.orange.demo.upms.dao.SysPermCodeMapper; +import com.orange.demo.upms.dao.SysPermCodePermMapper; +import com.orange.demo.upms.model.SysMenuPermCode; +import com.orange.demo.upms.model.SysPermCode; +import com.orange.demo.upms.model.SysPermCodePerm; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * 权限字数据服务类。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Service +public class SysPermCodeService extends BaseService { + + @Autowired + private SysPermCodeMapper sysPermCodeMapper; + @Autowired + private SysPermCodePermMapper sysPermCodePermMapper; + @Autowired + private SysMenuPermCodeMapper sysMenuPermCodeMapper; + @Autowired + private SysPermService sysPermService; + @Autowired + private IdGeneratorWrapper idGenerator; + + /** + * 返回主对象的Mapper对象。 + * + * @return 主对象的Mapper对象。 + */ + @Override + protected BaseDaoMapper mapper() { + return sysPermCodeMapper; + } + + /** + * 获取指定用户的权限字列表。 + * + * @param userId 用户主键Id。 + * @return 用户关联的权限字列表。 + */ + public List getPermCodeListByUserId(Long userId) { + return sysPermCodeMapper.getPermCodeListByUserId(userId); + } + + /** + * 保存新增的权限字对象。 + * + * @param sysPermCode 新增的权限字对象。 + * @param permIdSet 权限资源Id列表。 + * @return 新增后的权限字对象。 + */ + @Transactional(rollbackFor = Exception.class) + public SysPermCode saveNew(SysPermCode sysPermCode, Set permIdSet) { + sysPermCode.setPermCodeId(idGenerator.nextLongId()); + sysPermCode.setCreateTime(new Date()); + sysPermCode.setDeletedFlag(GlobalDeletedFlag.NORMAL); + sysPermCodeMapper.insert(sysPermCode); + if (permIdSet != null) { + List sysPermCodePermList = new LinkedList<>(); + for (Long permId : permIdSet) { + SysPermCodePerm permCodePerm = new SysPermCodePerm(); + permCodePerm.setPermCodeId(sysPermCode.getPermCodeId()); + permCodePerm.setPermId(permId); + sysPermCodePermList.add(permCodePerm); + } + sysPermCodePermMapper.insertList(sysPermCodePermList); + } + return sysPermCode; + } + + /** + * 更新权限字对象。 + * + * @param sysPermCode 更新的权限字对象。 + * @param originalSysPermCode 原有的权限字对象。 + * @param permIdSet 权限资源Id列表。 + * @return 更新成功返回true,否则false。 + */ + @Transactional(rollbackFor = Exception.class) + public boolean update(SysPermCode sysPermCode, SysPermCode originalSysPermCode, Set permIdSet) { + sysPermCode.setCreateTime(originalSysPermCode.getCreateTime()); + sysPermCode.setParentId(originalSysPermCode.getParentId()); + sysPermCode.setDeletedFlag(GlobalDeletedFlag.NORMAL); + if (sysPermCodeMapper.updateByPrimaryKey(sysPermCode) != 1) { + return false; + } + SysPermCodePerm deletedPermCodePerm = new SysPermCodePerm(); + deletedPermCodePerm.setPermCodeId(sysPermCode.getPermCodeId()); + sysPermCodePermMapper.delete(deletedPermCodePerm); + if (permIdSet != null) { + List sysPermCodePermList = new LinkedList<>(); + for (Long permId : permIdSet) { + SysPermCodePerm permCodePerm = new SysPermCodePerm(); + permCodePerm.setPermCodeId(sysPermCode.getPermCodeId()); + permCodePerm.setPermId(permId); + sysPermCodePermList.add(permCodePerm); + } + sysPermCodePermMapper.insertList(sysPermCodePermList); + } + return true; + } + + /** + * 删除指定的权限字。 + * + * @param permCodeId 权限字主键Id。 + * @return 删除成功返回true,否则false。 + */ + @Transactional(rollbackFor = Exception.class) + public boolean remove(Long permCodeId) { + SysPermCode permCode = new SysPermCode(); + permCode.setPermCodeId(permCodeId); + permCode.setDeletedFlag(GlobalDeletedFlag.DELETED); + if (sysPermCodeMapper.updateByPrimaryKeySelective(permCode) != 1) { + return false; + } + SysMenuPermCode menuPermCode = new SysMenuPermCode(); + menuPermCode.setPermCodeId(permCodeId); + sysMenuPermCodeMapper.delete(menuPermCode); + SysPermCodePerm permCodePerm = new SysPermCodePerm(); + permCodePerm.setPermCodeId(permCodeId); + sysPermCodePermMapper.delete(permCodePerm); + return true; + } + + /** + * 获取指定用户的权限字列表。 + * + * @param loginName 精确匹配用户登录名。 + * @param permCode 模糊匹配的权限字名,LIKE %permCode%。 + * @return 权限字列表。 + */ + public List getUserPermCodeListByFilter(String loginName, String permCode) { + return sysPermCodeMapper.getUserPermCodeListByFilter(loginName, permCode); + } + + /** + * 获取该菜单的权限字,及其权限字关联的权限资源列表。 + * + * @param menuId 菜单Id。 + * @return 关联了权限资源的权限字列表。 + */ + public List> getPermCodeListByMenuId(Long menuId) { + return sysPermCodeMapper.getPermCodeListByMenuId(menuId); + } + + /** + * 判断当前权限字是否存在下级权限字对象。 + * + * @param permCodeId 权限字主键Id。 + * @return 存在返回true,否则false。 + */ + public boolean hasChildren(Long permCodeId) { + SysPermCode permCode = new SysPermCode(); + permCode.setParentId(permCodeId); + return this.getCountByFilter(permCode) > 0; + } + + /** + * 验证权限字对象关联的数据是否都合法。 + * + * @param sysPermCode 当前操作的对象。 + * @param originalSysPermCode 原有对象。 + * @param permIdListString 逗号分隔的权限资源Id列表。 + * @return 验证结果。 + */ + public CallResult verifyRelatedData( + SysPermCode sysPermCode, SysPermCode originalSysPermCode, String permIdListString) { + if (this.needToVerify(sysPermCode, originalSysPermCode, SysPermCode::getParentId)) { + if (getById(sysPermCode.getParentId()) == null) { + return CallResult.error("数据验证失败,关联的上级权限字并不存在,请刷新后重试!"); + } + } + JSONObject jsonObject = null; + if (StringUtils.isNotBlank(permIdListString)) { + Set permIdSet = Arrays.stream( + permIdListString.split(",")).map(Long::valueOf).collect(Collectors.toSet()); + if (!sysPermService.existAllPrimaryKeys(permIdSet)) { + return CallResult.error("数据验证失败,存在不合法的权限资源,请刷新后重试!"); + } + jsonObject = new JSONObject(); + jsonObject.put("permIdSet", permIdSet); + } + return CallResult.ok(jsonObject); + } +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/service/SysPermModuleService.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/service/SysPermModuleService.java new file mode 100644 index 00000000..bb33e45f --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/service/SysPermModuleService.java @@ -0,0 +1,118 @@ +package com.orange.demo.upms.service; + +import com.orange.demo.common.core.base.service.BaseService; +import com.orange.demo.common.sequence.wrapper.IdGeneratorWrapper; +import com.orange.demo.common.core.base.dao.BaseDaoMapper; +import com.orange.demo.common.core.constant.GlobalDeletedFlag; +import com.orange.demo.upms.dao.SysPermModuleMapper; +import com.orange.demo.upms.model.SysPerm; +import com.orange.demo.upms.model.SysPermModule; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Date; +import java.util.List; + +/** + * 权限资源模块数据服务类。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Service +public class SysPermModuleService extends BaseService { + + @Autowired + private SysPermModuleMapper sysPermModuleMapper; + @Autowired + private SysPermService sysPermService; + @Autowired + private IdGeneratorWrapper idGenerator; + + /** + * 返回主对象的Mapper对象。 + * + * @return 主对象的Mapper对象。 + */ + @Override + protected BaseDaoMapper mapper() { + return sysPermModuleMapper; + } + + /** + * 保存新增的权限资源模块对象。 + * + * @param sysPermModule 新增的权限资源模块对象。 + * @return 新增后的权限资源模块对象。 + */ + @Transactional(rollbackFor = Exception.class) + public SysPermModule saveNew(SysPermModule sysPermModule) { + sysPermModule.setModuleId(idGenerator.nextLongId()); + sysPermModule.setCreateTime(new Date()); + sysPermModule.setDeletedFlag(GlobalDeletedFlag.NORMAL); + sysPermModuleMapper.insert(sysPermModule); + return sysPermModule; + } + + /** + * 更新权限资源模块对象。 + * + * @param sysPermModule 更新的权限资源模块对象。 + * @param originalSysPermModule 原有的权限资源模块对象。 + * @return 更新成功返回true,否则false + */ + @Transactional(rollbackFor = Exception.class) + public boolean update(SysPermModule sysPermModule, SysPermModule originalSysPermModule) { + sysPermModule.setCreateTime(originalSysPermModule.getCreateTime()); + sysPermModule.setDeletedFlag(GlobalDeletedFlag.NORMAL); + return sysPermModuleMapper.updateByPrimaryKey(sysPermModule) != 0; + } + + /** + * 删除指定的权限资源模块。 + * + * @param moduleId 权限资源模块主键Id。 + * @return 删除成功返回true,否则false。 + */ + @Transactional(rollbackFor = Exception.class) + public boolean remove(Long moduleId) { + SysPermModule permModule = new SysPermModule(); + permModule.setModuleId(moduleId); + permModule.setDeletedFlag(GlobalDeletedFlag.DELETED); + return sysPermModuleMapper.updateByPrimaryKeySelective(permModule) != 0; + } + + /** + * 获取权限模块资源及其关联的权限资源列表。 + * + * @return 权限资源模块及其关联的权限资源列表。 + */ + public List getPermModuleAndPermList() { + return sysPermModuleMapper.getPermModuleAndPermList(); + } + + /** + * 判断是否存在下级权限资源模块。 + * + * @param moduleId 权限资源模块主键Id。 + * @return 存在返回true,否则false。 + */ + public boolean hasChildren(Long moduleId) { + SysPermModule permModule = new SysPermModule(); + permModule.setParentId(moduleId); + return this.getCountByFilter(permModule) > 0; + } + + /** + * 判断是否存在权限数据。 + * + * @param moduleId 权限资源模块主键Id。 + * @return 存在返回true,否则false。 + */ + public boolean hasModulePerms(Long moduleId) { + SysPerm filter = new SysPerm(); + filter.setModuleId(moduleId); + return sysPermService.getCountByFilter(filter) > 0; + } +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/service/SysPermService.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/service/SysPermService.java new file mode 100644 index 00000000..7f0917a0 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/service/SysPermService.java @@ -0,0 +1,257 @@ +package com.orange.demo.upms.service; + +import cn.hutool.core.util.ObjectUtil; +import com.alibaba.fastjson.JSONObject; +import com.orange.demo.common.core.base.service.BaseService; +import com.orange.demo.common.sequence.wrapper.IdGeneratorWrapper; +import com.orange.demo.common.core.base.dao.BaseDaoMapper; +import com.orange.demo.common.core.object.MyRelationParam; +import com.orange.demo.common.core.constant.GlobalDeletedFlag; +import com.orange.demo.common.core.object.CallResult; +import com.orange.demo.upms.dao.SysPermCodePermMapper; +import com.orange.demo.upms.dao.SysPermMapper; +import com.orange.demo.upms.model.SysPerm; +import com.orange.demo.upms.model.SysPermCodePerm; +import com.orange.demo.upms.model.SysPermModule; +import com.orange.demo.upms.model.SysUser; +import com.orange.demo.upms.model.constant.SysUserType; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.CachePut; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import tk.mybatis.mapper.entity.Example; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * 权限资源数据服务类。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Service +public class SysPermService extends BaseService { + + @Autowired + private SysPermMapper sysPermMapper; + @Autowired + private SysPermCodePermMapper sysPermCodePermMapper; + @Autowired + private SysPermModuleService sysPermModuleService; + @Autowired + private SysUserService sysUserService; + @Autowired + private IdGeneratorWrapper idGenerator; + + /** + * 返回主对象的Mapper对象。 + * + * @return 主对象的Mapper对象。 + */ + @Override + protected BaseDaoMapper mapper() { + return sysPermMapper; + } + + /** + * 保存新增的权限资源对象。 + * + * @param perm 新增的权限资源对象。 + * @return 新增后的权限资源对象。 + */ + @Transactional(rollbackFor = Exception.class) + public SysPerm saveNew(SysPerm perm) { + perm.setPermId(idGenerator.nextLongId()); + perm.setCreateTime(new Date()); + perm.setDeletedFlag(GlobalDeletedFlag.NORMAL); + sysPermMapper.insert(perm); + return perm; + } + + /** + * 更新权限资源对象。 + * + * @param perm 更新的权限资源对象。 + * @param originalPerm 原有的权限资源对象。 + * @return 更新成功返回true,否则false。 + */ + @Transactional(rollbackFor = Exception.class) + public boolean update(SysPerm perm, SysPerm originalPerm) { + perm.setCreateTime(originalPerm.getCreateTime()); + perm.setDeletedFlag(GlobalDeletedFlag.NORMAL); + return sysPermMapper.updateByPrimaryKeySelective(perm) != 0; + } + + /** + * 删除权限资源。 + * + * @param permId 权限资源主键Id。 + * @return 删除成功返回true,否则false。 + */ + @Transactional(rollbackFor = Exception.class) + public boolean remove(Long permId) { + SysPerm perm = new SysPerm(); + perm.setPermId(permId); + perm.setDeletedFlag(GlobalDeletedFlag.DELETED); + if (sysPermMapper.updateByPrimaryKeySelective(perm) != 1) { + return false; + } + Example e = new Example(SysPermCodePerm.class); + e.createCriteria().andEqualTo("permId", permId); + sysPermCodePermMapper.deleteByExample(e); + return true; + } + + /** + * 获取权限数据列表。 + * + * @param sysPermFilter 过滤对象。 + * @return 权限列表。 + */ + public List getPermListWithRelation(SysPerm sysPermFilter) { + Example e = new Example(SysPerm.class); + e.orderBy("showOrder"); + Example.Criteria c = e.createCriteria(); + if (ObjectUtil.isNotNull(sysPermFilter.getModuleId())) { + c.andEqualTo("moduleId", sysPermFilter.getModuleId()); + } + if (ObjectUtil.isNotNull(sysPermFilter.getUrl())) { + c.andLike("url", "%" + sysPermFilter.getUrl() + "%"); + } + c.andEqualTo("deletedFlag", GlobalDeletedFlag.NORMAL); + List permList = sysPermMapper.selectByExample(e); + // 这里因为权限只有字典数据,所以仅仅做字典关联。 + this.buildRelationForDataList(permList, MyRelationParam.dictOnly(), null); + return permList; + } + + /** + * 获取指定用户的权限资源集合,并存储于缓存,从而提升后续读取效率。 + * + * @param sessionId 用户会话Id。 + * @param userId 用户主键Id。 + * @return 当前用户权限集合。 + */ + @Cacheable(value = "USER_PERMISSION_CACHE", key = "#sessionId", unless = "#result == null") + public Set getCacheableSysPermSetByUserId(String sessionId, Long userId) { + // 这里可以防止非法的userId直接访问权限受限的url + SysUser user = sysUserService.getById(userId); + if (user == null) { + return new HashSet<>(1); + } + // 管理员账户返回空对象,便于缓存的统一处理。 + return user.getUserType() == SysUserType.TYPE_ADMIN + ? new HashSet<>(1) : this.getSysPermSetByUserId(userId); + } + + /** + * 将指定用户的指定会话的权限集合存入缓存。 + * + * @param sessionId 会话Id。 + * @param userId 用户主键Id。 + * @param isAdmin 是否是管理员。 + * @return 查询并缓存后的权限集合。 + */ + @CachePut(value = "USER_PERMISSION_CACHE", key = "#sessionId") + public Set putUserSysPermCache(String sessionId, Long userId, boolean isAdmin) { + // 管理员账户返回空对象,便于缓存的统一处理。 + return isAdmin ? new HashSet<>(1) : this.getSysPermSetByUserId(userId); + } + + /** + * 将指定会话的权限集合从缓存中移除。 + * + * @param sessionId 会话Id。 + */ + @CacheEvict(value = "USER_PERMISSION_CACHE", key = "#sessionId") + public void removeUserSysPermCache(String sessionId) { + // 空实现即可,只是通过注解将当前sessionId从cache中删除。 + } + + /** + * 获取指定用户的权限集合,这里之所以为公有方法,因为spring cache的技术要求,私有方法数据不能缓存。 + * + * @param userId 用户主键Id。 + * @return 用户权限集合。 + */ + public Set getSysPermSetByUserId(Long userId) { + List permList = this.getPermListByUserId(userId); + return permList.stream().map(SysPerm::getUrl).collect(Collectors.toSet()); + } + + /** + * 获取与指定权限字关联的权限资源列表。 + * + * @param permCodeId 关联的权限字主键Id。 + * @param orderBy 排序参数。 + * @return 与指定权限字Id关联的权限资源列表。 + */ + public List getPermListByPermCodeId(Long permCodeId, String orderBy) { + return sysPermMapper.getPermListByPermCodeId(permCodeId, orderBy); + } + + /** + * 获取与指定用户关联的权限资源列表。 + * + * @param userId 关联的用户主键Id。 + * @return 与指定用户Id关联的权限资源列表。 + */ + public List getPermListByUserId(Long userId) { + return sysPermMapper.getPermListByUserId(userId); + } + + /** + * 获取指定用户的用户权限关联列表。 + * + * @param loginName 精确匹配用户登录名。 + * @param moduleId 精确匹配权限模块Id。 + * @param url 模糊匹配的url过滤条件。 + * @return 用户权限关联列表。 + */ + public List> getUserPermListByFilter(String loginName, Long moduleId, String url) { + return sysPermMapper.getUserPermListByFilter(loginName, moduleId, url); + } + + /** + * 获取指定权限资源的权限用户关联数据列表。 + * + * @param permId 权限资源主键Id。 + * @return 用户和权限资源关联列表。 + */ + public List> getPermUserListById(Long permId) { + return sysPermMapper.getPermUserListById(permId); + } + + /** + * 获取指定权限资源的权限角色关联数据列表。 + * + * @param permId 权限资源主键Id。 + * @return 角色和权限资源关联列表。 + */ + public List> getPermRoleListById(Long permId) { + return sysPermMapper.getPermRoleListById(permId); + } + + /** + * 验证权限资源对象关联的数据是否都合法。 + * + * @param sysPerm 当前操作的对象。 + * @param originalSysPerm 原有对象。 + * @return 验证结果。 + */ + public CallResult verifyRelatedData(SysPerm sysPerm, SysPerm originalSysPerm) { + JSONObject jsonObject = null; + if (this.needToVerify(sysPerm, originalSysPerm, SysPerm::getModuleId)) { + SysPermModule permModule = sysPermModuleService.getById(sysPerm.getModuleId()); + if (permModule == null) { + return CallResult.error("数据验证失败,关联的权限模块Id并不存在,请刷新后重试!"); + } + jsonObject = new JSONObject(); + jsonObject.put("permModule", permModule); + } + return CallResult.ok(jsonObject); + } +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/service/SysPermWhitelistService.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/service/SysPermWhitelistService.java new file mode 100644 index 00000000..6e268f5b --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/service/SysPermWhitelistService.java @@ -0,0 +1,32 @@ +package com.orange.demo.upms.service; + +import com.orange.demo.common.core.base.service.BaseService; +import com.orange.demo.common.core.base.dao.BaseDaoMapper; +import com.orange.demo.upms.dao.SysPermWhitelistMapper; +import com.orange.demo.upms.model.SysPermWhitelist; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * 权限资源白名单数据服务类。 + * 白名单中的权限资源,可以不受权限控制,任何用户皆可访问,一般用于常用的字典数据列表接口。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Service +public class SysPermWhitelistService extends BaseService { + + @Autowired + private SysPermWhitelistMapper sysPermWhitelistMapper; + + /** + * 返回主对象的Mapper对象。 + * + * @return 主对象的Mapper对象。 + */ + @Override + protected BaseDaoMapper mapper() { + return sysPermWhitelistMapper; + } +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/service/SysRoleService.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/service/SysRoleService.java new file mode 100644 index 00000000..310873f9 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/service/SysRoleService.java @@ -0,0 +1,221 @@ +package com.orange.demo.upms.service; + +import com.alibaba.fastjson.JSONObject; +import com.orange.demo.common.core.base.service.BaseService; +import com.orange.demo.common.sequence.wrapper.IdGeneratorWrapper; +import com.orange.demo.common.core.base.dao.BaseDaoMapper; +import com.orange.demo.common.core.constant.GlobalDeletedFlag; +import com.orange.demo.common.core.object.TokenData; +import com.orange.demo.common.core.object.CallResult; +import com.orange.demo.upms.dao.SysRoleMapper; +import com.orange.demo.upms.dao.SysRoleMenuMapper; +import com.orange.demo.upms.dao.SysUserRoleMapper; +import com.orange.demo.upms.model.SysRole; +import com.orange.demo.upms.model.SysRoleMenu; +import com.orange.demo.upms.model.SysUserRole; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * 角色数据服务类。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Service +public class SysRoleService extends BaseService { + + @Autowired + private SysRoleMapper sysRoleMapper; + @Autowired + private SysRoleMenuMapper sysRoleMenuMapper; + @Autowired + private SysUserRoleMapper sysUserRoleMapper; + @Autowired + private SysMenuService sysMenuService; + @Autowired + private IdGeneratorWrapper idGenerator; + + /** + * 返回主对象的Mapper对象。 + * + * @return 主对象的Mapper对象。 + */ + @Override + protected BaseDaoMapper mapper() { + return sysRoleMapper; + } + + /** + * 保存新增的角色对象。 + * + * @param role 新增的角色对象。 + * @param menuIdSet 菜单Id列表。 + * @return 新增后的角色对象。 + */ + @Transactional(rollbackFor = Exception.class) + public SysRole saveNew(SysRole role, Set menuIdSet) { + role.setRoleId(idGenerator.nextLongId()); + TokenData tokenData = TokenData.takeFromRequest(); + role.setCreateUserId(tokenData.getUserId()); + role.setCreateUsername(tokenData.getShowName()); + Date now = new Date(); + role.setCreateTime(now); + role.setUpdateTime(now); + role.setDeletedFlag(GlobalDeletedFlag.NORMAL); + sysRoleMapper.insert(role); + if (menuIdSet != null) { + List roleMenuList = new LinkedList<>(); + for (Long menuId : menuIdSet) { + SysRoleMenu roleMenu = new SysRoleMenu(); + roleMenu.setRoleId(role.getRoleId()); + roleMenu.setMenuId(menuId); + roleMenuList.add(roleMenu); + } + sysRoleMenuMapper.insertList(roleMenuList); + } + return role; + } + + /** + * 更新角色对象。 + * + * @param role 更新的角色对象。 + * @param originalRole 原有的角色对象。 + * @param menuIdSet 菜单Id列表。 + * @return 更新成功返回true,否则false。 + */ + @Transactional(rollbackFor = Exception.class) + public boolean update(SysRole role, SysRole originalRole, Set menuIdSet) { + SysRole updateRole = new SysRole(); + BeanUtils.copyProperties(role, updateRole, "createUserId", "createUsername", "createTime"); + updateRole.setUpdateTime(new Date()); + updateRole.setDeletedFlag(GlobalDeletedFlag.NORMAL); + if (sysRoleMapper.updateByPrimaryKeySelective(updateRole) != 1) { + return false; + } + SysRoleMenu deletedRoleMenu = new SysRoleMenu(); + deletedRoleMenu.setRoleId(role.getRoleId()); + sysRoleMenuMapper.delete(deletedRoleMenu); + if (menuIdSet != null) { + List roleMenuList = new LinkedList<>(); + for (Long menuId : menuIdSet) { + SysRoleMenu roleMenu = new SysRoleMenu(); + roleMenu.setRoleId(role.getRoleId()); + roleMenu.setMenuId(menuId); + roleMenuList.add(roleMenu); + } + sysRoleMenuMapper.insertList(roleMenuList); + } + return true; + } + + /** + * 删除指定角色。 + * + * @param roleId 角色主键Id。 + * @return 删除成功返回true,否则false。 + */ + @Transactional(rollbackFor = Exception.class) + public boolean remove(Long roleId) { + SysRole role = new SysRole(); + role.setRoleId(roleId); + role.setDeletedFlag(GlobalDeletedFlag.DELETED); + if (sysRoleMapper.updateByPrimaryKeySelective(role) != 1) { + return false; + } + SysRoleMenu roleMenu = new SysRoleMenu(); + roleMenu.setRoleId(roleId); + sysRoleMenuMapper.delete(roleMenu); + SysUserRole userRole = new SysUserRole(); + userRole.setRoleId(roleId); + sysUserRoleMapper.delete(userRole); + return true; + } + + /** + * 获取角色列表。 + * + * @param filter 角色过滤对象。 + * @param orderBy 排序参数。 + * @return 角色列表。 + */ + public List getSysRoleList(SysRole filter, String orderBy) { + return sysRoleMapper.getSysRoleList(filter, orderBy); + } + + /** + * 通过权限字Id获取拥有改权限的所有角色。 + * 开发人员调试用接口。 + * + * @param permCodeId 查询的权限字Id。 + * @return 符合条件的角色列表。 + */ + public List getSysRoleListByPermCodeId(Long permCodeId) { + return sysRoleMapper.getSysRoleListByPermCodeId(permCodeId); + } + + /** + * 通过权限资源url,模糊搜索拥有改权限的所有角色。 + * 开发人员调试用接口。 + * + * @param url 用于模糊搜索的url。 + * @return 符合条件的角色列表。 + */ + public List getSysRoleListByPerm(String url) { + return sysRoleMapper.getSysRoleListByPerm(url); + } + + /** + * 批量新增用户角色关联。 + * + * @param userRoleList 用户角色关系数据列表。 + */ + @Transactional(rollbackFor = Exception.class) + public void addUserRoleList(List userRoleList) { + sysUserRoleMapper.addUserRoleList(userRoleList); + } + + /** + * 移除指定用户和指定角色的关联关系。 + * + * @param roleId 角色主键Id。 + * @param userId 用户主键Id。 + * @return 移除成功返回true,否则false。 + */ + @Transactional(rollbackFor = Exception.class) + public boolean removeUserRole(Long roleId, Long userId) { + SysUserRole userRole = new SysUserRole(); + userRole.setRoleId(roleId); + userRole.setUserId(userId); + return sysUserRoleMapper.delete(userRole) == 1; + } + + /** + * 验证角色对象关联的数据是否都合法。 + * + * @param sysRole 当前操作的对象。 + * @param originalSysRole 原有对象。 + * @param menuIdListString 逗号分隔的menuId列表。 + * @return 验证结果。 + */ + public CallResult verifyRelatedData(SysRole sysRole, SysRole originalSysRole, String menuIdListString) { + JSONObject jsonObject = null; + if (StringUtils.isNotBlank(menuIdListString)) { + Set menuIdSet = Arrays.stream( + menuIdListString.split(",")).map(Long::valueOf).collect(Collectors.toSet()); + if (!sysMenuService.existAllPrimaryKeys(menuIdSet)) { + return CallResult.error("数据验证失败,存在不合法的菜单权限,请刷新后重试!"); + } + jsonObject = new JSONObject(); + jsonObject.put("menuIdSet", menuIdSet); + } + return CallResult.ok(jsonObject); + } +} diff --git a/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/service/SysUserService.java b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/service/SysUserService.java new file mode 100644 index 00000000..ad77b598 --- /dev/null +++ b/orange-demo-single-service/application/src/main/java/com/orange/demo/upms/service/SysUserService.java @@ -0,0 +1,252 @@ +package com.orange.demo.upms.service; + +import com.alibaba.fastjson.JSONObject; +import com.orange.demo.upms.dao.*; +import com.orange.demo.upms.model.*; +import com.orange.demo.upms.model.constant.SysUserStatus; +import com.orange.demo.common.core.base.dao.BaseDaoMapper; +import com.orange.demo.common.core.constant.GlobalDeletedFlag; +import com.orange.demo.common.core.object.TokenData; +import com.orange.demo.common.core.object.MyWhereCriteria; +import com.orange.demo.common.core.object.MyRelationParam; +import com.orange.demo.common.core.object.CallResult; +import com.orange.demo.common.core.base.service.BaseService; +import com.orange.demo.common.sequence.wrapper.IdGeneratorWrapper; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import tk.mybatis.mapper.entity.Example; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * 用户管理数据操作服务类。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Service +public class SysUserService extends BaseService { + + @Autowired + private SysUserMapper sysUserMapper; + @Autowired + private SysUserRoleMapper sysUserRoleMapper; + @Autowired + private SysRoleService sysRoleService; + @Autowired + private IdGeneratorWrapper idGenerator; + @Autowired + private PasswordEncoder passwordEncoder; + + /** + * 返回当前Service的主表Mapper对象。 + * + * @return 主表Mapper对象。 + */ + @Override + protected BaseDaoMapper mapper() { + return sysUserMapper; + } + + /** + * 获取指定登录名的用户对象。 + * + * @param loginName 指定登录用户名。 + * @return 用户对象。 + */ + public SysUser getSysUserByLoginName(String loginName) { + Example e = new Example(SysUser.class); + Example.Criteria c = e.createCriteria(); + c.andEqualTo("loginName", loginName); + c.andEqualTo("deletedFlag", GlobalDeletedFlag.NORMAL); + return sysUserMapper.selectOneByExample(e); + } + + /** + * 保存新增的用户对象。 + * + * @param user 新增的用户对象。 + * @param roleIdSet 用户角色Id集合。 + * @return 新增后的用户对象。 + */ + @Transactional(rollbackFor = Exception.class) + public SysUser saveNew(SysUser user, Set roleIdSet) { + user.setUserId(idGenerator.nextLongId()); + user.setPassword(passwordEncoder.encode(user.getPassword())); + user.setUserStatus(SysUserStatus.STATUS_NORMAL); + user.setDeletedFlag(GlobalDeletedFlag.NORMAL); + TokenData tokenData = TokenData.takeFromRequest(); + user.setCreateUserId(tokenData.getUserId()); + user.setCreateUsername(tokenData.getShowName()); + Date now = new Date(); + user.setCreateTime(now); + user.setUpdateTime(now); + sysUserMapper.insert(user); + if (CollectionUtils.isNotEmpty(roleIdSet)) { + List userRoleList = new LinkedList<>(); + for (Long roleId : roleIdSet) { + SysUserRole userRole = new SysUserRole(); + userRole.setUserId(user.getUserId()); + userRole.setRoleId(roleId); + userRoleList.add(userRole); + } + sysUserRoleMapper.insertList(userRoleList); + } + return user; + } + + /** + * 更新用户对象。 + * + * @param user 更新的用户对象。 + * @param originalUser 原有的用户对象。 + * @param roleIdSet 用户角色Id列表。 + * @return 更新成功返回true,否则false。 + */ + @Transactional(rollbackFor = Exception.class) + public boolean update(SysUser user, SysUser originalUser, Set roleIdSet) { + user.setLoginName(originalUser.getLoginName()); + user.setPassword(originalUser.getPassword()); + user.setCreateUserId(originalUser.getCreateUserId()); + user.setCreateUsername(originalUser.getCreateUsername()); + user.setCreateTime(originalUser.getCreateTime()); + user.setUpdateTime(new Date()); + if (sysUserMapper.updateByPrimaryKeySelective(user) != 1) { + return false; + } + // 先删除原有的User-Role关联关系,再重新插入新的关联关系 + SysUserRole deletedUserRole = new SysUserRole(); + deletedUserRole.setUserId(user.getUserId()); + sysUserRoleMapper.delete(deletedUserRole); + if (CollectionUtils.isNotEmpty(roleIdSet)) { + List userRoleList = new LinkedList<>(); + for (Long roleId : roleIdSet) { + SysUserRole userRole = new SysUserRole(); + userRole.setUserId(user.getUserId()); + userRole.setRoleId(roleId); + userRoleList.add(userRole); + } + sysUserRoleMapper.insertList(userRoleList); + } + return true; + } + + /** + * 修改用户密码。 + * @param userId 用户主键Id。 + * @param newPass 新密码。 + * @return 成功返回true,否则false。 + */ + @Transactional(rollbackFor = Exception.class) + public boolean changePassword(Long userId, String newPass) { + Example e = new Example(SysUser.class); + e.createCriteria().andEqualTo(super.idFieldName, userId); + e.createCriteria().andEqualTo(super.deletedFlagFieldName, GlobalDeletedFlag.NORMAL); + SysUser updatedUser = new SysUser(); + updatedUser.setPassword(passwordEncoder.encode(newPass)); + return sysUserMapper.updateByExampleSelective(updatedUser, e) == 1; + } + + /** + * 删除指定数据。 + * + * @param userId 主键Id。 + * @return 成功返回true,否则false。 + */ + @Transactional(rollbackFor = Exception.class) + public boolean remove(Long userId) { + Example sysUserExample = new Example(SysUser.class); + Example.Criteria c = sysUserExample.createCriteria(); + c.andEqualTo(super.idFieldName, userId); + c.andEqualTo(super.deletedFlagFieldName, GlobalDeletedFlag.NORMAL); + // 这里先删除主数据 + SysUser deletedObject = new SysUser(); + deletedObject.setDeletedFlag(GlobalDeletedFlag.DELETED); + if (sysUserMapper.updateByExampleSelective(deletedObject, sysUserExample) == 0) { + return false; + } + // 这里可继续删除关联数据。 + SysUserRole userRole = new SysUserRole(); + userRole.setUserId(userId); + sysUserRoleMapper.delete(userRole); + return true; + } + + /** + * 获取单表查询结果。由于没有关联数据查询,因此在仅仅获取单表数据的场景下,效率更高。 + * 如果需要同时获取关联数据,请移步(getSysUserListWithRelation)方法。 + * + * @param filter 过滤对象。 + * @param orderBy 排序参数。 + * @return 查询结果集。 + */ + public List getSysUserList(SysUser filter, String orderBy) { + return sysUserMapper.getSysUserList(filter, orderBy); + } + + /** + * 获取主表的查询结果,以及主表关联的字典数据和一对一从表数据,以及一对一从表的字典数据。 + * 如果仅仅需要获取主表数据,请移步(getSysUserList),以便获取更好的查询性能。 + * + * @param filter 主表过滤对象。 + * @param orderBy 排序参数。 + * @return 查询结果集。 + */ + public List getSysUserListWithRelation(SysUser filter, String orderBy) { + List resultList = sysUserMapper.getSysUserList(filter, orderBy); + Map> criteriaMap = buildAggregationAdditionalWhereCriteria(); + this.buildRelationForDataList(resultList, MyRelationParam.normal(), criteriaMap); + return resultList; + } + + /** + * 获取指定角色的用户列表。 + * + * @param roleId 角色主键Id。 + * @param filter 用户过滤对象。 + * @param orderBy 排序参数。 + * @return 用户列表。 + */ + public List getSysUserListByRoleId(Long roleId, SysUser filter, String orderBy) { + return sysUserMapper.getSysUserListByRoleId(roleId, filter, orderBy); + } + + /** + * 获取不属于指定角色的用户列表。 + * + * @param roleId 角色主键Id。 + * @param filter 用户过滤对象。 + * @param orderBy 排序参数。 + * @return 用户列表。 + */ + public List getNotInSysUserListByRoleId(Long roleId, SysUser filter, String orderBy) { + return sysUserMapper.getNotInSysUserListByRoleId(roleId, filter, orderBy); + } + + /** + * 验证用户对象关联的数据是否都合法。 + * + * @param sysUser 当前操作的对象。 + * @param originalSysUser 原有对象。 + * @param roleIdListString 逗号分隔的角色Id列表字符串。 + * @return 验证结果。 + */ + public CallResult verifyRelatedData(SysUser sysUser, SysUser originalSysUser, String roleIdListString) { + JSONObject jsonObject = new JSONObject(); + if (StringUtils.isBlank(roleIdListString)) { + return CallResult.error("数据验证失败,用户的角色数据不能为空!"); + } + Set roleIdSet = Arrays.stream( + roleIdListString.split(",")).map(Long::valueOf).collect(Collectors.toSet()); + if (!sysRoleService.existAllPrimaryKeys(roleIdSet)) { + return CallResult.error("数据验证失败,存在不合法的用户角色,请刷新后重试!"); + } + jsonObject.put("roleIdSet", roleIdSet); + return CallResult.ok(jsonObject); + } +} diff --git a/orange-demo-single-service/application/src/main/resources/application.yml b/orange-demo-single-service/application/src/main/resources/application.yml new file mode 100644 index 00000000..10a3ec07 --- /dev/null +++ b/orange-demo-single-service/application/src/main/resources/application.yml @@ -0,0 +1,193 @@ +logging: + level: + # 这里设置的日志级别优先于log4j2.xml文件Loggers中的日志级别。 + com.orange.demo: info + +server: + tomcat: + uri-encoding: UTF-8 + max-threads: 100 + min-spare-threads: 10 + port: 8082 + +# spring相关配置 +spring: + application: + name: application + profiles: + active: dev + servlet: + multipart: + max-file-size: 50MB + max-request-size: 50MB + http: + converters: + preferred-json-mapper: fastjson + encoding: + force: true + charset: UTF-8 + enabled: true + freemarker: + template-loader-path: classpath:/template/ + cache: false + charset: UTF-8 + check-template-location: true + content-type: text/html + expose-request-attributes: false + expose-session-attributes: false + request-context-attribute: request + suffix: .ftl + +# mybatis的基本配置 +mybatis: + mapperLocations: classpath:com/orange/demo/*/dao/mapper/*Mapper.xml + typeAliasesPackage: com.orange.demo.*.model + +# mybatis的通用mapper的配置 +mapper: + mappers: tk.mybatis.mapper.common.Mapper,tk.mybatis.mapper.additional.insert.InsertListMapper + not-empty: false + identity: MYSQL + +# 自动分页的配置 +pagehelper: + helperDialect: mysql + reasonable: true + supportMethodsArguments: false + params: count=countSql + +# 暴露监控端点 +management: + endpoints: + web: + exposure: + include: '*' + jmx: + exposure: + include: '*' + endpoint: + # 与中间件相关的健康详情也会被展示 + health: + show-details: always + configprops: + # 在/actuator/configprops中,所有包含password的配置,将用 * 隐藏。 + # 如果不想隐藏任何配置项的值,可以直接使用如下被注释的空值。 + # keys-to-sanitize: + keys-to-sanitize: password + server: + servlet: + context-path: "/" + +# 开发数据库相关配置 +--- +spring: + profiles: dev + datasource: + type: com.alibaba.druid.pool.DruidDataSource + druid: + url: jdbc:mysql://localhost:3306/zzdemo-single?characterEncoding=utf8&useSSL=true&serverTimezone=Asia/Shanghai + username: root + password: 123456 + driver-class-name: com.mysql.cj.jdbc.Driver + name: application + initialSize: 10 + minIdle: 10 + maxActive: 50 + maxWait: 60000 + timeBetweenEvictionRunsMillis: 60000 + minEvictableIdleTimeMillis: 300000 + poolPreparedStatements: true + maxPoolPreparedStatementPerConnectionSize: 20 + maxOpenPreparedStatements: 20 + validationQuery: SELECT 'x' + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 + filters: stat,wall + useGlobalDataSourceStat: true + web-stat-filter: + enabled: true + url-pattern: /* + exclusions: "*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*,/actuator/*" + stat-view-servlet: + enabled: true + urlPattern: /druid/* + resetEnable: true + +application: + # Jwt令牌加密的签名值。 + tokenSigningKey: OrangeSingleDemo + # Jwt令牌在Http Header中的键名称。 + tokenHeaderKey: Authorization + # Jwt令牌刷新后在Http Header中的键名称。 + refreshedTokenHeaderKey: RefreshedToken + # Jwt令牌过期时间(毫秒)。 + expiration: 72000000 + # 初始化密码。 + defaultUserPassword: 123456 + # 缺省的文件上传根目录。 + uploadFileBaseDir: ./zz-resource/upload-files/app + # 跨域的IP白名单列表,多个IP之间逗号分隔(* 表示全部信任,空白表示禁用跨域信任)。 + credentialIpList: "*" + +sequence: + # Snowflake 分布式Id生成算法所需的WorkNode参数值。 + snowflakeWorkNode: 1 + +# 发布数据库相关配置 +--- +spring: + profiles: product + datasource: + type: com.alibaba.druid.pool.DruidDataSource + druid: + url: jdbc:mysql://localhost:3306/zzdemo-single?characterEncoding=utf8&useSSL=true&serverTimezone=Asia/Shanghai + username: root + password: 123456 + driver-class-name: com.mysql.cj.jdbc.Driver + name: application + initialSize: 10 + minIdle: 10 + maxActive: 50 + maxWait: 60000 + timeBetweenEvictionRunsMillis: 60000 + minEvictableIdleTimeMillis: 300000 + poolPreparedStatements: true + maxPoolPreparedStatementPerConnectionSize: 20 + maxOpenPreparedStatements: 20 + validationQuery: SELECT 'x' + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 + filters: stat,wall + useGlobalDataSourceStat: true + web-stat-filter: + enabled: true + url-pattern: /* + exclusions: "*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*,/actuator/*" + stat-view-servlet: + enabled: true + urlPattern: /druid/* + resetEnable: true + +application: + # Jwt令牌加密的签名值。 + tokenSigningKey: OrangeSingleDemo + # Jwt令牌在Http Header中的键名称。 + tokenHeaderKey: Authorization + # Jwt令牌刷新后在Http Header中的键名称。 + refreshedTokenHeaderKey: RefreshedToken + # Jwt令牌过期时间(毫秒)。 + expiration: 72000000 + # 初始化密码。 + defaultUserPassword: 123456 + # 缺省的文件上传根目录。 + uploadFileBaseDir: ./zz-resource/upload-files/app + # 跨域的IP白名单列表,多个IP之间逗号分隔(* 表示全部信任,空白表示禁用跨域信任)。 + credentialIpList: "*" + +sequence: + # Snowflake 分布式Id生成算法所需的WorkNode参数值。 + snowflakeWorkNode: 1 \ No newline at end of file diff --git a/orange-demo-single-service/application/src/main/resources/log4j2.xml b/orange-demo-single-service/application/src/main/resources/log4j2.xml new file mode 100644 index 00000000..1a4ca1f3 --- /dev/null +++ b/orange-demo-single-service/application/src/main/resources/log4j2.xml @@ -0,0 +1,70 @@ + + + + + + + + + + ./zzlogs + + ./zzlogs/backup + + info + + + + + + + + [%-5p] [%d{YYYY-MM-dd HH:mm:ss}] [%t] ==> %msg%n + + + [%-5p] [%d{YYYY-MM-dd HH:mm:ss}] 请求Id[%X{traceId}] [%t] ==> %msg%n + + + 31 + + 20M + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/orange-demo-single-service/application/src/main/resources/template/views/print_error.ftl b/orange-demo-single-service/application/src/main/resources/template/views/print_error.ftl new file mode 100644 index 00000000..af8b36a7 --- /dev/null +++ b/orange-demo-single-service/application/src/main/resources/template/views/print_error.ftl @@ -0,0 +1,329 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
天津公安警官职业学院2017—2018学年度第一学期课程表
班 级星期一星期二星期三星期四星期五
第1节第2节第3节第1节第2节第3节第1节第2节第3节第1节第2节第3节第1节第2节
16 级 刑 事 技 术 班 课程刑法自习刑事图像民 法(选修)派出所工作刑事图像法医学派出所工作法医学国内安全保卫体能自习刑事技术总论刑法
自习自习自习
教师曾岚陈磊邵刚杨丽伟陈磊于辉杨丽伟于辉朱学强张付海王 伟(刑技)曾岚
   
教室206206206206206206206206206操场206206
   
16 级 刑 事 侦 查 课程自习侦查措施经济案件侦查公安信息化公安信息化刑法体能自习痕迹检验刑法国内安全保卫经济案件侦查痕迹检验民 法(选修)
侦查措施
教师徐宏涛张静赵晓松赵晓松王骏强张付海郭海川王骏强朱学强张静郭海川邵刚
徐宏涛
教室2022023号机房3号机房202操场202202202202202202
16 级 治 安 管 理 班 课程刑事技术体能刑事技术治安秩序管理刑事侦查概论刑法群众工作与纠纷调解群众工作与纠纷调解公共关系(选修)刑事侦查概论刑法自习自习自习
q
教师郭海川 韩易浦张付海郭海川 韩易浦翟政亮邵妍薛强刘晓鹏刘晓鹏尚欣邵妍薛强
翟政亮
教室218操场218218218218218218218218218
16 网 络 安 全 监 察 1 班课程应用写作数据库系统应用周二中午:计算机安全管理及实用技术刑事诉讼法周一中午:数据库系统应用民法体育VB语言程序设计选修VB语言程序设计刑事诉讼法选修应用写作犯罪心理
民法犯罪心理
教师关利杨斌赵晓松王伟杨斌李静程军赵伟赵伟王伟关利张学林
李静张学林
教室东阶梯2号机房主楼2011012号机房101操场3号机房3号机房101东阶梯主楼201
主楼201
注:1、课程一栏中有两科次的,上面的课程单周上课,下面的课程双周上课。2、每天上课时间:上午第1节8:30至9:55;第2节10:15至11:40;中午上课时间12:30至13:55;下午第3节14:00至15:25。
+ + diff --git a/orange-demo-single-service/common/common-core/pom.xml b/orange-demo-single-service/common/common-core/pom.xml new file mode 100644 index 00000000..a2dd2491 --- /dev/null +++ b/orange-demo-single-service/common/common-core/pom.xml @@ -0,0 +1,110 @@ + + + + com.orange.demo + common + 1.0.0 + + 4.0.0 + + common-core + 1.0.0 + common-core + jar + + + + + com.google.guava + guava + + + org.apache.commons + commons-lang3 + + + commons-codec + commons-codec + + + commons-io + commons-io + + + commons-fileupload + commons-fileupload + + + org.apache.httpcomponents + httpclient + + + joda-time + joda-time + + + org.apache.commons + commons-collections4 + ${commons-collections4.version} + + + org.apache.commons + commons-csv + ${common-csv.version} + + + cn.hutool + hutool-all + ${hutool.version} + + + io.jsonwebtoken + jjwt + ${jjwt.version} + + + com.alibaba + fastjson + ${fastjson.version} + + + com.github.ben-manes.caffeine + caffeine + ${caffeine.version} + + + cn.jimmyshi + bean-query + ${bean.query.version} + + + + org.apache.poi + poi-ooxml + ${poi-ooxml.version} + + + + + mysql + mysql-connector-java + runtime + + + com.alibaba + druid-spring-boot-starter + ${druid.version} + + + tk.mybatis + mapper-spring-boot-starter + ${mybatis-mapper.version} + + + com.github.pagehelper + pagehelper-spring-boot-starter + ${pagehelper.version} + + + diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/advice/MyControllerAdvice.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/advice/MyControllerAdvice.java new file mode 100644 index 00000000..7a4196d0 --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/advice/MyControllerAdvice.java @@ -0,0 +1,30 @@ +package com.orange.demo.common.core.advice; + +import org.springframework.beans.propertyeditors.CustomDateEditor; +import org.springframework.web.bind.WebDataBinder; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.InitBinder; + +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * Controller的环绕拦截类。 + * + * @author Jerry + * @date 2020-09-25 + */ +@ControllerAdvice +public class MyControllerAdvice { + + /** + * 转换前端传入的日期变量参数为指定格式。 + * + * @param binder 数据绑定参数。 + */ + @InitBinder + public void initBinder(WebDataBinder binder) { + binder.registerCustomEditor(Date.class, + new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"), false)); + } +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/advice/MyExceptionHandler.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/advice/MyExceptionHandler.java new file mode 100644 index 00000000..5d91dc2e --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/advice/MyExceptionHandler.java @@ -0,0 +1,128 @@ +package com.orange.demo.common.core.advice; + +import com.orange.demo.common.core.exception.InvalidClassFieldException; +import com.orange.demo.common.core.exception.InvalidDataFieldException; +import com.orange.demo.common.core.exception.InvalidDataModelException; +import com.orange.demo.common.core.constant.ErrorCodeEnum; +import com.orange.demo.common.core.exception.RedisCacheAccessException; +import com.orange.demo.common.core.object.ResponseResult; +import lombok.extern.slf4j.Slf4j; +import org.apache.ibatis.exceptions.PersistenceException; +import org.springframework.dao.DataAccessException; +import org.springframework.dao.DuplicateKeyException; +import org.springframework.dao.PermissionDeniedDataAccessException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +import javax.servlet.http.HttpServletRequest; +import java.util.concurrent.TimeoutException; + +/** + * 业务层的异常处理类,这里只是给出最通用的Exception的捕捉,今后可以根据业务需要, + * 用不同的函数,处理不同类型的异常。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Slf4j +@RestControllerAdvice("com.orange.demo") +public class MyExceptionHandler { + + /** + * 通用异常处理方法。 + * + * @param ex 异常对象。 + * @param request http请求。 + * @return 应答对象。 + */ + @ExceptionHandler(value = Exception.class) + public ResponseResult exceptionHandle(Exception ex, HttpServletRequest request) { + log.error("Unhandled exception from URL [" + request.getRequestURI() + "]", ex); + return ResponseResult.error(ErrorCodeEnum.UNHANDLED_EXCEPTION); + } + + /** + * 无效的实体对象异常。 + * + * @param ex 异常对象。 + * @param request http请求。 + * @return 应答对象。 + */ + @ExceptionHandler(value = InvalidDataModelException.class) + public ResponseResult invalidDataModelExceptionHandle(Exception ex, HttpServletRequest request) { + log.error("InvalidDataModelException exception from URL [" + request.getRequestURI() + "]", ex); + return ResponseResult.error(ErrorCodeEnum.INVALID_DATA_MODEL); + } + + /** + * 无效的实体对象字段异常。 + * + * @param ex 异常对象。 + * @param request http请求。 + * @return 应答对象。 + */ + @ExceptionHandler(value = InvalidDataFieldException.class) + public ResponseResult invalidDataFieldExceptionHandle(Exception ex, HttpServletRequest request) { + log.error("InvalidDataFieldException exception from URL [" + request.getRequestURI() + "]", ex); + return ResponseResult.error(ErrorCodeEnum.INVALID_DATA_FIELD); + } + + /** + * 无效类字段异常。 + * + * @param ex 异常对象。 + * @param request http请求。 + * @return 应答对象。 + */ + @ExceptionHandler(value = InvalidClassFieldException.class) + public ResponseResult invalidClassFieldExceptionHandle(Exception ex, HttpServletRequest request) { + log.error("InvalidClassFieldException exception from URL [" + request.getRequestURI() + "]", ex); + return ResponseResult.error(ErrorCodeEnum.INVALID_CLASS_FIELD); + } + + /** + * 重复键异常处理方法。 + * + * @param ex 异常对象。 + * @param request http请求。 + * @return 应答对象。 + */ + @ExceptionHandler(value = DuplicateKeyException.class) + public ResponseResult duplicateKeyExceptionHandle(Exception ex, HttpServletRequest request) { + log.error("DuplicateKeyException exception from URL [" + request.getRequestURI() + "]", ex); + return ResponseResult.error(ErrorCodeEnum.DUPLICATED_UNIQUE_KEY); + } + + /** + * 数据访问失败异常处理方法。 + * + * @param ex 异常对象。 + * @param request http请求。 + * @return 应答对象。 + */ + @ExceptionHandler(value = DataAccessException.class) + public ResponseResult dataAccessExceptionHandle(Exception ex, HttpServletRequest request) { + log.error("DataAccessException exception from URL [" + request.getRequestURI() + "]", ex); + if (ex.getCause() instanceof PersistenceException + && ex.getCause().getCause() instanceof PermissionDeniedDataAccessException) { + return ResponseResult.error(ErrorCodeEnum.DATA_PERM_ACCESS_FAILED); + } + return ResponseResult.error(ErrorCodeEnum.DATA_ACCESS_FAILED); + } + + /** + * Redis缓存访问异常处理方法。 + * + * @param ex 异常对象。 + * @param request http请求。 + * @return 应答对象。 + */ + @ExceptionHandler(value = RedisCacheAccessException.class) + public ResponseResult redisCacheAccessExceptionHandle(Exception ex, HttpServletRequest request) { + log.error("RedisCacheAccessException exception from URL [" + request.getRequestURI() + "]", ex); + if (ex.getCause() instanceof TimeoutException) { + return ResponseResult.error(ErrorCodeEnum.REDIS_CACHE_ACCESS_TIMEOUT); + } + return ResponseResult.error(ErrorCodeEnum.REDIS_CACHE_ACCESS_STATE_ERROR); + } +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/annotation/DeletedFlagColumn.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/annotation/DeletedFlagColumn.java new file mode 100644 index 00000000..bdf7249d --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/annotation/DeletedFlagColumn.java @@ -0,0 +1,16 @@ +package com.orange.demo.common.core.annotation; + +import java.lang.annotation.*; + +/** + * 主要用于标记逻辑删除字段。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Target({ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface DeletedFlagColumn { + +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/annotation/JobUpdateTimeColumn.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/annotation/JobUpdateTimeColumn.java new file mode 100644 index 00000000..84da0a01 --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/annotation/JobUpdateTimeColumn.java @@ -0,0 +1,16 @@ +package com.orange.demo.common.core.annotation; + +import java.lang.annotation.*; + +/** + * 主要用于标记更新字段。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Target({ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface JobUpdateTimeColumn { + +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/annotation/MyDataSource.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/annotation/MyDataSource.java new file mode 100644 index 00000000..2c898d48 --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/annotation/MyDataSource.java @@ -0,0 +1,21 @@ +package com.orange.demo.common.core.annotation; + +import java.lang.annotation.*; + +/** + * 主要用于标记Service所依赖的数据源类型。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface MyDataSource { + + /** + * 标注的数据源类型 + * @return 当前标注的数据源类型。 + */ + int value(); +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/annotation/MyRequestBody.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/annotation/MyRequestBody.java new file mode 100644 index 00000000..612e73e7 --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/annotation/MyRequestBody.java @@ -0,0 +1,31 @@ +package com.orange.demo.common.core.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 标记Controller中的方法参数,参数解析器会根据该注解将请求中的JSON数据,映射到参数中的绑定字段。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Target(ElementType.PARAMETER) +@Retention(RetentionPolicy.RUNTIME) +public @interface MyRequestBody { + + /** + * 是否必须出现的参数。 + */ + boolean required() default false; + /** + * 解析时用到的JSON的key。 + */ + String value() default ""; + /** + * 集合元素的ClassType。只有在接口参数为List的时候,需要把E的class传入。 + * 缺省值Class.class表示没有设置。 + */ + Class elementType() default Class.class; +} \ No newline at end of file diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/annotation/NoAuthInterface.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/annotation/NoAuthInterface.java new file mode 100644 index 00000000..de33462a --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/annotation/NoAuthInterface.java @@ -0,0 +1,15 @@ +package com.orange.demo.common.core.annotation; + +import java.lang.annotation.*; + +/** + * 主要用于标记无需Token验证的接口 + * + * @author Jerry + * @date 2020-09-25 + */ +@Target({ElementType.METHOD, ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface NoAuthInterface { +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/annotation/RelationConstDict.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/annotation/RelationConstDict.java new file mode 100644 index 00000000..4615255d --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/annotation/RelationConstDict.java @@ -0,0 +1,29 @@ +package com.orange.demo.common.core.annotation; + +import java.lang.annotation.*; + +/** + * 标识Model和常量字典之间的关联关系。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Target({ElementType.FIELD, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface RelationConstDict { + + /** + * 当前对象的关联Id字段名称。 + * + * @return 当前对象的关联Id字段名称。 + */ + String masterIdField(); + + /** + * 被关联的常量字典的Class对象。 + * + * @return 关联的常量字典的Class对象。 + */ + Class constantDictClass(); +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/annotation/RelationDict.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/annotation/RelationDict.java new file mode 100644 index 00000000..97722f81 --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/annotation/RelationDict.java @@ -0,0 +1,60 @@ +package com.orange.demo.common.core.annotation; + +import java.lang.annotation.*; + +/** + * 标识Model之间的字典关联关系。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Target({ElementType.FIELD, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface RelationDict { + + /** + * 当前对象的关联Id字段名称。 + * + * @return 当前对象的关联Id字段名称。 + */ + String masterIdField(); + + /** + * 被关联Model对象的Class对象。 + * + * @return 被关联Model对象的Class对象。 + */ + Class slaveModelClass(); + + /** + * 被关联Model对象的关联Id字段名称。 + * + * @return 被关联Model对象的关联Id字段名称。 + */ + String slaveIdField(); + + /** + * 被关联Model对象的关联Name字段名称。 + * + * @return 被关联Model对象的关联Name字段名称。 + */ + String slaveNameField(); + + /** + * 被关联的本地Service对象名称。 + * + * @return 被关联的本地Service对象名称。 + */ + String slaveServiceName(); + + /** + * 在同一个实体对象中,如果有一对一关联和字典关联,都是基于相同的主表字段,并关联到 + * 相同关联表的同一关联字段时,可以在字典关联的注解中引用被一对一注解标准的对象属性。 + * 从而在数据整合时,当前字典的数据可以直接取自"equalOneToOneRelationField"指定 + * 的字段,从而避免一次没必要的数据库查询操作,提升了加载显示的效率。 + * + * @return 与该字典字段引用关系完全相同的一对一关联属性名称。 + */ + String equalOneToOneRelationField() default ""; +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/annotation/RelationManyToMany.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/annotation/RelationManyToMany.java new file mode 100644 index 00000000..c5cbed13 --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/annotation/RelationManyToMany.java @@ -0,0 +1,36 @@ +package com.orange.demo.common.core.annotation; + +import java.lang.annotation.*; + +/** + * 标注多对多的Model关系。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Target({ElementType.FIELD, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface RelationManyToMany { + + /** + * 多对多中间表的Mapper对象名称。 + * + * @return 被关联的本地Service对象名称。 + */ + String relationMapperName(); + + /** + * 多对多关联表Model对象的Class对象。 + * + * @return 被关联Model对象的Class对象。 + */ + Class relationModelClass(); + + /** + * 多对多关联表Model对象中与主表关联的Id字段名称。 + * + * @return 被关联Model对象的关联Id字段名称。 + */ + String relationMasterIdField(); +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/annotation/RelationManyToManyAggregation.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/annotation/RelationManyToManyAggregation.java new file mode 100644 index 00000000..86ed12e4 --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/annotation/RelationManyToManyAggregation.java @@ -0,0 +1,85 @@ +package com.orange.demo.common.core.annotation; + +import java.lang.annotation.*; + +/** + * 主要用于多对多的Model关系。标注通过从表关联字段或者关联表关联字段计算主表聚合计算字段的规则。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Target({ElementType.FIELD, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface RelationManyToManyAggregation { + + /** + * 当前对象的关联Id字段名称。 + * + * @return 当前对象的关联Id字段名称。 + */ + String masterIdField(); + + /** + * 被关联的本地Service对象名称。 + * + * @return 被关联的本地Service对象名称。 + */ + String slaveServiceName(); + + /** + * 多对多从表Model对象的Class对象。 + * + * @return 被关联Model对象的Class对象。 + */ + Class slaveModelClass(); + + /** + * 多对多从表Model对象的关联Id字段名称。 + * + * @return 被关联Model对象的关联Id字段名称。 + */ + String slaveIdField(); + + /** + * 多对多关联表Model对象的Class对象。 + * + * @return 被关联Model对象的Class对象。 + */ + Class relationModelClass(); + + /** + * 多对多关联表Model对象中与主表关联的Id字段名称。 + * + * @return 被关联Model对象的关联Id字段名称。 + */ + String relationMasterIdField(); + + /** + * 多对多关联表Model对象中与从表关联的Id字段名称。 + * + * @return 被关联Model对象的关联Id字段名称。 + */ + String relationSlaveIdField(); + + /** + * 聚合计算所在的Model。 + * + * @return 聚合计算所在Model的Class。 + */ + Class aggregationModelClass(); + + /** + * 聚合类型。具体数值参考AggregationType对象。 + * + * @return 聚合类型。 + */ + int aggregationType(); + + /** + * 聚合计算所在Model的字段名称。 + * + * @return 聚合计算所在Model的字段名称。 + */ + String aggregationField(); +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/annotation/RelationOneToManyAggregation.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/annotation/RelationOneToManyAggregation.java new file mode 100644 index 00000000..4e5db643 --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/annotation/RelationOneToManyAggregation.java @@ -0,0 +1,57 @@ +package com.orange.demo.common.core.annotation; + +import java.lang.annotation.*; + +/** + * 主要用于一对多的Model关系。标注通过从表关联字段计算主表聚合计算字段的规则。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Target({ElementType.FIELD, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface RelationOneToManyAggregation { + + /** + * 当前对象的关联Id字段名称。 + * + * @return 当前对象的关联Id字段名称。 + */ + String masterIdField(); + + /** + * 被关联的本地Service对象名称。 + * + * @return 被关联的本地Service对象名称。 + */ + String slaveServiceName(); + + /** + * 被关联Model对象的Class对象。 + * + * @return 被关联Model对象的Class对象。 + */ + Class slaveModelClass(); + + /** + * 被关联Model对象的关联Id字段名称。 + * + * @return 被关联Model对象的关联Id字段名称。 + */ + String slaveIdField(); + + /** + * 被关联Model对象中参与计算的聚合类型。具体数值参考AggregationType对象。 + * + * @return 被关联Model对象中参与计算的聚合类型。 + */ + int aggregationType(); + + /** + * 被关联Model对象中参与聚合计算的字段名称。 + * + * @return 被关联Model对象中参与计算字段的名称。 + */ + String aggregationField(); +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/annotation/RelationOneToOne.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/annotation/RelationOneToOne.java new file mode 100644 index 00000000..a1c8957a --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/annotation/RelationOneToOne.java @@ -0,0 +1,50 @@ +package com.orange.demo.common.core.annotation; + +import java.lang.annotation.*; + +/** + * 标识Model之间的一对一关联关系。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Target({ElementType.FIELD, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface RelationOneToOne { + + /** + * 当前对象的关联Id字段名称。 + * + * @return 当前对象的关联Id字段名称。 + */ + String masterIdField(); + + /** + * 被关联Model对象的Class对象。 + * + * @return 被关联Model对象的Class对象。 + */ + Class slaveModelClass(); + + /** + * 被关联Model对象的关联Id字段名称。 + * + * @return 被关联Model对象的关联Id字段名称。 + */ + String slaveIdField(); + + /** + * 被关联的本地Service对象名称。 + * + * @return 被关联的本地Service对象名称。 + */ + String slaveServiceName(); + + /** + * 在一对一关联时,是否加载从表的字典关联。 + * + * @return 是否加载从表的字典关联。true关联,false则只返回从表自身数据。 + */ + boolean loadSlaveDict() default true; +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/aop/AccessLogAspect.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/aop/AccessLogAspect.java new file mode 100644 index 00000000..8203b845 --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/aop/AccessLogAspect.java @@ -0,0 +1,84 @@ +package com.orange.demo.common.core.aop; + +import com.alibaba.fastjson.JSON; +import com.orange.demo.common.core.constant.ApplicationConstant; +import com.orange.demo.common.core.util.MyCommonUtil; +import lombok.extern.slf4j.Slf4j; +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.MDC; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.ArrayList; +import java.util.List; + +/** + * 记录接口的链路traceId、请求参数、应答数据、错误信息和调用时长。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Aspect +@Component +@Order(1) +@Slf4j +public class AccessLogAspect { + + /** + * 所有controller方法。 + */ + @Pointcut("execution(public * com.orange.demo..controller..*(..))") + public void controllerPointCut() { + // 空注释,避免sonar警告 + } + + @Around("controllerPointCut()") + public Object around(ProceedingJoinPoint joinPoint) throws Throwable { + HttpServletRequest request = + ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest(); + // 请求流水号 + String traceId = MyCommonUtil.generateUuid(); + HttpServletResponse response = + ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getResponse(); + response.setHeader(ApplicationConstant.HTTP_HEADER_TRACE_ID, traceId); + MDC.put(ApplicationConstant.HTTP_HEADER_TRACE_ID, traceId); + long start = System.currentTimeMillis(); + // 获取方法参数 + List httpReqArgs = new ArrayList<>(); + MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); + Object[] args = joinPoint.getArgs(); + for (Object object : args) { + if (!(object instanceof HttpServletRequest) + && !(object instanceof HttpServletResponse) + && !(object instanceof MultipartFile)) { + httpReqArgs.add(object); + } + } + String url = request.getRequestURI(); + String params = JSON.toJSONString(httpReqArgs); + log.info("开始请求,traceId={}, url={}, reqData={}", traceId, url, params); + Object result = null; + try { + // 调用原来的方法 + result = joinPoint.proceed(); + } catch (Exception e) { + log.error("请求报错,traceId={}, url={}, reqData={}, error={}", traceId, url, params, e.getMessage()); + throw e; + } finally { + // 获取应答报文及接口处理耗时 + String respData = result == null ? null : JSON.toJSONString(result); + log.info("请求完成, traceId={}, url={},elapse={}ms, respData={}", + traceId, url, (System.currentTimeMillis() - start), respData); + } + return result; + } +} \ No newline at end of file diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/base/dao/BaseDaoMapper.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/base/dao/BaseDaoMapper.java new file mode 100644 index 00000000..c91934c3 --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/base/dao/BaseDaoMapper.java @@ -0,0 +1,90 @@ +package com.orange.demo.common.core.base.dao; + +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; +import tk.mybatis.mapper.additional.insert.InsertListMapper; +import tk.mybatis.mapper.annotation.RegisterMapper; +import tk.mybatis.mapper.common.Mapper; + +import java.util.List; +import java.util.Map; + +/** + * 数据访问对象的基类。 + * + * @param 主Model实体对象。 + * @author Jerry + * @date 2020-09-25 + */ +@RegisterMapper +public interface BaseDaoMapper extends Mapper, InsertListMapper { + + /** + * 根据指定的表名、显示字段列表、过滤条件字符串和分组字段,返回聚合计算后的查询结果。 + * + * @param selectTable 表名称。 + * @param selectFields 返回字段列表,逗号分隔。 + * @param whereClause SQL常量形式的条件从句。 + * @param groupBy 分组字段列表,逗号分隔。 + * @return 对象可选字段Map列表。 + */ + @Select("") + List> getGroupedListByCondition( + @Param("selectTable") String selectTable, + @Param("selectFields") String selectFields, + @Param("whereClause") String whereClause, + @Param("groupBy") String groupBy); + + /** + * 根据指定的表名、显示字段列表、过滤条件字符串和排序字符串,返回查询结果。 + * + * @param selectTable 表名称。 + * @param selectFields 选择的字段列表。 + * @param whereClause 过滤字符串。 + * @param orderBy 排序字符串。 + * @return 查询结果。 + */ + @Select("") + List> getListByCondition( + @Param("selectTable") String selectTable, + @Param("selectFields") String selectFields, + @Param("whereClause") String whereClause, + @Param("orderBy") String orderBy); + + /** + * 用指定过滤条件,计算记录数量。 + * + * @param selectTable 表名称。 + * @param whereClause 过滤字符串。 + * @return 返回过滤后的数据数量。 + */ + @Select("") + int getCountByCondition(@Param("selectTable") String selectTable, @Param("whereClause") String whereClause); +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/base/mapper/BaseModelMapper.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/base/mapper/BaseModelMapper.java new file mode 100644 index 00000000..1cbbe602 --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/base/mapper/BaseModelMapper.java @@ -0,0 +1,124 @@ +package com.orange.demo.common.core.base.mapper; + +import cn.hutool.core.bean.BeanUtil; +import org.apache.commons.collections4.CollectionUtils; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * Model对象到Domain类型对象的相互转换。实现类通常声明在Model实体类中。 + * + * @param Domain域对象类型。 + * @param Model实体对象类型。 + * @author Jerry + * @date 2020-09-25 + */ +public interface BaseModelMapper { + + /** + * 转换Model实体对象到Domain域对象。 + * + * @param model Model实体对象。 + * @return Domain域对象。 + */ + D fromModel(M model); + + /** + * 转换Model实体对象列表到Domain域对象列表。 + * + * @param modelList Model实体对象列表。 + * @return Domain域对象列表。 + */ + List fromModelList(List modelList); + + /** + * 转换Domain域对象到Model实体对象。 + * + * @param domain Domain域对象。 + * @return Model实体对象。 + */ + M toModel(D domain); + + /** + * 转换Domain域对象列表到Model实体对象列表。 + * + * @param domainList Domain域对象列表。 + * @return Model实体对象列表。 + */ + List toModelList(List domainList); + + /** + * 转换bean到map + * + * @param bean bean对象。 + * @param ignoreNullValue 值为null的字段是否转换到Map。 + * @param bean类型。 + * @return 转换后的map对象。 + */ + default Map beanToMap(T bean, boolean ignoreNullValue) { + return BeanUtil.beanToMap(bean, false, ignoreNullValue); + } + + /** + * 转换bean集合到map集合 + * + * @param dataList bean对象集合。 + * @param ignoreNullValue 值为null的字段是否转换到Map。 + * @param bean类型。 + * @return 转换后的map对象集合。 + */ + default List> beanToMap(List dataList, boolean ignoreNullValue) { + if (CollectionUtils.isEmpty(dataList)) { + return new LinkedList<>(); + } + return dataList.stream() + .map(o -> BeanUtil.beanToMap(o, false, ignoreNullValue)) + .collect(Collectors.toList()); + } + + /** + * 转换map到bean。 + * + * @param map map对象。 + * @param beanClazz bean的Class对象。 + * @param bean类型。 + * @return 转换后的bean对象。 + */ + default T mapToBean(Map map, Class beanClazz) { + return BeanUtil.mapToBean(map, beanClazz, true); + } + + /** + * 转换map集合到bean集合。 + * + * @param mapList map对象集合。 + * @param beanClazz bean的Class对象。 + * @param bean类型。 + * @return 转换后的bean对象集合。 + */ + default List mapToBean(List> mapList, Class beanClazz) { + if (CollectionUtils.isEmpty(mapList)) { + return new LinkedList<>(); + } + return mapList.stream() + .map(m -> BeanUtil.mapToBean(m, beanClazz, true)) + .collect(Collectors.toList()); + } + + /** + * 对于Map字段到Map字段的映射场景,MapStruct会根据方法签名自动选择该函数 + * 作为对象copy的函数。由于该函数是直接返回的,因此没有对象copy,效率更高。 + * 如果没有该函数,MapStruct会生成如下代码: + * Map map = courseDto.getTeacherIdDictMap(); + * if ( map != null ) { + * course.setTeacherIdDictMap( new HashMap( map ) ); + * } + * + * @param map map对象。 + * @return 直接返回的map。 + */ + default Map mapToMap(Map map) { + return map; + } +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/base/mapper/DummyModelMapper.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/base/mapper/DummyModelMapper.java new file mode 100644 index 00000000..7228f446 --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/base/mapper/DummyModelMapper.java @@ -0,0 +1,58 @@ +package com.orange.demo.common.core.base.mapper; + +import java.util.List; + +/** + * 哑元占位对象。Model实体对象和Domain域对象相同的场景下使用。 + * 由于没有实际的数据转换,因此同时保证了代码统一和执行效率。 + * + * @param 数据类型。 + * @author Jerry + * @date 2020-09-25 + */ +public class DummyModelMapper implements BaseModelMapper { + + /** + * 不转换直接返回。 + * + * @param model Model实体对象。 + * @return Domain域对象。 + */ + @Override + public M fromModel(M model) { + return model; + } + + /** + * 不转换直接返回。 + * + * @param modelList Model实体对象列表。 + * @return Domain域对象列表。 + */ + @Override + public List fromModelList(List modelList) { + return modelList; + } + + /** + * 不转换直接返回。 + * + * @param domain Domain域对象。 + * @return Model实体对象。 + */ + @Override + public M toModel(M domain) { + return domain; + } + + /** + * 不转换直接返回。 + * + * @param domainList Domain域对象列表。 + * @return Model实体对象列表。 + */ + @Override + public List toModelList(List domainList) { + return domainList; + } +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/base/service/BaseDictService.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/base/service/BaseDictService.java new file mode 100644 index 00000000..f611dde0 --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/base/service/BaseDictService.java @@ -0,0 +1,149 @@ +package com.orange.demo.common.core.base.service; + +import com.orange.demo.common.core.cache.DictionaryCache; +import com.orange.demo.common.core.constant.GlobalDeletedFlag; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.CollectionUtils; +import tk.mybatis.mapper.entity.Example; + +import java.util.Set; +import java.util.List; + +/** + * 带有缓存功能的字典Service基类,需要留意的是,由于缓存基于Key/Value方式存储, + * 目前仅支持基于主键字段的缓存查找,其他条件的查找仍然从数据源获取。 + * + * @param Model实体对象的类型。 + * @param Model对象主键的类型。 + * @author Jerry + * @date 2020-09-25 + */ +@Slf4j +public abstract class BaseDictService extends BaseService { + + /** + * 缓存池对象。 + */ + protected DictionaryCache dictionaryCache; + + /** + * 构造函数使用缺省缓存池对象。 + */ + public BaseDictService() { + super(); + } + + /** + * 是否在服务启动的时候加载。子类可以重载该方法,并在需要的时候手工调用loadCachedData加载数据。 + * + * @return true表示启动即可加载数据,false需要手动调用loadCachedData进行加载。 + */ + public boolean loadOnStartup() { + return true; + } + + /** + * 在系统启动时,加载全部数据到内存,缓存的key只能为映射表的主键。 + */ + public void loadCachedData() { + if (loadOnStartup()) { + reloadCachedData(false); + } + } + + /** + * 重新加载数据库中所有当前表数据到系统内存。 + * + * @param force true则强制刷新,如果false,当缓存中存在数据时不刷新。 + */ + public void reloadCachedData(boolean force) { + // 在非强制刷新情况下。 + // 先行判断缓存中是否存在数据,如果有就不加载了。 + if (!force && dictionaryCache.getCount() > 0) { + return; + } + List allList = super.getAllList(); + dictionaryCache.reload(allList, force); + } + + /** + * 直接从缓存池中获取主键Id关联的数据。 + * + * @param id 主键Id。 + * @return 主键关联的数据,不存在返回null。 + */ + @Override + public M getById(K id) { + return dictionaryCache.get(id); + } + + /** + * 直接从缓存池中获取所有数据。 + * + * @return 返回所有数据。 + */ + @Override + public List getAllList() { + return dictionaryCache.getAll(); + } + + /** + * 直接从缓存池中返回符合主键 in (idValues) 条件的所有数据。 + * + * @param idValues 主键值列表。 + * @return 检索后的数据列表。 + */ + @Override + public List getInList(Set idValues) { + return dictionaryCache.getInList(idValues); + } + + /** + * 返回符合 inFilterField in (inFilterValues) 条件的所有数据。蜀国property是主键,则从缓存中读取。 + * + * @param inFilterField 参与(In-list)过滤的Java字段。 + * @param inFilterValues 参与(In-list)过滤的Java字段值集合。 + * @return 检索后的数据列表。 + */ + @Override + @SuppressWarnings("unchecked") + public List getInList(String inFilterField, Set inFilterValues) { + if (inFilterField.equals(this.idFieldName)) { + return this.getInList((Set) inFilterValues); + } + return this.getInList(inFilterField, inFilterValues, (String) null); + } + + /** + * 判断参数值列表中的所有数据,是否全部存在。另外,keyName字段在数据表中必须是唯一键值,否则返回结果会出现误判。 + * + * @param inFilterField 待校验的数据字段,这里使用Java对象中的属性,如courseId,而不是数据字段名course_id。 + * @param inFilterValues 数据值集合。 + * @return 全部存在返回true,否则false。 + */ + @Override + @SuppressWarnings("unchecked") + public boolean existUniqueKeyList(String inFilterField, Set inFilterValues) { + if (CollectionUtils.isEmpty(inFilterValues)) { + return false; + } + if (inFilterField.equals(this.idFieldName)) { + List dataList = dictionaryCache.getInList((Set) inFilterValues); + return dataList.size() == inFilterValues.size(); + } + Example e = this.makeDefaultInListExample(inFilterField, inFilterValues, null); + if (deletedFlagFieldName != null) { + e.and().andEqualTo(deletedFlagFieldName, GlobalDeletedFlag.NORMAL); + } + return mapper().selectCountByExample(e) == inFilterValues.size(); + } + + /** + * 获取缓存中的数据数量。 + * + * @return 缓存中的数据总量。 + */ + public int getCachedCount() { + return dictionaryCache.getCount(); + } +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/base/service/BaseService.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/base/service/BaseService.java new file mode 100644 index 00000000..c404c069 --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/base/service/BaseService.java @@ -0,0 +1,1380 @@ +package com.orange.demo.common.core.base.service; + +import com.orange.demo.common.core.annotation.*; +import com.orange.demo.common.core.base.dao.BaseDaoMapper; +import com.orange.demo.common.core.constant.AggregationType; +import com.orange.demo.common.core.constant.GlobalDeletedFlag; +import com.orange.demo.common.core.exception.MyRuntimeException; +import com.orange.demo.common.core.object.*; +import com.orange.demo.common.core.util.AopTargetUtil; +import com.orange.demo.common.core.util.ApplicationContextHolder; +import com.orange.demo.common.core.util.MyModelUtil; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.MapUtils; +import org.apache.commons.lang3.StringUtils; +import tk.mybatis.mapper.entity.Example; +import cn.hutool.core.util.ReflectUtil; + +import javax.persistence.Column; +import javax.persistence.Id; +import javax.persistence.Table; +import javax.persistence.Transient; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; +import java.util.*; +import java.util.function.Function; + +import static java.util.stream.Collectors.*; + +/** + * 所有Service的基类。 + * + * @param Model对象的类型。 + * @param Model对象主键的类型。 + * @author Jerry + * @date 2020-09-25 + */ +@Slf4j +public abstract class BaseService { + + /** + * 当前Service关联的主Model实体对象的Class。 + */ + protected Class modelClass; + /** + * 当前Service关联的主Model实体对象的实际表名称。 + */ + protected String tableName; + /** + * 当前Service关联的主Model对象主键字段名称。 + */ + protected String idFieldName; + /** + * 当前Service关联的主数据表中数据字段名称。 + */ + protected String idColumnName; + /** + * 当前Service关联的主Model对象逻辑删除字段名称。 + */ + protected String deletedFlagFieldName; + /** + * 当前Service关联的主数据表中逻辑删除字段名称。 + */ + protected String deletedFlagColumnName; + /** + * 当前Job服务源主表Model对象最后更新时间字段名称。 + */ + protected String updateTimeFieldName; + /** + * 当前Job服务源主表Model对象最后更新时间列名称。 + */ + protected String updateTimeColumnName; + /** + * 当前Service关联的主Model对象主键字段反射对象。 + */ + protected Field idField; + /** + * 当前Service关联的主Model对象逻辑删除字段反射对象。 + */ + protected Field deletedFlagField; + /** + * 当前Service关联的主Model对象逻辑字段赋值方法的反射对象。 + */ + private Method setDeletedFlagMethod; + /** + * 当前Service关联的主Model对象的所有字典关联的结构列表,该字段在系统启动阶段一次性预加载,提升运行时效率。 + */ + private List relationDictStructList = new LinkedList<>(); + /** + * 当前Service关联的主Model对象的所有常量字典关联的结构列表,该字段在系统启动阶段一次性预加载,提升运行时效率。 + */ + private List relationConstDictStructList = new LinkedList<>(); + /** + * 当前Service关联的主Model对象的所有一对一关联的结构列表,该字段在系统启动阶段一次性预加载,提升运行时效率。 + */ + private List relationOneToOneStructList = new LinkedList<>(); + /** + * 当前Service关联的主Model对象的所有多对多关联的结构列表,该字段在系统启动阶段一次性预加载,提升运行时效率。 + */ + private List relationManyToManyStructList = new LinkedList<>(); + /** + * 当前Service关联的主Model对象的所有一对多聚合关联的结构列表,该字段在系统启动阶段一次性预加载,提升运行时效率。 + */ + private List relationOneToManyAggrStructList = new LinkedList<>(); + /** + * 当前Service关联的主Model对象的所有多对多聚合关联的结构列表,该字段在系统启动阶段一次性预加载,提升运行时效率。 + */ + private List relationManyToManyAggrStructList = new LinkedList<>(); + + private static final String GROUPED_KEY = "groupedKey"; + private static final String AGGREGATED_VALUE = "aggregatedValue"; + private static final String AND_OP = " AND "; + + /** + * 构造函数,在实例化的时候,一次性完成所有有关主Model对象信息的加载。 + */ + @SuppressWarnings("unchecked") + public BaseService() { + modelClass = (Class) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]; + this.tableName = modelClass.getAnnotation(Table.class).name(); + Field[] fields = ReflectUtil.getFields(modelClass); + for (Field field : fields) { + initializeField(field); + } + } + + private void initializeField(Field field) { + if (idFieldName == null && null != field.getAnnotation(Id.class)) { + idFieldName = field.getName(); + idField = field; + Column c = field.getAnnotation(Column.class); + idColumnName = c == null ? idFieldName : c.name(); + } + if (updateTimeFieldName == null && null != field.getAnnotation(JobUpdateTimeColumn.class)) { + updateTimeFieldName = field.getName(); + Column c = field.getAnnotation(Column.class); + updateTimeColumnName = c == null ? updateTimeFieldName : c.name(); + } + if (deletedFlagFieldName == null && null != field.getAnnotation(DeletedFlagColumn.class)) { + deletedFlagFieldName = field.getName(); + Column c = field.getAnnotation(Column.class); + deletedFlagColumnName = c == null ? deletedFlagFieldName : c.name(); + deletedFlagField = field; + setDeletedFlagMethod = ReflectUtil.getMethod( + modelClass, "set" + StringUtils.capitalize(deletedFlagFieldName), Integer.class); + } + } + + /** + * 获取子类中注入的Mapper类。 + * + * @return 子类中注入的Mapper类。 + */ + protected abstract BaseDaoMapper mapper(); + + /** + * 判断指定字段的数据是否存在,且仅仅存在一条记录。 + * 如果是基于主键的过滤,会直接调用existId过滤函数,提升性能。在有缓存的场景下,也可以利用缓存。 + * + * @param fieldName 待过滤的字段名(Java 字段)。 + * @param fieldValue 字段值。 + * @return 存在且仅存在一条返回true,否则false。 + */ + @SuppressWarnings("unchecked") + public boolean existOne(String fieldName, Object fieldValue) { + if (fieldName.equals(this.idFieldName)) { + return this.existId((K) fieldValue); + } + Example e = new Example(modelClass); + e.createCriteria().andEqualTo(fieldName, fieldValue); + return mapper().selectByExample(e).size() == 1; + } + + /** + * 判断主键Id关联的数据是否存在。 + * + * @param id 主键Id。 + * @return 存在返回true,否则false。 + */ + public boolean existId(K id) { + return getById(id) != null; + } + + /** + * 获取主键Id关联的数据。 + * + * @param id 主键Id。 + * @return 主键关联的数据,不存在返回null。 + */ + public M getById(K id) { + if (deletedFlagFieldName == null) { + return mapper().selectByPrimaryKey(id); + } + Example e = new Example(modelClass); + e.createCriteria() + .andEqualTo(this.idFieldName, id) + .andEqualTo(deletedFlagFieldName, GlobalDeletedFlag.NORMAL); + return mapper().selectOneByExample(e); + } + + /** + * 获取主表的查询结果,以及主表关联的字典数据和一对一从表数据,以及一对一从表的字典数据。 + * + * @param id 主表主键Id。 + * @param relationParam 实体对象数据组装的参数构建器。 + * @return 查询结果对象。 + */ + public M getByIdWithRelation(K id, MyRelationParam relationParam) { + M dataObject = this.getById(id); + this.buildRelationForData(dataObject, relationParam, buildAggregationAdditionalWhereCriteria()); + return dataObject; + } + + /** + * 获取所有数据。 + * + * @return 返回所有数据。 + */ + public List getAllList() { + if (deletedFlagFieldName == null) { + return mapper().selectAll(); + } + Example e = new Example(modelClass); + e.createCriteria().andEqualTo(deletedFlagFieldName, GlobalDeletedFlag.NORMAL); + return mapper().selectByExample(e); + } + + /** + * 获取所有主数据,及其关联数据。 + * + * @param relationParam 实体对象数据组装的参数构建器。 + * @return 返回所有主数据,及其关联数据。 + */ + public List getAllListWithRelation(MyRelationParam relationParam) { + List resultList = getAllList(); + this.buildRelationForDataList(resultList, relationParam, null); + return resultList; + } + + /** + * 获取排序后所有数据。 + * + * @param orderByProperties 需要排序的字段属性,这里使用Java对象中的属性名,而不是数据库字段名。 + * @return 返回排序后所有数据。 + */ + public List getAllListByOrder(String... orderByProperties) { + Example e = new Example(modelClass); + for (String orderByProperty : orderByProperties) { + e.orderBy(orderByProperty); + } + if (deletedFlagFieldName != null) { + e.and().andEqualTo(deletedFlagFieldName, GlobalDeletedFlag.NORMAL); + } + return mapper().selectByExample(e); + } + + /** + * 判断参数值主键集合中的所有数据,是否全部存在 + * + * @param idSet 待校验的主键集合。 + * @return 全部存在返回true,否则false。 + */ + public boolean existAllPrimaryKeys(Set idSet) { + if (CollectionUtils.isEmpty(idSet)) { + return false; + } + return this.existUniqueKeyList(idFieldName, idSet); + } + + /** + * 判断参数值列表中的所有数据,是否全部存在。另外,keyName字段在数据表中必须是唯一键值,否则返回结果会出现误判。 + * + * @param inFilterField 待校验的数据字段,这里使用Java对象中的属性,如courseId,而不是数据字段名course_id + * @param inFilterValues 数据值列表。 + * @return 全部存在返回true,否则false。 + */ + public boolean existUniqueKeyList(String inFilterField, Set inFilterValues) { + if (CollectionUtils.isEmpty(inFilterValues)) { + return false; + } + Example e = this.makeDefaultInListExample(inFilterField, inFilterValues, null); + if (deletedFlagFieldName != null) { + e.and().andEqualTo(deletedFlagFieldName, GlobalDeletedFlag.NORMAL); + } + return mapper().selectCountByExample(e) == inFilterValues.size(); + } + + /** + * 获取所有数据的指定字段的数据列表。 + * + * @param getterFunc 指定字段的getter方法。 + * @param 指定字段的类型。 + * @return 指定字段的列表。 + */ + public List getAllListWithField(Function getterFunc) { + List allList = this.getAllList(); + // 即使没有符合filter条件的item存在,也会返回空列表对象,而不是null。 + return allList.stream().filter(x -> getterFunc.apply(x) != null).map(getterFunc).collect(toList()); + } + + /** + * 返回符合主键 in (idValues) 条件的所有数据。 + * + * @param idValues 主键值集合。 + * @return 检索后的数据列表。 + */ + public List getInList(Set idValues) { + return this.getInList(idFieldName, idValues, (String) null); + } + + /** + * 通过getIdFunc函数,获取主对象列表masterList中的主键列表。在基于该Id列表作为主键查询的in list条件,获取数据。 + * + * @param masterList 主对象列表,通过应用getIdFunc函数,获取查询条件中的主键in list条件。 + * @param getIdFunc 获取主对象中符合查询条件主键的id值。 + * @return 检索后的数据列表。 + */ + public List getInList(List masterList, Function getIdFunc) { + // 即使没有符合filter条件的item存在,也会返回空列表对象,而不是null。 + return this.getInList(masterList.stream() + .filter(x -> getIdFunc.apply(x) != null).map(getIdFunc).collect(toSet())); + } + + /** + * 返回符合 inFilterField in (inFilterValues) 条件的所有数据。 + * + * @param inFilterField 参与(In-list)过滤的Java字段。 + * @param inFilterValues 参与(In-list)过滤的Java字段值集合。 + * @return 检索后的数据列表。 + */ + public List getInList(String inFilterField, Set inFilterValues) { + return this.getInList(inFilterField, inFilterValues, (String) null); + } + + /** + * 返回符合 inFilterField in (inFilterValues) 条件的所有数据,并根据orderBy字段排序。 + * + * @param inFilterField 参与(In-list)过滤的Java字段。 + * @param inFilterValues 参与(In-list)过滤的Java字段值集合。 + * @param orderBy 排序字段。 + * @return 检索后的数据列表。 + */ + public List getInList(String inFilterField, Set inFilterValues, String orderBy) { + if (CollectionUtils.isEmpty(inFilterValues)) { + return new LinkedList<>(); + } + Example e = this.makeDefaultInListExample(inFilterField, inFilterValues, orderBy); + if (deletedFlagFieldName != null) { + e.and().andEqualTo(deletedFlagFieldName, GlobalDeletedFlag.NORMAL); + } + return mapper().selectByExample(e); + } + + /** + * 基于对象集合(masterList),并通过masterIdFunction函数对象获取property字段的数据列表, + * inFilterField in (inFilterValues)的所有数据。 + * + * @param inFilterField 参与(In-list)过滤的Java字段。 + * @param masterList 主对象数据集合。 + * @param masterIdFunction 获取主对象中,property字段数值的函数对象。 + * @param 主对象类型。 + * @return 检索后的数据列表。 + */ + public List getInList(String inFilterField, Collection masterList, Function masterIdFunction) { + // 即使没有符合filter条件的item存在,也会返回空列表对象,而不是null。 + return this.getInList(inFilterField, masterList.stream() + .filter(x -> masterIdFunction.apply(x) != null).map(masterIdFunction).collect(toSet())); + } + + /** + * 用参数对象作为过滤条件,获取数据数量。 + * + * @param filter 该方法基于mybatis 通用mapper,过滤对象中,只有被赋值的字段,才会成为where中的条件。 + * @return 返回过滤后的数据数量。 + */ + public int getCountByFilter(M filter) { + if (deletedFlagFieldName == null) { + return mapper().selectCount(filter); + } + try { + setDeletedFlagMethod.invoke(filter, GlobalDeletedFlag.NORMAL); + return mapper().selectCount(filter); + } catch (Exception e) { + log.error("Failed to call reflection code of BaseService.getCountByFilter.", e); + throw new MyRuntimeException(e); + } + } + + /** + * 用参数对象作为过滤条件,判断是否存在过滤数据。 + * + * @param filter 该方法基于mybatis 通用mapper,过滤对象中,只有被赋值的字段,才会成为where中的条件。 + * @return 存在返回true,否则false。 + */ + public boolean existByFilter(M filter) { + return this.getCountByFilter(filter) > 0; + } + + /** + * 用参数对象作为过滤条件,获取查询结果。 + * + * @param filter 该方法基于mybatis的通用mapper。如果参数为null,则返回全部数据。 + * @return 返回过滤后的数据。 + */ + private List getListByFilter(M filter) { + if (filter == null) { + return this.getAllList(); + } + if (deletedFlagFieldName == null) { + return mapper().select(filter); + } + try { + setDeletedFlagMethod.invoke(filter, GlobalDeletedFlag.NORMAL); + return mapper().select(filter); + } catch (Exception ex) { + log.error("Failed to call reflection code of BaseService.getListByFilter.", ex); + throw new MyRuntimeException(ex); + } + } + + /** + * 用参数对象作为过滤条件,获取查询结果。 + * + * @param filter 该方法基于mybatis的通用mapper。如果参数为null,则返回全部数据。 + * @param orderBy SQL中ORDER BY从句。 + * @return 返回过滤后的数据。 + */ + public List getListByFilter(M filter, String orderBy) { + if (StringUtils.isBlank(orderBy)) { + return this.getListByFilter(filter); + } + Example e = new Example(modelClass); + if (StringUtils.isNotBlank(orderBy)) { + e.setOrderByClause(orderBy); + } + if (filter != null) { + Example.Criteria c = e.createCriteria(); + Field[] fields = ReflectUtil.getFields(modelClass); + for (Field field : fields) { + if (field.getAnnotation(Transient.class) == null) { + assembleCriteriaByFilter(filter, field, c); + } + } + } + return mapper().selectByExample(e); + } + + private void assembleCriteriaByFilter(M filter, Field field, Example.Criteria c) { + int modifiers = field.getModifiers(); + // transient类型的字段不能作为查询条件 + int transientMask = 128; + if ((modifiers & transientMask) == 0) { + if (field.getName().equals(deletedFlagFieldName)) { + c.andEqualTo(deletedFlagFieldName, GlobalDeletedFlag.NORMAL); + } else { + ReflectUtil.setAccessible(field); + try { + Object o = field.get(filter); + if (o != null) { + c.andEqualTo(field.getName(), field.get(filter)); + } + } catch (IllegalAccessException ex) { + log.error("Failed to call reflection code of BaseService.getListByFilter.", ex); + throw new MyRuntimeException(ex); + } + } + } + } + + /** + * 用参数对象作为过滤条件,获取查询结果。同时组装实体对象中基于RelationXXXX注解关联的数据。 + * + * @param filter 该方法基于mybatis的通用mapper。如果参数为null,则返回全部数据。 + * @param orderBy SQL中ORDER BY从句。 + * @param relationParam 实体对象数据组装的参数构建器。 + * @return 返回过滤后的数据。 + */ + public List getListWithRelationByFilter(M filter, String orderBy, MyRelationParam relationParam) { + List resultList = this.getListByFilter(filter, orderBy); + Map> criteriaMap = buildAggregationAdditionalWhereCriteria(); + this.buildRelationForDataList(resultList, relationParam, criteriaMap); + return resultList; + } + + /** + * 获取父主键Id下的所有子数据列表。 + * + * @param parentIdFieldName 父主键字段名字,如"courseId"。 + * @param parentId 父主键的值。 + * @return 父主键Id下的所有子数据列表。 + */ + public List getListByParentId(String parentIdFieldName, K parentId) { + Example e = new Example(modelClass); + if (parentId != null) { + e.createCriteria().andEqualTo(parentIdFieldName, parentId); + } else { + e.createCriteria().andIsNull(parentIdFieldName); + } + return mapper().selectByExample(e); + } + + /** + * 根据指定的显示字段列表、过滤条件字符串和分组字符串,返回聚合计算后的查询结果。(基本是内部框架使用,不建议外部接口直接使用)。 + * + * @param selectFields 选择的字段列表,多个字段逗号分隔。 + * NOTE: 如果数据表字段和Java对象字段名字不同,Java对象字段应该以别名的形式出现。 + * 如: table_column_name modelFieldName。否则无法被反射回Bean对象。 + * @param whereClause SQL常量形式的条件从句。 + * @param groupBy SQL常量形式分组字段列表,逗号分隔。 + * @return 聚合计算后的数据结果集。 + */ + public List> getGroupedListByCondition( + String selectFields, String whereClause, String groupBy) { + return mapper().getGroupedListByCondition(tableName, selectFields, whereClause, groupBy); + } + + /** + * 根据指定的显示字段列表、过滤条件字符串和排序字符串,返回查询结果。(基本是内部框架使用,不建议外部接口直接使用)。 + * + * @param selectList 选择的Java字段列表。如果为空表示返回全部字段。 + * @param whereClause SQL常量形式的条件从句。 + * @param orderBy SQL常量形式排序字段列表,逗号分隔。 + * @return 查询结果。 + */ + public List getListByCondition(List selectList, String whereClause, String orderBy) { + Example e = new Example(modelClass); + if (CollectionUtils.isNotEmpty(selectList)) { + String[] selectFields = new String[selectList.size()]; + selectList.toArray(selectFields); + e.selectProperties(selectFields); + } + if (StringUtils.isNotBlank(orderBy)) { + e.setOrderByClause(orderBy); + } + if (StringUtils.isNotBlank(whereClause)) { + e.createCriteria().andCondition(whereClause); + } + return mapper().selectByExample(e); + } + + /** + * 用指定过滤条件,计算记录数量。(基本是内部框架使用,不建议外部接口直接使用)。 + * + * @param whereClause SQL常量形式的条件从句。 + * @return 返回过滤后的数据数量。 + */ + public Integer getCountByCondition(String whereClause) { + return mapper().getCountByCondition(this.tableName, whereClause); + } + + /** + * 集成所有与主表实体对象相关的关联数据列表。包括一对一、字典、一对多和多对多聚合运算等。 + * 也可以根据实际需求,单独调用该函数所包含的各个数据集成函数。 + * + * @param resultList 主表实体对象列表。数据集成将直接作用于该对象列表。 + * @param relationParam 实体对象数据组装的参数构建器。 + * @param criteriaListMap 仅仅用于一对多和多对多聚合计算的附加过滤条件。如果没有可以为NULL。 + */ + public void buildRelationForDataList( + List resultList, MyRelationParam relationParam, Map> criteriaListMap) { + if (relationParam == null || CollectionUtils.isEmpty(resultList)) { + return; + } + // 集成本地一对一和字段级别的数据关联。 + boolean buildOneToOne = relationParam.isBuildOneToOne() || relationParam.isBuildOneToOneWithDict(); + // 这里集成一对一关联。 + if (buildOneToOne) { + this.buildOneToOneForDataList(resultList, relationParam.isBuildOneToOneWithDict()); + } + // 这里集成字典关联 + if (relationParam.isBuildDict()) { + // 构建常量字典关联关系 + this.buildConstDictForDataList(resultList); + this.buildDictForDataList(resultList, buildOneToOne); + } + // 组装本地聚合计算关联数据 + if (relationParam.isBuildRelationAggregation()) { + // 处理多对多场景下,根据主表的结果,进行从表聚合数据的计算。 + this.buildManyToManyAggregationForDataList(resultList, criteriaListMap); + // 处理多一多场景下,根据主表的结果,进行从表聚合数据的计算。 + this.buildOneToManyAggregationForDataList(resultList, criteriaListMap); + } + } + + /** + * 集成所有与主表实体对象相关的关联数据对象。包括一对一、字典、一对多和多对多聚合运算等。 + * 也可以根据实际需求,单独调用该函数所包含的各个数据集成函数。 + * + * @param dataObject 主表实体对象。数据集成将直接作用于该对象。 + * @param relationParam 实体对象数据组装的参数构建器。 + * @param criteriaListMap 仅仅用于一对多和多对多聚合计算的附加过滤条件。如果没有可以为NULL。 + * @param 实体对象类型。 + */ + public void buildRelationForData( + T dataObject, MyRelationParam relationParam, Map> criteriaListMap) { + if (dataObject == null || relationParam == null) { + return; + } + // 集成本地一对一和字段级别的数据关联。 + boolean buildOneToOne = relationParam.isBuildOneToOne() || relationParam.isBuildOneToOneWithDict(); + if (buildOneToOne) { + this.buildOneToOneForData(dataObject, relationParam.isBuildOneToOneWithDict()); + } + if (relationParam.isBuildDict()) { + // 构建常量字典关联关系 + this.buildConstDictForData(dataObject); + // 构建本地数据字典关联关系。 + this.buildDictForData(dataObject, buildOneToOne); + } + // 组装本地聚合计算关联数据 + if (relationParam.isBuildRelationAggregation()) { + // 开始处理多对多场景。 + buildManyToManyAggregationForData(dataObject, criteriaListMap); + // 构建一对多场景 + buildOneToManyAggregationForData(dataObject, criteriaListMap); + } + if (relationParam.isBuildRelationManyToMany()) { + this.buildManyToManyRelation(dataObject); + } + } + + /** + * 集成主表和多对多中间表之间的关联关系。 + * + * @param dataObject 关联后的主表数据对象。 + */ + private void buildManyToManyRelation(T dataObject) { + if (dataObject == null || CollectionUtils.isEmpty(this.relationManyToManyStructList)) { + return; + } + for (RelationStruct relationStruct : this.relationManyToManyStructList) { + Object masterIdValue = ReflectUtil.getFieldValue(dataObject, relationStruct.masterIdField); + Example e = new Example(relationStruct.relationManyToMany.relationModelClass()); + e.createCriteria().andEqualTo(relationStruct.masterIdField.getName(), masterIdValue); + List manyToManyList = relationStruct.manyToManyMapper.selectByExample(e); + ReflectUtil.setFieldValue(dataObject, relationStruct.relationField, manyToManyList); + } + } + + /** + * 为实体对象参数列表数据集成本地静态字典关联数据。 + * + * @param resultList 主表数据列表。 + */ + private void buildConstDictForDataList(List resultList) { + if (CollectionUtils.isEmpty(this.relationConstDictStructList) + || CollectionUtils.isEmpty(resultList)) { + return; + } + for (RelationStruct relationStruct : this.relationConstDictStructList) { + for (M dataObject : resultList) { + Object id = ReflectUtil.getFieldValue(dataObject, relationStruct.masterIdField); + if (id != null) { + String name = relationStruct.dictMap.get(id); + if (name != null) { + Map dictMap = new HashMap<>(2); + dictMap.put("id", id); + dictMap.put("name", name); + ReflectUtil.setFieldValue(dataObject, relationStruct.relationField, dictMap); + } + } + } + } + } + + /** + * 为参数实体对象数据集成本地静态字典关联数据。 + * + * @param dataObject 实体对象。 + */ + private void buildConstDictForData(T dataObject) { + if (dataObject == null || CollectionUtils.isEmpty(this.relationConstDictStructList)) { + return; + } + for (RelationStruct relationStruct : this.relationConstDictStructList) { + Object id = ReflectUtil.getFieldValue(dataObject, relationStruct.masterIdField); + if (id != null) { + String name = relationStruct.dictMap.get(id); + if (name != null) { + Map dictMap = new HashMap<>(2); + dictMap.put("id", id); + dictMap.put("name", name); + ReflectUtil.setFieldValue(dataObject, relationStruct.relationField, dictMap); + } + } + } + } + + /** + * 为实体对象参数列表数据集成本地字典关联数据。 + * + * @param resultList 实体对象数据列表。 + * @param hasBuiltOneToOne 性能优化参数。如果该值为true,同时注解参数RelationDict.equalOneToOneRelationField + * 不为空,则直接从已经完成一对一数据关联的从表对象中获取数据,减少一次数据库交互。 + */ + private void buildDictForDataList(List resultList, boolean hasBuiltOneToOne) { + if (CollectionUtils.isEmpty(this.relationDictStructList) + || CollectionUtils.isEmpty(resultList)) { + return; + } + for (RelationStruct relationStruct : this.relationDictStructList) { + List relationList = null; + if (hasBuiltOneToOne && relationStruct.equalOneToOneRelationField != null) { + relationList = resultList.stream() + .map(obj -> ReflectUtil.getFieldValue(obj, relationStruct.equalOneToOneRelationField)) + .filter(Objects::nonNull) + .collect(toList()); + } else { + String slaveId = relationStruct.relationDict.slaveIdField(); + Set masterIdSet = resultList.stream() + .map(obj -> ReflectUtil.getFieldValue(obj, relationStruct.masterIdField)) + .filter(Objects::nonNull) + .collect(toSet()); + if (CollectionUtils.isNotEmpty(masterIdSet)) { + relationList = relationStruct.service.getInList(slaveId, masterIdSet); + } + } + MyModelUtil.makeDictRelation( + modelClass, resultList, relationList, relationStruct.relationField.getName()); + } + } + + /** + * 为实体对象数据集成本地数据字典关联数据。 + * + * @param dataObject 实体对象。 + * @param hasBuiltOneToOne 性能优化参数。如果该值为true,同时注解参数RelationDict.equalOneToOneRelationField + * 不为空,则直接从已经完成一对一数据关联的从表对象中获取数据,减少一次数据库交互。 + */ + private void buildDictForData(T dataObject, boolean hasBuiltOneToOne) { + if (dataObject == null || CollectionUtils.isEmpty(this.relationDictStructList)) { + return; + } + for (RelationStruct relationStruct : this.relationDictStructList) { + Object relationObject = null; + if (hasBuiltOneToOne && relationStruct.equalOneToOneRelationField != null) { + relationObject = ReflectUtil.getFieldValue(dataObject, relationStruct.equalOneToOneRelationField); + } else { + Object id = ReflectUtil.getFieldValue(dataObject, relationStruct.masterIdField); + if (id != null) { + relationObject = relationStruct.service.getById(id); + } + } + MyModelUtil.makeDictRelation( + modelClass, dataObject, relationObject, relationStruct.relationField.getName()); + } + } + + /** + * 为实体对象参数列表数据集成本地一对一关联数据。 + * + * @param resultList 实体对象数据列表。 + * @param withDict 关联从表数据后,是否把从表的字典数据也一起关联了。。 + */ + private void buildOneToOneForDataList(List resultList, boolean withDict) { + if (CollectionUtils.isEmpty(this.relationOneToOneStructList) + || CollectionUtils.isEmpty(resultList)) { + return; + } + for (RelationStruct relationStruct : this.relationOneToOneStructList) { + Set masterIdSet = resultList.stream() + .map(obj -> ReflectUtil.getFieldValue(obj, relationStruct.masterIdField)) + .filter(Objects::nonNull) + .collect(toSet()); + // 从主表集合中,抽取主表关联字段的集合,再以in list形式去从表中查询。 + if (CollectionUtils.isNotEmpty(masterIdSet)) { + BaseService relationService = relationStruct.service; + List relationList = + relationService.getInList(relationStruct.relationOneToOne.slaveIdField(), masterIdSet); + MyModelUtil.makeOneToOneRelation( + modelClass, resultList, relationList, relationStruct.relationField.getName()); + // 仅仅当需要加载从表字典关联时,才去加载。 + if (withDict && relationStruct.relationOneToOne.loadSlaveDict() + && CollectionUtils.isNotEmpty(relationList)) { + @SuppressWarnings("unchecked") + BaseService proxyTarget = + (BaseService) AopTargetUtil.getTarget(relationService); + // 关联本地字典。 + proxyTarget.buildDictForDataList(relationList, false); + // 关联常量字典 + proxyTarget.buildConstDictForDataList(relationList); + } + } + } + } + + /** + * 为实体对象数据集成本地一对一关联数据。 + * + * @param dataObject 实体对象。 + * @param withDict 关联从表数据后,是否把从表的字典数据也一起关联了。。 + */ + private void buildOneToOneForData(M dataObject, boolean withDict) { + if (dataObject == null || CollectionUtils.isEmpty(this.relationOneToOneStructList)) { + return; + } + for (RelationStruct relationStruct : this.relationOneToOneStructList) { + Object id = ReflectUtil.getFieldValue(dataObject, relationStruct.masterIdField); + if (id != null) { + BaseService relationService = relationStruct.service; + Object relationObject = relationService.getById(id); + ReflectUtil.setFieldValue(dataObject, relationStruct.relationField, relationObject); + // 仅仅当需要加载从表字典关联时,才去加载。 + if (withDict && relationStruct.relationOneToOne.loadSlaveDict() && relationObject != null) { + @SuppressWarnings("unchecked") + BaseService proxyTarget = + (BaseService) AopTargetUtil.getTarget(relationService); + // 关联本地字典 + proxyTarget.buildDictForData(relationObject, false); + // 关联常量字典 + proxyTarget.buildConstDictForData(relationObject); + } + } + } + } + + /** + * 根据实体对象参数列表和过滤条件,集成本地多对多关联聚合计算数据。 + * + * @param resultList 实体对象数据列表。 + * @param criteriaListMap 过滤参数。key为主表字段名称,value是过滤条件列表。 + */ + private void buildManyToManyAggregationForDataList( + List resultList, Map> criteriaListMap) { + if (CollectionUtils.isEmpty(this.relationManyToManyAggrStructList) + || CollectionUtils.isEmpty(resultList)) { + return; + } + if (criteriaListMap == null) { + criteriaListMap = new HashMap<>(this.relationManyToManyAggrStructList.size()); + } + for (RelationStruct relationStruct : this.relationManyToManyAggrStructList) { + Set masterIdSet = resultList.stream() + .map(obj -> ReflectUtil.getFieldValue(obj, relationStruct.masterIdField)) + .filter(Objects::nonNull) + .collect(toSet()); + if (CollectionUtils.isEmpty(masterIdSet)) { + continue; + } + RelationManyToManyAggregation relation = relationStruct.relationManyToManyAggregation; + // 提取关联中用到的各种字段和表数据。 + BasicAggregationRelationInfo basicRelationInfo = + this.parseBasicAggregationRelationInfo(relationStruct, criteriaListMap); + // 构建多表关联的where语句 + StringBuilder whereClause = new StringBuilder(256); + // 如果需要从表聚合计算或参与过滤,则需要把中间表和从表之间的关联条件加上。 + if (!basicRelationInfo.onlySelectRelationTable) { + whereClause.append(basicRelationInfo.relationTable) + .append(".") + .append(basicRelationInfo.relationSlaveColumn) + .append(" = ") + .append(basicRelationInfo.slaveTable) + .append(".") + .append(basicRelationInfo.slaveColumn); + } else { + whereClause.append("1 = 1"); + } + List criteriaList = criteriaListMap.get(relationStruct.relationField.getName()); + if (criteriaList == null) { + criteriaList = new LinkedList<>(); + } + MyWhereCriteria inlistFilter = new MyWhereCriteria(); + inlistFilter.setCriteria(relation.relationModelClass(), + relation.relationMasterIdField(), MyWhereCriteria.OPERATOR_IN, masterIdSet); + criteriaList.add(inlistFilter); + if (StringUtils.isNotBlank(relationStruct.service.deletedFlagFieldName)) { + MyWhereCriteria deleteFilter = new MyWhereCriteria(); + deleteFilter.setCriteria( + relation.slaveModelClass(), + relationStruct.service.deletedFlagFieldName, + MyWhereCriteria.OPERATOR_EQUAL, + GlobalDeletedFlag.NORMAL); + criteriaList.add(deleteFilter); + } + String criteriaString = MyWhereCriteria.makeCriteriaString(criteriaList); + whereClause.append(AND_OP).append(criteriaString); + StringBuilder tableNames = new StringBuilder(64); + tableNames.append(basicRelationInfo.relationTable); + if (!basicRelationInfo.onlySelectRelationTable) { + tableNames.append(", ").append(basicRelationInfo.slaveTable); + } + List> aggregationMapList = + mapper().getGroupedListByCondition(tableNames.toString(), + basicRelationInfo.selectList, whereClause.toString(), basicRelationInfo.groupBy); + doMakeLocalAggregationData(aggregationMapList, resultList, relationStruct); + } + } + + /** + * 根据实体对象和过滤条件,集成本地多对多关联聚合计算数据。 + * + * @param dataObject 实体对象。 + * @param criteriaListMap 过滤参数。key为主表字段名称,value是过滤条件列表。 + */ + private void buildManyToManyAggregationForData( + T dataObject, Map> criteriaListMap) { + if (dataObject == null || CollectionUtils.isEmpty(this.relationManyToManyAggrStructList)) { + return; + } + if (criteriaListMap == null) { + criteriaListMap = new HashMap<>(relationManyToManyAggrStructList.size()); + } + for (RelationStruct relationStruct : this.relationManyToManyAggrStructList) { + Object masterIdValue = ReflectUtil.getFieldValue(dataObject, relationStruct.masterIdField); + if (masterIdValue == null) { + continue; + } + BasicAggregationRelationInfo basicRelationInfo = + this.parseBasicAggregationRelationInfo(relationStruct, criteriaListMap); + // 组装过滤条件 + String whereClause = this.makeManyToManyWhereClause( + relationStruct, masterIdValue, basicRelationInfo, criteriaListMap); + StringBuilder tableNames = new StringBuilder(64); + tableNames.append(basicRelationInfo.relationTable); + if (!basicRelationInfo.onlySelectRelationTable) { + tableNames.append(", ").append(basicRelationInfo.slaveTable); + } + List> aggregationMapList = + mapper().getGroupedListByCondition(tableNames.toString(), + basicRelationInfo.selectList, whereClause, basicRelationInfo.groupBy); + // 将查询后的结果回填到主表数据中。 + if (CollectionUtils.isNotEmpty(aggregationMapList)) { + Object value = aggregationMapList.get(0).get(AGGREGATED_VALUE); + if (value != null) { + ReflectUtil.setFieldValue(dataObject, relationStruct.relationField, value); + } + } + } + } + + /** + * 根据实体对象参数列表和过滤条件,集成本地一对多关联聚合计算数据。 + * + * @param resultList 实体对象数据列表。 + * @param criteriaListMap 过滤参数。key为主表字段名称,value是过滤条件列表。 + */ + private void buildOneToManyAggregationForDataList( + List resultList, Map> criteriaListMap) { + // 处理多一多场景下,根据主表的结果,进行从表聚合数据的计算。 + if (CollectionUtils.isEmpty(this.relationOneToManyAggrStructList) + || CollectionUtils.isEmpty(resultList)) { + return; + } + if (criteriaListMap == null) { + criteriaListMap = new HashMap<>(relationOneToManyAggrStructList.size()); + } + for (RelationStruct relationStruct : this.relationOneToManyAggrStructList) { + Set masterIdSet = resultList.stream() + .map(obj -> ReflectUtil.getFieldValue(obj, relationStruct.masterIdField)) + .filter(Objects::nonNull) + .collect(toSet()); + if (CollectionUtils.isEmpty(masterIdSet)) { + continue; + } + RelationOneToManyAggregation relation = relationStruct.relationOneToManyAggregation; + // 开始获取后面所需的各种关联数据。此部分今后可以移植到缓存中,无需每次计算。 + String slaveTable = MyModelUtil.mapToTableName(relation.slaveModelClass()); + String slaveColumnName = MyModelUtil.mapToColumnName(relation.slaveIdField(), relation.slaveModelClass()); + Tuple2 selectAndGroupByTuple = makeSelectListAndGroupByClause( + slaveTable, slaveColumnName, relation.slaveModelClass(), + slaveTable, relation.aggregationField(), relation.aggregationType()); + String selectList = selectAndGroupByTuple.getFirst(); + String groupBy = selectAndGroupByTuple.getSecond(); + List criteriaList = criteriaListMap.get(relationStruct.relationField.getName()); + if (criteriaList == null) { + criteriaList = new LinkedList<>(); + } + MyWhereCriteria inlistFilter = new MyWhereCriteria(); + inlistFilter.setCriteria(relation.slaveModelClass(), + relation.slaveIdField(), MyWhereCriteria.OPERATOR_IN, masterIdSet); + criteriaList.add(inlistFilter); + if (StringUtils.isNotBlank(relationStruct.service.deletedFlagFieldName)) { + MyWhereCriteria deleteFilter = new MyWhereCriteria(); + deleteFilter.setCriteria( + relation.slaveModelClass(), + relationStruct.service.deletedFlagFieldName, + MyWhereCriteria.OPERATOR_EQUAL, + GlobalDeletedFlag.NORMAL); + criteriaList.add(deleteFilter); + } + String criteriaString = MyWhereCriteria.makeCriteriaString(criteriaList); + List> aggregationMapList = + mapper().getGroupedListByCondition(slaveTable, selectList, criteriaString, groupBy); + doMakeLocalAggregationData(aggregationMapList, resultList, relationStruct); + } + } + + /** + * 根据实体对象和过滤条件,集成本地一对多关联聚合计算数据。 + * + * @param dataObject 实体对象。 + * @param criteriaListMap 过滤参数。key为主表字段名称,value是过滤条件列表。 + */ + private void buildOneToManyAggregationForData( + T dataObject, Map> criteriaListMap) { + if (dataObject == null || CollectionUtils.isEmpty(this.relationOneToManyAggrStructList)) { + return; + } + if (criteriaListMap == null) { + criteriaListMap = new HashMap<>(relationOneToManyAggrStructList.size()); + } + for (RelationStruct relationStruct : this.relationOneToManyAggrStructList) { + Object masterIdValue = ReflectUtil.getFieldValue(dataObject, relationStruct.masterIdField); + if (masterIdValue == null) { + continue; + } + RelationOneToManyAggregation relation = relationStruct.relationOneToManyAggregation; + String slaveTable = MyModelUtil.mapToTableName(relation.slaveModelClass()); + String slaveColumnName = + MyModelUtil.mapToColumnName(relation.slaveIdField(), relation.slaveModelClass()); + Tuple2 selectAndGroupByTuple = makeSelectListAndGroupByClause( + slaveTable, slaveColumnName, relation.slaveModelClass(), + slaveTable, relation.aggregationField(), relation.aggregationType()); + String selectList = selectAndGroupByTuple.getFirst(); + String groupBy = selectAndGroupByTuple.getSecond(); + String whereClause = this.makeOneToManyWhereClause( + relationStruct, masterIdValue, slaveColumnName, criteriaListMap); + // 获取分组聚合计算结果 + List> aggregationMapList = + mapper().getGroupedListByCondition(slaveTable, selectList, whereClause, groupBy); + // 将计算结果回填到主表关联字段 + if (CollectionUtils.isNotEmpty(aggregationMapList)) { + Object value = aggregationMapList.get(0).get(AGGREGATED_VALUE); + if (value != null) { + ReflectUtil.setFieldValue(dataObject, relationStruct.relationField, value); + } + } + } + } + + /** + * 仅仅在spring boot 启动后的监听器事件中调用,缓存所有service的关联关系,加速后续的数据绑定效率。 + */ + public void loadRelationStruct() { + Field[] fields = ReflectUtil.getFields(modelClass); + for (Field f : fields) { + initializeRelationDictStruct(f); + initializeRelationStruct(f); + initializeRelationAggregationStruct(f); + } + } + + /** + * 缺省实现返回null,在进行一对多和多对多聚合计算时,没有额外的自定义过滤条件。如有需要,需子类自行实现。 + * + * @return 自定义过滤条件列表。 + */ + protected Map> buildAggregationAdditionalWhereCriteria() { + return null; + } + + /** + * 判断当前对象的关联字段数据是否需要被验证,如果原有对象为null,表示新对象第一次插入,则必须验证。 + * + * @param object 新对象。 + * @param originalObject 原有对象。 + * @param fieldGetter 获取需要验证字段的函数对象。 + * @param 需要验证字段的类型。 + * @return 需要关联验证返回true,否则false。 + */ + protected boolean needToVerify(M object, M originalObject, Function fieldGetter) { + T data = fieldGetter.apply(object); + if (data == null) { + return false; + } + if (data instanceof String) { + String stringData = (String) data; + if (stringData.length() == 0) { + return false; + } + } + if (originalObject == null) { + return true; + } + T originalData = fieldGetter.apply(originalObject); + return !data.equals(originalData); + } + + /** + * 通过(In-list)条件和orderBy条件,构建Example对象,以供后续的查询操作使用。 + * + * @param inFilterField 参与(In-list)过滤的Java字段。 + * @param inFilterValues 参与(In-list)过滤的Java字段值集合。 + * @param orderBy 排序字段。 + * @param in 属性字段的类型。 + * @return 构建后的Example对象。 + */ + protected Example makeDefaultInListExample(String inFilterField, Collection inFilterValues, String orderBy) { + Set inFilterValueSet; + Example e = new Example(modelClass); + if (StringUtils.isNotBlank(orderBy)) { + e.setOrderByClause(orderBy); + } + if (inFilterValues instanceof Set) { + inFilterValueSet = (Set) inFilterValues; + } else { + inFilterValueSet = new HashSet<>(inFilterValues.size()); + inFilterValueSet.addAll(inFilterValues); + } + e.createCriteria().andIn(inFilterField, inFilterValueSet); + return e; + } + + private void initializeRelationStruct(Field f) { + RelationOneToOne relationOneToOne = f.getAnnotation(RelationOneToOne.class); + if (relationOneToOne != null) { + RelationStruct relationStruct = new RelationStruct(); + relationStruct.relationField = f; + relationStruct.masterIdField = ReflectUtil.getField(modelClass, relationOneToOne.masterIdField()); + relationStruct.relationOneToOne = relationOneToOne; + relationStruct.service = ApplicationContextHolder.getBean( + StringUtils.uncapitalize(relationOneToOne.slaveServiceName())); + relationOneToOneStructList.add(relationStruct); + return; + } + RelationManyToMany relationManyToMany = f.getAnnotation(RelationManyToMany.class); + if (relationManyToMany != null) { + RelationStruct relationStruct = new RelationStruct(); + relationStruct.relationField = f; + relationStruct.masterIdField = ReflectUtil.getField(modelClass, relationManyToMany.relationMasterIdField()); + relationStruct.relationManyToMany = relationManyToMany; + relationStruct.manyToManyMapper = ApplicationContextHolder.getBean( + StringUtils.uncapitalize(relationManyToMany.relationMapperName())); + relationManyToManyStructList.add(relationStruct); + } + } + + private void initializeRelationAggregationStruct(Field f) { + RelationOneToManyAggregation relationOneToManyAggregation = f.getAnnotation(RelationOneToManyAggregation.class); + if (relationOneToManyAggregation != null) { + RelationStruct relationStruct = new RelationStruct(); + relationStruct.relationField = f; + relationStruct.masterIdField = ReflectUtil.getField(modelClass, relationOneToManyAggregation.masterIdField()); + relationStruct.relationOneToManyAggregation = relationOneToManyAggregation; + relationStruct.service = ApplicationContextHolder.getBean( + StringUtils.uncapitalize(relationOneToManyAggregation.slaveServiceName())); + relationOneToManyAggrStructList.add(relationStruct); + return; + } + RelationManyToManyAggregation relationManyToManyAggregation = f.getAnnotation(RelationManyToManyAggregation.class); + if (relationManyToManyAggregation != null) { + RelationStruct relationStruct = new RelationStruct(); + relationStruct.relationField = f; + relationStruct.masterIdField = ReflectUtil.getField(modelClass, relationManyToManyAggregation.masterIdField()); + relationStruct.relationManyToManyAggregation = relationManyToManyAggregation; + relationStruct.service = ApplicationContextHolder.getBean( + StringUtils.uncapitalize(relationManyToManyAggregation.slaveServiceName())); + relationManyToManyAggrStructList.add(relationStruct); + } + } + + @SuppressWarnings("unchecked") + private void initializeRelationDictStruct(Field f) { + RelationConstDict relationConstDict = f.getAnnotation(RelationConstDict.class); + if (relationConstDict != null) { + RelationStruct relationStruct = new RelationStruct(); + relationStruct.relationField = f; + relationStruct.masterIdField = ReflectUtil.getField(modelClass, relationConstDict.masterIdField()); + Field dictMapField = ReflectUtil.getField(relationConstDict.constantDictClass(), "DICT_MAP"); + relationStruct.dictMap = (Map) ReflectUtil.getFieldValue(modelClass, dictMapField); + relationConstDictStructList.add(relationStruct); + return; + } + RelationDict relationDict = f.getAnnotation(RelationDict.class); + if (relationDict != null) { + RelationStruct relationStruct = new RelationStruct(); + relationStruct.relationField = f; + relationStruct.masterIdField = ReflectUtil.getField(modelClass, relationDict.masterIdField()); + relationStruct.relationDict = relationDict; + if (StringUtils.isNotBlank(relationDict.equalOneToOneRelationField())) { + relationStruct.equalOneToOneRelationField = + ReflectUtil.getField(modelClass, relationDict.equalOneToOneRelationField()); + } + relationStruct.service = ApplicationContextHolder.getBean( + StringUtils.uncapitalize(relationDict.slaveServiceName())); + relationDictStructList.add(relationStruct); + } + } + + private BasicAggregationRelationInfo parseBasicAggregationRelationInfo( + RelationStruct relationStruct, Map> criteriaListMap) { + RelationManyToManyAggregation relation = relationStruct.relationManyToManyAggregation; + BasicAggregationRelationInfo relationInfo = new BasicAggregationRelationInfo(); + // 提取关联中用到的各种字段和表数据。 + relationInfo.slaveTable = MyModelUtil.mapToTableName(relation.slaveModelClass()); + relationInfo.relationTable = MyModelUtil.mapToTableName(relation.relationModelClass()); + relationInfo.relationMasterColumn = + MyModelUtil.mapToColumnName(relation.relationMasterIdField(), relation.relationModelClass()); + relationInfo.relationSlaveColumn = + MyModelUtil.mapToColumnName(relation.relationSlaveIdField(), relation.relationModelClass()); + relationInfo.slaveColumn = MyModelUtil.mapToColumnName(relation.slaveIdField(), relation.slaveModelClass()); + // 判断是否只需要关联中间表即可,从而提升查询统计的效率。 + // 1. 统计字段为中间表字段。2. 自定义过滤条件中没有基于从表字段的过滤条件。 + relationInfo.onlySelectRelationTable = + relation.aggregationModelClass().equals(relation.relationModelClass()); + if (relationInfo.onlySelectRelationTable && MapUtils.isNotEmpty(criteriaListMap)) { + List criteriaList = + criteriaListMap.get(relationStruct.relationField.getName()); + if (CollectionUtils.isNotEmpty(criteriaList)) { + for (MyWhereCriteria whereCriteria : criteriaList) { + if (whereCriteria.getModelClazz().equals(relation.slaveModelClass())) { + relationInfo.onlySelectRelationTable = false; + break; + } + } + } + } + String aggregationTable = relation.aggregationModelClass().equals(relation.relationModelClass()) + ? relationInfo.relationTable : relationInfo.slaveTable; + Tuple2 selectAndGroupByTuple = makeSelectListAndGroupByClause( + relationInfo.relationTable, relationInfo.relationMasterColumn, relation.aggregationModelClass(), + aggregationTable, relation.aggregationField(), relation.aggregationType()); + relationInfo.selectList = selectAndGroupByTuple.getFirst(); + relationInfo.groupBy = selectAndGroupByTuple.getSecond(); + return relationInfo; + } + + private String makeManyToManyWhereClause( + RelationStruct relationStruct, + Object masterIdValue, + BasicAggregationRelationInfo basicRelationInfo, + Map> criteriaListMap) { + StringBuilder whereClause = new StringBuilder(256); + whereClause.append(basicRelationInfo.relationTable) + .append(".").append(basicRelationInfo.relationMasterColumn); + if (masterIdValue instanceof Number) { + whereClause.append(" = ").append(masterIdValue); + } else { + whereClause.append(" = '").append(masterIdValue).append("'"); + } + // 如果需要从表聚合计算或参与过滤,则需要把中间表和从表之间的关联条件加上。 + if (!basicRelationInfo.onlySelectRelationTable) { + whereClause.append(AND_OP) + .append(basicRelationInfo.relationTable) + .append(".") + .append(basicRelationInfo.relationSlaveColumn) + .append(" = ") + .append(basicRelationInfo.slaveTable) + .append(".") + .append(basicRelationInfo.slaveColumn); + } + List criteriaList = criteriaListMap.get(relationStruct.relationField.getName()); + if (criteriaList == null) { + criteriaList = new LinkedList<>(); + } + if (StringUtils.isNotBlank(relationStruct.service.deletedFlagFieldName)) { + MyWhereCriteria deleteFilter = new MyWhereCriteria(); + deleteFilter.setCriteria( + relationStruct.relationManyToManyAggregation.slaveModelClass(), + relationStruct.service.deletedFlagFieldName, + MyWhereCriteria.OPERATOR_EQUAL, + GlobalDeletedFlag.NORMAL); + criteriaList.add(deleteFilter); + } + if (CollectionUtils.isNotEmpty(criteriaList)) { + String criteriaString = MyWhereCriteria.makeCriteriaString(criteriaList); + whereClause.append(AND_OP).append(criteriaString); + } + return whereClause.toString(); + } + + private String makeOneToManyWhereClause( + RelationStruct relationStruct, + Object masterIdValue, + String slaveColumnName, + Map> criteriaListMap) { + StringBuilder whereClause = new StringBuilder(64); + if (masterIdValue instanceof Number) { + whereClause.append(slaveColumnName).append(" = ").append(masterIdValue); + } else { + whereClause.append(slaveColumnName).append(" = '").append(masterIdValue).append("'"); + } + List criteriaList = criteriaListMap.get(relationStruct.relationField.getName()); + if (criteriaList == null) { + criteriaList = new LinkedList<>(); + } + if (StringUtils.isNotBlank(relationStruct.service.deletedFlagFieldName)) { + MyWhereCriteria deleteFilter = new MyWhereCriteria(); + deleteFilter.setCriteria( + relationStruct.relationOneToManyAggregation.slaveModelClass(), + relationStruct.service.deletedFlagFieldName, + MyWhereCriteria.OPERATOR_EQUAL, + GlobalDeletedFlag.NORMAL); + criteriaList.add(deleteFilter); + } + if (CollectionUtils.isNotEmpty(criteriaList)) { + String criteriaString = MyWhereCriteria.makeCriteriaString(criteriaList); + whereClause.append(AND_OP).append(criteriaString); + } + return whereClause.toString(); + } + + private static class BasicAggregationRelationInfo { + private String slaveTable; + private String slaveColumn; + private String relationTable; + private String relationMasterColumn; + private String relationSlaveColumn; + private String selectList; + private String groupBy; + private boolean onlySelectRelationTable; + } + + private void doMakeLocalAggregationData( + List> aggregationMapList, List resultList, RelationStruct relationStruct) { + if (CollectionUtils.isEmpty(resultList)) { + return; + } + // 根据获取的分组聚合结果集,绑定到主表总的关联字段。 + if (CollectionUtils.isNotEmpty(aggregationMapList)) { + Map relatedMap = new HashMap<>(aggregationMapList.size()); + for (Map map : aggregationMapList) { + relatedMap.put(map.get(GROUPED_KEY), map.get(AGGREGATED_VALUE)); + } + for (M dataObject : resultList) { + Object masterIdValue = ReflectUtil.getFieldValue(dataObject, relationStruct.masterIdField); + if (masterIdValue != null) { + Object value = relatedMap.get(masterIdValue); + if (value != null) { + ReflectUtil.setFieldValue(dataObject, relationStruct.relationField, value); + } + } + } + } + } + + private Tuple2 makeSelectListAndGroupByClause( + String groupTableName, + String groupColumnName, + Class aggregationModel, + String aggregationTableName, + String aggregationField, + Integer aggregationType) { + if (!AggregationType.isValid(aggregationType)) { + throw new IllegalArgumentException("Invalid AggregationType Value [" + + aggregationType + "] in Model [" + aggregationModel.getName() + "]."); + } + String aggregationFunc = AggregationType.getAggregationFunction(aggregationType); + String aggregationColumn = MyModelUtil.mapToColumnName(aggregationField, aggregationModel); + if (StringUtils.isBlank(aggregationColumn)) { + throw new IllegalArgumentException("Invalid AggregationField [" + + aggregationField + "] in Model [" + aggregationModel.getName() + "]."); + } + // 构建Select List + // 如:r_table.master_id groupedKey, SUM(r_table.aggr_column) aggregated_value + StringBuilder groupedSelectList = new StringBuilder(128); + groupedSelectList.append(groupTableName) + .append(".") + .append(groupColumnName) + .append(" ") + .append(GROUPED_KEY) + .append(", ") + .append(aggregationFunc) + .append("(") + .append(aggregationTableName) + .append(".") + .append(aggregationColumn) + .append(") ") + .append(AGGREGATED_VALUE) + .append(" "); + StringBuilder groupBy = new StringBuilder(64); + groupBy.append(groupTableName).append(".").append(groupColumnName); + return new Tuple2<>(groupedSelectList.toString(), groupBy.toString()); + } + + static class RelationStruct { + private Field relationField; + private Field masterIdField; + private Field equalOneToOneRelationField; + private BaseService service; + private BaseDaoMapper manyToManyMapper; + private Map dictMap; + private RelationDict relationDict; + private RelationOneToOne relationOneToOne; + private RelationManyToMany relationManyToMany; + private RelationOneToManyAggregation relationOneToManyAggregation; + private RelationManyToManyAggregation relationManyToManyAggregation; + } +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/cache/CacheConfig.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/cache/CacheConfig.java new file mode 100644 index 00000000..a1522ace --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/cache/CacheConfig.java @@ -0,0 +1,90 @@ +package com.orange.demo.common.core.cache; + +import com.github.benmanes.caffeine.cache.Caffeine; +import org.springframework.cache.CacheManager; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.cache.caffeine.CaffeineCache; +import org.springframework.cache.support.SimpleCacheManager; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.ArrayList; +import java.util.concurrent.TimeUnit; + +/** + * 使用Caffeine作为本地缓存库 + * + * @author Jerry + * @date 2020-09-25 + */ +@Configuration +@EnableCaching +public class CacheConfig { + + private static final int DEFAULT_MAXSIZE = 10000; + private static final int DEFAULT_TTL = 3600; + + /** + * 定义cache名称、超时时长秒、最大个数 + * 每个cache缺省3600秒过期,最大个数1000 + */ + public enum CacheEnum { + /** + * 专门存储用户权限的缓存。 + */ + USER_PERMISSION_CACHE(1800, 10000), + /** + * session下上传文件名的缓存(时间是24小时)。 + */ + UPLOAD_FILENAME_CACHE(86400, 20000), + /** + * 缺省全局缓存(时间是24小时)。 + */ + GLOBAL_CACHE(86400, 20000); + + CacheEnum() { + } + + CacheEnum(int ttl, int maxSize) { + this.ttl = ttl; + this.maxSize = maxSize; + } + + /** + * 缓存的最大数量。 + */ + private int maxSize = DEFAULT_MAXSIZE; + /** + * 缓存的时长(单位:秒) + */ + private int ttl = DEFAULT_TTL; + + public int getMaxSize() { + return maxSize; + } + + public int getTtl() { + return ttl; + } + } + + /** + * 初始化缓存配置。 + */ + @Bean + public CacheManager cacheManager() { + SimpleCacheManager manager = new SimpleCacheManager(); + //把各个cache注册到cacheManager中,CaffeineCache实现了org.springframework.cache.Cache接口 + ArrayList caches = new ArrayList<>(); + for (CacheEnum c : CacheEnum.values()) { + caches.add(new CaffeineCache(c.name(), + Caffeine.newBuilder().recordStats() + .expireAfterAccess(c.getTtl(), TimeUnit.SECONDS) + .maximumSize(c.getMaxSize()) + .build()) + ); + } + manager.setCaches(caches); + return manager; + } +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/cache/DictionaryCache.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/cache/DictionaryCache.java new file mode 100644 index 00000000..31fef714 --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/cache/DictionaryCache.java @@ -0,0 +1,88 @@ +package com.orange.demo.common.core.cache; + +import java.util.List; +import java.util.Set; + +/** + * 主要用于完整缓存字典表数据的接口对象。 + * + * @param 字典表主键类型。 + * @param 字典表对象类型。 + * @author Jerry + * @date 2020-09-25 + */ +public interface DictionaryCache { + + /** + * 按照数据插入的顺序返回全部字典对象的列表。 + * + * @return 全部字段数据列表。 + */ + List getAll(); + + /** + * 获取缓存中与键列表对应的对象列表。 + * + * @param keys 主键集合。 + * @return 对象列表。 + */ + List getInList(Set keys); + + /** + * 将参数List中的数据保存到缓存中,同时保证getAll返回的数据列表,与参数列表中数据项的顺序保持一致。 + * + * @param dataList 待缓存的数据列表。 + */ + void putAll(List dataList); + + /** + * 重新加载,先清空原有数据,在执行putAll的操作。 + * + * @param dataList 待缓存的数据列表。 + * @param force true则强制刷新,如果false,当缓存中存在数据时不刷新。 + */ + void reload(List dataList, boolean force); + + /** + * 从缓存中获取指定的数据。 + * + * @param key 数据的key。 + * @return 获取到的数据,如果没有返回null。 + */ + V get(K key); + + /** + * 将数据存入缓存。 + * + * @param key 通常为字典数据的主键。 + * @param object 字典数据对象。 + */ + void put(K key, V object); + + /** + * 获取缓存中数据条目的数量。 + * + * @return 返回缓存的数据数量。 + */ + int getCount(); + + /** + * 删除缓存中指定的键。 + * + * @param key 待删除数据的主键。 + * @return 返回被删除的对象,如果主键不存在,返回null。 + */ + V invalidate(K key); + + /** + * 删除缓存中,参数列表中包含的键。 + * + * @param keys 待删除数据的主键集合。 + */ + void invalidateSet(Set keys); + + /** + * 清空缓存。 + */ + void invalidateAll(); +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/cache/MapDictionaryCache.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/cache/MapDictionaryCache.java new file mode 100644 index 00000000..431772d9 --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/cache/MapDictionaryCache.java @@ -0,0 +1,176 @@ +package com.orange.demo.common.core.cache; + +import java.util.*; +import java.util.function.Function; + +/** + * 字典数据内存缓存对象。 + * + * @param 字典表主键类型。 + * @param 字典表对象类型。 + * @author Jerry + * @date 2020-09-25 + */ +public class MapDictionaryCache implements DictionaryCache { + + /** + * 存储字典数据的Map。 + */ + protected LinkedHashMap dataMap = new LinkedHashMap<>(); + /** + * 获取字典主键数据的函数对象。 + */ + protected Function idGetter; + + /** + * 当前对象的构造器函数。 + * + * @param idGetter 获取当前类主键字段值的函数对象。 + * @param 字典主键类型。 + * @param 字典对象类型 + * @return 实例化后的字典内存缓存对象。 + */ + public static MapDictionaryCache create(Function idGetter) { + if (idGetter == null) { + throw new IllegalArgumentException("IdGetter can't be NULL."); + } + return new MapDictionaryCache<>(idGetter); + } + + /** + * 构造函数。 + * + * @param idGetter 主键Id的获取函数对象。 + */ + public MapDictionaryCache(Function idGetter) { + this.idGetter = idGetter; + } + + /** + * 按照数据插入的顺序返回全部字典对象的列表。 + * + * @return 全部字段数据列表。 + */ + @Override + public synchronized List getAll() { + List resultList = new LinkedList<>(); + for (Map.Entry entry : dataMap.entrySet()) { + resultList.add(entry.getValue()); + } + return resultList; + } + + /** + * 获取缓存中与键列表对应的对象列表。 + * + * @param keys 主键集合。 + * @return 对象列表。 + */ + @Override + public synchronized List getInList(Set keys) { + List resultList = new LinkedList<>(); + keys.forEach(key -> { + V object = dataMap.get(key); + if (object != null) { + resultList.add(object); + } + }); + return resultList; + } + + /** + * 将参数List中的数据保存到缓存中,同时保证getAll返回的数据列表,与参数列表中数据项的顺序保持一致。 + * + * @param dataList 待缓存的数据列表。 + */ + @Override + public synchronized void putAll(List dataList) { + if (dataList == null) { + return; + } + dataList.forEach(dataObj -> { + K id = idGetter.apply(dataObj); + dataMap.put(id, dataObj); + }); + } + + /** + * 重新加载,先清空原有数据,在执行putAll的操作。 + * + * @param dataList 待缓存的数据列表。 + * @param force true则强制刷新,如果false,当缓存中存在数据时不刷新。 + */ + @Override + public synchronized void reload(List dataList, boolean force) { + if (!force && this.getCount() > 0) { + return; + } + this.invalidateAll(); + this.putAll(dataList); + } + + /** + * 从缓存中获取指定的数据。 + * + * @param id 数据的key。 + * @return 获取到的数据,如果没有返回null。 + */ + @Override + public synchronized V get(K id) { + return id == null ? null : dataMap.get(id); + } + + /** + * 将数据存入缓存。 + * + * @param id 通常为字典数据的主键。 + * @param object 字典数据对象。 + */ + @Override + public synchronized void put(K id, V object) { + dataMap.put(id, object); + } + + /** + * 获取缓存中数据条目的数量。 + * + * @return 返回缓存的数据数量。 + */ + @Override + public synchronized int getCount() { + return dataMap.size(); + } + + /** + * 删除缓存中指定的键。 + * + * @param id 待删除数据的主键。 + * @return 返回被删除的对象,如果主键不存在,返回null。 + */ + @Override + public synchronized V invalidate(K id) { + return id == null ? null : dataMap.remove(id); + } + + /** + * 删除缓存中,参数列表中包含的键。 + * + * @param keys 待删除数据的主键集合。 + */ + @Override + public synchronized void invalidateSet(Set keys) { + keys.forEach(id -> { + if (id != null) { + dataMap.remove(id); + } + }); + } + + /** + * 清空缓存。 + */ + @Override + public synchronized void invalidateAll() { + dataMap.clear(); + } +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/cache/MapTreeDictionaryCache.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/cache/MapTreeDictionaryCache.java new file mode 100644 index 00000000..d16d86c3 --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/cache/MapTreeDictionaryCache.java @@ -0,0 +1,142 @@ +package com.orange.demo.common.core.cache; + +import com.google.common.collect.LinkedHashMultimap; +import com.google.common.collect.Multimap; + +import java.util.*; +import java.util.function.Function; + +/** + * 树形字典数据内存缓存对象。 + * + * @param 字典表主键类型。 + * @param 字典表对象类型。 + * @author Jerry + * @date 2020-09-25 + */ +public class MapTreeDictionaryCache extends MapDictionaryCache { + + /** + * 树形数据存储对象。 + */ + private final Multimap allTreeMap = LinkedHashMultimap.create(); + /** + * 获取字典父主键数据的函数对象。 + */ + protected Function parentIdGetter; + + /** + * 当前对象的构造器函数。 + * + * @param idGetter 获取当前类主键字段值的函数对象。 + * @param parentIdGetter 获取当前类父主键字段值的函数对象。 + * @param 字典主键类型。 + * @param 字典对象类型 + * @return 实例化后的树形字典内存缓存对象。 + */ + public static MapTreeDictionaryCache create(Function idGetter, Function parentIdGetter) { + if (idGetter == null) { + throw new IllegalArgumentException("IdGetter can't be NULL."); + } + if (parentIdGetter == null) { + throw new IllegalArgumentException("ParentIdGetter can't be NULL."); + } + return new MapTreeDictionaryCache<>(idGetter, parentIdGetter); + } + + /** + * 构造函数。 + * + * @param idGetter 获取当前类主键字段值的函数对象。 + * @param parentIdGetter 获取当前类父主键字段值的函数对象。 + */ + public MapTreeDictionaryCache(Function idGetter, Function parentIdGetter) { + super(idGetter); + this.parentIdGetter = parentIdGetter; + } + + /** + * 获取该父主键的子数据列表。 + * + * @param parentId 父主键Id。 + * @return 子数据列表。 + */ + public synchronized List getListByParentId(K parentId) { + return new LinkedList<>(allTreeMap.get(parentId)); + } + + /** + * 将参数List中的数据保存到缓存中,同时保证getAll返回的数据列表,与参数列表中数据项的顺序保持一致。 + * + * @param dataList 待缓存的数据列表。 + */ + @Override + public synchronized void putAll(List dataList) { + if (dataList == null) { + return; + } + super.putAll(dataList); + dataList.forEach(data -> { + K parentId = parentIdGetter.apply(data); + allTreeMap.remove(parentId, data); + allTreeMap.put(parentId, data); + }); + } + + /** + * 将数据存入缓存。 + * + * @param id 通常为字典数据的主键。 + * @param data 字典数据对象。 + */ + @Override + public synchronized void put(K id, V data) { + super.put(id, data); + K parentId = parentIdGetter.apply(data); + allTreeMap.remove(parentId, data); + allTreeMap.put(parentId, data); + } + + /** + * 删除缓存中指定的键。 + * + * @param id 待删除数据的主键。 + * @return 返回被删除的对象,如果主键不存在,返回null。 + */ + @Override + public synchronized V invalidate(K id) { + V v = super.invalidate(id); + if (v != null) { + K parentId = parentIdGetter.apply(v); + allTreeMap.remove(parentId, v); + } + return v; + } + + /** + * 删除缓存中,参数列表中包含的键。 + * + * @param keys 待删除数据的主键集合。 + */ + @Override + public synchronized void invalidateSet(Set keys) { + keys.forEach(id -> { + if (id != null) { + V data = dataMap.remove(id); + if (data != null) { + K parentId = parentIdGetter.apply(data); + allTreeMap.remove(parentId, data); + } + } + }); + } + + /** + * 清空缓存。 + */ + @Override + public synchronized void invalidateAll() { + super.invalidateAll(); + allTreeMap.clear(); + } +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/cache/SessionCacheHelper.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/cache/SessionCacheHelper.java new file mode 100644 index 00000000..a68212c6 --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/cache/SessionCacheHelper.java @@ -0,0 +1,97 @@ +package com.orange.demo.common.core.cache; + +import com.orange.demo.common.core.object.TokenData; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.Cache; +import org.springframework.cache.CacheManager; +import org.springframework.stereotype.Component; + +import java.util.HashSet; +import java.util.Set; + +/** + * Session数据缓存辅助类。 + * + * @author Jerry + * @date 2020-09-25 + */ +@SuppressWarnings("unchecked") +@Component +public class SessionCacheHelper { + + @Autowired + private CacheManager cacheManager; + + /** + * 缓存当前session内,上传过的文件名。 + * + * @param filename 通常是本地存储的文件名,而不是上传时的原始文件名。 + */ + public void putSessionUploadFile(String filename) { + if (filename != null) { + Set sessionUploadFileSet = null; + Cache cache = cacheManager.getCache(CacheConfig.CacheEnum.UPLOAD_FILENAME_CACHE.name()); + Cache.ValueWrapper valueWrapper = cache.get(TokenData.takeFromRequest().getSessionId()); + if (valueWrapper != null) { + sessionUploadFileSet = (Set) valueWrapper.get(); + } + if (sessionUploadFileSet == null) { + sessionUploadFileSet = new HashSet<>(); + } + sessionUploadFileSet.add(filename); + cache.put(TokenData.takeFromRequest().getSessionId(), sessionUploadFileSet); + } + } + + /** + * 判断参数中的文件名,是否有当前session上传。 + * + * @param filename 通常是本地存储的文件名,而不是上传时的原始文件名。 + * @return true表示该文件是由当前session上传并存储在本地的,否则false。 + */ + public boolean existSessionUploadFile(String filename) { + if (filename == null) { + return false; + } + Cache cache = cacheManager.getCache(CacheConfig.CacheEnum.UPLOAD_FILENAME_CACHE.name()); + Cache.ValueWrapper valueWrapper = cache.get(TokenData.takeFromRequest().getSessionId()); + if (valueWrapper == null) { + return false; + } + return ((Set) valueWrapper.get()).contains(filename); + } + + /** + * 存放session的Token数据。 + * + * @param sessionId 当前会话的SessionId。 + * @param tokenData 当前会话的JWT Token对象。 + */ + public void putTokenData(String sessionId, TokenData tokenData) { + if (sessionId == null || tokenData == null) { + return; + } + Cache cache = cacheManager.getCache(CacheConfig.CacheEnum.GLOBAL_CACHE.name()); + cache.put(sessionId, tokenData); + } + + /** + * 获取session的JWT Token对象。 + * + * @param sessionId 当前会话的SessionId。 + * @return 当前会话的JWT Token对象。 + */ + public TokenData getTokenData(String sessionId) { + Cache cache = cacheManager.getCache(CacheConfig.CacheEnum.GLOBAL_CACHE.name()); + return cache.get(sessionId, TokenData.class); + } + + /** + * 清除当前session的所有缓存数据。 + */ + public void removeAllSessionCache() { + for (CacheConfig.CacheEnum c : CacheConfig.CacheEnum.values()) { + cacheManager.getCache(c.name()).clear(); + } + } +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/config/CommonWebMvcConfig.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/config/CommonWebMvcConfig.java new file mode 100644 index 00000000..1dcec660 --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/config/CommonWebMvcConfig.java @@ -0,0 +1,67 @@ +package com.orange.demo.common.core.config; + +import com.alibaba.fastjson.serializer.SerializerFeature; +import com.alibaba.fastjson.support.config.FastJsonConfig; +import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter; +import com.orange.demo.common.core.interceptor.MyRequestArgumentResolver; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.MediaType; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.StringHttpMessageConverter; +import org.springframework.validation.beanvalidation.MethodValidationPostProcessor; +import org.springframework.web.method.support.HandlerMethodArgumentResolver; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; + +/** + * 所有的项目拦截器、参数解析器、消息对象转换器都在这里集中配置。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Configuration +public class CommonWebMvcConfig implements WebMvcConfigurer { + + @Bean + public MethodValidationPostProcessor methodValidationPostProcessor() { + return new MethodValidationPostProcessor(); + } + + @Override + public void addArgumentResolvers(List argumentResolvers) { + // 添加MyRequestBody参数解析器 + argumentResolvers.add(new MyRequestArgumentResolver()); + } + + @Bean + public HttpMessageConverter responseBodyConverter() { + return new StringHttpMessageConverter(StandardCharsets.UTF_8); + } + + @Bean + public FastJsonHttpMessageConverter fastJsonHttpMessageConverters() { + FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter(); + List supportedMediaTypes = new ArrayList<>(); + supportedMediaTypes.add(MediaType.APPLICATION_JSON); + supportedMediaTypes.add(MediaType.APPLICATION_FORM_URLENCODED); + fastConverter.setSupportedMediaTypes(supportedMediaTypes); + FastJsonConfig fastJsonConfig = new FastJsonConfig(); + fastJsonConfig.setSerializerFeatures( + SerializerFeature.PrettyFormat, + SerializerFeature.DisableCircularReferenceDetect, + SerializerFeature.IgnoreNonFieldGetter); + fastJsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss"); + fastConverter.setFastJsonConfig(fastJsonConfig); + return fastConverter; + } + + @Override + public void configureMessageConverters(List> converters) { + converters.add(responseBodyConverter()); + converters.add(fastJsonHttpMessageConverters()); + } +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/config/EncryptConfig.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/config/EncryptConfig.java new file mode 100644 index 00000000..783bb595 --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/config/EncryptConfig.java @@ -0,0 +1,20 @@ +package com.orange.demo.common.core.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; + +/** + * 目前用于用户密码加密,UAA接入应用客户端的client_secret加密。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Configuration +public class EncryptConfig { + + @Bean + public BCryptPasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/config/RestTemplateConfig.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/config/RestTemplateConfig.java new file mode 100644 index 00000000..8d99aa0c --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/config/RestTemplateConfig.java @@ -0,0 +1,64 @@ +package com.orange.demo.common.core.config; + +import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter; +import org.apache.http.client.HttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.client.ClientHttpRequestFactory; +import org.springframework.http.client.ClientHttpResponse; +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.StringHttpMessageConverter; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.web.client.DefaultResponseErrorHandler; +import org.springframework.web.client.RestOperations; +import org.springframework.web.client.RestTemplate; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.List; + +/** + * RestTemplate连接池配置对象。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Configuration +public class RestTemplateConfig { + private static final int MAX_TOTAL_CONNECTION = 50; + private static final int MAX_CONNECTION_PER_ROUTE = 20; + private static final int CONNECTION_TIMEOUT = 20000; + private static final int READ_TIMEOUT = 30000; + + @Bean + @ConditionalOnMissingBean({RestOperations.class, RestTemplate.class}) + public RestTemplate restTemplate() { + RestTemplate restTemplate = new RestTemplate(createFactory()); + List> messageConverters = restTemplate.getMessageConverters(); + messageConverters.removeIf( + c -> c instanceof StringHttpMessageConverter || c instanceof MappingJackson2HttpMessageConverter); + messageConverters.add(1, new StringHttpMessageConverter(StandardCharsets.UTF_8)); + messageConverters.add(new FastJsonHttpMessageConverter()); + restTemplate.setErrorHandler(new DefaultResponseErrorHandler() { + @Override + public void handleError(ClientHttpResponse response) throws IOException { + // 防止400+和500等错误被直接抛出异常,这里避开了缺省处理方式,所有的错误均交给业务代码处理。 + } + }); + return restTemplate; + } + + private ClientHttpRequestFactory createFactory() { + HttpClient httpClient = HttpClientBuilder.create() + .setMaxConnTotal(MAX_TOTAL_CONNECTION) + .setMaxConnPerRoute(MAX_CONNECTION_PER_ROUTE) + .build(); + HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient); + factory.setReadTimeout(READ_TIMEOUT); + factory.setConnectTimeout(CONNECTION_TIMEOUT); + return factory; + } +} \ No newline at end of file diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/config/TomcatConfig.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/config/TomcatConfig.java new file mode 100644 index 00000000..1171309f --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/config/TomcatConfig.java @@ -0,0 +1,39 @@ +package com.orange.demo.common.core.config; + +import org.apache.tomcat.util.descriptor.web.SecurityCollection; +import org.apache.tomcat.util.descriptor.web.SecurityConstraint; +import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * tomcat配置对象。当前配置禁用了PUT和DELETE方法,防止渗透攻击。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Configuration +public class TomcatConfig { + + @Bean + public TomcatServletWebServerFactory servletContainer() { + TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory(); + factory.addContextCustomizers(context -> { + SecurityConstraint securityConstraint = new SecurityConstraint(); + securityConstraint.setUserConstraint("CONFIDENTIAL"); + SecurityCollection collection = new SecurityCollection(); + collection.addPattern("/*"); + collection.addMethod("HEAD"); + collection.addMethod("PUT"); + collection.addMethod("PATCH"); + collection.addMethod("DELETE"); + collection.addMethod("TRACE"); + collection.addMethod("COPY"); + collection.addMethod("SEARCH"); + collection.addMethod("PROPFIND"); + securityConstraint.addCollection(collection); + context.addConstraint(securityConstraint); + }); + return factory; + } +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/constant/AggregationType.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/constant/AggregationType.java new file mode 100644 index 00000000..f95c04c6 --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/constant/AggregationType.java @@ -0,0 +1,81 @@ +package com.orange.demo.common.core.constant; + +import java.util.HashMap; +import java.util.Map; + +/** + * 聚合计算的常量类型对象。 + * + * @author Jerry + * @date 2020-09-25 + */ +public final class AggregationType { + + /** + * sum 计数 + */ + public static final int SUM = 0; + /** + * count 汇总 + */ + public static final int COUNT = 1; + /** + * average 平均值 + */ + public static final int AVG = 2; + /** + * min 最小值 + */ + public static final int MIN = 3; + /** + * max 最大值 + */ + public static final int MAX = 4; + + private static final Map DICT_MAP = new HashMap<>(5); + static { + DICT_MAP.put(0, "累计总和"); + DICT_MAP.put(1, "数量总和"); + DICT_MAP.put(2, "平均值"); + DICT_MAP.put(3, "最小值"); + DICT_MAP.put(4, "最大值"); + } + + /** + * 判断参数是否为当前常量字典的合法值。 + * + * @param value 待验证的参数值。 + * @return 合法返回true,否则false。 + */ + public static boolean isValid(Integer value) { + return value != null && DICT_MAP.containsKey(value); + } + + /** + * 获取与SQL对应的聚合函数字符串名称。 + * + * @return 聚合函数名称。 + */ + public static String getAggregationFunction(Integer aggregationType) { + switch (aggregationType) { + case COUNT: + return "COUNT"; + case AVG: + return "AVG"; + case SUM: + return "SUM"; + case MAX: + return "MAX"; + case MIN: + return "MIN"; + default: + throw new IllegalArgumentException("无效的聚合类型!"); + } + } + + /** + * 私有构造函数,明确标识该常量类的作用。 + */ + private AggregationType() { + } +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/constant/ApplicationConstant.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/constant/ApplicationConstant.java new file mode 100644 index 00000000..7efe88d6 --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/constant/ApplicationConstant.java @@ -0,0 +1,55 @@ +package com.orange.demo.common.core.constant; + +/** + * 应用程序的常量声明对象。 + * + * @author Jerry + * @date 2020-09-25 + */ +public final class ApplicationConstant { + + /** + * 图片文件上传的父目录。 + */ + public static final String UPLOAD_IMAGE_PARENT_PATH = "image"; + /** + * 附件文件上传的父目录。 + */ + public static final String UPLOAD_ATTACHMENT_PARENT_PATH = "attachment"; + /** + * CSV文件扩展名。 + */ + public static final String CSV_EXT = "csv"; + /** + * XLSX文件扩展名。 + */ + public static final String XLSX_EXT = "xlsx"; + /** + * 统计分类计算时,按天聚合计算的常量值。(前端在MyOrderParam和MyGroupParam中传给后台) + */ + public static final String DAY_AGGREGATION = "day"; + /** + * 统计分类计算时,按月聚合计算的常量值。(前端在MyOrderParam和MyGroupParam中传给后台) + */ + public static final String MONTH_AGGREGATION = "month"; + /** + * 统计分类计算时,按年聚合计算的常量值。(前端在MyOrderParam和MyGroupParam中传给后台) + */ + public static final String YEAR_AGGREGATION = "year"; + /** + * 请求头跟踪id名。 + */ + public static final String HTTP_HEADER_TRACE_ID = "traceId"; + /** + * 重要说明:该值为项目生成后的缺省密钥,仅为使用户可以快速上手并跑通流程。 + * 在实际的应用中,一定要为不同的项目或服务,自行生成公钥和私钥,并将 PRIVATE_KEY 的引用改为服务的配置项。 + * 密钥的生成方式,可通过执行common.core.util.RsaUtil类的main函数动态生成。 + */ + public static final String PRIVATE_KEY = + "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKkLhAydtOtA4WuIkkIIUVaGWu4ElOEAQF9GTulHHWOwCHI1UvcKolvS1G+mdsKcmGtEAQ92AUde/kDRGu8Wn7kLDtCgUfo72soHz7Qfv5pVB4ohMxQd/9cxeKjKbDoirhB9Z3xGF20zUozp4ZPLxpTtI7azr0xzUtd5+D/HfLDrAgMBAAECgYEApESZhDz4YyeAJiPnpJ06lS8oS2VOWzsIUs0av5uoloeoHXtt7Lx7u2kroHeNrl3Hy2yg7ypH4dgQkGHin3VHrVAgjG3TxhgBXIqqntzzk2AGJKBeIIkRX86uTvtKZyp3flUgcwcGmpepAHS1V1DPY3aVYvbcqAmoL6DX6VYN0NECQQDQUitMdC76lEtAr5/ywS0nrZJDo6U7eQ7ywx/eiJ+YmrSye8oorlAj1VBWG+Cl6jdHOHtTQyYv/tu71fjzQiJTAkEAz7wb47/vcSUpNWQxItFpXz0o6rbJh71xmShn1AKP7XptOVZGlW9QRYEzHabV9m/DHqI00cMGhHrWZAhCiTkUCQJAFsJjaJ7o4weAkTieyO7B+CvGZw1h5/V55Jvcx3s1tH5yb22G0Jr6tm9/r2isSnQkReutzZLwgR3e886UvD7lcQJAAUcD2OOuQkDbPwPNtYwaHMbQgJj9JkOI9kskUE5vuiMdltOr/XFAyhygRtdmy2wmhAK1VnDfkmL6/IR8fEGImQJABOB0KCalb0M8CPnqqHzozrD8gPObnIIr4aVvLIPATN2g7MM2N6F7JbI4RZFiKa92LV6bhQCY8OvHi5K2cgFpbw=="; + /** + * 私有构造函数,明确标识该常量类的作用。 + */ + private ApplicationConstant() { + } +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/constant/ErrorCodeEnum.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/constant/ErrorCodeEnum.java new file mode 100644 index 00000000..5e928b58 --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/constant/ErrorCodeEnum.java @@ -0,0 +1,78 @@ +package com.orange.demo.common.core.constant; + +/** + * 返回应答中的错误代码和错误信息。 + * + * @author Jerry + * @date 2020-09-25 + */ +public enum ErrorCodeEnum { + + /** + * 没有错误 + */ + NO_ERROR("没有错误"), + /** + * 未处理的异常! + */ + UNHANDLED_EXCEPTION("未处理的异常!"), + + ARGUMENT_NULL_EXIST("数据验证失败,接口调用参数存在空值,请核对!"), + ARGUMENT_PK_ID_NULL("数据验证失败,接口调用主键Id参数为空,请核对!"), + INVALID_ARGUMENT_FORMAT("数据验证失败,不合法的参数格式,请核对!"), + INVALID_STATUS_ARGUMENT("数据验证失败,无效的状态参数值,请核对!"), + INVALID_UPLOAD_FILE_ARGUMENT("数据验证失败,上传文件参数错误,请核对!"), + INVALID_UPLOAD_FILE_IOERROR("上传文件写入失败,请联系管理员!"), + UNAUTHORIZED_LOGIN("当前用户尚未登录或登录已超时,请重新登录!"), + UNAUTHORIZED_USER_PERMISSION("权限验证失败,当前用户不能访问该接口,请核对!"), + NO_ACCESS_PERMISSION("当前用户没有访问权限,请核对!"), + NO_OPERATION_PERMISSION("当前用户没有操作权限,请核对!"), + + PASSWORD_ERR("密码错误,请重试!"), + INVALID_USERNAME_PASSWORD("用户名或密码错误,请重试!"), + INVALID_ACCESS_TOKEN("无效的用户访问令牌!"), + INVALID_USER_STATUS("用户状态错误,请刷新后重试!"), + + HAS_CHILDREN_DATA("数据验证失败,子数据存在,请刷新后重试!"), + DATA_VALIDATAED_FAILED("数据验证失败,请核对!"), + UPLOAD_FILE_FAILED("文件上传失败,请联系管理员!"), + DATA_SAVE_FAILED("数据保存失败,请联系管理员!"), + DATA_ACCESS_FAILED("数据访问失败,请联系管理员!"), + DATA_PERM_ACCESS_FAILED("数据访问失败,您没有该页面的数据访问权限!"), + DUPLICATED_UNIQUE_KEY("数据保存失败,存在重复数据,请核对!"), + DATA_NOT_EXIST("数据不存在,请刷新后重试!"), + DATA_PARENT_LEVEL_ID_NOT_EXIST("数据验证失败,父级别关联Id不存在,请刷新后重试!"), + DATA_PARENT_ID_NOT_EXIST("数据验证失败,ParentId不存在,请核对!"), + INVALID_RELATED_RECORD_ID("数据验证失败,关联数据并不存在,请刷新后重试!"), + INVALID_DATA_MODEL("数据验证失败,无效的数据实体对象!"), + INVALID_DATA_FIELD("数据验证失败,无效的数据实体对象字段!"), + INVALID_CLASS_FIELD("数据验证失败,无效的类对象字段!"), + SERVER_INTERNAL_ERROR("服务器内部错误,请联系管理员!"), + REDIS_CACHE_ACCESS_TIMEOUT("Redis缓存数据访问超时,请刷新后重试!"), + REDIS_CACHE_ACCESS_STATE_ERROR("Redis缓存数据访问状态错误,请刷新后重试!"); + + // 下面的枚举值为特定枚举值,即开发者可以根据自己的项目需求定义更多的非通用枚举值 + + /** + * 构造函数。 + * + * @param errorMessage 错误消息。 + */ + ErrorCodeEnum(String errorMessage) { + this.errorMessage = errorMessage; + } + + /** + * 错误信息。 + */ + private String errorMessage; + + /** + * 获取错误信息。 + * + * @return 错误信息。 + */ + public String getErrorMessage() { + return errorMessage; + } +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/constant/GlobalDeletedFlag.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/constant/GlobalDeletedFlag.java new file mode 100644 index 00000000..cac588a4 --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/constant/GlobalDeletedFlag.java @@ -0,0 +1,25 @@ +package com.orange.demo.common.core.constant; + +/** + * 数据记录逻辑删除标记常量。 + * + * @author Jerry + * @date 2020-09-25 + */ +public final class GlobalDeletedFlag { + + /** + * 表示数据表记录已经删除 + */ + public static final int DELETED = -1; + /** + * 数据记录正常 + */ + public static final int NORMAL = 1; + + /** + * 私有构造函数,明确标识该常量类的作用。 + */ + private GlobalDeletedFlag() { + } +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/exception/DataValidationException.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/exception/DataValidationException.java new file mode 100644 index 00000000..c7fb997c --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/exception/DataValidationException.java @@ -0,0 +1,26 @@ +package com.orange.demo.common.core.exception; + +/** + * 数据验证失败的自定义异常。 + * + * @author Jerry + * @date 2020-09-25 + */ +public class DataValidationException extends RuntimeException { + + /** + * 构造函数。 + */ + public DataValidationException() { + + } + + /** + * 构造函数。 + * + * @param msg 错误信息。 + */ + public DataValidationException(String msg) { + super(msg); + } +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/exception/InvalidClassFieldException.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/exception/InvalidClassFieldException.java new file mode 100644 index 00000000..97a9a7b6 --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/exception/InvalidClassFieldException.java @@ -0,0 +1,30 @@ +package com.orange.demo.common.core.exception; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 无效的类对象字段的自定义异常。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class InvalidClassFieldException extends RuntimeException { + + private final String className; + private final String fieldName; + + /** + * 构造函数。 + * + * @param className 对象名。 + * @param fieldName 字段名。 + */ + public InvalidClassFieldException(String className, String fieldName) { + super("Invalid FieldName [" + fieldName + "] in Class [" + className + "]."); + this.className = className; + this.fieldName = fieldName; + } +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/exception/InvalidDataFieldException.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/exception/InvalidDataFieldException.java new file mode 100644 index 00000000..0f7df706 --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/exception/InvalidDataFieldException.java @@ -0,0 +1,30 @@ +package com.orange.demo.common.core.exception; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 无效的实体对象字段的自定义异常。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class InvalidDataFieldException extends RuntimeException { + + private final String modelName; + private final String fieldName; + + /** + * 构造函数。 + * + * @param modelName 实体对象名。 + * @param fieldName 字段名。 + */ + public InvalidDataFieldException(String modelName, String fieldName) { + super("Invalid FieldName [" + fieldName + "] in Model Class [" + modelName + "]."); + this.modelName = modelName; + this.fieldName = fieldName; + } +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/exception/InvalidDataModelException.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/exception/InvalidDataModelException.java new file mode 100644 index 00000000..71de86e9 --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/exception/InvalidDataModelException.java @@ -0,0 +1,27 @@ +package com.orange.demo.common.core.exception; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 无效的实体对象的自定义异常。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class InvalidDataModelException extends RuntimeException { + + private final String modelName; + + /** + * 构造函数。 + * + * @param modelName 实体对象名。 + */ + public InvalidDataModelException(String modelName) { + super("Invalid Model Class [" + modelName + "]."); + this.modelName = modelName; + } +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/exception/MyRuntimeException.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/exception/MyRuntimeException.java new file mode 100644 index 00000000..46c15640 --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/exception/MyRuntimeException.java @@ -0,0 +1,36 @@ +package com.orange.demo.common.core.exception; + +/** + * 自定义的运行时异常,在需要抛出运行时异常时,可使用该异常。 + * NOTE:主要是为了避免SonarQube进行代码质量扫描时,给出警告。 + * + * @author Jerry + * @date 2020-09-25 + */ +public class MyRuntimeException extends RuntimeException { + + /** + * 构造函数。 + */ + public MyRuntimeException() { + + } + + /** + * 构造函数。 + * + * @param throwable 引发异常对象。 + */ + public MyRuntimeException(Throwable throwable) { + super(throwable); + } + + /** + * 构造函数。 + * + * @param msg 错误信息。 + */ + public MyRuntimeException(String msg) { + super(msg); + } +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/exception/NoDataAffectException.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/exception/NoDataAffectException.java new file mode 100644 index 00000000..37364f7f --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/exception/NoDataAffectException.java @@ -0,0 +1,26 @@ +package com.orange.demo.common.core.exception; + +/** + * 没有数据被修改的自定义异常。 + * + * @author Jerry + * @date 2020-09-25 + */ +public class NoDataAffectException extends RuntimeException { + + /** + * 构造函数。 + */ + public NoDataAffectException() { + + } + + /** + * 构造函数。 + * + * @param msg 错误信息。 + */ + public NoDataAffectException(String msg) { + super(msg); + } +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/exception/NoDataPermException.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/exception/NoDataPermException.java new file mode 100644 index 00000000..8f0a3c8b --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/exception/NoDataPermException.java @@ -0,0 +1,26 @@ +package com.orange.demo.common.core.exception; + +/** + * 没有数据访问权限的自定义异常。 + * + * @author Jerry + * @date 2020-09-25 + */ +public class NoDataPermException extends RuntimeException { + + /** + * 构造函数。 + */ + public NoDataPermException() { + + } + + /** + * 构造函数。 + * + * @param msg 错误信息。 + */ + public NoDataPermException(String msg) { + super(msg); + } +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/exception/RedisCacheAccessException.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/exception/RedisCacheAccessException.java new file mode 100644 index 00000000..793c524f --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/exception/RedisCacheAccessException.java @@ -0,0 +1,20 @@ +package com.orange.demo.common.core.exception; + +/** + * Redis缓存访问失败。比如:获取分布式数据锁超时、等待线程中断等。 + * + * @author Jerry + * @date 2020-09-25 + */ +public class RedisCacheAccessException extends RuntimeException { + + /** + * 构造函数。 + * + * @param msg 错误信息。 + * @param cause 原始异常。 + */ + public RedisCacheAccessException(String msg, Throwable cause) { + super(msg, cause); + } +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/interceptor/MyRequestArgumentResolver.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/interceptor/MyRequestArgumentResolver.java new file mode 100644 index 00000000..406111c0 --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/interceptor/MyRequestArgumentResolver.java @@ -0,0 +1,226 @@ +package com.orange.demo.common.core.interceptor; + +import cn.hutool.core.convert.Convert; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.orange.demo.common.core.annotation.MyRequestBody; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.core.MethodParameter; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.lang.NonNull; +import org.springframework.web.bind.support.WebDataBinderFactory; +import org.springframework.web.context.request.NativeWebRequest; +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.method.support.HandlerMethodArgumentResolver; +import org.springframework.web.method.support.ModelAndViewContainer; + +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; +import java.lang.reflect.ParameterizedType; +import java.util.*; + +/** + * MyRequestBody解析器 + * 解决的问题: + * 1、单个字符串等包装类型都要写一个对象才可以用@RequestBody接收; + * 2、多个对象需要封装到一个对象里才可以用@RequestBody接收。 + * + * @author Jerry + * @date 2020-09-25 + */ +public class MyRequestArgumentResolver implements HandlerMethodArgumentResolver { + + private static final String JSONBODY_ATTRIBUTE = "MY_REQUEST_BODY_ATTRIBUTE_XX"; + + private static Set> classSet = new HashSet<>(); + + static { + classSet.add(Integer.class); + classSet.add(Long.class); + classSet.add(Short.class); + classSet.add(Float.class); + classSet.add(Double.class); + classSet.add(Boolean.class); + classSet.add(Byte.class); + classSet.add(Character.class); + } + + /** + * 设置支持的方法参数类型。 + * + * @param parameter 方法参数。 + * @return 支持的类型。 + */ + @Override + public boolean supportsParameter(@NonNull MethodParameter parameter) { + return parameter.hasParameterAnnotation(MyRequestBody.class); + } + + /** + * 参数解析,利用fastjson。 + * 注意:非基本类型返回null会报空指针异常,要通过反射或者JSON工具类创建一个空对象。 + */ + @Override + public Object resolveArgument( + @NonNull MethodParameter parameter, + ModelAndViewContainer mavContainer, + @NonNull NativeWebRequest webRequest, + WebDataBinderFactory binderFactory) throws Exception { + HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class); + String contentType = servletRequest.getContentType(); + if (!HttpMethod.POST.name().equals(servletRequest.getMethod())) { + throw new IllegalArgumentException("Only POST method can be applied @MyRequestBody annotation!"); + } + if (!StringUtils.containsIgnoreCase(contentType, MediaType.APPLICATION_JSON_VALUE)) { + throw new IllegalArgumentException( + "Only application/json Content-Type can be applied @MyRequestBody annotation!"); + } + // 根据@MyRequestBody注解value作为json解析的key + MyRequestBody parameterAnnotation = parameter.getParameterAnnotation(MyRequestBody.class); + JSONObject jsonObject = getRequestBody(webRequest); + if (jsonObject == null) { + if (parameterAnnotation.required()) { + throw new IllegalArgumentException("Request Body is EMPTY!"); + } + return null; + } + String key = parameterAnnotation.value(); + if (StringUtils.isBlank(key)) { + key = parameter.getParameterName(); + } + Object value = jsonObject.get(key); + if (value == null) { + if (parameterAnnotation.required()) { + throw new IllegalArgumentException(String.format("Required parameter %s is not present!", key)); + } + return null; + } + // 获取参数类型。 + Class parameterType = parameter.getParameterType(); + //基本类型 + if (parameterType.isPrimitive()) { + return parsePrimitive(parameterType.getName(), value); + } + // 基本类型包装类 + if (isBasicDataTypes(parameterType)) { + return parseBasicTypeWrapper(parameterType, value); + } else if (parameterType == String.class) { + // 字符串类型 + return value.toString(); + } + // 数组类型 + if (value instanceof JSONArray) { + return parseArray(parameterType, parameterAnnotation.elementType(), key, value); + } + // 其他复杂对象 + return JSON.toJavaObject((JSONObject) value, parameterType); + } + + @SuppressWarnings("unchecked") + private Object parseArray(Class parameterType, Class elementType, String key, Object value) + throws IllegalAccessException, InstantiationException { + Object o; + if (!parameterType.equals(List.class)) { + o = parameterType.newInstance(); + parameterType = (Class) ((ParameterizedType) + parameterType.getGenericSuperclass()).getActualTypeArguments()[0]; + } else { + parameterType = elementType; + if (parameterType.equals(Class.class)) { + throw new IllegalArgumentException( + String.format("List Type parameter %s MUST have elementType!", key)); + } + o = new LinkedList<>(); + } + if (!(o instanceof List)) { + throw new IllegalArgumentException(String.format("Required parameter %s is List!", key)); + } + ((List) o).addAll(((JSONArray) value).toJavaList(parameterType)); + return o; + } + + private Object parsePrimitive(String parameterTypeName, Object value) { + final String booleanTypeName = "boolean"; + if (booleanTypeName.equals(parameterTypeName)) { + return Boolean.valueOf(value.toString()); + } + final String intTypeName = "int"; + if (intTypeName.equals(parameterTypeName)) { + return Integer.valueOf(value.toString()); + } + final String charTypeName = "char"; + if (charTypeName.equals(parameterTypeName)) { + return value.toString().charAt(0); + } + final String shortTypeName = "short"; + if (shortTypeName.equals(parameterTypeName)) { + return Short.valueOf(value.toString()); + } + final String longTypeName = "long"; + if (longTypeName.equals(parameterTypeName)) { + return Long.valueOf(value.toString()); + } + final String floatTypeName = "float"; + if (floatTypeName.equals(parameterTypeName)) { + return Float.valueOf(value.toString()); + } + final String doubleTypeName = "double"; + if (doubleTypeName.equals(parameterTypeName)) { + return Double.valueOf(value.toString()); + } + final String byteTypeName = "byte"; + if (byteTypeName.equals(parameterTypeName)) { + return Byte.valueOf(value.toString()); + } + return null; + } + + private Object parseBasicTypeWrapper(Class parameterType, Object value) { + if (Number.class.isAssignableFrom(parameterType)) { + if (value instanceof String) { + return Convert.convert(parameterType, value); + } + Number number = (Number) value; + if (parameterType == Integer.class) { + return number.intValue(); + } else if (parameterType == Short.class) { + return number.shortValue(); + } else if (parameterType == Long.class) { + return number.longValue(); + } else if (parameterType == Float.class) { + return number.floatValue(); + } else if (parameterType == Double.class) { + return number.doubleValue(); + } else if (parameterType == Byte.class) { + return number.byteValue(); + } + } else if (parameterType == Boolean.class) { + return value.toString(); + } else if (parameterType == Character.class) { + return value.toString().charAt(0); + } + return null; + } + + private boolean isBasicDataTypes(Class clazz) { + return classSet.contains(clazz); + } + + private JSONObject getRequestBody(NativeWebRequest webRequest) throws IOException { + HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class); + // 有就直接获取 + JSONObject jsonObject = (JSONObject) webRequest.getAttribute(JSONBODY_ATTRIBUTE, RequestAttributes.SCOPE_REQUEST); + // 没有就从请求中读取 + if (jsonObject == null) { + String jsonBody = IOUtils.toString(servletRequest.getReader()); + jsonObject = JSON.parseObject(jsonBody); + if (jsonObject != null) { + webRequest.setAttribute(JSONBODY_ATTRIBUTE, jsonObject, RequestAttributes.SCOPE_REQUEST); + } + } + return jsonObject; + } +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/listener/LoadCachedDataListener.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/listener/LoadCachedDataListener.java new file mode 100644 index 00000000..ca9611bf --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/listener/LoadCachedDataListener.java @@ -0,0 +1,28 @@ +package com.orange.demo.common.core.listener; + +import com.orange.demo.common.core.base.service.BaseDictService; +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.stereotype.Component; + +import java.util.Map; + +/** + * 应用程序启动后的事件监听对象。主要负责加载Model之间的字典关联和一对一关联所对应的Service结构关系。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Component +public class LoadCachedDataListener implements ApplicationListener { + + @SuppressWarnings("all") + @Override + public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) { + Map serviceMap = + applicationReadyEvent.getApplicationContext().getBeansOfType(BaseDictService.class); + for (Map.Entry e : serviceMap.entrySet()) { + e.getValue().loadCachedData(); + } + } +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/listener/LoadServiceRelationListener.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/listener/LoadServiceRelationListener.java new file mode 100644 index 00000000..3be64d6b --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/listener/LoadServiceRelationListener.java @@ -0,0 +1,28 @@ +package com.orange.demo.common.core.listener; + +import com.orange.demo.common.core.base.service.BaseService; +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.stereotype.Component; + +import java.util.Map; + +/** + * 应用程序启动后的事件监听对象。主要负责加载Model之间的字典关联和一对一关联所对应的Service结构关系。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Component +public class LoadServiceRelationListener implements ApplicationListener { + + @SuppressWarnings("all") + @Override + public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) { + Map serviceMap = + applicationReadyEvent.getApplicationContext().getBeansOfType(BaseService.class); + for (Map.Entry e : serviceMap.entrySet()) { + e.getValue().loadRelationStruct(); + } + } +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/object/CallResult.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/object/CallResult.java new file mode 100644 index 00000000..37fbbb2b --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/object/CallResult.java @@ -0,0 +1,87 @@ +package com.orange.demo.common.core.object; + +import com.alibaba.fastjson.JSONObject; +import lombok.Data; + +/** + * 接口数据验证结果对象。主要是Service类使用。 + * 同时为了提升效率,减少查询次数,可以根据具体的需求,将部分验证关联对象存入data字段,以供Controller使用。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Data +public class CallResult { + + /** + * 为了优化性能,所有没有携带数据的正确结果,均可用该对象表示。 + */ + private static final CallResult OK = new CallResult(); + /** + * 是否成功标记。 + */ + private boolean success = true; + /** + * 错误信息描述。 + */ + private String errorMessage = null; + /** + * 在验证同时,仍然需要附加的关联数据对象。 + */ + private JSONObject data; + + /** + * 创建验证结果对象。 + * + * @param errorMessage 错误描述信息。 + * @return 如果参数为空,表示成功,否则返回代码错误信息的错误对象实例。 + */ + public static CallResult create(String errorMessage) { + return errorMessage == null ? ok() : error(errorMessage); + } + + /** + * 创建验证结果对象。 + * + * @param errorMessage 错误描述信息。 + * @param data 附带的数据对象。 + * @return 如果参数为空,表示成功,否则返回代码错误信息的错误对象实例。 + */ + public static CallResult create(String errorMessage, JSONObject data) { + return errorMessage == null ? ok(data) : error(errorMessage); + } + + /** + * 创建表示验证成功的对象实例。 + * + * @return 验证成功对象实例。 + */ + public static CallResult ok() { + return OK; + } + + /** + * 创建表示验证成功的对象实例。 + * + * @param data 附带的数据对象。 + * @return 验证成功对象实例。 + */ + public static CallResult ok(JSONObject data) { + CallResult result = new CallResult(); + result.data = data; + return result; + } + + /** + * 创建表示验证失败的对象实例。 + * + * @param errorMessage 错误描述。 + * @return 验证失败对象实例。 + */ + public static CallResult error(String errorMessage) { + CallResult result = new CallResult(); + result.success = false; + result.errorMessage = errorMessage; + return result; + } +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/object/MyGroupCriteria.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/object/MyGroupCriteria.java new file mode 100644 index 00000000..ff71ebe3 --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/object/MyGroupCriteria.java @@ -0,0 +1,24 @@ +package com.orange.demo.common.core.object; + +import lombok.AllArgsConstructor; +import lombok.Data; + +/** + * Mybatis Mapper.xml中所需的分组条件对象。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Data +@AllArgsConstructor +public class MyGroupCriteria { + + /** + * GROUP BY 从句后面的参数。 + */ + private String groupBy; + /** + * SELECT 从句后面的分组显示字段。 + */ + private String groupSelect; +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/object/MyGroupParam.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/object/MyGroupParam.java new file mode 100644 index 00000000..33465285 --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/object/MyGroupParam.java @@ -0,0 +1,168 @@ +package com.orange.demo.common.core.object; + +import cn.hutool.core.util.ReflectUtil; +import com.orange.demo.common.core.constant.ApplicationConstant; +import com.orange.demo.common.core.exception.InvalidClassFieldException; +import com.orange.demo.common.core.exception.InvalidDataFieldException; +import com.orange.demo.common.core.exception.InvalidDataModelException; +import com.orange.demo.common.core.util.MyModelUtil; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +/** + * 查询分组参数请求对象。 + * + * @author Jerry + * @date 2020-09-25 + */ +@EqualsAndHashCode(callSuper = true) +@Slf4j +@Data +public class MyGroupParam extends ArrayList { + + /** + * SQL语句的SELECT LIST中,分组字段的返回字段名称列表。 + */ + private List selectGroupFieldList; + + /** + * 分组参数解析后构建的SQL语句中所需的分组数据,如GROUP BY的字段列表和SELECT LIST中的分组字段显示列表。 + */ + private MyGroupCriteria groupCriteria; + /** + * 基于分组参数对象中的数据,构建SQL中select list和group by从句可以直接使用的分组对象。 + * + * @param groupParam 分组参数对象。 + * @param modelClazz 查询表对应的主对象的Class。 + * @return SQL中所需的GROUP对象。详见MyGroupCriteria类定义。 + */ + public static MyGroupParam buildGroupBy(MyGroupParam groupParam, Class modelClazz) { + if (groupParam == null) { + return null; + } + if (modelClazz == null) { + throw new IllegalArgumentException("modelClazz Argument can't be NULL"); + } + groupParam.selectGroupFieldList = new LinkedList<>(); + StringBuilder groupByBuilder = new StringBuilder(128); + StringBuilder groupSelectBuilder = new StringBuilder(128); + int i = 0; + for (GroupInfo groupInfo : groupParam) { + GroupBaseData groupBaseData = parseGroupBaseData(groupInfo, modelClazz); + if (StringUtils.isBlank(groupBaseData.tableName)) { + throw new InvalidDataModelException(groupBaseData.modelName); + } + if (StringUtils.isBlank(groupBaseData.columnName)) { + throw new InvalidDataFieldException(groupBaseData.modelName, groupBaseData.fieldName); + } + processGroupInfo(groupInfo, groupBaseData, groupByBuilder, groupSelectBuilder); + String aliasName = StringUtils.isBlank(groupInfo.aliasName) ? groupInfo.fieldName : groupInfo.aliasName; + // selectGroupFieldList中的元素,目前只是被export操作使用。会根据集合中的元素名称匹配导出表头。 + groupParam.selectGroupFieldList.add(aliasName); + if (++i < groupParam.size()) { + groupByBuilder.append(", "); + groupSelectBuilder.append(", "); + } + } + groupParam.groupCriteria = new MyGroupCriteria(groupByBuilder.toString(), groupSelectBuilder.toString()); + return groupParam; + } + + private static GroupBaseData parseGroupBaseData(GroupInfo groupInfo, Class modelClazz) { + GroupBaseData baseData = new GroupBaseData(); + String[] stringArray = StringUtils.split(groupInfo.fieldName,'.'); + if (stringArray.length == 1) { + baseData.modelName = modelClazz.getSimpleName(); + baseData.fieldName = groupInfo.fieldName; + baseData.tableName = MyModelUtil.mapToTableName(modelClazz); + baseData.columnName = MyModelUtil.mapToColumnName(groupInfo.fieldName, modelClazz); + } else { + Field field = ReflectUtil.getField(modelClazz, stringArray[0]); + if (field == null) { + throw new InvalidClassFieldException(modelClazz.getSimpleName(), stringArray[0]); + } + Class fieldClazz = field.getType(); + baseData.modelName = fieldClazz.getSimpleName(); + baseData.fieldName = stringArray[1]; + baseData.tableName = MyModelUtil.mapToTableName(fieldClazz); + baseData.columnName = MyModelUtil.mapToColumnName(baseData.fieldName, fieldClazz); + } + return baseData; + } + + private static void processGroupInfo( + GroupInfo groupInfo, + GroupBaseData baseData, + StringBuilder groupByBuilder, + StringBuilder groupSelectBuilder) { + String tableName = baseData.tableName; + String columnName = baseData.columnName; + if (StringUtils.isNotBlank(groupInfo.dateAggregateBy)) { + groupByBuilder.append("DATE_FORMAT(").append(tableName).append(".").append(columnName); + groupSelectBuilder.append("DATE_FORMAT(").append(tableName).append(".").append(columnName); + if (ApplicationConstant.DAY_AGGREGATION.equals(groupInfo.dateAggregateBy)) { + groupByBuilder.append(", '%Y-%m-%d')"); + groupSelectBuilder.append(", '%Y-%m-%d')"); + } else if (ApplicationConstant.MONTH_AGGREGATION.equals(groupInfo.dateAggregateBy)) { + groupByBuilder.append(", '%Y-%m-01')"); + groupSelectBuilder.append(", '%Y-%m-01')"); + } else if (ApplicationConstant.YEAR_AGGREGATION.equals(groupInfo.dateAggregateBy)) { + groupByBuilder.append(", '%Y-01-01')"); + groupSelectBuilder.append(", '%Y-01-01')"); + } else { + throw new IllegalArgumentException("Illegal DATE_FORMAT for GROUP ID list."); + } + if (StringUtils.isNotBlank(groupInfo.aliasName)) { + groupSelectBuilder.append(" ").append(groupInfo.aliasName); + } else { + groupSelectBuilder.append(" ").append(columnName); + } + } else { + groupByBuilder.append(tableName).append(".").append(columnName); + groupSelectBuilder.append(tableName).append(".").append(columnName); + if (StringUtils.isNotBlank(groupInfo.aliasName)) { + groupSelectBuilder.append(" ").append(groupInfo.aliasName); + } + } + } + + /** + * 分组信息对象。 + */ + @Data + public static class GroupInfo { + /** + * Java对象的字段名。目前主要包含三种格式: + * 1. 简单的属性名称,如userId,将会直接映射到与其关联的数据库字段。表名为当前ModelClazz所对应的表名。 + * 映射结果或为 my_main_table.user_id + * 2. 一对一关联表属性,如user.userId,这里将先获取user属性的对象类型并映射到对应的表名,后面的userId为 + * user所在实体的属性。映射结果或为:my_sys_user.user_id + */ + private String fieldName; + /** + * SQL语句的Select List中,分组字段的别名。如果别名为NULL,直接取fieldName。 + */ + private String aliasName; + /** + * 如果该值不为NULL,则会对分组字段进行DATE_FORMAT函数的计算,并根据具体的值,将日期数据截取到指定的位。 + * day: 表示按照天聚合,将会截取到天。DATE_FORMAT(columnName, '%Y-%m-%d') + * month: 表示按照月聚合,将会截取到月。DATE_FORMAT(columnName, '%Y-%m-01') + * year: 表示按照年聚合,将会截取到年。DATE_FORMAT(columnName, '%Y-01-01') + */ + private String dateAggregateBy; + } + + private static class GroupBaseData { + private String modelName; + private String fieldName; + private String tableName; + private String columnName; + } +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/object/MyOrderParam.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/object/MyOrderParam.java new file mode 100644 index 00000000..e8bcc8c5 --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/object/MyOrderParam.java @@ -0,0 +1,258 @@ +package com.orange.demo.common.core.object; + +import cn.hutool.core.util.ReflectUtil; +import com.orange.demo.common.core.constant.ApplicationConstant; +import com.orange.demo.common.core.exception.InvalidClassFieldException; +import com.orange.demo.common.core.exception.InvalidDataFieldException; +import com.orange.demo.common.core.exception.InvalidDataModelException; +import com.orange.demo.common.core.util.MyModelUtil; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; + +import java.lang.reflect.Field; +import java.util.*; + +/** + * Controller参数中的排序请求对象。 + * + * @author Jerry + * @date 2020-09-25 + */ +@EqualsAndHashCode(callSuper = true) +@Slf4j +@Data +public class MyOrderParam extends ArrayList { + + private static final String DICT_MAP = "DictMap."; + /** + * 基于排序对象中的JSON数据,构建SQL中order by从句可以直接使用的排序字符串。 + * + * @param orderParam 排序参数对象。 + * @param modelClazz 查询主表对应的主对象的Class。 + * @return SQL中order by从句可以直接使用的排序字符串。 + */ + public static String buildOrderBy(MyOrderParam orderParam, Class modelClazz) { + if (orderParam == null) { + return null; + } + if (modelClazz == null) { + throw new IllegalArgumentException( + "modelClazz Argument in MyOrderParam.buildOrderBy can't be NULL"); + } + int i = 0; + StringBuilder orderBy = new StringBuilder(128); + for (OrderInfo orderInfo : orderParam) { + OrderBaseData orderBaseData = parseOrderBaseData(orderInfo, modelClazz); + if (StringUtils.isBlank(orderBaseData.tableName)) { + throw new InvalidDataModelException(orderBaseData.modelName); + } + if (StringUtils.isBlank(orderBaseData.columnName)) { + throw new InvalidDataFieldException(orderBaseData.modelName, orderBaseData.fieldName); + } + processOrderInfo(orderInfo, orderBaseData, orderBy); + if (++i < orderParam.size()) { + orderBy.append(", "); + } + } + return orderBy.toString(); + } + + private static void processOrderInfo( + OrderInfo orderInfo, OrderBaseData orderBaseData, StringBuilder orderByBuilder) { + if (StringUtils.isNotBlank(orderInfo.dateAggregateBy)) { + orderByBuilder.append("DATE_FORMAT(") + .append(orderBaseData.tableName).append(".").append(orderBaseData.columnName); + if (ApplicationConstant.DAY_AGGREGATION.equals(orderInfo.dateAggregateBy)) { + orderByBuilder.append(", '%Y-%m-%d')"); + } else if (ApplicationConstant.MONTH_AGGREGATION.equals(orderInfo.dateAggregateBy)) { + orderByBuilder.append(", '%Y-%m-01')"); + } else if (ApplicationConstant.YEAR_AGGREGATION.equals(orderInfo.dateAggregateBy)) { + orderByBuilder.append(", '%Y-01-01')"); + } else { + throw new IllegalArgumentException("Illegal DATE_FORMAT for GROUP ID list."); + } + } else { + orderByBuilder.append(orderBaseData.tableName).append(".").append(orderBaseData.columnName); + } + if (orderInfo.asc != null && !orderInfo.asc) { + orderByBuilder.append(" DESC"); + } + } + + private static OrderBaseData parseOrderBaseData(OrderInfo orderInfo, Class modelClazz) { + OrderBaseData orderBaseData = new OrderBaseData(); + orderBaseData.fieldName = StringUtils.substringBefore(orderInfo.fieldName, DICT_MAP); + String[] stringArray = StringUtils.split(orderBaseData.fieldName, '.'); + if (stringArray.length == 1) { + orderBaseData.modelName = modelClazz.getSimpleName(); + orderBaseData.tableName = MyModelUtil.mapToTableName(modelClazz); + orderBaseData.columnName = MyModelUtil.mapToColumnName(orderBaseData.fieldName, modelClazz); + } else { + Field field = ReflectUtil.getField(modelClazz, stringArray[0]); + if (field == null) { + throw new InvalidClassFieldException(modelClazz.getSimpleName(), stringArray[0]); + } + Class fieldClazz = field.getType(); + orderBaseData.modelName = fieldClazz.getSimpleName(); + orderBaseData.fieldName = stringArray[1]; + orderBaseData.tableName = MyModelUtil.mapToTableName(fieldClazz); + orderBaseData.columnName = MyModelUtil.mapToColumnName(orderBaseData.fieldName, fieldClazz); + } + return orderBaseData; + } + + /** + * 在排序列表中,可能存在基于指定表字段的排序,该函数将获取指定表的所有排序字段。 + * 返回的字符串,可直接用于SQL中的ORDER BY从句。 + * + * @param orderParam 排序参数对象。 + * @param modelClazz 查询主表对应的主对象的Class。 + * @param relationModelName 与关联表对应的Model的名称,如my_course_paper表应对的Java对象CoursePaper。 + * 如果该值为null或空字符串,则获取所有主表的排序字段。 + * @return 返回的是表字段,而非Java对象的属性,多个字段之间逗号分隔。 + */ + public static String getOrderClauseByModelName( + MyOrderParam orderParam, Class modelClazz, String relationModelName) { + if (orderParam == null) { + return null; + } + if (modelClazz == null) { + throw new IllegalArgumentException( + "modelClazz Argument in MyOrderParam.getOrderClauseByModelName can't be NULL"); + } + List fieldNameList = new LinkedList<>(); + String prefix = null; + if (StringUtils.isNotBlank(relationModelName)) { + prefix = relationModelName + "."; + } + for (OrderInfo orderInfo : orderParam) { + OrderBaseData baseData = parseOrderBaseData(orderInfo, modelClazz, prefix, relationModelName); + if (baseData != null) { + fieldNameList.add(makeOrderBy(baseData, orderInfo.asc)); + } + } + return StringUtils.join(fieldNameList, ", "); + } + + private static OrderBaseData parseOrderBaseData( + OrderInfo orderInfo, Class modelClazz, String prefix, String relationModelName) { + OrderBaseData baseData = null; + String fieldName = StringUtils.substringBefore(orderInfo.fieldName, DICT_MAP); + if (prefix != null) { + if (fieldName.startsWith(prefix)) { + baseData = new OrderBaseData(); + Field field = ReflectUtil.getField(modelClazz, relationModelName); + if (field == null) { + throw new InvalidClassFieldException(modelClazz.getSimpleName(), relationModelName); + } + Class fieldClazz = field.getType(); + baseData.modelName = fieldClazz.getSimpleName(); + baseData.fieldName = StringUtils.removeStart(fieldName, prefix); + baseData.tableName = MyModelUtil.mapToTableName(fieldClazz); + baseData.columnName = MyModelUtil.mapToColumnName(fieldName, fieldClazz); + } + } else { + String dotLimitor = "."; + if (!fieldName.contains(dotLimitor)) { + baseData = new OrderBaseData(); + baseData.modelName = modelClazz.getSimpleName(); + baseData.tableName = MyModelUtil.mapToTableName(modelClazz); + baseData.columnName = MyModelUtil.mapToColumnName(fieldName, modelClazz); + } + } + return baseData; + } + + private static String makeOrderBy(OrderBaseData baseData, Boolean asc) { + if (StringUtils.isBlank(baseData.tableName)) { + throw new InvalidDataModelException(baseData.modelName); + } + if (StringUtils.isBlank(baseData.columnName)) { + throw new InvalidDataFieldException(baseData.modelName, baseData.fieldName); + } + StringBuilder orderBy = new StringBuilder(128); + orderBy.append(baseData.tableName).append(".").append(baseData.columnName); + if (asc != null && !asc) { + orderBy.append(" DESC"); + } + return orderBy.toString(); + } + + /** + * 在排序列表中,可能存在基于指定表字段的排序,该函数将删除指定表的所有排序字段。 + * + * @param orderParam 排序参数对象。 + * @param modelClazz 查询主表对应的主对象的Class。 + * @param relationModelName 与关联表对应的Model的名称,如my_course_paper表应对的Java对象CoursePaper。 + * 如果该值为null或空字符串,则获取所有主表的排序字段。 + */ + public static void removeOrderClauseByModelName( + MyOrderParam orderParam, Class modelClazz, String relationModelName) { + if (orderParam == null) { + return; + } + if (modelClazz == null) { + throw new IllegalArgumentException( + "modelClazz Argument in MyOrderParam.removeOrderClauseByModelName can't be NULL"); + } + List fieldIndexList = new LinkedList<>(); + String prefix = null; + if (StringUtils.isNotBlank(relationModelName)) { + prefix = relationModelName + "."; + } + int i = 0; + for (OrderInfo orderInfo : orderParam) { + String fieldName = StringUtils.substringBefore(orderInfo.fieldName, DICT_MAP); + if (prefix != null) { + if (fieldName.startsWith(prefix)) { + fieldIndexList.add(i); + } + } else { + if (!fieldName.contains(".")) { + fieldIndexList.add(i); + } + } + ++i; + } + for (int index : fieldIndexList) { + orderParam.remove(index); + } + } + + /** + * 排序信息对象。 + */ + @Data + public static class OrderInfo { + /** + * Java对象的字段名。目前主要包含三种格式: + * 1. 简单的属性名称,如userId,将会直接映射到与其关联的数据库字段。表名为当前ModelClazz所对应的表名。 + * 映射结果或为 my_main_table.user_id + * 2. 字典属性名称,如userIdDictMap.id,由于仅仅支持字典中Id数据的排序,所以直接截取DictMap之前的字符串userId作为排序属性。 + * 表名为当前ModelClazz所对应的表名。映射结果或为 my_main_table.user_id + * 3. 一对一关联表属性,如user.userId,这里将先获取user属性的对象类型并映射到对应的表名,后面的userId为 + * user所在实体的属性。映射结果或为:my_sys_user.user_id + */ + private String fieldName; + /** + * 排序方向。true为升序,否则降序。 + */ + private Boolean asc = true; + /** + * 如果该值不为NULL,则会对日期型排序字段进行DATE_FORMAT函数的计算,并根据具体的值,将日期数据截取到指定的位。 + * day: 表示按照天聚合,将会截取到天。DATE_FORMAT(columnName, '%Y-%m-%d') + * month: 表示按照月聚合,将会截取到月。DATE_FORMAT(columnName, '%Y-%m-01') + * year: 表示按照年聚合,将会截取到年。DATE_FORMAT(columnName, '%Y-01-01') + */ + private String dateAggregateBy; + } + + private static class OrderBaseData { + private String modelName; + private String fieldName; + private String tableName; + private String columnName; + } +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/object/MyPageParam.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/object/MyPageParam.java new file mode 100644 index 00000000..0e97be67 --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/object/MyPageParam.java @@ -0,0 +1,58 @@ +package com.orange.demo.common.core.object; + +import lombok.Getter; + +/** + * Controller参数中的分页请求对象 + * + * @author Jerry + * @date 2020-09-25 + */ +@Getter +public class MyPageParam { + + public static final int DEFAULT_PAGE_NUM = 1; + public static final int DEFAULT_PAGE_SIZE = 10; + public static final int DEFAULT_MAX_SIZE = 100; + + /** + * 分页号码,从1开始计数。 + */ + private Integer pageNum; + + /** + * 每页大小。 + */ + private Integer pageSize; + + /** + * 设置当前分页页号。 + * + * @param pageNum 页号,如果传入非法值,则使用缺省值。 + */ + public void setPageNum(Integer pageNum) { + if (pageNum == null) { + return; + } + if (pageNum <= 0) { + pageNum = DEFAULT_PAGE_NUM; + } + this.pageNum = pageNum; + } + + /** + * 设置分页的大小。 + * + * @param pageSize 分页大小,如果传入非法值,则使用缺省值。 + */ + public void setPageSize(Integer pageSize) { + if (pageSize == null) { + return; + } + if (pageSize <= 0 || pageSize > DEFAULT_MAX_SIZE) { + pageSize = DEFAULT_PAGE_SIZE; + } + this.pageSize = pageSize; + } + +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/object/MyRelationParam.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/object/MyRelationParam.java new file mode 100644 index 00000000..f8a1e562 --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/object/MyRelationParam.java @@ -0,0 +1,84 @@ +package com.orange.demo.common.core.object; + +import lombok.Builder; +import lombok.Data; + +/** + * 实体对象数据组装参数构建器。 + * BaseService中的实体对象数据组装函数,会根据该参数对象进行数据组装。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Data +@Builder +public class MyRelationParam { + + /** + * 是否组装字典关联的标记。 + * 组装RelationDict和RelationConstDict注解标记的字段。 + */ + private boolean buildDict; + + /** + * 是否组装一对一关联的标记。 + * 组装RelationOneToOne注解标记的字段。 + */ + private boolean buildOneToOne; + + /** + * 在组装一对一关联的同时,是否继续关联从表中的字典。 + * 从表中RelationDict和RelationConstDict注解标记的字段。 + * 该字段为true时,无需设置buildOneToOne了。 + */ + private boolean buildOneToOneWithDict; + + /** + * 是否组装主表对多对多中间表关联的标记。 + * 组装RelationManyToMany注解标记的字段。 + */ + private boolean buildRelationManyToMany; + + /** + * 是否组装聚合计算关联的标记。 + * 组装RelationOneToManyAggregation和RelationManyToManyAggregation注解标记的字段。 + */ + private boolean buildRelationAggregation; + + /** + * 便捷方法,返回仅做字典关联的参数对象。 + * + * @return 返回仅做字典关联的参数对象。 + */ + public static MyRelationParam dictOnly() { + return MyRelationParam.builder().buildDict(true).build(); + } + + /** + * 便捷方法,返回仅做字典关联、一对一从表及其字典和聚合计算的参数对象。 + * NOTE: 对于一对多和多对多,这种从表数据是列表结果的关联,均不返回。 + * + * @return 返回仅做字典关联、一对一从表及其字典和聚合计算的参数对象。 + */ + public static MyRelationParam normal() { + return MyRelationParam.builder() + .buildDict(true) + .buildOneToOneWithDict(true) + .buildRelationAggregation(true) + .build(); + } + + /** + * 便捷方法,返回全部关联的参数对象。 + * + * @return 返回全部关联的参数对象。 + */ + public static MyRelationParam full() { + return MyRelationParam.builder() + .buildDict(true) + .buildOneToOneWithDict(true) + .buildRelationAggregation(true) + .buildRelationManyToMany(true) + .build(); + } +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/object/MyWhereCriteria.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/object/MyWhereCriteria.java new file mode 100644 index 00000000..8211efbe --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/object/MyWhereCriteria.java @@ -0,0 +1,308 @@ +package com.orange.demo.common.core.object; + +import cn.hutool.core.util.ReflectUtil; +import com.alibaba.fastjson.annotation.JSONField; +import com.orange.demo.common.core.exception.InvalidDataFieldException; +import com.orange.demo.common.core.exception.InvalidDataModelException; +import com.orange.demo.common.core.util.MyModelUtil; +import lombok.*; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.CollectionUtils; + +import java.util.Collection; +import java.util.List; + +/** + * Where中的条件语句。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Slf4j +@Data +@NoArgsConstructor +@AllArgsConstructor +public class MyWhereCriteria { + + /** + * 等于 + */ + public static final int OPERATOR_EQUAL = 0; + + /** + * 不等于 + */ + public static final int OPERATOR_NOT_EQUAL = 1; + + /** + * 大于等于 + */ + public static final int OPERATOR_GE = 2; + + /** + * 大于 + */ + public static final int OPERATOR_GT = 3; + + /** + * 小于等于 + */ + public static final int OPERATOR_LE = 4; + + /** + * 小于 + */ + public static final int OPERATOR_LT = 5; + + /** + * LIKE + */ + public static final int OPERATOR_LIKE = 6; + + /** + * NOT NULL + */ + public static final int OPERATOR_NOT_NULL = 7; + + /** + * IS NULL + */ + public static final int OPERATOR_IS_NULL = 8; + + /** + * IN + */ + public static final int OPERATOR_IN = 9; + + /** + * 参与过滤的实体对象的Class。 + */ + @JSONField(serialize = false) + private Class modelClazz; + + /** + * Java属性名称。 + */ + private String fieldName; + + /** + * 操作符类型,取值范围见上面的常量值。 + */ + private Integer operatorType; + + /** + * 条件数据值。 + */ + private Object value; + + /** + * 设置条件值。 + * + * @param fieldName 条件所属的实体对象的字段名。 + * @param operatorType 条件操作符。具体值可参考当前对象的静态变量。 + * @param value 条件过滤值。 + * @return 验证结果对象,如果有错误将会返回具体的错误信息。 + */ + public CallResult setCriteria(String fieldName, Integer operatorType, Object value) { + this.operatorType = operatorType; + this.fieldName = fieldName; + this.value = value; + return doVerify(); + } + + /** + * 设置条件值。 + * + * @param modelClazz 数据表对应实体对象的Class. + * @param fieldName 条件所属的实体对象的字段名。 + * @param operatorType 条件操作符。具体值可参考当前对象的静态变量。 + * @param value 条件过滤值。 + * @return 验证结果对象,如果有错误将会返回具体的错误信息。 + */ + public CallResult setCriteria(Class modelClazz, String fieldName, Integer operatorType, Object value) { + this.modelClazz = modelClazz; + this.operatorType = operatorType; + this.fieldName = fieldName; + this.value = value; + return doVerify(); + } + + /** + * 在执行该函数之前,该对象的所有数据均已经赋值完毕。 + * 该函数主要验证操作符字段和条件值字段对应关系的合法性。 + * + * @return 验证结果对象,如果有错误将会返回具体的错误信息。 + */ + public CallResult doVerify() { + if (fieldName == null) { + return CallResult.error("过滤字段名称 [fieldName] 不能为空!"); + } + if (modelClazz != null && ReflectUtil.getField(modelClazz, fieldName) == null) { + return CallResult.error( + "过滤字段 [" + fieldName + "] 在实体对象 [" + modelClazz.getSimpleName() + "] 中并不存在!"); + } + if (!checkOperatorType()) { + return CallResult.error("无效的操作符类型 [" + operatorType + "]!"); + } + // 其他操作符必须包含value值 + if (operatorType != OPERATOR_IS_NULL && operatorType != OPERATOR_NOT_NULL && value == null) { + String operatorString = this.getOperatorString(); + return CallResult.error("操作符 [" + operatorString + "] 的条件值不能为空!"); + } + if (this.operatorType == OPERATOR_IN) { + if (!(value instanceof Collection)) { + return CallResult.error("操作符 [IN] 的条件值必须为集合对象!"); + } + if (CollectionUtils.isEmpty((Collection) value)) { + return CallResult.error("操作符 [IN] 的条件值不能为空!"); + } + } + return CallResult.ok(); + } + + /** + * 判断操作符类型是否合法。 + * + * @return 合法返回true,否则false。 + */ + public boolean checkOperatorType() { + return operatorType != null + && (operatorType >= OPERATOR_EQUAL && operatorType <= OPERATOR_IN); + } + + /** + * 获取操作符的字符串形式。 + * + * @return 操作符的字符串。 + */ + public String getOperatorString() { + switch (operatorType) { + case OPERATOR_EQUAL: + return " = "; + case OPERATOR_NOT_EQUAL: + return " != "; + case OPERATOR_GE: + return " >= "; + case OPERATOR_GT: + return " > "; + case OPERATOR_LE: + return " <= "; + case OPERATOR_LT: + return " < "; + case OPERATOR_LIKE: + return " LIKE "; + case OPERATOR_NOT_NULL: + return " IS NOT NULL "; + case OPERATOR_IS_NULL: + return " IS NULL "; + case OPERATOR_IN: + return " IN "; + default: + return null; + } + } + + /** + * 获取组装后的SQL Where从句,如 table_name.column_name = 'value'。 + * 与查询数据表对应的实体对象Class为当前对象的modelClazz字段。 + * + * @exception InvalidDataFieldException selectFieldList中存在非法实体字段时,抛出该异常。 + * @return 组装后的SQL条件从句。 + */ + public String makeCriteriaString() { + return makeCriteriaString(this.modelClazz); + } + + /** + * 获取组装后的SQL Where从句,如 table_name.column_name = 'value'。 + * + * @param modelClazz 与查询数据表对应的实体对象的Class。 + * @exception InvalidDataFieldException selectFieldList中存在非法实体字段时,抛出该异常。 + * @exception InvalidDataModelException 参数modelClazz没有对应的table,抛出该异常。 + * @return 组装后的SQL条件从句。 + */ + public String makeCriteriaString(Class modelClazz) { + if (modelClazz == null) { + throw new IllegalArgumentException("ModelClazz argument can't be NULL."); + } + Tuple2 fieldInfo = MyModelUtil.mapToColumnInfo(fieldName, modelClazz); + if (fieldInfo == null) { + throw new InvalidDataFieldException(modelClazz.getSimpleName(), fieldName); + } + String tableName = MyModelUtil.mapToTableName(modelClazz); + if (tableName == null) { + throw new InvalidDataModelException(modelClazz.getSimpleName()); + } + return this.buildClauseString(tableName, fieldInfo.getFirst(), fieldInfo.getSecond()); + } + + /** + * 获取组装后的SQL Where从句。如 table_name.column_name = 'value'。 + * + * @param criteriaList 条件列表,所有条件直接目前仅支持 AND 的关系。 + * @exception InvalidDataFieldException selectFieldList中存在非法实体字段时,抛出该异常。 + * @return 组装后的SQL条件从句。 + */ + public static String makeCriteriaString(List criteriaList) { + return makeCriteriaString(criteriaList, null); + } + + /** + * 获取组装后的SQL Where从句。如 table_name.column_name = 'value'。 + * + * @param criteriaList 条件列表,所有条件直接目前仅支持 AND 的关系。 + * @param modelClazz 与数据表对应的实体对象的Class。 + * 如果不为NULL实体对象Class使用该值,否则使用每个MyWhereCriteria自身的modelClazz。 + * @exception InvalidDataFieldException selectFieldList中存在非法实体字段时,抛出该异常。 + * @return 组装后的SQL条件从句。 + */ + public static String makeCriteriaString(List criteriaList, Class modelClazz) { + if (CollectionUtils.isEmpty(criteriaList)) { + return null; + } + StringBuilder sb = new StringBuilder(256); + int i = 0; + for (MyWhereCriteria whereCriteria : criteriaList) { + Class clazz = modelClazz; + if (clazz == null) { + clazz = whereCriteria.modelClazz; + } + if (i++ != 0) { + sb.append(" AND "); + } + String criteriaString = whereCriteria.makeCriteriaString(clazz); + sb.append(criteriaString); + } + return sb.length() == 0 ? null : sb.toString(); + } + + private String buildClauseString(String tableName, String columnName, Integer columnType) { + StringBuilder sb = new StringBuilder(64); + sb.append(tableName).append(".").append(columnName).append(getOperatorString()); + if (operatorType == OPERATOR_IN) { + Collection filterValues = (Collection) value; + sb.append("("); + int i = 0; + for (Object filterValue : filterValues) { + if (columnType.equals(MyModelUtil.NUMERIC_FIELD_TYPE)) { + sb.append(filterValue); + } else { + sb.append("'").append(filterValue).append("'"); + } + if (i++ != filterValues.size() - 1) { + sb.append(", "); + } + } + sb.append(")"); + return sb.toString(); + } + if (value != null) { + if (columnType.equals(MyModelUtil.NUMERIC_FIELD_TYPE)) { + sb.append(value); + } else { + sb.append("'").append(value).append("'"); + } + } + return sb.toString(); + } +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/object/ResponseResult.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/object/ResponseResult.java new file mode 100644 index 00000000..718bb8d8 --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/object/ResponseResult.java @@ -0,0 +1,157 @@ +package com.orange.demo.common.core.object; + +import com.orange.demo.common.core.constant.ErrorCodeEnum; +import lombok.Data; + +/** + * 接口返回对象 + * + * @author Jerry + * @date 2020-09-25 + */ +@Data +public class ResponseResult { + + /** + * 为了优化性能,所有没有携带数据的正确结果,均可用该对象表示。 + */ + private static final ResponseResult OK = new ResponseResult<>(); + /** + * 是否成功标记。 + */ + private boolean success = true; + /** + * 错误码。 + */ + private String errorCode = "NO-ERROR"; + /** + * 错误信息描述。 + */ + private String errorMessage = "NO-MESSAGE"; + /** + * 实际数据。 + */ + private T data = null; + + /** + * 根据参数errorCodeEnum的枚举值,判断创建成功对象还是错误对象。 + * 如果返回错误对象,errorCode 和 errorMessage 分别取自于参数 errorCodeEnum 的 name() 和 getErrorMessage()。 + * + * @param errorCodeEnum 错误码枚举 + * @return 返回创建的ResponseResult实例对象 + */ + public static ResponseResult create(ErrorCodeEnum errorCodeEnum) { + return create(errorCodeEnum, errorCodeEnum.getErrorMessage()); + } + + /** + * 根据参数errorCodeEnum的枚举值,判断创建成功对象还是错误对象。 + * 如果返回错误对象,errorCode 和 errorMessage 分别取自于参数 errorCodeEnum 的 name() 和参数 errorMessage。 + * + * @param errorCodeEnum 错误码枚举。 + * @param errorMessage 如果该参数为null,错误信息取自errorCodeEnum参数内置的errorMessage,否则使用当前参数。 + * @return 返回创建的ResponseResult实例对象 + */ + public static ResponseResult create(ErrorCodeEnum errorCodeEnum, String errorMessage) { + errorMessage = errorMessage != null ? errorMessage : errorCodeEnum.getErrorMessage(); + return errorCodeEnum == ErrorCodeEnum.NO_ERROR ? success() : error(errorCodeEnum.name(), errorMessage); + } + + /** + * 根据参数errorCode是否为空,判断创建成功对象还是错误对象。 + * 如果返回错误对象,errorCode 和 errorMessage 分别取自于参数 errorCode 和参数 errorMessage。 + * + * @param errorCode 自定义的错误码 + * @param errorMessage 自定义的错误信息 + * @return 返回创建的ResponseResult实例对象 + */ + public static ResponseResult create(String errorCode, String errorMessage) { + return errorCode == null ? success() : error(errorCode, errorMessage); + } + + /** + * 创建成功对象。 + * 如果需要绑定返回数据,可以在实例化后调用setDataObject方法。 + * + * @return 返回创建的ResponseResult实例对象 + */ + public static ResponseResult success() { + return OK; + } + + /** + * 创建带有返回数据的成功对象。 + * + * @param data 返回的数据对象 + * @return 返回创建的ResponseResult实例对象 + */ + public static ResponseResult success(T data) { + ResponseResult resp = new ResponseResult<>(); + resp.data = data; + return resp; + } + + /** + * 创建错误对象。 + * 如果返回错误对象,errorCode 和 errorMessage 分别取自于参数 errorCodeEnum 的 name() 和 getErrorMessage()。 + * + * @param errorCodeEnum 错误码枚举 + * @return 返回创建的ResponseResult实例对象 + */ + public static ResponseResult error(ErrorCodeEnum errorCodeEnum) { + return error(errorCodeEnum.name(), errorCodeEnum.getErrorMessage()); + } + + /** + * 创建错误对象。 + * 如果返回错误对象,errorCode 和 errorMessage 分别取自于参数 errorCodeEnum 的 name() 和参数 errorMessage。 + * + * @param errorCodeEnum 错误码枚举 + * @param errorMessage 自定义的错误信息 + * @return 返回创建的ResponseResult实例对象 + */ + public static ResponseResult error(ErrorCodeEnum errorCodeEnum, String errorMessage) { + return error(errorCodeEnum.name(), errorMessage); + } + + /** + * 创建错误对象。 + * 如果返回错误对象,errorCode 和 errorMessage 分别取自于参数 errorCode 和参数 errorMessage。 + * + * @param errorCode 自定义的错误码 + * @param errorMessage 自定义的错误信息 + * @return 返回创建的ResponseResult实例对象 + */ + public static ResponseResult error(String errorCode, String errorMessage) { + return new ResponseResult<>(false, errorCode, errorMessage); + } + + /** + * 根据参数的errorCode和errorMessage创建新的错误应答对象。 + * + * @param errorCause 导致错误原因的应答对象。 + * @return 返回创建的ResponseResult实例对象。 + */ + public static ResponseResult errorFrom(ResponseResult errorCause) { + return error(errorCause.errorCode, errorCause.getErrorMessage()); + } + + /** + * 是否成功。 + * + * @return true成功,否则false。 + */ + public boolean isSuccess() { + return success; + } + + private ResponseResult() { + + } + + private ResponseResult(boolean success, String errorCode, String errorMessage) { + this.success = success; + this.errorCode = errorCode; + this.errorMessage = errorMessage; + } +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/object/TokenData.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/object/TokenData.java new file mode 100644 index 00000000..b1d74f58 --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/object/TokenData.java @@ -0,0 +1,59 @@ +package com.orange.demo.common.core.object; + +import com.orange.demo.common.core.util.ContextUtil; +import lombok.Data; +import lombok.ToString; + +import javax.servlet.http.HttpServletRequest; + +/** + * 基于Jwt,用于前后端传递的令牌对象。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Data +@ToString +public class TokenData { + + /** + * 在HTTP Request对象中的属性键。 + */ + public static final String REQUEST_ATTRIBUTE_NAME = "tokenData"; + /** + * 用户Id。 + */ + private Long userId; + /** + * 是否为超级管理员。 + */ + private Boolean isAdmin; + /** + * 用户显示名称。 + */ + private String showName; + /** + * 标识不同登录的会话Id。 + */ + private String sessionId; + + /** + * 将令牌对象添加到Http请求对象。 + * + * @param tokenData 令牌对象。 + */ + public static void addToRequest(TokenData tokenData) { + HttpServletRequest request = ContextUtil.getHttpRequest(); + request.setAttribute(TokenData.REQUEST_ATTRIBUTE_NAME, tokenData); + } + + /** + * 从Http Request对象中获取令牌对象。 + * + * @return 令牌对象。 + */ + public static TokenData takeFromRequest() { + HttpServletRequest request = ContextUtil.getHttpRequest(); + return (TokenData) request.getAttribute(REQUEST_ATTRIBUTE_NAME); + } +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/object/Tuple2.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/object/Tuple2.java new file mode 100644 index 00000000..b908d019 --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/object/Tuple2.java @@ -0,0 +1,50 @@ +package com.orange.demo.common.core.object; + +/** + * 二元组对象。主要用于可以一次返回多个结果的场景,同时还能避免强制转换。 + * + * @author Jerry + * @date 2020-09-25 + */ +public class Tuple2 { + + /** + * 第一个变量。 + */ + private final T1 first; + /** + * 第二个变量。 + */ + private final T2 second; + + /** + * 构造函数。 + * + * @param first 第一个变量。 + * @param second 第二个变量。 + */ + public Tuple2(T1 first, T2 second) { + this.first = first; + this.second = second; + } + + /** + * 获取第一个变量。 + * + * @return 返回第一个变量。 + */ + public T1 getFirst() { + return first; + } + + /** + * 获取第二个变量。 + * + * @return 返回第二个变量。 + */ + public T2 getSecond() { + return second; + } + +} + diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/AopTargetUtil.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/AopTargetUtil.java new file mode 100644 index 00000000..77002bad --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/AopTargetUtil.java @@ -0,0 +1,58 @@ +package com.orange.demo.common.core.util; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.aop.framework.AdvisedSupport; +import org.springframework.aop.framework.AopProxy; +import org.springframework.aop.support.AopUtils; + +import java.lang.reflect.Field; + +/** + * 获取JDK动态代理/CGLIB代理对象代理的目标对象的工具类。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Slf4j +public class AopTargetUtil { + + /** + * 获取参数对象代理的目标对象。 + * + * @param proxy 代理对象 + * @return 代理的目标对象。 + */ + public static Object getTarget(Object proxy) { + if (!AopUtils.isAopProxy(proxy)) { + return proxy; + } + try { + if (AopUtils.isJdkDynamicProxy(proxy)) { + return getJdkDynamicProxyTargetObject(proxy); + } else { + return getCglibProxyTargetObject(proxy); + } + } catch (Exception e) { + log.error("Failed to call getJdkDynamicProxyTargetObject or getCglibProxyTargetObject", e); + return null; + } + } + + private static Object getCglibProxyTargetObject(Object proxy) throws Exception { + Field h = proxy.getClass().getDeclaredField("CGLIB$CALLBACK_0"); + h.setAccessible(true); + Object dynamicAdvisedInterceptor = h.get(proxy); + Field advised = dynamicAdvisedInterceptor.getClass().getDeclaredField("advised"); + advised.setAccessible(true); + return ((AdvisedSupport) advised.get(dynamicAdvisedInterceptor)).getTargetSource().getTarget(); + } + + private static Object getJdkDynamicProxyTargetObject(Object proxy) throws Exception { + Field h = proxy.getClass().getSuperclass().getDeclaredField("h"); + h.setAccessible(true); + AopProxy aopProxy = (AopProxy) h.get(proxy); + Field advised = aopProxy.getClass().getDeclaredField("advised"); + advised.setAccessible(true); + return ((AdvisedSupport) advised.get(aopProxy)).getTargetSource().getTarget(); + } +} \ No newline at end of file diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/ApplicationContextHolder.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/ApplicationContextHolder.java new file mode 100644 index 00000000..8341de18 --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/ApplicationContextHolder.java @@ -0,0 +1,74 @@ +package com.orange.demo.common.core.util; + +import com.orange.demo.common.core.exception.MyRuntimeException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.lang.NonNull; +import org.springframework.stereotype.Component; + +/** + * Spring 系统启动应用感知对象,主要用于获取Spring Bean的上下文对象,后续的代码中可以直接查找系统中加载的Bean对象。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Component +public class ApplicationContextHolder implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + /** + * Spring 启动的过程中会自动调用,并将应用上下文对象赋值进来。 + * + * @param applicationContext 应用上下文对象,可通过该对象查找Spring中已经加载的Bean。 + */ + @Override + public void setApplicationContext(@NonNull ApplicationContext applicationContext) { + doSetApplicationContext(applicationContext); + } + + /** + * 获取应用上下文对象。 + * + * @return 应用上下文。 + */ + public static ApplicationContext getApplicationContext() { + assertApplicationContext(); + return applicationContext; + } + + /** + * 根据BeanName,获取Bean对象。 + * + * @param beanName Bean名称。 + * @param 返回的Bean类型。 + * @return Bean对象。 + */ + @SuppressWarnings("unchecked") + public static T getBean(String beanName) { + assertApplicationContext(); + return (T) applicationContext.getBean(beanName); + } + + /** + * 根据Bean的ClassType,获取Bean对象。 + * + * @param beanType Bean的Class类型。。 + * @param 返回的Bean类型。 + * @return Bean对象。 + */ + public static T getBean(Class beanType) { + assertApplicationContext(); + return applicationContext.getBean(beanType); + } + + private static void assertApplicationContext() { + if (ApplicationContextHolder.applicationContext == null) { + throw new MyRuntimeException("applicaitonContext属性为null,请检查是否注入了ApplicationContextHolder!"); + } + } + + private static void doSetApplicationContext(ApplicationContext applicationContext) { + ApplicationContextHolder.applicationContext = applicationContext; + } +} \ No newline at end of file diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/ContextUtil.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/ContextUtil.java new file mode 100644 index 00000000..83332f7a --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/ContextUtil.java @@ -0,0 +1,49 @@ +package com.orange.demo.common.core.util; + +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * 获取Servlet HttpRequest和HttpResponse的工具类。 + * + * @author Jerry + * @date 2020-09-25 + */ +public class ContextUtil { + + /** + * 判断当前是否处于HttpServletRequest上下文环境。 + * + * @return 是返回true,否则false。 + */ + public static boolean hasRequestContext() { + return RequestContextHolder.getRequestAttributes() != null; + } + + /** + * 获取Servlet请求上下文的HttpRequest对象。 + * + * @return 请求上下文中的HttpRequest对象。 + */ + public static HttpServletRequest getHttpRequest() { + return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + } + + /** + * 获取Servlet请求上下文的HttpResponse对象。 + * + * @return 请求上下文中的HttpResponse对象。 + */ + public static HttpServletResponse getHttpResponse() { + return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse(); + } + + /** + * 私有构造函数,明确标识该常量类的作用。 + */ + private ContextUtil() { + } +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/ExportUtil.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/ExportUtil.java new file mode 100644 index 00000000..37562b06 --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/ExportUtil.java @@ -0,0 +1,95 @@ +package com.orange.demo.common.core.util; + +import cn.hutool.core.io.IoUtil; +import cn.hutool.poi.excel.ExcelUtil; +import cn.hutool.poi.excel.ExcelWriter; +import cn.jimmyshi.beanquery.BeanQuery; +import com.orange.demo.common.core.constant.ApplicationConstant; +import com.orange.demo.common.core.exception.MyRuntimeException; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.csv.CSVFormat; +import org.apache.commons.csv.CSVPrinter; +import org.apache.commons.io.FilenameUtils; + +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.Writer; +import java.nio.charset.StandardCharsets; +import java.util.*; + +/** + * 导出工具类,目前支持xlsx和csv两种类型。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Slf4j +public class ExportUtil { + + /** + * 数据导出。目前仅支持xlsx和csv。 + * + * @param dataList 导出数据列表。 + * @param selectFieldMap 导出的数据字段,key为对象字段名称,value为中文标题名称。 + * @param filename 导出文件名。 + * @param 数据对象类型。 + * @throws IOException 文件操作失败。 + */ + public static void doExport( + Collection dataList, Map selectFieldMap, String filename) throws IOException { + if (CollectionUtils.isEmpty(dataList)) { + return; + } + StringBuilder sb = new StringBuilder(128); + for (Map.Entry e : selectFieldMap.entrySet()) { + sb.append(e.getKey()).append(" as ").append(e.getValue()).append(", "); + } + // 去掉末尾的逗号 + String selectFieldString = sb.substring(0, sb.length() - 2); + // 写出数据到xcel格式的输出流 + List> resultList = BeanQuery.select(selectFieldString).executeFrom(dataList); + // 构建HTTP输出流参数 + HttpServletResponse response = ContextUtil.getHttpResponse(); + response.setHeader("content-type", "application/octet-stream"); + response.setContentType("application/octet-stream"); + response.setHeader("Content-Disposition", "attachment;filename=" + filename); + if (ApplicationConstant.XLSX_EXT.equals(FilenameUtils.getExtension(filename))) { + ServletOutputStream out = response.getOutputStream(); + ExcelWriter writer = ExcelUtil.getWriter(true); + writer.setRowHeight(-1, 30); + writer.setColumnWidth(-1, 30); + writer.setColumnWidth(1, 20); + writer.write(resultList); + writer.flush(out); + writer.close(); + IoUtil.close(out); + } else if (ApplicationConstant.CSV_EXT.equals(FilenameUtils.getExtension(filename))) { + Collection headerList = selectFieldMap.values(); + String[] headerArray = new String[headerList.size()]; + headerList.toArray(headerArray); + CSVFormat format = CSVFormat.DEFAULT.withHeader(headerArray); + response.setCharacterEncoding(StandardCharsets.UTF_8.name()); + try (Writer out = response.getWriter(); CSVPrinter printer = new CSVPrinter(out, format)) { + for (Map o : resultList) { + for (Map.Entry entry : o.entrySet()) { + printer.print(entry.getValue()); + } + printer.println(); + } + printer.flush(); + } catch (Exception e) { + log.error("Failed to call ExportUtil.doExport", e); + } + } else { + throw new MyRuntimeException("不支持的导出文件类型!"); + } + } + + /** + * 私有构造函数,明确标识该常量类的作用。 + */ + private ExportUtil() { + } +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/ImportUtil.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/ImportUtil.java new file mode 100644 index 00000000..32eaf9b9 --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/ImportUtil.java @@ -0,0 +1,214 @@ +package com.orange.demo.common.core.util; + +import cn.hutool.core.util.ReflectUtil; +import cn.hutool.poi.excel.ExcelReader; +import cn.hutool.poi.excel.ExcelUtil; +import cn.hutool.poi.excel.sax.Excel07SaxReader; +import com.orange.demo.common.core.constant.ApplicationConstant; +import com.orange.demo.common.core.exception.MyRuntimeException; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.csv.CSVFormat; +import org.apache.commons.csv.CSVParser; +import org.apache.commons.csv.CSVRecord; +import org.apache.commons.io.FilenameUtils; +import org.apache.commons.lang3.StringUtils; + +import java.io.*; +import java.lang.reflect.Field; +import java.util.*; +import java.util.stream.Collectors; + +/** + * 导入工具类,目前支持xlsx和csv两种类型。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Slf4j +public class ImportUtil { + + private static final String IMPORT_EXCEPTION_ERROR = "Failed to call ImportUtil.doImport"; + private static final String UNSUPPORT_FILE_EXT_ERROR = "不支持的导入文件类型!"; + /** + * 同步导入方式。 + * + * @param filename 导入文件名。 + * @return 导入数据列表。 + */ + public static List> doImport(String filename) { + if (ApplicationConstant.XLSX_EXT.equals(FilenameUtils.getExtension(filename))) { + try (ExcelReader reader = ExcelUtil.getReader(filename)) { + return reader.readAll(); + } + } else if (ApplicationConstant.CSV_EXT.equals(FilenameUtils.getExtension(filename))) { + List> resultList = new LinkedList<>(); + try (FileReader reader = new FileReader(filename)) { + CSVParser parser = CSVFormat.DEFAULT.withFirstRecordAsHeader().parse(reader); + Map headerMap = parser.getHeaderMap(); + for (CSVRecord record : parser) { + Map rowMap = new LinkedHashMap<>(); + for (final Map.Entry header : headerMap.entrySet()) { + int col = header.getValue(); + if (col < record.size()) { + rowMap.put(header.getKey(), record.get(col)); + } + } + resultList.add(rowMap); + } + } catch (Exception e) { + log.error(IMPORT_EXCEPTION_ERROR, e); + } + return resultList; + } + throw new MyRuntimeException(UNSUPPORT_FILE_EXT_ERROR); + } + + /** + * 异步导入方式,即SAX导入方式。 + * + * @param filename 导入文件名。 + * @param importer 异步导入处理接口。 + * @throws IOException 文件处理异常。 + */ + public static void doImport(String filename, BaseImporter importer) throws IOException { + if (ApplicationConstant.XLSX_EXT.equals(FilenameUtils.getExtension(filename))) { + Excel07SaxReader reader = new MyExcel07SaxReader<>(importer); + try (InputStream in = new FileInputStream(filename)) { + reader.read(in, 0); + } + } else if (ApplicationConstant.CSV_EXT.equals(FilenameUtils.getExtension(filename))) { + try (BufferedReader reader = new BufferedReader(new FileReader(filename))) { + int rowIndex = 0; + do { + String rowData = reader.readLine(); + if (StringUtils.isBlank(rowData)) { + importer.doImport(-1, null); + break; + } + String[] dataArray = StringUtils.split(rowData, ","); + importer.doImport(rowIndex++, Arrays.asList(dataArray)); + } while (!importer.doInterrupt()); + } catch (Exception e) { + log.error(IMPORT_EXCEPTION_ERROR, e); + } + } + throw new MyRuntimeException(UNSUPPORT_FILE_EXT_ERROR); + } + + /** + * 异步导入抽象类。 + * + * @param 导入数据对象类型。 + */ + public abstract static class BaseImporter { + private Class beanType; + private List batchRowList = new LinkedList<>(); + private int batchSize; + private Field[] fieldArray = null; + private Map headerColumnMap; + + public BaseImporter(int batchSize, Class beanType, Map headerColumnMap) { + if (batchSize <= 0) { + batchSize = 100; + } + this.batchSize = batchSize; + this.beanType = beanType; + this.headerColumnMap = headerColumnMap; + } + + /** + * 导入操作执行函数。 + * + * @param rowIndex 当前行号。 + * @param row 当前行数据列表对象。 + */ + public void doImport(int rowIndex, List row) { + if (row == null) { + doProcess(batchRowList); + doFinish(); + batchRowList.clear(); + return; + } + if (rowIndex <= 0) { + fieldArray = new Field[row.size()]; + List headerList = row.stream().map(Object::toString).collect(Collectors.toList()); + List columnList = new ArrayList<>(row.size()); + for (String headerName : headerList) { + String columnName = headerColumnMap.get(headerName); + if (columnName != null) { + columnList.add(columnName); + } + } + columnList.stream() + .map(columnName -> ReflectUtil.getField(beanType, columnName)) + .collect(Collectors.toList()) + .toArray(fieldArray); + return; + } + T data; + try { + data = beanType.newInstance(); + for (int i = 0; i < row.size(); i++) { + Object value = row.get(i); + Field field = fieldArray[i]; + if (field != null) { + ReflectUtil.setFieldValue(data, field, value); + } + } + batchRowList.add(data); + } catch (Exception e) { + log.error(IMPORT_EXCEPTION_ERROR, e); + } + if (rowIndex % batchSize == 0) { + doProcess(batchRowList); + batchRowList.clear(); + } + } + + /** + * 数据处理进行中回调模板函数。 + * + * @param batchRowList 一批数据行。 + */ + public abstract void doProcess(List batchRowList); + + /** + * 数据处理完毕回调模板函数。 + */ + public abstract void doFinish(); + + /** + * 数据处理终端标记模板函数。 + * @return 是否中断。true则中断后面的处理。 + */ + public abstract boolean doInterrupt(); + } + + static class MyExcel07SaxReader extends Excel07SaxReader { + private BaseImporter importer; + + MyExcel07SaxReader(BaseImporter importer) { + super((sheetIndex, rowIndex, rowList) -> importer.doImport(rowIndex, rowList)); + this.importer = importer; + } + + @Override + public void endElement(String uri, String localName, String qName) { + super.endElement(uri, localName, qName); + if (importer.doInterrupt()) { + throw new MyRuntimeException(); + } + } + + @Override + public void endDocument() { + importer.doImport(-1, null); + } + } + + /** + * 私有构造函数,明确标识该常量类的作用。 + */ + private ImportUtil() { + } +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/IpUtil.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/IpUtil.java new file mode 100644 index 00000000..a0ead06c --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/IpUtil.java @@ -0,0 +1,101 @@ +package com.orange.demo.common.core.util; + +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; + +import javax.servlet.http.HttpServletRequest; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; + +/** + * Ip工具类。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Slf4j +public class IpUtil { + + private static final String UNKNOWN = "unknown"; + + /** + * 通过Servlet的HttpRequest对象获取Ip地址。 + * + * @param request HttpRequest对象。 + * @return 本次请求的Ip地址。 + */ + public static String getRemoteIpAddress(HttpServletRequest request) { + String ip = null; + //X-Forwarded-For:Squid 服务代理 + String ipAddresses = request.getHeader("X-Forwarded-For"); + if (StringUtils.isBlank(ipAddresses) || UNKNOWN.equalsIgnoreCase(ipAddresses)) { + //Proxy-Client-IP:apache 服务代理 + ipAddresses = request.getHeader("Proxy-Client-IP"); + } + if (StringUtils.isBlank(ipAddresses) || UNKNOWN.equalsIgnoreCase(ipAddresses)) { + //WL-Proxy-Client-IP:weblogic 服务代理 + ipAddresses = request.getHeader("WL-Proxy-Client-IP"); + } + if (StringUtils.isBlank(ipAddresses) || UNKNOWN.equalsIgnoreCase(ipAddresses)) { + //HTTP_CLIENT_IP:有些代理服务器 + ipAddresses = request.getHeader("HTTP_CLIENT_IP"); + } + if (StringUtils.isBlank(ipAddresses) || UNKNOWN.equalsIgnoreCase(ipAddresses)) { + //X-Real-IP:nginx服务代理 + ipAddresses = request.getHeader("X-Real-IP"); + } + //有些网络通过多层代理,那么获取到的ip就会有多个,一般都是通过逗号(,)分割开来,并且第一个ip为客户端的真实IP + if (StringUtils.isNotBlank(ipAddresses)) { + ip = ipAddresses.split(",")[0]; + } + //还是不能获取到,最后再通过request.getRemoteAddr();获取 + if (StringUtils.isBlank(ipAddresses) || UNKNOWN.equalsIgnoreCase(ipAddresses)) { + ip = request.getRemoteAddr(); + } + return ip; + } + + public static String getFirstLocalIpAddress() { + String ip; + try { + List ipList = getHostAddress(); + // default the first + ip = (!ipList.isEmpty()) ? ipList.get(0) : ""; + } catch (Exception ex) { + ip = ""; + log.error("Failed to call ", ex); + } + return ip; + } + + private static List getHostAddress() throws SocketException { + List ipList = new ArrayList<>(5); + Enumeration interfaces = NetworkInterface.getNetworkInterfaces(); + while (interfaces.hasMoreElements()) { + NetworkInterface ni = interfaces.nextElement(); + Enumeration allAddress = ni.getInetAddresses(); + while (allAddress.hasMoreElements()) { + InetAddress address = allAddress.nextElement(); + // skip the IPv6 addr + // skip the IPv6 addr + if (address.isLoopbackAddress() || address instanceof Inet6Address) { + continue; + } + String hostAddress = address.getHostAddress(); + ipList.add(hostAddress); + } + } + return ipList; + } + + /** + * 私有构造函数,明确标识该常量类的作用。 + */ + private IpUtil() { + } +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/JwtUtil.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/JwtUtil.java new file mode 100644 index 00000000..9c2726dd --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/JwtUtil.java @@ -0,0 +1,110 @@ +package com.orange.demo.common.core.util; + +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import lombok.extern.slf4j.Slf4j; + +import java.util.Date; +import java.util.Map; + +/** + * 基于JWT的Token生成工具类 + * + * @author Jerry + * @date 2020-09-25 + */ +@Slf4j +public class JwtUtil { + + private static final String TOKEN_PREFIX = "Bearer:"; + private static final String CLAIM_KEY_CREATEDTIME = "CreatedTime"; + + /** + * Token缺省过期时间是30分钟 + */ + private static final Long TOKEN_EXPIRATION = 1800000L; + /** + * 缺省情况下,Token会每5分钟被刷新一次 + */ + private static final Long REFRESH_TOKEN_INTERVAL = 300000L; + + /** + * 生成加密后的JWT令牌,生成的结果中包含令牌前缀,如"Bearer " + * + * @param claims 令牌中携带的数据 + * @param expirationMillisecond 过期的毫秒数 + * @return 生成后的令牌信息 + */ + public static String generateToken(Map claims, long expirationMillisecond, String signingKey) { + // 自动添加token的创建时间 + long createTime = System.currentTimeMillis(); + claims.put(CLAIM_KEY_CREATEDTIME, createTime); + String token = Jwts.builder() + .setClaims(claims) + .setExpiration(new Date(createTime + expirationMillisecond)) + .signWith(SignatureAlgorithm.HS512, signingKey) + .compact(); + return TOKEN_PREFIX + token; + } + + /** + * 生成加密后的JWT令牌,生成的结果中包含令牌前缀,如"Bearer " + * + * @param claims 令牌中携带的数据 + * @return 生成后的令牌信息 + */ + public static String generateToken(Map claims, String signingKey) { + return generateToken(claims, TOKEN_EXPIRATION, signingKey); + } + + /** + * 获取token中的数据对象 + * + * @param token 令牌信息(需要包含令牌前缀,如"Bearer:") + * @return 令牌中的数据对象,解析视频返回null。 + */ + public static Claims parseToken(String token, String signingKey) { + if (token == null || !token.startsWith(TOKEN_PREFIX)) { + return null; + } + String tokenKey = token.substring(TOKEN_PREFIX.length()); + Claims claims = null; + try { + claims = Jwts.parser().setSigningKey(signingKey).parseClaimsJws(tokenKey).getBody(); + } catch (Exception e) { + log.error("Token Expired", e); + } + return claims; + } + + /** + * 判断令牌是否过期 + * + * @param claims 令牌解密后的Map对象。 + * @return true 过期,否则false。 + */ + public static boolean isNullOrExpired(Claims claims) { + return claims == null || claims.getExpiration().before(new Date()); + } + + /** + * 判断解密后的Token payload是否需要被强制刷新,如果需要,则调用generateToken方法重新生成Token。 + * + * @param claims Token解密后payload数据 + * @return true 需要刷新,否则false + */ + public static boolean needToRefresh(Claims claims) { + if (claims == null) { + return false; + } + Long createTime = (Long) claims.get(CLAIM_KEY_CREATEDTIME); + return createTime == null || System.currentTimeMillis() - createTime > REFRESH_TOKEN_INTERVAL; + } + + /** + * 私有构造函数,明确标识该常量类的作用。 + */ + private JwtUtil() { + } +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/LogMessageUtil.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/LogMessageUtil.java new file mode 100644 index 00000000..7c8f069d --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/LogMessageUtil.java @@ -0,0 +1,33 @@ +package com.orange.demo.common.core.util; + +/** + * 拼接日志消息的工具类。 + * 主要目标是,尽量保证日志输出的统一性,同时也可以有效减少与日志信息相关的常量字符串, + * 提高代码的规范度和可维护性。 + * + * @author Jerry + * @date 2020-09-25 + */ +public class LogMessageUtil { + + /** + * RPC调用错误格式。 + */ + private static final String RPC_ERROR_MSG_FORMAT = "RPC Failed with Error message [%s]"; + + /** + * 组装RPC调用的错误信息。 + * + * @param errorMsg 具体的错误信息。 + * @return 格式化后的错误信息。 + */ + public static String makeRpcError(String errorMsg) { + return String.format(RPC_ERROR_MSG_FORMAT, errorMsg); + } + + /** + * 私有构造函数,明确标识该常量类的作用。 + */ + private LogMessageUtil() { + } +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/MyCommonUtil.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/MyCommonUtil.java new file mode 100644 index 00000000..40d7d226 --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/MyCommonUtil.java @@ -0,0 +1,144 @@ +package com.orange.demo.common.core.util; + +import cn.hutool.crypto.digest.DigestUtil; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; + +import javax.validation.ConstraintViolation; +import javax.validation.Validation; +import javax.validation.Validator; +import java.util.Collection; +import java.util.Iterator; +import java.util.Set; +import java.util.UUID; + +/** + * 脚手架中常用的基本工具方法集合,一般而言工程内部使用的方法。 + * + * @author Jerry + * @date 2020-09-25 + */ +public class MyCommonUtil { + + private static Validator validator; + + static { + validator = Validation.buildDefaultValidatorFactory().getValidator(); + } + + /** + * 创建uuid。 + * + * @return 返回uuid。 + */ + public static String generateUuid() { + return UUID.randomUUID().toString().replace("-", ""); + } + + /** + * 对用户密码进行加盐后加密。 + * + * @param password 明文密码。 + * @param passwordSalt 盐值。 + * @return 加密后的密码。 + */ + public static String encrptedPassword(String password, String passwordSalt) { + return DigestUtil.md5Hex(password + passwordSalt); + } + + /** + * 这个方法一般用于Controller对于入口参数的基本验证。 + * 对于字符串,如果为空字符串,也将视为Blank,同时返回true。 + * + * @param objs 一组参数。 + * @return 返回是否存在null或空字符串的参数。 + */ + public static boolean existBlankArgument(Object...objs) { + for (Object obj : objs) { + if (MyCommonUtil.isBlankOrNull(obj)) { + return true; + } + } + return false; + } + + /** + * 结果和 existBlankArgument 相反。 + * + * @param objs 一组参数。 + * @return 返回是否存在null或空字符串的参数。 + */ + public static boolean existNotBlankArgument(Object...objs) { + for (Object obj : objs) { + if (!MyCommonUtil.isBlankOrNull(obj)) { + return true; + } + } + return false; + } + + /** + * 验证参数是否为空。 + * + * @param obj 待判断的参数。 + * @return 空或者null返回true,否则false。 + */ + public static boolean isBlankOrNull(Object obj) { + if (obj instanceof Collection) { + return CollectionUtils.isEmpty((Collection) obj); + } + return obj == null || (obj instanceof CharSequence && StringUtils.isBlank((CharSequence) obj)); + } + + /** + * 验证参数是否为非空。 + * + * @param obj 待判断的参数。 + * @return 空或者null返回false,否则true。 + */ + public static boolean isNotBlankOrNull(Object obj) { + return !isBlankOrNull(obj); + } + + /** + * 判断模型对象是否通过校验,没有通过返回具体的校验错误信息。 + * + * @param model 带校验的model。 + * @param groups Validate绑定的校验组。 + * @return 没有错误返回null,否则返回具体的错误信息。 + */ + public static String getModelValidationError(T model, Class...groups) { + Set> constraintViolations = validator.validate(model, groups); + if (!constraintViolations.isEmpty()) { + Iterator> it = constraintViolations.iterator(); + ConstraintViolation constraint = it.next(); + return constraint.getMessage(); + } + return null; + } + + /** + * 拼接参数中的字符串列表,用指定分隔符进行分割,同时每个字符串对象用单引号括起来。 + * + * @param dataList 字符串集合。 + * @param separator 分隔符。 + * @return 拼接后的字符串。 + */ + public static String joinString(Collection dataList, final char separator) { + int index = 0; + StringBuilder sb = new StringBuilder(128); + for (String data : dataList) { + sb.append("'").append(data).append("'"); + if (index++ != dataList.size() - 1) { + sb.append(separator); + } + } + return sb.toString(); + } + + /** + * 私有构造函数,明确标识该常量类的作用。 + */ + private MyCommonUtil() { + } +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/MyDateUtil.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/MyDateUtil.java new file mode 100644 index 00000000..9ee747d5 --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/MyDateUtil.java @@ -0,0 +1,181 @@ +package com.orange.demo.common.core.util; + +import com.orange.demo.common.core.object.Tuple2; +import org.apache.commons.lang3.time.DateUtils; +import org.joda.time.DateTime; +import org.joda.time.Period; +import org.joda.time.format.DateTimeFormat; +import org.joda.time.format.DateTimeFormatter; + +import java.util.Calendar; +import java.util.Date; + +import static org.joda.time.PeriodType.days; + +/** + * 日期工具类,主要封装了部分joda-time中的方法,让很多代码一行完成,同时统一了日期到字符串的pattern格式。 + * + * @author Jerry + * @date 2020-09-25 + */ +public class MyDateUtil { + + /** + * 统一的日期pattern,今后可以根据自己的需求去修改。 + */ + public static final String COMMON_DATE_FORMAT = "yyyy-MM-dd"; + /** + * 统一的日期时间pattern,今后可以根据自己的需求去修改。 + */ + public static final String COMMON_DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss.SSS"; + /** + * 缺省日期格式化器,提前获取提升运行时效率。 + */ + private static final DateTimeFormatter DATE_PARSE_FORMATTER = + DateTimeFormat.forPattern(MyDateUtil.COMMON_DATE_FORMAT); + /** + * 缺省日期时间格式化器,提前获取提升运行时效率。 + */ + private static final DateTimeFormatter DATETIME_PARSE_FORMATTER = + DateTimeFormat.forPattern(MyDateUtil.COMMON_DATETIME_FORMAT); + + /** + * 获取一天的开始时间的字符串格式,如2019-08-03 00:00:00.000。 + * + * @param dateTime 待格式化的日期时间对象。 + * @return 格式化后的字符串。 + */ + public static String getBeginTimeOfDay(DateTime dateTime) { + return dateTime.withTimeAtStartOfDay().toString(COMMON_DATETIME_FORMAT); + } + + /** + * 获取一天的结束时间的字符串格式,如2019-08-03 23:59:59.999。 + * + * @param dateTime 待格式化的日期时间对象。 + * @return 格式化后的字符串。 + */ + public static String getEndTimeOfDay(DateTime dateTime) { + return dateTime.withTime(23, 59, 59, 999).toString(COMMON_DATETIME_FORMAT); + } + + /** + * 获取一天中的开始时间和结束时间的字符串格式,如2019-08-03 00:00:00.000 和 2019-08-03 23:59:59.999。 + * + * @param dateTime 待格式化的日期时间对象。 + * @return 包含格式后字符串的二元组对象。 + */ + public static Tuple2 getDateTimeRangeOfDay(DateTime dateTime) { + return new Tuple2<>(getBeginTimeOfDay(dateTime), getEndTimeOfDay(dateTime)); + } + + /** + * 获取本月第一天的日期格式。如2019-08-01。 + * + * @param dateTime 待格式化的日期对象。 + * @return 格式化后的字符串。 + */ + public static String getBeginDateOfMonth(DateTime dateTime) { + return dateTime.withDayOfMonth(1).toString(COMMON_DATE_FORMAT); + } + + /** + * 获取本月第一天的日期格式。如2019-08-01。 + * + * @param dateString 待格式化的日期字符串对象。 + * @return 格式化后的字符串。 + */ + public static String getBeginDateOfMonth(String dateString) { + DateTime dateTime = toDate(dateString); + return dateTime.withDayOfMonth(1).toString(COMMON_DATE_FORMAT); + } + + /** + * 计算指定日期距离今天相差的天数。 + * + * @param dateTime 待格式化的日期时间对象。 + * @return 相差天数。 + */ + public static int getDayDiffToNow(DateTime dateTime) { + return new Period(dateTime, new DateTime(), days()).getDays(); + } + + /** + * 将日期对象格式化为缺省的字符串格式。 + * + * @param dateTime 待格式化的日期对象。 + * @return 格式化后的字符串。 + */ + public static String toDateString(DateTime dateTime) { + return dateTime.toString(COMMON_DATE_FORMAT); + } + + /** + * 将日期时间对象格式化为缺省的字符串格式。 + * + * @param dateTime 待格式化的日期对象。 + * @return 格式化后的字符串。 + */ + public static String toDateTimeString(DateTime dateTime) { + return dateTime.toString(COMMON_DATETIME_FORMAT); + } + + /** + * 将缺省格式的日期字符串解析为日期对象。 + * + * @param dateString 待解析的字符串。 + * @return 解析后的日期对象。 + */ + public static DateTime toDate(String dateString) { + return DATE_PARSE_FORMATTER.parseDateTime(dateString); + } + + /** + * 将缺省格式的日期字符串解析为日期对象。 + * + * @param dateTimeString 待解析的字符串。 + * @return 解析后的日期对象。 + */ + public static DateTime toDateTime(String dateTimeString) { + return DATETIME_PARSE_FORMATTER.parseDateTime(dateTimeString); + } + + /** + * 截取时间到天。如2019-10-03 01:20:30 转换为 2019-10-03 00:00:00。 + * 由于没有字符串的中间转换,因此效率更高。 + * + * @param date 待截取日期对象。 + * @return 转换后日期对象。 + */ + public static Date truncateToDay(Date date) { + return DateUtils.truncate(date, Calendar.DAY_OF_MONTH); + } + + /** + * 截取时间到月。如2019-10-03 01:20:30 转换为 2019-10-01 00:00:00。 + * 由于没有字符串的中间转换,因此效率更高。 + * + * @param date 待截取日期对象。 + * @return 转换后日期对象。 + */ + public static Date truncateToMonth(Date date) { + return DateUtils.truncate(date, Calendar.MONTH); + } + + /** + * 截取时间到年。如2019-10-03 01:20:30 转换为 2019-01-01 00:00:00。 + * 由于没有字符串的中间转换,因此效率更高。 + * + * @param date 待截取日期对象。 + * @return 转换后日期对象。 + */ + public static Date truncateToYear(Date date) { + return DateUtils.truncate(date, Calendar.YEAR); + } + + /** + * 私有构造函数,明确标识该常量类的作用。 + */ + private MyDateUtil() { + } +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/MyModelUtil.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/MyModelUtil.java new file mode 100644 index 00000000..419f02a1 --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/MyModelUtil.java @@ -0,0 +1,437 @@ +package com.orange.demo.common.core.util; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.ReflectUtil; +import com.orange.demo.common.core.annotation.RelationConstDict; +import com.orange.demo.common.core.annotation.RelationDict; +import com.orange.demo.common.core.annotation.RelationOneToOne; +import com.orange.demo.common.core.exception.MyRuntimeException; +import com.orange.demo.common.core.object.Tuple2; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.MapUtils; +import org.apache.commons.lang3.StringUtils; +import tk.mybatis.mapper.entity.Example; + +import javax.persistence.Column; +import javax.persistence.Table; +import javax.persistence.Transient; +import java.lang.reflect.Field; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * 负责Model数据操作、类型转换和关系关联等行为的工具类。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Slf4j +public class MyModelUtil { + + /** + * 数值型字段。 + */ + public static final Integer NUMERIC_FIELD_TYPE = 0; + /** + * 字符型字段。 + */ + public static final Integer STRING_FIELD_TYPE = 1; + /** + * 日期型字段。 + */ + public static final Integer DATE_FIELD_TYPE = 2; + /** + * mapToColumnName和mapToColumnInfo使用的缓存。 + */ + private static Map> cachedColumnInfoMap = new ConcurrentHashMap<>(); + + /** + * 映射Model对象的字段反射对象,获取与该字段对应的数据库列名称。 + * + * @param field 字段反射对象。 + * @param modelClazz Model对象的Class类。 + * @return 该字段所对应的数据表列名称。 + */ + public static String mapToColumnName(Field field, Class modelClazz) { + return mapToColumnName(field.getName(), modelClazz); + } + + /** + * 映射Model对象的字段名称,获取与该字段对应的数据库列名称。 + * + * @param fieldName 字段名称。 + * @param modelClazz Model对象的Class类。 + * @return 该字段所对应的数据表列名称。 + */ + public static String mapToColumnName(String fieldName, Class modelClazz) { + Tuple2 columnInfo = mapToColumnInfo(fieldName, modelClazz); + return columnInfo == null ? null : columnInfo.getFirst(); + } + + /** + * 映射Model对象的字段名称,获取与该字段对应的数据库列名称和字段类型。 + * + * @param fieldName 字段名称。 + * @param modelClazz Model对象的Class类。 + * @return 该字段所对应的数据表列名称和Java字段类型。 + */ + public static Tuple2 mapToColumnInfo(String fieldName, Class modelClazz) { + if (StringUtils.isBlank(fieldName)) { + return null; + } + StringBuilder sb = new StringBuilder(128); + sb.append(modelClazz.getName()).append("-#-").append(fieldName); + Tuple2 columnInfo = cachedColumnInfoMap.get(sb.toString()); + if (columnInfo == null) { + Field field = ReflectUtil.getField(modelClazz, fieldName); + if (field == null) { + return null; + } + Column c = field.getAnnotation(Column.class); + String typeName = field.getType().getSimpleName(); + String columnName = c == null ? fieldName : c.name(); + // 这里缺省情况下都是按照整型去处理,因为他覆盖太多的类型了。 + // 如Integer/Long/Double/BigDecimal,可根据实际情况完善和扩充。 + Integer type = NUMERIC_FIELD_TYPE; + if (String.class.getSimpleName().equals(typeName)) { + type = STRING_FIELD_TYPE; + } else if (Date.class.getSimpleName().equals(typeName)) { + type = DATE_FIELD_TYPE; + } + columnInfo = new Tuple2<>(columnName, type); + cachedColumnInfoMap.put(sb.toString(), columnInfo); + } + return columnInfo; + } + + /** + * 映射Model主对象的Class名称,到Model所对应的表名称。 + * + * @param modelClazz Model主对象的Class。 + * @return Model对象对应的数据表名称。 + */ + public static String mapToTableName(Class modelClazz) { + Table t = modelClazz.getAnnotation(Table.class); + return t == null ? null : t.name(); + } + + /** + * 主Model类型中,遍历所有包含RelationConstDict注解的字段,并将关联的静态字典中的数据, + * 填充到thisModel对象的被注解字段中。 + * + * @param thisClazz 主对象的Class对象。 + * @param thisModel 主对象。 + * @param 主表对象类型。 + */ + @SuppressWarnings("unchecked") + public static void makeConstDictRelation(Class thisClazz, T thisModel) { + if (thisModel == null) { + return; + } + Field[] fields = ReflectUtil.getFields(thisClazz); + for (Field field : fields) { + // 这里不做任何空值判断,从而让配置错误在调试期间即可抛出 + Field thisTargetField = ReflectUtil.getField(thisClazz, field.getName()); + RelationConstDict r = thisTargetField.getAnnotation(RelationConstDict.class); + if (r == null) { + continue; + } + Field dictMapField = ReflectUtil.getField(r.constantDictClass(), "DICT_MAP"); + Map dictMap = (Map) ReflectUtil.getFieldValue(thisClazz, dictMapField); + Object id = ReflectUtil.getFieldValue(thisModel, r.masterIdField()); + if (id != null) { + String name = dictMap.get(id); + if (name != null) { + Map m = new HashMap<>(2); + m.put("id", id); + m.put("name", name); + ReflectUtil.setFieldValue(thisModel, thisTargetField, m); + } + } + } + } + + /** + * 在主Model类型中,根据thisRelationField字段的RelationDict注解参数,将被关联对象thatModel中的数据, + * 关联到thisModel对象的thisRelationField字段中。 + * + * @param thisClazz 主对象的Class对象。 + * @param thisModel 主对象。 + * @param thatModel 字典关联对象。 + * @param thisRelationField 主表对象中保存被关联对象的字段名称。 + * @param 主表对象类型。 + * @param 从表对象类型。 + */ + public static void makeDictRelation( + Class thisClazz, T thisModel, R thatModel, String thisRelationField) { + if (thatModel == null || thisModel == null) { + return; + } + // 这里不做任何空值判断,从而让配置错误在调试期间即可抛出 + Field thisTargetField = ReflectUtil.getField(thisClazz, thisRelationField); + RelationDict r = thisTargetField.getAnnotation(RelationDict.class); + Class thatClass = r.slaveModelClass(); + Field slaveIdField = ReflectUtil.getField(thatClass, r.slaveIdField()); + Field slaveNameField = ReflectUtil.getField(thatClass, r.slaveNameField()); + Map m = new HashMap<>(2); + m.put("id", ReflectUtil.getFieldValue(thatModel, slaveIdField)); + m.put("name", ReflectUtil.getFieldValue(thatModel, slaveNameField)); + ReflectUtil.setFieldValue(thisModel, thisTargetField, m); + } + + /** + * 在主Model类型中,根据thisRelationField字段的RelationDict注解参数,将被关联对象集合thatModelList中的数据, + * 逐个关联到thisModelList每一个元素的thisRelationField字段中。 + * + * @param thisClazz 主对象的Class对象。 + * @param thisModelList 主对象列表。 + * @param thatModelList 字典关联对象列表集合。 + * @param thisRelationField 主表对象中保存被关联对象的字段名称。 + * @param 主表对象类型。 + * @param 从表对象类型。 + */ + public static void makeDictRelation( + Class thisClazz, List thisModelList, List thatModelList, String thisRelationField) { + if (CollectionUtils.isEmpty(thatModelList) + || CollectionUtils.isEmpty(thisModelList)) { + return; + } + // 这里不做任何空值判断,从而让配置错误在调试期间即可抛出 + Field thisTargetField = ReflectUtil.getField(thisClazz, thisRelationField); + RelationDict r = thisTargetField.getAnnotation(RelationDict.class); + Field masterIdField = ReflectUtil.getField(thisClazz, r.masterIdField()); + Class thatClass = r.slaveModelClass(); + Field slaveIdField = ReflectUtil.getField(thatClass, r.slaveIdField()); + Field slaveNameField = ReflectUtil.getField(thatClass, r.slaveNameField()); + Map thatMap = new HashMap<>(20); + thatModelList.forEach(thatModel -> { + Object id = ReflectUtil.getFieldValue(thatModel, slaveIdField); + thatMap.put(id, thatModel); + }); + thisModelList.forEach(thisModel -> { + if (thisModel != null) { + Object id = ReflectUtil.getFieldValue(thisModel, masterIdField); + R thatModel = thatMap.get(id); + if (thatModel != null) { + Map m = new HashMap<>(4); + m.put("id", id); + m.put("name", ReflectUtil.getFieldValue(thatModel, slaveNameField)); + ReflectUtil.setFieldValue(thisModel, thisTargetField, m); + } + } + }); + } + + /** + * 在主Model类型中,根据thisRelationField字段的RelationDict注解参数,将被关联对象集合thatModelMap中的数据, + * 逐个关联到thisModelList每一个元素的thisRelationField字段中。 + * 该函数之所以使用Map,主要出于性能优化考虑,在连续使用thatModelMap进行关联时,有效的避免了从多次从List转换到Map的过程。 + * + * @param thisClazz 主对象的Class对象。 + * @param thisModelList 主对象列表。 + * @param thatMadelMap 字典关联对象映射集合。 + * @param thisRelationField 主表对象中保存被关联对象的字段名称。 + * @param 主表对象类型。 + * @param 从表对象类型。 + */ + public static void makeDictRelation( + Class thisClazz, List thisModelList, Map thatMadelMap, String thisRelationField) { + if (MapUtils.isEmpty(thatMadelMap) + || CollectionUtils.isEmpty(thisModelList)) { + return; + } + // 这里不做任何空值判断,从而让配置错误在调试期间即可抛出 + Field thisTargetField = ReflectUtil.getField(thisClazz, thisRelationField); + RelationDict r = thisTargetField.getAnnotation(RelationDict.class); + Field masterIdField = ReflectUtil.getField(thisClazz, r.masterIdField()); + Class thatClass = r.slaveModelClass(); + Field slaveNameField = ReflectUtil.getField(thatClass, r.slaveNameField()); + thisModelList.forEach(thisModel -> { + if (thisModel != null) { + Object id = ReflectUtil.getFieldValue(thisModel, masterIdField); + R thatModel = thatMadelMap.get(id); + if (thatModel != null) { + Map m = new HashMap<>(4); + m.put("id", id); + m.put("name", ReflectUtil.getFieldValue(thatModel, slaveNameField)); + ReflectUtil.setFieldValue(thisModel, thisTargetField, m); + } + } + }); + } + + /** + * 在主Model类型中,根据thisRelationField字段的RelationOneToOne注解参数,将被关联对象列表thatModelList中的数据, + * 逐个关联到thisModelList每一个元素的thisRelationField字段中。 + * + * @param thisClazz 主对象的Class对象。 + * @param thisModelList 主对象列表。 + * @param thatModelList 一对一关联对象列表。 + * @param thisRelationField 主表对象中保存被关联对象的字段名称。 + * @param 主表对象类型。 + * @param 从表对象类型。 + */ + public static void makeOneToOneRelation( + Class thisClazz, List thisModelList, List thatModelList, String thisRelationField) { + if (CollectionUtils.isEmpty(thatModelList) + || CollectionUtils.isEmpty(thisModelList)) { + return; + } + // 这里不做任何空值判断,从而让配置错误在调试期间即可抛出 + Field thisTargetField = ReflectUtil.getField(thisClazz, thisRelationField); + RelationOneToOne r = thisTargetField.getAnnotation(RelationOneToOne.class); + Field masterIdField = ReflectUtil.getField(thisClazz, r.masterIdField()); + Class thatClass = r.slaveModelClass(); + Field slaveIdField = ReflectUtil.getField(thatClass, r.slaveIdField()); + Map thatMap = new HashMap<>(20); + thatModelList.forEach(thatModel -> { + Object id = ReflectUtil.getFieldValue(thatModel, slaveIdField); + thatMap.put(id, thatModel); + }); + // 判断放在循环的外部,提升一点儿效率。 + if (thisTargetField.getType().equals(Map.class)) { + thisModelList.forEach(thisModel -> { + Object id = ReflectUtil.getFieldValue(thisModel, masterIdField); + R thatModel = thatMap.get(id); + if (thatModel != null) { + ReflectUtil.setFieldValue(thisModel, thisTargetField, BeanUtil.beanToMap(thatModel)); + } + }); + } else { + thisModelList.forEach(thisModel -> { + Object id = ReflectUtil.getFieldValue(thisModel, masterIdField); + R thatModel = thatMap.get(id); + if (thatModel != null) { + ReflectUtil.setFieldValue(thisModel, thisTargetField, thatModel); + } + }); + } + } + + /** + * 根据主对象和关联对象各自的关联Id函数,将主对象列表和关联对象列表中的数据关联到一起,并将关联对象 + * 设置到主对象的指定关联字段中。 + * NOTE: 用于主对象关联字段中,没有包含RelationOneToOne注解的场景。 + * + * @param thisClazz 主对象的Class对象。 + * @param thisModelList 主对象列表。 + * @param thisIdGetterFunc 主对象Id的Getter函数。 + * @param thatModelList 关联对象列表。 + * @param thatIdGetterFunc 关联对象Id的Getter函数。 + * @param thisRelationField 主对象中保存被关联对象的字段名称。 + * @param 主表对象类型。 + * @param 从表对象类型。 + */ + public static void makeOneToOneRelation( + Class thisClazz, + List thisModelList, + Function thisIdGetterFunc, + List thatModelList, + Function thatIdGetterFunc, + String thisRelationField) { + makeOneToOneRelation(thisClazz, thisModelList, + thisIdGetterFunc, thatModelList, thatIdGetterFunc, thisRelationField, false); + } + + /** + * 根据主对象和关联对象各自的关联Id函数,将主对象列表和关联对象列表中的数据关联到一起,并将关联对象 + * 设置到主对象的指定关联字段中。 + * NOTE: 用于主对象关联字段中,没有包含RelationOneToOne注解的场景。 + * + * @param thisClazz 主对象的Class对象。 + * @param thisModelList 主对象列表。 + * @param thisIdGetterFunc 主对象Id的Getter函数。 + * @param thatModelList 关联对象列表。 + * @param thatIdGetterFunc 关联对象Id的Getter函数。 + * @param thisRelationField 主对象中保存被关联对象的字段名称。 + * @param orderByThatList 如果为true,则按照ThatModelList的顺序输出。同时thisModelList被排序后的新列表替换。 + * @param 主表对象类型。 + * @param 从表对象类型。 + */ + public static void makeOneToOneRelation( + Class thisClazz, + List thisModelList, + Function thisIdGetterFunc, + List thatModelList, + Function thatIdGetterFunc, + String thisRelationField, + boolean orderByThatList) { + Field thisTargetField = ReflectUtil.getField(thisClazz, thisRelationField); + boolean isMap = thisTargetField.getType().equals(Map.class); + if (orderByThatList) { + List newThisModelList = new LinkedList<>(); + Map thisModelMap = + thisModelList.stream().collect(Collectors.toMap(thisIdGetterFunc, c -> c)); + thatModelList.forEach(thatModel -> { + Object thatId = thatIdGetterFunc.apply(thatModel); + T thisModel = thisModelMap.get(thatId); + if (thisModel != null) { + ReflectUtil.setFieldValue(thisModel, thisTargetField, normalize(isMap, thatModel)); + newThisModelList.add(thisModel); + } + }); + thisModelList.clear(); + thisModelList.addAll(newThisModelList); + } else { + Map thatMadelMap = + thatModelList.stream().collect(Collectors.toMap(thatIdGetterFunc, c -> c)); + thisModelList.forEach(thisModel -> { + Object thisId = thisIdGetterFunc.apply(thisModel); + R thatModel = thatMadelMap.get(thisId); + if (thatModel != null) { + ReflectUtil.setFieldValue(thisModel, thisTargetField, normalize(isMap, thatModel)); + } + }); + } + } + + private static Object normalize(boolean isMap, M model) { + return isMap ? BeanUtil.beanToMap(model) : model; + } + + /** + * 转换过滤对象到与其等效的Example对象。 + * + * @param filterModel 过滤对象。 + * @param modelClass 过滤对象的Class对象。 + * @param 过滤对象类型。 + * @return 转换后的Example对象。 + */ + public static Example convertFilterModelToExample(T filterModel, Class modelClass) { + if (filterModel == null) { + return null; + } + Example e = new Example(modelClass); + Example.Criteria c = e.createCriteria(); + Field[] fields = ReflectUtil.getFields(modelClass); + for (Field field : fields) { + if (field.getAnnotation(Transient.class) != null) { + continue; + } + int modifiers = field.getModifiers(); + // transient类型的字段不能作为查询条件 + if ((modifiers & 128) == 0) { + ReflectUtil.setAccessible(field); + try { + Object o = field.get(filterModel); + if (o != null) { + c.andEqualTo(field.getName(), field.get(filterModel)); + } + } catch (IllegalAccessException ex) { + log.error("Failed to call reflection code.", ex); + throw new MyRuntimeException(ex); + } + } + } + return e; + } + + /** + * 私有构造函数,明确标识该常量类的作用。 + */ + private MyModelUtil() { + } +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/MyPageUtil.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/MyPageUtil.java new file mode 100644 index 00000000..76e70d0c --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/MyPageUtil.java @@ -0,0 +1,72 @@ +package com.orange.demo.common.core.util; + +import cn.jimmyshi.beanquery.BeanQuery; +import com.alibaba.fastjson.JSONObject; +import com.github.pagehelper.Page; + +import java.util.List; + +/** + * 生成带有分页信息的数据列表 + * + * @author Jerry + * @date 2020-09-25 + */ +public class MyPageUtil { + + private static final String DATA_LIST_LITERAL = "dataList"; + private static final String TOTAL_COUNT_LITERAL = "totalCount"; + + /** + * 用户构建带有分页信息的数据列表。 + * + * @param dataList 数据列表,该参数必须是调用PageMethod.startPage之后,立即执行mybatis查询操作的结果集。 + * @param includeFields 结果集中需要返回到前端的字段,多个字段之间逗号分隔。 + * @return 返回只是包含includeFields字段的数据列表,以及结果集TotalCount。 + */ + public static JSONObject makeResponseData(List dataList, String includeFields) { + JSONObject pageData = new JSONObject(); + pageData.put(DATA_LIST_LITERAL, BeanQuery.select(includeFields).from(dataList).execute()); + if (dataList instanceof Page) { + pageData.put(TOTAL_COUNT_LITERAL, ((Page)dataList).getTotal()); + } + return pageData; + } + + /** + * 用户构建带有分页信息的数据列表。 + * + * @param dataList 数据列表,该参数必须是调用PageMethod.startPage之后,立即执行mybatis查询操作的结果集。 + * @return 返回结果集和TotalCount。 + */ + public static JSONObject makeResponseData(List dataList) { + JSONObject pageData = new JSONObject(); + pageData.put(DATA_LIST_LITERAL, dataList); + if (dataList instanceof Page) { + pageData.put(TOTAL_COUNT_LITERAL, ((Page)dataList).getTotal()); + } + return pageData; + } + + /** + * 用户构建带有分页信息的数据列表。 + * + * @param dataList 数据列表,该参数必须是调用PageMethod.startPage之后,立即执行mybatis查询操作的结果集。 + * @param totalCount 总数量。 + * @return 返回结果集和TotalCount。 + */ + public static JSONObject makeResponseData(List dataList, Long totalCount) { + JSONObject pageData = new JSONObject(); + pageData.put(DATA_LIST_LITERAL, dataList); + if (totalCount != null) { + pageData.put(TOTAL_COUNT_LITERAL, totalCount); + } + return pageData; + } + + /** + * 私有构造函数,明确标识该常量类的作用。 + */ + private MyPageUtil() { + } +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/RsaUtil.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/RsaUtil.java new file mode 100644 index 00000000..a8e345c4 --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/RsaUtil.java @@ -0,0 +1,114 @@ +package com.orange.demo.common.core.util; + +import javax.crypto.Cipher; +import java.nio.charset.StandardCharsets; +import java.security.*; +import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.RSAPublicKey; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; +import java.util.Base64; +import java.util.HashMap; +import java.util.Map; + +/** + * Java RSA 加密工具类。 + * + * @author Jerry + * @date 2020-09-25 + */ +public class RsaUtil { + + /** + * 密钥长度 于原文长度对应 以及越长速度越慢 + */ + private static final int KEY_SIZE = 1024; + /** + * 用于封装随机产生的公钥与私钥 + */ + private static Map keyMap = new HashMap<>(); + + /** + * 随机生成密钥对。 + */ + public static void genKeyPair() throws NoSuchAlgorithmException { + // KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象 + KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA"); + // 初始化密钥对生成器 + keyPairGen.initialize(KEY_SIZE, new SecureRandom()); + // 生成一个密钥对,保存在keyPair中 + KeyPair keyPair = keyPairGen.generateKeyPair(); + // 得到私钥 + RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); + // 得到公钥 + RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); + String publicKeyString = Base64.getEncoder().encodeToString(publicKey.getEncoded()); + // 得到私钥字符串 + String privateKeyString = Base64.getEncoder().encodeToString(privateKey.getEncoded()); + // 将公钥和私钥保存到Map + //0表示公钥 + keyMap.put(0, publicKeyString); + //1表示私钥 + keyMap.put(1, privateKeyString); + } + + /** + * RSA公钥加密。 + * + * @param str 加密字符串 + * @param publicKey 公钥 + * @return 密文 + * @throws Exception 加密过程中的异常信息 + */ + public static String encrypt(String str, String publicKey) throws Exception { + //base64编码的公钥 + byte[] decoded = Base64.getDecoder().decode(publicKey); + RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded)); + //RSA加密 + Cipher cipher = Cipher.getInstance("RSA"); + cipher.init(Cipher.ENCRYPT_MODE, pubKey); + return Base64.getEncoder().encodeToString(cipher.doFinal(str.getBytes(StandardCharsets.UTF_8))); + } + + /** + * RSA私钥解密。 + * + * @param str 加密字符串 + * @param privateKey 私钥 + * @return 明文 + * @throws Exception 解密过程中的异常信息 + */ + public static String decrypt(String str, String privateKey) throws Exception { + //64位解码加密后的字符串 + byte[] inputByte = Base64.getDecoder().decode(str); + //base64编码的私钥 + byte[] decoded = Base64.getDecoder().decode(privateKey); + RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded)); + //RSA解密 + Cipher cipher = Cipher.getInstance("RSA"); + cipher.init(Cipher.DECRYPT_MODE, priKey); + return new String(cipher.doFinal(inputByte)); + } + + public static void main(String[] args) throws Exception { + long temp = System.currentTimeMillis(); + //生成公钥和私钥 + genKeyPair(); + //加密字符串 + System.out.println("公钥:" + keyMap.get(0)); + System.out.println("私钥:" + keyMap.get(1)); + System.out.println("生成密钥消耗时间:" + (System.currentTimeMillis() - temp) / 1000.0 + "秒"); + System.out.println("生成后的公钥前端使用!"); + System.out.println("生成后的私钥后台使用!"); + String message = "RSA测试ABCD~!@#$"; + System.out.println("原文:" + message); + temp = System.currentTimeMillis(); + String messageEn = encrypt(message, keyMap.get(0)); + System.out.println("密文:" + messageEn); + System.out.println("加密消耗时间:" + (System.currentTimeMillis() - temp) / 1000.0 + "秒"); + temp = System.currentTimeMillis(); + String messageDe = decrypt(messageEn, keyMap.get(1)); + System.out.println("解密:" + messageDe); + System.out.println("解密消耗时间:" + (System.currentTimeMillis() - temp) / 1000.0 + "秒"); + } +} \ No newline at end of file diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/TreeNode.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/TreeNode.java new file mode 100644 index 00000000..715fe5df --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/TreeNode.java @@ -0,0 +1,93 @@ +package com.orange.demo.common.core.util; + +import lombok.Data; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Function; + +/** + * 将列表结构组建为树结构的工具类。 + * + * @param 对象类型。 + * @param 节点之间关联键的类型。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Data +public class TreeNode { + + private K id; + private K parentId; + private T data; + private List> childList = new ArrayList<>(); + + /** + * 将列表结构组建为树结构的工具方法。 + * + * @param dataList 数据列表结构。 + * @param idFunc 获取关联id的函数对象。 + * @param parentIdFunc 获取关联ParentId的函数对象。 + * @param root 根节点。 + * @param 数据对象类型。 + * @param 节点之间关联键的类型。 + * @return 源数据对象的树结构存储。 + */ + public static List> build( + List dataList, Function idFunc, Function parentIdFunc, K root) { + List> treeNodeList = new ArrayList<>(); + for (T data : dataList) { + if (parentIdFunc.apply(data).equals(idFunc.apply(data))) { + continue; + } + TreeNode dataNode = new TreeNode<>(); + dataNode.setId(idFunc.apply(data)); + dataNode.setParentId(parentIdFunc.apply(data)); + dataNode.setData(data); + treeNodeList.add(dataNode); + } + return root == null ? toBuildTreeWithoutRoot(treeNodeList) : toBuildTree(treeNodeList, root); + } + + private static List> toBuildTreeWithoutRoot(List> treeNodes) { + Map> treeNodeMap = new HashMap<>(treeNodes.size()); + for (TreeNode treeNode : treeNodes) { + treeNodeMap.put(treeNode.id, treeNode); + } + List> treeNodeList = new ArrayList<>(); + for (TreeNode treeNode : treeNodes) { + TreeNode parentNode = treeNodeMap.get(treeNode.getParentId()); + if (parentNode == null) { + treeNodeList.add(treeNode); + } else { + parentNode.add(treeNode); + } + } + return treeNodeList; + } + + private static List> toBuildTree(List> treeNodes, K root) { + List> treeNodeList = new ArrayList<>(); + for (TreeNode treeNode : treeNodes) { + if (root.equals(treeNode.getParentId())) { + treeNodeList.add(treeNode); + } + for (TreeNode it : treeNodes) { + if (it.getParentId() == treeNode.getId()) { + if (treeNode.getChildList() == null) { + treeNode.setChildList(new ArrayList<>()); + } + treeNode.add(it); + } + } + } + return treeNodeList; + } + + private void add(TreeNode node) { + childList.add(node); + } +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/UpDownloadUtil.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/UpDownloadUtil.java new file mode 100644 index 00000000..fedb42d5 --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/util/UpDownloadUtil.java @@ -0,0 +1,180 @@ +package com.orange.demo.common.core.util; + +import com.alibaba.fastjson.JSON; +import com.orange.demo.common.core.constant.ApplicationConstant; +import com.orange.demo.common.core.constant.ErrorCodeEnum; +import com.orange.demo.common.core.object.ResponseResult; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.io.FilenameUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.*; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; +import java.util.Objects; + +/** + * 上传或下载附件文件的工具类。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Slf4j +public class UpDownloadUtil { + + /** + * 执行下载操作,并将读取的文件数据直接写入到HttpServletResponse应答对象。 + * + * @param rootBaseDir 文件下载的根目录。 + * @param modelName 所在数据表的实体对象名。 + * @param fieldName 关联字段的实体对象属性名。 + * @param fileName 文件名。 + * @param asImage 是否为图片对象。图片是无需权限验证的,因此和附件存放在不同的子目录。 + * @param response Http 应答对象。 + */ + public static void doDownload( + String rootBaseDir, + String modelName, + String fieldName, + String fileName, + Boolean asImage, + HttpServletResponse response) { + StringBuilder uploadPathBuilder = new StringBuilder(128); + uploadPathBuilder.append(rootBaseDir).append("/"); + if (Boolean.TRUE.equals(asImage)) { + uploadPathBuilder.append(ApplicationConstant.UPLOAD_IMAGE_PARENT_PATH); + } else { + uploadPathBuilder.append(ApplicationConstant.UPLOAD_ATTACHMENT_PARENT_PATH); + } + uploadPathBuilder.append("/").append(modelName).append("/").append(fieldName).append("/").append(fileName); + File file = new File(uploadPathBuilder.toString()); + if (!file.exists()) { + log.warn("Download file [" + uploadPathBuilder.toString() + "] failed, no file found!"); + response.setStatus(HttpServletResponse.SC_NOT_FOUND); + return; + } + response.setHeader("content-type", "application/octet-stream"); + response.setContentType("application/octet-stream"); + response.setHeader("Content-Disposition", "attachment;filename=" + fileName); + byte[] buff = new byte[2048]; + try (OutputStream os = response.getOutputStream(); + BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file))) { + int i = bis.read(buff); + while (i != -1) { + os.write(buff, 0, buff.length); + os.flush(); + i = bis.read(buff); + } + } catch (IOException e) { + log.error("Failed to call UpDownloadUtil.doDownload", e); + } + } + + /** + * 执行文件上传操作,并将与该文件下载对应的Url直接写入到HttpServletResponse应答对象,返回给前端。 + * + * @param rootBaseDir 存放上传文件的根目录。 + * @param modelName 所在数据表的实体对象名。 + * @param fieldName 关联字段的实体对象属性名。 + * @param uploadFile Http请求中上传的文件对象。 + * @param asImage 是否为图片对象。图片是无需权限验证的,因此和附件存放在不同的子目录。 + * @param response Http 应答对象。 + * @return 存储在本地上传文件名。 + * @throws IOException 文件操作错误。 + */ + public static String doUpload( + String rootBaseDir, + String modelName, + String fieldName, + Boolean asImage, + MultipartFile uploadFile, + HttpServletResponse response) throws IOException { + PrintWriter out = response.getWriter(); + response.setContentType("application/json; charset=utf-8"); + if (Objects.isNull(uploadFile) || uploadFile.isEmpty() || MyCommonUtil.isBlankOrNull(fieldName)) { + response.setStatus(HttpServletResponse.SC_FORBIDDEN); + out.print(JSON.toJSONString(ResponseResult.error(ErrorCodeEnum.INVALID_UPLOAD_FILE_ARGUMENT))); + return null; + } + StringBuilder uploadPathBuilder = new StringBuilder(128); + uploadPathBuilder.append(rootBaseDir).append("/"); + if (Boolean.TRUE.equals(asImage)) { + uploadPathBuilder.append(ApplicationConstant.UPLOAD_IMAGE_PARENT_PATH); + } else { + uploadPathBuilder.append(ApplicationConstant.UPLOAD_ATTACHMENT_PARENT_PATH); + } + uploadPathBuilder.append("/").append(modelName).append("/").append(fieldName).append("/"); + // 根据请求上传的uri构建下载uri,只是将末尾的/upload改为/download即可。 + HttpServletRequest request = ContextUtil.getHttpRequest(); + String uri = request.getRequestURI(); + uri = StringUtils.removeEnd(uri, "/"); + uri = StringUtils.removeEnd(uri, "/upload"); + String downloadUri = uri + "/download"; + StringBuilder filenameBuilder = new StringBuilder(64); + filenameBuilder.append(MyCommonUtil.generateUuid()) + .append(".").append(FilenameUtils.getExtension(uploadFile.getOriginalFilename())); + UploadFileInfo fileInfo = new UploadFileInfo(); + fileInfo.downloadUri = downloadUri; + fileInfo.filename = filenameBuilder.toString(); + try { + byte[] bytes = uploadFile.getBytes(); + Path path = Paths.get(uploadPathBuilder.toString() + filenameBuilder.toString()); + //如果没有files文件夹,则创建 + if (!Files.isWritable(path)) { + Files.createDirectories(Paths.get(uploadPathBuilder.toString())); + } + //文件写入指定路径 + Files.write(path, bytes); + } catch (IOException e) { + log.error("Failed to write uploaded file [" + uploadFile.getOriginalFilename() + " ].", e); + response.setStatus(HttpServletResponse.SC_FORBIDDEN); + out.print(JSON.toJSONString(ResponseResult.error(ErrorCodeEnum.INVALID_UPLOAD_FILE_IOERROR))); + return null; + } + out.print(JSON.toJSONString(ResponseResult.success(fileInfo))); + out.flush(); + out.close(); + return fileInfo.filename; + } + + /** + * 判断filename参数指定的文件名,是否被包含在fileInfoJson参数中。 + * + * @param fileInfoJson 内部类UploadFileInfo的JSONArray数组。 + * @param filename 被包含的文件名。 + * @return 存在返回true,否则false。 + */ + public static boolean containFile(String fileInfoJson, String filename) { + if (StringUtils.isAnyBlank(fileInfoJson, filename)) { + return false; + } + List fileInfoList = JSON.parseArray(fileInfoJson, UploadFileInfo.class); + if (CollectionUtils.isNotEmpty(fileInfoList)) { + for (UploadFileInfo fileInfo : fileInfoList) { + if (StringUtils.equals(filename, fileInfo.filename)) { + return true; + } + } + } + return false; + } + + /** + * 私有构造函数,明确标识该常量类的作用。 + */ + private UpDownloadUtil() { + } + + @Data + static class UploadFileInfo { + private String downloadUri; + private String filename; + } +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/validator/AddGroup.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/validator/AddGroup.java new file mode 100644 index 00000000..a0412961 --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/validator/AddGroup.java @@ -0,0 +1,10 @@ +package com.orange.demo.common.core.validator; + +/** + * 数据增加的验证分组。通常用于数据新增场景。 + * + * @author Jerry + * @date 2020-09-25 + */ +public interface AddGroup { +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/validator/ConstDictRef.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/validator/ConstDictRef.java new file mode 100644 index 00000000..eb897142 --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/validator/ConstDictRef.java @@ -0,0 +1,48 @@ +package com.orange.demo.common.core.validator; + +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; + +/** + * 定义在Model对象中,标注字段值引用自指定的常量字典,和ConstDictRefValidator对象配合完成数据验证。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Target({ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +@Constraint(validatedBy = ConstDictValidator.class) +public @interface ConstDictRef { + + /** + * 引用的常量字典对象,该对象必须包含isValid的静态方法。 + * + * @return 最大长度。 + */ + Class constDictClass(); + + /** + * 超过边界后的错误消息提示。 + * + * @return 错误提示。 + */ + String message() default "无效的字典引用值!"; + + /** + * 验证分组。 + * + * @return 验证分组。 + */ + Class[] groups() default {}; + + /** + * 载荷对象类型。 + * + * @return 载荷对象。 + */ + Class[] payload() default {}; +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/validator/ConstDictValidator.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/validator/ConstDictValidator.java new file mode 100644 index 00000000..dd8dce31 --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/validator/ConstDictValidator.java @@ -0,0 +1,33 @@ +package com.orange.demo.common.core.validator; + +import cn.hutool.core.util.ReflectUtil; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; +import java.lang.reflect.Method; + +/** + * 数据字段自定义验证,用于验证Model中字符串字段的最大长度和最小长度。 + * + * @author Jerry + * @date 2020-09-25 + */ +public class ConstDictValidator implements ConstraintValidator { + + private ConstDictRef constDictRef; + + @Override + public void initialize(ConstDictRef constDictRef) { + this.constDictRef = constDictRef; + } + + @Override + public boolean isValid(Object s, ConstraintValidatorContext constraintValidatorContext) { + if (s == null) { + return true; + } + Method method = + ReflectUtil.getMethodByName(constDictRef.constDictClass(), "isValid"); + return ReflectUtil.invokeStatic(method, s); + } +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/validator/TextLength.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/validator/TextLength.java new file mode 100644 index 00000000..31f669a1 --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/validator/TextLength.java @@ -0,0 +1,55 @@ +package com.orange.demo.common.core.validator; + +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; + +/** + * 定义在Model或Dto对象中,UTF-8编码的字符串字段长度的上限和下限,和TextLengthValidator对象配合完成数据验证。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Target({ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +@Constraint(validatedBy = TextLengthValidator.class) +public @interface TextLength { + + /** + * 字符串字段的最小长度。 + * + * @return 最小长度。 + */ + int min() default 0; + + /** + * 字符串字段的最大长度。 + * + * @return 最大长度。 + */ + int max() default Integer.MAX_VALUE; + + /** + * 超过边界后的错误消息提示。 + * + * @return 错误提示。 + */ + String message() default "字段长度超过最大字节数!"; + + /** + * 验证分组。 + * + * @return 验证分组。 + */ + Class[] groups() default { }; + + /** + * 载荷对象类型。 + * + * @return 载荷对象。 + */ + Class[] payload() default { }; +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/validator/TextLengthValidator.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/validator/TextLengthValidator.java new file mode 100644 index 00000000..cf643f25 --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/validator/TextLengthValidator.java @@ -0,0 +1,39 @@ +package com.orange.demo.common.core.validator; + +import org.apache.commons.lang3.CharUtils; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; + +/** + * 数据字段自定义验证,用于验证Model中UTF-8编码的字符串字段的最大长度和最小长度。 + * + * @author Jerry + * @date 2020-09-25 + */ +public class TextLengthValidator implements ConstraintValidator { + + private TextLength textLength; + + @Override + public void initialize(TextLength textLength) { + this.textLength = textLength; + } + + @Override + public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) { + if (s == null) { + return true; + } + int length = 0; + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + if (CharUtils.isAscii(c)) { + ++length; + } else { + length += 2; + } + } + return length >= textLength.min() && length <= textLength.max(); + } +} diff --git a/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/validator/UpdateGroup.java b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/validator/UpdateGroup.java new file mode 100644 index 00000000..f8d34107 --- /dev/null +++ b/orange-demo-single-service/common/common-core/src/main/java/com/orange/demo/common/core/validator/UpdateGroup.java @@ -0,0 +1,11 @@ +package com.orange.demo.common.core.validator; + +/** + * 数据修改的验证分组。通常用于数据更新的场景。 + * + * @author Jerry + * @date 2020-09-25 + */ +public interface UpdateGroup { + +} diff --git a/orange-demo-single-service/common/common-sequence/pom.xml b/orange-demo-single-service/common/common-sequence/pom.xml new file mode 100644 index 00000000..6c801e67 --- /dev/null +++ b/orange-demo-single-service/common/common-sequence/pom.xml @@ -0,0 +1,24 @@ + + + + common + com.orange.demo + 1.0.0 + + 4.0.0 + + common-sequence + 1.0.0 + common-sequence + jar + + + + com.orange.demo + common-core + 1.0.0 + + + \ No newline at end of file diff --git a/orange-demo-single-service/common/common-sequence/src/main/java/com/orange/demo/common/sequence/config/IdGeneratorAutoConfigure.java b/orange-demo-single-service/common/common-sequence/src/main/java/com/orange/demo/common/sequence/config/IdGeneratorAutoConfigure.java new file mode 100644 index 00000000..b335355e --- /dev/null +++ b/orange-demo-single-service/common/common-sequence/src/main/java/com/orange/demo/common/sequence/config/IdGeneratorAutoConfigure.java @@ -0,0 +1,14 @@ +package com.orange.demo.common.sequence.config; + +import org.springframework.boot.context.properties.EnableConfigurationProperties; + +/** + * common-sequence模块的自动配置引导类。 + * + * @author Jerry + * @date 2020-09-25 + */ +@EnableConfigurationProperties({IdGeneratorProperties.class}) +public class IdGeneratorAutoConfigure { + +} diff --git a/orange-demo-single-service/common/common-sequence/src/main/java/com/orange/demo/common/sequence/config/IdGeneratorProperties.java b/orange-demo-single-service/common/common-sequence/src/main/java/com/orange/demo/common/sequence/config/IdGeneratorProperties.java new file mode 100644 index 00000000..b6ad2baa --- /dev/null +++ b/orange-demo-single-service/common/common-sequence/src/main/java/com/orange/demo/common/sequence/config/IdGeneratorProperties.java @@ -0,0 +1,20 @@ +package com.orange.demo.common.sequence.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; + +/** + * common-sequence模块的配置类。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Data +@ConfigurationProperties(prefix = "sequence") +public class IdGeneratorProperties { + + /** + * 基础版生成器所需的WorkNode参数值。仅当advanceIdGenerator为false时生效。 + */ + private Integer snowflakeWorkNode = 1; +} diff --git a/orange-demo-single-service/common/common-sequence/src/main/java/com/orange/demo/common/sequence/generator/BasicIdGenerator.java b/orange-demo-single-service/common/common-sequence/src/main/java/com/orange/demo/common/sequence/generator/BasicIdGenerator.java new file mode 100644 index 00000000..729acb17 --- /dev/null +++ b/orange-demo-single-service/common/common-sequence/src/main/java/com/orange/demo/common/sequence/generator/BasicIdGenerator.java @@ -0,0 +1,48 @@ +package com.orange.demo.common.sequence.generator; + +import cn.hutool.core.lang.Snowflake; +import cn.hutool.core.util.IdUtil; + +/** + * 基础版snowflake计算工具类。 + * 和SnowflakeIdGenerator相比,相同点是均为基于Snowflake算法的生成器。不同点在于当前类的 + * WorkNodeId是通过配置文件静态指定的。而SnowflakeIdGenerator的WorkNodeId是由zk生成的。 + * + * @author Jerry + * @date 2020-09-25 + */ +public class BasicIdGenerator implements MyIdGenerator { + + private Snowflake snowflake; + + /** + * 构造函数。 + * + * @param workNode 工作节点。 + */ + public BasicIdGenerator(Integer workNode) { + snowflake = IdUtil.createSnowflake(workNode, 0); + } + + /** + * 获取基于Snowflake算法的数值型Id。 + * 由于底层实现为synchronized方法,因此计算过程串行化,且线程安全。 + * + * @return 计算后的全局唯一Id。 + */ + @Override + public long nextLongId() { + return this.snowflake.nextId(); + } + + /** + * 获取基于Snowflake算法的字符串Id。 + * 由于底层实现为synchronized方法,因此计算过程串行化,且线程安全。 + * + * @return 计算后的全局唯一Id。 + */ + @Override + public String nextStringId() { + return this.snowflake.nextIdStr(); + } +} diff --git a/orange-demo-single-service/common/common-sequence/src/main/java/com/orange/demo/common/sequence/generator/MyIdGenerator.java b/orange-demo-single-service/common/common-sequence/src/main/java/com/orange/demo/common/sequence/generator/MyIdGenerator.java new file mode 100644 index 00000000..a1d67f08 --- /dev/null +++ b/orange-demo-single-service/common/common-sequence/src/main/java/com/orange/demo/common/sequence/generator/MyIdGenerator.java @@ -0,0 +1,24 @@ +package com.orange.demo.common.sequence.generator; + +/** + * 分布式Id生成器的统一接口。 + * + * @author Jerry + * @date 2020-09-25 + */ +public interface MyIdGenerator { + + /** + * 获取数值型分布式Id。 + * + * @return 生成后的Id。 + */ + long nextLongId(); + + /** + * 获取字符型分布式Id。 + * + * @return 生成后的Id。 + */ + String nextStringId(); +} diff --git a/orange-demo-single-service/common/common-sequence/src/main/java/com/orange/demo/common/sequence/wrapper/IdGeneratorWrapper.java b/orange-demo-single-service/common/common-sequence/src/main/java/com/orange/demo/common/sequence/wrapper/IdGeneratorWrapper.java new file mode 100644 index 00000000..21d2c568 --- /dev/null +++ b/orange-demo-single-service/common/common-sequence/src/main/java/com/orange/demo/common/sequence/wrapper/IdGeneratorWrapper.java @@ -0,0 +1,52 @@ +package com.orange.demo.common.sequence.wrapper; + +import com.orange.demo.common.sequence.config.IdGeneratorProperties; +import com.orange.demo.common.sequence.generator.BasicIdGenerator; +import com.orange.demo.common.sequence.generator.MyIdGenerator; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; + +/** + * 分布式Id生成器的封装类。该对象可根据配置选择不同的生成器实现类。 + * + * @author Jerry + * @date 2020-09-25 + */ +@Component +public class IdGeneratorWrapper { + + @Autowired + private IdGeneratorProperties properties; + /** + * Id生成器接口对象。 + */ + private MyIdGenerator idGenerator; + + /** + * 今后如果支持更多Id生成器时,可以在该函数内实现不同生成器的动态选择。 + */ + @PostConstruct + public void init() { + idGenerator = new BasicIdGenerator(properties.getSnowflakeWorkNode()); + } + + /** + * 由于底层实现为synchronized方法,因此计算过程串行化,且线程安全。 + * + * @return 计算后的全局唯一Id。 + */ + public long nextLongId() { + return idGenerator.nextLongId(); + } + + /** + * 由于底层实现为synchronized方法,因此计算过程串行化,且线程安全。 + * + * @return 计算后的全局唯一Id。 + */ + public String nextStringId() { + return idGenerator.nextStringId(); + } +} diff --git a/orange-demo-single-service/common/common-sequence/src/main/resources/META-INF/spring.factories b/orange-demo-single-service/common/common-sequence/src/main/resources/META-INF/spring.factories new file mode 100644 index 00000000..b2628200 --- /dev/null +++ b/orange-demo-single-service/common/common-sequence/src/main/resources/META-INF/spring.factories @@ -0,0 +1,2 @@ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ +com.orange.demo.common.sequence.config.IdGeneratorAutoConfigure \ No newline at end of file diff --git a/orange-demo-single-service/common/pom.xml b/orange-demo-single-service/common/pom.xml new file mode 100644 index 00000000..6dc41ee7 --- /dev/null +++ b/orange-demo-single-service/common/pom.xml @@ -0,0 +1,18 @@ + + + + com.orange.demo + OrangeSingleDemo + 1.0.0 + + 4.0.0 + + common + pom + + + common-core + common-sequence + + diff --git a/orange-demo-single-service/pom.xml b/orange-demo-single-service/pom.xml new file mode 100644 index 00000000..8cd555bc --- /dev/null +++ b/orange-demo-single-service/pom.xml @@ -0,0 +1,149 @@ + + + 4.0.0 + + com.orange.demo + OrangeSingleDemo + 1.0.0 + OrangeSingleDemo + pom + + + 2.2.5.RELEASE + Cairo-SR8 + 2.2.2 + UTF-8 + 1.8 + 1.8 + 1.8 + OrangeSingleDemo + + + 4.4 + 1.8 + 4.1.2 + 5.1.5 + 0.9.1 + 1.2.70 + 1.1.5 + 2.8.1 + 1.3.1.Final + + + 1.1.22 + 2.1.5 + 1.3.7 + 1.2.13 + + + + application + application-common + common + + + + + + org.springframework.boot + spring-boot-starter-web + + + spring-boot-starter-logging + org.springframework.boot + + + + + + org.springframework.boot + spring-boot-starter-freemarker + + + + javax.servlet + javax.servlet-api + + + + org.springframework.boot + spring-boot-starter-log4j2 + + + + org.springframework.boot + spring-boot-starter-aop + + + + org.springframework.boot + spring-boot-starter-cache + + + + org.springframework.boot + spring-boot-configuration-processor + true + + + + org.springframework.security + spring-security-crypto + + + + org.springframework.boot + spring-boot-starter-actuator + + + + de.codecentric + spring-boot-admin-starter-client + ${spring-boot-admin.version} + + + + org.mapstruct + mapstruct + ${mapstruct.version} + + + org.mapstruct + mapstruct-processor + ${mapstruct.version} + provided + + + + org.projectlombok + lombok + provided + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-dependencies + ${spring-boot.version} + pom + import + + + io.spring.platform + platform-bom + ${spring-platform.version} + pom + import + + + + diff --git a/orange-demo-single-service/zz-orange-demo.sql b/orange-demo-single-service/zz-orange-demo.sql new file mode 100644 index 00000000..875d9dfc --- /dev/null +++ b/orange-demo-single-service/zz-orange-demo.sql @@ -0,0 +1,5043 @@ +CREATE DATABASE `zzdemo-single` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_bin; +USE `zzdemo-single`; + +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +-- ---------------------------- +-- Table structure for zz_class +-- ---------------------------- +DROP TABLE IF EXISTS `zz_class`; +CREATE TABLE `zz_class` ( + `class_id` bigint(20) NOT NULL COMMENT '班级Id', + `class_name` varchar(64) COLLATE utf8mb4_bin NOT NULL COMMENT '班级名称', + `school_id` bigint(20) NOT NULL COMMENT '学校Id', + `leader_id` bigint(20) NOT NULL COMMENT '学生班长Id', + `finish_class_hour` int(11) NOT NULL DEFAULT '0' COMMENT '已完成课时数量', + `class_level` tinyint(4) NOT NULL COMMENT '班级级别(0: 初级班 1: 培优班 2: 冲刺提分班 3: 竞赛班)', + `create_user_id` bigint(20) NOT NULL COMMENT '创建用户', + `create_time` datetime NOT NULL COMMENT '班级创建时间', + `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '班级状态(0: 正常 1: 解散)', + PRIMARY KEY (`class_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; + +-- ---------------------------- +-- Records of zz_class +-- ---------------------------- +BEGIN; +INSERT INTO `zz_class` VALUES (1016971499387228160, '小学一年级随堂班', 1015817732197453824, 1015842628948463616, 15, 0, 1093809448606765057, CURDATE(), 1); +INSERT INTO `zz_class` VALUES (1016971692685922304, '小学二年级随堂班', 1015818056597508096, 1018000939508568064, 20, 0, 1093809448606765057, CURDATE(), 1); +INSERT INTO `zz_class` VALUES (1016971755373989888, '小学三年级随堂班', 1015817732197453824, 1015842628948463616, 100, 0, 1093809448606765057, CURDATE(), 1); +INSERT INTO `zz_class` VALUES (1016971816040402944, '小学四年级随堂班', 1015817732197453824, 1015852853839532032, 0, 0, 1093809448606765057, CURDATE(), 1); +INSERT INTO `zz_class` VALUES (1016971872105664512, '小学五年级随堂班', 1015818056597508096, 1018001219050541056, 0, 0, 1093809448606765057, CURDATE(), 1); +INSERT INTO `zz_class` VALUES (1016971931153076224, '小学六年级随堂班', 1015817732197453824, 1015852480873631744, 0, 0, 1093809448606765057, CURDATE(), 1); +INSERT INTO `zz_class` VALUES (1016972016347779072, '小学一年级提高班', 1015817732197453824, 1015842628948463616, 0, 1, 1093809448606765057, CURDATE(), 1); +INSERT INTO `zz_class` VALUES (1016972071955861504, '小学二年级提高班', 1015817732197453824, 1015852480873631744, 0, 1, 1093809448606765057, CURDATE(), 1); +INSERT INTO `zz_class` VALUES (1016972128667045888, '小学三年级提高班', 1015818056597508096, 1018001219050541056, 0, 1, 1093809448606765057, CURDATE(), 1); +INSERT INTO `zz_class` VALUES (1016972187949338624, '小学四年级提高班', 1015817732197453824, 1015852480873631744, 0, 1, 1093809448606765057, CURDATE(), 1); +INSERT INTO `zz_class` VALUES (1016972236452270080, '小学五年级提高班', 1015817732197453824, 1015852480873631744, 0, 1, 1093809448606765057, CURDATE(), 1); +INSERT INTO `zz_class` VALUES (1016972308355223552, '小学六年级提高班', 1015818056597508096, 1018000939508568064, 0, 1, 1093809448606765057, CURDATE(), 1); +INSERT INTO `zz_class` VALUES (1016972406023786496, '小学奥林匹克竞赛班', 1015818056597508096, 1018001219050541056, 0, 1, 1093809448606765057, CURDATE(), 1); +INSERT INTO `zz_class` VALUES (1016972484746678272, '小学毕业提分班', 1015818056597508096, 1018000939508568064, 0, 2, 1093809448606765057, CURDATE(), 1); +COMMIT; + +-- ---------------------------- +-- Table structure for zz_class_course +-- ---------------------------- +DROP TABLE IF EXISTS `zz_class_course`; +CREATE TABLE `zz_class_course` ( + `class_id` bigint(20) NOT NULL COMMENT '班级Id', + `course_id` bigint(20) NOT NULL COMMENT '课程Id', + `course_order` tinyint(4) NOT NULL DEFAULT '0' COMMENT '课程顺序(数值越小越靠前)', + PRIMARY KEY (`class_id`,`course_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; + +-- ---------------------------- +-- Records of zz_class_course +-- ---------------------------- +BEGIN; +INSERT INTO `zz_class_course` VALUES (1016971499387228160, 1016699195411402752, 0); +INSERT INTO `zz_class_course` VALUES (1016971499387228160, 1016917385529790464, 0); +INSERT INTO `zz_class_course` VALUES (1016971499387228160, 1016920878164480000, 0); +INSERT INTO `zz_class_course` VALUES (1016971499387228160, 1016923276064854016, 0); +INSERT INTO `zz_class_course` VALUES (1016971692685922304, 1016917385529790464, 0); +INSERT INTO `zz_class_course` VALUES (1016971755373989888, 1016917732260319232, 0); +INSERT INTO `zz_class_course` VALUES (1016971755373989888, 1016917900699373568, 0); +INSERT INTO `zz_class_course` VALUES (1016971755373989888, 1016918360520921088, 0); +INSERT INTO `zz_class_course` VALUES (1016971755373989888, 1016918605715738624, 0); +INSERT INTO `zz_class_course` VALUES (1016971755373989888, 1016918836729614336, 0); +COMMIT; + +-- ---------------------------- +-- Table structure for zz_class_student +-- ---------------------------- +DROP TABLE IF EXISTS `zz_class_student`; +CREATE TABLE `zz_class_student` ( + `class_id` bigint(20) NOT NULL COMMENT '班级Id', + `student_id` bigint(20) NOT NULL COMMENT '学生Id', + PRIMARY KEY (`class_id`,`student_id`) USING BTREE, + KEY `idx_student_id` (`student_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; + +-- ---------------------------- +-- Records of zz_class_student +-- ---------------------------- +BEGIN; +INSERT INTO `zz_class_student` VALUES (1016971499387228160, 1015842628948463616); +INSERT INTO `zz_class_student` VALUES (1016971692685922304, 1015842628948463616); +INSERT INTO `zz_class_student` VALUES (1016971499387228160, 1015852480873631744); +INSERT INTO `zz_class_student` VALUES (1016971692685922304, 1015852853839532032); +INSERT INTO `zz_class_student` VALUES (1016972016347779072, 1018000939508568064); +INSERT INTO `zz_class_student` VALUES (1016972016347779072, 1018001219050541056); +COMMIT; + +-- ---------------------------- +-- Table structure for zz_course +-- ---------------------------- +DROP TABLE IF EXISTS `zz_course`; +CREATE TABLE `zz_course` ( + `course_id` bigint(20) NOT NULL COMMENT '主键Id', + `course_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '课程名称', + `price` decimal(10,2) NOT NULL COMMENT '课程价格', + `description` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '课程描述', + `difficulty` int(11) NOT NULL COMMENT '课程难度(0: 容易 1: 普通 2: 很难)', + `grade_id` tinyint(4) NOT NULL COMMENT '年级Id', + `subject_id` tinyint(4) NOT NULL COMMENT '学科Id', + `class_hour` int(11) NOT NULL COMMENT '课时数量', + `picture_url` varchar(1024) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '多张课程图片地址', + `create_user_id` bigint(20) NOT NULL COMMENT '创建用户Id', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_time` datetime NOT NULL COMMENT '最后修改时间', + PRIMARY KEY (`course_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; + +-- ---------------------------- +-- Records of zz_course +-- ---------------------------- +BEGIN; +INSERT INTO `zz_course` VALUES (1016699195411402752, '小学一年级拼音基础练习', 299.00, '小学一年级拼音基础练习', 0, 1, 0, 10, '[{\"name\":\"IMG_0003.JPG\",\"downloadUri\":\"/admin/coursepaper/course/download\",\"filename\":\"b09ef09478d8452d908600ff98b6f1ce.JPG\"}]', 1093809448606765057, CURDATE(), CURDATE()); +INSERT INTO `zz_course` VALUES (1016917385529790464, '小学二年级语文课程', 980.00, '小学二年级课程', 1, 2, 0, 25, '[{\"name\":\"IMG_0455.JPG\",\"downloadUri\":\"/admin/coursepaper/course/download\",\"filename\":\"79651a658e88408888f847366fbf98d0.JPG\"}]', 1093809448606765057, CURDATE(), CURDATE()); +INSERT INTO `zz_course` VALUES (1016917732260319232, '小学三年级语文课程', 1080.00, '小学三年级语文课程', 1, 3, 0, 30, '[{\"name\":\"IMG_0001.JPG\",\"downloadUri\":\"/admin/coursepaper/course/download\",\"filename\":\"0d11548eb91142d49a9253c0060d3f94.JPG\"}]', 1093809448606765057, CURDATE(), CURDATE()); +INSERT INTO `zz_course` VALUES (1016917900699373568, '小学四年级语文课程', 888.00, '小学四年级语文课程', 1, 4, 0, 27, '[{\"name\":\"IMG_0002.JPG\",\"downloadUri\":\"/admin/coursepaper/course/download\",\"filename\":\"7358b520e31e4ee0b2b8c4f9c31614d9.JPG\"}]', 1093809448606765057, CURDATE(), CURDATE()); +INSERT INTO `zz_course` VALUES (1016918360520921088, '小学五年级语文课程', 1199.00, '小学五年级语文课程', 2, 5, 0, 30, '[{\"name\":\"IMG_0004.JPG\",\"downloadUri\":\"/admin/coursepaper/course/download\",\"filename\":\"cf804a5e14fb498fa8bf3745cad39bca.JPG\"}]', 1093809448606765057, CURDATE(), CURDATE()); +INSERT INTO `zz_course` VALUES (1016918605715738624, '小学六年级语文课程', 1288.00, '小学六年级语文课程', 2, 6, 0, 32, '[{\"name\":\"IMG_0006.JPG\",\"downloadUri\":\"/admin/coursepaper/course/download\",\"filename\":\"a0d0476fac9c46f08b7ebef597b8765a.JPG\"}]', 1093809448606765057, CURDATE(), CURDATE()); +INSERT INTO `zz_course` VALUES (1016918836729614336, '天津小学一年级语文课程', 300.00, '天津小学一年级语文课程', 0, 1, 0, 20, '[{\"name\":\"IMG_0003.JPG\",\"downloadUri\":\"/admin/coursepaper/course/download\",\"filename\":\"7f64971a69944b0082f21a6036c31efd.JPG\"}]', 1093809448606765057, CURDATE(), CURDATE()); +INSERT INTO `zz_course` VALUES (1016920152549888000, '天津小学二年级语文课程', 699.00, '天津小学二年级语文课程', 1, 2, 0, 20, '[{\"name\":\"IMG_0007.JPG\",\"downloadUri\":\"/admin/coursepaper/course/download\",\"filename\":\"4baf08c1da8741bb808caf09475e49a9.JPG\"}]', 1093809448606765057, CURDATE(), CURDATE()); +INSERT INTO `zz_course` VALUES (1016920339255136256, '天津小学三年级语文课程', 998.00, '天津小学三年级语文课程', 1, 3, 0, 25, '[{\"name\":\"IMG_0009.JPG\",\"downloadUri\":\"/admin/coursepaper/course/download\",\"filename\":\"6bc1eaab831d49708e4b1e0a5d657d61.JPG\"}]', 1093809448606765057, CURDATE(), CURDATE()); +INSERT INTO `zz_course` VALUES (1016920878164480000, '小学数学一年级课程', 388.00, '小学数学一年级课程', 0, 1, 1, 15, '[{\"name\":\"IMG_0010.JPG\",\"downloadUri\":\"/admin/coursepaper/course/download\",\"filename\":\"7e9583aba9594a98b1e0268837d2a5d0.JPG\"}]', 1093809448606765057, CURDATE(), CURDATE()); +INSERT INTO `zz_course` VALUES (1016921053566078976, '小学数学二年级课程', 700.00, '小学数学二年级课程', 0, 2, 1, 20, '[{\"name\":\"shuxue2.jpg\",\"downloadUri\":\"/admin/app/course/download\",\"filename\":\"7a1fdc70976f4820aa019f91514de272.jpg\"}]', 1093809448606765057, CURDATE(), CURDATE()); +INSERT INTO `zz_course` VALUES (1016921250996162560, '小学数学三年级课程', 700.00, '小学数学三年级课程', 1, 3, 1, 20, '[{\"name\":\"shuxue.jpg\",\"downloadUri\":\"/admin/app/course/download\",\"filename\":\"f14c0f101146453c80607230e842f1c9.jpg\"},{\"name\":\"shuxue2.jpg\",\"downloadUri\":\"/admin/app/course/download\",\"filename\":\"b8451e95fa314facaa8a3cd720888574.jpg\"}]', 1093809448606765057, CURDATE(), CURDATE()); +INSERT INTO `zz_course` VALUES (1016921446102601728, '小学数学四年级课程', 800.00, '小学数学四年级课程', 1, 4, 1, 21, '[{\"name\":\"shuxue2.jpg\",\"downloadUri\":\"/admin/app/course/download\",\"filename\":\"78e1cac8c4284c8a82c7ea4bef5162a4.jpg\"}]', 1093809448606765057, CURDATE(), CURDATE()); +INSERT INTO `zz_course` VALUES (1016921667582824448, '小学数学五年级课程', 900.00, '小学数学五年级课程', 2, 5, 1, 25, '[{\"name\":\"shuxue.jpg\",\"downloadUri\":\"/admin/app/course/download\",\"filename\":\"167967c0c025406483861eed038111a0.jpg\"}]', 1093809448606765057, CURDATE(), CURDATE()); +INSERT INTO `zz_course` VALUES (1016922210208321536, '小学数学六年级课程', 1099.00, '小学数学六年级课程', 2, 6, 1, 20, '[{\"name\":\"shuxue2.jpg\",\"downloadUri\":\"/admin/app/course/download\",\"filename\":\"7f79d414e4b14ce19d75f038306088a9.jpg\"}]', 1093809448606765057, CURDATE(), CURDATE()); +INSERT INTO `zz_course` VALUES (1016922414236045312, '天津数学一年级课程', 499.00, '天津数学一年级课程', 0, 1, 1, 20, '[{\"name\":\"shuxue.jpg\",\"downloadUri\":\"/admin/app/course/download\",\"filename\":\"59d6f1cea3584a1ab637ab6a69ebacd6.jpg\"}]', 1093809448606765057, CURDATE(), CURDATE()); +INSERT INTO `zz_course` VALUES (1016922587657932800, '天津数学二年级课程', 500.00, '天津数学二年级课程', 1, 2, 1, 25, '[{\"name\":\"shuxue2.jpg\",\"downloadUri\":\"/admin/app/course/download\",\"filename\":\"830a0f67737e4b79a605ecbbd20f9418.jpg\"},{\"name\":\"shuxue.jpg\",\"downloadUri\":\"/admin/app/course/download\",\"filename\":\"5f9be80c275c48bda8a67562276aa04e.jpg\"}]', 1093809448606765057, CURDATE(), CURDATE()); +INSERT INTO `zz_course` VALUES (1016922752997396480, '天津数学三年级课程', 799.00, '天津数学三年级课程', 2, 3, 1, 24, '[{\"name\":\"shuxue2.jpg\",\"downloadUri\":\"/admin/app/course/download\",\"filename\":\"0fb454a0d56843e6b77bfc874f8a4a0f.jpg\"}]', 1093809448606765057, CURDATE(), CURDATE()); +INSERT INTO `zz_course` VALUES (1016923276064854016, '小学英语一年级课程', 399.00, '小学英语一年级课程', 0, 1, 2, 15, '[{\"name\":\"english.jpg\",\"downloadUri\":\"/admin/app/course/download\",\"filename\":\"44177c3674f543fda24222b8297ef203.jpg\"}]', 1093809448606765057, CURDATE(), CURDATE()); +INSERT INTO `zz_course` VALUES (1016923512082534400, '小学英语二年级课程', 428.00, '小学英语二年级课程', 0, 2, 2, 15, '[{\"name\":\"english2.jpg\",\"downloadUri\":\"/admin/app/course/download\",\"filename\":\"1a775271ccf9436c8b4e92a841556d79.jpg\"}]', 1093809448606765057, CURDATE(), CURDATE()); +INSERT INTO `zz_course` VALUES (1016924065042796544, '小学英语三年级课程', 666.00, '小学英语三年级课程', 1, 3, 2, 25, '[{\"name\":\"english2.jpg\",\"downloadUri\":\"/admin/app/course/download\",\"filename\":\"d9eded33a06d4931ae326cac3871948f.jpg\"},{\"name\":\"english.jpg\",\"downloadUri\":\"/admin/app/course/download\",\"filename\":\"f179474ce95e4210b4e2a04d480c6535.jpg\"}]', 1093809448606765057, CURDATE(), CURDATE()); +INSERT INTO `zz_course` VALUES (1016924308048187392, '小学英语四年级课程', 700.00, '小学英语四年级课程', 1, 4, 2, 25, '[{\"name\":\"english.jpg\",\"downloadUri\":\"/admin/app/course/download\",\"filename\":\"c71da8ce21b44dd8bb761fa93b09a341.jpg\"}]', 1093809448606765057, CURDATE(), CURDATE()); +INSERT INTO `zz_course` VALUES (1016924664354312192, '小学英语五年级课程', 805.00, '小学英语五年级课程', 2, 5, 2, 28, '[{\"name\":\"english2.jpg\",\"downloadUri\":\"/admin/app/course/download\",\"filename\":\"0d81493585d94962acbcdc81c074224a.jpg\"}]', 1093809448606765057, CURDATE(), CURDATE()); +INSERT INTO `zz_course` VALUES (1016924985629609984, '小学英语六年级课程', 998.00, '小学英语六年级课程', 2, 6, 2, 30, '[{\"name\":\"english.jpg\",\"downloadUri\":\"/admin/app/course/download\",\"filename\":\"17b2b4380fc746659666f9c51bfa7618.jpg\"}]', 1093809448606765057, CURDATE(), CURDATE()); +INSERT INTO `zz_course` VALUES (1016925257013661696, '天津英语一年级课程', 499.00, '天津英语一年级课程', 0, 1, 2, 20, '[{\"name\":\"english2.jpg\",\"downloadUri\":\"/admin/app/course/download\",\"filename\":\"dd15b00b79154c398a3daa9fb8cff9f9.jpg\"},{\"name\":\"english.jpg\",\"downloadUri\":\"/admin/app/course/download\",\"filename\":\"2a0b1f0d262649a294a9f647421f5a7e.jpg\"}]', 1093809448606765057, CURDATE(), CURDATE()); +INSERT INTO `zz_course` VALUES (1016925420855758848, '天津英语二年级课程', 528.00, '天津英语二年级课程', 1, 2, 2, 23, '[{\"name\":\"english.jpg\",\"downloadUri\":\"/admin/app/course/download\",\"filename\":\"7dc07373076f452eac02d9405ac83479.jpg\"}]', 1093809448606765057, CURDATE(), CURDATE()); +INSERT INTO `zz_course` VALUES (1018007994936070144, '小学一年级语文课程B', 1111.00, '1112222', 0, 1, 1, 23, '[{\"name\":\"微信图片_20190406094309.jpg\",\"downloadUri\":\"/admin/app/course/download\",\"filename\":\"b11699acb7094c11a1c1efa71d53ee19.jpg\"},{\"name\":\"微信图片_20190406094305.jpg\",\"downloadUri\":\"/admin/app/course/download\",\"filename\":\"e248874a47e849e29dd7b699b2685d30.jpg\"}]', 1093809448606765057, CURDATE(), CURDATE()); +COMMIT; + +-- ---------------------------- +-- Table structure for zz_course_trans_stats +-- ---------------------------- +DROP TABLE IF EXISTS `zz_course_trans_stats`; +CREATE TABLE `zz_course_trans_stats` ( + `stats_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键Id', + `stats_date` date NOT NULL COMMENT '统计日期', + `subject_id` tinyint(4) NOT NULL COMMENT '科目Id', + `grade_id` tinyint(4) NOT NULL COMMENT '年级Id', + `grade_name` varchar(20) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '年级名称', + `course_id` bigint(20) NOT NULL COMMENT '课程Id', + `course_name` varchar(128) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '课程名称', + `student_attend_count` int(11) NOT NULL COMMENT '学生上课次数', + `student_flower_amount` int(11) NOT NULL COMMENT '学生献花数量', + `student_flower_count` int(11) NOT NULL COMMENT '学生献花次数', + PRIMARY KEY (`stats_id`) USING BTREE, + UNIQUE KEY `uk_stats_date_subject_id_grade_course_id` (`stats_date`,`grade_id`,`course_id`) USING BTREE, + KEY `idx_grade_id` (`grade_id`) USING BTREE, + KEY `idx_course_id` (`course_id`) USING BTREE +) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; + +-- ---------------------------- +-- Records of zz_course_trans_stats +-- ---------------------------- +BEGIN; +INSERT INTO `zz_course_trans_stats` VALUES (1, '2020-01-10', 0, 1, NULL, 1016699195411402752, '小学一年级拼音基础练习', 1, 0, 0); +INSERT INTO `zz_course_trans_stats` VALUES (2, '2020-01-10', 0, 2, NULL, 1016917385529790464, '小学二年级语文课程', 2, 55, 1); +INSERT INTO `zz_course_trans_stats` VALUES (3, '2020-01-10', 0, 3, NULL, 1016917732260319232, '小学三年级语文课程', 2, 118, 2); +INSERT INTO `zz_course_trans_stats` VALUES (4, '2020-01-10', 0, 4, NULL, 1016917900699373568, '小学四年级语文课程', 0, 40, 1); +INSERT INTO `zz_course_trans_stats` VALUES (5, '2020-01-11', 0, 1, NULL, 1016699195411402752, '小学一年级拼音基础练习', 3, 119, 2); +INSERT INTO `zz_course_trans_stats` VALUES (6, '2020-01-11', 0, 2, NULL, 1016917385529790464, '小学二年级语文课程', 1, 36, 1); +INSERT INTO `zz_course_trans_stats` VALUES (7, '2020-01-11', 0, 3, NULL, 1016917732260319232, '小学三年级语文课程', 1, 147, 2); +INSERT INTO `zz_course_trans_stats` VALUES (8, '2020-01-11', 0, 4, NULL, 1016917900699373568, '小学四年级语文课程', 0, 76, 1); +COMMIT; + +-- ---------------------------- +-- Table structure for zz_grade +-- ---------------------------- +DROP TABLE IF EXISTS `zz_grade`; +CREATE TABLE `zz_grade` ( + `grade_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键Id', + `grade_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '年级名称', + `status` int(11) NOT NULL COMMENT '是否正在使用(0:不是,1:是)', + PRIMARY KEY (`grade_id`) USING BTREE +) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; + +-- ---------------------------- +-- Records of zz_grade +-- ---------------------------- +BEGIN; +INSERT INTO `zz_grade` VALUES (1, '一年级', 1); +INSERT INTO `zz_grade` VALUES (2, '二年级', 1); +INSERT INTO `zz_grade` VALUES (3, '三年级', 1); +INSERT INTO `zz_grade` VALUES (4, '四年级', 1); +INSERT INTO `zz_grade` VALUES (5, '五年级', 1); +INSERT INTO `zz_grade` VALUES (6, '六年级', 1); +INSERT INTO `zz_grade` VALUES (7, '初一', 1); +INSERT INTO `zz_grade` VALUES (8, '初二', 1); +INSERT INTO `zz_grade` VALUES (9, '初三', 1); +INSERT INTO `zz_grade` VALUES (10, '高一', 1); +INSERT INTO `zz_grade` VALUES (11, '高二', 1); +INSERT INTO `zz_grade` VALUES (12, '高三', 1); +COMMIT; + +-- ---------------------------- +-- Table structure for zz_material_edition +-- ---------------------------- +DROP TABLE IF EXISTS `zz_material_edition`; +CREATE TABLE `zz_material_edition` ( + `edition_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键Id', + `edition_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '教材版本名称', + `status` int(11) NOT NULL COMMENT '是否正在使用(0:不是,1:是)', + PRIMARY KEY (`edition_id`) USING BTREE +) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; + +-- ---------------------------- +-- Records of zz_material_edition +-- ---------------------------- +BEGIN; +INSERT INTO `zz_material_edition` VALUES (1, '苏教版', 1); +INSERT INTO `zz_material_edition` VALUES (2, '人教版', 1); +INSERT INTO `zz_material_edition` VALUES (3, '湘教版', 1); +INSERT INTO `zz_material_edition` VALUES (4, '沪教版', 1); +COMMIT; + +-- ---------------------------- +-- Table structure for zz_school_info +-- ---------------------------- +DROP TABLE IF EXISTS `zz_school_info`; +CREATE TABLE `zz_school_info` ( + `school_id` bigint(20) NOT NULL COMMENT '学校Id', + `school_name` varchar(128) COLLATE utf8mb4_bin NOT NULL COMMENT '学校名称', + `province_id` bigint(20) NOT NULL COMMENT '所在省Id', + `city_id` bigint(20) NOT NULL COMMENT '所在城市Id', + PRIMARY KEY (`school_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; + +-- ---------------------------- +-- Records of zz_school_info +-- ---------------------------- +BEGIN; +INSERT INTO `zz_school_info` VALUES (1014065909648330752, '公司总部', 110000000000, 110100000000); +INSERT INTO `zz_school_info` VALUES (1015817732197453824, '北京校区', 110000000000, 110100000000); +INSERT INTO `zz_school_info` VALUES (1015818056597508096, '天津校区', 120000000000, 120100000000); +INSERT INTO `zz_school_info` VALUES (1015818992220901376, '浙江校区', 330000000000, 330100000000); +COMMIT; + +-- ---------------------------- +-- Table structure for zz_student +-- ---------------------------- +DROP TABLE IF EXISTS `zz_student`; +CREATE TABLE `zz_student` ( + `student_id` bigint(20) NOT NULL COMMENT '学生Id', + `login_mobile` varchar(20) COLLATE utf8mb4_bin NOT NULL COMMENT '登录手机', + `student_name` varchar(20) COLLATE utf8mb4_bin NOT NULL COMMENT '学生姓名', + `province_id` bigint(20) NOT NULL COMMENT '所在省份Id', + `city_id` bigint(20) NOT NULL COMMENT '所在城市Id', + `district_id` bigint(20) NOT NULL COMMENT '区县Id', + `gender` int(11) NOT NULL COMMENT '学生性别 (0: 女生 1: 男生)', + `birthday` date NOT NULL COMMENT '生日', + `experience_level` tinyint(4) NOT NULL COMMENT '经验等级 (0: 初级 1: 中级 2: 高级 3: 资深)', + `total_coin` int(11) NOT NULL DEFAULT '0' COMMENT '总共充值学币数量', + `left_coin` int(11) NOT NULL DEFAULT '0' COMMENT '可用学币数量', + `grade_id` int(11) NOT NULL COMMENT '年级Id', + `school_id` bigint(20) NOT NULL COMMENT '校区Id', + `register_time` datetime NOT NULL COMMENT '注册时间', + `status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '学生状态 (0: 正常 1: 锁定 2: 注销)', + PRIMARY KEY (`student_id`) USING BTREE, + KEY `idx_login_mobile` (`login_mobile`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; + +-- ---------------------------- +-- Records of zz_student +-- ---------------------------- +BEGIN; +INSERT INTO `zz_student` VALUES (1015842628948463616, '13834561230', '张三', 110000000000, 110100000000, 110105000000, 1, '2010-08-19', 1, 3412, 1077, 4, 1015817732197453824, CURDATE(), 0); +INSERT INTO `zz_student` VALUES (1015852480873631744, '13945651267', '李军', 110000000000, 110100000000, 110107000000, 1, '2011-11-18', 1, 3178, 3024, 3, 1015817732197453824, CURDATE(), 0); +INSERT INTO `zz_student` VALUES (1015852853839532032, '13709481736', '王石', 110000000000, 110100000000, 110108000000, 1, '2015-01-15', 0, 3187, 2199, 1, 1015817732197453824, CURDATE(), 0); +INSERT INTO `zz_student` VALUES (1018000939508568064, '13700023451', '天津二哥', 120000000000, 120100000000, 120103000000, 1, '2010-06-10', 0, 1287, 634, 3, 1015818056597508096, CURDATE(), 0); +INSERT INTO `zz_student` VALUES (1018001219050541056, '13903122987', '南开学霸', 120000000000, 120100000000, 120104000000, 0, '2009-07-17', 2, 8721, 7023, 4, 1015818056597508096, CURDATE(), 0); +INSERT INTO `zz_student` VALUES (1023072888777609216, '13920134567', 'aaa', 120000000000, 120100000000, 120103000000, 1, '2020-01-08', 1, 0, 0, 1, 1015818992220901376, CURDATE(), 0); +COMMIT; + +-- ---------------------------- +-- Table structure for zz_student_action_stats +-- ---------------------------- +DROP TABLE IF EXISTS `zz_student_action_stats`; +CREATE TABLE `zz_student_action_stats` ( + `stats_id` bigint(20) NOT NULL COMMENT '主键Id', + `stats_date` date NOT NULL COMMENT '统计日期', + `stats_month` date DEFAULT NULL COMMENT '统计小时', + `grade_id` int(11) NOT NULL COMMENT '年级Id', + `province_id` bigint(20) NOT NULL COMMENT '学生所在省Id', + `city_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '学生所在城市Id', + `buy_course_amount` int(11) NOT NULL DEFAULT '0' COMMENT '购课学币数量', + `buy_course_count` int(11) NOT NULL DEFAULT '0' COMMENT '购买课程次数', + `buy_video_amount` int(11) NOT NULL DEFAULT '0' COMMENT '购买视频学币数量', + `buy_video_count` int(11) NOT NULL DEFAULT '0' COMMENT '购买视频次数', + `buy_paper_amount` int(11) NOT NULL DEFAULT '0' COMMENT '购买作业学币数量', + `buy_paper_count` int(11) NOT NULL DEFAULT '0' COMMENT '购买作业次数', + `buy_flower_amount` int(11) NOT NULL DEFAULT '0' COMMENT '购买献花数量', + `buy_flower_count` int(11) NOT NULL DEFAULT '0' COMMENT '购买献花次数', + `recharge_coin_amount` int(11) NOT NULL DEFAULT '0' COMMENT '充值学币数量', + `recharge_coin_count` int(11) NOT NULL DEFAULT '0' COMMENT '充值学币次数', + `do_course_count` int(11) NOT NULL COMMENT '线下课程上课次数', + `watch_video_count` int(11) NOT NULL DEFAULT '0' COMMENT '观看视频次数', + `watch_video_total_second` int(11) NOT NULL COMMENT '购买献花消费学币数量', + `do_exercise_count` int(11) NOT NULL DEFAULT '0' COMMENT '做题数量', + `do_exercise_correct_count` int(11) NOT NULL DEFAULT '0' COMMENT '做题正确的数量', + PRIMARY KEY (`stats_id`) USING BTREE, + UNIQUE KEY `uk_stats_date_grade_id_region_id` (`stats_date`,`grade_id`,`province_id`,`city_id`) USING BTREE, + KEY `idx_province_id` (`province_id`) USING BTREE, + KEY `idx_city_id` (`city_id`) USING BTREE, + KEY `idx_grade_id` (`grade_id`) USING BTREE, + KEY `idx_stats_month` (`stats_month`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; + +-- ---------------------------- +-- Records of zz_student_action_stats +-- ---------------------------- +BEGIN; +INSERT INTO `zz_student_action_stats` VALUES (1293010719117148160, '2020-01-10', NULL, 1, 110000000000, 110100000000, 16, 5, 0, 0, 14, 2, 123, 3, 2694, 5, 3, 3, 707, 3, 0); +INSERT INTO `zz_student_action_stats` VALUES (1293010719121342468, '2020-01-10', NULL, 2, 110000000000, 110100000000, 8, 3, 0, 0, 6, 1, 133, 2, 1717, 3, 3, 0, 0, 4, 0); +INSERT INTO `zz_student_action_stats` VALUES (1293010719121342475, '2020-01-10', NULL, 4, 110000000000, 110100000000, 0, 0, 0, 0, 16, 2, 55, 2, 1881, 4, 2, 6, 2987, 2, 0); +INSERT INTO `zz_student_action_stats` VALUES (1293010719121342482, '2020-01-10', NULL, 2, 120000000000, 120100000000, 12, 4, 0, 0, 0, 0, 134, 2, 292, 2, 3, 1, 434, 1, 1); +INSERT INTO `zz_student_action_stats` VALUES (1293010719121342489, '2020-01-10', NULL, 3, 120000000000, 120100000000, 5, 2, 0, 0, 18, 3, 79, 2, 1343, 2, 2, 4, 2266, 5, 5); +INSERT INTO `zz_student_action_stats` VALUES (1293010719121342497, '2020-01-10', NULL, 4, 120000000000, 120100000000, 10, 3, 0, 0, 33, 4, 212, 4, 766, 2, 3, 2, 1480, 4, 4); +INSERT INTO `zz_student_action_stats` VALUES (1293010719297503232, '2020-01-11', NULL, 1, 110000000000, 110100000000, 12, 3, 0, 0, 13, 2, 216, 3, 1119, 2, 3, 2, 511, 2, 2); +INSERT INTO `zz_student_action_stats` VALUES (1293010719297503240, '2020-01-11', NULL, 2, 110000000000, 110100000000, 7, 4, 0, 0, 20, 3, 142, 2, 509, 2, 3, 3, 1699, 3, 3); +INSERT INTO `zz_student_action_stats` VALUES (1293010719297503248, '2020-01-11', NULL, 3, 110000000000, 110100000000, 2, 1, 0, 0, 11, 2, 158, 3, 1571, 2, 3, 0, 0, 3, 3); +INSERT INTO `zz_student_action_stats` VALUES (1293010719297503255, '2020-01-11', NULL, 2, 120000000000, 120100000000, 0, 0, 0, 0, 15, 2, 0, 0, 1741, 3, 2, 3, 1280, 3, 3); +INSERT INTO `zz_student_action_stats` VALUES (1293010719301697539, '2020-01-11', NULL, 3, 120000000000, 120100000000, 3, 2, 0, 0, 0, 0, 176, 3, 1702, 2, 2, 2, 1306, 2, 2); +INSERT INTO `zz_student_action_stats` VALUES (1293010719301697545, '2020-01-11', NULL, 4, 120000000000, 120100000000, 7, 2, 0, 0, 9, 2, 122, 2, 1257, 3, 0, 3, 1210, 2, 2); +COMMIT; + +-- ---------------------------- +-- Table structure for zz_student_action_trans +-- ---------------------------- +DROP TABLE IF EXISTS `zz_student_action_trans`; +CREATE TABLE `zz_student_action_trans` ( + `trans_id` bigint(20) NOT NULL COMMENT '主键Id', + `student_id` bigint(20) NOT NULL COMMENT '学生Id', + `student_name` varchar(64) COLLATE utf8mb4_bin NOT NULL COMMENT '学生名称', + `school_id` bigint(20) NOT NULL COMMENT '学生校区', + `grade_id` int(11) NOT NULL COMMENT '年级Id', + `action_type` tinyint(4) NOT NULL COMMENT '行为类型(0: 充值 1: 购课 2: 上课签到 3: 上课签退 4: 看视频课 5: 做作业 6: 刷题 7: 献花)', + `device_type` tinyint(4) NOT NULL COMMENT '设备类型(0: iOS 1: Android 2: PC)', + `watch_video_seconds` int(11) DEFAULT NULL COMMENT '看视频秒数', + `flower_count` int(11) DEFAULT NULL COMMENT '购买献花数量', + `paper_count` int(11) DEFAULT NULL COMMENT '购买作业数量', + `video_count` int(11) DEFAULT NULL COMMENT '购买视频数量', + `course_count` int(11) DEFAULT NULL COMMENT '购买课程数量', + `coin_count` int(11) DEFAULT NULL COMMENT '充值学币数量', + `exercise_correct_flag` tinyint(4) DEFAULT NULL COMMENT '做题是否正确标记', + `create_time` datetime NOT NULL COMMENT '发生时间', + PRIMARY KEY (`trans_id`) USING BTREE, + KEY `idx_student_id` (`student_id`) USING BTREE, + KEY `idx_grade_id` (`grade_id`) USING BTREE, + KEY `idx_action_type` (`action_type`) USING BTREE, + KEY `idx_create_time` (`create_time`) USING BTREE, + KEY `idx_device_type` (`action_type`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; + +-- ---------------------------- +-- Records of zz_student_action_trans +-- ---------------------------- +BEGIN; +INSERT INTO `zz_student_action_trans` VALUES (1018423001834328064, 1015841864515588096, '张大', 1015817732197453824, 1, 0, 0, NULL, NULL, NULL, NULL, NULL, 617, NULL, '2020-01-10 11:13:23'); +INSERT INTO `zz_student_action_trans` VALUES (1018803416562667520, 1015841864515588096, '张大', 1015817732197453824, 1, 0, 0, NULL, NULL, NULL, NULL, NULL, 468, NULL, '2020-01-10 11:13:25'); +INSERT INTO `zz_student_action_trans` VALUES (1018803445553696768, 1015841864515588096, '张大', 1015817732197453824, 1, 0, 1, NULL, NULL, NULL, NULL, NULL, 548, NULL, '2020-01-10 11:13:30'); +INSERT INTO `zz_student_action_trans` VALUES (1018803590760501248, 1015841864515588096, '张大', 1015817732197453824, 1, 0, 2, NULL, NULL, NULL, NULL, NULL, 250, NULL, '2020-01-10 11:13:35'); +INSERT INTO `zz_student_action_trans` VALUES (1018803838299934720, 1015841864515588096, '张大', 1015817732197453824, 1, 0, 2, NULL, NULL, NULL, NULL, NULL, 811, NULL, '2020-01-10 11:13:40'); +INSERT INTO `zz_student_action_trans` VALUES (1018803855614021632, 1015841864515588096, '张大', 1015817732197453824, 1, 1, 2, NULL, NULL, NULL, NULL, 5, NULL, NULL, '2020-01-10 11:13:45'); +INSERT INTO `zz_student_action_trans` VALUES (1018803873183961088, 1015841864515588096, '张大', 1015817732197453824, 1, 1, 1, NULL, NULL, NULL, NULL, 4, NULL, NULL, '2020-01-10 11:13:50'); +INSERT INTO `zz_student_action_trans` VALUES (1018803890552573952, 1015841864515588096, '张大', 1015817732197453824, 1, 1, 0, NULL, NULL, NULL, NULL, 4, NULL, NULL, '2020-01-10 11:13:55'); +INSERT INTO `zz_student_action_trans` VALUES (1018803897053745152, 1015841864515588096, '张大', 1015817732197453824, 1, 1, 0, NULL, NULL, NULL, NULL, 2, NULL, NULL, '2020-01-10 11:14:00'); +INSERT INTO `zz_student_action_trans` VALUES (1018803910555209728, 1015841864515588096, '张大', 1015817732197453824, 1, 1, 0, NULL, NULL, NULL, NULL, 1, NULL, NULL, '2020-01-10 11:14:05'); +INSERT INTO `zz_student_action_trans` VALUES (1018803926451621888, 1015841864515588096, '张大', 1015817732197453824, 1, 2, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:14:10'); +INSERT INTO `zz_student_action_trans` VALUES (1018803940418654208, 1015841864515588096, '张大', 1015817732197453824, 1, 2, 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:14:15'); +INSERT INTO `zz_student_action_trans` VALUES (1018803955727863808, 1015841864515588096, '张大', 1015817732197453824, 1, 2, 2, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:14:20'); +INSERT INTO `zz_student_action_trans` VALUES (1018803973427826688, 1015841864515588096, '张大', 1015817732197453824, 1, 3, 2, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:14:25'); +INSERT INTO `zz_student_action_trans` VALUES (1018803982235865088, 1015841864515588096, '张大', 1015817732197453824, 1, 3, 2, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:14:30'); +INSERT INTO `zz_student_action_trans` VALUES (1018803988154028032, 1015841864515588096, '张大', 1015817732197453824, 1, 3, 2, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:14:35'); +INSERT INTO `zz_student_action_trans` VALUES (1018804009414955008, 1015841864515588096, '张大', 1015817732197453824, 1, 3, 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:14:40'); +INSERT INTO `zz_student_action_trans` VALUES (1018804025521082368, 1015841864515588096, '张大', 1015817732197453824, 1, 4, 1, 342, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:14:45'); +INSERT INTO `zz_student_action_trans` VALUES (1018804040956121088, 1015841864515588096, '张大', 1015817732197453824, 1, 4, 0, 324, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:14:50'); +INSERT INTO `zz_student_action_trans` VALUES (1018804057104191488, 1015841864515588096, '张大', 1015817732197453824, 1, 4, 2, 41, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:14:55'); +INSERT INTO `zz_student_action_trans` VALUES (1018804073457782784, 1015841864515588096, '张大', 1015817732197453824, 1, 5, 2, NULL, NULL, NULL, NULL, NULL, NULL, 0, '2020-01-10 11:15:00'); +INSERT INTO `zz_student_action_trans` VALUES (1018804090696372224, 1015841864515588096, '张大', 1015817732197453824, 1, 5, 1, NULL, NULL, NULL, NULL, NULL, NULL, 0, '2020-01-10 11:15:05'); +INSERT INTO `zz_student_action_trans` VALUES (1018804111659503616, 1015841864515588096, '张大', 1015817732197453824, 1, 5, 0, NULL, NULL, NULL, NULL, NULL, NULL, 0, '2020-01-10 11:15:10'); +INSERT INTO `zz_student_action_trans` VALUES (1018804134585569280, 1015841864515588096, '张大', 1015817732197453824, 1, 9, 0, NULL, 15, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:15:15'); +INSERT INTO `zz_student_action_trans` VALUES (1018804139606151168, 1015841864515588096, '张大', 1015817732197453824, 1, 9, 0, NULL, 60, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:15:20'); +INSERT INTO `zz_student_action_trans` VALUES (1018804156295286784, 1015841864515588096, '张大', 1015817732197453824, 1, 9, 1, NULL, 48, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:15:25'); +INSERT INTO `zz_student_action_trans` VALUES (1018804244874792960, 1015841864515588096, '张大', 1015817732197453824, 1, 10, 1, NULL, NULL, 4, NULL, NULL, NULL, NULL, '2020-01-10 11:15:30'); +INSERT INTO `zz_student_action_trans` VALUES (1018804264130842624, 1015841864515588096, '张大', 1015817732197453824, 1, 10, 0, NULL, NULL, 10, NULL, NULL, NULL, NULL, '2020-01-10 11:15:35'); +INSERT INTO `zz_student_action_trans` VALUES (1018806531059879936, 1015841864515588096, '张大', 1015817732197453824, 2, 0, 0, NULL, NULL, NULL, NULL, NULL, 545, NULL, '2020-01-10 11:15:40'); +INSERT INTO `zz_student_action_trans` VALUES (1018806537225506816, 1015841864515588096, '张大', 1015817732197453824, 2, 0, 0, NULL, NULL, NULL, NULL, NULL, 743, NULL, '2020-01-10 11:15:45'); +INSERT INTO `zz_student_action_trans` VALUES (1018806554631868416, 1015841864515588096, '张大', 1015817732197453824, 2, 0, 1, NULL, NULL, NULL, NULL, NULL, 429, NULL, '2020-01-10 11:15:50'); +INSERT INTO `zz_student_action_trans` VALUES (1018806571031597056, 1015841864515588096, '张大', 1015817732197453824, 2, 1, 1, NULL, NULL, NULL, NULL, 3, NULL, NULL, '2020-01-10 11:15:55'); +INSERT INTO `zz_student_action_trans` VALUES (1018806573841780736, 1015841864515588096, '张大', 1015817732197453824, 2, 1, 1, NULL, NULL, NULL, NULL, 2, NULL, NULL, '2020-01-10 11:16:00'); +INSERT INTO `zz_student_action_trans` VALUES (1018806589612363776, 1015841864515588096, '张大', 1015817732197453824, 2, 1, 2, NULL, NULL, NULL, NULL, 3, NULL, NULL, '2020-01-10 11:16:05'); +INSERT INTO `zz_student_action_trans` VALUES (1018806602698592256, 1015841864515588096, '张大', 1015817732197453824, 2, 2, 2, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:16:10'); +INSERT INTO `zz_student_action_trans` VALUES (1018806617378656256, 1015841864515588096, '张大', 1015817732197453824, 2, 2, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:16:15'); +INSERT INTO `zz_student_action_trans` VALUES (1018806622076276736, 1015841864515588096, '张大', 1015817732197453824, 2, 2, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:16:20'); +INSERT INTO `zz_student_action_trans` VALUES (1018806639230980096, 1015841864515588096, '张大', 1015817732197453824, 2, 3, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:16:25'); +INSERT INTO `zz_student_action_trans` VALUES (1018806643047796736, 1015841864515588096, '张大', 1015817732197453824, 2, 3, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:16:30'); +INSERT INTO `zz_student_action_trans` VALUES (1018806664732348416, 1015841864515588096, '张大', 1015817732197453824, 2, 5, 0, NULL, NULL, NULL, NULL, NULL, NULL, 0, '2020-01-10 11:16:35'); +INSERT INTO `zz_student_action_trans` VALUES (1018806668976984064, 1015841864515588096, '张大', 1015817732197453824, 2, 5, 0, NULL, NULL, NULL, NULL, NULL, NULL, 0, '2020-01-10 11:16:40'); +INSERT INTO `zz_student_action_trans` VALUES (1018806682558140416, 1015841864515588096, '张大', 1015817732197453824, 2, 5, 1, NULL, NULL, NULL, NULL, NULL, NULL, 0, '2020-01-10 11:16:45'); +INSERT INTO `zz_student_action_trans` VALUES (1018806691030634496, 1015841864515588096, '张大', 1015817732197453824, 2, 5, 1, NULL, NULL, NULL, NULL, NULL, NULL, 0, '2020-01-10 11:16:50'); +INSERT INTO `zz_student_action_trans` VALUES (1018806709733036032, 1015841864515588096, '张大', 1015817732197453824, 2, 9, 1, NULL, 49, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:16:55'); +INSERT INTO `zz_student_action_trans` VALUES (1018806725126131712, 1015841864515588096, '张大', 1015817732197453824, 2, 9, 0, NULL, 84, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:17:00'); +INSERT INTO `zz_student_action_trans` VALUES (1018806755786493952, 1015841864515588096, '张大', 1015817732197453824, 2, 10, 0, NULL, NULL, 6, NULL, NULL, NULL, NULL, '2020-01-10 11:17:05'); +INSERT INTO `zz_student_action_trans` VALUES (1018806774576975872, 1015841864515588096, '张大', 1015817732197453824, 4, 10, 0, NULL, NULL, 8, NULL, NULL, NULL, NULL, '2020-01-10 11:17:10'); +INSERT INTO `zz_student_action_trans` VALUES (1018806780532887552, 1015841864515588096, '张大', 1015817732197453824, 4, 10, 0, NULL, NULL, 8, NULL, NULL, NULL, NULL, '2020-01-10 11:17:15'); +INSERT INTO `zz_student_action_trans` VALUES (1018806796135698432, 1015841864515588096, '张大', 1015817732197453824, 4, 9, 0, NULL, 33, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:17:20'); +INSERT INTO `zz_student_action_trans` VALUES (1018806799491141632, 1015841864515588096, '张大', 1015817732197453824, 4, 9, 0, NULL, 22, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:17:25'); +INSERT INTO `zz_student_action_trans` VALUES (1018806813844049920, 1015841864515588096, '张大', 1015817732197453824, 4, 5, 0, NULL, NULL, NULL, NULL, NULL, NULL, 0, '2020-01-10 11:17:30'); +INSERT INTO `zz_student_action_trans` VALUES (1018806817694420992, 1015841864515588096, '张大', 1015817732197453824, 4, 5, 0, NULL, NULL, NULL, NULL, NULL, NULL, 0, '2020-01-10 11:17:35'); +INSERT INTO `zz_student_action_trans` VALUES (1018806836275187712, 1015841864515588096, '张大', 1015817732197453824, 4, 4, 0, 627, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:17:40'); +INSERT INTO `zz_student_action_trans` VALUES (1018806840423354368, 1015841864515588096, '张大', 1015817732197453824, 4, 4, 0, 463, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:17:45'); +INSERT INTO `zz_student_action_trans` VALUES (1018806858966372352, 1015841864515588096, '张大', 1015817732197453824, 4, 4, 1, 104, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:17:50'); +INSERT INTO `zz_student_action_trans` VALUES (1018806862112100352, 1015841864515588096, '张大', 1015817732197453824, 4, 4, 1, 329, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:17:55'); +INSERT INTO `zz_student_action_trans` VALUES (1018806877714911232, 1015841864515588096, '张大', 1015817732197453824, 4, 4, 2, 601, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:18:00'); +INSERT INTO `zz_student_action_trans` VALUES (1018806899365908480, 1015841864515588096, '张大', 1015817732197453824, 4, 4, 2, 863, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:18:05'); +INSERT INTO `zz_student_action_trans` VALUES (1018806913865617408, 1015841864515588096, '张大', 1015817732197453824, 4, 3, 2, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:18:10'); +INSERT INTO `zz_student_action_trans` VALUES (1018806916679995392, 1015841864515588096, '张大', 1015817732197453824, 4, 3, 2, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:18:15'); +INSERT INTO `zz_student_action_trans` VALUES (1018806932240863232, 1015841864515588096, '张大', 1015817732197453824, 4, 2, 2, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:18:20'); +INSERT INTO `zz_student_action_trans` VALUES (1018806950439948288, 1015841864515588096, '张大', 1015817732197453824, 4, 2, 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:18:25'); +INSERT INTO `zz_student_action_trans` VALUES (1018806964746719232, 1015841864515588096, '张大', 1015817732197453824, 4, 0, 1, NULL, NULL, NULL, NULL, NULL, 618, NULL, '2020-01-10 11:18:30'); +INSERT INTO `zz_student_action_trans` VALUES (1018806967473016832, 1015841864515588096, '张大', 1015817732197453824, 4, 0, 1, NULL, NULL, NULL, NULL, NULL, 25, NULL, '2020-01-10 11:18:35'); +INSERT INTO `zz_student_action_trans` VALUES (1018806982023057408, 1015841864515588096, '张大', 1015817732197453824, 4, 0, 0, NULL, NULL, NULL, NULL, NULL, 523, NULL, '2020-01-10 11:18:40'); +INSERT INTO `zz_student_action_trans` VALUES (1018806984879378432, 1015841864515588096, '张大', 1015817732197453824, 4, 0, 0, NULL, NULL, NULL, NULL, NULL, 715, NULL, '2020-01-10 11:18:45'); +INSERT INTO `zz_student_action_trans` VALUES (1018807041246629888, 1015842628948463616, '张三', 1015818056597508096, 2, 0, 0, NULL, NULL, NULL, NULL, NULL, 269, NULL, '2020-01-10 11:18:50'); +INSERT INTO `zz_student_action_trans` VALUES (1018807044560130048, 1015842628948463616, '张三', 1015818056597508096, 2, 0, 0, NULL, NULL, NULL, NULL, NULL, 23, NULL, '2020-01-10 11:18:55'); +INSERT INTO `zz_student_action_trans` VALUES (1018807060251021312, 1015842628948463616, '张三', 1015818056597508096, 2, 1, 0, NULL, NULL, NULL, NULL, 2, NULL, NULL, '2020-01-10 11:19:00'); +INSERT INTO `zz_student_action_trans` VALUES (1018807064650846208, 1015842628948463616, '张三', 1015818056597508096, 2, 1, 0, NULL, NULL, NULL, NULL, 4, NULL, NULL, '2020-01-10 11:19:05'); +INSERT INTO `zz_student_action_trans` VALUES (1018807069302329344, 1015842628948463616, '张三', 1015818056597508096, 2, 1, 0, NULL, NULL, NULL, NULL, 5, NULL, NULL, '2020-01-10 11:19:10'); +INSERT INTO `zz_student_action_trans` VALUES (1018807073211420672, 1015842628948463616, '张三', 1015818056597508096, 2, 1, 0, NULL, NULL, NULL, NULL, 1, NULL, NULL, '2020-01-10 11:19:15'); +INSERT INTO `zz_student_action_trans` VALUES (1018807086876463104, 1015842628948463616, '张三', 1015818056597508096, 2, 2, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:19:20'); +INSERT INTO `zz_student_action_trans` VALUES (1018807102311501824, 1015842628948463616, '张三', 1015818056597508096, 2, 2, 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:19:25'); +INSERT INTO `zz_student_action_trans` VALUES (1018807118379880448, 1015842628948463616, '张三', 1015818056597508096, 2, 2, 2, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:19:30'); +INSERT INTO `zz_student_action_trans` VALUES (1018807134397927424, 1015842628948463616, '张三', 1015818056597508096, 2, 3, 2, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:19:35'); +INSERT INTO `zz_student_action_trans` VALUES (1018807148918607872, 1015842628948463616, '张三', 1015818056597508096, 2, 3, 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:19:40'); +INSERT INTO `zz_student_action_trans` VALUES (1018807151863009280, 1015842628948463616, '张三', 1015818056597508096, 2, 3, 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:19:45'); +INSERT INTO `zz_student_action_trans` VALUES (1018807176013811712, 1015842628948463616, '张三', 1015818056597508096, 2, 4, 1, 434, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:19:50'); +INSERT INTO `zz_student_action_trans` VALUES (1018807190026981376, 1015842628948463616, '张三', 1015818056597508096, 2, 5, 1, NULL, NULL, NULL, NULL, NULL, NULL, 1, '2020-01-10 11:19:55'); +INSERT INTO `zz_student_action_trans` VALUES (1018807205868867584, 1015842628948463616, '张三', 1015818056597508096, 2, 9, 1, NULL, 100, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:20:00'); +INSERT INTO `zz_student_action_trans` VALUES (1018807221144522752, 1015842628948463616, '张三', 1015818056597508096, 2, 9, 0, NULL, 34, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:20:05'); +INSERT INTO `zz_student_action_trans` VALUES (1018807245962219520, 1015842628948463616, '张三', 1015818056597508096, 3, 9, 0, NULL, 57, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:20:10'); +INSERT INTO `zz_student_action_trans` VALUES (1018807249124724736, 1015842628948463616, '张三', 1015818056597508096, 3, 9, 0, NULL, 22, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:20:15'); +INSERT INTO `zz_student_action_trans` VALUES (1018807263423107072, 1015842628948463616, '张三', 1015818056597508096, 3, 5, 0, NULL, NULL, NULL, NULL, NULL, NULL, 1, '2020-01-10 11:20:20'); +INSERT INTO `zz_student_action_trans` VALUES (1018807267189592064, 1015842628948463616, '张三', 1015818056597508096, 3, 5, 0, NULL, NULL, NULL, NULL, NULL, NULL, 1, '2020-01-10 11:20:25'); +INSERT INTO `zz_student_action_trans` VALUES (1018807284394627072, 1015842628948463616, '张三', 1015818056597508096, 3, 10, 0, NULL, NULL, 6, NULL, NULL, NULL, NULL, '2020-01-10 11:20:30'); +INSERT INTO `zz_student_action_trans` VALUES (1018807287661989888, 1015842628948463616, '张三', 1015818056597508096, 3, 10, 0, NULL, NULL, 4, NULL, NULL, NULL, NULL, '2020-01-10 11:20:35'); +INSERT INTO `zz_student_action_trans` VALUES (1018807304527286272, 1015842628948463616, '张三', 1015818056597508096, 3, 10, 2, NULL, NULL, 8, NULL, NULL, NULL, NULL, '2020-01-10 11:20:40'); +INSERT INTO `zz_student_action_trans` VALUES (1018807321082204160, 1015842628948463616, '张三', 1015818056597508096, 3, 5, 2, NULL, NULL, NULL, NULL, NULL, NULL, 1, '2020-01-10 11:20:45'); +INSERT INTO `zz_student_action_trans` VALUES (1018807323640729600, 1015842628948463616, '张三', 1015818056597508096, 3, 5, 2, NULL, NULL, NULL, NULL, NULL, NULL, 1, '2020-01-10 11:20:50'); +INSERT INTO `zz_student_action_trans` VALUES (1018807341474910208, 1015842628948463616, '张三', 1015818056597508096, 3, 5, 1, NULL, NULL, NULL, NULL, NULL, NULL, 1, '2020-01-10 11:20:55'); +INSERT INTO `zz_student_action_trans` VALUES (1018807358168240128, 1015842628948463616, '张三', 1015818056597508096, 3, 4, 1, 109, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:21:00'); +INSERT INTO `zz_student_action_trans` VALUES (1018807377902440448, 1015842628948463616, '张三', 1015818056597508096, 3, 4, 0, 923, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:21:05'); +INSERT INTO `zz_student_action_trans` VALUES (1018807396172828672, 1015842628948463616, '张三', 1015818056597508096, 3, 4, 2, 598, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:21:10'); +INSERT INTO `zz_student_action_trans` VALUES (1018807399939313664, 1015842628948463616, '张三', 1015818056597508096, 3, 4, 2, 636, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:21:15'); +INSERT INTO `zz_student_action_trans` VALUES (1018807412731940864, 1015842628948463616, '张三', 1015818056597508096, 3, 3, 2, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:21:20'); +INSERT INTO `zz_student_action_trans` VALUES (1018807416288710656, 1015842628948463616, '张三', 1015818056597508096, 3, 3, 2, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:21:25'); +INSERT INTO `zz_student_action_trans` VALUES (1018807429895032832, 1015842628948463616, '张三', 1015818056597508096, 3, 3, 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:21:30'); +INSERT INTO `zz_student_action_trans` VALUES (1018807443853676544, 1015842628948463616, '张三', 1015818056597508096, 3, 2, 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:21:35'); +INSERT INTO `zz_student_action_trans` VALUES (1018807458953170944, 1015842628948463616, '张三', 1015818056597508096, 3, 2, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:21:40'); +INSERT INTO `zz_student_action_trans` VALUES (1018807471968096256, 1015842628948463616, '张三', 1015818056597508096, 3, 1, 0, NULL, NULL, NULL, NULL, 3, NULL, NULL, '2020-01-10 11:21:45'); +INSERT INTO `zz_student_action_trans` VALUES (1018807475562614784, 1015842628948463616, '张三', 1015818056597508096, 3, 1, 0, NULL, NULL, NULL, NULL, 2, NULL, NULL, '2020-01-10 11:21:50'); +INSERT INTO `zz_student_action_trans` VALUES (1018807497494630400, 1015842628948463616, '张三', 1015818056597508096, 3, 0, 1, NULL, NULL, NULL, NULL, NULL, 546, NULL, '2020-01-10 11:21:55'); +INSERT INTO `zz_student_action_trans` VALUES (1018807510580858880, 1015842628948463616, '张三', 1015818056597508096, 3, 0, 2, NULL, NULL, NULL, NULL, NULL, 797, NULL, '2020-01-10 11:22:00'); +INSERT INTO `zz_student_action_trans` VALUES (1018807530558328832, 1015842628948463616, '张三', 1015818056597508096, 4, 0, 2, NULL, NULL, NULL, NULL, NULL, 668, NULL, '2020-01-10 11:22:05'); +INSERT INTO `zz_student_action_trans` VALUES (1018807544810573824, 1015842628948463616, '张三', 1015818056597508096, 4, 0, 2, NULL, NULL, NULL, NULL, NULL, 98, NULL, '2020-01-10 11:22:10'); +INSERT INTO `zz_student_action_trans` VALUES (1018807559650021376, 1015842628948463616, '张三', 1015818056597508096, 4, 1, 2, NULL, NULL, NULL, NULL, 4, NULL, NULL, '2020-01-10 11:22:15'); +INSERT INTO `zz_student_action_trans` VALUES (1018807565647876096, 1015842628948463616, '张三', 1015818056597508096, 4, 1, 2, NULL, NULL, NULL, NULL, 2, NULL, NULL, '2020-01-10 11:22:20'); +INSERT INTO `zz_student_action_trans` VALUES (1018807581548482560, 1015842628948463616, '张三', 1015818056597508096, 4, 1, 1, NULL, NULL, NULL, NULL, 4, NULL, NULL, '2020-01-10 11:22:25'); +INSERT INTO `zz_student_action_trans` VALUES (1018807596224352256, 1015842628948463616, '张三', 1015818056597508096, 4, 2, 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:22:30'); +INSERT INTO `zz_student_action_trans` VALUES (1018807598866763776, 1015842628948463616, '张三', 1015818056597508096, 4, 2, 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:22:35'); +INSERT INTO `zz_student_action_trans` VALUES (1018807614889005056, 1015842628948463616, '张三', 1015818056597508096, 4, 2, 2, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:22:40'); +INSERT INTO `zz_student_action_trans` VALUES (1018807628856037376, 1015842628948463616, '张三', 1015818056597508096, 4, 3, 2, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:22:45'); +INSERT INTO `zz_student_action_trans` VALUES (1018807632249229312, 1015842628948463616, '张三', 1015818056597508096, 4, 3, 2, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:22:50'); +INSERT INTO `zz_student_action_trans` VALUES (1018807646891544576, 1015842628948463616, '张三', 1015818056597508096, 4, 3, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:22:55'); +INSERT INTO `zz_student_action_trans` VALUES (1018807659432513536, 1015842628948463616, '张三', 1015818056597508096, 4, 4, 0, 931, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:23:00'); +INSERT INTO `zz_student_action_trans` VALUES (1018807675786104832, 1015842628948463616, '张三', 1015818056597508096, 4, 4, 1, 549, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:23:05'); +INSERT INTO `zz_student_action_trans` VALUES (1018807693569953792, 1015842628948463616, '张三', 1015818056597508096, 4, 5, 1, NULL, NULL, NULL, NULL, NULL, NULL, 1, '2020-01-10 11:23:10'); +INSERT INTO `zz_student_action_trans` VALUES (1018807696216559616, 1015842628948463616, '张三', 1015818056597508096, 4, 5, 1, NULL, NULL, NULL, NULL, NULL, NULL, 1, '2020-01-10 11:23:15'); +INSERT INTO `zz_student_action_trans` VALUES (1018807710099705856, 1015842628948463616, '张三', 1015818056597508096, 4, 5, 2, NULL, NULL, NULL, NULL, NULL, NULL, 1, '2020-01-10 11:23:20'); +INSERT INTO `zz_student_action_trans` VALUES (1018807726746898432, 1015842628948463616, '张三', 1015818056597508096, 4, 5, 0, NULL, NULL, NULL, NULL, NULL, NULL, 1, '2020-01-10 11:23:25'); +INSERT INTO `zz_student_action_trans` VALUES (1018807743188570112, 1015842628948463616, '张三', 1015818056597508096, 4, 9, 0, NULL, 89, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:23:30'); +INSERT INTO `zz_student_action_trans` VALUES (1018807747508703232, 1015842628948463616, '张三', 1015818056597508096, 4, 9, 0, NULL, 45, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:23:35'); +INSERT INTO `zz_student_action_trans` VALUES (1018807762734026752, 1015842628948463616, '张三', 1015818056597508096, 4, 9, 1, NULL, 26, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:23:40'); +INSERT INTO `zz_student_action_trans` VALUES (1018807779007926272, 1015842628948463616, '张三', 1015818056597508096, 4, 9, 2, NULL, 52, NULL, NULL, NULL, NULL, NULL, '2020-01-10 11:23:45'); +INSERT INTO `zz_student_action_trans` VALUES (1018807795281825792, 1015842628948463616, '张三', 1015818056597508096, 4, 10, 2, NULL, NULL, 9, NULL, NULL, NULL, NULL, '2020-01-10 11:23:50'); +INSERT INTO `zz_student_action_trans` VALUES (1018807814282022912, 1015842628948463616, '张三', 1015818056597508096, 4, 10, 1, NULL, NULL, 9, NULL, NULL, NULL, NULL, '2020-01-10 11:23:55'); +INSERT INTO `zz_student_action_trans` VALUES (1018807818304360448, 1015842628948463616, '张三', 1015818056597508096, 4, 10, 1, NULL, NULL, 10, NULL, NULL, NULL, NULL, '2020-01-10 11:24:00'); +INSERT INTO `zz_student_action_trans` VALUES (1018807839112302592, 1015842628948463616, '张三', 1015818056597508096, 4, 10, 0, NULL, NULL, 5, NULL, NULL, NULL, NULL, '2020-01-10 11:24:05'); +INSERT INTO `zz_student_action_trans` VALUES (1018807937338707968, 1015852480873631744, '李军', 1015817732197453824, 1, 0, 0, NULL, NULL, NULL, NULL, NULL, 868, NULL, '2020-01-11 11:24:10'); +INSERT INTO `zz_student_action_trans` VALUES (1018807958184398848, 1015852480873631744, '李军', 1015817732197453824, 1, 0, 1, NULL, NULL, NULL, NULL, NULL, 251, NULL, '2020-01-11 11:24:15'); +INSERT INTO `zz_student_action_trans` VALUES (1018807973283893248, 1015852480873631744, '李军', 1015817732197453824, 1, 1, 1, NULL, NULL, NULL, NULL, 3, NULL, NULL, '2020-01-11 11:24:20'); +INSERT INTO `zz_student_action_trans` VALUES (1018807976429621248, 1015852480873631744, '李军', 1015817732197453824, 1, 1, 1, NULL, NULL, NULL, NULL, 4, NULL, NULL, '2020-01-11 11:24:25'); +INSERT INTO `zz_student_action_trans` VALUES (1018807990446985216, 1015852480873631744, '李军', 1015817732197453824, 1, 1, 0, NULL, NULL, NULL, NULL, 5, NULL, NULL, '2020-01-11 11:24:30'); +INSERT INTO `zz_student_action_trans` VALUES (1018808007266144256, 1015852480873631744, '李军', 1015817732197453824, 1, 2, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-11 11:24:35'); +INSERT INTO `zz_student_action_trans` VALUES (1018808010520924160, 1015852480873631744, '李军', 1015817732197453824, 1, 2, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-11 11:24:40'); +INSERT INTO `zz_student_action_trans` VALUES (1018808029248491520, 1015852480873631744, '李军', 1015817732197453824, 1, 2, 2, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-11 11:24:45'); +INSERT INTO `zz_student_action_trans` VALUES (1018808046189285376, 1015852480873631744, '李军', 1015817732197453824, 1, 3, 2, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-11 11:24:50'); +INSERT INTO `zz_student_action_trans` VALUES (1018808049536339968, 1015852480873631744, '李军', 1015817732197453824, 1, 3, 2, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-11 11:24:55'); +INSERT INTO `zz_student_action_trans` VALUES (1018808063356571648, 1015852480873631744, '李军', 1015817732197453824, 1, 3, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-11 11:25:00'); +INSERT INTO `zz_student_action_trans` VALUES (1018808090606964736, 1015852480873631744, '李军', 1015817732197453824, 1, 4, 0, 331, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-11 11:25:05'); +INSERT INTO `zz_student_action_trans` VALUES (1018808105442217984, 1015852480873631744, '李军', 1015817732197453824, 1, 4, 1, 180, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-11 11:25:10'); +INSERT INTO `zz_student_action_trans` VALUES (1018808123947487232, 1015852480873631744, '李军', 1015817732197453824, 1, 5, 1, NULL, NULL, NULL, NULL, NULL, NULL, 1, '2020-01-11 11:25:15'); +INSERT INTO `zz_student_action_trans` VALUES (1018808139374137344, 1015852480873631744, '李军', 1015817732197453824, 1, 5, 2, NULL, NULL, NULL, NULL, NULL, NULL, 1, '2020-01-11 11:25:20'); +INSERT INTO `zz_student_action_trans` VALUES (1018808163239727104, 1015852480873631744, '李军', 1015817732197453824, 1, 9, 2, NULL, 73, NULL, NULL, NULL, NULL, NULL, '2020-01-11 11:25:25'); +INSERT INTO `zz_student_action_trans` VALUES (1018808178884481024, 1015852480873631744, '李军', 1015817732197453824, 1, 9, 1, NULL, 85, NULL, NULL, NULL, NULL, NULL, '2020-01-11 11:25:30'); +INSERT INTO `zz_student_action_trans` VALUES (1018808202037039104, 1015852480873631744, '李军', 1015817732197453824, 1, 9, 0, NULL, 58, NULL, NULL, NULL, NULL, NULL, '2020-01-11 11:25:35'); +INSERT INTO `zz_student_action_trans` VALUES (1018808225227345920, 1015852480873631744, '李军', 1015817732197453824, 1, 10, 0, NULL, NULL, 3, NULL, NULL, NULL, NULL, '2020-01-11 11:25:40'); +INSERT INTO `zz_student_action_trans` VALUES (1018808239072743424, 1015852480873631744, '李军', 1015817732197453824, 1, 10, 1, NULL, NULL, 10, NULL, NULL, NULL, NULL, '2020-01-11 11:25:45'); +INSERT INTO `zz_student_action_trans` VALUES (1018808259285094400, 1015852480873631744, '李军', 1015817732197453824, 2, 10, 1, NULL, NULL, 6, NULL, NULL, NULL, NULL, '2020-01-11 11:25:50'); +INSERT INTO `zz_student_action_trans` VALUES (1018808281019977728, 1015852480873631744, '李军', 1015817732197453824, 2, 10, 0, NULL, NULL, 6, NULL, NULL, NULL, NULL, '2020-01-11 11:25:55'); +INSERT INTO `zz_student_action_trans` VALUES (1018808284450918400, 1015852480873631744, '李军', 1015817732197453824, 2, 10, 0, NULL, NULL, 8, NULL, NULL, NULL, NULL, '2020-01-11 11:26:00'); +INSERT INTO `zz_student_action_trans` VALUES (1018808301647564800, 1015852480873631744, '李军', 1015817732197453824, 2, 9, 0, NULL, 44, NULL, NULL, NULL, NULL, NULL, '2020-01-11 11:26:05'); +INSERT INTO `zz_student_action_trans` VALUES (1018808305003008000, 1015852480873631744, '李军', 1015817732197453824, 2, 9, 0, NULL, 98, NULL, NULL, NULL, NULL, NULL, '2020-01-11 11:26:10'); +INSERT INTO `zz_student_action_trans` VALUES (1018808319687266304, 1015852480873631744, '李军', 1015817732197453824, 2, 5, 0, NULL, NULL, NULL, NULL, NULL, NULL, 1, '2020-01-11 11:26:15'); +INSERT INTO `zz_student_action_trans` VALUES (1018808334279249920, 1015852480873631744, '李军', 1015817732197453824, 2, 5, 1, NULL, NULL, NULL, NULL, NULL, NULL, 1, '2020-01-11 11:26:20'); +INSERT INTO `zz_student_action_trans` VALUES (1018808337051684864, 1015852480873631744, '李军', 1015817732197453824, 2, 5, 1, NULL, NULL, NULL, NULL, NULL, NULL, 1, '2020-01-11 11:26:25'); +INSERT INTO `zz_student_action_trans` VALUES (1018808352482529280, 1015852480873631744, '李军', 1015817732197453824, 2, 4, 1, 829, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-11 11:26:30'); +INSERT INTO `zz_student_action_trans` VALUES (1018808368341192704, 1015852480873631744, '李军', 1015817732197453824, 2, 4, 2, 143, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-11 11:26:35'); +INSERT INTO `zz_student_action_trans` VALUES (1018808371201708032, 1015852480873631744, '李军', 1015817732197453824, 2, 4, 2, 727, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-11 11:26:40'); +INSERT INTO `zz_student_action_trans` VALUES (1018808386959708160, 1015852480873631744, '李军', 1015817732197453824, 2, 3, 2, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-11 11:26:45'); +INSERT INTO `zz_student_action_trans` VALUES (1018808389941858304, 1015852480873631744, '李军', 1015817732197453824, 2, 3, 2, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-11 11:26:50'); +INSERT INTO `zz_student_action_trans` VALUES (1018808403061641216, 1015852480873631744, '李军', 1015817732197453824, 2, 3, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-11 11:26:55'); +INSERT INTO `zz_student_action_trans` VALUES (1018808417364217856, 1015852480873631744, '李军', 1015817732197453824, 2, 3, 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-11 11:27:00'); +INSERT INTO `zz_student_action_trans` VALUES (1018808431247364096, 1015852480873631744, '李军', 1015817732197453824, 2, 2, 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-11 11:27:05'); +INSERT INTO `zz_student_action_trans` VALUES (1018808434900602880, 1015852480873631744, '李军', 1015817732197453824, 2, 2, 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-11 11:27:10'); +INSERT INTO `zz_student_action_trans` VALUES (1018808450344030208, 1015852480873631744, '李军', 1015817732197453824, 2, 2, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-11 11:27:15'); +INSERT INTO `zz_student_action_trans` VALUES (1018808468366954496, 1015852480873631744, '李军', 1015817732197453824, 2, 1, 0, NULL, NULL, NULL, NULL, 1, NULL, NULL, '2020-01-11 11:27:20'); +INSERT INTO `zz_student_action_trans` VALUES (1018808471776923648, 1015852480873631744, '李军', 1015817732197453824, 2, 1, 0, NULL, NULL, NULL, NULL, 1, NULL, NULL, '2020-01-11 11:27:25'); +INSERT INTO `zz_student_action_trans` VALUES (1018808486574428160, 1015852480873631744, '李军', 1015817732197453824, 2, 1, 1, NULL, NULL, NULL, NULL, 4, NULL, NULL, '2020-01-11 11:27:30'); +INSERT INTO `zz_student_action_trans` VALUES (1018808489720156160, 1015852480873631744, '李军', 1015817732197453824, 2, 1, 1, NULL, NULL, NULL, NULL, 1, NULL, NULL, '2020-01-11 11:27:35'); +INSERT INTO `zz_student_action_trans` VALUES (1018808519092867072, 1015852480873631744, '李军', 1015817732197453824, 2, 0, 1, NULL, NULL, NULL, NULL, NULL, 23, NULL, '2020-01-11 11:27:40'); +INSERT INTO `zz_student_action_trans` VALUES (1018808533722599424, 1015852480873631744, '李军', 1015817732197453824, 2, 0, 0, NULL, NULL, NULL, NULL, NULL, 486, NULL, '2020-01-11 11:27:45'); +INSERT INTO `zz_student_action_trans` VALUES (1018808549908418560, 1015852480873631744, '李军', 1015817732197453824, 3, 0, 0, NULL, NULL, NULL, NULL, NULL, 937, NULL, '2020-01-11 11:27:50'); +INSERT INTO `zz_student_action_trans` VALUES (1018808553595211776, 1015852480873631744, '李军', 1015817732197453824, 3, 0, 0, NULL, NULL, NULL, NULL, NULL, 634, NULL, '2020-01-11 11:27:55'); +INSERT INTO `zz_student_action_trans` VALUES (1018808567696461824, 1015852480873631744, '李军', 1015817732197453824, 3, 1, 0, NULL, NULL, NULL, NULL, 2, NULL, NULL, '2020-01-11 11:28:00'); +INSERT INTO `zz_student_action_trans` VALUES (1018808589381013504, 1015852480873631744, '李军', 1015817732197453824, 3, 2, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-11 11:28:05'); +INSERT INTO `zz_student_action_trans` VALUES (1018808603381600256, 1015852480873631744, '李军', 1015817732197453824, 3, 2, 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-11 11:28:10'); +INSERT INTO `zz_student_action_trans` VALUES (1018808627708563456, 1015852853839532032, '王石', 1015817732197453824, 3, 2, 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-11 11:28:15'); +INSERT INTO `zz_student_action_trans` VALUES (1018808643911159808, 1015852853839532032, '王石', 1015817732197453824, 3, 3, 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-11 11:28:20'); +INSERT INTO `zz_student_action_trans` VALUES (1018808647878971392, 1015852853839532032, '王石', 1015817732197453824, 3, 3, 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-11 11:28:25'); +INSERT INTO `zz_student_action_trans` VALUES (1018808662647115776, 1015852853839532032, '王石', 1015817732197453824, 3, 3, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-11 11:28:30'); +INSERT INTO `zz_student_action_trans` VALUES (1018808676190523392, 1015852853839532032, '王石', 1015817732197453824, 3, 5, 0, NULL, NULL, NULL, NULL, NULL, NULL, 1, '2020-01-11 11:28:35'); +INSERT INTO `zz_student_action_trans` VALUES (1018808679671795712, 1015852853839532032, '王石', 1015817732197453824, 3, 5, 0, NULL, NULL, NULL, NULL, NULL, NULL, 1, '2020-01-11 11:28:40'); +INSERT INTO `zz_student_action_trans` VALUES (1018808713146535936, 1015841864515588096, '张大', 1015817732197453824, 3, 5, 2, NULL, NULL, NULL, NULL, NULL, NULL, 1, '2020-01-11 11:28:45'); +INSERT INTO `zz_student_action_trans` VALUES (1018808727696576512, 1015841864515588096, '张大', 1015817732197453824, 3, 9, 2, NULL, 93, NULL, NULL, NULL, NULL, NULL, '2020-01-11 11:28:50'); +INSERT INTO `zz_student_action_trans` VALUES (1018808730968133632, 1015841864515588096, '张大', 1015817732197453824, 3, 9, 2, NULL, 39, NULL, NULL, NULL, NULL, NULL, '2020-01-11 11:28:55'); +INSERT INTO `zz_student_action_trans` VALUES (1018808745056800768, 1015841864515588096, '张大', 1015817732197453824, 3, 9, 0, NULL, 26, NULL, NULL, NULL, NULL, NULL, '2020-01-11 11:29:00'); +INSERT INTO `zz_student_action_trans` VALUES (1018808762224087040, 1015841864515588096, '张大', 1015817732197453824, 3, 10, 0, NULL, NULL, 4, NULL, NULL, NULL, NULL, '2020-01-11 11:29:05'); +INSERT INTO `zz_student_action_trans` VALUES (1018808766552608768, 1015841864515588096, '张大', 1015817732197453824, 3, 10, 0, NULL, NULL, 7, NULL, NULL, NULL, NULL, '2020-01-11 11:29:10'); +INSERT INTO `zz_student_action_trans` VALUES (1018808834777157632, 1015841864515588096, '张大', 1015818056597508096, 2, 10, 0, NULL, NULL, 8, NULL, NULL, NULL, NULL, '2020-01-11 11:29:15'); +INSERT INTO `zz_student_action_trans` VALUES (1018808837880942592, 1015841864515588096, '张大', 1015818056597508096, 2, 10, 0, NULL, NULL, 7, NULL, NULL, NULL, NULL, '2020-01-11 11:29:20'); +INSERT INTO `zz_student_action_trans` VALUES (1018808852263211008, 1015841864515588096, '张大', 1015818056597508096, 2, 5, 0, NULL, NULL, NULL, NULL, NULL, NULL, 1, '2020-01-11 11:29:25'); +INSERT INTO `zz_student_action_trans` VALUES (1018808870055448576, 1015841864515588096, '张大', 1015818056597508096, 2, 5, 1, NULL, NULL, NULL, NULL, NULL, NULL, 1, '2020-01-11 11:29:30'); +INSERT INTO `zz_student_action_trans` VALUES (1018808872664305664, 1015841864515588096, '张大', 1015818056597508096, 2, 5, 1, NULL, NULL, NULL, NULL, NULL, NULL, 1, '2020-01-11 11:29:35'); +INSERT INTO `zz_student_action_trans` VALUES (1018808889886117888, 1015841864515588096, '张大', 1015818056597508096, 2, 3, 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-11 11:29:40'); +INSERT INTO `zz_student_action_trans` VALUES (1018808905585397760, 1015841864515588096, '张大', 1015818056597508096, 2, 4, 1, 756, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-11 11:29:45'); +INSERT INTO `zz_student_action_trans` VALUES (1018808924665286656, 1015841864515588096, '张大', 1015818056597508096, 2, 4, 2, 35, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-11 11:29:50'); +INSERT INTO `zz_student_action_trans` VALUES (1018808927844569088, 1015841864515588096, '张大', 1015818056597508096, 2, 4, 2, 489, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-11 11:29:55'); +INSERT INTO `zz_student_action_trans` VALUES (1018808941014683648, 1015841864515588096, '张大', 1015818056597508096, 2, 2, 2, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-11 11:30:00'); +INSERT INTO `zz_student_action_trans` VALUES (1018808944089108480, 1015841864515588096, '张大', 1015818056597508096, 2, 2, 2, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-11 11:30:05'); +INSERT INTO `zz_student_action_trans` VALUES (1018808963789754368, 1015841864515588096, '张大', 1015818056597508096, 2, 0, 2, NULL, NULL, NULL, NULL, NULL, 342, NULL, '2020-01-11 11:30:10'); +INSERT INTO `zz_student_action_trans` VALUES (1018808967061311488, 1015841864515588096, '张大', 1015818056597508096, 2, 0, 2, NULL, NULL, NULL, NULL, NULL, 894, NULL, '2020-01-11 11:30:15'); +INSERT INTO `zz_student_action_trans` VALUES (1018808971549216768, 1015841864515588096, '张大', 1015818056597508096, 2, 0, 2, NULL, NULL, NULL, NULL, NULL, 505, NULL, '2020-01-11 11:30:20'); +INSERT INTO `zz_student_action_trans` VALUES (1018809014373060608, 1015841864515588096, '张大', 1015818056597508096, 3, 0, 2, NULL, NULL, NULL, NULL, NULL, 870, NULL, '2020-01-11 11:30:25'); +INSERT INTO `zz_student_action_trans` VALUES (1018809017279713280, 1015841864515588096, '张大', 1015818056597508096, 3, 0, 2, NULL, NULL, NULL, NULL, NULL, 832, NULL, '2020-01-11 11:30:30'); +INSERT INTO `zz_student_action_trans` VALUES (1018809030013620224, 1015841864515588096, '张大', 1015818056597508096, 3, 1, 2, NULL, NULL, NULL, NULL, 1, NULL, NULL, '2020-01-11 11:30:35'); +INSERT INTO `zz_student_action_trans` VALUES (1018809043577999360, 1015841864515588096, '张大', 1015818056597508096, 3, 1, 0, NULL, NULL, NULL, NULL, 2, NULL, NULL, '2020-01-11 11:30:40'); +INSERT INTO `zz_student_action_trans` VALUES (1018809058333560832, 1015841864515588096, '张大', 1015818056597508096, 3, 2, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-11 11:30:45'); +INSERT INTO `zz_student_action_trans` VALUES (1018809068521525248, 1015841864515588096, '张大', 1015818056597508096, 3, 2, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-11 11:30:50'); +INSERT INTO `zz_student_action_trans` VALUES (1018809083839123456, 1015841864515588096, '张大', 1015818056597508096, 3, 4, 0, 484, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-11 11:30:55'); +INSERT INTO `zz_student_action_trans` VALUES (1018809101107073024, 1015841864515588096, '张大', 1015818056597508096, 3, 4, 1, 822, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-11 11:31:00'); +INSERT INTO `zz_student_action_trans` VALUES (1018809116709883904, 1015841864515588096, '张大', 1015818056597508096, 3, 5, 1, NULL, NULL, NULL, NULL, NULL, NULL, 1, '2020-01-11 11:31:05'); +INSERT INTO `zz_student_action_trans` VALUES (1018809119352295424, 1015841864515588096, '张大', 1015818056597508096, 3, 5, 1, NULL, NULL, NULL, NULL, NULL, NULL, 1, '2020-01-11 11:31:10'); +INSERT INTO `zz_student_action_trans` VALUES (1018809140072157184, 1015841864515588096, '张大', 1015818056597508096, 3, 9, 1, NULL, 92, NULL, NULL, NULL, NULL, NULL, '2020-01-11 11:31:15'); +INSERT INTO `zz_student_action_trans` VALUES (1018809153410043904, 1015841864515588096, '张大', 1015818056597508096, 3, 9, 0, NULL, 23, NULL, NULL, NULL, NULL, NULL, '2020-01-11 11:31:20'); +INSERT INTO `zz_student_action_trans` VALUES (1018809156404776960, 1015841864515588096, '张大', 1015818056597508096, 3, 9, 0, NULL, 61, NULL, NULL, NULL, NULL, NULL, '2020-01-11 11:31:25'); +INSERT INTO `zz_student_action_trans` VALUES (1018809187635564544, 1015841864515588096, '张大', 1015818056597508096, 4, 9, 0, NULL, 26, NULL, NULL, NULL, NULL, NULL, '2020-01-11 11:31:30'); +INSERT INTO `zz_student_action_trans` VALUES (1018809205096452096, 1015841864515588096, '张大', 1015818056597508096, 4, 9, 1, NULL, 96, NULL, NULL, NULL, NULL, NULL, '2020-01-11 11:31:35'); +INSERT INTO `zz_student_action_trans` VALUES (1018809219889762304, 1015841864515588096, '张大', 1015818056597508096, 4, 5, 1, NULL, NULL, NULL, NULL, NULL, NULL, 1, '2020-01-11 11:31:40'); +INSERT INTO `zz_student_action_trans` VALUES (1018809223115182080, 1015841864515588096, '张大', 1015818056597508096, 4, 5, 1, NULL, NULL, NULL, NULL, NULL, NULL, 1, '2020-01-11 11:31:45'); +INSERT INTO `zz_student_action_trans` VALUES (1018809241318461440, 1015841864515588096, '张大', 1015818056597508096, 4, 10, 1, NULL, NULL, 4, NULL, NULL, NULL, NULL, '2020-01-11 11:31:50'); +INSERT INTO `zz_student_action_trans` VALUES (1018809244799733760, 1015841864515588096, '张大', 1015818056597508096, 4, 10, 1, NULL, NULL, 5, NULL, NULL, NULL, NULL, '2020-01-11 11:31:55'); +INSERT INTO `zz_student_action_trans` VALUES (1018809259483992064, 1015841864515588096, '张大', 1015818056597508096, 4, 4, 1, 244, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-11 11:32:00'); +INSERT INTO `zz_student_action_trans` VALUES (1018809272926736384, 1015841864515588096, '张大', 1015818056597508096, 4, 4, 0, 736, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-11 11:32:05'); +INSERT INTO `zz_student_action_trans` VALUES (1018809275388792832, 1015841864515588096, '张大', 1015818056597508096, 4, 4, 0, 230, NULL, NULL, NULL, NULL, NULL, NULL, '2020-01-11 11:32:10'); +INSERT INTO `zz_student_action_trans` VALUES (1018809289016086528, 1015841864515588096, '张大', 1015818056597508096, 4, 1, 0, NULL, NULL, NULL, NULL, 3, NULL, NULL, '2020-01-11 11:32:15'); +INSERT INTO `zz_student_action_trans` VALUES (1018809291985653760, 1015841864515588096, '张大', 1015818056597508096, 4, 1, 0, NULL, NULL, NULL, NULL, 4, NULL, NULL, '2020-01-11 11:32:20'); +INSERT INTO `zz_student_action_trans` VALUES (1018809313879920640, 1015841864515588096, '张大', 1015818056597508096, 4, 0, 0, NULL, NULL, NULL, NULL, NULL, 441, NULL, '2020-01-11 11:32:25'); +INSERT INTO `zz_student_action_trans` VALUES (1018809333760921600, 1015841864515588096, '张大', 1015818056597508096, 4, 0, 1, NULL, NULL, NULL, NULL, NULL, 202, NULL, '2020-01-11 11:32:30'); +INSERT INTO `zz_student_action_trans` VALUES (1018809347316912128, 1015841864515588096, '张大', 1015818056597508096, 4, 0, 2, NULL, NULL, NULL, NULL, NULL, 614, NULL, '2020-01-11 11:32:35'); +COMMIT; + +-- ---------------------------- +-- Table structure for zz_sys_menu +-- ---------------------------- +DROP TABLE IF EXISTS `zz_sys_menu`; +CREATE TABLE `zz_sys_menu` ( + `menu_id` bigint(20) NOT NULL COMMENT '主键Id', + `parent_id` bigint(20) DEFAULT NULL COMMENT '父菜单Id,目录菜单的父菜单为null', + `menu_name` varchar(50) COLLATE utf8mb4_bin NOT NULL COMMENT '菜单显示名称', + `menu_type` int(11) NOT NULL COMMENT '(0: 目录 1: 菜单 2: 按钮 3: UI片段)', + `form_router_name` varchar(64) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '前端表单路由名称,仅用于menu_type为1的菜单类型', + `show_order` int(11) NOT NULL COMMENT '菜单显示顺序 (值越小,排序越靠前)', + `icon` varchar(50) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '菜单图标', + `create_time` datetime NOT NULL COMMENT '创建时间', + `deleted_flag` int(11) NOT NULL COMMENT '逻辑删除标记(1: 正常 -1: 已删除)', + PRIMARY KEY (`menu_id`) USING BTREE, + KEY `idx_show_order` (`show_order`) USING BTREE, + KEY `idx_parent_id` (`parent_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin ROW_FORMAT=COMPACT COMMENT='菜单和操作权限管理表'; + +-- ---------------------------- +-- Records of zz_sys_menu +-- ---------------------------- +BEGIN; +INSERT INTO `zz_sys_menu` VALUES (1093376634899927040, NULL, '系统管理', 0, NULL, 1, 'el-icon-setting', CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093376634916704256, 1093376634899927040, '用户管理', 1, 'formSysUser', 100, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093376634916704258, 1093376634899927040, '角色管理', 1, 'formSysRole', 110, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093376634916704259, 1093376634899927040, '菜单管理', 1, 'formSysMenu', 120, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093376634916704260, 1093376634899927040, '权限字管理', 1, 'formSysPermCode', 125, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093376634916704261, 1093376634899927040, '权限管理', 1, 'formSysPerm', 130, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093376634916704262, 1093376634899927040, '字典管理', 1, 'formSysDict', 135, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093478813098840064, NULL, '业务管理', 0, NULL, 10, 'el-icon-s-goods', CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093478847987060736, NULL, '统计管理', 0, NULL, 20, 'el-icon-s-data', CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093478946238631936, 1093478813098840064, '校区管理', 1, 'formSchool', 1, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093479020943380480, 1093478813098840064, '学生管理', 1, 'formStudent', 5, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093479114610577408, 1093478813098840064, '课程管理', 1, 'formCourse', 10, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093479177793572864, 1093478813098840064, '班级管理', 1, 'formClass', 15, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093479249499394048, 1093478847987060736, '课程统计', 1, 'formCourseStats', 1, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093479313416392704, 1093478847987060736, '学生行为统计', 1, 'formStudentActionStats', 5, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376532, 1093376634916704256, '显示', 3, NULL, 1, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376533, 1093376634916704256, '新增', 3, NULL, 2, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376534, 1093376634916704256, '编辑', 3, NULL, 3, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376535, 1093376634916704256, '删除', 3, NULL, 4, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376536, 1093376634916704256, '重置密码', 3, NULL, 5, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376554, 1093376634916704258, '角色管理', 2, NULL, 1, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376555, 1093376634916704258, '用户授权', 2, NULL, 2, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376556, 1093809448598376554, '显示', 3, NULL, 1, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376557, 1093809448598376554, '新增', 3, NULL, 2, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376558, 1093809448598376554, '编辑', 3, NULL, 3, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376559, 1093809448598376554, '删除', 3, NULL, 4, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376560, 1093809448598376555, '显示', 3, NULL, 1, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376561, 1093809448598376555, '授权用户', 3, NULL, 2, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376562, 1093809448598376555, '移除用户', 3, NULL, 3, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376572, 1093376634916704259, '显示', 3, NULL, 1, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376573, 1093376634916704259, '新增', 3, NULL, 2, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376574, 1093376634916704259, '编辑', 3, NULL, 3, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376575, 1093376634916704259, '删除', 3, NULL, 4, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376576, 1093376634916704259, '权限列表', 3, NULL, 5, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376584, 1093376634916704260, '显示', 3, NULL, 1, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376585, 1093376634916704260, '新增', 3, NULL, 2, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376586, 1093376634916704260, '编辑', 3, NULL, 3, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376587, 1093376634916704260, '删除', 3, NULL, 4, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376594, 1093376634916704261, '显示', 3, NULL, 1, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376595, 1093376634916704261, '新增模块', 3, NULL, 2, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376596, 1093376634916704261, '编辑模块', 3, NULL, 3, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376597, 1093376634916704261, '删除模块', 3, NULL, 4, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376598, 1093376634916704261, '新增权限', 3, NULL, 5, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376599, 1093376634916704261, '编辑权限', 3, NULL, 6, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376600, 1093376634916704261, '删除权限', 3, NULL, 7, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376610, 1093376634916704262, '显示', 3, NULL, 1, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376611, 1093376634916704262, '新增', 3, NULL, 2, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376612, 1093376634916704262, '编辑', 3, NULL, 3, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376613, 1093376634916704262, '删除', 3, NULL, 4, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376614, 1093376634916704262, '同步缓存', 3, NULL, 5, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376624, 1093478946238631936, '显示', 3, NULL, 1, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376625, 1093478946238631936, '新建', 3, NULL, 2, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376626, 1093478946238631936, '编辑', 3, NULL, 3, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376627, 1093478946238631936, '删除', 3, NULL, 4, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376629, 1093479020943380480, '显示', 3, NULL, 1, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376630, 1093479020943380480, '新建', 3, NULL, 2, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376631, 1093479020943380480, '编辑', 3, NULL, 3, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376632, 1093479020943380480, '删除', 3, NULL, 4, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376634, 1093479114610577408, '显示', 3, NULL, 1, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376635, 1093479114610577408, '新建', 3, NULL, 2, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376636, 1093479114610577408, '编辑', 3, NULL, 3, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376637, 1093479114610577408, '删除', 3, NULL, 4, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376639, 1093479177793572864, '显示', 3, NULL, 1, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376640, 1093479177793572864, '新建', 3, NULL, 2, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376641, 1093479177793572864, '编辑', 3, NULL, 3, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376642, 1093479177793572864, '学生', 3, NULL, 4, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376643, 1093479177793572864, '课程', 3, NULL, 5, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376644, 1093479177793572864, '删除', 3, NULL, 6, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376646, 1093479249499394048, '显示', 3, NULL, 1, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376648, 1093479313416392704, '显示', 3, NULL, 1, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376649, 1093479313416392704, '学生行为详情', 3, NULL, 2, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376650, 1093479313416392704, '学生行为详情', 3, NULL, 3, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376651, 1093479313416392704, '学生行为详情', 3, NULL, 4, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376652, 1093479313416392704, '学生行为详情', 3, NULL, 5, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376653, 1093479313416392704, '学生行为详情', 3, NULL, 6, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376654, 1093479313416392704, '学生行为详情', 3, NULL, 7, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376655, 1093479313416392704, '学生行为详情', 3, NULL, 8, NULL, CURDATE(), 1); +INSERT INTO `zz_sys_menu` VALUES (1093809448598376656, 1093479313416392704, '学生行为详情', 3, NULL, 9, NULL, CURDATE(), 1); +COMMIT; + +-- ---------------------------- +-- Table structure for zz_sys_menu_perm_code +-- ---------------------------- +DROP TABLE IF EXISTS `zz_sys_menu_perm_code`; +CREATE TABLE `zz_sys_menu_perm_code` ( + `menu_id` bigint(20) NOT NULL COMMENT '关联菜单Id', + `perm_code_id` bigint(20) NOT NULL COMMENT '关联权限字Id', + PRIMARY KEY (`menu_id`,`perm_code_id`) USING BTREE, + KEY `idx_perm_code_id` (`perm_code_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='菜单和权限关系表'; + +-- ---------------------------- +-- Records of zz_sys_menu_perm_code +-- ---------------------------- +BEGIN; +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376624, 1093809448598376449); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376625, 1093809448598376450); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376626, 1093809448598376451); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376627, 1093809448598376452); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376625, 1093809448598376453); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376625, 1093809448598376454); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376625, 1093809448598376455); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376625, 1093809448598376456); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376626, 1093809448598376457); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376626, 1093809448598376458); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376626, 1093809448598376459); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376626, 1093809448598376460); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376629, 1093809448598376462); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376630, 1093809448598376463); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376631, 1093809448598376464); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376632, 1093809448598376465); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376630, 1093809448598376466); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376630, 1093809448598376467); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376630, 1093809448598376468); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376630, 1093809448598376469); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376631, 1093809448598376470); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376631, 1093809448598376471); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376631, 1093809448598376472); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376631, 1093809448598376473); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376634, 1093809448598376475); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376635, 1093809448598376476); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376636, 1093809448598376477); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376637, 1093809448598376478); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376635, 1093809448598376479); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376635, 1093809448598376480); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376635, 1093809448598376481); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376635, 1093809448598376482); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376636, 1093809448598376483); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376636, 1093809448598376484); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376636, 1093809448598376485); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376636, 1093809448598376486); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376639, 1093809448598376488); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376640, 1093809448598376489); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376641, 1093809448598376490); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376642, 1093809448598376491); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376643, 1093809448598376492); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376644, 1093809448598376493); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376640, 1093809448598376494); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376640, 1093809448598376495); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376640, 1093809448598376496); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376640, 1093809448598376497); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376641, 1093809448598376498); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376641, 1093809448598376499); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376641, 1093809448598376500); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376641, 1093809448598376501); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376642, 1093809448598376502); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376642, 1093809448598376503); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376642, 1093809448598376504); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376642, 1093809448598376505); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376643, 1093809448598376506); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376643, 1093809448598376507); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376643, 1093809448598376508); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376643, 1093809448598376509); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376642, 1093809448598376510); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376642, 1093809448598376511); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376642, 1093809448598376512); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376643, 1093809448598376513); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376643, 1093809448598376514); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376643, 1093809448598376515); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376646, 1093809448598376517); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376648, 1093809448598376519); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376649, 1093809448598376520); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376650, 1093809448598376521); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376651, 1093809448598376522); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376652, 1093809448598376523); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376653, 1093809448598376524); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376654, 1093809448598376525); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376655, 1093809448598376526); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376656, 1093809448598376527); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376649, 1093809448598376528); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376650, 1093809448598376528); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376651, 1093809448598376528); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376652, 1093809448598376528); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376653, 1093809448598376528); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376654, 1093809448598376528); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376655, 1093809448598376528); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376656, 1093809448598376528); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376649, 1093809448598376529); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376650, 1093809448598376529); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376651, 1093809448598376529); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376652, 1093809448598376529); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376653, 1093809448598376529); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376654, 1093809448598376529); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376655, 1093809448598376529); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376656, 1093809448598376529); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376532, 1093809448598376538); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376533, 1093809448598376539); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376534, 1093809448598376540); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376535, 1093809448598376541); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376536, 1093809448598376542); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376556, 1093809448598376564); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376560, 1093809448598376565); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376557, 1093809448598376566); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376558, 1093809448598376567); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376559, 1093809448598376568); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376561, 1093809448598376569); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376562, 1093809448598376570); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376572, 1093809448598376578); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376573, 1093809448598376579); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376574, 1093809448598376580); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376575, 1093809448598376581); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376576, 1093809448598376582); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376584, 1093809448598376589); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376585, 1093809448598376590); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376586, 1093809448598376591); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376587, 1093809448598376592); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376594, 1093809448598376602); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376595, 1093809448598376603); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376596, 1093809448598376604); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376597, 1093809448598376605); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376598, 1093809448598376606); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376599, 1093809448598376607); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376600, 1093809448598376608); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093376634916704262, 1093809448598376616); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376610, 1093809448598376616); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093376634916704262, 1093809448598376617); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376611, 1093809448598376617); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093376634916704262, 1093809448598376618); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376612, 1093809448598376618); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093376634916704262, 1093809448598376619); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376613, 1093809448598376619); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093376634916704262, 1093809448598376620); +INSERT INTO `zz_sys_menu_perm_code` VALUES (1093809448598376614, 1093809448598376620); +COMMIT; + +-- ---------------------------- +-- Table structure for zz_sys_perm +-- ---------------------------- +DROP TABLE IF EXISTS `zz_sys_perm`; +CREATE TABLE `zz_sys_perm` ( + `perm_id` bigint(20) NOT NULL COMMENT '权限id', + `module_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '权限所在的权限模块id', + `perm_name` varchar(64) COLLATE utf8mb4_bin NOT NULL DEFAULT '' COMMENT '权限名称', + `url` varchar(128) COLLATE utf8mb4_bin NOT NULL DEFAULT '' COMMENT '关联的url', + `show_order` int(11) NOT NULL DEFAULT '0' COMMENT '权限在当前模块下的顺序,由小到大', + `create_time` datetime NOT NULL COMMENT '创建时间', + `deleted_flag` int(11) NOT NULL COMMENT '逻辑删除标记(1: 正常 -1: 已删除)', + PRIMARY KEY (`perm_id`) USING BTREE, + KEY `idx_show_order` (`show_order`) USING BTREE, + KEY `idx_module_id` (`module_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin ROW_FORMAT=COMPACT COMMENT='系统权限表'; + +-- ---------------------------- +-- Records of zz_sys_perm +-- ---------------------------- +BEGIN; +INSERT INTO `zz_sys_perm` VALUES (1093809448569016321, 1093809448569016320, '新增', '/admin/CourseClass/course/add', 1, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016322, 1093809448569016320, '编辑', '/admin/CourseClass/course/update', 2, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016323, 1093809448569016320, '删除', '/admin/CourseClass/course/delete', 3, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016324, 1093809448569016320, '显示列表', '/admin/CourseClass/course/list', 4, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016325, 1093809448569016320, '导出', '/admin/CourseClass/course/export', 5, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016326, 1093809448569016320, '详情', '/admin/CourseClass/course/view', 6, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016327, 1093809448569016320, '打印', '/admin/CourseClass/course/print', 7, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016328, 1093809448569016320, '课程数据文件上传', '/admin/CourseClass/course/upload', 8, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016329, 1093809448569016320, '课程数据文件下载', '/admin/CourseClass/course/download', 9, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016331, 1093809448569016330, '新增', '/admin/CourseClass/schoolInfo/add', 1, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016332, 1093809448569016330, '编辑', '/admin/CourseClass/schoolInfo/update', 2, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016333, 1093809448569016330, '删除', '/admin/CourseClass/schoolInfo/delete', 3, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016334, 1093809448569016330, '显示列表', '/admin/CourseClass/schoolInfo/list', 4, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016335, 1093809448569016330, '导出', '/admin/CourseClass/schoolInfo/export', 5, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016336, 1093809448569016330, '详情', '/admin/CourseClass/schoolInfo/view', 6, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016337, 1093809448569016330, '打印', '/admin/CourseClass/schoolInfo/print', 7, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016339, 1093809448569016338, '新增', '/admin/CourseClass/student/add', 1, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016340, 1093809448569016338, '编辑', '/admin/CourseClass/student/update', 2, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016341, 1093809448569016338, '删除', '/admin/CourseClass/student/delete', 3, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016342, 1093809448569016338, '显示列表', '/admin/CourseClass/student/list', 4, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016343, 1093809448569016338, '导出', '/admin/CourseClass/student/export', 5, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016344, 1093809448569016338, '详情', '/admin/CourseClass/student/view', 6, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016345, 1093809448569016338, '打印', '/admin/CourseClass/student/print', 7, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016347, 1093809448569016346, '新增', '/admin/upms/sysUser/add', 1, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016348, 1093809448569016346, '编辑', '/admin/upms/sysUser/update', 2, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016349, 1093809448569016346, '删除', '/admin/upms/sysUser/delete', 3, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016350, 1093809448569016346, '显示列表', '/admin/upms/sysUser/list', 4, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016351, 1093809448569016346, '导出', '/admin/upms/sysUser/export', 5, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016352, 1093809448569016346, '详情', '/admin/upms/sysUser/view', 6, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016353, 1093809448569016346, '打印', '/admin/upms/sysUser/print', 7, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016354, 1093809448569016346, '重置密码', '/admin/upms/sysUser/resetPassword', 8, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016356, 1093809448569016355, '新增', '/admin/CourseClass/studentClass/add', 1, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016357, 1093809448569016355, '编辑', '/admin/CourseClass/studentClass/update', 2, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016358, 1093809448569016355, '删除', '/admin/CourseClass/studentClass/delete', 3, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016359, 1093809448569016355, '显示列表', '/admin/CourseClass/studentClass/list', 4, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016360, 1093809448569016355, '导出', '/admin/CourseClass/studentClass/export', 5, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016361, 1093809448569016355, '详情', '/admin/CourseClass/studentClass/view', 6, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016362, 1093809448569016355, '打印', '/admin/CourseClass/studentClass/print', 7, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016363, 1093809448569016355, '新增班级课程', '/admin/CourseClass/studentClass/addClassCourse', 8, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016364, 1093809448569016355, '移除班级课程', '/admin/CourseClass/studentClass/deleteClassCourse', 9, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016365, 1093809448569016355, '班级课程列表', '/admin/CourseClass/studentClass/listClassCourse', 10, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016366, 1093809448569016355, '班级课程未关联列表', '/admin/CourseClass/studentClass/listNotInClassCourse', 11, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016367, 1093809448569016355, '新增班级学生', '/admin/CourseClass/studentClass/addClassStudent', 12, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016368, 1093809448569016355, '移除班级学生', '/admin/CourseClass/studentClass/deleteClassStudent', 13, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016369, 1093809448569016355, '班级学生列表', '/admin/CourseClass/studentClass/listClassStudent', 14, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016370, 1093809448569016355, '班级学生未关联列表', '/admin/CourseClass/studentClass/listNotInClassStudent', 15, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016372, 1093809448569016371, '分组列表', '/admin/stats/courseTransStats/listWithGroup', 1, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016373, 1093809448569016371, '显示列表', '/admin/stats/courseTransStats/list', 2, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016374, 1093809448569016371, '导出', '/admin/stats/courseTransStats/export', 3, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016375, 1093809448569016371, '详情', '/admin/stats/courseTransStats/view', 4, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016376, 1093809448569016371, '打印', '/admin/stats/courseTransStats/print', 5, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016378, 1093809448569016377, '分组列表', '/admin/stats/studentActionStats/listWithGroup', 1, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016379, 1093809448569016377, '显示列表', '/admin/stats/studentActionStats/list', 2, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016380, 1093809448569016377, '导出', '/admin/stats/studentActionStats/export', 3, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016381, 1093809448569016377, '详情', '/admin/stats/studentActionStats/view', 4, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016382, 1093809448569016377, '打印', '/admin/stats/studentActionStats/print', 5, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016384, 1093809448569016383, '新增', '/admin/stats/studentActionTrans/add', 1, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016385, 1093809448569016383, '编辑', '/admin/stats/studentActionTrans/update', 2, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016386, 1093809448569016383, '删除', '/admin/stats/studentActionTrans/delete', 3, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016387, 1093809448569016383, '显示列表', '/admin/stats/studentActionTrans/list', 4, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016388, 1093809448569016383, '导出', '/admin/stats/studentActionTrans/export', 5, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016389, 1093809448569016383, '详情', '/admin/stats/studentActionTrans/view', 6, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016390, 1093809448569016383, '打印', '/admin/stats/studentActionTrans/print', 7, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016392, 1093809448569016391, '新增', '/admin/upms/sysRole/add', 1, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016393, 1093809448569016391, '编辑', '/admin/upms/sysRole/update', 2, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016394, 1093809448569016391, '删除', '/admin/upms/sysRole/delete', 3, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016395, 1093809448569016391, '显示列表', '/admin/upms/sysRole/list', 4, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016396, 1093809448569016391, '详情', '/admin/upms/sysRole/view', 5, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016397, 1093809448569016391, '授权用户', '/admin/upms/sysRole/addUserRole', 6, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016398, 1093809448569016391, '移除用户', '/admin/upms/sysRole/deleteUserRole', 7, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016399, 1093809448569016391, '角色用户列表', '/admin/upms/sysRole/listUserRole', 8, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016400, 1093809448569016391, '角色未添加用户列表', '/admin/upms/sysRole/listNotInUserRole', 9, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016402, 1093809448569016401, '新增', '/admin/upms/sysMenu/add', 1, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016403, 1093809448569016401, '编辑', '/admin/upms/sysMenu/update', 2, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016404, 1093809448569016401, '删除', '/admin/upms/sysMenu/delete', 3, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016405, 1093809448569016401, '显示列表', '/admin/upms/sysMenu/list', 4, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016406, 1093809448569016401, '详情', '/admin/upms/sysMenu/view', 5, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016407, 1093809448569016401, '权限资源列表', '/admin/upms/sysMenu/listMenuPerm', 6, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016409, 1093809448569016408, '新增', '/admin/upms/sysPermCode/add', 1, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016410, 1093809448569016408, '编辑', '/admin/upms/sysPermCode/update', 2, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016411, 1093809448569016408, '删除', '/admin/upms/sysPermCode/delete', 3, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016412, 1093809448569016408, '显示列表', '/admin/upms/sysPermCode/list', 4, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016413, 1093809448569016408, '详情', '/admin/upms/sysPermCode/view', 5, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016415, 1093809448569016414, '新增', '/admin/upms/sysPermModule/add', 1, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016416, 1093809448569016414, '编辑', '/admin/upms/sysPermModule/update', 2, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016417, 1093809448569016414, '删除', '/admin/upms/sysPermModule/delete', 3, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016418, 1093809448569016414, '显示列表', '/admin/upms/sysPermModule/list', 4, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016419, 1093809448569016414, '显示全部', '/admin/upms/sysPermModule/listAll', 5, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016421, 1093809448569016420, '新增', '/admin/upms/sysPerm/add', 1, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016422, 1093809448569016420, '编辑', '/admin/upms/sysPerm/update', 2, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016423, 1093809448569016420, '删除', '/admin/upms/sysPerm/delete', 3, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016424, 1093809448569016420, '显示列表', '/admin/upms/sysPerm/list', 4, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016425, 1093809448569016420, '详情', '/admin/upms/sysPerm/view', 5, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016428, 1093809448569016427, '新增', '/admin/CourseClass/areaCode/add', 1, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016429, 1093809448569016427, '编辑', '/admin/CourseClass/areaCode/update', 2, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016430, 1093809448569016427, '删除', '/admin/CourseClass/areaCode/delete', 3, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016431, 1093809448569016427, '同步缓存', '/admin/CourseClass/areaCode/reloadCachedData', 4, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016433, 1093809448569016432, '新增', '/admin/CourseClass/grade/add', 1, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016434, 1093809448569016432, '编辑', '/admin/CourseClass/grade/update', 2, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016435, 1093809448569016432, '删除', '/admin/CourseClass/grade/delete', 3, CURDATE(), 1); +INSERT INTO `zz_sys_perm` VALUES (1093809448569016436, 1093809448569016432, '同步缓存', '/admin/CourseClass/grade/reloadCachedData', 4, CURDATE(), 1); +COMMIT; + +-- ---------------------------- +-- Table structure for zz_sys_perm_code +-- ---------------------------- +DROP TABLE IF EXISTS `zz_sys_perm_code`; +CREATE TABLE `zz_sys_perm_code` ( + `perm_code_id` bigint(20) NOT NULL COMMENT '主键Id', + `parent_id` bigint(20) DEFAULT NULL COMMENT '上级权限字Id', + `perm_code` varchar(128) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '权限字标识(一般为有含义的英文字符串)', + `perm_code_type` int(11) NOT NULL COMMENT '类型(0: 表单 1: UI片段 2: 操作)', + `show_name` varchar(128) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '显示名称', + `show_order` int(11) NOT NULL COMMENT '显示顺序(数值越小,越靠前)', + `create_time` datetime NOT NULL COMMENT '创建时间', + `deleted_flag` int(11) NOT NULL COMMENT '逻辑删除标记(1: 正常 -1: 已删除)', + PRIMARY KEY (`perm_code_id`), + UNIQUE KEY `idx_perm_code` (`perm_code`) USING BTREE, + KEY `idx_parent_id` (`parent_id`) USING BTREE, + KEY `idx_show_order` (`show_order`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin ROW_FORMAT=COMPACT COMMENT='系统权限资源表'; + +-- ---------------------------- +-- Records of zz_sys_perm_code +-- ---------------------------- +BEGIN; +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376448, NULL, 'formSchool', 0, '校区管理', 0, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376449, 1093809448598376448, 'formSchool:formSchool', 1, '校区管理', 0, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376450, 1093809448598376449, 'formSchool:formSchool:formCreateClass', 2, '新建', 0, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376451, 1093809448598376449, 'formSchool:formSchool:formEditSchool', 2, '编辑', 10, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376452, 1093809448598376449, 'formSchool:formSchool:delete', 2, '删除', 20, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376453, NULL, 'formCreateSchool', 0, '新建校区', 10, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376454, 1093809448598376453, 'formCreateSchool:formCreateClass', 1, '新建校区', 0, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376455, 1093809448598376454, 'formCreateSchool:formCreateClass:cancel', 2, '取消', 0, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376456, 1093809448598376454, 'formCreateSchool:formCreateClass:add', 2, '保存', 10, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376457, NULL, 'formEditSchool', 0, '编辑校区', 20, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376458, 1093809448598376457, 'formEditSchool:formEditSchool', 1, '编辑校区', 0, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376459, 1093809448598376458, 'formEditSchool:formEditSchool:cancel', 2, '取消', 0, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376460, 1093809448598376458, 'formEditSchool:formEditSchool:update', 2, '保存', 10, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376461, NULL, 'formStudent', 0, '学生管理', 30, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376462, 1093809448598376461, 'formStudent:formStudent', 1, '学生管理', 0, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376463, 1093809448598376462, 'formStudent:formStudent:formCreateStudent', 2, '新建', 0, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376464, 1093809448598376462, 'formStudent:formStudent:formEditStudent', 2, '编辑', 10, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376465, 1093809448598376462, 'formStudent:formStudent:delete', 2, '删除', 20, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376466, NULL, 'formCreateStudent', 0, '新建学生', 40, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376467, 1093809448598376466, 'formCreateStudent:formCreateStudent', 1, '新建学生', 0, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376468, 1093809448598376467, 'formCreateStudent:formCreateStudent:cancel', 2, '取消', 0, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376469, 1093809448598376467, 'formCreateStudent:formCreateStudent:update', 2, '保存', 10, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376470, NULL, 'formEditStudent', 0, '编辑学生', 50, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376471, 1093809448598376470, 'formEditStudent:formEditStudent', 1, '编辑学生', 0, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376472, 1093809448598376471, 'formEditStudent:formEditStudent:cancel', 2, '取消', 0, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376473, 1093809448598376471, 'formEditStudent:formEditStudent:update', 2, '保存', 10, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376474, NULL, 'formCourse', 0, '课程管理', 60, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376475, 1093809448598376474, 'formCourse:formCourse', 1, '课程管理', 0, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376476, 1093809448598376475, 'formCourse:formCourse:formCreateCourse', 2, '新建', 0, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376477, 1093809448598376475, 'formCourse:formCourse:formEditCourse', 2, '编辑', 10, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376478, 1093809448598376475, 'formCourse:formCourse:delete', 2, '删除', 20, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376479, NULL, 'formCreateCourse', 0, '新建课程', 70, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376480, 1093809448598376479, 'formCreateCourse:formCreateCourse', 1, '新建课程', 0, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376481, 1093809448598376480, 'formCreateCourse:formCreateCourse:cancel', 2, '取消', 0, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376482, 1093809448598376480, 'formCreateCourse:formCreateCourse:add', 2, '保存', 10, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376483, NULL, 'formEditCourse', 0, '编辑课程', 80, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376484, 1093809448598376483, 'formEditCourse:formEditCourse', 1, '编辑课程', 0, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376485, 1093809448598376484, 'formEditCourse:formEditCourse:cancel', 2, '取消', 0, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376486, 1093809448598376484, 'formEditCourse:formEditCourse:update', 2, '保存', 10, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376487, NULL, 'formClass', 0, '班级管理', 90, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376488, 1093809448598376487, 'formClass:formClass', 1, '班级管理', 0, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376489, 1093809448598376488, 'formClass:formClass:formCreateClass', 2, '新建', 0, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376490, 1093809448598376488, 'formClass:formClass:formEditClass', 2, '编辑', 10, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376491, 1093809448598376488, 'formClass:formClass:formClassStudent', 2, '学生', 20, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376492, 1093809448598376488, 'formClass:formClass:formClassCourse', 2, '课程', 30, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376493, 1093809448598376488, 'formClass:formClass:delete', 2, '删除', 40, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376494, NULL, 'formCreateClass', 0, '新建班级', 100, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376495, 1093809448598376494, 'formCreateClass:formCreateClass', 1, '新建班级', 0, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376496, 1093809448598376495, 'formCreateClass:formCreateClass:cancel', 2, '取消', 0, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376497, 1093809448598376495, 'formCreateClass:formCreateClass:add', 2, '保存', 10, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376498, NULL, 'formEditClass', 0, '编辑班级', 110, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376499, 1093809448598376498, 'formEditClass:formEditClass', 1, '编辑班级', 0, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376500, 1093809448598376499, 'formEditClass:formEditClass:cancel', 2, '取消', 0, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376501, 1093809448598376499, 'formEditClass:formEditClass:update', 2, '保存', 10, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376502, NULL, 'formClassStudent', 0, '班级学生', 120, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376503, 1093809448598376502, 'formClassStudent:formClassStudent', 1, '班级学生', 0, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376504, 1093809448598376503, 'formClassStudent:formClassStudent:formSetClassStudent', 2, '设置班级学生', 0, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376505, 1093809448598376503, 'formClassStudent:formClassStudent:deleteClassStudent', 2, '移除', 10, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376506, NULL, 'formClassCourse', 0, '班级课程', 130, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376507, 1093809448598376506, 'formClassCourse:formClassCourse', 1, '班级课程', 0, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376508, 1093809448598376507, 'formClassCourse:formClassCourse:formSetClassCourse', 2, '设置班级课程', 0, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376509, 1093809448598376507, 'formClassCourse:formClassCourse:deleteClassCourse', 2, '移除', 10, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376510, NULL, 'formSetClassStudent', 0, '设置班级学生', 140, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376511, 1093809448598376510, 'formSetClassStudent:formSetClassStudent', 1, '设置班级学生', 0, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376512, 1093809448598376511, 'formSetClassStudent:formSetClassStudent:addClassStudent', 2, '添加', 0, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376513, NULL, 'formSetClassCourse', 0, '设置班级课程', 150, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376514, 1093809448598376513, 'formSetClassCourse:formSetClassCourse', 1, '设置班级课程', 0, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376515, 1093809448598376514, 'formSetClassCourse:formSetClassCourse:addClassCourse', 2, '添加', 0, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376516, NULL, 'formCourseStats', 0, '课程统计', 160, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376517, 1093809448598376516, 'formCourseStats:formCourseStats', 1, '课程统计', 0, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376518, NULL, 'formStudentActionStats', 0, '学生行为统计', 170, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376519, 1093809448598376518, 'formStudentActionStats:formStudentActionStats', 1, '学生行为统计', 0, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376520, 1093809448598376519, 'formStudentActionStats:formStudentActionStats:formBuyCourseDetail', 2, '学生行为详情', 0, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376521, 1093809448598376519, 'formStudentActionStats:formStudentActionStats:formBuyVideoDetail', 2, '学生行为详情', 10, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376522, 1093809448598376519, 'formStudentActionStats:formStudentActionStats:formBuyFlowerDetail', 2, '学生行为详情', 20, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376523, 1093809448598376519, 'formStudentActionStats:formStudentActionStats:formBuyPaperDetail', 2, '学生行为详情', 30, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376524, 1093809448598376519, 'formStudentActionStats:formStudentActionStats:formBuyCoinDetail', 2, '学生行为详情', 40, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376525, 1093809448598376519, 'formStudentActionStats:formStudentActionStats:formDoCourseDetail', 2, '学生行为详情', 50, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376526, 1093809448598376519, 'formStudentActionStats:formStudentActionStats:formWatchVideoDetail', 2, '学生行为详情', 60, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376527, 1093809448598376519, 'formStudentActionStats:formStudentActionStats:formRfreshDetail', 2, '学生行为详情', 70, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376528, NULL, 'formStudentActionDetail', 0, '学生行为详情', 180, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376529, 1093809448598376528, 'formStudentActionDetail:formStudentActionDetail', 1, '学生行为详情', 0, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376537, NULL, 'formSysUser', 0, '用户管理', 10000, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376538, 1093809448598376537, 'formSysUser:fragmentSysUser', 1, '用户管理', 1, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376539, 1093809448598376538, 'formSysUser:fragmentSysUser:add', 2, '新增', 1, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376540, 1093809448598376538, 'formSysUser:fragmentSysUser:update', 2, '编辑', 2, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376541, 1093809448598376538, 'formSysUser:fragmentSysUser:delete', 2, '删除', 3, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376542, 1093809448598376538, 'formSysUser:fragmentSysUser:resetPassword', 2, '重置密码', 4, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376563, NULL, 'formSysRole', 0, '角色管理', 10200, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376564, 1093809448598376563, 'formSysRole:fragmentSysRole', 1, '角色管理', 1, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376565, 1093809448598376563, 'formSysRole:fragmentSysRoleUser', 1, '用户授权', 2, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376566, 1093809448598376564, 'formSysRole:fragmentSysRole:add', 2, '新增', 1, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376567, 1093809448598376564, 'formSysRole:fragmentSysRole:update', 2, '编辑', 2, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376568, 1093809448598376564, 'formSysRole:fragmentSysRole:delete', 2, '删除', 3, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376569, 1093809448598376565, 'formSysRole:fragmentSysRoleUser:addUserRole', 2, '授权用户', 1, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376570, 1093809448598376565, 'formSysRole:fragmentSysRoleUser:deleteUserRole', 2, '移除用户', 2, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376577, NULL, 'formSysMenu', 0, '菜单管理', 10600, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376578, 1093809448598376577, 'formSysMenu:fragmentSysMenu', 1, '菜单管理', 1, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376579, 1093809448598376578, 'formSysMenu:fragmentSysMenu:add', 2, '新增', 1, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376580, 1093809448598376578, 'formSysMenu:fragmentSysMenu:update', 2, '编辑', 2, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376581, 1093809448598376578, 'formSysMenu:fragmentSysMenu:delete', 2, '删除', 3, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376582, 1093809448598376578, 'formSysMenu:fragmentSysMenu:listMenuPerm', 2, '权限列表', 4, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376588, NULL, 'formSysPermCode', 0, '权限字管理', 10700, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376589, 1093809448598376588, 'formSysPermCode:fragmentSysPermCode', 1, '权限字管理', 1, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376590, 1093809448598376589, 'formSysPermCode:fragmentSysPermCode:add', 2, '新增', 1, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376591, 1093809448598376589, 'formSysPermCode:fragmentSysPermCode:update', 2, '编辑', 2, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376592, 1093809448598376589, 'formSysPermCode:fragmentSysPermCode:delete', 2, '删除', 3, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376601, NULL, 'formSysPerm', 0, '权限管理', 10800, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376602, 1093809448598376601, 'formSysPerm:fragmentSysPerm', 1, '权限管理', 1, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376603, 1093809448598376602, 'formSysPerm:fragmentSysPerm:addPermModule', 2, '新增模块', 1, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376604, 1093809448598376602, 'formSysPerm:fragmentSysPerm:updatePermModule', 2, '编辑模块', 2, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376605, 1093809448598376602, 'formSysPerm:fragmentSysPerm:deletePermModule', 2, '删除模块', 3, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376606, 1093809448598376602, 'formSysPerm:fragmentSysPerm:addPerm', 2, '新增权限', 4, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376607, 1093809448598376602, 'formSysPerm:fragmentSysPerm:updatePerm', 2, '编辑权限', 5, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376608, 1093809448598376602, 'formSysPerm:fragmentSysPerm:deletePerm', 2, '删除权限', 6, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376615, NULL, 'formSysDict', 0, '字典管理', 10900, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376616, 1093809448598376615, 'formSysDict:fragmentSysDict', 1, '字典管理', 1, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376617, 1093809448598376616, 'formSysDict:fragmentSysDict:add', 2, '新增', 1, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376618, 1093809448598376616, 'formSysDict:fragmentSysDict:update', 2, '编辑', 2, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376619, 1093809448598376616, 'formSysDict:fragmentSysDict:delete', 2, '删除', 3, CURDATE(), 1); +INSERT INTO `zz_sys_perm_code` VALUES (1093809448598376620, 1093809448598376616, 'formSysDict:fragmentSysDict:reloadCache', 2, '同步缓存', 4, CURDATE(), 1); +COMMIT; + +-- ---------------------------- +-- Table structure for zz_sys_perm_code_perm +-- ---------------------------- +DROP TABLE IF EXISTS `zz_sys_perm_code_perm`; +CREATE TABLE `zz_sys_perm_code_perm` ( + `perm_code_id` bigint(20) NOT NULL COMMENT '权限字Id', + `perm_id` bigint(20) NOT NULL COMMENT '权限id', + PRIMARY KEY (`perm_code_id`,`perm_id`), + KEY `idx_perm_id` (`perm_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin ROW_FORMAT=COMPACT COMMENT='系统权限字和权限资源关联表'; + +-- ---------------------------- +-- Records of zz_sys_perm_code_perm +-- ---------------------------- +BEGIN; +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376482, 1093809448569016321); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376486, 1093809448569016322); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376478, 1093809448569016323); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376475, 1093809448569016324); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376484, 1093809448569016326); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376482, 1093809448569016328); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376486, 1093809448569016328); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376475, 1093809448569016329); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376484, 1093809448569016329); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376456, 1093809448569016331); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376460, 1093809448569016332); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376452, 1093809448569016333); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376449, 1093809448569016334); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376458, 1093809448569016336); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376469, 1093809448569016340); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376473, 1093809448569016340); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376465, 1093809448569016341); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376462, 1093809448569016342); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376539, 1093809448569016347); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376540, 1093809448569016348); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376541, 1093809448569016349); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376538, 1093809448569016350); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376538, 1093809448569016351); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376540, 1093809448569016352); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376540, 1093809448569016353); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376542, 1093809448569016354); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376497, 1093809448569016356); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376501, 1093809448569016357); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376493, 1093809448569016358); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376488, 1093809448569016359); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376499, 1093809448569016361); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376515, 1093809448569016363); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376509, 1093809448569016364); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376507, 1093809448569016365); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376514, 1093809448569016366); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376512, 1093809448569016367); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376505, 1093809448569016368); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376503, 1093809448569016369); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376511, 1093809448569016370); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376517, 1093809448569016372); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376517, 1093809448569016373); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376519, 1093809448569016378); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376519, 1093809448569016379); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376529, 1093809448569016387); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376566, 1093809448569016392); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376567, 1093809448569016393); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376568, 1093809448569016394); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376539, 1093809448569016395); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376540, 1093809448569016395); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376564, 1093809448569016395); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376567, 1093809448569016396); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376569, 1093809448569016397); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376570, 1093809448569016398); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376565, 1093809448569016399); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376569, 1093809448569016400); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376579, 1093809448569016402); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376580, 1093809448569016403); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376581, 1093809448569016404); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376566, 1093809448569016405); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376567, 1093809448569016405); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376578, 1093809448569016405); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376580, 1093809448569016406); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376582, 1093809448569016407); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376590, 1093809448569016409); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376591, 1093809448569016410); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376592, 1093809448569016411); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376579, 1093809448569016412); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376580, 1093809448569016412); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376589, 1093809448569016412); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376591, 1093809448569016413); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376603, 1093809448569016415); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376604, 1093809448569016416); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376605, 1093809448569016417); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376602, 1093809448569016418); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376590, 1093809448569016419); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376591, 1093809448569016419); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376602, 1093809448569016419); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376606, 1093809448569016421); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376607, 1093809448569016422); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376608, 1093809448569016423); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376602, 1093809448569016424); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376607, 1093809448569016425); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376616, 1093809448569016428); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376616, 1093809448569016429); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376616, 1093809448569016430); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376616, 1093809448569016431); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376616, 1093809448569016433); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376616, 1093809448569016434); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376616, 1093809448569016435); +INSERT INTO `zz_sys_perm_code_perm` VALUES (1093809448598376616, 1093809448569016436); +COMMIT; + +-- ---------------------------- +-- Table structure for zz_sys_perm_module +-- ---------------------------- +DROP TABLE IF EXISTS `zz_sys_perm_module`; +CREATE TABLE `zz_sys_perm_module` ( + `module_id` bigint(20) NOT NULL COMMENT '权限模块id', + `parent_id` bigint(20) DEFAULT '0' COMMENT '上级权限模块id', + `module_name` varchar(64) COLLATE utf8mb4_bin NOT NULL DEFAULT '' COMMENT '权限模块名称', + `module_type` int(11) NOT NULL COMMENT '模块类型(0: 普通模块 1: Controller模块)', + `show_order` int(11) NOT NULL DEFAULT '0' COMMENT '权限模块在当前层级下的顺序,由小到大', + `create_time` datetime NOT NULL COMMENT '创建时间', + `deleted_flag` int(11) NOT NULL COMMENT '逻辑删除标记(1: 正常 -1: 已删除)', + PRIMARY KEY (`module_id`) USING BTREE, + KEY `idx_show_order` (`show_order`) USING BTREE, + KEY `idx_parent_id` (`parent_id`) USING BTREE, + KEY `idx_module_type` (`module_type`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin ROW_FORMAT=COMPACT COMMENT='系统权限模块表'; + +-- ---------------------------- +-- Records of zz_sys_perm_module +-- ---------------------------- +BEGIN; +INSERT INTO `zz_sys_perm_module` VALUES (1093376634891538435, NULL, '用户权限', 0, 1, CURDATE(), 1); +INSERT INTO `zz_sys_perm_module` VALUES (1093376634933481472, NULL, '系统配置', 0, 2, CURDATE(), 1); +INSERT INTO `zz_sys_perm_module` VALUES (1093376634933481473, NULL, '缺省分组', 0, 3, CURDATE(), 1); +INSERT INTO `zz_sys_perm_module` VALUES (1093809448569016320, 1093376634933481473, '课程数据', 1, 0, CURDATE(), 1); +INSERT INTO `zz_sys_perm_module` VALUES (1093809448569016330, 1093376634933481473, '校区数据', 1, 5, CURDATE(), 1); +INSERT INTO `zz_sys_perm_module` VALUES (1093809448569016338, 1093376634933481473, '学生数据', 1, 10, CURDATE(), 1); +INSERT INTO `zz_sys_perm_module` VALUES (1093809448569016346, 1093376634891538435, '用户管理', 1, 0, CURDATE(), 1); +INSERT INTO `zz_sys_perm_module` VALUES (1093809448569016355, 1093376634933481473, '班级数据', 1, 15, CURDATE(), 1); +INSERT INTO `zz_sys_perm_module` VALUES (1093809448569016371, 1093376634933481473, '课程统计', 1, 20, CURDATE(), 1); +INSERT INTO `zz_sys_perm_module` VALUES (1093809448569016377, 1093376634933481473, '学生行为统计', 1, 25, CURDATE(), 1); +INSERT INTO `zz_sys_perm_module` VALUES (1093809448569016383, 1093376634933481473, '学生行为流水', 1, 30, CURDATE(), 1); +INSERT INTO `zz_sys_perm_module` VALUES (1093809448569016391, 1093376634891538435, '角色管理', 1, 10, CURDATE(), 1); +INSERT INTO `zz_sys_perm_module` VALUES (1093809448569016401, 1093376634891538435, '菜单管理', 1, 15, CURDATE(), 1); +INSERT INTO `zz_sys_perm_module` VALUES (1093809448569016408, 1093376634891538435, '权限字管理', 1, 20, CURDATE(), 1); +INSERT INTO `zz_sys_perm_module` VALUES (1093809448569016414, 1093376634891538435, '权限模块管理', 1, 25, CURDATE(), 1); +INSERT INTO `zz_sys_perm_module` VALUES (1093809448569016420, 1093376634891538435, '权限资源管理', 1, 30, CURDATE(), 1); +INSERT INTO `zz_sys_perm_module` VALUES (1093809448569016426, 1093376634933481472, '字典管理', 0, 1, CURDATE(), 1); +INSERT INTO `zz_sys_perm_module` VALUES (1093809448569016427, 1093809448569016426, '行政区划', 1, 1, CURDATE(), 1); +INSERT INTO `zz_sys_perm_module` VALUES (1093809448569016432, 1093809448569016426, '年级', 1, 2, CURDATE(), 1); +COMMIT; + +-- ---------------------------- +-- Table structure for zz_sys_perm_whitelist +-- ---------------------------- +DROP TABLE IF EXISTS `zz_sys_perm_whitelist`; +CREATE TABLE `zz_sys_perm_whitelist` ( + `perm_url` varchar(512) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '权限资源的url', + `module_name` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '权限资源所属模块名字(通常是Controller的名字)', + `perm_name` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '权限的名称', + PRIMARY KEY (`perm_url`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='权限资源白名单表(认证用户均可访问的url资源)'; + +-- ---------------------------- +-- Records of zz_sys_perm_whitelist +-- ---------------------------- +BEGIN; +INSERT INTO `zz_sys_perm_whitelist` VALUES ('/admin/CourseClass/areaCode/listDictAreaCode', '行政区划', '行政区划列表'); +INSERT INTO `zz_sys_perm_whitelist` VALUES ('/admin/CourseClass/areaCode/listDictAreaCodeByParentId', '行政区划', '行政区划过滤列表'); +INSERT INTO `zz_sys_perm_whitelist` VALUES ('/admin/CourseClass/course/listDictCourse', '课程数据', '课程字典列表'); +INSERT INTO `zz_sys_perm_whitelist` VALUES ('/admin/CourseClass/grade/listDictGrade', '年级', '字典列表'); +INSERT INTO `zz_sys_perm_whitelist` VALUES ('/admin/CourseClass/schoolInfo/listDictSchoolInfo', '校区数据', '校区字典列表'); +INSERT INTO `zz_sys_perm_whitelist` VALUES ('/admin/CourseClass/student/listDictStudent', '学生数据', '学生字典列表'); +INSERT INTO `zz_sys_perm_whitelist` VALUES ('/admin/login/doLogout', '登录模块', '退出登陆'); +COMMIT; + +-- ---------------------------- +-- Table structure for zz_sys_role +-- ---------------------------- +DROP TABLE IF EXISTS `zz_sys_role`; +CREATE TABLE `zz_sys_role` ( + `role_id` bigint(20) NOT NULL COMMENT '主键Id', + `role_name` varchar(64) COLLATE utf8mb4_bin NOT NULL COMMENT '角色名称', + `create_user_id` bigint(20) NOT NULL COMMENT '创建者', + `create_username` varchar(64) COLLATE utf8mb4_bin NOT NULL COMMENT '创建用户显示名', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_time` datetime NOT NULL COMMENT '更新时间', + `deleted_flag` int(11) NOT NULL COMMENT '逻辑删除标记(1: 正常 -1: 已删除)', + PRIMARY KEY (`role_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin ROW_FORMAT=COMPACT COMMENT='系统角色表'; + +-- ---------------------------- +-- Table structure for zz_sys_role_menu +-- ---------------------------- +DROP TABLE IF EXISTS `zz_sys_role_menu`; +CREATE TABLE `zz_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`) USING BTREE, + KEY `idx_menu_id` (`menu_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin ROW_FORMAT=COMPACT COMMENT='角色与菜单对应关系表'; + +-- ---------------------------- +-- Table structure for zz_sys_user +-- ---------------------------- +DROP TABLE IF EXISTS `zz_sys_user`; +CREATE TABLE `zz_sys_user` ( + `user_id` bigint(20) NOT NULL COMMENT '主键Id', + `login_name` varchar(64) COLLATE utf8mb4_bin NOT NULL COMMENT '用户登录名称', + `password` varchar(64) COLLATE utf8mb4_bin NOT NULL COMMENT '密码', + `show_name` varchar(32) COLLATE utf8mb4_bin NOT NULL COMMENT '用户显示名称', + `user_type` int(11) NOT NULL COMMENT '用户类型(0: 管理员 1: 系统管理用户 2: 系统业务用户)', + `head_image_url` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '用户头像的Url', + `user_status` int(11) NOT NULL COMMENT '状态(0: 正常 1: 锁定)', + `create_user_id` bigint(20) NOT NULL COMMENT '创建者', + `create_username` varchar(64) COLLATE utf8mb4_bin NOT NULL COMMENT '创建用户名', + `create_time` datetime NOT NULL COMMENT '创建时间', + `update_time` datetime NOT NULL COMMENT '最后更新时间', + `deleted_flag` int(11) NOT NULL COMMENT '删除标记(1: 正常 -1: 已删除)', + PRIMARY KEY (`user_id`) USING BTREE, + UNIQUE KEY `uk_login_name` (`login_name`) USING BTREE, + KEY `idx_status` (`user_status`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin ROW_FORMAT=COMPACT COMMENT='系统用户表'; + +-- ---------------------------- +-- Records of zz_sys_user +-- ---------------------------- +BEGIN; +INSERT INTO `zz_sys_user` VALUES (1093809448606765057, 'admin', '$2a$10$gvX5Jvv.AF3rKA7H0AVrCu8gQ2v6zPKvUazqRzAEwE1JabSUz9FFm', '管理员', 0, 'CHANGE TO YOUR HEAD IMAGE URL!!!', 0, 1093809448606765057, '管理员', CURDATE(), CURDATE(), 1); +COMMIT; + +-- ---------------------------- +-- Table structure for zz_sys_user_role +-- ---------------------------- +DROP TABLE IF EXISTS `zz_sys_user_role`; +CREATE TABLE `zz_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`) USING BTREE, + KEY `idx_role_id` (`role_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin ROW_FORMAT=COMPACT COMMENT='用户与角色对应关系表'; + +-- ---------------------------- +-- Table structure for zz_area_code +-- ---------------------------- +DROP TABLE IF EXISTS `zz_area_code`; +CREATE TABLE `zz_area_code` ( + `area_id` bigint(20) unsigned NOT NULL COMMENT '行政区划主键Id', + `area_name` varchar(128) COLLATE utf8mb4_bin NOT NULL DEFAULT '' COMMENT '行政区划名称', + `area_level` int(11) NOT NULL COMMENT '行政区划级别 (1: 省级别 2: 市级别 3: 区级别)', + `parent_id` bigint(20) DEFAULT NULL COMMENT '父级行政区划Id', + PRIMARY KEY (`area_id`) USING BTREE, + KEY `idx_level` (`area_level`) USING BTREE, + KEY `idx_area_name` (`area_name`) USING BTREE, + KEY `idx_parent_id` (`parent_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='行政区划表'; + +-- ---------------------------- +-- Records of zz_area_code +-- ---------------------------- +BEGIN; +INSERT INTO `zz_area_code` VALUES (110000000000, '北京市', 1, NULL); +INSERT INTO `zz_area_code` VALUES (110100000000, '市辖区', 2, 110000000000); +INSERT INTO `zz_area_code` VALUES (110101000000, '东城区', 3, 110100000000); +INSERT INTO `zz_area_code` VALUES (110102000000, '西城区', 3, 110100000000); +INSERT INTO `zz_area_code` VALUES (110105000000, '朝阳区', 3, 110100000000); +INSERT INTO `zz_area_code` VALUES (110106000000, '丰台区', 3, 110100000000); +INSERT INTO `zz_area_code` VALUES (110107000000, '石景山区', 3, 110100000000); +INSERT INTO `zz_area_code` VALUES (110108000000, '海淀区', 3, 110100000000); +INSERT INTO `zz_area_code` VALUES (110109000000, '门头沟区', 3, 110100000000); +INSERT INTO `zz_area_code` VALUES (110111000000, '房山区', 3, 110100000000); +INSERT INTO `zz_area_code` VALUES (110112000000, '通州区', 3, 110100000000); +INSERT INTO `zz_area_code` VALUES (110113000000, '顺义区', 3, 110100000000); +INSERT INTO `zz_area_code` VALUES (110114000000, '昌平区', 3, 110100000000); +INSERT INTO `zz_area_code` VALUES (110115000000, '大兴区', 3, 110100000000); +INSERT INTO `zz_area_code` VALUES (110116000000, '怀柔区', 3, 110100000000); +INSERT INTO `zz_area_code` VALUES (110117000000, '平谷区', 3, 110100000000); +INSERT INTO `zz_area_code` VALUES (110118000000, '密云区', 3, 110100000000); +INSERT INTO `zz_area_code` VALUES (110119000000, '延庆区', 3, 110100000000); +INSERT INTO `zz_area_code` VALUES (120000000000, '天津市', 1, NULL); +INSERT INTO `zz_area_code` VALUES (120100000000, '市辖区', 2, 120000000000); +INSERT INTO `zz_area_code` VALUES (120101000000, '和平区', 3, 120100000000); +INSERT INTO `zz_area_code` VALUES (120102000000, '河东区', 3, 120100000000); +INSERT INTO `zz_area_code` VALUES (120103000000, '河西区', 3, 120100000000); +INSERT INTO `zz_area_code` VALUES (120104000000, '南开区', 3, 120100000000); +INSERT INTO `zz_area_code` VALUES (120105000000, '河北区', 3, 120100000000); +INSERT INTO `zz_area_code` VALUES (120106000000, '红桥区', 3, 120100000000); +INSERT INTO `zz_area_code` VALUES (120110000000, '东丽区', 3, 120100000000); +INSERT INTO `zz_area_code` VALUES (120111000000, '西青区', 3, 120100000000); +INSERT INTO `zz_area_code` VALUES (120112000000, '津南区', 3, 120100000000); +INSERT INTO `zz_area_code` VALUES (120113000000, '北辰区', 3, 120100000000); +INSERT INTO `zz_area_code` VALUES (120114000000, '武清区', 3, 120100000000); +INSERT INTO `zz_area_code` VALUES (120115000000, '宝坻区', 3, 120100000000); +INSERT INTO `zz_area_code` VALUES (120116000000, '滨海新区', 3, 120100000000); +INSERT INTO `zz_area_code` VALUES (120117000000, '宁河区', 3, 120100000000); +INSERT INTO `zz_area_code` VALUES (120118000000, '静海区', 3, 120100000000); +INSERT INTO `zz_area_code` VALUES (120119000000, '蓟州区', 3, 120100000000); +INSERT INTO `zz_area_code` VALUES (130000000000, '河北省', 1, NULL); +INSERT INTO `zz_area_code` VALUES (130100000000, '石家庄市', 2, 130000000000); +INSERT INTO `zz_area_code` VALUES (130101000000, '市辖区', 3, 130100000000); +INSERT INTO `zz_area_code` VALUES (130102000000, '长安区', 3, 130100000000); +INSERT INTO `zz_area_code` VALUES (130104000000, '桥西区', 3, 130100000000); +INSERT INTO `zz_area_code` VALUES (130105000000, '新华区', 3, 130100000000); +INSERT INTO `zz_area_code` VALUES (130107000000, '井陉矿区', 3, 130100000000); +INSERT INTO `zz_area_code` VALUES (130108000000, '裕华区', 3, 130100000000); +INSERT INTO `zz_area_code` VALUES (130109000000, '藁城区', 3, 130100000000); +INSERT INTO `zz_area_code` VALUES (130110000000, '鹿泉区', 3, 130100000000); +INSERT INTO `zz_area_code` VALUES (130111000000, '栾城区', 3, 130100000000); +INSERT INTO `zz_area_code` VALUES (130121000000, '井陉县', 3, 130100000000); +INSERT INTO `zz_area_code` VALUES (130123000000, '正定县', 3, 130100000000); +INSERT INTO `zz_area_code` VALUES (130125000000, '行唐县', 3, 130100000000); +INSERT INTO `zz_area_code` VALUES (130126000000, '灵寿县', 3, 130100000000); +INSERT INTO `zz_area_code` VALUES (130127000000, '高邑县', 3, 130100000000); +INSERT INTO `zz_area_code` VALUES (130128000000, '深泽县', 3, 130100000000); +INSERT INTO `zz_area_code` VALUES (130129000000, '赞皇县', 3, 130100000000); +INSERT INTO `zz_area_code` VALUES (130130000000, '无极县', 3, 130100000000); +INSERT INTO `zz_area_code` VALUES (130131000000, '平山县', 3, 130100000000); +INSERT INTO `zz_area_code` VALUES (130132000000, '元氏县', 3, 130100000000); +INSERT INTO `zz_area_code` VALUES (130133000000, '赵县', 3, 130100000000); +INSERT INTO `zz_area_code` VALUES (130171000000, '石家庄高新技术产业开发区', 3, 130100000000); +INSERT INTO `zz_area_code` VALUES (130172000000, '石家庄循环化工园区', 3, 130100000000); +INSERT INTO `zz_area_code` VALUES (130181000000, '辛集市', 3, 130100000000); +INSERT INTO `zz_area_code` VALUES (130183000000, '晋州市', 3, 130100000000); +INSERT INTO `zz_area_code` VALUES (130184000000, '新乐市', 3, 130100000000); +INSERT INTO `zz_area_code` VALUES (130200000000, '唐山市', 2, 130000000000); +INSERT INTO `zz_area_code` VALUES (130201000000, '市辖区', 3, 130200000000); +INSERT INTO `zz_area_code` VALUES (130202000000, '路南区', 3, 130200000000); +INSERT INTO `zz_area_code` VALUES (130203000000, '路北区', 3, 130200000000); +INSERT INTO `zz_area_code` VALUES (130204000000, '古冶区', 3, 130200000000); +INSERT INTO `zz_area_code` VALUES (130205000000, '开平区', 3, 130200000000); +INSERT INTO `zz_area_code` VALUES (130207000000, '丰南区', 3, 130200000000); +INSERT INTO `zz_area_code` VALUES (130208000000, '丰润区', 3, 130200000000); +INSERT INTO `zz_area_code` VALUES (130209000000, '曹妃甸区', 3, 130200000000); +INSERT INTO `zz_area_code` VALUES (130224000000, '滦南县', 3, 130200000000); +INSERT INTO `zz_area_code` VALUES (130225000000, '乐亭县', 3, 130200000000); +INSERT INTO `zz_area_code` VALUES (130227000000, '迁西县', 3, 130200000000); +INSERT INTO `zz_area_code` VALUES (130229000000, '玉田县', 3, 130200000000); +INSERT INTO `zz_area_code` VALUES (130271000000, '唐山市芦台经济技术开发区', 3, 130200000000); +INSERT INTO `zz_area_code` VALUES (130272000000, '唐山市汉沽管理区', 3, 130200000000); +INSERT INTO `zz_area_code` VALUES (130273000000, '唐山高新技术产业开发区', 3, 130200000000); +INSERT INTO `zz_area_code` VALUES (130274000000, '河北唐山海港经济开发区', 3, 130200000000); +INSERT INTO `zz_area_code` VALUES (130281000000, '遵化市', 3, 130200000000); +INSERT INTO `zz_area_code` VALUES (130283000000, '迁安市', 3, 130200000000); +INSERT INTO `zz_area_code` VALUES (130284000000, '滦州市', 3, 130200000000); +INSERT INTO `zz_area_code` VALUES (130300000000, '秦皇岛市', 2, 130000000000); +INSERT INTO `zz_area_code` VALUES (130301000000, '市辖区', 3, 130300000000); +INSERT INTO `zz_area_code` VALUES (130302000000, '海港区', 3, 130300000000); +INSERT INTO `zz_area_code` VALUES (130303000000, '山海关区', 3, 130300000000); +INSERT INTO `zz_area_code` VALUES (130304000000, '北戴河区', 3, 130300000000); +INSERT INTO `zz_area_code` VALUES (130306000000, '抚宁区', 3, 130300000000); +INSERT INTO `zz_area_code` VALUES (130321000000, '青龙满族自治县', 3, 130300000000); +INSERT INTO `zz_area_code` VALUES (130322000000, '昌黎县', 3, 130300000000); +INSERT INTO `zz_area_code` VALUES (130324000000, '卢龙县', 3, 130300000000); +INSERT INTO `zz_area_code` VALUES (130371000000, '秦皇岛市经济技术开发区', 3, 130300000000); +INSERT INTO `zz_area_code` VALUES (130372000000, '北戴河新区', 3, 130300000000); +INSERT INTO `zz_area_code` VALUES (130400000000, '邯郸市', 2, 130000000000); +INSERT INTO `zz_area_code` VALUES (130401000000, '市辖区', 3, 130400000000); +INSERT INTO `zz_area_code` VALUES (130402000000, '邯山区', 3, 130400000000); +INSERT INTO `zz_area_code` VALUES (130403000000, '丛台区', 3, 130400000000); +INSERT INTO `zz_area_code` VALUES (130404000000, '复兴区', 3, 130400000000); +INSERT INTO `zz_area_code` VALUES (130406000000, '峰峰矿区', 3, 130400000000); +INSERT INTO `zz_area_code` VALUES (130407000000, '肥乡区', 3, 130400000000); +INSERT INTO `zz_area_code` VALUES (130408000000, '永年区', 3, 130400000000); +INSERT INTO `zz_area_code` VALUES (130423000000, '临漳县', 3, 130400000000); +INSERT INTO `zz_area_code` VALUES (130424000000, '成安县', 3, 130400000000); +INSERT INTO `zz_area_code` VALUES (130425000000, '大名县', 3, 130400000000); +INSERT INTO `zz_area_code` VALUES (130426000000, '涉县', 3, 130400000000); +INSERT INTO `zz_area_code` VALUES (130427000000, '磁县', 3, 130400000000); +INSERT INTO `zz_area_code` VALUES (130430000000, '邱县', 3, 130400000000); +INSERT INTO `zz_area_code` VALUES (130431000000, '鸡泽县', 3, 130400000000); +INSERT INTO `zz_area_code` VALUES (130432000000, '广平县', 3, 130400000000); +INSERT INTO `zz_area_code` VALUES (130433000000, '馆陶县', 3, 130400000000); +INSERT INTO `zz_area_code` VALUES (130434000000, '魏县', 3, 130400000000); +INSERT INTO `zz_area_code` VALUES (130435000000, '曲周县', 3, 130400000000); +INSERT INTO `zz_area_code` VALUES (130471000000, '邯郸经济技术开发区', 3, 130400000000); +INSERT INTO `zz_area_code` VALUES (130473000000, '邯郸冀南新区', 3, 130400000000); +INSERT INTO `zz_area_code` VALUES (130481000000, '武安市', 3, 130400000000); +INSERT INTO `zz_area_code` VALUES (130500000000, '邢台市', 2, 130000000000); +INSERT INTO `zz_area_code` VALUES (130501000000, '市辖区', 3, 130500000000); +INSERT INTO `zz_area_code` VALUES (130502000000, '桥东区', 3, 130500000000); +INSERT INTO `zz_area_code` VALUES (130503000000, '桥西区', 3, 130500000000); +INSERT INTO `zz_area_code` VALUES (130521000000, '邢台县', 3, 130500000000); +INSERT INTO `zz_area_code` VALUES (130522000000, '临城县', 3, 130500000000); +INSERT INTO `zz_area_code` VALUES (130523000000, '内丘县', 3, 130500000000); +INSERT INTO `zz_area_code` VALUES (130524000000, '柏乡县', 3, 130500000000); +INSERT INTO `zz_area_code` VALUES (130525000000, '隆尧县', 3, 130500000000); +INSERT INTO `zz_area_code` VALUES (130526000000, '任县', 3, 130500000000); +INSERT INTO `zz_area_code` VALUES (130527000000, '南和县', 3, 130500000000); +INSERT INTO `zz_area_code` VALUES (130528000000, '宁晋县', 3, 130500000000); +INSERT INTO `zz_area_code` VALUES (130529000000, '巨鹿县', 3, 130500000000); +INSERT INTO `zz_area_code` VALUES (130530000000, '新河县', 3, 130500000000); +INSERT INTO `zz_area_code` VALUES (130531000000, '广宗县', 3, 130500000000); +INSERT INTO `zz_area_code` VALUES (130532000000, '平乡县', 3, 130500000000); +INSERT INTO `zz_area_code` VALUES (130533000000, '威县', 3, 130500000000); +INSERT INTO `zz_area_code` VALUES (130534000000, '清河县', 3, 130500000000); +INSERT INTO `zz_area_code` VALUES (130535000000, '临西县', 3, 130500000000); +INSERT INTO `zz_area_code` VALUES (130571000000, '河北邢台经济开发区', 3, 130500000000); +INSERT INTO `zz_area_code` VALUES (130581000000, '南宫市', 3, 130500000000); +INSERT INTO `zz_area_code` VALUES (130582000000, '沙河市', 3, 130500000000); +INSERT INTO `zz_area_code` VALUES (130600000000, '保定市', 2, 130000000000); +INSERT INTO `zz_area_code` VALUES (130601000000, '市辖区', 3, 130600000000); +INSERT INTO `zz_area_code` VALUES (130602000000, '竞秀区', 3, 130600000000); +INSERT INTO `zz_area_code` VALUES (130606000000, '莲池区', 3, 130600000000); +INSERT INTO `zz_area_code` VALUES (130607000000, '满城区', 3, 130600000000); +INSERT INTO `zz_area_code` VALUES (130608000000, '清苑区', 3, 130600000000); +INSERT INTO `zz_area_code` VALUES (130609000000, '徐水区', 3, 130600000000); +INSERT INTO `zz_area_code` VALUES (130623000000, '涞水县', 3, 130600000000); +INSERT INTO `zz_area_code` VALUES (130624000000, '阜平县', 3, 130600000000); +INSERT INTO `zz_area_code` VALUES (130626000000, '定兴县', 3, 130600000000); +INSERT INTO `zz_area_code` VALUES (130627000000, '唐县', 3, 130600000000); +INSERT INTO `zz_area_code` VALUES (130628000000, '高阳县', 3, 130600000000); +INSERT INTO `zz_area_code` VALUES (130629000000, '容城县', 3, 130600000000); +INSERT INTO `zz_area_code` VALUES (130630000000, '涞源县', 3, 130600000000); +INSERT INTO `zz_area_code` VALUES (130631000000, '望都县', 3, 130600000000); +INSERT INTO `zz_area_code` VALUES (130632000000, '安新县', 3, 130600000000); +INSERT INTO `zz_area_code` VALUES (130633000000, '易县', 3, 130600000000); +INSERT INTO `zz_area_code` VALUES (130634000000, '曲阳县', 3, 130600000000); +INSERT INTO `zz_area_code` VALUES (130635000000, '蠡县', 3, 130600000000); +INSERT INTO `zz_area_code` VALUES (130636000000, '顺平县', 3, 130600000000); +INSERT INTO `zz_area_code` VALUES (130637000000, '博野县', 3, 130600000000); +INSERT INTO `zz_area_code` VALUES (130638000000, '雄县', 3, 130600000000); +INSERT INTO `zz_area_code` VALUES (130671000000, '保定高新技术产业开发区', 3, 130600000000); +INSERT INTO `zz_area_code` VALUES (130672000000, '保定白沟新城', 3, 130600000000); +INSERT INTO `zz_area_code` VALUES (130681000000, '涿州市', 3, 130600000000); +INSERT INTO `zz_area_code` VALUES (130682000000, '定州市', 3, 130600000000); +INSERT INTO `zz_area_code` VALUES (130683000000, '安国市', 3, 130600000000); +INSERT INTO `zz_area_code` VALUES (130684000000, '高碑店市', 3, 130600000000); +INSERT INTO `zz_area_code` VALUES (130700000000, '张家口市', 2, 130000000000); +INSERT INTO `zz_area_code` VALUES (130701000000, '市辖区', 3, 130700000000); +INSERT INTO `zz_area_code` VALUES (130702000000, '桥东区', 3, 130700000000); +INSERT INTO `zz_area_code` VALUES (130703000000, '桥西区', 3, 130700000000); +INSERT INTO `zz_area_code` VALUES (130705000000, '宣化区', 3, 130700000000); +INSERT INTO `zz_area_code` VALUES (130706000000, '下花园区', 3, 130700000000); +INSERT INTO `zz_area_code` VALUES (130708000000, '万全区', 3, 130700000000); +INSERT INTO `zz_area_code` VALUES (130709000000, '崇礼区', 3, 130700000000); +INSERT INTO `zz_area_code` VALUES (130722000000, '张北县', 3, 130700000000); +INSERT INTO `zz_area_code` VALUES (130723000000, '康保县', 3, 130700000000); +INSERT INTO `zz_area_code` VALUES (130724000000, '沽源县', 3, 130700000000); +INSERT INTO `zz_area_code` VALUES (130725000000, '尚义县', 3, 130700000000); +INSERT INTO `zz_area_code` VALUES (130726000000, '蔚县', 3, 130700000000); +INSERT INTO `zz_area_code` VALUES (130727000000, '阳原县', 3, 130700000000); +INSERT INTO `zz_area_code` VALUES (130728000000, '怀安县', 3, 130700000000); +INSERT INTO `zz_area_code` VALUES (130730000000, '怀来县', 3, 130700000000); +INSERT INTO `zz_area_code` VALUES (130731000000, '涿鹿县', 3, 130700000000); +INSERT INTO `zz_area_code` VALUES (130732000000, '赤城县', 3, 130700000000); +INSERT INTO `zz_area_code` VALUES (130771000000, '张家口市高新技术产业开发区', 3, 130700000000); +INSERT INTO `zz_area_code` VALUES (130772000000, '张家口市察北管理区', 3, 130700000000); +INSERT INTO `zz_area_code` VALUES (130773000000, '张家口市塞北管理区', 3, 130700000000); +INSERT INTO `zz_area_code` VALUES (130800000000, '承德市', 2, 130000000000); +INSERT INTO `zz_area_code` VALUES (130801000000, '市辖区', 3, 130800000000); +INSERT INTO `zz_area_code` VALUES (130802000000, '双桥区', 3, 130800000000); +INSERT INTO `zz_area_code` VALUES (130803000000, '双滦区', 3, 130800000000); +INSERT INTO `zz_area_code` VALUES (130804000000, '鹰手营子矿区', 3, 130800000000); +INSERT INTO `zz_area_code` VALUES (130821000000, '承德县', 3, 130800000000); +INSERT INTO `zz_area_code` VALUES (130822000000, '兴隆县', 3, 130800000000); +INSERT INTO `zz_area_code` VALUES (130824000000, '滦平县', 3, 130800000000); +INSERT INTO `zz_area_code` VALUES (130825000000, '隆化县', 3, 130800000000); +INSERT INTO `zz_area_code` VALUES (130826000000, '丰宁满族自治县', 3, 130800000000); +INSERT INTO `zz_area_code` VALUES (130827000000, '宽城满族自治县', 3, 130800000000); +INSERT INTO `zz_area_code` VALUES (130828000000, '围场满族蒙古族自治县', 3, 130800000000); +INSERT INTO `zz_area_code` VALUES (130871000000, '承德高新技术产业开发区', 3, 130800000000); +INSERT INTO `zz_area_code` VALUES (130881000000, '平泉市', 3, 130800000000); +INSERT INTO `zz_area_code` VALUES (130900000000, '沧州市', 2, 130000000000); +INSERT INTO `zz_area_code` VALUES (130901000000, '市辖区', 3, 130900000000); +INSERT INTO `zz_area_code` VALUES (130902000000, '新华区', 3, 130900000000); +INSERT INTO `zz_area_code` VALUES (130903000000, '运河区', 3, 130900000000); +INSERT INTO `zz_area_code` VALUES (130921000000, '沧县', 3, 130900000000); +INSERT INTO `zz_area_code` VALUES (130922000000, '青县', 3, 130900000000); +INSERT INTO `zz_area_code` VALUES (130923000000, '东光县', 3, 130900000000); +INSERT INTO `zz_area_code` VALUES (130924000000, '海兴县', 3, 130900000000); +INSERT INTO `zz_area_code` VALUES (130925000000, '盐山县', 3, 130900000000); +INSERT INTO `zz_area_code` VALUES (130926000000, '肃宁县', 3, 130900000000); +INSERT INTO `zz_area_code` VALUES (130927000000, '南皮县', 3, 130900000000); +INSERT INTO `zz_area_code` VALUES (130928000000, '吴桥县', 3, 130900000000); +INSERT INTO `zz_area_code` VALUES (130929000000, '献县', 3, 130900000000); +INSERT INTO `zz_area_code` VALUES (130930000000, '孟村回族自治县', 3, 130900000000); +INSERT INTO `zz_area_code` VALUES (130971000000, '河北沧州经济开发区', 3, 130900000000); +INSERT INTO `zz_area_code` VALUES (130972000000, '沧州高新技术产业开发区', 3, 130900000000); +INSERT INTO `zz_area_code` VALUES (130973000000, '沧州渤海新区', 3, 130900000000); +INSERT INTO `zz_area_code` VALUES (130981000000, '泊头市', 3, 130900000000); +INSERT INTO `zz_area_code` VALUES (130982000000, '任丘市', 3, 130900000000); +INSERT INTO `zz_area_code` VALUES (130983000000, '黄骅市', 3, 130900000000); +INSERT INTO `zz_area_code` VALUES (130984000000, '河间市', 3, 130900000000); +INSERT INTO `zz_area_code` VALUES (131000000000, '廊坊市', 2, 130000000000); +INSERT INTO `zz_area_code` VALUES (131001000000, '市辖区', 3, 131000000000); +INSERT INTO `zz_area_code` VALUES (131002000000, '安次区', 3, 131000000000); +INSERT INTO `zz_area_code` VALUES (131003000000, '广阳区', 3, 131000000000); +INSERT INTO `zz_area_code` VALUES (131022000000, '固安县', 3, 131000000000); +INSERT INTO `zz_area_code` VALUES (131023000000, '永清县', 3, 131000000000); +INSERT INTO `zz_area_code` VALUES (131024000000, '香河县', 3, 131000000000); +INSERT INTO `zz_area_code` VALUES (131025000000, '大城县', 3, 131000000000); +INSERT INTO `zz_area_code` VALUES (131026000000, '文安县', 3, 131000000000); +INSERT INTO `zz_area_code` VALUES (131028000000, '大厂回族自治县', 3, 131000000000); +INSERT INTO `zz_area_code` VALUES (131071000000, '廊坊经济技术开发区', 3, 131000000000); +INSERT INTO `zz_area_code` VALUES (131081000000, '霸州市', 3, 131000000000); +INSERT INTO `zz_area_code` VALUES (131082000000, '三河市', 3, 131000000000); +INSERT INTO `zz_area_code` VALUES (131100000000, '衡水市', 2, 130000000000); +INSERT INTO `zz_area_code` VALUES (131101000000, '市辖区', 3, 131100000000); +INSERT INTO `zz_area_code` VALUES (131102000000, '桃城区', 3, 131100000000); +INSERT INTO `zz_area_code` VALUES (131103000000, '冀州区', 3, 131100000000); +INSERT INTO `zz_area_code` VALUES (131121000000, '枣强县', 3, 131100000000); +INSERT INTO `zz_area_code` VALUES (131122000000, '武邑县', 3, 131100000000); +INSERT INTO `zz_area_code` VALUES (131123000000, '武强县', 3, 131100000000); +INSERT INTO `zz_area_code` VALUES (131124000000, '饶阳县', 3, 131100000000); +INSERT INTO `zz_area_code` VALUES (131125000000, '安平县', 3, 131100000000); +INSERT INTO `zz_area_code` VALUES (131126000000, '故城县', 3, 131100000000); +INSERT INTO `zz_area_code` VALUES (131127000000, '景县', 3, 131100000000); +INSERT INTO `zz_area_code` VALUES (131128000000, '阜城县', 3, 131100000000); +INSERT INTO `zz_area_code` VALUES (131171000000, '河北衡水高新技术产业开发区', 3, 131100000000); +INSERT INTO `zz_area_code` VALUES (131172000000, '衡水滨湖新区', 3, 131100000000); +INSERT INTO `zz_area_code` VALUES (131182000000, '深州市', 3, 131100000000); +INSERT INTO `zz_area_code` VALUES (140000000000, '山西省', 1, NULL); +INSERT INTO `zz_area_code` VALUES (140100000000, '太原市', 2, 140000000000); +INSERT INTO `zz_area_code` VALUES (140101000000, '市辖区', 3, 140100000000); +INSERT INTO `zz_area_code` VALUES (140105000000, '小店区', 3, 140100000000); +INSERT INTO `zz_area_code` VALUES (140106000000, '迎泽区', 3, 140100000000); +INSERT INTO `zz_area_code` VALUES (140107000000, '杏花岭区', 3, 140100000000); +INSERT INTO `zz_area_code` VALUES (140108000000, '尖草坪区', 3, 140100000000); +INSERT INTO `zz_area_code` VALUES (140109000000, '万柏林区', 3, 140100000000); +INSERT INTO `zz_area_code` VALUES (140110000000, '晋源区', 3, 140100000000); +INSERT INTO `zz_area_code` VALUES (140121000000, '清徐县', 3, 140100000000); +INSERT INTO `zz_area_code` VALUES (140122000000, '阳曲县', 3, 140100000000); +INSERT INTO `zz_area_code` VALUES (140123000000, '娄烦县', 3, 140100000000); +INSERT INTO `zz_area_code` VALUES (140171000000, '山西转型综合改革示范区', 3, 140100000000); +INSERT INTO `zz_area_code` VALUES (140181000000, '古交市', 3, 140100000000); +INSERT INTO `zz_area_code` VALUES (140200000000, '大同市', 2, 140000000000); +INSERT INTO `zz_area_code` VALUES (140201000000, '市辖区', 3, 140200000000); +INSERT INTO `zz_area_code` VALUES (140212000000, '新荣区', 3, 140200000000); +INSERT INTO `zz_area_code` VALUES (140213000000, '平城区', 3, 140200000000); +INSERT INTO `zz_area_code` VALUES (140214000000, '云冈区', 3, 140200000000); +INSERT INTO `zz_area_code` VALUES (140215000000, '云州区', 3, 140200000000); +INSERT INTO `zz_area_code` VALUES (140221000000, '阳高县', 3, 140200000000); +INSERT INTO `zz_area_code` VALUES (140222000000, '天镇县', 3, 140200000000); +INSERT INTO `zz_area_code` VALUES (140223000000, '广灵县', 3, 140200000000); +INSERT INTO `zz_area_code` VALUES (140224000000, '灵丘县', 3, 140200000000); +INSERT INTO `zz_area_code` VALUES (140225000000, '浑源县', 3, 140200000000); +INSERT INTO `zz_area_code` VALUES (140226000000, '左云县', 3, 140200000000); +INSERT INTO `zz_area_code` VALUES (140271000000, '山西大同经济开发区', 3, 140200000000); +INSERT INTO `zz_area_code` VALUES (140300000000, '阳泉市', 2, 140000000000); +INSERT INTO `zz_area_code` VALUES (140301000000, '市辖区', 3, 140300000000); +INSERT INTO `zz_area_code` VALUES (140302000000, '城区', 3, 140300000000); +INSERT INTO `zz_area_code` VALUES (140303000000, '矿区', 3, 140300000000); +INSERT INTO `zz_area_code` VALUES (140311000000, '郊区', 3, 140300000000); +INSERT INTO `zz_area_code` VALUES (140321000000, '平定县', 3, 140300000000); +INSERT INTO `zz_area_code` VALUES (140322000000, '盂县', 3, 140300000000); +INSERT INTO `zz_area_code` VALUES (140400000000, '长治市', 2, 140000000000); +INSERT INTO `zz_area_code` VALUES (140401000000, '市辖区', 3, 140400000000); +INSERT INTO `zz_area_code` VALUES (140403000000, '潞州区', 3, 140400000000); +INSERT INTO `zz_area_code` VALUES (140404000000, '上党区', 3, 140400000000); +INSERT INTO `zz_area_code` VALUES (140405000000, '屯留区', 3, 140400000000); +INSERT INTO `zz_area_code` VALUES (140406000000, '潞城区', 3, 140400000000); +INSERT INTO `zz_area_code` VALUES (140423000000, '襄垣县', 3, 140400000000); +INSERT INTO `zz_area_code` VALUES (140425000000, '平顺县', 3, 140400000000); +INSERT INTO `zz_area_code` VALUES (140426000000, '黎城县', 3, 140400000000); +INSERT INTO `zz_area_code` VALUES (140427000000, '壶关县', 3, 140400000000); +INSERT INTO `zz_area_code` VALUES (140428000000, '长子县', 3, 140400000000); +INSERT INTO `zz_area_code` VALUES (140429000000, '武乡县', 3, 140400000000); +INSERT INTO `zz_area_code` VALUES (140430000000, '沁县', 3, 140400000000); +INSERT INTO `zz_area_code` VALUES (140431000000, '沁源县', 3, 140400000000); +INSERT INTO `zz_area_code` VALUES (140471000000, '山西长治高新技术产业园区', 3, 140400000000); +INSERT INTO `zz_area_code` VALUES (140500000000, '晋城市', 2, 140000000000); +INSERT INTO `zz_area_code` VALUES (140501000000, '市辖区', 3, 140500000000); +INSERT INTO `zz_area_code` VALUES (140502000000, '城区', 3, 140500000000); +INSERT INTO `zz_area_code` VALUES (140521000000, '沁水县', 3, 140500000000); +INSERT INTO `zz_area_code` VALUES (140522000000, '阳城县', 3, 140500000000); +INSERT INTO `zz_area_code` VALUES (140524000000, '陵川县', 3, 140500000000); +INSERT INTO `zz_area_code` VALUES (140525000000, '泽州县', 3, 140500000000); +INSERT INTO `zz_area_code` VALUES (140581000000, '高平市', 3, 140500000000); +INSERT INTO `zz_area_code` VALUES (140600000000, '朔州市', 2, 140000000000); +INSERT INTO `zz_area_code` VALUES (140601000000, '市辖区', 3, 140600000000); +INSERT INTO `zz_area_code` VALUES (140602000000, '朔城区', 3, 140600000000); +INSERT INTO `zz_area_code` VALUES (140603000000, '平鲁区', 3, 140600000000); +INSERT INTO `zz_area_code` VALUES (140621000000, '山阴县', 3, 140600000000); +INSERT INTO `zz_area_code` VALUES (140622000000, '应县', 3, 140600000000); +INSERT INTO `zz_area_code` VALUES (140623000000, '右玉县', 3, 140600000000); +INSERT INTO `zz_area_code` VALUES (140671000000, '山西朔州经济开发区', 3, 140600000000); +INSERT INTO `zz_area_code` VALUES (140681000000, '怀仁市', 3, 140600000000); +INSERT INTO `zz_area_code` VALUES (140700000000, '晋中市', 2, 140000000000); +INSERT INTO `zz_area_code` VALUES (140701000000, '市辖区', 3, 140700000000); +INSERT INTO `zz_area_code` VALUES (140702000000, '榆次区', 3, 140700000000); +INSERT INTO `zz_area_code` VALUES (140721000000, '榆社县', 3, 140700000000); +INSERT INTO `zz_area_code` VALUES (140722000000, '左权县', 3, 140700000000); +INSERT INTO `zz_area_code` VALUES (140723000000, '和顺县', 3, 140700000000); +INSERT INTO `zz_area_code` VALUES (140724000000, '昔阳县', 3, 140700000000); +INSERT INTO `zz_area_code` VALUES (140725000000, '寿阳县', 3, 140700000000); +INSERT INTO `zz_area_code` VALUES (140726000000, '太谷县', 3, 140700000000); +INSERT INTO `zz_area_code` VALUES (140727000000, '祁县', 3, 140700000000); +INSERT INTO `zz_area_code` VALUES (140728000000, '平遥县', 3, 140700000000); +INSERT INTO `zz_area_code` VALUES (140729000000, '灵石县', 3, 140700000000); +INSERT INTO `zz_area_code` VALUES (140781000000, '介休市', 3, 140700000000); +INSERT INTO `zz_area_code` VALUES (140800000000, '运城市', 2, 140000000000); +INSERT INTO `zz_area_code` VALUES (140801000000, '市辖区', 3, 140800000000); +INSERT INTO `zz_area_code` VALUES (140802000000, '盐湖区', 3, 140800000000); +INSERT INTO `zz_area_code` VALUES (140821000000, '临猗县', 3, 140800000000); +INSERT INTO `zz_area_code` VALUES (140822000000, '万荣县', 3, 140800000000); +INSERT INTO `zz_area_code` VALUES (140823000000, '闻喜县', 3, 140800000000); +INSERT INTO `zz_area_code` VALUES (140824000000, '稷山县', 3, 140800000000); +INSERT INTO `zz_area_code` VALUES (140825000000, '新绛县', 3, 140800000000); +INSERT INTO `zz_area_code` VALUES (140826000000, '绛县', 3, 140800000000); +INSERT INTO `zz_area_code` VALUES (140827000000, '垣曲县', 3, 140800000000); +INSERT INTO `zz_area_code` VALUES (140828000000, '夏县', 3, 140800000000); +INSERT INTO `zz_area_code` VALUES (140829000000, '平陆县', 3, 140800000000); +INSERT INTO `zz_area_code` VALUES (140830000000, '芮城县', 3, 140800000000); +INSERT INTO `zz_area_code` VALUES (140881000000, '永济市', 3, 140800000000); +INSERT INTO `zz_area_code` VALUES (140882000000, '河津市', 3, 140800000000); +INSERT INTO `zz_area_code` VALUES (140900000000, '忻州市', 2, 140000000000); +INSERT INTO `zz_area_code` VALUES (140901000000, '市辖区', 3, 140900000000); +INSERT INTO `zz_area_code` VALUES (140902000000, '忻府区', 3, 140900000000); +INSERT INTO `zz_area_code` VALUES (140921000000, '定襄县', 3, 140900000000); +INSERT INTO `zz_area_code` VALUES (140922000000, '五台县', 3, 140900000000); +INSERT INTO `zz_area_code` VALUES (140923000000, '代县', 3, 140900000000); +INSERT INTO `zz_area_code` VALUES (140924000000, '繁峙县', 3, 140900000000); +INSERT INTO `zz_area_code` VALUES (140925000000, '宁武县', 3, 140900000000); +INSERT INTO `zz_area_code` VALUES (140926000000, '静乐县', 3, 140900000000); +INSERT INTO `zz_area_code` VALUES (140927000000, '神池县', 3, 140900000000); +INSERT INTO `zz_area_code` VALUES (140928000000, '五寨县', 3, 140900000000); +INSERT INTO `zz_area_code` VALUES (140929000000, '岢岚县', 3, 140900000000); +INSERT INTO `zz_area_code` VALUES (140930000000, '河曲县', 3, 140900000000); +INSERT INTO `zz_area_code` VALUES (140931000000, '保德县', 3, 140900000000); +INSERT INTO `zz_area_code` VALUES (140932000000, '偏关县', 3, 140900000000); +INSERT INTO `zz_area_code` VALUES (140971000000, '五台山风景名胜区', 3, 140900000000); +INSERT INTO `zz_area_code` VALUES (140981000000, '原平市', 3, 140900000000); +INSERT INTO `zz_area_code` VALUES (141000000000, '临汾市', 2, 140000000000); +INSERT INTO `zz_area_code` VALUES (141001000000, '市辖区', 3, 141000000000); +INSERT INTO `zz_area_code` VALUES (141002000000, '尧都区', 3, 141000000000); +INSERT INTO `zz_area_code` VALUES (141021000000, '曲沃县', 3, 141000000000); +INSERT INTO `zz_area_code` VALUES (141022000000, '翼城县', 3, 141000000000); +INSERT INTO `zz_area_code` VALUES (141023000000, '襄汾县', 3, 141000000000); +INSERT INTO `zz_area_code` VALUES (141024000000, '洪洞县', 3, 141000000000); +INSERT INTO `zz_area_code` VALUES (141025000000, '古县', 3, 141000000000); +INSERT INTO `zz_area_code` VALUES (141026000000, '安泽县', 3, 141000000000); +INSERT INTO `zz_area_code` VALUES (141027000000, '浮山县', 3, 141000000000); +INSERT INTO `zz_area_code` VALUES (141028000000, '吉县', 3, 141000000000); +INSERT INTO `zz_area_code` VALUES (141029000000, '乡宁县', 3, 141000000000); +INSERT INTO `zz_area_code` VALUES (141030000000, '大宁县', 3, 141000000000); +INSERT INTO `zz_area_code` VALUES (141031000000, '隰县', 3, 141000000000); +INSERT INTO `zz_area_code` VALUES (141032000000, '永和县', 3, 141000000000); +INSERT INTO `zz_area_code` VALUES (141033000000, '蒲县', 3, 141000000000); +INSERT INTO `zz_area_code` VALUES (141034000000, '汾西县', 3, 141000000000); +INSERT INTO `zz_area_code` VALUES (141081000000, '侯马市', 3, 141000000000); +INSERT INTO `zz_area_code` VALUES (141082000000, '霍州市', 3, 141000000000); +INSERT INTO `zz_area_code` VALUES (141100000000, '吕梁市', 2, 140000000000); +INSERT INTO `zz_area_code` VALUES (141101000000, '市辖区', 3, 141100000000); +INSERT INTO `zz_area_code` VALUES (141102000000, '离石区', 3, 141100000000); +INSERT INTO `zz_area_code` VALUES (141121000000, '文水县', 3, 141100000000); +INSERT INTO `zz_area_code` VALUES (141122000000, '交城县', 3, 141100000000); +INSERT INTO `zz_area_code` VALUES (141123000000, '兴县', 3, 141100000000); +INSERT INTO `zz_area_code` VALUES (141124000000, '临县', 3, 141100000000); +INSERT INTO `zz_area_code` VALUES (141125000000, '柳林县', 3, 141100000000); +INSERT INTO `zz_area_code` VALUES (141126000000, '石楼县', 3, 141100000000); +INSERT INTO `zz_area_code` VALUES (141127000000, '岚县', 3, 141100000000); +INSERT INTO `zz_area_code` VALUES (141128000000, '方山县', 3, 141100000000); +INSERT INTO `zz_area_code` VALUES (141129000000, '中阳县', 3, 141100000000); +INSERT INTO `zz_area_code` VALUES (141130000000, '交口县', 3, 141100000000); +INSERT INTO `zz_area_code` VALUES (141181000000, '孝义市', 3, 141100000000); +INSERT INTO `zz_area_code` VALUES (141182000000, '汾阳市', 3, 141100000000); +INSERT INTO `zz_area_code` VALUES (150000000000, '内蒙古自治区', 1, NULL); +INSERT INTO `zz_area_code` VALUES (150100000000, '呼和浩特市', 2, 150000000000); +INSERT INTO `zz_area_code` VALUES (150101000000, '市辖区', 3, 150100000000); +INSERT INTO `zz_area_code` VALUES (150102000000, '新城区', 3, 150100000000); +INSERT INTO `zz_area_code` VALUES (150103000000, '回民区', 3, 150100000000); +INSERT INTO `zz_area_code` VALUES (150104000000, '玉泉区', 3, 150100000000); +INSERT INTO `zz_area_code` VALUES (150105000000, '赛罕区', 3, 150100000000); +INSERT INTO `zz_area_code` VALUES (150121000000, '土默特左旗', 3, 150100000000); +INSERT INTO `zz_area_code` VALUES (150122000000, '托克托县', 3, 150100000000); +INSERT INTO `zz_area_code` VALUES (150123000000, '和林格尔县', 3, 150100000000); +INSERT INTO `zz_area_code` VALUES (150124000000, '清水河县', 3, 150100000000); +INSERT INTO `zz_area_code` VALUES (150125000000, '武川县', 3, 150100000000); +INSERT INTO `zz_area_code` VALUES (150171000000, '呼和浩特金海工业园区', 3, 150100000000); +INSERT INTO `zz_area_code` VALUES (150172000000, '呼和浩特经济技术开发区', 3, 150100000000); +INSERT INTO `zz_area_code` VALUES (150200000000, '包头市', 2, 150000000000); +INSERT INTO `zz_area_code` VALUES (150201000000, '市辖区', 3, 150200000000); +INSERT INTO `zz_area_code` VALUES (150202000000, '东河区', 3, 150200000000); +INSERT INTO `zz_area_code` VALUES (150203000000, '昆都仑区', 3, 150200000000); +INSERT INTO `zz_area_code` VALUES (150204000000, '青山区', 3, 150200000000); +INSERT INTO `zz_area_code` VALUES (150205000000, '石拐区', 3, 150200000000); +INSERT INTO `zz_area_code` VALUES (150206000000, '白云鄂博矿区', 3, 150200000000); +INSERT INTO `zz_area_code` VALUES (150207000000, '九原区', 3, 150200000000); +INSERT INTO `zz_area_code` VALUES (150221000000, '土默特右旗', 3, 150200000000); +INSERT INTO `zz_area_code` VALUES (150222000000, '固阳县', 3, 150200000000); +INSERT INTO `zz_area_code` VALUES (150223000000, '达尔罕茂明安联合旗', 3, 150200000000); +INSERT INTO `zz_area_code` VALUES (150271000000, '包头稀土高新技术产业开发区', 3, 150200000000); +INSERT INTO `zz_area_code` VALUES (150300000000, '乌海市', 2, 150000000000); +INSERT INTO `zz_area_code` VALUES (150301000000, '市辖区', 3, 150300000000); +INSERT INTO `zz_area_code` VALUES (150302000000, '海勃湾区', 3, 150300000000); +INSERT INTO `zz_area_code` VALUES (150303000000, '海南区', 3, 150300000000); +INSERT INTO `zz_area_code` VALUES (150304000000, '乌达区', 3, 150300000000); +INSERT INTO `zz_area_code` VALUES (150400000000, '赤峰市', 2, 150000000000); +INSERT INTO `zz_area_code` VALUES (150401000000, '市辖区', 3, 150400000000); +INSERT INTO `zz_area_code` VALUES (150402000000, '红山区', 3, 150400000000); +INSERT INTO `zz_area_code` VALUES (150403000000, '元宝山区', 3, 150400000000); +INSERT INTO `zz_area_code` VALUES (150404000000, '松山区', 3, 150400000000); +INSERT INTO `zz_area_code` VALUES (150421000000, '阿鲁科尔沁旗', 3, 150400000000); +INSERT INTO `zz_area_code` VALUES (150422000000, '巴林左旗', 3, 150400000000); +INSERT INTO `zz_area_code` VALUES (150423000000, '巴林右旗', 3, 150400000000); +INSERT INTO `zz_area_code` VALUES (150424000000, '林西县', 3, 150400000000); +INSERT INTO `zz_area_code` VALUES (150425000000, '克什克腾旗', 3, 150400000000); +INSERT INTO `zz_area_code` VALUES (150426000000, '翁牛特旗', 3, 150400000000); +INSERT INTO `zz_area_code` VALUES (150428000000, '喀喇沁旗', 3, 150400000000); +INSERT INTO `zz_area_code` VALUES (150429000000, '宁城县', 3, 150400000000); +INSERT INTO `zz_area_code` VALUES (150430000000, '敖汉旗', 3, 150400000000); +INSERT INTO `zz_area_code` VALUES (150500000000, '通辽市', 2, 150000000000); +INSERT INTO `zz_area_code` VALUES (150501000000, '市辖区', 3, 150500000000); +INSERT INTO `zz_area_code` VALUES (150502000000, '科尔沁区', 3, 150500000000); +INSERT INTO `zz_area_code` VALUES (150521000000, '科尔沁左翼中旗', 3, 150500000000); +INSERT INTO `zz_area_code` VALUES (150522000000, '科尔沁左翼后旗', 3, 150500000000); +INSERT INTO `zz_area_code` VALUES (150523000000, '开鲁县', 3, 150500000000); +INSERT INTO `zz_area_code` VALUES (150524000000, '库伦旗', 3, 150500000000); +INSERT INTO `zz_area_code` VALUES (150525000000, '奈曼旗', 3, 150500000000); +INSERT INTO `zz_area_code` VALUES (150526000000, '扎鲁特旗', 3, 150500000000); +INSERT INTO `zz_area_code` VALUES (150571000000, '通辽经济技术开发区', 3, 150500000000); +INSERT INTO `zz_area_code` VALUES (150581000000, '霍林郭勒市', 3, 150500000000); +INSERT INTO `zz_area_code` VALUES (150600000000, '鄂尔多斯市', 2, 150000000000); +INSERT INTO `zz_area_code` VALUES (150601000000, '市辖区', 3, 150600000000); +INSERT INTO `zz_area_code` VALUES (150602000000, '东胜区', 3, 150600000000); +INSERT INTO `zz_area_code` VALUES (150603000000, '康巴什区', 3, 150600000000); +INSERT INTO `zz_area_code` VALUES (150621000000, '达拉特旗', 3, 150600000000); +INSERT INTO `zz_area_code` VALUES (150622000000, '准格尔旗', 3, 150600000000); +INSERT INTO `zz_area_code` VALUES (150623000000, '鄂托克前旗', 3, 150600000000); +INSERT INTO `zz_area_code` VALUES (150624000000, '鄂托克旗', 3, 150600000000); +INSERT INTO `zz_area_code` VALUES (150625000000, '杭锦旗', 3, 150600000000); +INSERT INTO `zz_area_code` VALUES (150626000000, '乌审旗', 3, 150600000000); +INSERT INTO `zz_area_code` VALUES (150627000000, '伊金霍洛旗', 3, 150600000000); +INSERT INTO `zz_area_code` VALUES (150700000000, '呼伦贝尔市', 2, 150000000000); +INSERT INTO `zz_area_code` VALUES (150701000000, '市辖区', 3, 150700000000); +INSERT INTO `zz_area_code` VALUES (150702000000, '海拉尔区', 3, 150700000000); +INSERT INTO `zz_area_code` VALUES (150703000000, '扎赉诺尔区', 3, 150700000000); +INSERT INTO `zz_area_code` VALUES (150721000000, '阿荣旗', 3, 150700000000); +INSERT INTO `zz_area_code` VALUES (150722000000, '莫力达瓦达斡尔族自治旗', 3, 150700000000); +INSERT INTO `zz_area_code` VALUES (150723000000, '鄂伦春自治旗', 3, 150700000000); +INSERT INTO `zz_area_code` VALUES (150724000000, '鄂温克族自治旗', 3, 150700000000); +INSERT INTO `zz_area_code` VALUES (150725000000, '陈巴尔虎旗', 3, 150700000000); +INSERT INTO `zz_area_code` VALUES (150726000000, '新巴尔虎左旗', 3, 150700000000); +INSERT INTO `zz_area_code` VALUES (150727000000, '新巴尔虎右旗', 3, 150700000000); +INSERT INTO `zz_area_code` VALUES (150781000000, '满洲里市', 3, 150700000000); +INSERT INTO `zz_area_code` VALUES (150782000000, '牙克石市', 3, 150700000000); +INSERT INTO `zz_area_code` VALUES (150783000000, '扎兰屯市', 3, 150700000000); +INSERT INTO `zz_area_code` VALUES (150784000000, '额尔古纳市', 3, 150700000000); +INSERT INTO `zz_area_code` VALUES (150785000000, '根河市', 3, 150700000000); +INSERT INTO `zz_area_code` VALUES (150800000000, '巴彦淖尔市', 2, 150000000000); +INSERT INTO `zz_area_code` VALUES (150801000000, '市辖区', 3, 150800000000); +INSERT INTO `zz_area_code` VALUES (150802000000, '临河区', 3, 150800000000); +INSERT INTO `zz_area_code` VALUES (150821000000, '五原县', 3, 150800000000); +INSERT INTO `zz_area_code` VALUES (150822000000, '磴口县', 3, 150800000000); +INSERT INTO `zz_area_code` VALUES (150823000000, '乌拉特前旗', 3, 150800000000); +INSERT INTO `zz_area_code` VALUES (150824000000, '乌拉特中旗', 3, 150800000000); +INSERT INTO `zz_area_code` VALUES (150825000000, '乌拉特后旗', 3, 150800000000); +INSERT INTO `zz_area_code` VALUES (150826000000, '杭锦后旗', 3, 150800000000); +INSERT INTO `zz_area_code` VALUES (150900000000, '乌兰察布市', 2, 150000000000); +INSERT INTO `zz_area_code` VALUES (150901000000, '市辖区', 3, 150900000000); +INSERT INTO `zz_area_code` VALUES (150902000000, '集宁区', 3, 150900000000); +INSERT INTO `zz_area_code` VALUES (150921000000, '卓资县', 3, 150900000000); +INSERT INTO `zz_area_code` VALUES (150922000000, '化德县', 3, 150900000000); +INSERT INTO `zz_area_code` VALUES (150923000000, '商都县', 3, 150900000000); +INSERT INTO `zz_area_code` VALUES (150924000000, '兴和县', 3, 150900000000); +INSERT INTO `zz_area_code` VALUES (150925000000, '凉城县', 3, 150900000000); +INSERT INTO `zz_area_code` VALUES (150926000000, '察哈尔右翼前旗', 3, 150900000000); +INSERT INTO `zz_area_code` VALUES (150927000000, '察哈尔右翼中旗', 3, 150900000000); +INSERT INTO `zz_area_code` VALUES (150928000000, '察哈尔右翼后旗', 3, 150900000000); +INSERT INTO `zz_area_code` VALUES (150929000000, '四子王旗', 3, 150900000000); +INSERT INTO `zz_area_code` VALUES (150981000000, '丰镇市', 3, 150900000000); +INSERT INTO `zz_area_code` VALUES (152200000000, '兴安盟', 2, 150000000000); +INSERT INTO `zz_area_code` VALUES (152201000000, '乌兰浩特市', 3, 152200000000); +INSERT INTO `zz_area_code` VALUES (152202000000, '阿尔山市', 3, 152200000000); +INSERT INTO `zz_area_code` VALUES (152221000000, '科尔沁右翼前旗', 3, 152200000000); +INSERT INTO `zz_area_code` VALUES (152222000000, '科尔沁右翼中旗', 3, 152200000000); +INSERT INTO `zz_area_code` VALUES (152223000000, '扎赉特旗', 3, 152200000000); +INSERT INTO `zz_area_code` VALUES (152224000000, '突泉县', 3, 152200000000); +INSERT INTO `zz_area_code` VALUES (152500000000, '锡林郭勒盟', 2, 150000000000); +INSERT INTO `zz_area_code` VALUES (152501000000, '二连浩特市', 3, 152500000000); +INSERT INTO `zz_area_code` VALUES (152502000000, '锡林浩特市', 3, 152500000000); +INSERT INTO `zz_area_code` VALUES (152522000000, '阿巴嘎旗', 3, 152500000000); +INSERT INTO `zz_area_code` VALUES (152523000000, '苏尼特左旗', 3, 152500000000); +INSERT INTO `zz_area_code` VALUES (152524000000, '苏尼特右旗', 3, 152500000000); +INSERT INTO `zz_area_code` VALUES (152525000000, '东乌珠穆沁旗', 3, 152500000000); +INSERT INTO `zz_area_code` VALUES (152526000000, '西乌珠穆沁旗', 3, 152500000000); +INSERT INTO `zz_area_code` VALUES (152527000000, '太仆寺旗', 3, 152500000000); +INSERT INTO `zz_area_code` VALUES (152528000000, '镶黄旗', 3, 152500000000); +INSERT INTO `zz_area_code` VALUES (152529000000, '正镶白旗', 3, 152500000000); +INSERT INTO `zz_area_code` VALUES (152530000000, '正蓝旗', 3, 152500000000); +INSERT INTO `zz_area_code` VALUES (152531000000, '多伦县', 3, 152500000000); +INSERT INTO `zz_area_code` VALUES (152571000000, '乌拉盖管委会', 3, 152500000000); +INSERT INTO `zz_area_code` VALUES (152900000000, '阿拉善盟', 2, 150000000000); +INSERT INTO `zz_area_code` VALUES (152921000000, '阿拉善左旗', 3, 152900000000); +INSERT INTO `zz_area_code` VALUES (152922000000, '阿拉善右旗', 3, 152900000000); +INSERT INTO `zz_area_code` VALUES (152923000000, '额济纳旗', 3, 152900000000); +INSERT INTO `zz_area_code` VALUES (152971000000, '内蒙古阿拉善经济开发区', 3, 152900000000); +INSERT INTO `zz_area_code` VALUES (210000000000, '辽宁省', 1, NULL); +INSERT INTO `zz_area_code` VALUES (210100000000, '沈阳市', 2, 210000000000); +INSERT INTO `zz_area_code` VALUES (210101000000, '市辖区', 3, 210100000000); +INSERT INTO `zz_area_code` VALUES (210102000000, '和平区', 3, 210100000000); +INSERT INTO `zz_area_code` VALUES (210103000000, '沈河区', 3, 210100000000); +INSERT INTO `zz_area_code` VALUES (210104000000, '大东区', 3, 210100000000); +INSERT INTO `zz_area_code` VALUES (210105000000, '皇姑区', 3, 210100000000); +INSERT INTO `zz_area_code` VALUES (210106000000, '铁西区', 3, 210100000000); +INSERT INTO `zz_area_code` VALUES (210111000000, '苏家屯区', 3, 210100000000); +INSERT INTO `zz_area_code` VALUES (210112000000, '浑南区', 3, 210100000000); +INSERT INTO `zz_area_code` VALUES (210113000000, '沈北新区', 3, 210100000000); +INSERT INTO `zz_area_code` VALUES (210114000000, '于洪区', 3, 210100000000); +INSERT INTO `zz_area_code` VALUES (210115000000, '辽中区', 3, 210100000000); +INSERT INTO `zz_area_code` VALUES (210123000000, '康平县', 3, 210100000000); +INSERT INTO `zz_area_code` VALUES (210124000000, '法库县', 3, 210100000000); +INSERT INTO `zz_area_code` VALUES (210181000000, '新民市', 3, 210100000000); +INSERT INTO `zz_area_code` VALUES (210200000000, '大连市', 2, 210000000000); +INSERT INTO `zz_area_code` VALUES (210201000000, '市辖区', 3, 210200000000); +INSERT INTO `zz_area_code` VALUES (210202000000, '中山区', 3, 210200000000); +INSERT INTO `zz_area_code` VALUES (210203000000, '西岗区', 3, 210200000000); +INSERT INTO `zz_area_code` VALUES (210204000000, '沙河口区', 3, 210200000000); +INSERT INTO `zz_area_code` VALUES (210211000000, '甘井子区', 3, 210200000000); +INSERT INTO `zz_area_code` VALUES (210212000000, '旅顺口区', 3, 210200000000); +INSERT INTO `zz_area_code` VALUES (210213000000, '金州区', 3, 210200000000); +INSERT INTO `zz_area_code` VALUES (210214000000, '普兰店区', 3, 210200000000); +INSERT INTO `zz_area_code` VALUES (210224000000, '长海县', 3, 210200000000); +INSERT INTO `zz_area_code` VALUES (210281000000, '瓦房店市', 3, 210200000000); +INSERT INTO `zz_area_code` VALUES (210283000000, '庄河市', 3, 210200000000); +INSERT INTO `zz_area_code` VALUES (210300000000, '鞍山市', 2, 210000000000); +INSERT INTO `zz_area_code` VALUES (210301000000, '市辖区', 3, 210300000000); +INSERT INTO `zz_area_code` VALUES (210302000000, '铁东区', 3, 210300000000); +INSERT INTO `zz_area_code` VALUES (210303000000, '铁西区', 3, 210300000000); +INSERT INTO `zz_area_code` VALUES (210304000000, '立山区', 3, 210300000000); +INSERT INTO `zz_area_code` VALUES (210311000000, '千山区', 3, 210300000000); +INSERT INTO `zz_area_code` VALUES (210321000000, '台安县', 3, 210300000000); +INSERT INTO `zz_area_code` VALUES (210323000000, '岫岩满族自治县', 3, 210300000000); +INSERT INTO `zz_area_code` VALUES (210381000000, '海城市', 3, 210300000000); +INSERT INTO `zz_area_code` VALUES (210400000000, '抚顺市', 2, 210000000000); +INSERT INTO `zz_area_code` VALUES (210401000000, '市辖区', 3, 210400000000); +INSERT INTO `zz_area_code` VALUES (210402000000, '新抚区', 3, 210400000000); +INSERT INTO `zz_area_code` VALUES (210403000000, '东洲区', 3, 210400000000); +INSERT INTO `zz_area_code` VALUES (210404000000, '望花区', 3, 210400000000); +INSERT INTO `zz_area_code` VALUES (210411000000, '顺城区', 3, 210400000000); +INSERT INTO `zz_area_code` VALUES (210421000000, '抚顺县', 3, 210400000000); +INSERT INTO `zz_area_code` VALUES (210422000000, '新宾满族自治县', 3, 210400000000); +INSERT INTO `zz_area_code` VALUES (210423000000, '清原满族自治县', 3, 210400000000); +INSERT INTO `zz_area_code` VALUES (210500000000, '本溪市', 2, 210000000000); +INSERT INTO `zz_area_code` VALUES (210501000000, '市辖区', 3, 210500000000); +INSERT INTO `zz_area_code` VALUES (210502000000, '平山区', 3, 210500000000); +INSERT INTO `zz_area_code` VALUES (210503000000, '溪湖区', 3, 210500000000); +INSERT INTO `zz_area_code` VALUES (210504000000, '明山区', 3, 210500000000); +INSERT INTO `zz_area_code` VALUES (210505000000, '南芬区', 3, 210500000000); +INSERT INTO `zz_area_code` VALUES (210521000000, '本溪满族自治县', 3, 210500000000); +INSERT INTO `zz_area_code` VALUES (210522000000, '桓仁满族自治县', 3, 210500000000); +INSERT INTO `zz_area_code` VALUES (210600000000, '丹东市', 2, 210000000000); +INSERT INTO `zz_area_code` VALUES (210601000000, '市辖区', 3, 210600000000); +INSERT INTO `zz_area_code` VALUES (210602000000, '元宝区', 3, 210600000000); +INSERT INTO `zz_area_code` VALUES (210603000000, '振兴区', 3, 210600000000); +INSERT INTO `zz_area_code` VALUES (210604000000, '振安区', 3, 210600000000); +INSERT INTO `zz_area_code` VALUES (210624000000, '宽甸满族自治县', 3, 210600000000); +INSERT INTO `zz_area_code` VALUES (210681000000, '东港市', 3, 210600000000); +INSERT INTO `zz_area_code` VALUES (210682000000, '凤城市', 3, 210600000000); +INSERT INTO `zz_area_code` VALUES (210700000000, '锦州市', 2, 210000000000); +INSERT INTO `zz_area_code` VALUES (210701000000, '市辖区', 3, 210700000000); +INSERT INTO `zz_area_code` VALUES (210702000000, '古塔区', 3, 210700000000); +INSERT INTO `zz_area_code` VALUES (210703000000, '凌河区', 3, 210700000000); +INSERT INTO `zz_area_code` VALUES (210711000000, '太和区', 3, 210700000000); +INSERT INTO `zz_area_code` VALUES (210726000000, '黑山县', 3, 210700000000); +INSERT INTO `zz_area_code` VALUES (210727000000, '义县', 3, 210700000000); +INSERT INTO `zz_area_code` VALUES (210781000000, '凌海市', 3, 210700000000); +INSERT INTO `zz_area_code` VALUES (210782000000, '北镇市', 3, 210700000000); +INSERT INTO `zz_area_code` VALUES (210800000000, '营口市', 2, 210000000000); +INSERT INTO `zz_area_code` VALUES (210801000000, '市辖区', 3, 210800000000); +INSERT INTO `zz_area_code` VALUES (210802000000, '站前区', 3, 210800000000); +INSERT INTO `zz_area_code` VALUES (210803000000, '西市区', 3, 210800000000); +INSERT INTO `zz_area_code` VALUES (210804000000, '鲅鱼圈区', 3, 210800000000); +INSERT INTO `zz_area_code` VALUES (210811000000, '老边区', 3, 210800000000); +INSERT INTO `zz_area_code` VALUES (210881000000, '盖州市', 3, 210800000000); +INSERT INTO `zz_area_code` VALUES (210882000000, '大石桥市', 3, 210800000000); +INSERT INTO `zz_area_code` VALUES (210900000000, '阜新市', 2, 210000000000); +INSERT INTO `zz_area_code` VALUES (210901000000, '市辖区', 3, 210900000000); +INSERT INTO `zz_area_code` VALUES (210902000000, '海州区', 3, 210900000000); +INSERT INTO `zz_area_code` VALUES (210903000000, '新邱区', 3, 210900000000); +INSERT INTO `zz_area_code` VALUES (210904000000, '太平区', 3, 210900000000); +INSERT INTO `zz_area_code` VALUES (210905000000, '清河门区', 3, 210900000000); +INSERT INTO `zz_area_code` VALUES (210911000000, '细河区', 3, 210900000000); +INSERT INTO `zz_area_code` VALUES (210921000000, '阜新蒙古族自治县', 3, 210900000000); +INSERT INTO `zz_area_code` VALUES (210922000000, '彰武县', 3, 210900000000); +INSERT INTO `zz_area_code` VALUES (211000000000, '辽阳市', 2, 210000000000); +INSERT INTO `zz_area_code` VALUES (211001000000, '市辖区', 3, 211000000000); +INSERT INTO `zz_area_code` VALUES (211002000000, '白塔区', 3, 211000000000); +INSERT INTO `zz_area_code` VALUES (211003000000, '文圣区', 3, 211000000000); +INSERT INTO `zz_area_code` VALUES (211004000000, '宏伟区', 3, 211000000000); +INSERT INTO `zz_area_code` VALUES (211005000000, '弓长岭区', 3, 211000000000); +INSERT INTO `zz_area_code` VALUES (211011000000, '太子河区', 3, 211000000000); +INSERT INTO `zz_area_code` VALUES (211021000000, '辽阳县', 3, 211000000000); +INSERT INTO `zz_area_code` VALUES (211081000000, '灯塔市', 3, 211000000000); +INSERT INTO `zz_area_code` VALUES (211100000000, '盘锦市', 2, 210000000000); +INSERT INTO `zz_area_code` VALUES (211101000000, '市辖区', 3, 211100000000); +INSERT INTO `zz_area_code` VALUES (211102000000, '双台子区', 3, 211100000000); +INSERT INTO `zz_area_code` VALUES (211103000000, '兴隆台区', 3, 211100000000); +INSERT INTO `zz_area_code` VALUES (211104000000, '大洼区', 3, 211100000000); +INSERT INTO `zz_area_code` VALUES (211122000000, '盘山县', 3, 211100000000); +INSERT INTO `zz_area_code` VALUES (211200000000, '铁岭市', 2, 210000000000); +INSERT INTO `zz_area_code` VALUES (211201000000, '市辖区', 3, 211200000000); +INSERT INTO `zz_area_code` VALUES (211202000000, '银州区', 3, 211200000000); +INSERT INTO `zz_area_code` VALUES (211204000000, '清河区', 3, 211200000000); +INSERT INTO `zz_area_code` VALUES (211221000000, '铁岭县', 3, 211200000000); +INSERT INTO `zz_area_code` VALUES (211223000000, '西丰县', 3, 211200000000); +INSERT INTO `zz_area_code` VALUES (211224000000, '昌图县', 3, 211200000000); +INSERT INTO `zz_area_code` VALUES (211281000000, '调兵山市', 3, 211200000000); +INSERT INTO `zz_area_code` VALUES (211282000000, '开原市', 3, 211200000000); +INSERT INTO `zz_area_code` VALUES (211300000000, '朝阳市', 2, 210000000000); +INSERT INTO `zz_area_code` VALUES (211301000000, '市辖区', 3, 211300000000); +INSERT INTO `zz_area_code` VALUES (211302000000, '双塔区', 3, 211300000000); +INSERT INTO `zz_area_code` VALUES (211303000000, '龙城区', 3, 211300000000); +INSERT INTO `zz_area_code` VALUES (211321000000, '朝阳县', 3, 211300000000); +INSERT INTO `zz_area_code` VALUES (211322000000, '建平县', 3, 211300000000); +INSERT INTO `zz_area_code` VALUES (211324000000, '喀喇沁左翼蒙古族自治县', 3, 211300000000); +INSERT INTO `zz_area_code` VALUES (211381000000, '北票市', 3, 211300000000); +INSERT INTO `zz_area_code` VALUES (211382000000, '凌源市', 3, 211300000000); +INSERT INTO `zz_area_code` VALUES (211400000000, '葫芦岛市', 2, 210000000000); +INSERT INTO `zz_area_code` VALUES (211401000000, '市辖区', 3, 211400000000); +INSERT INTO `zz_area_code` VALUES (211402000000, '连山区', 3, 211400000000); +INSERT INTO `zz_area_code` VALUES (211403000000, '龙港区', 3, 211400000000); +INSERT INTO `zz_area_code` VALUES (211404000000, '南票区', 3, 211400000000); +INSERT INTO `zz_area_code` VALUES (211421000000, '绥中县', 3, 211400000000); +INSERT INTO `zz_area_code` VALUES (211422000000, '建昌县', 3, 211400000000); +INSERT INTO `zz_area_code` VALUES (211481000000, '兴城市', 3, 211400000000); +INSERT INTO `zz_area_code` VALUES (220000000000, '吉林省', 1, NULL); +INSERT INTO `zz_area_code` VALUES (220100000000, '长春市', 2, 220000000000); +INSERT INTO `zz_area_code` VALUES (220101000000, '市辖区', 3, 220100000000); +INSERT INTO `zz_area_code` VALUES (220102000000, '南关区', 3, 220100000000); +INSERT INTO `zz_area_code` VALUES (220103000000, '宽城区', 3, 220100000000); +INSERT INTO `zz_area_code` VALUES (220104000000, '朝阳区', 3, 220100000000); +INSERT INTO `zz_area_code` VALUES (220105000000, '二道区', 3, 220100000000); +INSERT INTO `zz_area_code` VALUES (220106000000, '绿园区', 3, 220100000000); +INSERT INTO `zz_area_code` VALUES (220112000000, '双阳区', 3, 220100000000); +INSERT INTO `zz_area_code` VALUES (220113000000, '九台区', 3, 220100000000); +INSERT INTO `zz_area_code` VALUES (220122000000, '农安县', 3, 220100000000); +INSERT INTO `zz_area_code` VALUES (220171000000, '长春经济技术开发区', 3, 220100000000); +INSERT INTO `zz_area_code` VALUES (220172000000, '长春净月高新技术产业开发区', 3, 220100000000); +INSERT INTO `zz_area_code` VALUES (220173000000, '长春高新技术产业开发区', 3, 220100000000); +INSERT INTO `zz_area_code` VALUES (220174000000, '长春汽车经济技术开发区', 3, 220100000000); +INSERT INTO `zz_area_code` VALUES (220182000000, '榆树市', 3, 220100000000); +INSERT INTO `zz_area_code` VALUES (220183000000, '德惠市', 3, 220100000000); +INSERT INTO `zz_area_code` VALUES (220200000000, '吉林市', 2, 220000000000); +INSERT INTO `zz_area_code` VALUES (220201000000, '市辖区', 3, 220200000000); +INSERT INTO `zz_area_code` VALUES (220202000000, '昌邑区', 3, 220200000000); +INSERT INTO `zz_area_code` VALUES (220203000000, '龙潭区', 3, 220200000000); +INSERT INTO `zz_area_code` VALUES (220204000000, '船营区', 3, 220200000000); +INSERT INTO `zz_area_code` VALUES (220211000000, '丰满区', 3, 220200000000); +INSERT INTO `zz_area_code` VALUES (220221000000, '永吉县', 3, 220200000000); +INSERT INTO `zz_area_code` VALUES (220271000000, '吉林经济开发区', 3, 220200000000); +INSERT INTO `zz_area_code` VALUES (220272000000, '吉林高新技术产业开发区', 3, 220200000000); +INSERT INTO `zz_area_code` VALUES (220273000000, '吉林中国新加坡食品区', 3, 220200000000); +INSERT INTO `zz_area_code` VALUES (220281000000, '蛟河市', 3, 220200000000); +INSERT INTO `zz_area_code` VALUES (220282000000, '桦甸市', 3, 220200000000); +INSERT INTO `zz_area_code` VALUES (220283000000, '舒兰市', 3, 220200000000); +INSERT INTO `zz_area_code` VALUES (220284000000, '磐石市', 3, 220200000000); +INSERT INTO `zz_area_code` VALUES (220300000000, '四平市', 2, 220000000000); +INSERT INTO `zz_area_code` VALUES (220301000000, '市辖区', 3, 220300000000); +INSERT INTO `zz_area_code` VALUES (220302000000, '铁西区', 3, 220300000000); +INSERT INTO `zz_area_code` VALUES (220303000000, '铁东区', 3, 220300000000); +INSERT INTO `zz_area_code` VALUES (220322000000, '梨树县', 3, 220300000000); +INSERT INTO `zz_area_code` VALUES (220323000000, '伊通满族自治县', 3, 220300000000); +INSERT INTO `zz_area_code` VALUES (220381000000, '公主岭市', 3, 220300000000); +INSERT INTO `zz_area_code` VALUES (220382000000, '双辽市', 3, 220300000000); +INSERT INTO `zz_area_code` VALUES (220400000000, '辽源市', 2, 220000000000); +INSERT INTO `zz_area_code` VALUES (220401000000, '市辖区', 3, 220400000000); +INSERT INTO `zz_area_code` VALUES (220402000000, '龙山区', 3, 220400000000); +INSERT INTO `zz_area_code` VALUES (220403000000, '西安区', 3, 220400000000); +INSERT INTO `zz_area_code` VALUES (220421000000, '东丰县', 3, 220400000000); +INSERT INTO `zz_area_code` VALUES (220422000000, '东辽县', 3, 220400000000); +INSERT INTO `zz_area_code` VALUES (220500000000, '通化市', 2, 220000000000); +INSERT INTO `zz_area_code` VALUES (220501000000, '市辖区', 3, 220500000000); +INSERT INTO `zz_area_code` VALUES (220502000000, '东昌区', 3, 220500000000); +INSERT INTO `zz_area_code` VALUES (220503000000, '二道江区', 3, 220500000000); +INSERT INTO `zz_area_code` VALUES (220521000000, '通化县', 3, 220500000000); +INSERT INTO `zz_area_code` VALUES (220523000000, '辉南县', 3, 220500000000); +INSERT INTO `zz_area_code` VALUES (220524000000, '柳河县', 3, 220500000000); +INSERT INTO `zz_area_code` VALUES (220581000000, '梅河口市', 3, 220500000000); +INSERT INTO `zz_area_code` VALUES (220582000000, '集安市', 3, 220500000000); +INSERT INTO `zz_area_code` VALUES (220600000000, '白山市', 2, 220000000000); +INSERT INTO `zz_area_code` VALUES (220601000000, '市辖区', 3, 220600000000); +INSERT INTO `zz_area_code` VALUES (220602000000, '浑江区', 3, 220600000000); +INSERT INTO `zz_area_code` VALUES (220605000000, '江源区', 3, 220600000000); +INSERT INTO `zz_area_code` VALUES (220621000000, '抚松县', 3, 220600000000); +INSERT INTO `zz_area_code` VALUES (220622000000, '靖宇县', 3, 220600000000); +INSERT INTO `zz_area_code` VALUES (220623000000, '长白朝鲜族自治县', 3, 220600000000); +INSERT INTO `zz_area_code` VALUES (220681000000, '临江市', 3, 220600000000); +INSERT INTO `zz_area_code` VALUES (220700000000, '松原市', 2, 220000000000); +INSERT INTO `zz_area_code` VALUES (220701000000, '市辖区', 3, 220700000000); +INSERT INTO `zz_area_code` VALUES (220702000000, '宁江区', 3, 220700000000); +INSERT INTO `zz_area_code` VALUES (220721000000, '前郭尔罗斯蒙古族自治县', 3, 220700000000); +INSERT INTO `zz_area_code` VALUES (220722000000, '长岭县', 3, 220700000000); +INSERT INTO `zz_area_code` VALUES (220723000000, '乾安县', 3, 220700000000); +INSERT INTO `zz_area_code` VALUES (220771000000, '吉林松原经济开发区', 3, 220700000000); +INSERT INTO `zz_area_code` VALUES (220781000000, '扶余市', 3, 220700000000); +INSERT INTO `zz_area_code` VALUES (220800000000, '白城市', 2, 220000000000); +INSERT INTO `zz_area_code` VALUES (220801000000, '市辖区', 3, 220800000000); +INSERT INTO `zz_area_code` VALUES (220802000000, '洮北区', 3, 220800000000); +INSERT INTO `zz_area_code` VALUES (220821000000, '镇赉县', 3, 220800000000); +INSERT INTO `zz_area_code` VALUES (220822000000, '通榆县', 3, 220800000000); +INSERT INTO `zz_area_code` VALUES (220871000000, '吉林白城经济开发区', 3, 220800000000); +INSERT INTO `zz_area_code` VALUES (220881000000, '洮南市', 3, 220800000000); +INSERT INTO `zz_area_code` VALUES (220882000000, '大安市', 3, 220800000000); +INSERT INTO `zz_area_code` VALUES (222400000000, '延边朝鲜族自治州', 2, 220000000000); +INSERT INTO `zz_area_code` VALUES (222401000000, '延吉市', 3, 222400000000); +INSERT INTO `zz_area_code` VALUES (222402000000, '图们市', 3, 222400000000); +INSERT INTO `zz_area_code` VALUES (222403000000, '敦化市', 3, 222400000000); +INSERT INTO `zz_area_code` VALUES (222404000000, '珲春市', 3, 222400000000); +INSERT INTO `zz_area_code` VALUES (222405000000, '龙井市', 3, 222400000000); +INSERT INTO `zz_area_code` VALUES (222406000000, '和龙市', 3, 222400000000); +INSERT INTO `zz_area_code` VALUES (222424000000, '汪清县', 3, 222400000000); +INSERT INTO `zz_area_code` VALUES (222426000000, '安图县', 3, 222400000000); +INSERT INTO `zz_area_code` VALUES (230000000000, '黑龙江省', 1, NULL); +INSERT INTO `zz_area_code` VALUES (230100000000, '哈尔滨市', 2, 230000000000); +INSERT INTO `zz_area_code` VALUES (230101000000, '市辖区', 3, 230100000000); +INSERT INTO `zz_area_code` VALUES (230102000000, '道里区', 3, 230100000000); +INSERT INTO `zz_area_code` VALUES (230103000000, '南岗区', 3, 230100000000); +INSERT INTO `zz_area_code` VALUES (230104000000, '道外区', 3, 230100000000); +INSERT INTO `zz_area_code` VALUES (230108000000, '平房区', 3, 230100000000); +INSERT INTO `zz_area_code` VALUES (230109000000, '松北区', 3, 230100000000); +INSERT INTO `zz_area_code` VALUES (230110000000, '香坊区', 3, 230100000000); +INSERT INTO `zz_area_code` VALUES (230111000000, '呼兰区', 3, 230100000000); +INSERT INTO `zz_area_code` VALUES (230112000000, '阿城区', 3, 230100000000); +INSERT INTO `zz_area_code` VALUES (230113000000, '双城区', 3, 230100000000); +INSERT INTO `zz_area_code` VALUES (230123000000, '依兰县', 3, 230100000000); +INSERT INTO `zz_area_code` VALUES (230124000000, '方正县', 3, 230100000000); +INSERT INTO `zz_area_code` VALUES (230125000000, '宾县', 3, 230100000000); +INSERT INTO `zz_area_code` VALUES (230126000000, '巴彦县', 3, 230100000000); +INSERT INTO `zz_area_code` VALUES (230127000000, '木兰县', 3, 230100000000); +INSERT INTO `zz_area_code` VALUES (230128000000, '通河县', 3, 230100000000); +INSERT INTO `zz_area_code` VALUES (230129000000, '延寿县', 3, 230100000000); +INSERT INTO `zz_area_code` VALUES (230183000000, '尚志市', 3, 230100000000); +INSERT INTO `zz_area_code` VALUES (230184000000, '五常市', 3, 230100000000); +INSERT INTO `zz_area_code` VALUES (230200000000, '齐齐哈尔市', 2, 230000000000); +INSERT INTO `zz_area_code` VALUES (230201000000, '市辖区', 3, 230200000000); +INSERT INTO `zz_area_code` VALUES (230202000000, '龙沙区', 3, 230200000000); +INSERT INTO `zz_area_code` VALUES (230203000000, '建华区', 3, 230200000000); +INSERT INTO `zz_area_code` VALUES (230204000000, '铁锋区', 3, 230200000000); +INSERT INTO `zz_area_code` VALUES (230205000000, '昂昂溪区', 3, 230200000000); +INSERT INTO `zz_area_code` VALUES (230206000000, '富拉尔基区', 3, 230200000000); +INSERT INTO `zz_area_code` VALUES (230207000000, '碾子山区', 3, 230200000000); +INSERT INTO `zz_area_code` VALUES (230208000000, '梅里斯达斡尔族区', 3, 230200000000); +INSERT INTO `zz_area_code` VALUES (230221000000, '龙江县', 3, 230200000000); +INSERT INTO `zz_area_code` VALUES (230223000000, '依安县', 3, 230200000000); +INSERT INTO `zz_area_code` VALUES (230224000000, '泰来县', 3, 230200000000); +INSERT INTO `zz_area_code` VALUES (230225000000, '甘南县', 3, 230200000000); +INSERT INTO `zz_area_code` VALUES (230227000000, '富裕县', 3, 230200000000); +INSERT INTO `zz_area_code` VALUES (230229000000, '克山县', 3, 230200000000); +INSERT INTO `zz_area_code` VALUES (230230000000, '克东县', 3, 230200000000); +INSERT INTO `zz_area_code` VALUES (230231000000, '拜泉县', 3, 230200000000); +INSERT INTO `zz_area_code` VALUES (230281000000, '讷河市', 3, 230200000000); +INSERT INTO `zz_area_code` VALUES (230300000000, '鸡西市', 2, 230000000000); +INSERT INTO `zz_area_code` VALUES (230301000000, '市辖区', 3, 230300000000); +INSERT INTO `zz_area_code` VALUES (230302000000, '鸡冠区', 3, 230300000000); +INSERT INTO `zz_area_code` VALUES (230303000000, '恒山区', 3, 230300000000); +INSERT INTO `zz_area_code` VALUES (230304000000, '滴道区', 3, 230300000000); +INSERT INTO `zz_area_code` VALUES (230305000000, '梨树区', 3, 230300000000); +INSERT INTO `zz_area_code` VALUES (230306000000, '城子河区', 3, 230300000000); +INSERT INTO `zz_area_code` VALUES (230307000000, '麻山区', 3, 230300000000); +INSERT INTO `zz_area_code` VALUES (230321000000, '鸡东县', 3, 230300000000); +INSERT INTO `zz_area_code` VALUES (230381000000, '虎林市', 3, 230300000000); +INSERT INTO `zz_area_code` VALUES (230382000000, '密山市', 3, 230300000000); +INSERT INTO `zz_area_code` VALUES (230400000000, '鹤岗市', 2, 230000000000); +INSERT INTO `zz_area_code` VALUES (230401000000, '市辖区', 3, 230400000000); +INSERT INTO `zz_area_code` VALUES (230402000000, '向阳区', 3, 230400000000); +INSERT INTO `zz_area_code` VALUES (230403000000, '工农区', 3, 230400000000); +INSERT INTO `zz_area_code` VALUES (230404000000, '南山区', 3, 230400000000); +INSERT INTO `zz_area_code` VALUES (230405000000, '兴安区', 3, 230400000000); +INSERT INTO `zz_area_code` VALUES (230406000000, '东山区', 3, 230400000000); +INSERT INTO `zz_area_code` VALUES (230407000000, '兴山区', 3, 230400000000); +INSERT INTO `zz_area_code` VALUES (230421000000, '萝北县', 3, 230400000000); +INSERT INTO `zz_area_code` VALUES (230422000000, '绥滨县', 3, 230400000000); +INSERT INTO `zz_area_code` VALUES (230500000000, '双鸭山市', 2, 230000000000); +INSERT INTO `zz_area_code` VALUES (230501000000, '市辖区', 3, 230500000000); +INSERT INTO `zz_area_code` VALUES (230502000000, '尖山区', 3, 230500000000); +INSERT INTO `zz_area_code` VALUES (230503000000, '岭东区', 3, 230500000000); +INSERT INTO `zz_area_code` VALUES (230505000000, '四方台区', 3, 230500000000); +INSERT INTO `zz_area_code` VALUES (230506000000, '宝山区', 3, 230500000000); +INSERT INTO `zz_area_code` VALUES (230521000000, '集贤县', 3, 230500000000); +INSERT INTO `zz_area_code` VALUES (230522000000, '友谊县', 3, 230500000000); +INSERT INTO `zz_area_code` VALUES (230523000000, '宝清县', 3, 230500000000); +INSERT INTO `zz_area_code` VALUES (230524000000, '饶河县', 3, 230500000000); +INSERT INTO `zz_area_code` VALUES (230600000000, '大庆市', 2, 230000000000); +INSERT INTO `zz_area_code` VALUES (230601000000, '市辖区', 3, 230600000000); +INSERT INTO `zz_area_code` VALUES (230602000000, '萨尔图区', 3, 230600000000); +INSERT INTO `zz_area_code` VALUES (230603000000, '龙凤区', 3, 230600000000); +INSERT INTO `zz_area_code` VALUES (230604000000, '让胡路区', 3, 230600000000); +INSERT INTO `zz_area_code` VALUES (230605000000, '红岗区', 3, 230600000000); +INSERT INTO `zz_area_code` VALUES (230606000000, '大同区', 3, 230600000000); +INSERT INTO `zz_area_code` VALUES (230621000000, '肇州县', 3, 230600000000); +INSERT INTO `zz_area_code` VALUES (230622000000, '肇源县', 3, 230600000000); +INSERT INTO `zz_area_code` VALUES (230623000000, '林甸县', 3, 230600000000); +INSERT INTO `zz_area_code` VALUES (230624000000, '杜尔伯特蒙古族自治县', 3, 230600000000); +INSERT INTO `zz_area_code` VALUES (230671000000, '大庆高新技术产业开发区', 3, 230600000000); +INSERT INTO `zz_area_code` VALUES (230700000000, '伊春市', 2, 230000000000); +INSERT INTO `zz_area_code` VALUES (230701000000, '市辖区', 3, 230700000000); +INSERT INTO `zz_area_code` VALUES (230702000000, '伊春区', 3, 230700000000); +INSERT INTO `zz_area_code` VALUES (230703000000, '南岔区', 3, 230700000000); +INSERT INTO `zz_area_code` VALUES (230704000000, '友好区', 3, 230700000000); +INSERT INTO `zz_area_code` VALUES (230705000000, '西林区', 3, 230700000000); +INSERT INTO `zz_area_code` VALUES (230706000000, '翠峦区', 3, 230700000000); +INSERT INTO `zz_area_code` VALUES (230707000000, '新青区', 3, 230700000000); +INSERT INTO `zz_area_code` VALUES (230708000000, '美溪区', 3, 230700000000); +INSERT INTO `zz_area_code` VALUES (230709000000, '金山屯区', 3, 230700000000); +INSERT INTO `zz_area_code` VALUES (230710000000, '五营区', 3, 230700000000); +INSERT INTO `zz_area_code` VALUES (230711000000, '乌马河区', 3, 230700000000); +INSERT INTO `zz_area_code` VALUES (230712000000, '汤旺河区', 3, 230700000000); +INSERT INTO `zz_area_code` VALUES (230713000000, '带岭区', 3, 230700000000); +INSERT INTO `zz_area_code` VALUES (230714000000, '乌伊岭区', 3, 230700000000); +INSERT INTO `zz_area_code` VALUES (230715000000, '红星区', 3, 230700000000); +INSERT INTO `zz_area_code` VALUES (230716000000, '上甘岭区', 3, 230700000000); +INSERT INTO `zz_area_code` VALUES (230722000000, '嘉荫县', 3, 230700000000); +INSERT INTO `zz_area_code` VALUES (230781000000, '铁力市', 3, 230700000000); +INSERT INTO `zz_area_code` VALUES (230800000000, '佳木斯市', 2, 230000000000); +INSERT INTO `zz_area_code` VALUES (230801000000, '市辖区', 3, 230800000000); +INSERT INTO `zz_area_code` VALUES (230803000000, '向阳区', 3, 230800000000); +INSERT INTO `zz_area_code` VALUES (230804000000, '前进区', 3, 230800000000); +INSERT INTO `zz_area_code` VALUES (230805000000, '东风区', 3, 230800000000); +INSERT INTO `zz_area_code` VALUES (230811000000, '郊区', 3, 230800000000); +INSERT INTO `zz_area_code` VALUES (230822000000, '桦南县', 3, 230800000000); +INSERT INTO `zz_area_code` VALUES (230826000000, '桦川县', 3, 230800000000); +INSERT INTO `zz_area_code` VALUES (230828000000, '汤原县', 3, 230800000000); +INSERT INTO `zz_area_code` VALUES (230881000000, '同江市', 3, 230800000000); +INSERT INTO `zz_area_code` VALUES (230882000000, '富锦市', 3, 230800000000); +INSERT INTO `zz_area_code` VALUES (230883000000, '抚远市', 3, 230800000000); +INSERT INTO `zz_area_code` VALUES (230900000000, '七台河市', 2, 230000000000); +INSERT INTO `zz_area_code` VALUES (230901000000, '市辖区', 3, 230900000000); +INSERT INTO `zz_area_code` VALUES (230902000000, '新兴区', 3, 230900000000); +INSERT INTO `zz_area_code` VALUES (230903000000, '桃山区', 3, 230900000000); +INSERT INTO `zz_area_code` VALUES (230904000000, '茄子河区', 3, 230900000000); +INSERT INTO `zz_area_code` VALUES (230921000000, '勃利县', 3, 230900000000); +INSERT INTO `zz_area_code` VALUES (231000000000, '牡丹江市', 2, 230000000000); +INSERT INTO `zz_area_code` VALUES (231001000000, '市辖区', 3, 231000000000); +INSERT INTO `zz_area_code` VALUES (231002000000, '东安区', 3, 231000000000); +INSERT INTO `zz_area_code` VALUES (231003000000, '阳明区', 3, 231000000000); +INSERT INTO `zz_area_code` VALUES (231004000000, '爱民区', 3, 231000000000); +INSERT INTO `zz_area_code` VALUES (231005000000, '西安区', 3, 231000000000); +INSERT INTO `zz_area_code` VALUES (231025000000, '林口县', 3, 231000000000); +INSERT INTO `zz_area_code` VALUES (231071000000, '牡丹江经济技术开发区', 3, 231000000000); +INSERT INTO `zz_area_code` VALUES (231081000000, '绥芬河市', 3, 231000000000); +INSERT INTO `zz_area_code` VALUES (231083000000, '海林市', 3, 231000000000); +INSERT INTO `zz_area_code` VALUES (231084000000, '宁安市', 3, 231000000000); +INSERT INTO `zz_area_code` VALUES (231085000000, '穆棱市', 3, 231000000000); +INSERT INTO `zz_area_code` VALUES (231086000000, '东宁市', 3, 231000000000); +INSERT INTO `zz_area_code` VALUES (231100000000, '黑河市', 2, 230000000000); +INSERT INTO `zz_area_code` VALUES (231101000000, '市辖区', 3, 231100000000); +INSERT INTO `zz_area_code` VALUES (231102000000, '爱辉区', 3, 231100000000); +INSERT INTO `zz_area_code` VALUES (231121000000, '嫩江县', 3, 231100000000); +INSERT INTO `zz_area_code` VALUES (231123000000, '逊克县', 3, 231100000000); +INSERT INTO `zz_area_code` VALUES (231124000000, '孙吴县', 3, 231100000000); +INSERT INTO `zz_area_code` VALUES (231181000000, '北安市', 3, 231100000000); +INSERT INTO `zz_area_code` VALUES (231182000000, '五大连池市', 3, 231100000000); +INSERT INTO `zz_area_code` VALUES (231200000000, '绥化市', 2, 230000000000); +INSERT INTO `zz_area_code` VALUES (231201000000, '市辖区', 3, 231200000000); +INSERT INTO `zz_area_code` VALUES (231202000000, '北林区', 3, 231200000000); +INSERT INTO `zz_area_code` VALUES (231221000000, '望奎县', 3, 231200000000); +INSERT INTO `zz_area_code` VALUES (231222000000, '兰西县', 3, 231200000000); +INSERT INTO `zz_area_code` VALUES (231223000000, '青冈县', 3, 231200000000); +INSERT INTO `zz_area_code` VALUES (231224000000, '庆安县', 3, 231200000000); +INSERT INTO `zz_area_code` VALUES (231225000000, '明水县', 3, 231200000000); +INSERT INTO `zz_area_code` VALUES (231226000000, '绥棱县', 3, 231200000000); +INSERT INTO `zz_area_code` VALUES (231281000000, '安达市', 3, 231200000000); +INSERT INTO `zz_area_code` VALUES (231282000000, '肇东市', 3, 231200000000); +INSERT INTO `zz_area_code` VALUES (231283000000, '海伦市', 3, 231200000000); +INSERT INTO `zz_area_code` VALUES (232700000000, '大兴安岭地区', 2, 230000000000); +INSERT INTO `zz_area_code` VALUES (232701000000, '漠河市', 3, 232700000000); +INSERT INTO `zz_area_code` VALUES (232721000000, '呼玛县', 3, 232700000000); +INSERT INTO `zz_area_code` VALUES (232722000000, '塔河县', 3, 232700000000); +INSERT INTO `zz_area_code` VALUES (232761000000, '加格达奇区', 3, 232700000000); +INSERT INTO `zz_area_code` VALUES (232762000000, '松岭区', 3, 232700000000); +INSERT INTO `zz_area_code` VALUES (232763000000, '新林区', 3, 232700000000); +INSERT INTO `zz_area_code` VALUES (232764000000, '呼中区', 3, 232700000000); +INSERT INTO `zz_area_code` VALUES (310000000000, '上海市', 1, NULL); +INSERT INTO `zz_area_code` VALUES (310100000000, '市辖区', 2, 310000000000); +INSERT INTO `zz_area_code` VALUES (310101000000, '黄浦区', 3, 310100000000); +INSERT INTO `zz_area_code` VALUES (310104000000, '徐汇区', 3, 310100000000); +INSERT INTO `zz_area_code` VALUES (310105000000, '长宁区', 3, 310100000000); +INSERT INTO `zz_area_code` VALUES (310106000000, '静安区', 3, 310100000000); +INSERT INTO `zz_area_code` VALUES (310107000000, '普陀区', 3, 310100000000); +INSERT INTO `zz_area_code` VALUES (310109000000, '虹口区', 3, 310100000000); +INSERT INTO `zz_area_code` VALUES (310110000000, '杨浦区', 3, 310100000000); +INSERT INTO `zz_area_code` VALUES (310112000000, '闵行区', 3, 310100000000); +INSERT INTO `zz_area_code` VALUES (310113000000, '宝山区', 3, 310100000000); +INSERT INTO `zz_area_code` VALUES (310114000000, '嘉定区', 3, 310100000000); +INSERT INTO `zz_area_code` VALUES (310115000000, '浦东新区', 3, 310100000000); +INSERT INTO `zz_area_code` VALUES (310116000000, '金山区', 3, 310100000000); +INSERT INTO `zz_area_code` VALUES (310117000000, '松江区', 3, 310100000000); +INSERT INTO `zz_area_code` VALUES (310118000000, '青浦区', 3, 310100000000); +INSERT INTO `zz_area_code` VALUES (310120000000, '奉贤区', 3, 310100000000); +INSERT INTO `zz_area_code` VALUES (310151000000, '崇明区', 3, 310100000000); +INSERT INTO `zz_area_code` VALUES (320000000000, '江苏省', 1, NULL); +INSERT INTO `zz_area_code` VALUES (320100000000, '南京市', 2, 320000000000); +INSERT INTO `zz_area_code` VALUES (320101000000, '市辖区', 3, 320100000000); +INSERT INTO `zz_area_code` VALUES (320102000000, '玄武区', 3, 320100000000); +INSERT INTO `zz_area_code` VALUES (320104000000, '秦淮区', 3, 320100000000); +INSERT INTO `zz_area_code` VALUES (320105000000, '建邺区', 3, 320100000000); +INSERT INTO `zz_area_code` VALUES (320106000000, '鼓楼区', 3, 320100000000); +INSERT INTO `zz_area_code` VALUES (320111000000, '浦口区', 3, 320100000000); +INSERT INTO `zz_area_code` VALUES (320113000000, '栖霞区', 3, 320100000000); +INSERT INTO `zz_area_code` VALUES (320114000000, '雨花台区', 3, 320100000000); +INSERT INTO `zz_area_code` VALUES (320115000000, '江宁区', 3, 320100000000); +INSERT INTO `zz_area_code` VALUES (320116000000, '六合区', 3, 320100000000); +INSERT INTO `zz_area_code` VALUES (320117000000, '溧水区', 3, 320100000000); +INSERT INTO `zz_area_code` VALUES (320118000000, '高淳区', 3, 320100000000); +INSERT INTO `zz_area_code` VALUES (320200000000, '无锡市', 2, 320000000000); +INSERT INTO `zz_area_code` VALUES (320201000000, '市辖区', 3, 320200000000); +INSERT INTO `zz_area_code` VALUES (320205000000, '锡山区', 3, 320200000000); +INSERT INTO `zz_area_code` VALUES (320206000000, '惠山区', 3, 320200000000); +INSERT INTO `zz_area_code` VALUES (320211000000, '滨湖区', 3, 320200000000); +INSERT INTO `zz_area_code` VALUES (320213000000, '梁溪区', 3, 320200000000); +INSERT INTO `zz_area_code` VALUES (320214000000, '新吴区', 3, 320200000000); +INSERT INTO `zz_area_code` VALUES (320281000000, '江阴市', 3, 320200000000); +INSERT INTO `zz_area_code` VALUES (320282000000, '宜兴市', 3, 320200000000); +INSERT INTO `zz_area_code` VALUES (320300000000, '徐州市', 2, 320000000000); +INSERT INTO `zz_area_code` VALUES (320301000000, '市辖区', 3, 320300000000); +INSERT INTO `zz_area_code` VALUES (320302000000, '鼓楼区', 3, 320300000000); +INSERT INTO `zz_area_code` VALUES (320303000000, '云龙区', 3, 320300000000); +INSERT INTO `zz_area_code` VALUES (320305000000, '贾汪区', 3, 320300000000); +INSERT INTO `zz_area_code` VALUES (320311000000, '泉山区', 3, 320300000000); +INSERT INTO `zz_area_code` VALUES (320312000000, '铜山区', 3, 320300000000); +INSERT INTO `zz_area_code` VALUES (320321000000, '丰县', 3, 320300000000); +INSERT INTO `zz_area_code` VALUES (320322000000, '沛县', 3, 320300000000); +INSERT INTO `zz_area_code` VALUES (320324000000, '睢宁县', 3, 320300000000); +INSERT INTO `zz_area_code` VALUES (320371000000, '徐州经济技术开发区', 3, 320300000000); +INSERT INTO `zz_area_code` VALUES (320381000000, '新沂市', 3, 320300000000); +INSERT INTO `zz_area_code` VALUES (320382000000, '邳州市', 3, 320300000000); +INSERT INTO `zz_area_code` VALUES (320400000000, '常州市', 2, 320000000000); +INSERT INTO `zz_area_code` VALUES (320401000000, '市辖区', 3, 320400000000); +INSERT INTO `zz_area_code` VALUES (320402000000, '天宁区', 3, 320400000000); +INSERT INTO `zz_area_code` VALUES (320404000000, '钟楼区', 3, 320400000000); +INSERT INTO `zz_area_code` VALUES (320411000000, '新北区', 3, 320400000000); +INSERT INTO `zz_area_code` VALUES (320412000000, '武进区', 3, 320400000000); +INSERT INTO `zz_area_code` VALUES (320413000000, '金坛区', 3, 320400000000); +INSERT INTO `zz_area_code` VALUES (320481000000, '溧阳市', 3, 320400000000); +INSERT INTO `zz_area_code` VALUES (320500000000, '苏州市', 2, 320000000000); +INSERT INTO `zz_area_code` VALUES (320501000000, '市辖区', 3, 320500000000); +INSERT INTO `zz_area_code` VALUES (320505000000, '虎丘区', 3, 320500000000); +INSERT INTO `zz_area_code` VALUES (320506000000, '吴中区', 3, 320500000000); +INSERT INTO `zz_area_code` VALUES (320507000000, '相城区', 3, 320500000000); +INSERT INTO `zz_area_code` VALUES (320508000000, '姑苏区', 3, 320500000000); +INSERT INTO `zz_area_code` VALUES (320509000000, '吴江区', 3, 320500000000); +INSERT INTO `zz_area_code` VALUES (320571000000, '苏州工业园区', 3, 320500000000); +INSERT INTO `zz_area_code` VALUES (320581000000, '常熟市', 3, 320500000000); +INSERT INTO `zz_area_code` VALUES (320582000000, '张家港市', 3, 320500000000); +INSERT INTO `zz_area_code` VALUES (320583000000, '昆山市', 3, 320500000000); +INSERT INTO `zz_area_code` VALUES (320585000000, '太仓市', 3, 320500000000); +INSERT INTO `zz_area_code` VALUES (320600000000, '南通市', 2, 320000000000); +INSERT INTO `zz_area_code` VALUES (320601000000, '市辖区', 3, 320600000000); +INSERT INTO `zz_area_code` VALUES (320602000000, '崇川区', 3, 320600000000); +INSERT INTO `zz_area_code` VALUES (320611000000, '港闸区', 3, 320600000000); +INSERT INTO `zz_area_code` VALUES (320612000000, '通州区', 3, 320600000000); +INSERT INTO `zz_area_code` VALUES (320623000000, '如东县', 3, 320600000000); +INSERT INTO `zz_area_code` VALUES (320671000000, '南通经济技术开发区', 3, 320600000000); +INSERT INTO `zz_area_code` VALUES (320681000000, '启东市', 3, 320600000000); +INSERT INTO `zz_area_code` VALUES (320682000000, '如皋市', 3, 320600000000); +INSERT INTO `zz_area_code` VALUES (320684000000, '海门市', 3, 320600000000); +INSERT INTO `zz_area_code` VALUES (320685000000, '海安市', 3, 320600000000); +INSERT INTO `zz_area_code` VALUES (320700000000, '连云港市', 2, 320000000000); +INSERT INTO `zz_area_code` VALUES (320701000000, '市辖区', 3, 320700000000); +INSERT INTO `zz_area_code` VALUES (320703000000, '连云区', 3, 320700000000); +INSERT INTO `zz_area_code` VALUES (320706000000, '海州区', 3, 320700000000); +INSERT INTO `zz_area_code` VALUES (320707000000, '赣榆区', 3, 320700000000); +INSERT INTO `zz_area_code` VALUES (320722000000, '东海县', 3, 320700000000); +INSERT INTO `zz_area_code` VALUES (320723000000, '灌云县', 3, 320700000000); +INSERT INTO `zz_area_code` VALUES (320724000000, '灌南县', 3, 320700000000); +INSERT INTO `zz_area_code` VALUES (320771000000, '连云港经济技术开发区', 3, 320700000000); +INSERT INTO `zz_area_code` VALUES (320772000000, '连云港高新技术产业开发区', 3, 320700000000); +INSERT INTO `zz_area_code` VALUES (320800000000, '淮安市', 2, 320000000000); +INSERT INTO `zz_area_code` VALUES (320801000000, '市辖区', 3, 320800000000); +INSERT INTO `zz_area_code` VALUES (320803000000, '淮安区', 3, 320800000000); +INSERT INTO `zz_area_code` VALUES (320804000000, '淮阴区', 3, 320800000000); +INSERT INTO `zz_area_code` VALUES (320812000000, '清江浦区', 3, 320800000000); +INSERT INTO `zz_area_code` VALUES (320813000000, '洪泽区', 3, 320800000000); +INSERT INTO `zz_area_code` VALUES (320826000000, '涟水县', 3, 320800000000); +INSERT INTO `zz_area_code` VALUES (320830000000, '盱眙县', 3, 320800000000); +INSERT INTO `zz_area_code` VALUES (320831000000, '金湖县', 3, 320800000000); +INSERT INTO `zz_area_code` VALUES (320871000000, '淮安经济技术开发区', 3, 320800000000); +INSERT INTO `zz_area_code` VALUES (320900000000, '盐城市', 2, 320000000000); +INSERT INTO `zz_area_code` VALUES (320901000000, '市辖区', 3, 320900000000); +INSERT INTO `zz_area_code` VALUES (320902000000, '亭湖区', 3, 320900000000); +INSERT INTO `zz_area_code` VALUES (320903000000, '盐都区', 3, 320900000000); +INSERT INTO `zz_area_code` VALUES (320904000000, '大丰区', 3, 320900000000); +INSERT INTO `zz_area_code` VALUES (320921000000, '响水县', 3, 320900000000); +INSERT INTO `zz_area_code` VALUES (320922000000, '滨海县', 3, 320900000000); +INSERT INTO `zz_area_code` VALUES (320923000000, '阜宁县', 3, 320900000000); +INSERT INTO `zz_area_code` VALUES (320924000000, '射阳县', 3, 320900000000); +INSERT INTO `zz_area_code` VALUES (320925000000, '建湖县', 3, 320900000000); +INSERT INTO `zz_area_code` VALUES (320971000000, '盐城经济技术开发区', 3, 320900000000); +INSERT INTO `zz_area_code` VALUES (320981000000, '东台市', 3, 320900000000); +INSERT INTO `zz_area_code` VALUES (321000000000, '扬州市', 2, 320000000000); +INSERT INTO `zz_area_code` VALUES (321001000000, '市辖区', 3, 321000000000); +INSERT INTO `zz_area_code` VALUES (321002000000, '广陵区', 3, 321000000000); +INSERT INTO `zz_area_code` VALUES (321003000000, '邗江区', 3, 321000000000); +INSERT INTO `zz_area_code` VALUES (321012000000, '江都区', 3, 321000000000); +INSERT INTO `zz_area_code` VALUES (321023000000, '宝应县', 3, 321000000000); +INSERT INTO `zz_area_code` VALUES (321071000000, '扬州经济技术开发区', 3, 321000000000); +INSERT INTO `zz_area_code` VALUES (321081000000, '仪征市', 3, 321000000000); +INSERT INTO `zz_area_code` VALUES (321084000000, '高邮市', 3, 321000000000); +INSERT INTO `zz_area_code` VALUES (321100000000, '镇江市', 2, 320000000000); +INSERT INTO `zz_area_code` VALUES (321101000000, '市辖区', 3, 321100000000); +INSERT INTO `zz_area_code` VALUES (321102000000, '京口区', 3, 321100000000); +INSERT INTO `zz_area_code` VALUES (321111000000, '润州区', 3, 321100000000); +INSERT INTO `zz_area_code` VALUES (321112000000, '丹徒区', 3, 321100000000); +INSERT INTO `zz_area_code` VALUES (321171000000, '镇江新区', 3, 321100000000); +INSERT INTO `zz_area_code` VALUES (321181000000, '丹阳市', 3, 321100000000); +INSERT INTO `zz_area_code` VALUES (321182000000, '扬中市', 3, 321100000000); +INSERT INTO `zz_area_code` VALUES (321183000000, '句容市', 3, 321100000000); +INSERT INTO `zz_area_code` VALUES (321200000000, '泰州市', 2, 320000000000); +INSERT INTO `zz_area_code` VALUES (321201000000, '市辖区', 3, 321200000000); +INSERT INTO `zz_area_code` VALUES (321202000000, '海陵区', 3, 321200000000); +INSERT INTO `zz_area_code` VALUES (321203000000, '高港区', 3, 321200000000); +INSERT INTO `zz_area_code` VALUES (321204000000, '姜堰区', 3, 321200000000); +INSERT INTO `zz_area_code` VALUES (321271000000, '泰州医药高新技术产业开发区', 3, 321200000000); +INSERT INTO `zz_area_code` VALUES (321281000000, '兴化市', 3, 321200000000); +INSERT INTO `zz_area_code` VALUES (321282000000, '靖江市', 3, 321200000000); +INSERT INTO `zz_area_code` VALUES (321283000000, '泰兴市', 3, 321200000000); +INSERT INTO `zz_area_code` VALUES (321300000000, '宿迁市', 2, 320000000000); +INSERT INTO `zz_area_code` VALUES (321301000000, '市辖区', 3, 321300000000); +INSERT INTO `zz_area_code` VALUES (321302000000, '宿城区', 3, 321300000000); +INSERT INTO `zz_area_code` VALUES (321311000000, '宿豫区', 3, 321300000000); +INSERT INTO `zz_area_code` VALUES (321322000000, '沭阳县', 3, 321300000000); +INSERT INTO `zz_area_code` VALUES (321323000000, '泗阳县', 3, 321300000000); +INSERT INTO `zz_area_code` VALUES (321324000000, '泗洪县', 3, 321300000000); +INSERT INTO `zz_area_code` VALUES (321371000000, '宿迁经济技术开发区', 3, 321300000000); +INSERT INTO `zz_area_code` VALUES (330000000000, '浙江省', 1, NULL); +INSERT INTO `zz_area_code` VALUES (330100000000, '杭州市', 2, 330000000000); +INSERT INTO `zz_area_code` VALUES (330101000000, '市辖区', 3, 330100000000); +INSERT INTO `zz_area_code` VALUES (330102000000, '上城区', 3, 330100000000); +INSERT INTO `zz_area_code` VALUES (330103000000, '下城区', 3, 330100000000); +INSERT INTO `zz_area_code` VALUES (330104000000, '江干区', 3, 330100000000); +INSERT INTO `zz_area_code` VALUES (330105000000, '拱墅区', 3, 330100000000); +INSERT INTO `zz_area_code` VALUES (330106000000, '西湖区', 3, 330100000000); +INSERT INTO `zz_area_code` VALUES (330108000000, '滨江区', 3, 330100000000); +INSERT INTO `zz_area_code` VALUES (330109000000, '萧山区', 3, 330100000000); +INSERT INTO `zz_area_code` VALUES (330110000000, '余杭区', 3, 330100000000); +INSERT INTO `zz_area_code` VALUES (330111000000, '富阳区', 3, 330100000000); +INSERT INTO `zz_area_code` VALUES (330112000000, '临安区', 3, 330100000000); +INSERT INTO `zz_area_code` VALUES (330122000000, '桐庐县', 3, 330100000000); +INSERT INTO `zz_area_code` VALUES (330127000000, '淳安县', 3, 330100000000); +INSERT INTO `zz_area_code` VALUES (330182000000, '建德市', 3, 330100000000); +INSERT INTO `zz_area_code` VALUES (330200000000, '宁波市', 2, 330000000000); +INSERT INTO `zz_area_code` VALUES (330201000000, '市辖区', 3, 330200000000); +INSERT INTO `zz_area_code` VALUES (330203000000, '海曙区', 3, 330200000000); +INSERT INTO `zz_area_code` VALUES (330205000000, '江北区', 3, 330200000000); +INSERT INTO `zz_area_code` VALUES (330206000000, '北仑区', 3, 330200000000); +INSERT INTO `zz_area_code` VALUES (330211000000, '镇海区', 3, 330200000000); +INSERT INTO `zz_area_code` VALUES (330212000000, '鄞州区', 3, 330200000000); +INSERT INTO `zz_area_code` VALUES (330213000000, '奉化区', 3, 330200000000); +INSERT INTO `zz_area_code` VALUES (330225000000, '象山县', 3, 330200000000); +INSERT INTO `zz_area_code` VALUES (330226000000, '宁海县', 3, 330200000000); +INSERT INTO `zz_area_code` VALUES (330281000000, '余姚市', 3, 330200000000); +INSERT INTO `zz_area_code` VALUES (330282000000, '慈溪市', 3, 330200000000); +INSERT INTO `zz_area_code` VALUES (330300000000, '温州市', 2, 330000000000); +INSERT INTO `zz_area_code` VALUES (330301000000, '市辖区', 3, 330300000000); +INSERT INTO `zz_area_code` VALUES (330302000000, '鹿城区', 3, 330300000000); +INSERT INTO `zz_area_code` VALUES (330303000000, '龙湾区', 3, 330300000000); +INSERT INTO `zz_area_code` VALUES (330304000000, '瓯海区', 3, 330300000000); +INSERT INTO `zz_area_code` VALUES (330305000000, '洞头区', 3, 330300000000); +INSERT INTO `zz_area_code` VALUES (330324000000, '永嘉县', 3, 330300000000); +INSERT INTO `zz_area_code` VALUES (330326000000, '平阳县', 3, 330300000000); +INSERT INTO `zz_area_code` VALUES (330327000000, '苍南县', 3, 330300000000); +INSERT INTO `zz_area_code` VALUES (330328000000, '文成县', 3, 330300000000); +INSERT INTO `zz_area_code` VALUES (330329000000, '泰顺县', 3, 330300000000); +INSERT INTO `zz_area_code` VALUES (330371000000, '温州经济技术开发区', 3, 330300000000); +INSERT INTO `zz_area_code` VALUES (330381000000, '瑞安市', 3, 330300000000); +INSERT INTO `zz_area_code` VALUES (330382000000, '乐清市', 3, 330300000000); +INSERT INTO `zz_area_code` VALUES (330400000000, '嘉兴市', 2, 330000000000); +INSERT INTO `zz_area_code` VALUES (330401000000, '市辖区', 3, 330400000000); +INSERT INTO `zz_area_code` VALUES (330402000000, '南湖区', 3, 330400000000); +INSERT INTO `zz_area_code` VALUES (330411000000, '秀洲区', 3, 330400000000); +INSERT INTO `zz_area_code` VALUES (330421000000, '嘉善县', 3, 330400000000); +INSERT INTO `zz_area_code` VALUES (330424000000, '海盐县', 3, 330400000000); +INSERT INTO `zz_area_code` VALUES (330481000000, '海宁市', 3, 330400000000); +INSERT INTO `zz_area_code` VALUES (330482000000, '平湖市', 3, 330400000000); +INSERT INTO `zz_area_code` VALUES (330483000000, '桐乡市', 3, 330400000000); +INSERT INTO `zz_area_code` VALUES (330500000000, '湖州市', 2, 330000000000); +INSERT INTO `zz_area_code` VALUES (330501000000, '市辖区', 3, 330500000000); +INSERT INTO `zz_area_code` VALUES (330502000000, '吴兴区', 3, 330500000000); +INSERT INTO `zz_area_code` VALUES (330503000000, '南浔区', 3, 330500000000); +INSERT INTO `zz_area_code` VALUES (330521000000, '德清县', 3, 330500000000); +INSERT INTO `zz_area_code` VALUES (330522000000, '长兴县', 3, 330500000000); +INSERT INTO `zz_area_code` VALUES (330523000000, '安吉县', 3, 330500000000); +INSERT INTO `zz_area_code` VALUES (330600000000, '绍兴市', 2, 330000000000); +INSERT INTO `zz_area_code` VALUES (330601000000, '市辖区', 3, 330600000000); +INSERT INTO `zz_area_code` VALUES (330602000000, '越城区', 3, 330600000000); +INSERT INTO `zz_area_code` VALUES (330603000000, '柯桥区', 3, 330600000000); +INSERT INTO `zz_area_code` VALUES (330604000000, '上虞区', 3, 330600000000); +INSERT INTO `zz_area_code` VALUES (330624000000, '新昌县', 3, 330600000000); +INSERT INTO `zz_area_code` VALUES (330681000000, '诸暨市', 3, 330600000000); +INSERT INTO `zz_area_code` VALUES (330683000000, '嵊州市', 3, 330600000000); +INSERT INTO `zz_area_code` VALUES (330700000000, '金华市', 2, 330000000000); +INSERT INTO `zz_area_code` VALUES (330701000000, '市辖区', 3, 330700000000); +INSERT INTO `zz_area_code` VALUES (330702000000, '婺城区', 3, 330700000000); +INSERT INTO `zz_area_code` VALUES (330703000000, '金东区', 3, 330700000000); +INSERT INTO `zz_area_code` VALUES (330723000000, '武义县', 3, 330700000000); +INSERT INTO `zz_area_code` VALUES (330726000000, '浦江县', 3, 330700000000); +INSERT INTO `zz_area_code` VALUES (330727000000, '磐安县', 3, 330700000000); +INSERT INTO `zz_area_code` VALUES (330781000000, '兰溪市', 3, 330700000000); +INSERT INTO `zz_area_code` VALUES (330782000000, '义乌市', 3, 330700000000); +INSERT INTO `zz_area_code` VALUES (330783000000, '东阳市', 3, 330700000000); +INSERT INTO `zz_area_code` VALUES (330784000000, '永康市', 3, 330700000000); +INSERT INTO `zz_area_code` VALUES (330800000000, '衢州市', 2, 330000000000); +INSERT INTO `zz_area_code` VALUES (330801000000, '市辖区', 3, 330800000000); +INSERT INTO `zz_area_code` VALUES (330802000000, '柯城区', 3, 330800000000); +INSERT INTO `zz_area_code` VALUES (330803000000, '衢江区', 3, 330800000000); +INSERT INTO `zz_area_code` VALUES (330822000000, '常山县', 3, 330800000000); +INSERT INTO `zz_area_code` VALUES (330824000000, '开化县', 3, 330800000000); +INSERT INTO `zz_area_code` VALUES (330825000000, '龙游县', 3, 330800000000); +INSERT INTO `zz_area_code` VALUES (330881000000, '江山市', 3, 330800000000); +INSERT INTO `zz_area_code` VALUES (330900000000, '舟山市', 2, 330000000000); +INSERT INTO `zz_area_code` VALUES (330901000000, '市辖区', 3, 330900000000); +INSERT INTO `zz_area_code` VALUES (330902000000, '定海区', 3, 330900000000); +INSERT INTO `zz_area_code` VALUES (330903000000, '普陀区', 3, 330900000000); +INSERT INTO `zz_area_code` VALUES (330921000000, '岱山县', 3, 330900000000); +INSERT INTO `zz_area_code` VALUES (330922000000, '嵊泗县', 3, 330900000000); +INSERT INTO `zz_area_code` VALUES (331000000000, '台州市', 2, 330000000000); +INSERT INTO `zz_area_code` VALUES (331001000000, '市辖区', 3, 331000000000); +INSERT INTO `zz_area_code` VALUES (331002000000, '椒江区', 3, 331000000000); +INSERT INTO `zz_area_code` VALUES (331003000000, '黄岩区', 3, 331000000000); +INSERT INTO `zz_area_code` VALUES (331004000000, '路桥区', 3, 331000000000); +INSERT INTO `zz_area_code` VALUES (331022000000, '三门县', 3, 331000000000); +INSERT INTO `zz_area_code` VALUES (331023000000, '天台县', 3, 331000000000); +INSERT INTO `zz_area_code` VALUES (331024000000, '仙居县', 3, 331000000000); +INSERT INTO `zz_area_code` VALUES (331081000000, '温岭市', 3, 331000000000); +INSERT INTO `zz_area_code` VALUES (331082000000, '临海市', 3, 331000000000); +INSERT INTO `zz_area_code` VALUES (331083000000, '玉环市', 3, 331000000000); +INSERT INTO `zz_area_code` VALUES (331100000000, '丽水市', 2, 330000000000); +INSERT INTO `zz_area_code` VALUES (331101000000, '市辖区', 3, 331100000000); +INSERT INTO `zz_area_code` VALUES (331102000000, '莲都区', 3, 331100000000); +INSERT INTO `zz_area_code` VALUES (331121000000, '青田县', 3, 331100000000); +INSERT INTO `zz_area_code` VALUES (331122000000, '缙云县', 3, 331100000000); +INSERT INTO `zz_area_code` VALUES (331123000000, '遂昌县', 3, 331100000000); +INSERT INTO `zz_area_code` VALUES (331124000000, '松阳县', 3, 331100000000); +INSERT INTO `zz_area_code` VALUES (331125000000, '云和县', 3, 331100000000); +INSERT INTO `zz_area_code` VALUES (331126000000, '庆元县', 3, 331100000000); +INSERT INTO `zz_area_code` VALUES (331127000000, '景宁畲族自治县', 3, 331100000000); +INSERT INTO `zz_area_code` VALUES (331181000000, '龙泉市', 3, 331100000000); +INSERT INTO `zz_area_code` VALUES (340000000000, '安徽省', 1, NULL); +INSERT INTO `zz_area_code` VALUES (340100000000, '合肥市', 2, 340000000000); +INSERT INTO `zz_area_code` VALUES (340101000000, '市辖区', 3, 340100000000); +INSERT INTO `zz_area_code` VALUES (340102000000, '瑶海区', 3, 340100000000); +INSERT INTO `zz_area_code` VALUES (340103000000, '庐阳区', 3, 340100000000); +INSERT INTO `zz_area_code` VALUES (340104000000, '蜀山区', 3, 340100000000); +INSERT INTO `zz_area_code` VALUES (340111000000, '包河区', 3, 340100000000); +INSERT INTO `zz_area_code` VALUES (340121000000, '长丰县', 3, 340100000000); +INSERT INTO `zz_area_code` VALUES (340122000000, '肥东县', 3, 340100000000); +INSERT INTO `zz_area_code` VALUES (340123000000, '肥西县', 3, 340100000000); +INSERT INTO `zz_area_code` VALUES (340124000000, '庐江县', 3, 340100000000); +INSERT INTO `zz_area_code` VALUES (340171000000, '合肥高新技术产业开发区', 3, 340100000000); +INSERT INTO `zz_area_code` VALUES (340172000000, '合肥经济技术开发区', 3, 340100000000); +INSERT INTO `zz_area_code` VALUES (340173000000, '合肥新站高新技术产业开发区', 3, 340100000000); +INSERT INTO `zz_area_code` VALUES (340181000000, '巢湖市', 3, 340100000000); +INSERT INTO `zz_area_code` VALUES (340200000000, '芜湖市', 2, 340000000000); +INSERT INTO `zz_area_code` VALUES (340201000000, '市辖区', 3, 340200000000); +INSERT INTO `zz_area_code` VALUES (340202000000, '镜湖区', 3, 340200000000); +INSERT INTO `zz_area_code` VALUES (340203000000, '弋江区', 3, 340200000000); +INSERT INTO `zz_area_code` VALUES (340207000000, '鸠江区', 3, 340200000000); +INSERT INTO `zz_area_code` VALUES (340208000000, '三山区', 3, 340200000000); +INSERT INTO `zz_area_code` VALUES (340221000000, '芜湖县', 3, 340200000000); +INSERT INTO `zz_area_code` VALUES (340222000000, '繁昌县', 3, 340200000000); +INSERT INTO `zz_area_code` VALUES (340223000000, '南陵县', 3, 340200000000); +INSERT INTO `zz_area_code` VALUES (340225000000, '无为县', 3, 340200000000); +INSERT INTO `zz_area_code` VALUES (340271000000, '芜湖经济技术开发区', 3, 340200000000); +INSERT INTO `zz_area_code` VALUES (340272000000, '安徽芜湖长江大桥经济开发区', 3, 340200000000); +INSERT INTO `zz_area_code` VALUES (340300000000, '蚌埠市', 2, 340000000000); +INSERT INTO `zz_area_code` VALUES (340301000000, '市辖区', 3, 340300000000); +INSERT INTO `zz_area_code` VALUES (340302000000, '龙子湖区', 3, 340300000000); +INSERT INTO `zz_area_code` VALUES (340303000000, '蚌山区', 3, 340300000000); +INSERT INTO `zz_area_code` VALUES (340304000000, '禹会区', 3, 340300000000); +INSERT INTO `zz_area_code` VALUES (340311000000, '淮上区', 3, 340300000000); +INSERT INTO `zz_area_code` VALUES (340321000000, '怀远县', 3, 340300000000); +INSERT INTO `zz_area_code` VALUES (340322000000, '五河县', 3, 340300000000); +INSERT INTO `zz_area_code` VALUES (340323000000, '固镇县', 3, 340300000000); +INSERT INTO `zz_area_code` VALUES (340371000000, '蚌埠市高新技术开发区', 3, 340300000000); +INSERT INTO `zz_area_code` VALUES (340372000000, '蚌埠市经济开发区', 3, 340300000000); +INSERT INTO `zz_area_code` VALUES (340400000000, '淮南市', 2, 340000000000); +INSERT INTO `zz_area_code` VALUES (340401000000, '市辖区', 3, 340400000000); +INSERT INTO `zz_area_code` VALUES (340402000000, '大通区', 3, 340400000000); +INSERT INTO `zz_area_code` VALUES (340403000000, '田家庵区', 3, 340400000000); +INSERT INTO `zz_area_code` VALUES (340404000000, '谢家集区', 3, 340400000000); +INSERT INTO `zz_area_code` VALUES (340405000000, '八公山区', 3, 340400000000); +INSERT INTO `zz_area_code` VALUES (340406000000, '潘集区', 3, 340400000000); +INSERT INTO `zz_area_code` VALUES (340421000000, '凤台县', 3, 340400000000); +INSERT INTO `zz_area_code` VALUES (340422000000, '寿县', 3, 340400000000); +INSERT INTO `zz_area_code` VALUES (340500000000, '马鞍山市', 2, 340000000000); +INSERT INTO `zz_area_code` VALUES (340501000000, '市辖区', 3, 340500000000); +INSERT INTO `zz_area_code` VALUES (340503000000, '花山区', 3, 340500000000); +INSERT INTO `zz_area_code` VALUES (340504000000, '雨山区', 3, 340500000000); +INSERT INTO `zz_area_code` VALUES (340506000000, '博望区', 3, 340500000000); +INSERT INTO `zz_area_code` VALUES (340521000000, '当涂县', 3, 340500000000); +INSERT INTO `zz_area_code` VALUES (340522000000, '含山县', 3, 340500000000); +INSERT INTO `zz_area_code` VALUES (340523000000, '和县', 3, 340500000000); +INSERT INTO `zz_area_code` VALUES (340600000000, '淮北市', 2, 340000000000); +INSERT INTO `zz_area_code` VALUES (340601000000, '市辖区', 3, 340600000000); +INSERT INTO `zz_area_code` VALUES (340602000000, '杜集区', 3, 340600000000); +INSERT INTO `zz_area_code` VALUES (340603000000, '相山区', 3, 340600000000); +INSERT INTO `zz_area_code` VALUES (340604000000, '烈山区', 3, 340600000000); +INSERT INTO `zz_area_code` VALUES (340621000000, '濉溪县', 3, 340600000000); +INSERT INTO `zz_area_code` VALUES (340700000000, '铜陵市', 2, 340000000000); +INSERT INTO `zz_area_code` VALUES (340701000000, '市辖区', 3, 340700000000); +INSERT INTO `zz_area_code` VALUES (340705000000, '铜官区', 3, 340700000000); +INSERT INTO `zz_area_code` VALUES (340706000000, '义安区', 3, 340700000000); +INSERT INTO `zz_area_code` VALUES (340711000000, '郊区', 3, 340700000000); +INSERT INTO `zz_area_code` VALUES (340722000000, '枞阳县', 3, 340700000000); +INSERT INTO `zz_area_code` VALUES (340800000000, '安庆市', 2, 340000000000); +INSERT INTO `zz_area_code` VALUES (340801000000, '市辖区', 3, 340800000000); +INSERT INTO `zz_area_code` VALUES (340802000000, '迎江区', 3, 340800000000); +INSERT INTO `zz_area_code` VALUES (340803000000, '大观区', 3, 340800000000); +INSERT INTO `zz_area_code` VALUES (340811000000, '宜秀区', 3, 340800000000); +INSERT INTO `zz_area_code` VALUES (340822000000, '怀宁县', 3, 340800000000); +INSERT INTO `zz_area_code` VALUES (340825000000, '太湖县', 3, 340800000000); +INSERT INTO `zz_area_code` VALUES (340826000000, '宿松县', 3, 340800000000); +INSERT INTO `zz_area_code` VALUES (340827000000, '望江县', 3, 340800000000); +INSERT INTO `zz_area_code` VALUES (340828000000, '岳西县', 3, 340800000000); +INSERT INTO `zz_area_code` VALUES (340871000000, '安徽安庆经济开发区', 3, 340800000000); +INSERT INTO `zz_area_code` VALUES (340881000000, '桐城市', 3, 340800000000); +INSERT INTO `zz_area_code` VALUES (340882000000, '潜山市', 3, 340800000000); +INSERT INTO `zz_area_code` VALUES (341000000000, '黄山市', 2, 340000000000); +INSERT INTO `zz_area_code` VALUES (341001000000, '市辖区', 3, 341000000000); +INSERT INTO `zz_area_code` VALUES (341002000000, '屯溪区', 3, 341000000000); +INSERT INTO `zz_area_code` VALUES (341003000000, '黄山区', 3, 341000000000); +INSERT INTO `zz_area_code` VALUES (341004000000, '徽州区', 3, 341000000000); +INSERT INTO `zz_area_code` VALUES (341021000000, '歙县', 3, 341000000000); +INSERT INTO `zz_area_code` VALUES (341022000000, '休宁县', 3, 341000000000); +INSERT INTO `zz_area_code` VALUES (341023000000, '黟县', 3, 341000000000); +INSERT INTO `zz_area_code` VALUES (341024000000, '祁门县', 3, 341000000000); +INSERT INTO `zz_area_code` VALUES (341100000000, '滁州市', 2, 340000000000); +INSERT INTO `zz_area_code` VALUES (341101000000, '市辖区', 3, 341100000000); +INSERT INTO `zz_area_code` VALUES (341102000000, '琅琊区', 3, 341100000000); +INSERT INTO `zz_area_code` VALUES (341103000000, '南谯区', 3, 341100000000); +INSERT INTO `zz_area_code` VALUES (341122000000, '来安县', 3, 341100000000); +INSERT INTO `zz_area_code` VALUES (341124000000, '全椒县', 3, 341100000000); +INSERT INTO `zz_area_code` VALUES (341125000000, '定远县', 3, 341100000000); +INSERT INTO `zz_area_code` VALUES (341126000000, '凤阳县', 3, 341100000000); +INSERT INTO `zz_area_code` VALUES (341171000000, '苏滁现代产业园', 3, 341100000000); +INSERT INTO `zz_area_code` VALUES (341172000000, '滁州经济技术开发区', 3, 341100000000); +INSERT INTO `zz_area_code` VALUES (341181000000, '天长市', 3, 341100000000); +INSERT INTO `zz_area_code` VALUES (341182000000, '明光市', 3, 341100000000); +INSERT INTO `zz_area_code` VALUES (341200000000, '阜阳市', 2, 340000000000); +INSERT INTO `zz_area_code` VALUES (341201000000, '市辖区', 3, 341200000000); +INSERT INTO `zz_area_code` VALUES (341202000000, '颍州区', 3, 341200000000); +INSERT INTO `zz_area_code` VALUES (341203000000, '颍东区', 3, 341200000000); +INSERT INTO `zz_area_code` VALUES (341204000000, '颍泉区', 3, 341200000000); +INSERT INTO `zz_area_code` VALUES (341221000000, '临泉县', 3, 341200000000); +INSERT INTO `zz_area_code` VALUES (341222000000, '太和县', 3, 341200000000); +INSERT INTO `zz_area_code` VALUES (341225000000, '阜南县', 3, 341200000000); +INSERT INTO `zz_area_code` VALUES (341226000000, '颍上县', 3, 341200000000); +INSERT INTO `zz_area_code` VALUES (341271000000, '阜阳合肥现代产业园区', 3, 341200000000); +INSERT INTO `zz_area_code` VALUES (341272000000, '阜阳经济技术开发区', 3, 341200000000); +INSERT INTO `zz_area_code` VALUES (341282000000, '界首市', 3, 341200000000); +INSERT INTO `zz_area_code` VALUES (341300000000, '宿州市', 2, 340000000000); +INSERT INTO `zz_area_code` VALUES (341301000000, '市辖区', 3, 341300000000); +INSERT INTO `zz_area_code` VALUES (341302000000, '埇桥区', 3, 341300000000); +INSERT INTO `zz_area_code` VALUES (341321000000, '砀山县', 3, 341300000000); +INSERT INTO `zz_area_code` VALUES (341322000000, '萧县', 3, 341300000000); +INSERT INTO `zz_area_code` VALUES (341323000000, '灵璧县', 3, 341300000000); +INSERT INTO `zz_area_code` VALUES (341324000000, '泗县', 3, 341300000000); +INSERT INTO `zz_area_code` VALUES (341371000000, '宿州马鞍山现代产业园区', 3, 341300000000); +INSERT INTO `zz_area_code` VALUES (341372000000, '宿州经济技术开发区', 3, 341300000000); +INSERT INTO `zz_area_code` VALUES (341500000000, '六安市', 2, 340000000000); +INSERT INTO `zz_area_code` VALUES (341501000000, '市辖区', 3, 341500000000); +INSERT INTO `zz_area_code` VALUES (341502000000, '金安区', 3, 341500000000); +INSERT INTO `zz_area_code` VALUES (341503000000, '裕安区', 3, 341500000000); +INSERT INTO `zz_area_code` VALUES (341504000000, '叶集区', 3, 341500000000); +INSERT INTO `zz_area_code` VALUES (341522000000, '霍邱县', 3, 341500000000); +INSERT INTO `zz_area_code` VALUES (341523000000, '舒城县', 3, 341500000000); +INSERT INTO `zz_area_code` VALUES (341524000000, '金寨县', 3, 341500000000); +INSERT INTO `zz_area_code` VALUES (341525000000, '霍山县', 3, 341500000000); +INSERT INTO `zz_area_code` VALUES (341600000000, '亳州市', 2, 340000000000); +INSERT INTO `zz_area_code` VALUES (341601000000, '市辖区', 3, 341600000000); +INSERT INTO `zz_area_code` VALUES (341602000000, '谯城区', 3, 341600000000); +INSERT INTO `zz_area_code` VALUES (341621000000, '涡阳县', 3, 341600000000); +INSERT INTO `zz_area_code` VALUES (341622000000, '蒙城县', 3, 341600000000); +INSERT INTO `zz_area_code` VALUES (341623000000, '利辛县', 3, 341600000000); +INSERT INTO `zz_area_code` VALUES (341700000000, '池州市', 2, 340000000000); +INSERT INTO `zz_area_code` VALUES (341701000000, '市辖区', 3, 341700000000); +INSERT INTO `zz_area_code` VALUES (341702000000, '贵池区', 3, 341700000000); +INSERT INTO `zz_area_code` VALUES (341721000000, '东至县', 3, 341700000000); +INSERT INTO `zz_area_code` VALUES (341722000000, '石台县', 3, 341700000000); +INSERT INTO `zz_area_code` VALUES (341723000000, '青阳县', 3, 341700000000); +INSERT INTO `zz_area_code` VALUES (341800000000, '宣城市', 2, 340000000000); +INSERT INTO `zz_area_code` VALUES (341801000000, '市辖区', 3, 341800000000); +INSERT INTO `zz_area_code` VALUES (341802000000, '宣州区', 3, 341800000000); +INSERT INTO `zz_area_code` VALUES (341821000000, '郎溪县', 3, 341800000000); +INSERT INTO `zz_area_code` VALUES (341822000000, '广德县', 3, 341800000000); +INSERT INTO `zz_area_code` VALUES (341823000000, '泾县', 3, 341800000000); +INSERT INTO `zz_area_code` VALUES (341824000000, '绩溪县', 3, 341800000000); +INSERT INTO `zz_area_code` VALUES (341825000000, '旌德县', 3, 341800000000); +INSERT INTO `zz_area_code` VALUES (341871000000, '宣城市经济开发区', 3, 341800000000); +INSERT INTO `zz_area_code` VALUES (341881000000, '宁国市', 3, 341800000000); +INSERT INTO `zz_area_code` VALUES (350000000000, '福建省', 1, NULL); +INSERT INTO `zz_area_code` VALUES (350100000000, '福州市', 2, 350000000000); +INSERT INTO `zz_area_code` VALUES (350101000000, '市辖区', 3, 350100000000); +INSERT INTO `zz_area_code` VALUES (350102000000, '鼓楼区', 3, 350100000000); +INSERT INTO `zz_area_code` VALUES (350103000000, '台江区', 3, 350100000000); +INSERT INTO `zz_area_code` VALUES (350104000000, '仓山区', 3, 350100000000); +INSERT INTO `zz_area_code` VALUES (350105000000, '马尾区', 3, 350100000000); +INSERT INTO `zz_area_code` VALUES (350111000000, '晋安区', 3, 350100000000); +INSERT INTO `zz_area_code` VALUES (350112000000, '长乐区', 3, 350100000000); +INSERT INTO `zz_area_code` VALUES (350121000000, '闽侯县', 3, 350100000000); +INSERT INTO `zz_area_code` VALUES (350122000000, '连江县', 3, 350100000000); +INSERT INTO `zz_area_code` VALUES (350123000000, '罗源县', 3, 350100000000); +INSERT INTO `zz_area_code` VALUES (350124000000, '闽清县', 3, 350100000000); +INSERT INTO `zz_area_code` VALUES (350125000000, '永泰县', 3, 350100000000); +INSERT INTO `zz_area_code` VALUES (350128000000, '平潭县', 3, 350100000000); +INSERT INTO `zz_area_code` VALUES (350181000000, '福清市', 3, 350100000000); +INSERT INTO `zz_area_code` VALUES (350200000000, '厦门市', 2, 350000000000); +INSERT INTO `zz_area_code` VALUES (350201000000, '市辖区', 3, 350200000000); +INSERT INTO `zz_area_code` VALUES (350203000000, '思明区', 3, 350200000000); +INSERT INTO `zz_area_code` VALUES (350205000000, '海沧区', 3, 350200000000); +INSERT INTO `zz_area_code` VALUES (350206000000, '湖里区', 3, 350200000000); +INSERT INTO `zz_area_code` VALUES (350211000000, '集美区', 3, 350200000000); +INSERT INTO `zz_area_code` VALUES (350212000000, '同安区', 3, 350200000000); +INSERT INTO `zz_area_code` VALUES (350213000000, '翔安区', 3, 350200000000); +INSERT INTO `zz_area_code` VALUES (350300000000, '莆田市', 2, 350000000000); +INSERT INTO `zz_area_code` VALUES (350301000000, '市辖区', 3, 350300000000); +INSERT INTO `zz_area_code` VALUES (350302000000, '城厢区', 3, 350300000000); +INSERT INTO `zz_area_code` VALUES (350303000000, '涵江区', 3, 350300000000); +INSERT INTO `zz_area_code` VALUES (350304000000, '荔城区', 3, 350300000000); +INSERT INTO `zz_area_code` VALUES (350305000000, '秀屿区', 3, 350300000000); +INSERT INTO `zz_area_code` VALUES (350322000000, '仙游县', 3, 350300000000); +INSERT INTO `zz_area_code` VALUES (350400000000, '三明市', 2, 350000000000); +INSERT INTO `zz_area_code` VALUES (350401000000, '市辖区', 3, 350400000000); +INSERT INTO `zz_area_code` VALUES (350402000000, '梅列区', 3, 350400000000); +INSERT INTO `zz_area_code` VALUES (350403000000, '三元区', 3, 350400000000); +INSERT INTO `zz_area_code` VALUES (350421000000, '明溪县', 3, 350400000000); +INSERT INTO `zz_area_code` VALUES (350423000000, '清流县', 3, 350400000000); +INSERT INTO `zz_area_code` VALUES (350424000000, '宁化县', 3, 350400000000); +INSERT INTO `zz_area_code` VALUES (350425000000, '大田县', 3, 350400000000); +INSERT INTO `zz_area_code` VALUES (350426000000, '尤溪县', 3, 350400000000); +INSERT INTO `zz_area_code` VALUES (350427000000, '沙县', 3, 350400000000); +INSERT INTO `zz_area_code` VALUES (350428000000, '将乐县', 3, 350400000000); +INSERT INTO `zz_area_code` VALUES (350429000000, '泰宁县', 3, 350400000000); +INSERT INTO `zz_area_code` VALUES (350430000000, '建宁县', 3, 350400000000); +INSERT INTO `zz_area_code` VALUES (350481000000, '永安市', 3, 350400000000); +INSERT INTO `zz_area_code` VALUES (350500000000, '泉州市', 2, 350000000000); +INSERT INTO `zz_area_code` VALUES (350501000000, '市辖区', 3, 350500000000); +INSERT INTO `zz_area_code` VALUES (350502000000, '鲤城区', 3, 350500000000); +INSERT INTO `zz_area_code` VALUES (350503000000, '丰泽区', 3, 350500000000); +INSERT INTO `zz_area_code` VALUES (350504000000, '洛江区', 3, 350500000000); +INSERT INTO `zz_area_code` VALUES (350505000000, '泉港区', 3, 350500000000); +INSERT INTO `zz_area_code` VALUES (350521000000, '惠安县', 3, 350500000000); +INSERT INTO `zz_area_code` VALUES (350524000000, '安溪县', 3, 350500000000); +INSERT INTO `zz_area_code` VALUES (350525000000, '永春县', 3, 350500000000); +INSERT INTO `zz_area_code` VALUES (350526000000, '德化县', 3, 350500000000); +INSERT INTO `zz_area_code` VALUES (350527000000, '金门县', 3, 350500000000); +INSERT INTO `zz_area_code` VALUES (350581000000, '石狮市', 3, 350500000000); +INSERT INTO `zz_area_code` VALUES (350582000000, '晋江市', 3, 350500000000); +INSERT INTO `zz_area_code` VALUES (350583000000, '南安市', 3, 350500000000); +INSERT INTO `zz_area_code` VALUES (350600000000, '漳州市', 2, 350000000000); +INSERT INTO `zz_area_code` VALUES (350601000000, '市辖区', 3, 350600000000); +INSERT INTO `zz_area_code` VALUES (350602000000, '芗城区', 3, 350600000000); +INSERT INTO `zz_area_code` VALUES (350603000000, '龙文区', 3, 350600000000); +INSERT INTO `zz_area_code` VALUES (350622000000, '云霄县', 3, 350600000000); +INSERT INTO `zz_area_code` VALUES (350623000000, '漳浦县', 3, 350600000000); +INSERT INTO `zz_area_code` VALUES (350624000000, '诏安县', 3, 350600000000); +INSERT INTO `zz_area_code` VALUES (350625000000, '长泰县', 3, 350600000000); +INSERT INTO `zz_area_code` VALUES (350626000000, '东山县', 3, 350600000000); +INSERT INTO `zz_area_code` VALUES (350627000000, '南靖县', 3, 350600000000); +INSERT INTO `zz_area_code` VALUES (350628000000, '平和县', 3, 350600000000); +INSERT INTO `zz_area_code` VALUES (350629000000, '华安县', 3, 350600000000); +INSERT INTO `zz_area_code` VALUES (350681000000, '龙海市', 3, 350600000000); +INSERT INTO `zz_area_code` VALUES (350700000000, '南平市', 2, 350000000000); +INSERT INTO `zz_area_code` VALUES (350701000000, '市辖区', 3, 350700000000); +INSERT INTO `zz_area_code` VALUES (350702000000, '延平区', 3, 350700000000); +INSERT INTO `zz_area_code` VALUES (350703000000, '建阳区', 3, 350700000000); +INSERT INTO `zz_area_code` VALUES (350721000000, '顺昌县', 3, 350700000000); +INSERT INTO `zz_area_code` VALUES (350722000000, '浦城县', 3, 350700000000); +INSERT INTO `zz_area_code` VALUES (350723000000, '光泽县', 3, 350700000000); +INSERT INTO `zz_area_code` VALUES (350724000000, '松溪县', 3, 350700000000); +INSERT INTO `zz_area_code` VALUES (350725000000, '政和县', 3, 350700000000); +INSERT INTO `zz_area_code` VALUES (350781000000, '邵武市', 3, 350700000000); +INSERT INTO `zz_area_code` VALUES (350782000000, '武夷山市', 3, 350700000000); +INSERT INTO `zz_area_code` VALUES (350783000000, '建瓯市', 3, 350700000000); +INSERT INTO `zz_area_code` VALUES (350800000000, '龙岩市', 2, 350000000000); +INSERT INTO `zz_area_code` VALUES (350801000000, '市辖区', 3, 350800000000); +INSERT INTO `zz_area_code` VALUES (350802000000, '新罗区', 3, 350800000000); +INSERT INTO `zz_area_code` VALUES (350803000000, '永定区', 3, 350800000000); +INSERT INTO `zz_area_code` VALUES (350821000000, '长汀县', 3, 350800000000); +INSERT INTO `zz_area_code` VALUES (350823000000, '上杭县', 3, 350800000000); +INSERT INTO `zz_area_code` VALUES (350824000000, '武平县', 3, 350800000000); +INSERT INTO `zz_area_code` VALUES (350825000000, '连城县', 3, 350800000000); +INSERT INTO `zz_area_code` VALUES (350881000000, '漳平市', 3, 350800000000); +INSERT INTO `zz_area_code` VALUES (350900000000, '宁德市', 2, 350000000000); +INSERT INTO `zz_area_code` VALUES (350901000000, '市辖区', 3, 350900000000); +INSERT INTO `zz_area_code` VALUES (350902000000, '蕉城区', 3, 350900000000); +INSERT INTO `zz_area_code` VALUES (350921000000, '霞浦县', 3, 350900000000); +INSERT INTO `zz_area_code` VALUES (350922000000, '古田县', 3, 350900000000); +INSERT INTO `zz_area_code` VALUES (350923000000, '屏南县', 3, 350900000000); +INSERT INTO `zz_area_code` VALUES (350924000000, '寿宁县', 3, 350900000000); +INSERT INTO `zz_area_code` VALUES (350925000000, '周宁县', 3, 350900000000); +INSERT INTO `zz_area_code` VALUES (350926000000, '柘荣县', 3, 350900000000); +INSERT INTO `zz_area_code` VALUES (350981000000, '福安市', 3, 350900000000); +INSERT INTO `zz_area_code` VALUES (350982000000, '福鼎市', 3, 350900000000); +INSERT INTO `zz_area_code` VALUES (360000000000, '江西省', 1, NULL); +INSERT INTO `zz_area_code` VALUES (360100000000, '南昌市', 2, 360000000000); +INSERT INTO `zz_area_code` VALUES (360101000000, '市辖区', 3, 360100000000); +INSERT INTO `zz_area_code` VALUES (360102000000, '东湖区', 3, 360100000000); +INSERT INTO `zz_area_code` VALUES (360103000000, '西湖区', 3, 360100000000); +INSERT INTO `zz_area_code` VALUES (360104000000, '青云谱区', 3, 360100000000); +INSERT INTO `zz_area_code` VALUES (360105000000, '湾里区', 3, 360100000000); +INSERT INTO `zz_area_code` VALUES (360111000000, '青山湖区', 3, 360100000000); +INSERT INTO `zz_area_code` VALUES (360112000000, '新建区', 3, 360100000000); +INSERT INTO `zz_area_code` VALUES (360121000000, '南昌县', 3, 360100000000); +INSERT INTO `zz_area_code` VALUES (360123000000, '安义县', 3, 360100000000); +INSERT INTO `zz_area_code` VALUES (360124000000, '进贤县', 3, 360100000000); +INSERT INTO `zz_area_code` VALUES (360200000000, '景德镇市', 2, 360000000000); +INSERT INTO `zz_area_code` VALUES (360201000000, '市辖区', 3, 360200000000); +INSERT INTO `zz_area_code` VALUES (360202000000, '昌江区', 3, 360200000000); +INSERT INTO `zz_area_code` VALUES (360203000000, '珠山区', 3, 360200000000); +INSERT INTO `zz_area_code` VALUES (360222000000, '浮梁县', 3, 360200000000); +INSERT INTO `zz_area_code` VALUES (360281000000, '乐平市', 3, 360200000000); +INSERT INTO `zz_area_code` VALUES (360300000000, '萍乡市', 2, 360000000000); +INSERT INTO `zz_area_code` VALUES (360301000000, '市辖区', 3, 360300000000); +INSERT INTO `zz_area_code` VALUES (360302000000, '安源区', 3, 360300000000); +INSERT INTO `zz_area_code` VALUES (360313000000, '湘东区', 3, 360300000000); +INSERT INTO `zz_area_code` VALUES (360321000000, '莲花县', 3, 360300000000); +INSERT INTO `zz_area_code` VALUES (360322000000, '上栗县', 3, 360300000000); +INSERT INTO `zz_area_code` VALUES (360323000000, '芦溪县', 3, 360300000000); +INSERT INTO `zz_area_code` VALUES (360400000000, '九江市', 2, 360000000000); +INSERT INTO `zz_area_code` VALUES (360401000000, '市辖区', 3, 360400000000); +INSERT INTO `zz_area_code` VALUES (360402000000, '濂溪区', 3, 360400000000); +INSERT INTO `zz_area_code` VALUES (360403000000, '浔阳区', 3, 360400000000); +INSERT INTO `zz_area_code` VALUES (360404000000, '柴桑区', 3, 360400000000); +INSERT INTO `zz_area_code` VALUES (360423000000, '武宁县', 3, 360400000000); +INSERT INTO `zz_area_code` VALUES (360424000000, '修水县', 3, 360400000000); +INSERT INTO `zz_area_code` VALUES (360425000000, '永修县', 3, 360400000000); +INSERT INTO `zz_area_code` VALUES (360426000000, '德安县', 3, 360400000000); +INSERT INTO `zz_area_code` VALUES (360428000000, '都昌县', 3, 360400000000); +INSERT INTO `zz_area_code` VALUES (360429000000, '湖口县', 3, 360400000000); +INSERT INTO `zz_area_code` VALUES (360430000000, '彭泽县', 3, 360400000000); +INSERT INTO `zz_area_code` VALUES (360481000000, '瑞昌市', 3, 360400000000); +INSERT INTO `zz_area_code` VALUES (360482000000, '共青城市', 3, 360400000000); +INSERT INTO `zz_area_code` VALUES (360483000000, '庐山市', 3, 360400000000); +INSERT INTO `zz_area_code` VALUES (360500000000, '新余市', 2, 360000000000); +INSERT INTO `zz_area_code` VALUES (360501000000, '市辖区', 3, 360500000000); +INSERT INTO `zz_area_code` VALUES (360502000000, '渝水区', 3, 360500000000); +INSERT INTO `zz_area_code` VALUES (360521000000, '分宜县', 3, 360500000000); +INSERT INTO `zz_area_code` VALUES (360600000000, '鹰潭市', 2, 360000000000); +INSERT INTO `zz_area_code` VALUES (360601000000, '市辖区', 3, 360600000000); +INSERT INTO `zz_area_code` VALUES (360602000000, '月湖区', 3, 360600000000); +INSERT INTO `zz_area_code` VALUES (360603000000, '余江区', 3, 360600000000); +INSERT INTO `zz_area_code` VALUES (360681000000, '贵溪市', 3, 360600000000); +INSERT INTO `zz_area_code` VALUES (360700000000, '赣州市', 2, 360000000000); +INSERT INTO `zz_area_code` VALUES (360701000000, '市辖区', 3, 360700000000); +INSERT INTO `zz_area_code` VALUES (360702000000, '章贡区', 3, 360700000000); +INSERT INTO `zz_area_code` VALUES (360703000000, '南康区', 3, 360700000000); +INSERT INTO `zz_area_code` VALUES (360704000000, '赣县区', 3, 360700000000); +INSERT INTO `zz_area_code` VALUES (360722000000, '信丰县', 3, 360700000000); +INSERT INTO `zz_area_code` VALUES (360723000000, '大余县', 3, 360700000000); +INSERT INTO `zz_area_code` VALUES (360724000000, '上犹县', 3, 360700000000); +INSERT INTO `zz_area_code` VALUES (360725000000, '崇义县', 3, 360700000000); +INSERT INTO `zz_area_code` VALUES (360726000000, '安远县', 3, 360700000000); +INSERT INTO `zz_area_code` VALUES (360727000000, '龙南县', 3, 360700000000); +INSERT INTO `zz_area_code` VALUES (360728000000, '定南县', 3, 360700000000); +INSERT INTO `zz_area_code` VALUES (360729000000, '全南县', 3, 360700000000); +INSERT INTO `zz_area_code` VALUES (360730000000, '宁都县', 3, 360700000000); +INSERT INTO `zz_area_code` VALUES (360731000000, '于都县', 3, 360700000000); +INSERT INTO `zz_area_code` VALUES (360732000000, '兴国县', 3, 360700000000); +INSERT INTO `zz_area_code` VALUES (360733000000, '会昌县', 3, 360700000000); +INSERT INTO `zz_area_code` VALUES (360734000000, '寻乌县', 3, 360700000000); +INSERT INTO `zz_area_code` VALUES (360735000000, '石城县', 3, 360700000000); +INSERT INTO `zz_area_code` VALUES (360781000000, '瑞金市', 3, 360700000000); +INSERT INTO `zz_area_code` VALUES (360800000000, '吉安市', 2, 360000000000); +INSERT INTO `zz_area_code` VALUES (360801000000, '市辖区', 3, 360800000000); +INSERT INTO `zz_area_code` VALUES (360802000000, '吉州区', 3, 360800000000); +INSERT INTO `zz_area_code` VALUES (360803000000, '青原区', 3, 360800000000); +INSERT INTO `zz_area_code` VALUES (360821000000, '吉安县', 3, 360800000000); +INSERT INTO `zz_area_code` VALUES (360822000000, '吉水县', 3, 360800000000); +INSERT INTO `zz_area_code` VALUES (360823000000, '峡江县', 3, 360800000000); +INSERT INTO `zz_area_code` VALUES (360824000000, '新干县', 3, 360800000000); +INSERT INTO `zz_area_code` VALUES (360825000000, '永丰县', 3, 360800000000); +INSERT INTO `zz_area_code` VALUES (360826000000, '泰和县', 3, 360800000000); +INSERT INTO `zz_area_code` VALUES (360827000000, '遂川县', 3, 360800000000); +INSERT INTO `zz_area_code` VALUES (360828000000, '万安县', 3, 360800000000); +INSERT INTO `zz_area_code` VALUES (360829000000, '安福县', 3, 360800000000); +INSERT INTO `zz_area_code` VALUES (360830000000, '永新县', 3, 360800000000); +INSERT INTO `zz_area_code` VALUES (360881000000, '井冈山市', 3, 360800000000); +INSERT INTO `zz_area_code` VALUES (360900000000, '宜春市', 2, 360000000000); +INSERT INTO `zz_area_code` VALUES (360901000000, '市辖区', 3, 360900000000); +INSERT INTO `zz_area_code` VALUES (360902000000, '袁州区', 3, 360900000000); +INSERT INTO `zz_area_code` VALUES (360921000000, '奉新县', 3, 360900000000); +INSERT INTO `zz_area_code` VALUES (360922000000, '万载县', 3, 360900000000); +INSERT INTO `zz_area_code` VALUES (360923000000, '上高县', 3, 360900000000); +INSERT INTO `zz_area_code` VALUES (360924000000, '宜丰县', 3, 360900000000); +INSERT INTO `zz_area_code` VALUES (360925000000, '靖安县', 3, 360900000000); +INSERT INTO `zz_area_code` VALUES (360926000000, '铜鼓县', 3, 360900000000); +INSERT INTO `zz_area_code` VALUES (360981000000, '丰城市', 3, 360900000000); +INSERT INTO `zz_area_code` VALUES (360982000000, '樟树市', 3, 360900000000); +INSERT INTO `zz_area_code` VALUES (360983000000, '高安市', 3, 360900000000); +INSERT INTO `zz_area_code` VALUES (361000000000, '抚州市', 2, 360000000000); +INSERT INTO `zz_area_code` VALUES (361001000000, '市辖区', 3, 361000000000); +INSERT INTO `zz_area_code` VALUES (361002000000, '临川区', 3, 361000000000); +INSERT INTO `zz_area_code` VALUES (361003000000, '东乡区', 3, 361000000000); +INSERT INTO `zz_area_code` VALUES (361021000000, '南城县', 3, 361000000000); +INSERT INTO `zz_area_code` VALUES (361022000000, '黎川县', 3, 361000000000); +INSERT INTO `zz_area_code` VALUES (361023000000, '南丰县', 3, 361000000000); +INSERT INTO `zz_area_code` VALUES (361024000000, '崇仁县', 3, 361000000000); +INSERT INTO `zz_area_code` VALUES (361025000000, '乐安县', 3, 361000000000); +INSERT INTO `zz_area_code` VALUES (361026000000, '宜黄县', 3, 361000000000); +INSERT INTO `zz_area_code` VALUES (361027000000, '金溪县', 3, 361000000000); +INSERT INTO `zz_area_code` VALUES (361028000000, '资溪县', 3, 361000000000); +INSERT INTO `zz_area_code` VALUES (361030000000, '广昌县', 3, 361000000000); +INSERT INTO `zz_area_code` VALUES (361100000000, '上饶市', 2, 360000000000); +INSERT INTO `zz_area_code` VALUES (361101000000, '市辖区', 3, 361100000000); +INSERT INTO `zz_area_code` VALUES (361102000000, '信州区', 3, 361100000000); +INSERT INTO `zz_area_code` VALUES (361103000000, '广丰区', 3, 361100000000); +INSERT INTO `zz_area_code` VALUES (361121000000, '上饶县', 3, 361100000000); +INSERT INTO `zz_area_code` VALUES (361123000000, '玉山县', 3, 361100000000); +INSERT INTO `zz_area_code` VALUES (361124000000, '铅山县', 3, 361100000000); +INSERT INTO `zz_area_code` VALUES (361125000000, '横峰县', 3, 361100000000); +INSERT INTO `zz_area_code` VALUES (361126000000, '弋阳县', 3, 361100000000); +INSERT INTO `zz_area_code` VALUES (361127000000, '余干县', 3, 361100000000); +INSERT INTO `zz_area_code` VALUES (361128000000, '鄱阳县', 3, 361100000000); +INSERT INTO `zz_area_code` VALUES (361129000000, '万年县', 3, 361100000000); +INSERT INTO `zz_area_code` VALUES (361130000000, '婺源县', 3, 361100000000); +INSERT INTO `zz_area_code` VALUES (361181000000, '德兴市', 3, 361100000000); +INSERT INTO `zz_area_code` VALUES (370000000000, '山东省', 1, NULL); +INSERT INTO `zz_area_code` VALUES (370100000000, '济南市', 2, 370000000000); +INSERT INTO `zz_area_code` VALUES (370101000000, '市辖区', 3, 370100000000); +INSERT INTO `zz_area_code` VALUES (370102000000, '历下区', 3, 370100000000); +INSERT INTO `zz_area_code` VALUES (370103000000, '市中区', 3, 370100000000); +INSERT INTO `zz_area_code` VALUES (370104000000, '槐荫区', 3, 370100000000); +INSERT INTO `zz_area_code` VALUES (370105000000, '天桥区', 3, 370100000000); +INSERT INTO `zz_area_code` VALUES (370112000000, '历城区', 3, 370100000000); +INSERT INTO `zz_area_code` VALUES (370113000000, '长清区', 3, 370100000000); +INSERT INTO `zz_area_code` VALUES (370114000000, '章丘区', 3, 370100000000); +INSERT INTO `zz_area_code` VALUES (370115000000, '济阳区', 3, 370100000000); +INSERT INTO `zz_area_code` VALUES (370124000000, '平阴县', 3, 370100000000); +INSERT INTO `zz_area_code` VALUES (370126000000, '商河县', 3, 370100000000); +INSERT INTO `zz_area_code` VALUES (370171000000, '济南高新技术产业开发区', 3, 370100000000); +INSERT INTO `zz_area_code` VALUES (370200000000, '青岛市', 2, 370000000000); +INSERT INTO `zz_area_code` VALUES (370201000000, '市辖区', 3, 370200000000); +INSERT INTO `zz_area_code` VALUES (370202000000, '市南区', 3, 370200000000); +INSERT INTO `zz_area_code` VALUES (370203000000, '市北区', 3, 370200000000); +INSERT INTO `zz_area_code` VALUES (370211000000, '黄岛区', 3, 370200000000); +INSERT INTO `zz_area_code` VALUES (370212000000, '崂山区', 3, 370200000000); +INSERT INTO `zz_area_code` VALUES (370213000000, '李沧区', 3, 370200000000); +INSERT INTO `zz_area_code` VALUES (370214000000, '城阳区', 3, 370200000000); +INSERT INTO `zz_area_code` VALUES (370215000000, '即墨区', 3, 370200000000); +INSERT INTO `zz_area_code` VALUES (370271000000, '青岛高新技术产业开发区', 3, 370200000000); +INSERT INTO `zz_area_code` VALUES (370281000000, '胶州市', 3, 370200000000); +INSERT INTO `zz_area_code` VALUES (370283000000, '平度市', 3, 370200000000); +INSERT INTO `zz_area_code` VALUES (370285000000, '莱西市', 3, 370200000000); +INSERT INTO `zz_area_code` VALUES (370300000000, '淄博市', 2, 370000000000); +INSERT INTO `zz_area_code` VALUES (370301000000, '市辖区', 3, 370300000000); +INSERT INTO `zz_area_code` VALUES (370302000000, '淄川区', 3, 370300000000); +INSERT INTO `zz_area_code` VALUES (370303000000, '张店区', 3, 370300000000); +INSERT INTO `zz_area_code` VALUES (370304000000, '博山区', 3, 370300000000); +INSERT INTO `zz_area_code` VALUES (370305000000, '临淄区', 3, 370300000000); +INSERT INTO `zz_area_code` VALUES (370306000000, '周村区', 3, 370300000000); +INSERT INTO `zz_area_code` VALUES (370321000000, '桓台县', 3, 370300000000); +INSERT INTO `zz_area_code` VALUES (370322000000, '高青县', 3, 370300000000); +INSERT INTO `zz_area_code` VALUES (370323000000, '沂源县', 3, 370300000000); +INSERT INTO `zz_area_code` VALUES (370400000000, '枣庄市', 2, 370000000000); +INSERT INTO `zz_area_code` VALUES (370401000000, '市辖区', 3, 370400000000); +INSERT INTO `zz_area_code` VALUES (370402000000, '市中区', 3, 370400000000); +INSERT INTO `zz_area_code` VALUES (370403000000, '薛城区', 3, 370400000000); +INSERT INTO `zz_area_code` VALUES (370404000000, '峄城区', 3, 370400000000); +INSERT INTO `zz_area_code` VALUES (370405000000, '台儿庄区', 3, 370400000000); +INSERT INTO `zz_area_code` VALUES (370406000000, '山亭区', 3, 370400000000); +INSERT INTO `zz_area_code` VALUES (370481000000, '滕州市', 3, 370400000000); +INSERT INTO `zz_area_code` VALUES (370500000000, '东营市', 2, 370000000000); +INSERT INTO `zz_area_code` VALUES (370501000000, '市辖区', 3, 370500000000); +INSERT INTO `zz_area_code` VALUES (370502000000, '东营区', 3, 370500000000); +INSERT INTO `zz_area_code` VALUES (370503000000, '河口区', 3, 370500000000); +INSERT INTO `zz_area_code` VALUES (370505000000, '垦利区', 3, 370500000000); +INSERT INTO `zz_area_code` VALUES (370522000000, '利津县', 3, 370500000000); +INSERT INTO `zz_area_code` VALUES (370523000000, '广饶县', 3, 370500000000); +INSERT INTO `zz_area_code` VALUES (370571000000, '东营经济技术开发区', 3, 370500000000); +INSERT INTO `zz_area_code` VALUES (370572000000, '东营港经济开发区', 3, 370500000000); +INSERT INTO `zz_area_code` VALUES (370600000000, '烟台市', 2, 370000000000); +INSERT INTO `zz_area_code` VALUES (370601000000, '市辖区', 3, 370600000000); +INSERT INTO `zz_area_code` VALUES (370602000000, '芝罘区', 3, 370600000000); +INSERT INTO `zz_area_code` VALUES (370611000000, '福山区', 3, 370600000000); +INSERT INTO `zz_area_code` VALUES (370612000000, '牟平区', 3, 370600000000); +INSERT INTO `zz_area_code` VALUES (370613000000, '莱山区', 3, 370600000000); +INSERT INTO `zz_area_code` VALUES (370634000000, '长岛县', 3, 370600000000); +INSERT INTO `zz_area_code` VALUES (370671000000, '烟台高新技术产业开发区', 3, 370600000000); +INSERT INTO `zz_area_code` VALUES (370672000000, '烟台经济技术开发区', 3, 370600000000); +INSERT INTO `zz_area_code` VALUES (370681000000, '龙口市', 3, 370600000000); +INSERT INTO `zz_area_code` VALUES (370682000000, '莱阳市', 3, 370600000000); +INSERT INTO `zz_area_code` VALUES (370683000000, '莱州市', 3, 370600000000); +INSERT INTO `zz_area_code` VALUES (370684000000, '蓬莱市', 3, 370600000000); +INSERT INTO `zz_area_code` VALUES (370685000000, '招远市', 3, 370600000000); +INSERT INTO `zz_area_code` VALUES (370686000000, '栖霞市', 3, 370600000000); +INSERT INTO `zz_area_code` VALUES (370687000000, '海阳市', 3, 370600000000); +INSERT INTO `zz_area_code` VALUES (370700000000, '潍坊市', 2, 370000000000); +INSERT INTO `zz_area_code` VALUES (370701000000, '市辖区', 3, 370700000000); +INSERT INTO `zz_area_code` VALUES (370702000000, '潍城区', 3, 370700000000); +INSERT INTO `zz_area_code` VALUES (370703000000, '寒亭区', 3, 370700000000); +INSERT INTO `zz_area_code` VALUES (370704000000, '坊子区', 3, 370700000000); +INSERT INTO `zz_area_code` VALUES (370705000000, '奎文区', 3, 370700000000); +INSERT INTO `zz_area_code` VALUES (370724000000, '临朐县', 3, 370700000000); +INSERT INTO `zz_area_code` VALUES (370725000000, '昌乐县', 3, 370700000000); +INSERT INTO `zz_area_code` VALUES (370772000000, '潍坊滨海经济技术开发区', 3, 370700000000); +INSERT INTO `zz_area_code` VALUES (370781000000, '青州市', 3, 370700000000); +INSERT INTO `zz_area_code` VALUES (370782000000, '诸城市', 3, 370700000000); +INSERT INTO `zz_area_code` VALUES (370783000000, '寿光市', 3, 370700000000); +INSERT INTO `zz_area_code` VALUES (370784000000, '安丘市', 3, 370700000000); +INSERT INTO `zz_area_code` VALUES (370785000000, '高密市', 3, 370700000000); +INSERT INTO `zz_area_code` VALUES (370786000000, '昌邑市', 3, 370700000000); +INSERT INTO `zz_area_code` VALUES (370800000000, '济宁市', 2, 370000000000); +INSERT INTO `zz_area_code` VALUES (370801000000, '市辖区', 3, 370800000000); +INSERT INTO `zz_area_code` VALUES (370811000000, '任城区', 3, 370800000000); +INSERT INTO `zz_area_code` VALUES (370812000000, '兖州区', 3, 370800000000); +INSERT INTO `zz_area_code` VALUES (370826000000, '微山县', 3, 370800000000); +INSERT INTO `zz_area_code` VALUES (370827000000, '鱼台县', 3, 370800000000); +INSERT INTO `zz_area_code` VALUES (370828000000, '金乡县', 3, 370800000000); +INSERT INTO `zz_area_code` VALUES (370829000000, '嘉祥县', 3, 370800000000); +INSERT INTO `zz_area_code` VALUES (370830000000, '汶上县', 3, 370800000000); +INSERT INTO `zz_area_code` VALUES (370831000000, '泗水县', 3, 370800000000); +INSERT INTO `zz_area_code` VALUES (370832000000, '梁山县', 3, 370800000000); +INSERT INTO `zz_area_code` VALUES (370871000000, '济宁高新技术产业开发区', 3, 370800000000); +INSERT INTO `zz_area_code` VALUES (370881000000, '曲阜市', 3, 370800000000); +INSERT INTO `zz_area_code` VALUES (370883000000, '邹城市', 3, 370800000000); +INSERT INTO `zz_area_code` VALUES (370900000000, '泰安市', 2, 370000000000); +INSERT INTO `zz_area_code` VALUES (370901000000, '市辖区', 3, 370900000000); +INSERT INTO `zz_area_code` VALUES (370902000000, '泰山区', 3, 370900000000); +INSERT INTO `zz_area_code` VALUES (370911000000, '岱岳区', 3, 370900000000); +INSERT INTO `zz_area_code` VALUES (370921000000, '宁阳县', 3, 370900000000); +INSERT INTO `zz_area_code` VALUES (370923000000, '东平县', 3, 370900000000); +INSERT INTO `zz_area_code` VALUES (370982000000, '新泰市', 3, 370900000000); +INSERT INTO `zz_area_code` VALUES (370983000000, '肥城市', 3, 370900000000); +INSERT INTO `zz_area_code` VALUES (371000000000, '威海市', 2, 370000000000); +INSERT INTO `zz_area_code` VALUES (371001000000, '市辖区', 3, 371000000000); +INSERT INTO `zz_area_code` VALUES (371002000000, '环翠区', 3, 371000000000); +INSERT INTO `zz_area_code` VALUES (371003000000, '文登区', 3, 371000000000); +INSERT INTO `zz_area_code` VALUES (371071000000, '威海火炬高技术产业开发区', 3, 371000000000); +INSERT INTO `zz_area_code` VALUES (371072000000, '威海经济技术开发区', 3, 371000000000); +INSERT INTO `zz_area_code` VALUES (371073000000, '威海临港经济技术开发区', 3, 371000000000); +INSERT INTO `zz_area_code` VALUES (371082000000, '荣成市', 3, 371000000000); +INSERT INTO `zz_area_code` VALUES (371083000000, '乳山市', 3, 371000000000); +INSERT INTO `zz_area_code` VALUES (371100000000, '日照市', 2, 370000000000); +INSERT INTO `zz_area_code` VALUES (371101000000, '市辖区', 3, 371100000000); +INSERT INTO `zz_area_code` VALUES (371102000000, '东港区', 3, 371100000000); +INSERT INTO `zz_area_code` VALUES (371103000000, '岚山区', 3, 371100000000); +INSERT INTO `zz_area_code` VALUES (371121000000, '五莲县', 3, 371100000000); +INSERT INTO `zz_area_code` VALUES (371122000000, '莒县', 3, 371100000000); +INSERT INTO `zz_area_code` VALUES (371171000000, '日照经济技术开发区', 3, 371100000000); +INSERT INTO `zz_area_code` VALUES (371200000000, '莱芜市', 2, 370000000000); +INSERT INTO `zz_area_code` VALUES (371201000000, '市辖区', 3, 371200000000); +INSERT INTO `zz_area_code` VALUES (371202000000, '莱城区', 3, 371200000000); +INSERT INTO `zz_area_code` VALUES (371203000000, '钢城区', 3, 371200000000); +INSERT INTO `zz_area_code` VALUES (371300000000, '临沂市', 2, 370000000000); +INSERT INTO `zz_area_code` VALUES (371301000000, '市辖区', 3, 371300000000); +INSERT INTO `zz_area_code` VALUES (371302000000, '兰山区', 3, 371300000000); +INSERT INTO `zz_area_code` VALUES (371311000000, '罗庄区', 3, 371300000000); +INSERT INTO `zz_area_code` VALUES (371312000000, '河东区', 3, 371300000000); +INSERT INTO `zz_area_code` VALUES (371321000000, '沂南县', 3, 371300000000); +INSERT INTO `zz_area_code` VALUES (371322000000, '郯城县', 3, 371300000000); +INSERT INTO `zz_area_code` VALUES (371323000000, '沂水县', 3, 371300000000); +INSERT INTO `zz_area_code` VALUES (371324000000, '兰陵县', 3, 371300000000); +INSERT INTO `zz_area_code` VALUES (371325000000, '费县', 3, 371300000000); +INSERT INTO `zz_area_code` VALUES (371326000000, '平邑县', 3, 371300000000); +INSERT INTO `zz_area_code` VALUES (371327000000, '莒南县', 3, 371300000000); +INSERT INTO `zz_area_code` VALUES (371328000000, '蒙阴县', 3, 371300000000); +INSERT INTO `zz_area_code` VALUES (371329000000, '临沭县', 3, 371300000000); +INSERT INTO `zz_area_code` VALUES (371371000000, '临沂高新技术产业开发区', 3, 371300000000); +INSERT INTO `zz_area_code` VALUES (371372000000, '临沂经济技术开发区', 3, 371300000000); +INSERT INTO `zz_area_code` VALUES (371373000000, '临沂临港经济开发区', 3, 371300000000); +INSERT INTO `zz_area_code` VALUES (371400000000, '德州市', 2, 370000000000); +INSERT INTO `zz_area_code` VALUES (371401000000, '市辖区', 3, 371400000000); +INSERT INTO `zz_area_code` VALUES (371402000000, '德城区', 3, 371400000000); +INSERT INTO `zz_area_code` VALUES (371403000000, '陵城区', 3, 371400000000); +INSERT INTO `zz_area_code` VALUES (371422000000, '宁津县', 3, 371400000000); +INSERT INTO `zz_area_code` VALUES (371423000000, '庆云县', 3, 371400000000); +INSERT INTO `zz_area_code` VALUES (371424000000, '临邑县', 3, 371400000000); +INSERT INTO `zz_area_code` VALUES (371425000000, '齐河县', 3, 371400000000); +INSERT INTO `zz_area_code` VALUES (371426000000, '平原县', 3, 371400000000); +INSERT INTO `zz_area_code` VALUES (371427000000, '夏津县', 3, 371400000000); +INSERT INTO `zz_area_code` VALUES (371428000000, '武城县', 3, 371400000000); +INSERT INTO `zz_area_code` VALUES (371471000000, '德州经济技术开发区', 3, 371400000000); +INSERT INTO `zz_area_code` VALUES (371472000000, '德州运河经济开发区', 3, 371400000000); +INSERT INTO `zz_area_code` VALUES (371481000000, '乐陵市', 3, 371400000000); +INSERT INTO `zz_area_code` VALUES (371482000000, '禹城市', 3, 371400000000); +INSERT INTO `zz_area_code` VALUES (371500000000, '聊城市', 2, 370000000000); +INSERT INTO `zz_area_code` VALUES (371501000000, '市辖区', 3, 371500000000); +INSERT INTO `zz_area_code` VALUES (371502000000, '东昌府区', 3, 371500000000); +INSERT INTO `zz_area_code` VALUES (371521000000, '阳谷县', 3, 371500000000); +INSERT INTO `zz_area_code` VALUES (371522000000, '莘县', 3, 371500000000); +INSERT INTO `zz_area_code` VALUES (371523000000, '茌平县', 3, 371500000000); +INSERT INTO `zz_area_code` VALUES (371524000000, '东阿县', 3, 371500000000); +INSERT INTO `zz_area_code` VALUES (371525000000, '冠县', 3, 371500000000); +INSERT INTO `zz_area_code` VALUES (371526000000, '高唐县', 3, 371500000000); +INSERT INTO `zz_area_code` VALUES (371581000000, '临清市', 3, 371500000000); +INSERT INTO `zz_area_code` VALUES (371600000000, '滨州市', 2, 370000000000); +INSERT INTO `zz_area_code` VALUES (371601000000, '市辖区', 3, 371600000000); +INSERT INTO `zz_area_code` VALUES (371602000000, '滨城区', 3, 371600000000); +INSERT INTO `zz_area_code` VALUES (371603000000, '沾化区', 3, 371600000000); +INSERT INTO `zz_area_code` VALUES (371621000000, '惠民县', 3, 371600000000); +INSERT INTO `zz_area_code` VALUES (371622000000, '阳信县', 3, 371600000000); +INSERT INTO `zz_area_code` VALUES (371623000000, '无棣县', 3, 371600000000); +INSERT INTO `zz_area_code` VALUES (371625000000, '博兴县', 3, 371600000000); +INSERT INTO `zz_area_code` VALUES (371681000000, '邹平市', 3, 371600000000); +INSERT INTO `zz_area_code` VALUES (371700000000, '菏泽市', 2, 370000000000); +INSERT INTO `zz_area_code` VALUES (371701000000, '市辖区', 3, 371700000000); +INSERT INTO `zz_area_code` VALUES (371702000000, '牡丹区', 3, 371700000000); +INSERT INTO `zz_area_code` VALUES (371703000000, '定陶区', 3, 371700000000); +INSERT INTO `zz_area_code` VALUES (371721000000, '曹县', 3, 371700000000); +INSERT INTO `zz_area_code` VALUES (371722000000, '单县', 3, 371700000000); +INSERT INTO `zz_area_code` VALUES (371723000000, '成武县', 3, 371700000000); +INSERT INTO `zz_area_code` VALUES (371724000000, '巨野县', 3, 371700000000); +INSERT INTO `zz_area_code` VALUES (371725000000, '郓城县', 3, 371700000000); +INSERT INTO `zz_area_code` VALUES (371726000000, '鄄城县', 3, 371700000000); +INSERT INTO `zz_area_code` VALUES (371728000000, '东明县', 3, 371700000000); +INSERT INTO `zz_area_code` VALUES (371771000000, '菏泽经济技术开发区', 3, 371700000000); +INSERT INTO `zz_area_code` VALUES (371772000000, '菏泽高新技术开发区', 3, 371700000000); +INSERT INTO `zz_area_code` VALUES (410000000000, '河南省', 1, NULL); +INSERT INTO `zz_area_code` VALUES (410100000000, '郑州市', 2, 410000000000); +INSERT INTO `zz_area_code` VALUES (410101000000, '市辖区', 3, 410100000000); +INSERT INTO `zz_area_code` VALUES (410102000000, '中原区', 3, 410100000000); +INSERT INTO `zz_area_code` VALUES (410103000000, '二七区', 3, 410100000000); +INSERT INTO `zz_area_code` VALUES (410104000000, '管城回族区', 3, 410100000000); +INSERT INTO `zz_area_code` VALUES (410105000000, '金水区', 3, 410100000000); +INSERT INTO `zz_area_code` VALUES (410106000000, '上街区', 3, 410100000000); +INSERT INTO `zz_area_code` VALUES (410108000000, '惠济区', 3, 410100000000); +INSERT INTO `zz_area_code` VALUES (410122000000, '中牟县', 3, 410100000000); +INSERT INTO `zz_area_code` VALUES (410171000000, '郑州经济技术开发区', 3, 410100000000); +INSERT INTO `zz_area_code` VALUES (410172000000, '郑州高新技术产业开发区', 3, 410100000000); +INSERT INTO `zz_area_code` VALUES (410173000000, '郑州航空港经济综合实验区', 3, 410100000000); +INSERT INTO `zz_area_code` VALUES (410181000000, '巩义市', 3, 410100000000); +INSERT INTO `zz_area_code` VALUES (410182000000, '荥阳市', 3, 410100000000); +INSERT INTO `zz_area_code` VALUES (410183000000, '新密市', 3, 410100000000); +INSERT INTO `zz_area_code` VALUES (410184000000, '新郑市', 3, 410100000000); +INSERT INTO `zz_area_code` VALUES (410185000000, '登封市', 3, 410100000000); +INSERT INTO `zz_area_code` VALUES (410200000000, '开封市', 2, 410000000000); +INSERT INTO `zz_area_code` VALUES (410201000000, '市辖区', 3, 410200000000); +INSERT INTO `zz_area_code` VALUES (410202000000, '龙亭区', 3, 410200000000); +INSERT INTO `zz_area_code` VALUES (410203000000, '顺河回族区', 3, 410200000000); +INSERT INTO `zz_area_code` VALUES (410204000000, '鼓楼区', 3, 410200000000); +INSERT INTO `zz_area_code` VALUES (410205000000, '禹王台区', 3, 410200000000); +INSERT INTO `zz_area_code` VALUES (410212000000, '祥符区', 3, 410200000000); +INSERT INTO `zz_area_code` VALUES (410221000000, '杞县', 3, 410200000000); +INSERT INTO `zz_area_code` VALUES (410222000000, '通许县', 3, 410200000000); +INSERT INTO `zz_area_code` VALUES (410223000000, '尉氏县', 3, 410200000000); +INSERT INTO `zz_area_code` VALUES (410225000000, '兰考县', 3, 410200000000); +INSERT INTO `zz_area_code` VALUES (410300000000, '洛阳市', 2, 410000000000); +INSERT INTO `zz_area_code` VALUES (410301000000, '市辖区', 3, 410300000000); +INSERT INTO `zz_area_code` VALUES (410302000000, '老城区', 3, 410300000000); +INSERT INTO `zz_area_code` VALUES (410303000000, '西工区', 3, 410300000000); +INSERT INTO `zz_area_code` VALUES (410304000000, '瀍河回族区', 3, 410300000000); +INSERT INTO `zz_area_code` VALUES (410305000000, '涧西区', 3, 410300000000); +INSERT INTO `zz_area_code` VALUES (410306000000, '吉利区', 3, 410300000000); +INSERT INTO `zz_area_code` VALUES (410311000000, '洛龙区', 3, 410300000000); +INSERT INTO `zz_area_code` VALUES (410322000000, '孟津县', 3, 410300000000); +INSERT INTO `zz_area_code` VALUES (410323000000, '新安县', 3, 410300000000); +INSERT INTO `zz_area_code` VALUES (410324000000, '栾川县', 3, 410300000000); +INSERT INTO `zz_area_code` VALUES (410325000000, '嵩县', 3, 410300000000); +INSERT INTO `zz_area_code` VALUES (410326000000, '汝阳县', 3, 410300000000); +INSERT INTO `zz_area_code` VALUES (410327000000, '宜阳县', 3, 410300000000); +INSERT INTO `zz_area_code` VALUES (410328000000, '洛宁县', 3, 410300000000); +INSERT INTO `zz_area_code` VALUES (410329000000, '伊川县', 3, 410300000000); +INSERT INTO `zz_area_code` VALUES (410371000000, '洛阳高新技术产业开发区', 3, 410300000000); +INSERT INTO `zz_area_code` VALUES (410381000000, '偃师市', 3, 410300000000); +INSERT INTO `zz_area_code` VALUES (410400000000, '平顶山市', 2, 410000000000); +INSERT INTO `zz_area_code` VALUES (410401000000, '市辖区', 3, 410400000000); +INSERT INTO `zz_area_code` VALUES (410402000000, '新华区', 3, 410400000000); +INSERT INTO `zz_area_code` VALUES (410403000000, '卫东区', 3, 410400000000); +INSERT INTO `zz_area_code` VALUES (410404000000, '石龙区', 3, 410400000000); +INSERT INTO `zz_area_code` VALUES (410411000000, '湛河区', 3, 410400000000); +INSERT INTO `zz_area_code` VALUES (410421000000, '宝丰县', 3, 410400000000); +INSERT INTO `zz_area_code` VALUES (410422000000, '叶县', 3, 410400000000); +INSERT INTO `zz_area_code` VALUES (410423000000, '鲁山县', 3, 410400000000); +INSERT INTO `zz_area_code` VALUES (410425000000, '郏县', 3, 410400000000); +INSERT INTO `zz_area_code` VALUES (410471000000, '平顶山高新技术产业开发区', 3, 410400000000); +INSERT INTO `zz_area_code` VALUES (410472000000, '平顶山市新城区', 3, 410400000000); +INSERT INTO `zz_area_code` VALUES (410481000000, '舞钢市', 3, 410400000000); +INSERT INTO `zz_area_code` VALUES (410482000000, '汝州市', 3, 410400000000); +INSERT INTO `zz_area_code` VALUES (410500000000, '安阳市', 2, 410000000000); +INSERT INTO `zz_area_code` VALUES (410501000000, '市辖区', 3, 410500000000); +INSERT INTO `zz_area_code` VALUES (410502000000, '文峰区', 3, 410500000000); +INSERT INTO `zz_area_code` VALUES (410503000000, '北关区', 3, 410500000000); +INSERT INTO `zz_area_code` VALUES (410505000000, '殷都区', 3, 410500000000); +INSERT INTO `zz_area_code` VALUES (410506000000, '龙安区', 3, 410500000000); +INSERT INTO `zz_area_code` VALUES (410522000000, '安阳县', 3, 410500000000); +INSERT INTO `zz_area_code` VALUES (410523000000, '汤阴县', 3, 410500000000); +INSERT INTO `zz_area_code` VALUES (410526000000, '滑县', 3, 410500000000); +INSERT INTO `zz_area_code` VALUES (410527000000, '内黄县', 3, 410500000000); +INSERT INTO `zz_area_code` VALUES (410571000000, '安阳高新技术产业开发区', 3, 410500000000); +INSERT INTO `zz_area_code` VALUES (410581000000, '林州市', 3, 410500000000); +INSERT INTO `zz_area_code` VALUES (410600000000, '鹤壁市', 2, 410000000000); +INSERT INTO `zz_area_code` VALUES (410601000000, '市辖区', 3, 410600000000); +INSERT INTO `zz_area_code` VALUES (410602000000, '鹤山区', 3, 410600000000); +INSERT INTO `zz_area_code` VALUES (410603000000, '山城区', 3, 410600000000); +INSERT INTO `zz_area_code` VALUES (410611000000, '淇滨区', 3, 410600000000); +INSERT INTO `zz_area_code` VALUES (410621000000, '浚县', 3, 410600000000); +INSERT INTO `zz_area_code` VALUES (410622000000, '淇县', 3, 410600000000); +INSERT INTO `zz_area_code` VALUES (410671000000, '鹤壁经济技术开发区', 3, 410600000000); +INSERT INTO `zz_area_code` VALUES (410700000000, '新乡市', 2, 410000000000); +INSERT INTO `zz_area_code` VALUES (410701000000, '市辖区', 3, 410700000000); +INSERT INTO `zz_area_code` VALUES (410702000000, '红旗区', 3, 410700000000); +INSERT INTO `zz_area_code` VALUES (410703000000, '卫滨区', 3, 410700000000); +INSERT INTO `zz_area_code` VALUES (410704000000, '凤泉区', 3, 410700000000); +INSERT INTO `zz_area_code` VALUES (410711000000, '牧野区', 3, 410700000000); +INSERT INTO `zz_area_code` VALUES (410721000000, '新乡县', 3, 410700000000); +INSERT INTO `zz_area_code` VALUES (410724000000, '获嘉县', 3, 410700000000); +INSERT INTO `zz_area_code` VALUES (410725000000, '原阳县', 3, 410700000000); +INSERT INTO `zz_area_code` VALUES (410726000000, '延津县', 3, 410700000000); +INSERT INTO `zz_area_code` VALUES (410727000000, '封丘县', 3, 410700000000); +INSERT INTO `zz_area_code` VALUES (410728000000, '长垣县', 3, 410700000000); +INSERT INTO `zz_area_code` VALUES (410771000000, '新乡高新技术产业开发区', 3, 410700000000); +INSERT INTO `zz_area_code` VALUES (410772000000, '新乡经济技术开发区', 3, 410700000000); +INSERT INTO `zz_area_code` VALUES (410773000000, '新乡市平原城乡一体化示范区', 3, 410700000000); +INSERT INTO `zz_area_code` VALUES (410781000000, '卫辉市', 3, 410700000000); +INSERT INTO `zz_area_code` VALUES (410782000000, '辉县市', 3, 410700000000); +INSERT INTO `zz_area_code` VALUES (410800000000, '焦作市', 2, 410000000000); +INSERT INTO `zz_area_code` VALUES (410801000000, '市辖区', 3, 410800000000); +INSERT INTO `zz_area_code` VALUES (410802000000, '解放区', 3, 410800000000); +INSERT INTO `zz_area_code` VALUES (410803000000, '中站区', 3, 410800000000); +INSERT INTO `zz_area_code` VALUES (410804000000, '马村区', 3, 410800000000); +INSERT INTO `zz_area_code` VALUES (410811000000, '山阳区', 3, 410800000000); +INSERT INTO `zz_area_code` VALUES (410821000000, '修武县', 3, 410800000000); +INSERT INTO `zz_area_code` VALUES (410822000000, '博爱县', 3, 410800000000); +INSERT INTO `zz_area_code` VALUES (410823000000, '武陟县', 3, 410800000000); +INSERT INTO `zz_area_code` VALUES (410825000000, '温县', 3, 410800000000); +INSERT INTO `zz_area_code` VALUES (410871000000, '焦作城乡一体化示范区', 3, 410800000000); +INSERT INTO `zz_area_code` VALUES (410882000000, '沁阳市', 3, 410800000000); +INSERT INTO `zz_area_code` VALUES (410883000000, '孟州市', 3, 410800000000); +INSERT INTO `zz_area_code` VALUES (410900000000, '濮阳市', 2, 410000000000); +INSERT INTO `zz_area_code` VALUES (410901000000, '市辖区', 3, 410900000000); +INSERT INTO `zz_area_code` VALUES (410902000000, '华龙区', 3, 410900000000); +INSERT INTO `zz_area_code` VALUES (410922000000, '清丰县', 3, 410900000000); +INSERT INTO `zz_area_code` VALUES (410923000000, '南乐县', 3, 410900000000); +INSERT INTO `zz_area_code` VALUES (410926000000, '范县', 3, 410900000000); +INSERT INTO `zz_area_code` VALUES (410927000000, '台前县', 3, 410900000000); +INSERT INTO `zz_area_code` VALUES (410928000000, '濮阳县', 3, 410900000000); +INSERT INTO `zz_area_code` VALUES (410971000000, '河南濮阳工业园区', 3, 410900000000); +INSERT INTO `zz_area_code` VALUES (410972000000, '濮阳经济技术开发区', 3, 410900000000); +INSERT INTO `zz_area_code` VALUES (411000000000, '许昌市', 2, 410000000000); +INSERT INTO `zz_area_code` VALUES (411001000000, '市辖区', 3, 411000000000); +INSERT INTO `zz_area_code` VALUES (411002000000, '魏都区', 3, 411000000000); +INSERT INTO `zz_area_code` VALUES (411003000000, '建安区', 3, 411000000000); +INSERT INTO `zz_area_code` VALUES (411024000000, '鄢陵县', 3, 411000000000); +INSERT INTO `zz_area_code` VALUES (411025000000, '襄城县', 3, 411000000000); +INSERT INTO `zz_area_code` VALUES (411071000000, '许昌经济技术开发区', 3, 411000000000); +INSERT INTO `zz_area_code` VALUES (411081000000, '禹州市', 3, 411000000000); +INSERT INTO `zz_area_code` VALUES (411082000000, '长葛市', 3, 411000000000); +INSERT INTO `zz_area_code` VALUES (411100000000, '漯河市', 2, 410000000000); +INSERT INTO `zz_area_code` VALUES (411101000000, '市辖区', 3, 411100000000); +INSERT INTO `zz_area_code` VALUES (411102000000, '源汇区', 3, 411100000000); +INSERT INTO `zz_area_code` VALUES (411103000000, '郾城区', 3, 411100000000); +INSERT INTO `zz_area_code` VALUES (411104000000, '召陵区', 3, 411100000000); +INSERT INTO `zz_area_code` VALUES (411121000000, '舞阳县', 3, 411100000000); +INSERT INTO `zz_area_code` VALUES (411122000000, '临颍县', 3, 411100000000); +INSERT INTO `zz_area_code` VALUES (411171000000, '漯河经济技术开发区', 3, 411100000000); +INSERT INTO `zz_area_code` VALUES (411200000000, '三门峡市', 2, 410000000000); +INSERT INTO `zz_area_code` VALUES (411201000000, '市辖区', 3, 411200000000); +INSERT INTO `zz_area_code` VALUES (411202000000, '湖滨区', 3, 411200000000); +INSERT INTO `zz_area_code` VALUES (411203000000, '陕州区', 3, 411200000000); +INSERT INTO `zz_area_code` VALUES (411221000000, '渑池县', 3, 411200000000); +INSERT INTO `zz_area_code` VALUES (411224000000, '卢氏县', 3, 411200000000); +INSERT INTO `zz_area_code` VALUES (411271000000, '河南三门峡经济开发区', 3, 411200000000); +INSERT INTO `zz_area_code` VALUES (411281000000, '义马市', 3, 411200000000); +INSERT INTO `zz_area_code` VALUES (411282000000, '灵宝市', 3, 411200000000); +INSERT INTO `zz_area_code` VALUES (411300000000, '南阳市', 2, 410000000000); +INSERT INTO `zz_area_code` VALUES (411301000000, '市辖区', 3, 411300000000); +INSERT INTO `zz_area_code` VALUES (411302000000, '宛城区', 3, 411300000000); +INSERT INTO `zz_area_code` VALUES (411303000000, '卧龙区', 3, 411300000000); +INSERT INTO `zz_area_code` VALUES (411321000000, '南召县', 3, 411300000000); +INSERT INTO `zz_area_code` VALUES (411322000000, '方城县', 3, 411300000000); +INSERT INTO `zz_area_code` VALUES (411323000000, '西峡县', 3, 411300000000); +INSERT INTO `zz_area_code` VALUES (411324000000, '镇平县', 3, 411300000000); +INSERT INTO `zz_area_code` VALUES (411325000000, '内乡县', 3, 411300000000); +INSERT INTO `zz_area_code` VALUES (411326000000, '淅川县', 3, 411300000000); +INSERT INTO `zz_area_code` VALUES (411327000000, '社旗县', 3, 411300000000); +INSERT INTO `zz_area_code` VALUES (411328000000, '唐河县', 3, 411300000000); +INSERT INTO `zz_area_code` VALUES (411329000000, '新野县', 3, 411300000000); +INSERT INTO `zz_area_code` VALUES (411330000000, '桐柏县', 3, 411300000000); +INSERT INTO `zz_area_code` VALUES (411371000000, '南阳高新技术产业开发区', 3, 411300000000); +INSERT INTO `zz_area_code` VALUES (411372000000, '南阳市城乡一体化示范区', 3, 411300000000); +INSERT INTO `zz_area_code` VALUES (411381000000, '邓州市', 3, 411300000000); +INSERT INTO `zz_area_code` VALUES (411400000000, '商丘市', 2, 410000000000); +INSERT INTO `zz_area_code` VALUES (411401000000, '市辖区', 3, 411400000000); +INSERT INTO `zz_area_code` VALUES (411402000000, '梁园区', 3, 411400000000); +INSERT INTO `zz_area_code` VALUES (411403000000, '睢阳区', 3, 411400000000); +INSERT INTO `zz_area_code` VALUES (411421000000, '民权县', 3, 411400000000); +INSERT INTO `zz_area_code` VALUES (411422000000, '睢县', 3, 411400000000); +INSERT INTO `zz_area_code` VALUES (411423000000, '宁陵县', 3, 411400000000); +INSERT INTO `zz_area_code` VALUES (411424000000, '柘城县', 3, 411400000000); +INSERT INTO `zz_area_code` VALUES (411425000000, '虞城县', 3, 411400000000); +INSERT INTO `zz_area_code` VALUES (411426000000, '夏邑县', 3, 411400000000); +INSERT INTO `zz_area_code` VALUES (411471000000, '豫东综合物流产业聚集区', 3, 411400000000); +INSERT INTO `zz_area_code` VALUES (411472000000, '河南商丘经济开发区', 3, 411400000000); +INSERT INTO `zz_area_code` VALUES (411481000000, '永城市', 3, 411400000000); +INSERT INTO `zz_area_code` VALUES (411500000000, '信阳市', 2, 410000000000); +INSERT INTO `zz_area_code` VALUES (411501000000, '市辖区', 3, 411500000000); +INSERT INTO `zz_area_code` VALUES (411502000000, '浉河区', 3, 411500000000); +INSERT INTO `zz_area_code` VALUES (411503000000, '平桥区', 3, 411500000000); +INSERT INTO `zz_area_code` VALUES (411521000000, '罗山县', 3, 411500000000); +INSERT INTO `zz_area_code` VALUES (411522000000, '光山县', 3, 411500000000); +INSERT INTO `zz_area_code` VALUES (411523000000, '新县', 3, 411500000000); +INSERT INTO `zz_area_code` VALUES (411524000000, '商城县', 3, 411500000000); +INSERT INTO `zz_area_code` VALUES (411525000000, '固始县', 3, 411500000000); +INSERT INTO `zz_area_code` VALUES (411526000000, '潢川县', 3, 411500000000); +INSERT INTO `zz_area_code` VALUES (411527000000, '淮滨县', 3, 411500000000); +INSERT INTO `zz_area_code` VALUES (411528000000, '息县', 3, 411500000000); +INSERT INTO `zz_area_code` VALUES (411571000000, '信阳高新技术产业开发区', 3, 411500000000); +INSERT INTO `zz_area_code` VALUES (411600000000, '周口市', 2, 410000000000); +INSERT INTO `zz_area_code` VALUES (411601000000, '市辖区', 3, 411600000000); +INSERT INTO `zz_area_code` VALUES (411602000000, '川汇区', 3, 411600000000); +INSERT INTO `zz_area_code` VALUES (411621000000, '扶沟县', 3, 411600000000); +INSERT INTO `zz_area_code` VALUES (411622000000, '西华县', 3, 411600000000); +INSERT INTO `zz_area_code` VALUES (411623000000, '商水县', 3, 411600000000); +INSERT INTO `zz_area_code` VALUES (411624000000, '沈丘县', 3, 411600000000); +INSERT INTO `zz_area_code` VALUES (411625000000, '郸城县', 3, 411600000000); +INSERT INTO `zz_area_code` VALUES (411626000000, '淮阳县', 3, 411600000000); +INSERT INTO `zz_area_code` VALUES (411627000000, '太康县', 3, 411600000000); +INSERT INTO `zz_area_code` VALUES (411628000000, '鹿邑县', 3, 411600000000); +INSERT INTO `zz_area_code` VALUES (411671000000, '河南周口经济开发区', 3, 411600000000); +INSERT INTO `zz_area_code` VALUES (411681000000, '项城市', 3, 411600000000); +INSERT INTO `zz_area_code` VALUES (411700000000, '驻马店市', 2, 410000000000); +INSERT INTO `zz_area_code` VALUES (411701000000, '市辖区', 3, 411700000000); +INSERT INTO `zz_area_code` VALUES (411702000000, '驿城区', 3, 411700000000); +INSERT INTO `zz_area_code` VALUES (411721000000, '西平县', 3, 411700000000); +INSERT INTO `zz_area_code` VALUES (411722000000, '上蔡县', 3, 411700000000); +INSERT INTO `zz_area_code` VALUES (411723000000, '平舆县', 3, 411700000000); +INSERT INTO `zz_area_code` VALUES (411724000000, '正阳县', 3, 411700000000); +INSERT INTO `zz_area_code` VALUES (411725000000, '确山县', 3, 411700000000); +INSERT INTO `zz_area_code` VALUES (411726000000, '泌阳县', 3, 411700000000); +INSERT INTO `zz_area_code` VALUES (411727000000, '汝南县', 3, 411700000000); +INSERT INTO `zz_area_code` VALUES (411728000000, '遂平县', 3, 411700000000); +INSERT INTO `zz_area_code` VALUES (411729000000, '新蔡县', 3, 411700000000); +INSERT INTO `zz_area_code` VALUES (411771000000, '河南驻马店经济开发区', 3, 411700000000); +INSERT INTO `zz_area_code` VALUES (419000000000, '省直辖县级行政区划', 2, 410000000000); +INSERT INTO `zz_area_code` VALUES (419001000000, '济源市', 3, 419000000000); +INSERT INTO `zz_area_code` VALUES (420000000000, '湖北省', 1, NULL); +INSERT INTO `zz_area_code` VALUES (420100000000, '武汉市', 2, 420000000000); +INSERT INTO `zz_area_code` VALUES (420101000000, '市辖区', 3, 420100000000); +INSERT INTO `zz_area_code` VALUES (420102000000, '江岸区', 3, 420100000000); +INSERT INTO `zz_area_code` VALUES (420103000000, '江汉区', 3, 420100000000); +INSERT INTO `zz_area_code` VALUES (420104000000, '硚口区', 3, 420100000000); +INSERT INTO `zz_area_code` VALUES (420105000000, '汉阳区', 3, 420100000000); +INSERT INTO `zz_area_code` VALUES (420106000000, '武昌区', 3, 420100000000); +INSERT INTO `zz_area_code` VALUES (420107000000, '青山区', 3, 420100000000); +INSERT INTO `zz_area_code` VALUES (420111000000, '洪山区', 3, 420100000000); +INSERT INTO `zz_area_code` VALUES (420112000000, '东西湖区', 3, 420100000000); +INSERT INTO `zz_area_code` VALUES (420113000000, '汉南区', 3, 420100000000); +INSERT INTO `zz_area_code` VALUES (420114000000, '蔡甸区', 3, 420100000000); +INSERT INTO `zz_area_code` VALUES (420115000000, '江夏区', 3, 420100000000); +INSERT INTO `zz_area_code` VALUES (420116000000, '黄陂区', 3, 420100000000); +INSERT INTO `zz_area_code` VALUES (420117000000, '新洲区', 3, 420100000000); +INSERT INTO `zz_area_code` VALUES (420200000000, '黄石市', 2, 420000000000); +INSERT INTO `zz_area_code` VALUES (420201000000, '市辖区', 3, 420200000000); +INSERT INTO `zz_area_code` VALUES (420202000000, '黄石港区', 3, 420200000000); +INSERT INTO `zz_area_code` VALUES (420203000000, '西塞山区', 3, 420200000000); +INSERT INTO `zz_area_code` VALUES (420204000000, '下陆区', 3, 420200000000); +INSERT INTO `zz_area_code` VALUES (420205000000, '铁山区', 3, 420200000000); +INSERT INTO `zz_area_code` VALUES (420222000000, '阳新县', 3, 420200000000); +INSERT INTO `zz_area_code` VALUES (420281000000, '大冶市', 3, 420200000000); +INSERT INTO `zz_area_code` VALUES (420300000000, '十堰市', 2, 420000000000); +INSERT INTO `zz_area_code` VALUES (420301000000, '市辖区', 3, 420300000000); +INSERT INTO `zz_area_code` VALUES (420302000000, '茅箭区', 3, 420300000000); +INSERT INTO `zz_area_code` VALUES (420303000000, '张湾区', 3, 420300000000); +INSERT INTO `zz_area_code` VALUES (420304000000, '郧阳区', 3, 420300000000); +INSERT INTO `zz_area_code` VALUES (420322000000, '郧西县', 3, 420300000000); +INSERT INTO `zz_area_code` VALUES (420323000000, '竹山县', 3, 420300000000); +INSERT INTO `zz_area_code` VALUES (420324000000, '竹溪县', 3, 420300000000); +INSERT INTO `zz_area_code` VALUES (420325000000, '房县', 3, 420300000000); +INSERT INTO `zz_area_code` VALUES (420381000000, '丹江口市', 3, 420300000000); +INSERT INTO `zz_area_code` VALUES (420500000000, '宜昌市', 2, 420000000000); +INSERT INTO `zz_area_code` VALUES (420501000000, '市辖区', 3, 420500000000); +INSERT INTO `zz_area_code` VALUES (420502000000, '西陵区', 3, 420500000000); +INSERT INTO `zz_area_code` VALUES (420503000000, '伍家岗区', 3, 420500000000); +INSERT INTO `zz_area_code` VALUES (420504000000, '点军区', 3, 420500000000); +INSERT INTO `zz_area_code` VALUES (420505000000, '猇亭区', 3, 420500000000); +INSERT INTO `zz_area_code` VALUES (420506000000, '夷陵区', 3, 420500000000); +INSERT INTO `zz_area_code` VALUES (420525000000, '远安县', 3, 420500000000); +INSERT INTO `zz_area_code` VALUES (420526000000, '兴山县', 3, 420500000000); +INSERT INTO `zz_area_code` VALUES (420527000000, '秭归县', 3, 420500000000); +INSERT INTO `zz_area_code` VALUES (420528000000, '长阳土家族自治县', 3, 420500000000); +INSERT INTO `zz_area_code` VALUES (420529000000, '五峰土家族自治县', 3, 420500000000); +INSERT INTO `zz_area_code` VALUES (420581000000, '宜都市', 3, 420500000000); +INSERT INTO `zz_area_code` VALUES (420582000000, '当阳市', 3, 420500000000); +INSERT INTO `zz_area_code` VALUES (420583000000, '枝江市', 3, 420500000000); +INSERT INTO `zz_area_code` VALUES (420600000000, '襄阳市', 2, 420000000000); +INSERT INTO `zz_area_code` VALUES (420601000000, '市辖区', 3, 420600000000); +INSERT INTO `zz_area_code` VALUES (420602000000, '襄城区', 3, 420600000000); +INSERT INTO `zz_area_code` VALUES (420606000000, '樊城区', 3, 420600000000); +INSERT INTO `zz_area_code` VALUES (420607000000, '襄州区', 3, 420600000000); +INSERT INTO `zz_area_code` VALUES (420624000000, '南漳县', 3, 420600000000); +INSERT INTO `zz_area_code` VALUES (420625000000, '谷城县', 3, 420600000000); +INSERT INTO `zz_area_code` VALUES (420626000000, '保康县', 3, 420600000000); +INSERT INTO `zz_area_code` VALUES (420682000000, '老河口市', 3, 420600000000); +INSERT INTO `zz_area_code` VALUES (420683000000, '枣阳市', 3, 420600000000); +INSERT INTO `zz_area_code` VALUES (420684000000, '宜城市', 3, 420600000000); +INSERT INTO `zz_area_code` VALUES (420700000000, '鄂州市', 2, 420000000000); +INSERT INTO `zz_area_code` VALUES (420701000000, '市辖区', 3, 420700000000); +INSERT INTO `zz_area_code` VALUES (420702000000, '梁子湖区', 3, 420700000000); +INSERT INTO `zz_area_code` VALUES (420703000000, '华容区', 3, 420700000000); +INSERT INTO `zz_area_code` VALUES (420704000000, '鄂城区', 3, 420700000000); +INSERT INTO `zz_area_code` VALUES (420800000000, '荆门市', 2, 420000000000); +INSERT INTO `zz_area_code` VALUES (420801000000, '市辖区', 3, 420800000000); +INSERT INTO `zz_area_code` VALUES (420802000000, '东宝区', 3, 420800000000); +INSERT INTO `zz_area_code` VALUES (420804000000, '掇刀区', 3, 420800000000); +INSERT INTO `zz_area_code` VALUES (420822000000, '沙洋县', 3, 420800000000); +INSERT INTO `zz_area_code` VALUES (420881000000, '钟祥市', 3, 420800000000); +INSERT INTO `zz_area_code` VALUES (420882000000, '京山市', 3, 420800000000); +INSERT INTO `zz_area_code` VALUES (420900000000, '孝感市', 2, 420000000000); +INSERT INTO `zz_area_code` VALUES (420901000000, '市辖区', 3, 420900000000); +INSERT INTO `zz_area_code` VALUES (420902000000, '孝南区', 3, 420900000000); +INSERT INTO `zz_area_code` VALUES (420921000000, '孝昌县', 3, 420900000000); +INSERT INTO `zz_area_code` VALUES (420922000000, '大悟县', 3, 420900000000); +INSERT INTO `zz_area_code` VALUES (420923000000, '云梦县', 3, 420900000000); +INSERT INTO `zz_area_code` VALUES (420981000000, '应城市', 3, 420900000000); +INSERT INTO `zz_area_code` VALUES (420982000000, '安陆市', 3, 420900000000); +INSERT INTO `zz_area_code` VALUES (420984000000, '汉川市', 3, 420900000000); +INSERT INTO `zz_area_code` VALUES (421000000000, '荆州市', 2, 420000000000); +INSERT INTO `zz_area_code` VALUES (421001000000, '市辖区', 3, 421000000000); +INSERT INTO `zz_area_code` VALUES (421002000000, '沙市区', 3, 421000000000); +INSERT INTO `zz_area_code` VALUES (421003000000, '荆州区', 3, 421000000000); +INSERT INTO `zz_area_code` VALUES (421022000000, '公安县', 3, 421000000000); +INSERT INTO `zz_area_code` VALUES (421023000000, '监利县', 3, 421000000000); +INSERT INTO `zz_area_code` VALUES (421024000000, '江陵县', 3, 421000000000); +INSERT INTO `zz_area_code` VALUES (421071000000, '荆州经济技术开发区', 3, 421000000000); +INSERT INTO `zz_area_code` VALUES (421081000000, '石首市', 3, 421000000000); +INSERT INTO `zz_area_code` VALUES (421083000000, '洪湖市', 3, 421000000000); +INSERT INTO `zz_area_code` VALUES (421087000000, '松滋市', 3, 421000000000); +INSERT INTO `zz_area_code` VALUES (421100000000, '黄冈市', 2, 420000000000); +INSERT INTO `zz_area_code` VALUES (421101000000, '市辖区', 3, 421100000000); +INSERT INTO `zz_area_code` VALUES (421102000000, '黄州区', 3, 421100000000); +INSERT INTO `zz_area_code` VALUES (421121000000, '团风县', 3, 421100000000); +INSERT INTO `zz_area_code` VALUES (421122000000, '红安县', 3, 421100000000); +INSERT INTO `zz_area_code` VALUES (421123000000, '罗田县', 3, 421100000000); +INSERT INTO `zz_area_code` VALUES (421124000000, '英山县', 3, 421100000000); +INSERT INTO `zz_area_code` VALUES (421125000000, '浠水县', 3, 421100000000); +INSERT INTO `zz_area_code` VALUES (421126000000, '蕲春县', 3, 421100000000); +INSERT INTO `zz_area_code` VALUES (421127000000, '黄梅县', 3, 421100000000); +INSERT INTO `zz_area_code` VALUES (421171000000, '龙感湖管理区', 3, 421100000000); +INSERT INTO `zz_area_code` VALUES (421181000000, '麻城市', 3, 421100000000); +INSERT INTO `zz_area_code` VALUES (421182000000, '武穴市', 3, 421100000000); +INSERT INTO `zz_area_code` VALUES (421200000000, '咸宁市', 2, 420000000000); +INSERT INTO `zz_area_code` VALUES (421201000000, '市辖区', 3, 421200000000); +INSERT INTO `zz_area_code` VALUES (421202000000, '咸安区', 3, 421200000000); +INSERT INTO `zz_area_code` VALUES (421221000000, '嘉鱼县', 3, 421200000000); +INSERT INTO `zz_area_code` VALUES (421222000000, '通城县', 3, 421200000000); +INSERT INTO `zz_area_code` VALUES (421223000000, '崇阳县', 3, 421200000000); +INSERT INTO `zz_area_code` VALUES (421224000000, '通山县', 3, 421200000000); +INSERT INTO `zz_area_code` VALUES (421281000000, '赤壁市', 3, 421200000000); +INSERT INTO `zz_area_code` VALUES (421300000000, '随州市', 2, 420000000000); +INSERT INTO `zz_area_code` VALUES (421301000000, '市辖区', 3, 421300000000); +INSERT INTO `zz_area_code` VALUES (421303000000, '曾都区', 3, 421300000000); +INSERT INTO `zz_area_code` VALUES (421321000000, '随县', 3, 421300000000); +INSERT INTO `zz_area_code` VALUES (421381000000, '广水市', 3, 421300000000); +INSERT INTO `zz_area_code` VALUES (422800000000, '恩施土家族苗族自治州', 2, 420000000000); +INSERT INTO `zz_area_code` VALUES (422801000000, '恩施市', 3, 422800000000); +INSERT INTO `zz_area_code` VALUES (422802000000, '利川市', 3, 422800000000); +INSERT INTO `zz_area_code` VALUES (422822000000, '建始县', 3, 422800000000); +INSERT INTO `zz_area_code` VALUES (422823000000, '巴东县', 3, 422800000000); +INSERT INTO `zz_area_code` VALUES (422825000000, '宣恩县', 3, 422800000000); +INSERT INTO `zz_area_code` VALUES (422826000000, '咸丰县', 3, 422800000000); +INSERT INTO `zz_area_code` VALUES (422827000000, '来凤县', 3, 422800000000); +INSERT INTO `zz_area_code` VALUES (422828000000, '鹤峰县', 3, 422800000000); +INSERT INTO `zz_area_code` VALUES (429000000000, '省直辖县级行政区划', 2, 420000000000); +INSERT INTO `zz_area_code` VALUES (429004000000, '仙桃市', 3, 429000000000); +INSERT INTO `zz_area_code` VALUES (429005000000, '潜江市', 3, 429000000000); +INSERT INTO `zz_area_code` VALUES (429006000000, '天门市', 3, 429000000000); +INSERT INTO `zz_area_code` VALUES (429021000000, '神农架林区', 3, 429000000000); +INSERT INTO `zz_area_code` VALUES (430000000000, '湖南省', 1, NULL); +INSERT INTO `zz_area_code` VALUES (430100000000, '长沙市', 2, 430000000000); +INSERT INTO `zz_area_code` VALUES (430101000000, '市辖区', 3, 430100000000); +INSERT INTO `zz_area_code` VALUES (430102000000, '芙蓉区', 3, 430100000000); +INSERT INTO `zz_area_code` VALUES (430103000000, '天心区', 3, 430100000000); +INSERT INTO `zz_area_code` VALUES (430104000000, '岳麓区', 3, 430100000000); +INSERT INTO `zz_area_code` VALUES (430105000000, '开福区', 3, 430100000000); +INSERT INTO `zz_area_code` VALUES (430111000000, '雨花区', 3, 430100000000); +INSERT INTO `zz_area_code` VALUES (430112000000, '望城区', 3, 430100000000); +INSERT INTO `zz_area_code` VALUES (430121000000, '长沙县', 3, 430100000000); +INSERT INTO `zz_area_code` VALUES (430181000000, '浏阳市', 3, 430100000000); +INSERT INTO `zz_area_code` VALUES (430182000000, '宁乡市', 3, 430100000000); +INSERT INTO `zz_area_code` VALUES (430200000000, '株洲市', 2, 430000000000); +INSERT INTO `zz_area_code` VALUES (430201000000, '市辖区', 3, 430200000000); +INSERT INTO `zz_area_code` VALUES (430202000000, '荷塘区', 3, 430200000000); +INSERT INTO `zz_area_code` VALUES (430203000000, '芦淞区', 3, 430200000000); +INSERT INTO `zz_area_code` VALUES (430204000000, '石峰区', 3, 430200000000); +INSERT INTO `zz_area_code` VALUES (430211000000, '天元区', 3, 430200000000); +INSERT INTO `zz_area_code` VALUES (430212000000, '渌口区', 3, 430200000000); +INSERT INTO `zz_area_code` VALUES (430223000000, '攸县', 3, 430200000000); +INSERT INTO `zz_area_code` VALUES (430224000000, '茶陵县', 3, 430200000000); +INSERT INTO `zz_area_code` VALUES (430225000000, '炎陵县', 3, 430200000000); +INSERT INTO `zz_area_code` VALUES (430271000000, '云龙示范区', 3, 430200000000); +INSERT INTO `zz_area_code` VALUES (430281000000, '醴陵市', 3, 430200000000); +INSERT INTO `zz_area_code` VALUES (430300000000, '湘潭市', 2, 430000000000); +INSERT INTO `zz_area_code` VALUES (430301000000, '市辖区', 3, 430300000000); +INSERT INTO `zz_area_code` VALUES (430302000000, '雨湖区', 3, 430300000000); +INSERT INTO `zz_area_code` VALUES (430304000000, '岳塘区', 3, 430300000000); +INSERT INTO `zz_area_code` VALUES (430321000000, '湘潭县', 3, 430300000000); +INSERT INTO `zz_area_code` VALUES (430371000000, '湖南湘潭高新技术产业园区', 3, 430300000000); +INSERT INTO `zz_area_code` VALUES (430372000000, '湘潭昭山示范区', 3, 430300000000); +INSERT INTO `zz_area_code` VALUES (430373000000, '湘潭九华示范区', 3, 430300000000); +INSERT INTO `zz_area_code` VALUES (430381000000, '湘乡市', 3, 430300000000); +INSERT INTO `zz_area_code` VALUES (430382000000, '韶山市', 3, 430300000000); +INSERT INTO `zz_area_code` VALUES (430400000000, '衡阳市', 2, 430000000000); +INSERT INTO `zz_area_code` VALUES (430401000000, '市辖区', 3, 430400000000); +INSERT INTO `zz_area_code` VALUES (430405000000, '珠晖区', 3, 430400000000); +INSERT INTO `zz_area_code` VALUES (430406000000, '雁峰区', 3, 430400000000); +INSERT INTO `zz_area_code` VALUES (430407000000, '石鼓区', 3, 430400000000); +INSERT INTO `zz_area_code` VALUES (430408000000, '蒸湘区', 3, 430400000000); +INSERT INTO `zz_area_code` VALUES (430412000000, '南岳区', 3, 430400000000); +INSERT INTO `zz_area_code` VALUES (430421000000, '衡阳县', 3, 430400000000); +INSERT INTO `zz_area_code` VALUES (430422000000, '衡南县', 3, 430400000000); +INSERT INTO `zz_area_code` VALUES (430423000000, '衡山县', 3, 430400000000); +INSERT INTO `zz_area_code` VALUES (430424000000, '衡东县', 3, 430400000000); +INSERT INTO `zz_area_code` VALUES (430426000000, '祁东县', 3, 430400000000); +INSERT INTO `zz_area_code` VALUES (430471000000, '衡阳综合保税区', 3, 430400000000); +INSERT INTO `zz_area_code` VALUES (430472000000, '湖南衡阳高新技术产业园区', 3, 430400000000); +INSERT INTO `zz_area_code` VALUES (430473000000, '湖南衡阳松木经济开发区', 3, 430400000000); +INSERT INTO `zz_area_code` VALUES (430481000000, '耒阳市', 3, 430400000000); +INSERT INTO `zz_area_code` VALUES (430482000000, '常宁市', 3, 430400000000); +INSERT INTO `zz_area_code` VALUES (430500000000, '邵阳市', 2, 430000000000); +INSERT INTO `zz_area_code` VALUES (430501000000, '市辖区', 3, 430500000000); +INSERT INTO `zz_area_code` VALUES (430502000000, '双清区', 3, 430500000000); +INSERT INTO `zz_area_code` VALUES (430503000000, '大祥区', 3, 430500000000); +INSERT INTO `zz_area_code` VALUES (430511000000, '北塔区', 3, 430500000000); +INSERT INTO `zz_area_code` VALUES (430521000000, '邵东县', 3, 430500000000); +INSERT INTO `zz_area_code` VALUES (430522000000, '新邵县', 3, 430500000000); +INSERT INTO `zz_area_code` VALUES (430523000000, '邵阳县', 3, 430500000000); +INSERT INTO `zz_area_code` VALUES (430524000000, '隆回县', 3, 430500000000); +INSERT INTO `zz_area_code` VALUES (430525000000, '洞口县', 3, 430500000000); +INSERT INTO `zz_area_code` VALUES (430527000000, '绥宁县', 3, 430500000000); +INSERT INTO `zz_area_code` VALUES (430528000000, '新宁县', 3, 430500000000); +INSERT INTO `zz_area_code` VALUES (430529000000, '城步苗族自治县', 3, 430500000000); +INSERT INTO `zz_area_code` VALUES (430581000000, '武冈市', 3, 430500000000); +INSERT INTO `zz_area_code` VALUES (430600000000, '岳阳市', 2, 430000000000); +INSERT INTO `zz_area_code` VALUES (430601000000, '市辖区', 3, 430600000000); +INSERT INTO `zz_area_code` VALUES (430602000000, '岳阳楼区', 3, 430600000000); +INSERT INTO `zz_area_code` VALUES (430603000000, '云溪区', 3, 430600000000); +INSERT INTO `zz_area_code` VALUES (430611000000, '君山区', 3, 430600000000); +INSERT INTO `zz_area_code` VALUES (430621000000, '岳阳县', 3, 430600000000); +INSERT INTO `zz_area_code` VALUES (430623000000, '华容县', 3, 430600000000); +INSERT INTO `zz_area_code` VALUES (430624000000, '湘阴县', 3, 430600000000); +INSERT INTO `zz_area_code` VALUES (430626000000, '平江县', 3, 430600000000); +INSERT INTO `zz_area_code` VALUES (430671000000, '岳阳市屈原管理区', 3, 430600000000); +INSERT INTO `zz_area_code` VALUES (430681000000, '汨罗市', 3, 430600000000); +INSERT INTO `zz_area_code` VALUES (430682000000, '临湘市', 3, 430600000000); +INSERT INTO `zz_area_code` VALUES (430700000000, '常德市', 2, 430000000000); +INSERT INTO `zz_area_code` VALUES (430701000000, '市辖区', 3, 430700000000); +INSERT INTO `zz_area_code` VALUES (430702000000, '武陵区', 3, 430700000000); +INSERT INTO `zz_area_code` VALUES (430703000000, '鼎城区', 3, 430700000000); +INSERT INTO `zz_area_code` VALUES (430721000000, '安乡县', 3, 430700000000); +INSERT INTO `zz_area_code` VALUES (430722000000, '汉寿县', 3, 430700000000); +INSERT INTO `zz_area_code` VALUES (430723000000, '澧县', 3, 430700000000); +INSERT INTO `zz_area_code` VALUES (430724000000, '临澧县', 3, 430700000000); +INSERT INTO `zz_area_code` VALUES (430725000000, '桃源县', 3, 430700000000); +INSERT INTO `zz_area_code` VALUES (430726000000, '石门县', 3, 430700000000); +INSERT INTO `zz_area_code` VALUES (430771000000, '常德市西洞庭管理区', 3, 430700000000); +INSERT INTO `zz_area_code` VALUES (430781000000, '津市市', 3, 430700000000); +INSERT INTO `zz_area_code` VALUES (430800000000, '张家界市', 2, 430000000000); +INSERT INTO `zz_area_code` VALUES (430801000000, '市辖区', 3, 430800000000); +INSERT INTO `zz_area_code` VALUES (430802000000, '永定区', 3, 430800000000); +INSERT INTO `zz_area_code` VALUES (430811000000, '武陵源区', 3, 430800000000); +INSERT INTO `zz_area_code` VALUES (430821000000, '慈利县', 3, 430800000000); +INSERT INTO `zz_area_code` VALUES (430822000000, '桑植县', 3, 430800000000); +INSERT INTO `zz_area_code` VALUES (430900000000, '益阳市', 2, 430000000000); +INSERT INTO `zz_area_code` VALUES (430901000000, '市辖区', 3, 430900000000); +INSERT INTO `zz_area_code` VALUES (430902000000, '资阳区', 3, 430900000000); +INSERT INTO `zz_area_code` VALUES (430903000000, '赫山区', 3, 430900000000); +INSERT INTO `zz_area_code` VALUES (430921000000, '南县', 3, 430900000000); +INSERT INTO `zz_area_code` VALUES (430922000000, '桃江县', 3, 430900000000); +INSERT INTO `zz_area_code` VALUES (430923000000, '安化县', 3, 430900000000); +INSERT INTO `zz_area_code` VALUES (430971000000, '益阳市大通湖管理区', 3, 430900000000); +INSERT INTO `zz_area_code` VALUES (430972000000, '湖南益阳高新技术产业园区', 3, 430900000000); +INSERT INTO `zz_area_code` VALUES (430981000000, '沅江市', 3, 430900000000); +INSERT INTO `zz_area_code` VALUES (431000000000, '郴州市', 2, 430000000000); +INSERT INTO `zz_area_code` VALUES (431001000000, '市辖区', 3, 431000000000); +INSERT INTO `zz_area_code` VALUES (431002000000, '北湖区', 3, 431000000000); +INSERT INTO `zz_area_code` VALUES (431003000000, '苏仙区', 3, 431000000000); +INSERT INTO `zz_area_code` VALUES (431021000000, '桂阳县', 3, 431000000000); +INSERT INTO `zz_area_code` VALUES (431022000000, '宜章县', 3, 431000000000); +INSERT INTO `zz_area_code` VALUES (431023000000, '永兴县', 3, 431000000000); +INSERT INTO `zz_area_code` VALUES (431024000000, '嘉禾县', 3, 431000000000); +INSERT INTO `zz_area_code` VALUES (431025000000, '临武县', 3, 431000000000); +INSERT INTO `zz_area_code` VALUES (431026000000, '汝城县', 3, 431000000000); +INSERT INTO `zz_area_code` VALUES (431027000000, '桂东县', 3, 431000000000); +INSERT INTO `zz_area_code` VALUES (431028000000, '安仁县', 3, 431000000000); +INSERT INTO `zz_area_code` VALUES (431081000000, '资兴市', 3, 431000000000); +INSERT INTO `zz_area_code` VALUES (431100000000, '永州市', 2, 430000000000); +INSERT INTO `zz_area_code` VALUES (431101000000, '市辖区', 3, 431100000000); +INSERT INTO `zz_area_code` VALUES (431102000000, '零陵区', 3, 431100000000); +INSERT INTO `zz_area_code` VALUES (431103000000, '冷水滩区', 3, 431100000000); +INSERT INTO `zz_area_code` VALUES (431121000000, '祁阳县', 3, 431100000000); +INSERT INTO `zz_area_code` VALUES (431122000000, '东安县', 3, 431100000000); +INSERT INTO `zz_area_code` VALUES (431123000000, '双牌县', 3, 431100000000); +INSERT INTO `zz_area_code` VALUES (431124000000, '道县', 3, 431100000000); +INSERT INTO `zz_area_code` VALUES (431125000000, '江永县', 3, 431100000000); +INSERT INTO `zz_area_code` VALUES (431126000000, '宁远县', 3, 431100000000); +INSERT INTO `zz_area_code` VALUES (431127000000, '蓝山县', 3, 431100000000); +INSERT INTO `zz_area_code` VALUES (431128000000, '新田县', 3, 431100000000); +INSERT INTO `zz_area_code` VALUES (431129000000, '江华瑶族自治县', 3, 431100000000); +INSERT INTO `zz_area_code` VALUES (431171000000, '永州经济技术开发区', 3, 431100000000); +INSERT INTO `zz_area_code` VALUES (431172000000, '永州市金洞管理区', 3, 431100000000); +INSERT INTO `zz_area_code` VALUES (431173000000, '永州市回龙圩管理区', 3, 431100000000); +INSERT INTO `zz_area_code` VALUES (431200000000, '怀化市', 2, 430000000000); +INSERT INTO `zz_area_code` VALUES (431201000000, '市辖区', 3, 431200000000); +INSERT INTO `zz_area_code` VALUES (431202000000, '鹤城区', 3, 431200000000); +INSERT INTO `zz_area_code` VALUES (431221000000, '中方县', 3, 431200000000); +INSERT INTO `zz_area_code` VALUES (431222000000, '沅陵县', 3, 431200000000); +INSERT INTO `zz_area_code` VALUES (431223000000, '辰溪县', 3, 431200000000); +INSERT INTO `zz_area_code` VALUES (431224000000, '溆浦县', 3, 431200000000); +INSERT INTO `zz_area_code` VALUES (431225000000, '会同县', 3, 431200000000); +INSERT INTO `zz_area_code` VALUES (431226000000, '麻阳苗族自治县', 3, 431200000000); +INSERT INTO `zz_area_code` VALUES (431227000000, '新晃侗族自治县', 3, 431200000000); +INSERT INTO `zz_area_code` VALUES (431228000000, '芷江侗族自治县', 3, 431200000000); +INSERT INTO `zz_area_code` VALUES (431229000000, '靖州苗族侗族自治县', 3, 431200000000); +INSERT INTO `zz_area_code` VALUES (431230000000, '通道侗族自治县', 3, 431200000000); +INSERT INTO `zz_area_code` VALUES (431271000000, '怀化市洪江管理区', 3, 431200000000); +INSERT INTO `zz_area_code` VALUES (431281000000, '洪江市', 3, 431200000000); +INSERT INTO `zz_area_code` VALUES (431300000000, '娄底市', 2, 430000000000); +INSERT INTO `zz_area_code` VALUES (431301000000, '市辖区', 3, 431300000000); +INSERT INTO `zz_area_code` VALUES (431302000000, '娄星区', 3, 431300000000); +INSERT INTO `zz_area_code` VALUES (431321000000, '双峰县', 3, 431300000000); +INSERT INTO `zz_area_code` VALUES (431322000000, '新化县', 3, 431300000000); +INSERT INTO `zz_area_code` VALUES (431381000000, '冷水江市', 3, 431300000000); +INSERT INTO `zz_area_code` VALUES (431382000000, '涟源市', 3, 431300000000); +INSERT INTO `zz_area_code` VALUES (433100000000, '湘西土家族苗族自治州', 2, 430000000000); +INSERT INTO `zz_area_code` VALUES (433101000000, '吉首市', 3, 433100000000); +INSERT INTO `zz_area_code` VALUES (433122000000, '泸溪县', 3, 433100000000); +INSERT INTO `zz_area_code` VALUES (433123000000, '凤凰县', 3, 433100000000); +INSERT INTO `zz_area_code` VALUES (433124000000, '花垣县', 3, 433100000000); +INSERT INTO `zz_area_code` VALUES (433125000000, '保靖县', 3, 433100000000); +INSERT INTO `zz_area_code` VALUES (433126000000, '古丈县', 3, 433100000000); +INSERT INTO `zz_area_code` VALUES (433127000000, '永顺县', 3, 433100000000); +INSERT INTO `zz_area_code` VALUES (433130000000, '龙山县', 3, 433100000000); +INSERT INTO `zz_area_code` VALUES (433172000000, '湖南吉首经济开发区', 3, 433100000000); +INSERT INTO `zz_area_code` VALUES (433173000000, '湖南永顺经济开发区', 3, 433100000000); +INSERT INTO `zz_area_code` VALUES (440000000000, '广东省', 1, NULL); +INSERT INTO `zz_area_code` VALUES (440100000000, '广州市', 2, 440000000000); +INSERT INTO `zz_area_code` VALUES (440101000000, '市辖区', 3, 440100000000); +INSERT INTO `zz_area_code` VALUES (440103000000, '荔湾区', 3, 440100000000); +INSERT INTO `zz_area_code` VALUES (440104000000, '越秀区', 3, 440100000000); +INSERT INTO `zz_area_code` VALUES (440105000000, '海珠区', 3, 440100000000); +INSERT INTO `zz_area_code` VALUES (440106000000, '天河区', 3, 440100000000); +INSERT INTO `zz_area_code` VALUES (440111000000, '白云区', 3, 440100000000); +INSERT INTO `zz_area_code` VALUES (440112000000, '黄埔区', 3, 440100000000); +INSERT INTO `zz_area_code` VALUES (440113000000, '番禺区', 3, 440100000000); +INSERT INTO `zz_area_code` VALUES (440114000000, '花都区', 3, 440100000000); +INSERT INTO `zz_area_code` VALUES (440115000000, '南沙区', 3, 440100000000); +INSERT INTO `zz_area_code` VALUES (440117000000, '从化区', 3, 440100000000); +INSERT INTO `zz_area_code` VALUES (440118000000, '增城区', 3, 440100000000); +INSERT INTO `zz_area_code` VALUES (440200000000, '韶关市', 2, 440000000000); +INSERT INTO `zz_area_code` VALUES (440201000000, '市辖区', 3, 440200000000); +INSERT INTO `zz_area_code` VALUES (440203000000, '武江区', 3, 440200000000); +INSERT INTO `zz_area_code` VALUES (440204000000, '浈江区', 3, 440200000000); +INSERT INTO `zz_area_code` VALUES (440205000000, '曲江区', 3, 440200000000); +INSERT INTO `zz_area_code` VALUES (440222000000, '始兴县', 3, 440200000000); +INSERT INTO `zz_area_code` VALUES (440224000000, '仁化县', 3, 440200000000); +INSERT INTO `zz_area_code` VALUES (440229000000, '翁源县', 3, 440200000000); +INSERT INTO `zz_area_code` VALUES (440232000000, '乳源瑶族自治县', 3, 440200000000); +INSERT INTO `zz_area_code` VALUES (440233000000, '新丰县', 3, 440200000000); +INSERT INTO `zz_area_code` VALUES (440281000000, '乐昌市', 3, 440200000000); +INSERT INTO `zz_area_code` VALUES (440282000000, '南雄市', 3, 440200000000); +INSERT INTO `zz_area_code` VALUES (440300000000, '深圳市', 2, 440000000000); +INSERT INTO `zz_area_code` VALUES (440301000000, '市辖区', 3, 440300000000); +INSERT INTO `zz_area_code` VALUES (440303000000, '罗湖区', 3, 440300000000); +INSERT INTO `zz_area_code` VALUES (440304000000, '福田区', 3, 440300000000); +INSERT INTO `zz_area_code` VALUES (440305000000, '南山区', 3, 440300000000); +INSERT INTO `zz_area_code` VALUES (440306000000, '宝安区', 3, 440300000000); +INSERT INTO `zz_area_code` VALUES (440307000000, '龙岗区', 3, 440300000000); +INSERT INTO `zz_area_code` VALUES (440308000000, '盐田区', 3, 440300000000); +INSERT INTO `zz_area_code` VALUES (440309000000, '龙华区', 3, 440300000000); +INSERT INTO `zz_area_code` VALUES (440310000000, '坪山区', 3, 440300000000); +INSERT INTO `zz_area_code` VALUES (440311000000, '光明区', 3, 440300000000); +INSERT INTO `zz_area_code` VALUES (440400000000, '珠海市', 2, 440000000000); +INSERT INTO `zz_area_code` VALUES (440401000000, '市辖区', 3, 440400000000); +INSERT INTO `zz_area_code` VALUES (440402000000, '香洲区', 3, 440400000000); +INSERT INTO `zz_area_code` VALUES (440403000000, '斗门区', 3, 440400000000); +INSERT INTO `zz_area_code` VALUES (440404000000, '金湾区', 3, 440400000000); +INSERT INTO `zz_area_code` VALUES (440500000000, '汕头市', 2, 440000000000); +INSERT INTO `zz_area_code` VALUES (440501000000, '市辖区', 3, 440500000000); +INSERT INTO `zz_area_code` VALUES (440507000000, '龙湖区', 3, 440500000000); +INSERT INTO `zz_area_code` VALUES (440511000000, '金平区', 3, 440500000000); +INSERT INTO `zz_area_code` VALUES (440512000000, '濠江区', 3, 440500000000); +INSERT INTO `zz_area_code` VALUES (440513000000, '潮阳区', 3, 440500000000); +INSERT INTO `zz_area_code` VALUES (440514000000, '潮南区', 3, 440500000000); +INSERT INTO `zz_area_code` VALUES (440515000000, '澄海区', 3, 440500000000); +INSERT INTO `zz_area_code` VALUES (440523000000, '南澳县', 3, 440500000000); +INSERT INTO `zz_area_code` VALUES (440600000000, '佛山市', 2, 440000000000); +INSERT INTO `zz_area_code` VALUES (440601000000, '市辖区', 3, 440600000000); +INSERT INTO `zz_area_code` VALUES (440604000000, '禅城区', 3, 440600000000); +INSERT INTO `zz_area_code` VALUES (440605000000, '南海区', 3, 440600000000); +INSERT INTO `zz_area_code` VALUES (440606000000, '顺德区', 3, 440600000000); +INSERT INTO `zz_area_code` VALUES (440607000000, '三水区', 3, 440600000000); +INSERT INTO `zz_area_code` VALUES (440608000000, '高明区', 3, 440600000000); +INSERT INTO `zz_area_code` VALUES (440700000000, '江门市', 2, 440000000000); +INSERT INTO `zz_area_code` VALUES (440701000000, '市辖区', 3, 440700000000); +INSERT INTO `zz_area_code` VALUES (440703000000, '蓬江区', 3, 440700000000); +INSERT INTO `zz_area_code` VALUES (440704000000, '江海区', 3, 440700000000); +INSERT INTO `zz_area_code` VALUES (440705000000, '新会区', 3, 440700000000); +INSERT INTO `zz_area_code` VALUES (440781000000, '台山市', 3, 440700000000); +INSERT INTO `zz_area_code` VALUES (440783000000, '开平市', 3, 440700000000); +INSERT INTO `zz_area_code` VALUES (440784000000, '鹤山市', 3, 440700000000); +INSERT INTO `zz_area_code` VALUES (440785000000, '恩平市', 3, 440700000000); +INSERT INTO `zz_area_code` VALUES (440800000000, '湛江市', 2, 440000000000); +INSERT INTO `zz_area_code` VALUES (440801000000, '市辖区', 3, 440800000000); +INSERT INTO `zz_area_code` VALUES (440802000000, '赤坎区', 3, 440800000000); +INSERT INTO `zz_area_code` VALUES (440803000000, '霞山区', 3, 440800000000); +INSERT INTO `zz_area_code` VALUES (440804000000, '坡头区', 3, 440800000000); +INSERT INTO `zz_area_code` VALUES (440811000000, '麻章区', 3, 440800000000); +INSERT INTO `zz_area_code` VALUES (440823000000, '遂溪县', 3, 440800000000); +INSERT INTO `zz_area_code` VALUES (440825000000, '徐闻县', 3, 440800000000); +INSERT INTO `zz_area_code` VALUES (440881000000, '廉江市', 3, 440800000000); +INSERT INTO `zz_area_code` VALUES (440882000000, '雷州市', 3, 440800000000); +INSERT INTO `zz_area_code` VALUES (440883000000, '吴川市', 3, 440800000000); +INSERT INTO `zz_area_code` VALUES (440900000000, '茂名市', 2, 440000000000); +INSERT INTO `zz_area_code` VALUES (440901000000, '市辖区', 3, 440900000000); +INSERT INTO `zz_area_code` VALUES (440902000000, '茂南区', 3, 440900000000); +INSERT INTO `zz_area_code` VALUES (440904000000, '电白区', 3, 440900000000); +INSERT INTO `zz_area_code` VALUES (440981000000, '高州市', 3, 440900000000); +INSERT INTO `zz_area_code` VALUES (440982000000, '化州市', 3, 440900000000); +INSERT INTO `zz_area_code` VALUES (440983000000, '信宜市', 3, 440900000000); +INSERT INTO `zz_area_code` VALUES (441200000000, '肇庆市', 2, 440000000000); +INSERT INTO `zz_area_code` VALUES (441201000000, '市辖区', 3, 441200000000); +INSERT INTO `zz_area_code` VALUES (441202000000, '端州区', 3, 441200000000); +INSERT INTO `zz_area_code` VALUES (441203000000, '鼎湖区', 3, 441200000000); +INSERT INTO `zz_area_code` VALUES (441204000000, '高要区', 3, 441200000000); +INSERT INTO `zz_area_code` VALUES (441223000000, '广宁县', 3, 441200000000); +INSERT INTO `zz_area_code` VALUES (441224000000, '怀集县', 3, 441200000000); +INSERT INTO `zz_area_code` VALUES (441225000000, '封开县', 3, 441200000000); +INSERT INTO `zz_area_code` VALUES (441226000000, '德庆县', 3, 441200000000); +INSERT INTO `zz_area_code` VALUES (441284000000, '四会市', 3, 441200000000); +INSERT INTO `zz_area_code` VALUES (441300000000, '惠州市', 2, 440000000000); +INSERT INTO `zz_area_code` VALUES (441301000000, '市辖区', 3, 441300000000); +INSERT INTO `zz_area_code` VALUES (441302000000, '惠城区', 3, 441300000000); +INSERT INTO `zz_area_code` VALUES (441303000000, '惠阳区', 3, 441300000000); +INSERT INTO `zz_area_code` VALUES (441322000000, '博罗县', 3, 441300000000); +INSERT INTO `zz_area_code` VALUES (441323000000, '惠东县', 3, 441300000000); +INSERT INTO `zz_area_code` VALUES (441324000000, '龙门县', 3, 441300000000); +INSERT INTO `zz_area_code` VALUES (441400000000, '梅州市', 2, 440000000000); +INSERT INTO `zz_area_code` VALUES (441401000000, '市辖区', 3, 441400000000); +INSERT INTO `zz_area_code` VALUES (441402000000, '梅江区', 3, 441400000000); +INSERT INTO `zz_area_code` VALUES (441403000000, '梅县区', 3, 441400000000); +INSERT INTO `zz_area_code` VALUES (441422000000, '大埔县', 3, 441400000000); +INSERT INTO `zz_area_code` VALUES (441423000000, '丰顺县', 3, 441400000000); +INSERT INTO `zz_area_code` VALUES (441424000000, '五华县', 3, 441400000000); +INSERT INTO `zz_area_code` VALUES (441426000000, '平远县', 3, 441400000000); +INSERT INTO `zz_area_code` VALUES (441427000000, '蕉岭县', 3, 441400000000); +INSERT INTO `zz_area_code` VALUES (441481000000, '兴宁市', 3, 441400000000); +INSERT INTO `zz_area_code` VALUES (441500000000, '汕尾市', 2, 440000000000); +INSERT INTO `zz_area_code` VALUES (441501000000, '市辖区', 3, 441500000000); +INSERT INTO `zz_area_code` VALUES (441502000000, '城区', 3, 441500000000); +INSERT INTO `zz_area_code` VALUES (441521000000, '海丰县', 3, 441500000000); +INSERT INTO `zz_area_code` VALUES (441523000000, '陆河县', 3, 441500000000); +INSERT INTO `zz_area_code` VALUES (441581000000, '陆丰市', 3, 441500000000); +INSERT INTO `zz_area_code` VALUES (441600000000, '河源市', 2, 440000000000); +INSERT INTO `zz_area_code` VALUES (441601000000, '市辖区', 3, 441600000000); +INSERT INTO `zz_area_code` VALUES (441602000000, '源城区', 3, 441600000000); +INSERT INTO `zz_area_code` VALUES (441621000000, '紫金县', 3, 441600000000); +INSERT INTO `zz_area_code` VALUES (441622000000, '龙川县', 3, 441600000000); +INSERT INTO `zz_area_code` VALUES (441623000000, '连平县', 3, 441600000000); +INSERT INTO `zz_area_code` VALUES (441624000000, '和平县', 3, 441600000000); +INSERT INTO `zz_area_code` VALUES (441625000000, '东源县', 3, 441600000000); +INSERT INTO `zz_area_code` VALUES (441700000000, '阳江市', 2, 440000000000); +INSERT INTO `zz_area_code` VALUES (441701000000, '市辖区', 3, 441700000000); +INSERT INTO `zz_area_code` VALUES (441702000000, '江城区', 3, 441700000000); +INSERT INTO `zz_area_code` VALUES (441704000000, '阳东区', 3, 441700000000); +INSERT INTO `zz_area_code` VALUES (441721000000, '阳西县', 3, 441700000000); +INSERT INTO `zz_area_code` VALUES (441781000000, '阳春市', 3, 441700000000); +INSERT INTO `zz_area_code` VALUES (441800000000, '清远市', 2, 440000000000); +INSERT INTO `zz_area_code` VALUES (441801000000, '市辖区', 3, 441800000000); +INSERT INTO `zz_area_code` VALUES (441802000000, '清城区', 3, 441800000000); +INSERT INTO `zz_area_code` VALUES (441803000000, '清新区', 3, 441800000000); +INSERT INTO `zz_area_code` VALUES (441821000000, '佛冈县', 3, 441800000000); +INSERT INTO `zz_area_code` VALUES (441823000000, '阳山县', 3, 441800000000); +INSERT INTO `zz_area_code` VALUES (441825000000, '连山壮族瑶族自治县', 3, 441800000000); +INSERT INTO `zz_area_code` VALUES (441826000000, '连南瑶族自治县', 3, 441800000000); +INSERT INTO `zz_area_code` VALUES (441881000000, '英德市', 3, 441800000000); +INSERT INTO `zz_area_code` VALUES (441882000000, '连州市', 3, 441800000000); +INSERT INTO `zz_area_code` VALUES (441900000000, '东莞市', 2, 440000000000); +INSERT INTO `zz_area_code` VALUES (442000000000, '中山市', 2, 440000000000); +INSERT INTO `zz_area_code` VALUES (445100000000, '潮州市', 2, 440000000000); +INSERT INTO `zz_area_code` VALUES (445101000000, '市辖区', 3, 445100000000); +INSERT INTO `zz_area_code` VALUES (445102000000, '湘桥区', 3, 445100000000); +INSERT INTO `zz_area_code` VALUES (445103000000, '潮安区', 3, 445100000000); +INSERT INTO `zz_area_code` VALUES (445122000000, '饶平县', 3, 445100000000); +INSERT INTO `zz_area_code` VALUES (445200000000, '揭阳市', 2, 440000000000); +INSERT INTO `zz_area_code` VALUES (445201000000, '市辖区', 3, 445200000000); +INSERT INTO `zz_area_code` VALUES (445202000000, '榕城区', 3, 445200000000); +INSERT INTO `zz_area_code` VALUES (445203000000, '揭东区', 3, 445200000000); +INSERT INTO `zz_area_code` VALUES (445222000000, '揭西县', 3, 445200000000); +INSERT INTO `zz_area_code` VALUES (445224000000, '惠来县', 3, 445200000000); +INSERT INTO `zz_area_code` VALUES (445281000000, '普宁市', 3, 445200000000); +INSERT INTO `zz_area_code` VALUES (445300000000, '云浮市', 2, 440000000000); +INSERT INTO `zz_area_code` VALUES (445301000000, '市辖区', 3, 445300000000); +INSERT INTO `zz_area_code` VALUES (445302000000, '云城区', 3, 445300000000); +INSERT INTO `zz_area_code` VALUES (445303000000, '云安区', 3, 445300000000); +INSERT INTO `zz_area_code` VALUES (445321000000, '新兴县', 3, 445300000000); +INSERT INTO `zz_area_code` VALUES (445322000000, '郁南县', 3, 445300000000); +INSERT INTO `zz_area_code` VALUES (445381000000, '罗定市', 3, 445300000000); +INSERT INTO `zz_area_code` VALUES (450000000000, '广西壮族自治区', 1, NULL); +INSERT INTO `zz_area_code` VALUES (450100000000, '南宁市', 2, 450000000000); +INSERT INTO `zz_area_code` VALUES (450101000000, '市辖区', 3, 450100000000); +INSERT INTO `zz_area_code` VALUES (450102000000, '兴宁区', 3, 450100000000); +INSERT INTO `zz_area_code` VALUES (450103000000, '青秀区', 3, 450100000000); +INSERT INTO `zz_area_code` VALUES (450105000000, '江南区', 3, 450100000000); +INSERT INTO `zz_area_code` VALUES (450107000000, '西乡塘区', 3, 450100000000); +INSERT INTO `zz_area_code` VALUES (450108000000, '良庆区', 3, 450100000000); +INSERT INTO `zz_area_code` VALUES (450109000000, '邕宁区', 3, 450100000000); +INSERT INTO `zz_area_code` VALUES (450110000000, '武鸣区', 3, 450100000000); +INSERT INTO `zz_area_code` VALUES (450123000000, '隆安县', 3, 450100000000); +INSERT INTO `zz_area_code` VALUES (450124000000, '马山县', 3, 450100000000); +INSERT INTO `zz_area_code` VALUES (450125000000, '上林县', 3, 450100000000); +INSERT INTO `zz_area_code` VALUES (450126000000, '宾阳县', 3, 450100000000); +INSERT INTO `zz_area_code` VALUES (450127000000, '横县', 3, 450100000000); +INSERT INTO `zz_area_code` VALUES (450200000000, '柳州市', 2, 450000000000); +INSERT INTO `zz_area_code` VALUES (450201000000, '市辖区', 3, 450200000000); +INSERT INTO `zz_area_code` VALUES (450202000000, '城中区', 3, 450200000000); +INSERT INTO `zz_area_code` VALUES (450203000000, '鱼峰区', 3, 450200000000); +INSERT INTO `zz_area_code` VALUES (450204000000, '柳南区', 3, 450200000000); +INSERT INTO `zz_area_code` VALUES (450205000000, '柳北区', 3, 450200000000); +INSERT INTO `zz_area_code` VALUES (450206000000, '柳江区', 3, 450200000000); +INSERT INTO `zz_area_code` VALUES (450222000000, '柳城县', 3, 450200000000); +INSERT INTO `zz_area_code` VALUES (450223000000, '鹿寨县', 3, 450200000000); +INSERT INTO `zz_area_code` VALUES (450224000000, '融安县', 3, 450200000000); +INSERT INTO `zz_area_code` VALUES (450225000000, '融水苗族自治县', 3, 450200000000); +INSERT INTO `zz_area_code` VALUES (450226000000, '三江侗族自治县', 3, 450200000000); +INSERT INTO `zz_area_code` VALUES (450300000000, '桂林市', 2, 450000000000); +INSERT INTO `zz_area_code` VALUES (450301000000, '市辖区', 3, 450300000000); +INSERT INTO `zz_area_code` VALUES (450302000000, '秀峰区', 3, 450300000000); +INSERT INTO `zz_area_code` VALUES (450303000000, '叠彩区', 3, 450300000000); +INSERT INTO `zz_area_code` VALUES (450304000000, '象山区', 3, 450300000000); +INSERT INTO `zz_area_code` VALUES (450305000000, '七星区', 3, 450300000000); +INSERT INTO `zz_area_code` VALUES (450311000000, '雁山区', 3, 450300000000); +INSERT INTO `zz_area_code` VALUES (450312000000, '临桂区', 3, 450300000000); +INSERT INTO `zz_area_code` VALUES (450321000000, '阳朔县', 3, 450300000000); +INSERT INTO `zz_area_code` VALUES (450323000000, '灵川县', 3, 450300000000); +INSERT INTO `zz_area_code` VALUES (450324000000, '全州县', 3, 450300000000); +INSERT INTO `zz_area_code` VALUES (450325000000, '兴安县', 3, 450300000000); +INSERT INTO `zz_area_code` VALUES (450326000000, '永福县', 3, 450300000000); +INSERT INTO `zz_area_code` VALUES (450327000000, '灌阳县', 3, 450300000000); +INSERT INTO `zz_area_code` VALUES (450328000000, '龙胜各族自治县', 3, 450300000000); +INSERT INTO `zz_area_code` VALUES (450329000000, '资源县', 3, 450300000000); +INSERT INTO `zz_area_code` VALUES (450330000000, '平乐县', 3, 450300000000); +INSERT INTO `zz_area_code` VALUES (450332000000, '恭城瑶族自治县', 3, 450300000000); +INSERT INTO `zz_area_code` VALUES (450381000000, '荔浦市', 3, 450300000000); +INSERT INTO `zz_area_code` VALUES (450400000000, '梧州市', 2, 450000000000); +INSERT INTO `zz_area_code` VALUES (450401000000, '市辖区', 3, 450400000000); +INSERT INTO `zz_area_code` VALUES (450403000000, '万秀区', 3, 450400000000); +INSERT INTO `zz_area_code` VALUES (450405000000, '长洲区', 3, 450400000000); +INSERT INTO `zz_area_code` VALUES (450406000000, '龙圩区', 3, 450400000000); +INSERT INTO `zz_area_code` VALUES (450421000000, '苍梧县', 3, 450400000000); +INSERT INTO `zz_area_code` VALUES (450422000000, '藤县', 3, 450400000000); +INSERT INTO `zz_area_code` VALUES (450423000000, '蒙山县', 3, 450400000000); +INSERT INTO `zz_area_code` VALUES (450481000000, '岑溪市', 3, 450400000000); +INSERT INTO `zz_area_code` VALUES (450500000000, '北海市', 2, 450000000000); +INSERT INTO `zz_area_code` VALUES (450501000000, '市辖区', 3, 450500000000); +INSERT INTO `zz_area_code` VALUES (450502000000, '海城区', 3, 450500000000); +INSERT INTO `zz_area_code` VALUES (450503000000, '银海区', 3, 450500000000); +INSERT INTO `zz_area_code` VALUES (450512000000, '铁山港区', 3, 450500000000); +INSERT INTO `zz_area_code` VALUES (450521000000, '合浦县', 3, 450500000000); +INSERT INTO `zz_area_code` VALUES (450600000000, '防城港市', 2, 450000000000); +INSERT INTO `zz_area_code` VALUES (450601000000, '市辖区', 3, 450600000000); +INSERT INTO `zz_area_code` VALUES (450602000000, '港口区', 3, 450600000000); +INSERT INTO `zz_area_code` VALUES (450603000000, '防城区', 3, 450600000000); +INSERT INTO `zz_area_code` VALUES (450621000000, '上思县', 3, 450600000000); +INSERT INTO `zz_area_code` VALUES (450681000000, '东兴市', 3, 450600000000); +INSERT INTO `zz_area_code` VALUES (450700000000, '钦州市', 2, 450000000000); +INSERT INTO `zz_area_code` VALUES (450701000000, '市辖区', 3, 450700000000); +INSERT INTO `zz_area_code` VALUES (450702000000, '钦南区', 3, 450700000000); +INSERT INTO `zz_area_code` VALUES (450703000000, '钦北区', 3, 450700000000); +INSERT INTO `zz_area_code` VALUES (450721000000, '灵山县', 3, 450700000000); +INSERT INTO `zz_area_code` VALUES (450722000000, '浦北县', 3, 450700000000); +INSERT INTO `zz_area_code` VALUES (450800000000, '贵港市', 2, 450000000000); +INSERT INTO `zz_area_code` VALUES (450801000000, '市辖区', 3, 450800000000); +INSERT INTO `zz_area_code` VALUES (450802000000, '港北区', 3, 450800000000); +INSERT INTO `zz_area_code` VALUES (450803000000, '港南区', 3, 450800000000); +INSERT INTO `zz_area_code` VALUES (450804000000, '覃塘区', 3, 450800000000); +INSERT INTO `zz_area_code` VALUES (450821000000, '平南县', 3, 450800000000); +INSERT INTO `zz_area_code` VALUES (450881000000, '桂平市', 3, 450800000000); +INSERT INTO `zz_area_code` VALUES (450900000000, '玉林市', 2, 450000000000); +INSERT INTO `zz_area_code` VALUES (450901000000, '市辖区', 3, 450900000000); +INSERT INTO `zz_area_code` VALUES (450902000000, '玉州区', 3, 450900000000); +INSERT INTO `zz_area_code` VALUES (450903000000, '福绵区', 3, 450900000000); +INSERT INTO `zz_area_code` VALUES (450921000000, '容县', 3, 450900000000); +INSERT INTO `zz_area_code` VALUES (450922000000, '陆川县', 3, 450900000000); +INSERT INTO `zz_area_code` VALUES (450923000000, '博白县', 3, 450900000000); +INSERT INTO `zz_area_code` VALUES (450924000000, '兴业县', 3, 450900000000); +INSERT INTO `zz_area_code` VALUES (450981000000, '北流市', 3, 450900000000); +INSERT INTO `zz_area_code` VALUES (451000000000, '百色市', 2, 450000000000); +INSERT INTO `zz_area_code` VALUES (451001000000, '市辖区', 3, 451000000000); +INSERT INTO `zz_area_code` VALUES (451002000000, '右江区', 3, 451000000000); +INSERT INTO `zz_area_code` VALUES (451021000000, '田阳县', 3, 451000000000); +INSERT INTO `zz_area_code` VALUES (451022000000, '田东县', 3, 451000000000); +INSERT INTO `zz_area_code` VALUES (451023000000, '平果县', 3, 451000000000); +INSERT INTO `zz_area_code` VALUES (451024000000, '德保县', 3, 451000000000); +INSERT INTO `zz_area_code` VALUES (451026000000, '那坡县', 3, 451000000000); +INSERT INTO `zz_area_code` VALUES (451027000000, '凌云县', 3, 451000000000); +INSERT INTO `zz_area_code` VALUES (451028000000, '乐业县', 3, 451000000000); +INSERT INTO `zz_area_code` VALUES (451029000000, '田林县', 3, 451000000000); +INSERT INTO `zz_area_code` VALUES (451030000000, '西林县', 3, 451000000000); +INSERT INTO `zz_area_code` VALUES (451031000000, '隆林各族自治县', 3, 451000000000); +INSERT INTO `zz_area_code` VALUES (451081000000, '靖西市', 3, 451000000000); +INSERT INTO `zz_area_code` VALUES (451100000000, '贺州市', 2, 450000000000); +INSERT INTO `zz_area_code` VALUES (451101000000, '市辖区', 3, 451100000000); +INSERT INTO `zz_area_code` VALUES (451102000000, '八步区', 3, 451100000000); +INSERT INTO `zz_area_code` VALUES (451103000000, '平桂区', 3, 451100000000); +INSERT INTO `zz_area_code` VALUES (451121000000, '昭平县', 3, 451100000000); +INSERT INTO `zz_area_code` VALUES (451122000000, '钟山县', 3, 451100000000); +INSERT INTO `zz_area_code` VALUES (451123000000, '富川瑶族自治县', 3, 451100000000); +INSERT INTO `zz_area_code` VALUES (451200000000, '河池市', 2, 450000000000); +INSERT INTO `zz_area_code` VALUES (451201000000, '市辖区', 3, 451200000000); +INSERT INTO `zz_area_code` VALUES (451202000000, '金城江区', 3, 451200000000); +INSERT INTO `zz_area_code` VALUES (451203000000, '宜州区', 3, 451200000000); +INSERT INTO `zz_area_code` VALUES (451221000000, '南丹县', 3, 451200000000); +INSERT INTO `zz_area_code` VALUES (451222000000, '天峨县', 3, 451200000000); +INSERT INTO `zz_area_code` VALUES (451223000000, '凤山县', 3, 451200000000); +INSERT INTO `zz_area_code` VALUES (451224000000, '东兰县', 3, 451200000000); +INSERT INTO `zz_area_code` VALUES (451225000000, '罗城仫佬族自治县', 3, 451200000000); +INSERT INTO `zz_area_code` VALUES (451226000000, '环江毛南族自治县', 3, 451200000000); +INSERT INTO `zz_area_code` VALUES (451227000000, '巴马瑶族自治县', 3, 451200000000); +INSERT INTO `zz_area_code` VALUES (451228000000, '都安瑶族自治县', 3, 451200000000); +INSERT INTO `zz_area_code` VALUES (451229000000, '大化瑶族自治县', 3, 451200000000); +INSERT INTO `zz_area_code` VALUES (451300000000, '来宾市', 2, 450000000000); +INSERT INTO `zz_area_code` VALUES (451301000000, '市辖区', 3, 451300000000); +INSERT INTO `zz_area_code` VALUES (451302000000, '兴宾区', 3, 451300000000); +INSERT INTO `zz_area_code` VALUES (451321000000, '忻城县', 3, 451300000000); +INSERT INTO `zz_area_code` VALUES (451322000000, '象州县', 3, 451300000000); +INSERT INTO `zz_area_code` VALUES (451323000000, '武宣县', 3, 451300000000); +INSERT INTO `zz_area_code` VALUES (451324000000, '金秀瑶族自治县', 3, 451300000000); +INSERT INTO `zz_area_code` VALUES (451381000000, '合山市', 3, 451300000000); +INSERT INTO `zz_area_code` VALUES (451400000000, '崇左市', 2, 450000000000); +INSERT INTO `zz_area_code` VALUES (451401000000, '市辖区', 3, 451400000000); +INSERT INTO `zz_area_code` VALUES (451402000000, '江州区', 3, 451400000000); +INSERT INTO `zz_area_code` VALUES (451421000000, '扶绥县', 3, 451400000000); +INSERT INTO `zz_area_code` VALUES (451422000000, '宁明县', 3, 451400000000); +INSERT INTO `zz_area_code` VALUES (451423000000, '龙州县', 3, 451400000000); +INSERT INTO `zz_area_code` VALUES (451424000000, '大新县', 3, 451400000000); +INSERT INTO `zz_area_code` VALUES (451425000000, '天等县', 3, 451400000000); +INSERT INTO `zz_area_code` VALUES (451481000000, '凭祥市', 3, 451400000000); +INSERT INTO `zz_area_code` VALUES (460000000000, '海南省', 1, NULL); +INSERT INTO `zz_area_code` VALUES (460100000000, '海口市', 2, 460000000000); +INSERT INTO `zz_area_code` VALUES (460101000000, '市辖区', 3, 460100000000); +INSERT INTO `zz_area_code` VALUES (460105000000, '秀英区', 3, 460100000000); +INSERT INTO `zz_area_code` VALUES (460106000000, '龙华区', 3, 460100000000); +INSERT INTO `zz_area_code` VALUES (460107000000, '琼山区', 3, 460100000000); +INSERT INTO `zz_area_code` VALUES (460108000000, '美兰区', 3, 460100000000); +INSERT INTO `zz_area_code` VALUES (460200000000, '三亚市', 2, 460000000000); +INSERT INTO `zz_area_code` VALUES (460201000000, '市辖区', 3, 460200000000); +INSERT INTO `zz_area_code` VALUES (460202000000, '海棠区', 3, 460200000000); +INSERT INTO `zz_area_code` VALUES (460203000000, '吉阳区', 3, 460200000000); +INSERT INTO `zz_area_code` VALUES (460204000000, '天涯区', 3, 460200000000); +INSERT INTO `zz_area_code` VALUES (460205000000, '崖州区', 3, 460200000000); +INSERT INTO `zz_area_code` VALUES (460300000000, '三沙市', 2, 460000000000); +INSERT INTO `zz_area_code` VALUES (460321000000, '西沙群岛', 3, 460300000000); +INSERT INTO `zz_area_code` VALUES (460322000000, '南沙群岛', 3, 460300000000); +INSERT INTO `zz_area_code` VALUES (460323000000, '中沙群岛的岛礁及其海域', 3, 460300000000); +INSERT INTO `zz_area_code` VALUES (460400000000, '儋州市', 2, 460000000000); +INSERT INTO `zz_area_code` VALUES (469000000000, '省直辖县级行政区划', 2, 460000000000); +INSERT INTO `zz_area_code` VALUES (469001000000, '五指山市', 3, 469000000000); +INSERT INTO `zz_area_code` VALUES (469002000000, '琼海市', 3, 469000000000); +INSERT INTO `zz_area_code` VALUES (469005000000, '文昌市', 3, 469000000000); +INSERT INTO `zz_area_code` VALUES (469006000000, '万宁市', 3, 469000000000); +INSERT INTO `zz_area_code` VALUES (469007000000, '东方市', 3, 469000000000); +INSERT INTO `zz_area_code` VALUES (469021000000, '定安县', 3, 469000000000); +INSERT INTO `zz_area_code` VALUES (469022000000, '屯昌县', 3, 469000000000); +INSERT INTO `zz_area_code` VALUES (469023000000, '澄迈县', 3, 469000000000); +INSERT INTO `zz_area_code` VALUES (469024000000, '临高县', 3, 469000000000); +INSERT INTO `zz_area_code` VALUES (469025000000, '白沙黎族自治县', 3, 469000000000); +INSERT INTO `zz_area_code` VALUES (469026000000, '昌江黎族自治县', 3, 469000000000); +INSERT INTO `zz_area_code` VALUES (469027000000, '乐东黎族自治县', 3, 469000000000); +INSERT INTO `zz_area_code` VALUES (469028000000, '陵水黎族自治县', 3, 469000000000); +INSERT INTO `zz_area_code` VALUES (469029000000, '保亭黎族苗族自治县', 3, 469000000000); +INSERT INTO `zz_area_code` VALUES (469030000000, '琼中黎族苗族自治县', 3, 469000000000); +INSERT INTO `zz_area_code` VALUES (500000000000, '重庆市', 1, NULL); +INSERT INTO `zz_area_code` VALUES (500100000000, '市辖区', 2, 500000000000); +INSERT INTO `zz_area_code` VALUES (500101000000, '万州区', 3, 500100000000); +INSERT INTO `zz_area_code` VALUES (500102000000, '涪陵区', 3, 500100000000); +INSERT INTO `zz_area_code` VALUES (500103000000, '渝中区', 3, 500100000000); +INSERT INTO `zz_area_code` VALUES (500104000000, '大渡口区', 3, 500100000000); +INSERT INTO `zz_area_code` VALUES (500105000000, '江北区', 3, 500100000000); +INSERT INTO `zz_area_code` VALUES (500106000000, '沙坪坝区', 3, 500100000000); +INSERT INTO `zz_area_code` VALUES (500107000000, '九龙坡区', 3, 500100000000); +INSERT INTO `zz_area_code` VALUES (500108000000, '南岸区', 3, 500100000000); +INSERT INTO `zz_area_code` VALUES (500109000000, '北碚区', 3, 500100000000); +INSERT INTO `zz_area_code` VALUES (500110000000, '綦江区', 3, 500100000000); +INSERT INTO `zz_area_code` VALUES (500111000000, '大足区', 3, 500100000000); +INSERT INTO `zz_area_code` VALUES (500112000000, '渝北区', 3, 500100000000); +INSERT INTO `zz_area_code` VALUES (500113000000, '巴南区', 3, 500100000000); +INSERT INTO `zz_area_code` VALUES (500114000000, '黔江区', 3, 500100000000); +INSERT INTO `zz_area_code` VALUES (500115000000, '长寿区', 3, 500100000000); +INSERT INTO `zz_area_code` VALUES (500116000000, '江津区', 3, 500100000000); +INSERT INTO `zz_area_code` VALUES (500117000000, '合川区', 3, 500100000000); +INSERT INTO `zz_area_code` VALUES (500118000000, '永川区', 3, 500100000000); +INSERT INTO `zz_area_code` VALUES (500119000000, '南川区', 3, 500100000000); +INSERT INTO `zz_area_code` VALUES (500120000000, '璧山区', 3, 500100000000); +INSERT INTO `zz_area_code` VALUES (500151000000, '铜梁区', 3, 500100000000); +INSERT INTO `zz_area_code` VALUES (500152000000, '潼南区', 3, 500100000000); +INSERT INTO `zz_area_code` VALUES (500153000000, '荣昌区', 3, 500100000000); +INSERT INTO `zz_area_code` VALUES (500154000000, '开州区', 3, 500100000000); +INSERT INTO `zz_area_code` VALUES (500155000000, '梁平区', 3, 500100000000); +INSERT INTO `zz_area_code` VALUES (500156000000, '武隆区', 3, 500100000000); +INSERT INTO `zz_area_code` VALUES (500200000000, '县', 2, 500000000000); +INSERT INTO `zz_area_code` VALUES (500229000000, '城口县', 3, 500200000000); +INSERT INTO `zz_area_code` VALUES (500230000000, '丰都县', 3, 500200000000); +INSERT INTO `zz_area_code` VALUES (500231000000, '垫江县', 3, 500200000000); +INSERT INTO `zz_area_code` VALUES (500233000000, '忠县', 3, 500200000000); +INSERT INTO `zz_area_code` VALUES (500235000000, '云阳县', 3, 500200000000); +INSERT INTO `zz_area_code` VALUES (500236000000, '奉节县', 3, 500200000000); +INSERT INTO `zz_area_code` VALUES (500237000000, '巫山县', 3, 500200000000); +INSERT INTO `zz_area_code` VALUES (500238000000, '巫溪县', 3, 500200000000); +INSERT INTO `zz_area_code` VALUES (500240000000, '石柱土家族自治县', 3, 500200000000); +INSERT INTO `zz_area_code` VALUES (500241000000, '秀山土家族苗族自治县', 3, 500200000000); +INSERT INTO `zz_area_code` VALUES (500242000000, '酉阳土家族苗族自治县', 3, 500200000000); +INSERT INTO `zz_area_code` VALUES (500243000000, '彭水苗族土家族自治县', 3, 500200000000); +INSERT INTO `zz_area_code` VALUES (510000000000, '四川省', 1, NULL); +INSERT INTO `zz_area_code` VALUES (510100000000, '成都市', 2, 510000000000); +INSERT INTO `zz_area_code` VALUES (510101000000, '市辖区', 3, 510100000000); +INSERT INTO `zz_area_code` VALUES (510104000000, '锦江区', 3, 510100000000); +INSERT INTO `zz_area_code` VALUES (510105000000, '青羊区', 3, 510100000000); +INSERT INTO `zz_area_code` VALUES (510106000000, '金牛区', 3, 510100000000); +INSERT INTO `zz_area_code` VALUES (510107000000, '武侯区', 3, 510100000000); +INSERT INTO `zz_area_code` VALUES (510108000000, '成华区', 3, 510100000000); +INSERT INTO `zz_area_code` VALUES (510112000000, '龙泉驿区', 3, 510100000000); +INSERT INTO `zz_area_code` VALUES (510113000000, '青白江区', 3, 510100000000); +INSERT INTO `zz_area_code` VALUES (510114000000, '新都区', 3, 510100000000); +INSERT INTO `zz_area_code` VALUES (510115000000, '温江区', 3, 510100000000); +INSERT INTO `zz_area_code` VALUES (510116000000, '双流区', 3, 510100000000); +INSERT INTO `zz_area_code` VALUES (510117000000, '郫都区', 3, 510100000000); +INSERT INTO `zz_area_code` VALUES (510121000000, '金堂县', 3, 510100000000); +INSERT INTO `zz_area_code` VALUES (510129000000, '大邑县', 3, 510100000000); +INSERT INTO `zz_area_code` VALUES (510131000000, '蒲江县', 3, 510100000000); +INSERT INTO `zz_area_code` VALUES (510132000000, '新津县', 3, 510100000000); +INSERT INTO `zz_area_code` VALUES (510181000000, '都江堰市', 3, 510100000000); +INSERT INTO `zz_area_code` VALUES (510182000000, '彭州市', 3, 510100000000); +INSERT INTO `zz_area_code` VALUES (510183000000, '邛崃市', 3, 510100000000); +INSERT INTO `zz_area_code` VALUES (510184000000, '崇州市', 3, 510100000000); +INSERT INTO `zz_area_code` VALUES (510185000000, '简阳市', 3, 510100000000); +INSERT INTO `zz_area_code` VALUES (510300000000, '自贡市', 2, 510000000000); +INSERT INTO `zz_area_code` VALUES (510301000000, '市辖区', 3, 510300000000); +INSERT INTO `zz_area_code` VALUES (510302000000, '自流井区', 3, 510300000000); +INSERT INTO `zz_area_code` VALUES (510303000000, '贡井区', 3, 510300000000); +INSERT INTO `zz_area_code` VALUES (510304000000, '大安区', 3, 510300000000); +INSERT INTO `zz_area_code` VALUES (510311000000, '沿滩区', 3, 510300000000); +INSERT INTO `zz_area_code` VALUES (510321000000, '荣县', 3, 510300000000); +INSERT INTO `zz_area_code` VALUES (510322000000, '富顺县', 3, 510300000000); +INSERT INTO `zz_area_code` VALUES (510400000000, '攀枝花市', 2, 510000000000); +INSERT INTO `zz_area_code` VALUES (510401000000, '市辖区', 3, 510400000000); +INSERT INTO `zz_area_code` VALUES (510402000000, '东区', 3, 510400000000); +INSERT INTO `zz_area_code` VALUES (510403000000, '西区', 3, 510400000000); +INSERT INTO `zz_area_code` VALUES (510411000000, '仁和区', 3, 510400000000); +INSERT INTO `zz_area_code` VALUES (510421000000, '米易县', 3, 510400000000); +INSERT INTO `zz_area_code` VALUES (510422000000, '盐边县', 3, 510400000000); +INSERT INTO `zz_area_code` VALUES (510500000000, '泸州市', 2, 510000000000); +INSERT INTO `zz_area_code` VALUES (510501000000, '市辖区', 3, 510500000000); +INSERT INTO `zz_area_code` VALUES (510502000000, '江阳区', 3, 510500000000); +INSERT INTO `zz_area_code` VALUES (510503000000, '纳溪区', 3, 510500000000); +INSERT INTO `zz_area_code` VALUES (510504000000, '龙马潭区', 3, 510500000000); +INSERT INTO `zz_area_code` VALUES (510521000000, '泸县', 3, 510500000000); +INSERT INTO `zz_area_code` VALUES (510522000000, '合江县', 3, 510500000000); +INSERT INTO `zz_area_code` VALUES (510524000000, '叙永县', 3, 510500000000); +INSERT INTO `zz_area_code` VALUES (510525000000, '古蔺县', 3, 510500000000); +INSERT INTO `zz_area_code` VALUES (510600000000, '德阳市', 2, 510000000000); +INSERT INTO `zz_area_code` VALUES (510601000000, '市辖区', 3, 510600000000); +INSERT INTO `zz_area_code` VALUES (510603000000, '旌阳区', 3, 510600000000); +INSERT INTO `zz_area_code` VALUES (510604000000, '罗江区', 3, 510600000000); +INSERT INTO `zz_area_code` VALUES (510623000000, '中江县', 3, 510600000000); +INSERT INTO `zz_area_code` VALUES (510681000000, '广汉市', 3, 510600000000); +INSERT INTO `zz_area_code` VALUES (510682000000, '什邡市', 3, 510600000000); +INSERT INTO `zz_area_code` VALUES (510683000000, '绵竹市', 3, 510600000000); +INSERT INTO `zz_area_code` VALUES (510700000000, '绵阳市', 2, 510000000000); +INSERT INTO `zz_area_code` VALUES (510701000000, '市辖区', 3, 510700000000); +INSERT INTO `zz_area_code` VALUES (510703000000, '涪城区', 3, 510700000000); +INSERT INTO `zz_area_code` VALUES (510704000000, '游仙区', 3, 510700000000); +INSERT INTO `zz_area_code` VALUES (510705000000, '安州区', 3, 510700000000); +INSERT INTO `zz_area_code` VALUES (510722000000, '三台县', 3, 510700000000); +INSERT INTO `zz_area_code` VALUES (510723000000, '盐亭县', 3, 510700000000); +INSERT INTO `zz_area_code` VALUES (510725000000, '梓潼县', 3, 510700000000); +INSERT INTO `zz_area_code` VALUES (510726000000, '北川羌族自治县', 3, 510700000000); +INSERT INTO `zz_area_code` VALUES (510727000000, '平武县', 3, 510700000000); +INSERT INTO `zz_area_code` VALUES (510781000000, '江油市', 3, 510700000000); +INSERT INTO `zz_area_code` VALUES (510800000000, '广元市', 2, 510000000000); +INSERT INTO `zz_area_code` VALUES (510801000000, '市辖区', 3, 510800000000); +INSERT INTO `zz_area_code` VALUES (510802000000, '利州区', 3, 510800000000); +INSERT INTO `zz_area_code` VALUES (510811000000, '昭化区', 3, 510800000000); +INSERT INTO `zz_area_code` VALUES (510812000000, '朝天区', 3, 510800000000); +INSERT INTO `zz_area_code` VALUES (510821000000, '旺苍县', 3, 510800000000); +INSERT INTO `zz_area_code` VALUES (510822000000, '青川县', 3, 510800000000); +INSERT INTO `zz_area_code` VALUES (510823000000, '剑阁县', 3, 510800000000); +INSERT INTO `zz_area_code` VALUES (510824000000, '苍溪县', 3, 510800000000); +INSERT INTO `zz_area_code` VALUES (510900000000, '遂宁市', 2, 510000000000); +INSERT INTO `zz_area_code` VALUES (510901000000, '市辖区', 3, 510900000000); +INSERT INTO `zz_area_code` VALUES (510903000000, '船山区', 3, 510900000000); +INSERT INTO `zz_area_code` VALUES (510904000000, '安居区', 3, 510900000000); +INSERT INTO `zz_area_code` VALUES (510921000000, '蓬溪县', 3, 510900000000); +INSERT INTO `zz_area_code` VALUES (510922000000, '射洪县', 3, 510900000000); +INSERT INTO `zz_area_code` VALUES (510923000000, '大英县', 3, 510900000000); +INSERT INTO `zz_area_code` VALUES (511000000000, '内江市', 2, 510000000000); +INSERT INTO `zz_area_code` VALUES (511001000000, '市辖区', 3, 511000000000); +INSERT INTO `zz_area_code` VALUES (511002000000, '市中区', 3, 511000000000); +INSERT INTO `zz_area_code` VALUES (511011000000, '东兴区', 3, 511000000000); +INSERT INTO `zz_area_code` VALUES (511024000000, '威远县', 3, 511000000000); +INSERT INTO `zz_area_code` VALUES (511025000000, '资中县', 3, 511000000000); +INSERT INTO `zz_area_code` VALUES (511071000000, '内江经济开发区', 3, 511000000000); +INSERT INTO `zz_area_code` VALUES (511083000000, '隆昌市', 3, 511000000000); +INSERT INTO `zz_area_code` VALUES (511100000000, '乐山市', 2, 510000000000); +INSERT INTO `zz_area_code` VALUES (511101000000, '市辖区', 3, 511100000000); +INSERT INTO `zz_area_code` VALUES (511102000000, '市中区', 3, 511100000000); +INSERT INTO `zz_area_code` VALUES (511111000000, '沙湾区', 3, 511100000000); +INSERT INTO `zz_area_code` VALUES (511112000000, '五通桥区', 3, 511100000000); +INSERT INTO `zz_area_code` VALUES (511113000000, '金口河区', 3, 511100000000); +INSERT INTO `zz_area_code` VALUES (511123000000, '犍为县', 3, 511100000000); +INSERT INTO `zz_area_code` VALUES (511124000000, '井研县', 3, 511100000000); +INSERT INTO `zz_area_code` VALUES (511126000000, '夹江县', 3, 511100000000); +INSERT INTO `zz_area_code` VALUES (511129000000, '沐川县', 3, 511100000000); +INSERT INTO `zz_area_code` VALUES (511132000000, '峨边彝族自治县', 3, 511100000000); +INSERT INTO `zz_area_code` VALUES (511133000000, '马边彝族自治县', 3, 511100000000); +INSERT INTO `zz_area_code` VALUES (511181000000, '峨眉山市', 3, 511100000000); +INSERT INTO `zz_area_code` VALUES (511300000000, '南充市', 2, 510000000000); +INSERT INTO `zz_area_code` VALUES (511301000000, '市辖区', 3, 511300000000); +INSERT INTO `zz_area_code` VALUES (511302000000, '顺庆区', 3, 511300000000); +INSERT INTO `zz_area_code` VALUES (511303000000, '高坪区', 3, 511300000000); +INSERT INTO `zz_area_code` VALUES (511304000000, '嘉陵区', 3, 511300000000); +INSERT INTO `zz_area_code` VALUES (511321000000, '南部县', 3, 511300000000); +INSERT INTO `zz_area_code` VALUES (511322000000, '营山县', 3, 511300000000); +INSERT INTO `zz_area_code` VALUES (511323000000, '蓬安县', 3, 511300000000); +INSERT INTO `zz_area_code` VALUES (511324000000, '仪陇县', 3, 511300000000); +INSERT INTO `zz_area_code` VALUES (511325000000, '西充县', 3, 511300000000); +INSERT INTO `zz_area_code` VALUES (511381000000, '阆中市', 3, 511300000000); +INSERT INTO `zz_area_code` VALUES (511400000000, '眉山市', 2, 510000000000); +INSERT INTO `zz_area_code` VALUES (511401000000, '市辖区', 3, 511400000000); +INSERT INTO `zz_area_code` VALUES (511402000000, '东坡区', 3, 511400000000); +INSERT INTO `zz_area_code` VALUES (511403000000, '彭山区', 3, 511400000000); +INSERT INTO `zz_area_code` VALUES (511421000000, '仁寿县', 3, 511400000000); +INSERT INTO `zz_area_code` VALUES (511423000000, '洪雅县', 3, 511400000000); +INSERT INTO `zz_area_code` VALUES (511424000000, '丹棱县', 3, 511400000000); +INSERT INTO `zz_area_code` VALUES (511425000000, '青神县', 3, 511400000000); +INSERT INTO `zz_area_code` VALUES (511500000000, '宜宾市', 2, 510000000000); +INSERT INTO `zz_area_code` VALUES (511501000000, '市辖区', 3, 511500000000); +INSERT INTO `zz_area_code` VALUES (511502000000, '翠屏区', 3, 511500000000); +INSERT INTO `zz_area_code` VALUES (511503000000, '南溪区', 3, 511500000000); +INSERT INTO `zz_area_code` VALUES (511504000000, '叙州区', 3, 511500000000); +INSERT INTO `zz_area_code` VALUES (511523000000, '江安县', 3, 511500000000); +INSERT INTO `zz_area_code` VALUES (511524000000, '长宁县', 3, 511500000000); +INSERT INTO `zz_area_code` VALUES (511525000000, '高县', 3, 511500000000); +INSERT INTO `zz_area_code` VALUES (511526000000, '珙县', 3, 511500000000); +INSERT INTO `zz_area_code` VALUES (511527000000, '筠连县', 3, 511500000000); +INSERT INTO `zz_area_code` VALUES (511528000000, '兴文县', 3, 511500000000); +INSERT INTO `zz_area_code` VALUES (511529000000, '屏山县', 3, 511500000000); +INSERT INTO `zz_area_code` VALUES (511600000000, '广安市', 2, 510000000000); +INSERT INTO `zz_area_code` VALUES (511601000000, '市辖区', 3, 511600000000); +INSERT INTO `zz_area_code` VALUES (511602000000, '广安区', 3, 511600000000); +INSERT INTO `zz_area_code` VALUES (511603000000, '前锋区', 3, 511600000000); +INSERT INTO `zz_area_code` VALUES (511621000000, '岳池县', 3, 511600000000); +INSERT INTO `zz_area_code` VALUES (511622000000, '武胜县', 3, 511600000000); +INSERT INTO `zz_area_code` VALUES (511623000000, '邻水县', 3, 511600000000); +INSERT INTO `zz_area_code` VALUES (511681000000, '华蓥市', 3, 511600000000); +INSERT INTO `zz_area_code` VALUES (511700000000, '达州市', 2, 510000000000); +INSERT INTO `zz_area_code` VALUES (511701000000, '市辖区', 3, 511700000000); +INSERT INTO `zz_area_code` VALUES (511702000000, '通川区', 3, 511700000000); +INSERT INTO `zz_area_code` VALUES (511703000000, '达川区', 3, 511700000000); +INSERT INTO `zz_area_code` VALUES (511722000000, '宣汉县', 3, 511700000000); +INSERT INTO `zz_area_code` VALUES (511723000000, '开江县', 3, 511700000000); +INSERT INTO `zz_area_code` VALUES (511724000000, '大竹县', 3, 511700000000); +INSERT INTO `zz_area_code` VALUES (511725000000, '渠县', 3, 511700000000); +INSERT INTO `zz_area_code` VALUES (511771000000, '达州经济开发区', 3, 511700000000); +INSERT INTO `zz_area_code` VALUES (511781000000, '万源市', 3, 511700000000); +INSERT INTO `zz_area_code` VALUES (511800000000, '雅安市', 2, 510000000000); +INSERT INTO `zz_area_code` VALUES (511801000000, '市辖区', 3, 511800000000); +INSERT INTO `zz_area_code` VALUES (511802000000, '雨城区', 3, 511800000000); +INSERT INTO `zz_area_code` VALUES (511803000000, '名山区', 3, 511800000000); +INSERT INTO `zz_area_code` VALUES (511822000000, '荥经县', 3, 511800000000); +INSERT INTO `zz_area_code` VALUES (511823000000, '汉源县', 3, 511800000000); +INSERT INTO `zz_area_code` VALUES (511824000000, '石棉县', 3, 511800000000); +INSERT INTO `zz_area_code` VALUES (511825000000, '天全县', 3, 511800000000); +INSERT INTO `zz_area_code` VALUES (511826000000, '芦山县', 3, 511800000000); +INSERT INTO `zz_area_code` VALUES (511827000000, '宝兴县', 3, 511800000000); +INSERT INTO `zz_area_code` VALUES (511900000000, '巴中市', 2, 510000000000); +INSERT INTO `zz_area_code` VALUES (511901000000, '市辖区', 3, 511900000000); +INSERT INTO `zz_area_code` VALUES (511902000000, '巴州区', 3, 511900000000); +INSERT INTO `zz_area_code` VALUES (511903000000, '恩阳区', 3, 511900000000); +INSERT INTO `zz_area_code` VALUES (511921000000, '通江县', 3, 511900000000); +INSERT INTO `zz_area_code` VALUES (511922000000, '南江县', 3, 511900000000); +INSERT INTO `zz_area_code` VALUES (511923000000, '平昌县', 3, 511900000000); +INSERT INTO `zz_area_code` VALUES (511971000000, '巴中经济开发区', 3, 511900000000); +INSERT INTO `zz_area_code` VALUES (512000000000, '资阳市', 2, 510000000000); +INSERT INTO `zz_area_code` VALUES (512001000000, '市辖区', 3, 512000000000); +INSERT INTO `zz_area_code` VALUES (512002000000, '雁江区', 3, 512000000000); +INSERT INTO `zz_area_code` VALUES (512021000000, '安岳县', 3, 512000000000); +INSERT INTO `zz_area_code` VALUES (512022000000, '乐至县', 3, 512000000000); +INSERT INTO `zz_area_code` VALUES (513200000000, '阿坝藏族羌族自治州', 2, 510000000000); +INSERT INTO `zz_area_code` VALUES (513201000000, '马尔康市', 3, 513200000000); +INSERT INTO `zz_area_code` VALUES (513221000000, '汶川县', 3, 513200000000); +INSERT INTO `zz_area_code` VALUES (513222000000, '理县', 3, 513200000000); +INSERT INTO `zz_area_code` VALUES (513223000000, '茂县', 3, 513200000000); +INSERT INTO `zz_area_code` VALUES (513224000000, '松潘县', 3, 513200000000); +INSERT INTO `zz_area_code` VALUES (513225000000, '九寨沟县', 3, 513200000000); +INSERT INTO `zz_area_code` VALUES (513226000000, '金川县', 3, 513200000000); +INSERT INTO `zz_area_code` VALUES (513227000000, '小金县', 3, 513200000000); +INSERT INTO `zz_area_code` VALUES (513228000000, '黑水县', 3, 513200000000); +INSERT INTO `zz_area_code` VALUES (513230000000, '壤塘县', 3, 513200000000); +INSERT INTO `zz_area_code` VALUES (513231000000, '阿坝县', 3, 513200000000); +INSERT INTO `zz_area_code` VALUES (513232000000, '若尔盖县', 3, 513200000000); +INSERT INTO `zz_area_code` VALUES (513233000000, '红原县', 3, 513200000000); +INSERT INTO `zz_area_code` VALUES (513300000000, '甘孜藏族自治州', 2, 510000000000); +INSERT INTO `zz_area_code` VALUES (513301000000, '康定市', 3, 513300000000); +INSERT INTO `zz_area_code` VALUES (513322000000, '泸定县', 3, 513300000000); +INSERT INTO `zz_area_code` VALUES (513323000000, '丹巴县', 3, 513300000000); +INSERT INTO `zz_area_code` VALUES (513324000000, '九龙县', 3, 513300000000); +INSERT INTO `zz_area_code` VALUES (513325000000, '雅江县', 3, 513300000000); +INSERT INTO `zz_area_code` VALUES (513326000000, '道孚县', 3, 513300000000); +INSERT INTO `zz_area_code` VALUES (513327000000, '炉霍县', 3, 513300000000); +INSERT INTO `zz_area_code` VALUES (513328000000, '甘孜县', 3, 513300000000); +INSERT INTO `zz_area_code` VALUES (513329000000, '新龙县', 3, 513300000000); +INSERT INTO `zz_area_code` VALUES (513330000000, '德格县', 3, 513300000000); +INSERT INTO `zz_area_code` VALUES (513331000000, '白玉县', 3, 513300000000); +INSERT INTO `zz_area_code` VALUES (513332000000, '石渠县', 3, 513300000000); +INSERT INTO `zz_area_code` VALUES (513333000000, '色达县', 3, 513300000000); +INSERT INTO `zz_area_code` VALUES (513334000000, '理塘县', 3, 513300000000); +INSERT INTO `zz_area_code` VALUES (513335000000, '巴塘县', 3, 513300000000); +INSERT INTO `zz_area_code` VALUES (513336000000, '乡城县', 3, 513300000000); +INSERT INTO `zz_area_code` VALUES (513337000000, '稻城县', 3, 513300000000); +INSERT INTO `zz_area_code` VALUES (513338000000, '得荣县', 3, 513300000000); +INSERT INTO `zz_area_code` VALUES (513400000000, '凉山彝族自治州', 2, 510000000000); +INSERT INTO `zz_area_code` VALUES (513401000000, '西昌市', 3, 513400000000); +INSERT INTO `zz_area_code` VALUES (513422000000, '木里藏族自治县', 3, 513400000000); +INSERT INTO `zz_area_code` VALUES (513423000000, '盐源县', 3, 513400000000); +INSERT INTO `zz_area_code` VALUES (513424000000, '德昌县', 3, 513400000000); +INSERT INTO `zz_area_code` VALUES (513425000000, '会理县', 3, 513400000000); +INSERT INTO `zz_area_code` VALUES (513426000000, '会东县', 3, 513400000000); +INSERT INTO `zz_area_code` VALUES (513427000000, '宁南县', 3, 513400000000); +INSERT INTO `zz_area_code` VALUES (513428000000, '普格县', 3, 513400000000); +INSERT INTO `zz_area_code` VALUES (513429000000, '布拖县', 3, 513400000000); +INSERT INTO `zz_area_code` VALUES (513430000000, '金阳县', 3, 513400000000); +INSERT INTO `zz_area_code` VALUES (513431000000, '昭觉县', 3, 513400000000); +INSERT INTO `zz_area_code` VALUES (513432000000, '喜德县', 3, 513400000000); +INSERT INTO `zz_area_code` VALUES (513433000000, '冕宁县', 3, 513400000000); +INSERT INTO `zz_area_code` VALUES (513434000000, '越西县', 3, 513400000000); +INSERT INTO `zz_area_code` VALUES (513435000000, '甘洛县', 3, 513400000000); +INSERT INTO `zz_area_code` VALUES (513436000000, '美姑县', 3, 513400000000); +INSERT INTO `zz_area_code` VALUES (513437000000, '雷波县', 3, 513400000000); +INSERT INTO `zz_area_code` VALUES (520000000000, '贵州省', 1, NULL); +INSERT INTO `zz_area_code` VALUES (520100000000, '贵阳市', 2, 520000000000); +INSERT INTO `zz_area_code` VALUES (520101000000, '市辖区', 3, 520100000000); +INSERT INTO `zz_area_code` VALUES (520102000000, '南明区', 3, 520100000000); +INSERT INTO `zz_area_code` VALUES (520103000000, '云岩区', 3, 520100000000); +INSERT INTO `zz_area_code` VALUES (520111000000, '花溪区', 3, 520100000000); +INSERT INTO `zz_area_code` VALUES (520112000000, '乌当区', 3, 520100000000); +INSERT INTO `zz_area_code` VALUES (520113000000, '白云区', 3, 520100000000); +INSERT INTO `zz_area_code` VALUES (520115000000, '观山湖区', 3, 520100000000); +INSERT INTO `zz_area_code` VALUES (520121000000, '开阳县', 3, 520100000000); +INSERT INTO `zz_area_code` VALUES (520122000000, '息烽县', 3, 520100000000); +INSERT INTO `zz_area_code` VALUES (520123000000, '修文县', 3, 520100000000); +INSERT INTO `zz_area_code` VALUES (520181000000, '清镇市', 3, 520100000000); +INSERT INTO `zz_area_code` VALUES (520200000000, '六盘水市', 2, 520000000000); +INSERT INTO `zz_area_code` VALUES (520201000000, '钟山区', 3, 520200000000); +INSERT INTO `zz_area_code` VALUES (520203000000, '六枝特区', 3, 520200000000); +INSERT INTO `zz_area_code` VALUES (520221000000, '水城县', 3, 520200000000); +INSERT INTO `zz_area_code` VALUES (520281000000, '盘州市', 3, 520200000000); +INSERT INTO `zz_area_code` VALUES (520300000000, '遵义市', 2, 520000000000); +INSERT INTO `zz_area_code` VALUES (520301000000, '市辖区', 3, 520300000000); +INSERT INTO `zz_area_code` VALUES (520302000000, '红花岗区', 3, 520300000000); +INSERT INTO `zz_area_code` VALUES (520303000000, '汇川区', 3, 520300000000); +INSERT INTO `zz_area_code` VALUES (520304000000, '播州区', 3, 520300000000); +INSERT INTO `zz_area_code` VALUES (520322000000, '桐梓县', 3, 520300000000); +INSERT INTO `zz_area_code` VALUES (520323000000, '绥阳县', 3, 520300000000); +INSERT INTO `zz_area_code` VALUES (520324000000, '正安县', 3, 520300000000); +INSERT INTO `zz_area_code` VALUES (520325000000, '道真仡佬族苗族自治县', 3, 520300000000); +INSERT INTO `zz_area_code` VALUES (520326000000, '务川仡佬族苗族自治县', 3, 520300000000); +INSERT INTO `zz_area_code` VALUES (520327000000, '凤冈县', 3, 520300000000); +INSERT INTO `zz_area_code` VALUES (520328000000, '湄潭县', 3, 520300000000); +INSERT INTO `zz_area_code` VALUES (520329000000, '余庆县', 3, 520300000000); +INSERT INTO `zz_area_code` VALUES (520330000000, '习水县', 3, 520300000000); +INSERT INTO `zz_area_code` VALUES (520381000000, '赤水市', 3, 520300000000); +INSERT INTO `zz_area_code` VALUES (520382000000, '仁怀市', 3, 520300000000); +INSERT INTO `zz_area_code` VALUES (520400000000, '安顺市', 2, 520000000000); +INSERT INTO `zz_area_code` VALUES (520401000000, '市辖区', 3, 520400000000); +INSERT INTO `zz_area_code` VALUES (520402000000, '西秀区', 3, 520400000000); +INSERT INTO `zz_area_code` VALUES (520403000000, '平坝区', 3, 520400000000); +INSERT INTO `zz_area_code` VALUES (520422000000, '普定县', 3, 520400000000); +INSERT INTO `zz_area_code` VALUES (520423000000, '镇宁布依族苗族自治县', 3, 520400000000); +INSERT INTO `zz_area_code` VALUES (520424000000, '关岭布依族苗族自治县', 3, 520400000000); +INSERT INTO `zz_area_code` VALUES (520425000000, '紫云苗族布依族自治县', 3, 520400000000); +INSERT INTO `zz_area_code` VALUES (520500000000, '毕节市', 2, 520000000000); +INSERT INTO `zz_area_code` VALUES (520501000000, '市辖区', 3, 520500000000); +INSERT INTO `zz_area_code` VALUES (520502000000, '七星关区', 3, 520500000000); +INSERT INTO `zz_area_code` VALUES (520521000000, '大方县', 3, 520500000000); +INSERT INTO `zz_area_code` VALUES (520522000000, '黔西县', 3, 520500000000); +INSERT INTO `zz_area_code` VALUES (520523000000, '金沙县', 3, 520500000000); +INSERT INTO `zz_area_code` VALUES (520524000000, '织金县', 3, 520500000000); +INSERT INTO `zz_area_code` VALUES (520525000000, '纳雍县', 3, 520500000000); +INSERT INTO `zz_area_code` VALUES (520526000000, '威宁彝族回族苗族自治县', 3, 520500000000); +INSERT INTO `zz_area_code` VALUES (520527000000, '赫章县', 3, 520500000000); +INSERT INTO `zz_area_code` VALUES (520600000000, '铜仁市', 2, 520000000000); +INSERT INTO `zz_area_code` VALUES (520601000000, '市辖区', 3, 520600000000); +INSERT INTO `zz_area_code` VALUES (520602000000, '碧江区', 3, 520600000000); +INSERT INTO `zz_area_code` VALUES (520603000000, '万山区', 3, 520600000000); +INSERT INTO `zz_area_code` VALUES (520621000000, '江口县', 3, 520600000000); +INSERT INTO `zz_area_code` VALUES (520622000000, '玉屏侗族自治县', 3, 520600000000); +INSERT INTO `zz_area_code` VALUES (520623000000, '石阡县', 3, 520600000000); +INSERT INTO `zz_area_code` VALUES (520624000000, '思南县', 3, 520600000000); +INSERT INTO `zz_area_code` VALUES (520625000000, '印江土家族苗族自治县', 3, 520600000000); +INSERT INTO `zz_area_code` VALUES (520626000000, '德江县', 3, 520600000000); +INSERT INTO `zz_area_code` VALUES (520627000000, '沿河土家族自治县', 3, 520600000000); +INSERT INTO `zz_area_code` VALUES (520628000000, '松桃苗族自治县', 3, 520600000000); +INSERT INTO `zz_area_code` VALUES (522300000000, '黔西南布依族苗族自治州', 2, 520000000000); +INSERT INTO `zz_area_code` VALUES (522301000000, '兴义市', 3, 522300000000); +INSERT INTO `zz_area_code` VALUES (522302000000, '兴仁市', 3, 522300000000); +INSERT INTO `zz_area_code` VALUES (522323000000, '普安县', 3, 522300000000); +INSERT INTO `zz_area_code` VALUES (522324000000, '晴隆县', 3, 522300000000); +INSERT INTO `zz_area_code` VALUES (522325000000, '贞丰县', 3, 522300000000); +INSERT INTO `zz_area_code` VALUES (522326000000, '望谟县', 3, 522300000000); +INSERT INTO `zz_area_code` VALUES (522327000000, '册亨县', 3, 522300000000); +INSERT INTO `zz_area_code` VALUES (522328000000, '安龙县', 3, 522300000000); +INSERT INTO `zz_area_code` VALUES (522600000000, '黔东南苗族侗族自治州', 2, 520000000000); +INSERT INTO `zz_area_code` VALUES (522601000000, '凯里市', 3, 522600000000); +INSERT INTO `zz_area_code` VALUES (522622000000, '黄平县', 3, 522600000000); +INSERT INTO `zz_area_code` VALUES (522623000000, '施秉县', 3, 522600000000); +INSERT INTO `zz_area_code` VALUES (522624000000, '三穗县', 3, 522600000000); +INSERT INTO `zz_area_code` VALUES (522625000000, '镇远县', 3, 522600000000); +INSERT INTO `zz_area_code` VALUES (522626000000, '岑巩县', 3, 522600000000); +INSERT INTO `zz_area_code` VALUES (522627000000, '天柱县', 3, 522600000000); +INSERT INTO `zz_area_code` VALUES (522628000000, '锦屏县', 3, 522600000000); +INSERT INTO `zz_area_code` VALUES (522629000000, '剑河县', 3, 522600000000); +INSERT INTO `zz_area_code` VALUES (522630000000, '台江县', 3, 522600000000); +INSERT INTO `zz_area_code` VALUES (522631000000, '黎平县', 3, 522600000000); +INSERT INTO `zz_area_code` VALUES (522632000000, '榕江县', 3, 522600000000); +INSERT INTO `zz_area_code` VALUES (522633000000, '从江县', 3, 522600000000); +INSERT INTO `zz_area_code` VALUES (522634000000, '雷山县', 3, 522600000000); +INSERT INTO `zz_area_code` VALUES (522635000000, '麻江县', 3, 522600000000); +INSERT INTO `zz_area_code` VALUES (522636000000, '丹寨县', 3, 522600000000); +INSERT INTO `zz_area_code` VALUES (522700000000, '黔南布依族苗族自治州', 2, 520000000000); +INSERT INTO `zz_area_code` VALUES (522701000000, '都匀市', 3, 522700000000); +INSERT INTO `zz_area_code` VALUES (522702000000, '福泉市', 3, 522700000000); +INSERT INTO `zz_area_code` VALUES (522722000000, '荔波县', 3, 522700000000); +INSERT INTO `zz_area_code` VALUES (522723000000, '贵定县', 3, 522700000000); +INSERT INTO `zz_area_code` VALUES (522725000000, '瓮安县', 3, 522700000000); +INSERT INTO `zz_area_code` VALUES (522726000000, '独山县', 3, 522700000000); +INSERT INTO `zz_area_code` VALUES (522727000000, '平塘县', 3, 522700000000); +INSERT INTO `zz_area_code` VALUES (522728000000, '罗甸县', 3, 522700000000); +INSERT INTO `zz_area_code` VALUES (522729000000, '长顺县', 3, 522700000000); +INSERT INTO `zz_area_code` VALUES (522730000000, '龙里县', 3, 522700000000); +INSERT INTO `zz_area_code` VALUES (522731000000, '惠水县', 3, 522700000000); +INSERT INTO `zz_area_code` VALUES (522732000000, '三都水族自治县', 3, 522700000000); +INSERT INTO `zz_area_code` VALUES (530000000000, '云南省', 1, NULL); +INSERT INTO `zz_area_code` VALUES (530100000000, '昆明市', 2, 530000000000); +INSERT INTO `zz_area_code` VALUES (530101000000, '市辖区', 3, 530100000000); +INSERT INTO `zz_area_code` VALUES (530102000000, '五华区', 3, 530100000000); +INSERT INTO `zz_area_code` VALUES (530103000000, '盘龙区', 3, 530100000000); +INSERT INTO `zz_area_code` VALUES (530111000000, '官渡区', 3, 530100000000); +INSERT INTO `zz_area_code` VALUES (530112000000, '西山区', 3, 530100000000); +INSERT INTO `zz_area_code` VALUES (530113000000, '东川区', 3, 530100000000); +INSERT INTO `zz_area_code` VALUES (530114000000, '呈贡区', 3, 530100000000); +INSERT INTO `zz_area_code` VALUES (530115000000, '晋宁区', 3, 530100000000); +INSERT INTO `zz_area_code` VALUES (530124000000, '富民县', 3, 530100000000); +INSERT INTO `zz_area_code` VALUES (530125000000, '宜良县', 3, 530100000000); +INSERT INTO `zz_area_code` VALUES (530126000000, '石林彝族自治县', 3, 530100000000); +INSERT INTO `zz_area_code` VALUES (530127000000, '嵩明县', 3, 530100000000); +INSERT INTO `zz_area_code` VALUES (530128000000, '禄劝彝族苗族自治县', 3, 530100000000); +INSERT INTO `zz_area_code` VALUES (530129000000, '寻甸回族彝族自治县', 3, 530100000000); +INSERT INTO `zz_area_code` VALUES (530181000000, '安宁市', 3, 530100000000); +INSERT INTO `zz_area_code` VALUES (530300000000, '曲靖市', 2, 530000000000); +INSERT INTO `zz_area_code` VALUES (530301000000, '市辖区', 3, 530300000000); +INSERT INTO `zz_area_code` VALUES (530302000000, '麒麟区', 3, 530300000000); +INSERT INTO `zz_area_code` VALUES (530303000000, '沾益区', 3, 530300000000); +INSERT INTO `zz_area_code` VALUES (530304000000, '马龙区', 3, 530300000000); +INSERT INTO `zz_area_code` VALUES (530322000000, '陆良县', 3, 530300000000); +INSERT INTO `zz_area_code` VALUES (530323000000, '师宗县', 3, 530300000000); +INSERT INTO `zz_area_code` VALUES (530324000000, '罗平县', 3, 530300000000); +INSERT INTO `zz_area_code` VALUES (530325000000, '富源县', 3, 530300000000); +INSERT INTO `zz_area_code` VALUES (530326000000, '会泽县', 3, 530300000000); +INSERT INTO `zz_area_code` VALUES (530381000000, '宣威市', 3, 530300000000); +INSERT INTO `zz_area_code` VALUES (530400000000, '玉溪市', 2, 530000000000); +INSERT INTO `zz_area_code` VALUES (530401000000, '市辖区', 3, 530400000000); +INSERT INTO `zz_area_code` VALUES (530402000000, '红塔区', 3, 530400000000); +INSERT INTO `zz_area_code` VALUES (530403000000, '江川区', 3, 530400000000); +INSERT INTO `zz_area_code` VALUES (530422000000, '澄江县', 3, 530400000000); +INSERT INTO `zz_area_code` VALUES (530423000000, '通海县', 3, 530400000000); +INSERT INTO `zz_area_code` VALUES (530424000000, '华宁县', 3, 530400000000); +INSERT INTO `zz_area_code` VALUES (530425000000, '易门县', 3, 530400000000); +INSERT INTO `zz_area_code` VALUES (530426000000, '峨山彝族自治县', 3, 530400000000); +INSERT INTO `zz_area_code` VALUES (530427000000, '新平彝族傣族自治县', 3, 530400000000); +INSERT INTO `zz_area_code` VALUES (530428000000, '元江哈尼族彝族傣族自治县', 3, 530400000000); +INSERT INTO `zz_area_code` VALUES (530500000000, '保山市', 2, 530000000000); +INSERT INTO `zz_area_code` VALUES (530501000000, '市辖区', 3, 530500000000); +INSERT INTO `zz_area_code` VALUES (530502000000, '隆阳区', 3, 530500000000); +INSERT INTO `zz_area_code` VALUES (530521000000, '施甸县', 3, 530500000000); +INSERT INTO `zz_area_code` VALUES (530523000000, '龙陵县', 3, 530500000000); +INSERT INTO `zz_area_code` VALUES (530524000000, '昌宁县', 3, 530500000000); +INSERT INTO `zz_area_code` VALUES (530581000000, '腾冲市', 3, 530500000000); +INSERT INTO `zz_area_code` VALUES (530600000000, '昭通市', 2, 530000000000); +INSERT INTO `zz_area_code` VALUES (530601000000, '市辖区', 3, 530600000000); +INSERT INTO `zz_area_code` VALUES (530602000000, '昭阳区', 3, 530600000000); +INSERT INTO `zz_area_code` VALUES (530621000000, '鲁甸县', 3, 530600000000); +INSERT INTO `zz_area_code` VALUES (530622000000, '巧家县', 3, 530600000000); +INSERT INTO `zz_area_code` VALUES (530623000000, '盐津县', 3, 530600000000); +INSERT INTO `zz_area_code` VALUES (530624000000, '大关县', 3, 530600000000); +INSERT INTO `zz_area_code` VALUES (530625000000, '永善县', 3, 530600000000); +INSERT INTO `zz_area_code` VALUES (530626000000, '绥江县', 3, 530600000000); +INSERT INTO `zz_area_code` VALUES (530627000000, '镇雄县', 3, 530600000000); +INSERT INTO `zz_area_code` VALUES (530628000000, '彝良县', 3, 530600000000); +INSERT INTO `zz_area_code` VALUES (530629000000, '威信县', 3, 530600000000); +INSERT INTO `zz_area_code` VALUES (530681000000, '水富市', 3, 530600000000); +INSERT INTO `zz_area_code` VALUES (530700000000, '丽江市', 2, 530000000000); +INSERT INTO `zz_area_code` VALUES (530701000000, '市辖区', 3, 530700000000); +INSERT INTO `zz_area_code` VALUES (530702000000, '古城区', 3, 530700000000); +INSERT INTO `zz_area_code` VALUES (530721000000, '玉龙纳西族自治县', 3, 530700000000); +INSERT INTO `zz_area_code` VALUES (530722000000, '永胜县', 3, 530700000000); +INSERT INTO `zz_area_code` VALUES (530723000000, '华坪县', 3, 530700000000); +INSERT INTO `zz_area_code` VALUES (530724000000, '宁蒗彝族自治县', 3, 530700000000); +INSERT INTO `zz_area_code` VALUES (530800000000, '普洱市', 2, 530000000000); +INSERT INTO `zz_area_code` VALUES (530801000000, '市辖区', 3, 530800000000); +INSERT INTO `zz_area_code` VALUES (530802000000, '思茅区', 3, 530800000000); +INSERT INTO `zz_area_code` VALUES (530821000000, '宁洱哈尼族彝族自治县', 3, 530800000000); +INSERT INTO `zz_area_code` VALUES (530822000000, '墨江哈尼族自治县', 3, 530800000000); +INSERT INTO `zz_area_code` VALUES (530823000000, '景东彝族自治县', 3, 530800000000); +INSERT INTO `zz_area_code` VALUES (530824000000, '景谷傣族彝族自治县', 3, 530800000000); +INSERT INTO `zz_area_code` VALUES (530825000000, '镇沅彝族哈尼族拉祜族自治县', 3, 530800000000); +INSERT INTO `zz_area_code` VALUES (530826000000, '江城哈尼族彝族自治县', 3, 530800000000); +INSERT INTO `zz_area_code` VALUES (530827000000, '孟连傣族拉祜族佤族自治县', 3, 530800000000); +INSERT INTO `zz_area_code` VALUES (530828000000, '澜沧拉祜族自治县', 3, 530800000000); +INSERT INTO `zz_area_code` VALUES (530829000000, '西盟佤族自治县', 3, 530800000000); +INSERT INTO `zz_area_code` VALUES (530900000000, '临沧市', 2, 530000000000); +INSERT INTO `zz_area_code` VALUES (530901000000, '市辖区', 3, 530900000000); +INSERT INTO `zz_area_code` VALUES (530902000000, '临翔区', 3, 530900000000); +INSERT INTO `zz_area_code` VALUES (530921000000, '凤庆县', 3, 530900000000); +INSERT INTO `zz_area_code` VALUES (530922000000, '云县', 3, 530900000000); +INSERT INTO `zz_area_code` VALUES (530923000000, '永德县', 3, 530900000000); +INSERT INTO `zz_area_code` VALUES (530924000000, '镇康县', 3, 530900000000); +INSERT INTO `zz_area_code` VALUES (530925000000, '双江拉祜族佤族布朗族傣族自治县', 3, 530900000000); +INSERT INTO `zz_area_code` VALUES (530926000000, '耿马傣族佤族自治县', 3, 530900000000); +INSERT INTO `zz_area_code` VALUES (530927000000, '沧源佤族自治县', 3, 530900000000); +INSERT INTO `zz_area_code` VALUES (532300000000, '楚雄彝族自治州', 2, 530000000000); +INSERT INTO `zz_area_code` VALUES (532301000000, '楚雄市', 3, 532300000000); +INSERT INTO `zz_area_code` VALUES (532322000000, '双柏县', 3, 532300000000); +INSERT INTO `zz_area_code` VALUES (532323000000, '牟定县', 3, 532300000000); +INSERT INTO `zz_area_code` VALUES (532324000000, '南华县', 3, 532300000000); +INSERT INTO `zz_area_code` VALUES (532325000000, '姚安县', 3, 532300000000); +INSERT INTO `zz_area_code` VALUES (532326000000, '大姚县', 3, 532300000000); +INSERT INTO `zz_area_code` VALUES (532327000000, '永仁县', 3, 532300000000); +INSERT INTO `zz_area_code` VALUES (532328000000, '元谋县', 3, 532300000000); +INSERT INTO `zz_area_code` VALUES (532329000000, '武定县', 3, 532300000000); +INSERT INTO `zz_area_code` VALUES (532331000000, '禄丰县', 3, 532300000000); +INSERT INTO `zz_area_code` VALUES (532500000000, '红河哈尼族彝族自治州', 2, 530000000000); +INSERT INTO `zz_area_code` VALUES (532501000000, '个旧市', 3, 532500000000); +INSERT INTO `zz_area_code` VALUES (532502000000, '开远市', 3, 532500000000); +INSERT INTO `zz_area_code` VALUES (532503000000, '蒙自市', 3, 532500000000); +INSERT INTO `zz_area_code` VALUES (532504000000, '弥勒市', 3, 532500000000); +INSERT INTO `zz_area_code` VALUES (532523000000, '屏边苗族自治县', 3, 532500000000); +INSERT INTO `zz_area_code` VALUES (532524000000, '建水县', 3, 532500000000); +INSERT INTO `zz_area_code` VALUES (532525000000, '石屏县', 3, 532500000000); +INSERT INTO `zz_area_code` VALUES (532527000000, '泸西县', 3, 532500000000); +INSERT INTO `zz_area_code` VALUES (532528000000, '元阳县', 3, 532500000000); +INSERT INTO `zz_area_code` VALUES (532529000000, '红河县', 3, 532500000000); +INSERT INTO `zz_area_code` VALUES (532530000000, '金平苗族瑶族傣族自治县', 3, 532500000000); +INSERT INTO `zz_area_code` VALUES (532531000000, '绿春县', 3, 532500000000); +INSERT INTO `zz_area_code` VALUES (532532000000, '河口瑶族自治县', 3, 532500000000); +INSERT INTO `zz_area_code` VALUES (532600000000, '文山壮族苗族自治州', 2, 530000000000); +INSERT INTO `zz_area_code` VALUES (532601000000, '文山市', 3, 532600000000); +INSERT INTO `zz_area_code` VALUES (532622000000, '砚山县', 3, 532600000000); +INSERT INTO `zz_area_code` VALUES (532623000000, '西畴县', 3, 532600000000); +INSERT INTO `zz_area_code` VALUES (532624000000, '麻栗坡县', 3, 532600000000); +INSERT INTO `zz_area_code` VALUES (532625000000, '马关县', 3, 532600000000); +INSERT INTO `zz_area_code` VALUES (532626000000, '丘北县', 3, 532600000000); +INSERT INTO `zz_area_code` VALUES (532627000000, '广南县', 3, 532600000000); +INSERT INTO `zz_area_code` VALUES (532628000000, '富宁县', 3, 532600000000); +INSERT INTO `zz_area_code` VALUES (532800000000, '西双版纳傣族自治州', 2, 530000000000); +INSERT INTO `zz_area_code` VALUES (532801000000, '景洪市', 3, 532800000000); +INSERT INTO `zz_area_code` VALUES (532822000000, '勐海县', 3, 532800000000); +INSERT INTO `zz_area_code` VALUES (532823000000, '勐腊县', 3, 532800000000); +INSERT INTO `zz_area_code` VALUES (532900000000, '大理白族自治州', 2, 530000000000); +INSERT INTO `zz_area_code` VALUES (532901000000, '大理市', 3, 532900000000); +INSERT INTO `zz_area_code` VALUES (532922000000, '漾濞彝族自治县', 3, 532900000000); +INSERT INTO `zz_area_code` VALUES (532923000000, '祥云县', 3, 532900000000); +INSERT INTO `zz_area_code` VALUES (532924000000, '宾川县', 3, 532900000000); +INSERT INTO `zz_area_code` VALUES (532925000000, '弥渡县', 3, 532900000000); +INSERT INTO `zz_area_code` VALUES (532926000000, '南涧彝族自治县', 3, 532900000000); +INSERT INTO `zz_area_code` VALUES (532927000000, '巍山彝族回族自治县', 3, 532900000000); +INSERT INTO `zz_area_code` VALUES (532928000000, '永平县', 3, 532900000000); +INSERT INTO `zz_area_code` VALUES (532929000000, '云龙县', 3, 532900000000); +INSERT INTO `zz_area_code` VALUES (532930000000, '洱源县', 3, 532900000000); +INSERT INTO `zz_area_code` VALUES (532931000000, '剑川县', 3, 532900000000); +INSERT INTO `zz_area_code` VALUES (532932000000, '鹤庆县', 3, 532900000000); +INSERT INTO `zz_area_code` VALUES (533100000000, '德宏傣族景颇族自治州', 2, 530000000000); +INSERT INTO `zz_area_code` VALUES (533102000000, '瑞丽市', 3, 533100000000); +INSERT INTO `zz_area_code` VALUES (533103000000, '芒市', 3, 533100000000); +INSERT INTO `zz_area_code` VALUES (533122000000, '梁河县', 3, 533100000000); +INSERT INTO `zz_area_code` VALUES (533123000000, '盈江县', 3, 533100000000); +INSERT INTO `zz_area_code` VALUES (533124000000, '陇川县', 3, 533100000000); +INSERT INTO `zz_area_code` VALUES (533300000000, '怒江傈僳族自治州', 2, 530000000000); +INSERT INTO `zz_area_code` VALUES (533301000000, '泸水市', 3, 533300000000); +INSERT INTO `zz_area_code` VALUES (533323000000, '福贡县', 3, 533300000000); +INSERT INTO `zz_area_code` VALUES (533324000000, '贡山独龙族怒族自治县', 3, 533300000000); +INSERT INTO `zz_area_code` VALUES (533325000000, '兰坪白族普米族自治县', 3, 533300000000); +INSERT INTO `zz_area_code` VALUES (533400000000, '迪庆藏族自治州', 2, 530000000000); +INSERT INTO `zz_area_code` VALUES (533401000000, '香格里拉市', 3, 533400000000); +INSERT INTO `zz_area_code` VALUES (533422000000, '德钦县', 3, 533400000000); +INSERT INTO `zz_area_code` VALUES (533423000000, '维西傈僳族自治县', 3, 533400000000); +INSERT INTO `zz_area_code` VALUES (540000000000, '西藏自治区', 1, NULL); +INSERT INTO `zz_area_code` VALUES (540100000000, '拉萨市', 2, 540000000000); +INSERT INTO `zz_area_code` VALUES (540101000000, '市辖区', 3, 540100000000); +INSERT INTO `zz_area_code` VALUES (540102000000, '城关区', 3, 540100000000); +INSERT INTO `zz_area_code` VALUES (540103000000, '堆龙德庆区', 3, 540100000000); +INSERT INTO `zz_area_code` VALUES (540104000000, '达孜区', 3, 540100000000); +INSERT INTO `zz_area_code` VALUES (540121000000, '林周县', 3, 540100000000); +INSERT INTO `zz_area_code` VALUES (540122000000, '当雄县', 3, 540100000000); +INSERT INTO `zz_area_code` VALUES (540123000000, '尼木县', 3, 540100000000); +INSERT INTO `zz_area_code` VALUES (540124000000, '曲水县', 3, 540100000000); +INSERT INTO `zz_area_code` VALUES (540127000000, '墨竹工卡县', 3, 540100000000); +INSERT INTO `zz_area_code` VALUES (540171000000, '格尔木藏青工业园区', 3, 540100000000); +INSERT INTO `zz_area_code` VALUES (540172000000, '拉萨经济技术开发区', 3, 540100000000); +INSERT INTO `zz_area_code` VALUES (540173000000, '西藏文化旅游创意园区', 3, 540100000000); +INSERT INTO `zz_area_code` VALUES (540174000000, '达孜工业园区', 3, 540100000000); +INSERT INTO `zz_area_code` VALUES (540200000000, '日喀则市', 2, 540000000000); +INSERT INTO `zz_area_code` VALUES (540202000000, '桑珠孜区', 3, 540200000000); +INSERT INTO `zz_area_code` VALUES (540221000000, '南木林县', 3, 540200000000); +INSERT INTO `zz_area_code` VALUES (540222000000, '江孜县', 3, 540200000000); +INSERT INTO `zz_area_code` VALUES (540223000000, '定日县', 3, 540200000000); +INSERT INTO `zz_area_code` VALUES (540224000000, '萨迦县', 3, 540200000000); +INSERT INTO `zz_area_code` VALUES (540225000000, '拉孜县', 3, 540200000000); +INSERT INTO `zz_area_code` VALUES (540226000000, '昂仁县', 3, 540200000000); +INSERT INTO `zz_area_code` VALUES (540227000000, '谢通门县', 3, 540200000000); +INSERT INTO `zz_area_code` VALUES (540228000000, '白朗县', 3, 540200000000); +INSERT INTO `zz_area_code` VALUES (540229000000, '仁布县', 3, 540200000000); +INSERT INTO `zz_area_code` VALUES (540230000000, '康马县', 3, 540200000000); +INSERT INTO `zz_area_code` VALUES (540231000000, '定结县', 3, 540200000000); +INSERT INTO `zz_area_code` VALUES (540232000000, '仲巴县', 3, 540200000000); +INSERT INTO `zz_area_code` VALUES (540233000000, '亚东县', 3, 540200000000); +INSERT INTO `zz_area_code` VALUES (540234000000, '吉隆县', 3, 540200000000); +INSERT INTO `zz_area_code` VALUES (540235000000, '聂拉木县', 3, 540200000000); +INSERT INTO `zz_area_code` VALUES (540236000000, '萨嘎县', 3, 540200000000); +INSERT INTO `zz_area_code` VALUES (540237000000, '岗巴县', 3, 540200000000); +INSERT INTO `zz_area_code` VALUES (540300000000, '昌都市', 2, 540000000000); +INSERT INTO `zz_area_code` VALUES (540302000000, '卡若区', 3, 540300000000); +INSERT INTO `zz_area_code` VALUES (540321000000, '江达县', 3, 540300000000); +INSERT INTO `zz_area_code` VALUES (540322000000, '贡觉县', 3, 540300000000); +INSERT INTO `zz_area_code` VALUES (540323000000, '类乌齐县', 3, 540300000000); +INSERT INTO `zz_area_code` VALUES (540324000000, '丁青县', 3, 540300000000); +INSERT INTO `zz_area_code` VALUES (540325000000, '察雅县', 3, 540300000000); +INSERT INTO `zz_area_code` VALUES (540326000000, '八宿县', 3, 540300000000); +INSERT INTO `zz_area_code` VALUES (540327000000, '左贡县', 3, 540300000000); +INSERT INTO `zz_area_code` VALUES (540328000000, '芒康县', 3, 540300000000); +INSERT INTO `zz_area_code` VALUES (540329000000, '洛隆县', 3, 540300000000); +INSERT INTO `zz_area_code` VALUES (540330000000, '边坝县', 3, 540300000000); +INSERT INTO `zz_area_code` VALUES (540400000000, '林芝市', 2, 540000000000); +INSERT INTO `zz_area_code` VALUES (540402000000, '巴宜区', 3, 540400000000); +INSERT INTO `zz_area_code` VALUES (540421000000, '工布江达县', 3, 540400000000); +INSERT INTO `zz_area_code` VALUES (540422000000, '米林县', 3, 540400000000); +INSERT INTO `zz_area_code` VALUES (540423000000, '墨脱县', 3, 540400000000); +INSERT INTO `zz_area_code` VALUES (540424000000, '波密县', 3, 540400000000); +INSERT INTO `zz_area_code` VALUES (540425000000, '察隅县', 3, 540400000000); +INSERT INTO `zz_area_code` VALUES (540426000000, '朗县', 3, 540400000000); +INSERT INTO `zz_area_code` VALUES (540500000000, '山南市', 2, 540000000000); +INSERT INTO `zz_area_code` VALUES (540501000000, '市辖区', 3, 540500000000); +INSERT INTO `zz_area_code` VALUES (540502000000, '乃东区', 3, 540500000000); +INSERT INTO `zz_area_code` VALUES (540521000000, '扎囊县', 3, 540500000000); +INSERT INTO `zz_area_code` VALUES (540522000000, '贡嘎县', 3, 540500000000); +INSERT INTO `zz_area_code` VALUES (540523000000, '桑日县', 3, 540500000000); +INSERT INTO `zz_area_code` VALUES (540524000000, '琼结县', 3, 540500000000); +INSERT INTO `zz_area_code` VALUES (540525000000, '曲松县', 3, 540500000000); +INSERT INTO `zz_area_code` VALUES (540526000000, '措美县', 3, 540500000000); +INSERT INTO `zz_area_code` VALUES (540527000000, '洛扎县', 3, 540500000000); +INSERT INTO `zz_area_code` VALUES (540528000000, '加查县', 3, 540500000000); +INSERT INTO `zz_area_code` VALUES (540529000000, '隆子县', 3, 540500000000); +INSERT INTO `zz_area_code` VALUES (540530000000, '错那县', 3, 540500000000); +INSERT INTO `zz_area_code` VALUES (540531000000, '浪卡子县', 3, 540500000000); +INSERT INTO `zz_area_code` VALUES (540600000000, '那曲市', 2, 540000000000); +INSERT INTO `zz_area_code` VALUES (540602000000, '色尼区', 3, 540600000000); +INSERT INTO `zz_area_code` VALUES (540621000000, '嘉黎县', 3, 540600000000); +INSERT INTO `zz_area_code` VALUES (540622000000, '比如县', 3, 540600000000); +INSERT INTO `zz_area_code` VALUES (540623000000, '聂荣县', 3, 540600000000); +INSERT INTO `zz_area_code` VALUES (540624000000, '安多县', 3, 540600000000); +INSERT INTO `zz_area_code` VALUES (540625000000, '申扎县', 3, 540600000000); +INSERT INTO `zz_area_code` VALUES (540626000000, '索县', 3, 540600000000); +INSERT INTO `zz_area_code` VALUES (540627000000, '班戈县', 3, 540600000000); +INSERT INTO `zz_area_code` VALUES (540628000000, '巴青县', 3, 540600000000); +INSERT INTO `zz_area_code` VALUES (540629000000, '尼玛县', 3, 540600000000); +INSERT INTO `zz_area_code` VALUES (540630000000, '双湖县', 3, 540600000000); +INSERT INTO `zz_area_code` VALUES (542500000000, '阿里地区', 2, 540000000000); +INSERT INTO `zz_area_code` VALUES (542521000000, '普兰县', 3, 542500000000); +INSERT INTO `zz_area_code` VALUES (542522000000, '札达县', 3, 542500000000); +INSERT INTO `zz_area_code` VALUES (542523000000, '噶尔县', 3, 542500000000); +INSERT INTO `zz_area_code` VALUES (542524000000, '日土县', 3, 542500000000); +INSERT INTO `zz_area_code` VALUES (542525000000, '革吉县', 3, 542500000000); +INSERT INTO `zz_area_code` VALUES (542526000000, '改则县', 3, 542500000000); +INSERT INTO `zz_area_code` VALUES (542527000000, '措勤县', 3, 542500000000); +INSERT INTO `zz_area_code` VALUES (610000000000, '陕西省', 1, NULL); +INSERT INTO `zz_area_code` VALUES (610100000000, '西安市', 2, 610000000000); +INSERT INTO `zz_area_code` VALUES (610101000000, '市辖区', 3, 610100000000); +INSERT INTO `zz_area_code` VALUES (610102000000, '新城区', 3, 610100000000); +INSERT INTO `zz_area_code` VALUES (610103000000, '碑林区', 3, 610100000000); +INSERT INTO `zz_area_code` VALUES (610104000000, '莲湖区', 3, 610100000000); +INSERT INTO `zz_area_code` VALUES (610111000000, '灞桥区', 3, 610100000000); +INSERT INTO `zz_area_code` VALUES (610112000000, '未央区', 3, 610100000000); +INSERT INTO `zz_area_code` VALUES (610113000000, '雁塔区', 3, 610100000000); +INSERT INTO `zz_area_code` VALUES (610114000000, '阎良区', 3, 610100000000); +INSERT INTO `zz_area_code` VALUES (610115000000, '临潼区', 3, 610100000000); +INSERT INTO `zz_area_code` VALUES (610116000000, '长安区', 3, 610100000000); +INSERT INTO `zz_area_code` VALUES (610117000000, '高陵区', 3, 610100000000); +INSERT INTO `zz_area_code` VALUES (610118000000, '鄠邑区', 3, 610100000000); +INSERT INTO `zz_area_code` VALUES (610122000000, '蓝田县', 3, 610100000000); +INSERT INTO `zz_area_code` VALUES (610124000000, '周至县', 3, 610100000000); +INSERT INTO `zz_area_code` VALUES (610200000000, '铜川市', 2, 610000000000); +INSERT INTO `zz_area_code` VALUES (610201000000, '市辖区', 3, 610200000000); +INSERT INTO `zz_area_code` VALUES (610202000000, '王益区', 3, 610200000000); +INSERT INTO `zz_area_code` VALUES (610203000000, '印台区', 3, 610200000000); +INSERT INTO `zz_area_code` VALUES (610204000000, '耀州区', 3, 610200000000); +INSERT INTO `zz_area_code` VALUES (610222000000, '宜君县', 3, 610200000000); +INSERT INTO `zz_area_code` VALUES (610300000000, '宝鸡市', 2, 610000000000); +INSERT INTO `zz_area_code` VALUES (610301000000, '市辖区', 3, 610300000000); +INSERT INTO `zz_area_code` VALUES (610302000000, '渭滨区', 3, 610300000000); +INSERT INTO `zz_area_code` VALUES (610303000000, '金台区', 3, 610300000000); +INSERT INTO `zz_area_code` VALUES (610304000000, '陈仓区', 3, 610300000000); +INSERT INTO `zz_area_code` VALUES (610322000000, '凤翔县', 3, 610300000000); +INSERT INTO `zz_area_code` VALUES (610323000000, '岐山县', 3, 610300000000); +INSERT INTO `zz_area_code` VALUES (610324000000, '扶风县', 3, 610300000000); +INSERT INTO `zz_area_code` VALUES (610326000000, '眉县', 3, 610300000000); +INSERT INTO `zz_area_code` VALUES (610327000000, '陇县', 3, 610300000000); +INSERT INTO `zz_area_code` VALUES (610328000000, '千阳县', 3, 610300000000); +INSERT INTO `zz_area_code` VALUES (610329000000, '麟游县', 3, 610300000000); +INSERT INTO `zz_area_code` VALUES (610330000000, '凤县', 3, 610300000000); +INSERT INTO `zz_area_code` VALUES (610331000000, '太白县', 3, 610300000000); +INSERT INTO `zz_area_code` VALUES (610400000000, '咸阳市', 2, 610000000000); +INSERT INTO `zz_area_code` VALUES (610401000000, '市辖区', 3, 610400000000); +INSERT INTO `zz_area_code` VALUES (610402000000, '秦都区', 3, 610400000000); +INSERT INTO `zz_area_code` VALUES (610403000000, '杨陵区', 3, 610400000000); +INSERT INTO `zz_area_code` VALUES (610404000000, '渭城区', 3, 610400000000); +INSERT INTO `zz_area_code` VALUES (610422000000, '三原县', 3, 610400000000); +INSERT INTO `zz_area_code` VALUES (610423000000, '泾阳县', 3, 610400000000); +INSERT INTO `zz_area_code` VALUES (610424000000, '乾县', 3, 610400000000); +INSERT INTO `zz_area_code` VALUES (610425000000, '礼泉县', 3, 610400000000); +INSERT INTO `zz_area_code` VALUES (610426000000, '永寿县', 3, 610400000000); +INSERT INTO `zz_area_code` VALUES (610428000000, '长武县', 3, 610400000000); +INSERT INTO `zz_area_code` VALUES (610429000000, '旬邑县', 3, 610400000000); +INSERT INTO `zz_area_code` VALUES (610430000000, '淳化县', 3, 610400000000); +INSERT INTO `zz_area_code` VALUES (610431000000, '武功县', 3, 610400000000); +INSERT INTO `zz_area_code` VALUES (610481000000, '兴平市', 3, 610400000000); +INSERT INTO `zz_area_code` VALUES (610482000000, '彬州市', 3, 610400000000); +INSERT INTO `zz_area_code` VALUES (610500000000, '渭南市', 2, 610000000000); +INSERT INTO `zz_area_code` VALUES (610501000000, '市辖区', 3, 610500000000); +INSERT INTO `zz_area_code` VALUES (610502000000, '临渭区', 3, 610500000000); +INSERT INTO `zz_area_code` VALUES (610503000000, '华州区', 3, 610500000000); +INSERT INTO `zz_area_code` VALUES (610522000000, '潼关县', 3, 610500000000); +INSERT INTO `zz_area_code` VALUES (610523000000, '大荔县', 3, 610500000000); +INSERT INTO `zz_area_code` VALUES (610524000000, '合阳县', 3, 610500000000); +INSERT INTO `zz_area_code` VALUES (610525000000, '澄城县', 3, 610500000000); +INSERT INTO `zz_area_code` VALUES (610526000000, '蒲城县', 3, 610500000000); +INSERT INTO `zz_area_code` VALUES (610527000000, '白水县', 3, 610500000000); +INSERT INTO `zz_area_code` VALUES (610528000000, '富平县', 3, 610500000000); +INSERT INTO `zz_area_code` VALUES (610581000000, '韩城市', 3, 610500000000); +INSERT INTO `zz_area_code` VALUES (610582000000, '华阴市', 3, 610500000000); +INSERT INTO `zz_area_code` VALUES (610600000000, '延安市', 2, 610000000000); +INSERT INTO `zz_area_code` VALUES (610601000000, '市辖区', 3, 610600000000); +INSERT INTO `zz_area_code` VALUES (610602000000, '宝塔区', 3, 610600000000); +INSERT INTO `zz_area_code` VALUES (610603000000, '安塞区', 3, 610600000000); +INSERT INTO `zz_area_code` VALUES (610621000000, '延长县', 3, 610600000000); +INSERT INTO `zz_area_code` VALUES (610622000000, '延川县', 3, 610600000000); +INSERT INTO `zz_area_code` VALUES (610623000000, '子长县', 3, 610600000000); +INSERT INTO `zz_area_code` VALUES (610625000000, '志丹县', 3, 610600000000); +INSERT INTO `zz_area_code` VALUES (610626000000, '吴起县', 3, 610600000000); +INSERT INTO `zz_area_code` VALUES (610627000000, '甘泉县', 3, 610600000000); +INSERT INTO `zz_area_code` VALUES (610628000000, '富县', 3, 610600000000); +INSERT INTO `zz_area_code` VALUES (610629000000, '洛川县', 3, 610600000000); +INSERT INTO `zz_area_code` VALUES (610630000000, '宜川县', 3, 610600000000); +INSERT INTO `zz_area_code` VALUES (610631000000, '黄龙县', 3, 610600000000); +INSERT INTO `zz_area_code` VALUES (610632000000, '黄陵县', 3, 610600000000); +INSERT INTO `zz_area_code` VALUES (610700000000, '汉中市', 2, 610000000000); +INSERT INTO `zz_area_code` VALUES (610701000000, '市辖区', 3, 610700000000); +INSERT INTO `zz_area_code` VALUES (610702000000, '汉台区', 3, 610700000000); +INSERT INTO `zz_area_code` VALUES (610703000000, '南郑区', 3, 610700000000); +INSERT INTO `zz_area_code` VALUES (610722000000, '城固县', 3, 610700000000); +INSERT INTO `zz_area_code` VALUES (610723000000, '洋县', 3, 610700000000); +INSERT INTO `zz_area_code` VALUES (610724000000, '西乡县', 3, 610700000000); +INSERT INTO `zz_area_code` VALUES (610725000000, '勉县', 3, 610700000000); +INSERT INTO `zz_area_code` VALUES (610726000000, '宁强县', 3, 610700000000); +INSERT INTO `zz_area_code` VALUES (610727000000, '略阳县', 3, 610700000000); +INSERT INTO `zz_area_code` VALUES (610728000000, '镇巴县', 3, 610700000000); +INSERT INTO `zz_area_code` VALUES (610729000000, '留坝县', 3, 610700000000); +INSERT INTO `zz_area_code` VALUES (610730000000, '佛坪县', 3, 610700000000); +INSERT INTO `zz_area_code` VALUES (610800000000, '榆林市', 2, 610000000000); +INSERT INTO `zz_area_code` VALUES (610801000000, '市辖区', 3, 610800000000); +INSERT INTO `zz_area_code` VALUES (610802000000, '榆阳区', 3, 610800000000); +INSERT INTO `zz_area_code` VALUES (610803000000, '横山区', 3, 610800000000); +INSERT INTO `zz_area_code` VALUES (610822000000, '府谷县', 3, 610800000000); +INSERT INTO `zz_area_code` VALUES (610824000000, '靖边县', 3, 610800000000); +INSERT INTO `zz_area_code` VALUES (610825000000, '定边县', 3, 610800000000); +INSERT INTO `zz_area_code` VALUES (610826000000, '绥德县', 3, 610800000000); +INSERT INTO `zz_area_code` VALUES (610827000000, '米脂县', 3, 610800000000); +INSERT INTO `zz_area_code` VALUES (610828000000, '佳县', 3, 610800000000); +INSERT INTO `zz_area_code` VALUES (610829000000, '吴堡县', 3, 610800000000); +INSERT INTO `zz_area_code` VALUES (610830000000, '清涧县', 3, 610800000000); +INSERT INTO `zz_area_code` VALUES (610831000000, '子洲县', 3, 610800000000); +INSERT INTO `zz_area_code` VALUES (610881000000, '神木市', 3, 610800000000); +INSERT INTO `zz_area_code` VALUES (610900000000, '安康市', 2, 610000000000); +INSERT INTO `zz_area_code` VALUES (610901000000, '市辖区', 3, 610900000000); +INSERT INTO `zz_area_code` VALUES (610902000000, '汉滨区', 3, 610900000000); +INSERT INTO `zz_area_code` VALUES (610921000000, '汉阴县', 3, 610900000000); +INSERT INTO `zz_area_code` VALUES (610922000000, '石泉县', 3, 610900000000); +INSERT INTO `zz_area_code` VALUES (610923000000, '宁陕县', 3, 610900000000); +INSERT INTO `zz_area_code` VALUES (610924000000, '紫阳县', 3, 610900000000); +INSERT INTO `zz_area_code` VALUES (610925000000, '岚皋县', 3, 610900000000); +INSERT INTO `zz_area_code` VALUES (610926000000, '平利县', 3, 610900000000); +INSERT INTO `zz_area_code` VALUES (610927000000, '镇坪县', 3, 610900000000); +INSERT INTO `zz_area_code` VALUES (610928000000, '旬阳县', 3, 610900000000); +INSERT INTO `zz_area_code` VALUES (610929000000, '白河县', 3, 610900000000); +INSERT INTO `zz_area_code` VALUES (611000000000, '商洛市', 2, 610000000000); +INSERT INTO `zz_area_code` VALUES (611001000000, '市辖区', 3, 611000000000); +INSERT INTO `zz_area_code` VALUES (611002000000, '商州区', 3, 611000000000); +INSERT INTO `zz_area_code` VALUES (611021000000, '洛南县', 3, 611000000000); +INSERT INTO `zz_area_code` VALUES (611022000000, '丹凤县', 3, 611000000000); +INSERT INTO `zz_area_code` VALUES (611023000000, '商南县', 3, 611000000000); +INSERT INTO `zz_area_code` VALUES (611024000000, '山阳县', 3, 611000000000); +INSERT INTO `zz_area_code` VALUES (611025000000, '镇安县', 3, 611000000000); +INSERT INTO `zz_area_code` VALUES (611026000000, '柞水县', 3, 611000000000); +INSERT INTO `zz_area_code` VALUES (620000000000, '甘肃省', 1, NULL); +INSERT INTO `zz_area_code` VALUES (620100000000, '兰州市', 2, 620000000000); +INSERT INTO `zz_area_code` VALUES (620101000000, '市辖区', 3, 620100000000); +INSERT INTO `zz_area_code` VALUES (620102000000, '城关区', 3, 620100000000); +INSERT INTO `zz_area_code` VALUES (620103000000, '七里河区', 3, 620100000000); +INSERT INTO `zz_area_code` VALUES (620104000000, '西固区', 3, 620100000000); +INSERT INTO `zz_area_code` VALUES (620105000000, '安宁区', 3, 620100000000); +INSERT INTO `zz_area_code` VALUES (620111000000, '红古区', 3, 620100000000); +INSERT INTO `zz_area_code` VALUES (620121000000, '永登县', 3, 620100000000); +INSERT INTO `zz_area_code` VALUES (620122000000, '皋兰县', 3, 620100000000); +INSERT INTO `zz_area_code` VALUES (620123000000, '榆中县', 3, 620100000000); +INSERT INTO `zz_area_code` VALUES (620171000000, '兰州新区', 3, 620100000000); +INSERT INTO `zz_area_code` VALUES (620200000000, '嘉峪关市', 2, 620000000000); +INSERT INTO `zz_area_code` VALUES (620201000000, '市辖区', 3, 620200000000); +INSERT INTO `zz_area_code` VALUES (620300000000, '金昌市', 2, 620000000000); +INSERT INTO `zz_area_code` VALUES (620301000000, '市辖区', 3, 620300000000); +INSERT INTO `zz_area_code` VALUES (620302000000, '金川区', 3, 620300000000); +INSERT INTO `zz_area_code` VALUES (620321000000, '永昌县', 3, 620300000000); +INSERT INTO `zz_area_code` VALUES (620400000000, '白银市', 2, 620000000000); +INSERT INTO `zz_area_code` VALUES (620401000000, '市辖区', 3, 620400000000); +INSERT INTO `zz_area_code` VALUES (620402000000, '白银区', 3, 620400000000); +INSERT INTO `zz_area_code` VALUES (620403000000, '平川区', 3, 620400000000); +INSERT INTO `zz_area_code` VALUES (620421000000, '靖远县', 3, 620400000000); +INSERT INTO `zz_area_code` VALUES (620422000000, '会宁县', 3, 620400000000); +INSERT INTO `zz_area_code` VALUES (620423000000, '景泰县', 3, 620400000000); +INSERT INTO `zz_area_code` VALUES (620500000000, '天水市', 2, 620000000000); +INSERT INTO `zz_area_code` VALUES (620501000000, '市辖区', 3, 620500000000); +INSERT INTO `zz_area_code` VALUES (620502000000, '秦州区', 3, 620500000000); +INSERT INTO `zz_area_code` VALUES (620503000000, '麦积区', 3, 620500000000); +INSERT INTO `zz_area_code` VALUES (620521000000, '清水县', 3, 620500000000); +INSERT INTO `zz_area_code` VALUES (620522000000, '秦安县', 3, 620500000000); +INSERT INTO `zz_area_code` VALUES (620523000000, '甘谷县', 3, 620500000000); +INSERT INTO `zz_area_code` VALUES (620524000000, '武山县', 3, 620500000000); +INSERT INTO `zz_area_code` VALUES (620525000000, '张家川回族自治县', 3, 620500000000); +INSERT INTO `zz_area_code` VALUES (620600000000, '武威市', 2, 620000000000); +INSERT INTO `zz_area_code` VALUES (620601000000, '市辖区', 3, 620600000000); +INSERT INTO `zz_area_code` VALUES (620602000000, '凉州区', 3, 620600000000); +INSERT INTO `zz_area_code` VALUES (620621000000, '民勤县', 3, 620600000000); +INSERT INTO `zz_area_code` VALUES (620622000000, '古浪县', 3, 620600000000); +INSERT INTO `zz_area_code` VALUES (620623000000, '天祝藏族自治县', 3, 620600000000); +INSERT INTO `zz_area_code` VALUES (620700000000, '张掖市', 2, 620000000000); +INSERT INTO `zz_area_code` VALUES (620701000000, '市辖区', 3, 620700000000); +INSERT INTO `zz_area_code` VALUES (620702000000, '甘州区', 3, 620700000000); +INSERT INTO `zz_area_code` VALUES (620721000000, '肃南裕固族自治县', 3, 620700000000); +INSERT INTO `zz_area_code` VALUES (620722000000, '民乐县', 3, 620700000000); +INSERT INTO `zz_area_code` VALUES (620723000000, '临泽县', 3, 620700000000); +INSERT INTO `zz_area_code` VALUES (620724000000, '高台县', 3, 620700000000); +INSERT INTO `zz_area_code` VALUES (620725000000, '山丹县', 3, 620700000000); +INSERT INTO `zz_area_code` VALUES (620800000000, '平凉市', 2, 620000000000); +INSERT INTO `zz_area_code` VALUES (620801000000, '市辖区', 3, 620800000000); +INSERT INTO `zz_area_code` VALUES (620802000000, '崆峒区', 3, 620800000000); +INSERT INTO `zz_area_code` VALUES (620821000000, '泾川县', 3, 620800000000); +INSERT INTO `zz_area_code` VALUES (620822000000, '灵台县', 3, 620800000000); +INSERT INTO `zz_area_code` VALUES (620823000000, '崇信县', 3, 620800000000); +INSERT INTO `zz_area_code` VALUES (620825000000, '庄浪县', 3, 620800000000); +INSERT INTO `zz_area_code` VALUES (620826000000, '静宁县', 3, 620800000000); +INSERT INTO `zz_area_code` VALUES (620881000000, '华亭市', 3, 620800000000); +INSERT INTO `zz_area_code` VALUES (620900000000, '酒泉市', 2, 620000000000); +INSERT INTO `zz_area_code` VALUES (620901000000, '市辖区', 3, 620900000000); +INSERT INTO `zz_area_code` VALUES (620902000000, '肃州区', 3, 620900000000); +INSERT INTO `zz_area_code` VALUES (620921000000, '金塔县', 3, 620900000000); +INSERT INTO `zz_area_code` VALUES (620922000000, '瓜州县', 3, 620900000000); +INSERT INTO `zz_area_code` VALUES (620923000000, '肃北蒙古族自治县', 3, 620900000000); +INSERT INTO `zz_area_code` VALUES (620924000000, '阿克塞哈萨克族自治县', 3, 620900000000); +INSERT INTO `zz_area_code` VALUES (620981000000, '玉门市', 3, 620900000000); +INSERT INTO `zz_area_code` VALUES (620982000000, '敦煌市', 3, 620900000000); +INSERT INTO `zz_area_code` VALUES (621000000000, '庆阳市', 2, 620000000000); +INSERT INTO `zz_area_code` VALUES (621001000000, '市辖区', 3, 621000000000); +INSERT INTO `zz_area_code` VALUES (621002000000, '西峰区', 3, 621000000000); +INSERT INTO `zz_area_code` VALUES (621021000000, '庆城县', 3, 621000000000); +INSERT INTO `zz_area_code` VALUES (621022000000, '环县', 3, 621000000000); +INSERT INTO `zz_area_code` VALUES (621023000000, '华池县', 3, 621000000000); +INSERT INTO `zz_area_code` VALUES (621024000000, '合水县', 3, 621000000000); +INSERT INTO `zz_area_code` VALUES (621025000000, '正宁县', 3, 621000000000); +INSERT INTO `zz_area_code` VALUES (621026000000, '宁县', 3, 621000000000); +INSERT INTO `zz_area_code` VALUES (621027000000, '镇原县', 3, 621000000000); +INSERT INTO `zz_area_code` VALUES (621100000000, '定西市', 2, 620000000000); +INSERT INTO `zz_area_code` VALUES (621101000000, '市辖区', 3, 621100000000); +INSERT INTO `zz_area_code` VALUES (621102000000, '安定区', 3, 621100000000); +INSERT INTO `zz_area_code` VALUES (621121000000, '通渭县', 3, 621100000000); +INSERT INTO `zz_area_code` VALUES (621122000000, '陇西县', 3, 621100000000); +INSERT INTO `zz_area_code` VALUES (621123000000, '渭源县', 3, 621100000000); +INSERT INTO `zz_area_code` VALUES (621124000000, '临洮县', 3, 621100000000); +INSERT INTO `zz_area_code` VALUES (621125000000, '漳县', 3, 621100000000); +INSERT INTO `zz_area_code` VALUES (621126000000, '岷县', 3, 621100000000); +INSERT INTO `zz_area_code` VALUES (621200000000, '陇南市', 2, 620000000000); +INSERT INTO `zz_area_code` VALUES (621201000000, '市辖区', 3, 621200000000); +INSERT INTO `zz_area_code` VALUES (621202000000, '武都区', 3, 621200000000); +INSERT INTO `zz_area_code` VALUES (621221000000, '成县', 3, 621200000000); +INSERT INTO `zz_area_code` VALUES (621222000000, '文县', 3, 621200000000); +INSERT INTO `zz_area_code` VALUES (621223000000, '宕昌县', 3, 621200000000); +INSERT INTO `zz_area_code` VALUES (621224000000, '康县', 3, 621200000000); +INSERT INTO `zz_area_code` VALUES (621225000000, '西和县', 3, 621200000000); +INSERT INTO `zz_area_code` VALUES (621226000000, '礼县', 3, 621200000000); +INSERT INTO `zz_area_code` VALUES (621227000000, '徽县', 3, 621200000000); +INSERT INTO `zz_area_code` VALUES (621228000000, '两当县', 3, 621200000000); +INSERT INTO `zz_area_code` VALUES (622900000000, '临夏回族自治州', 2, 620000000000); +INSERT INTO `zz_area_code` VALUES (622901000000, '临夏市', 3, 622900000000); +INSERT INTO `zz_area_code` VALUES (622921000000, '临夏县', 3, 622900000000); +INSERT INTO `zz_area_code` VALUES (622922000000, '康乐县', 3, 622900000000); +INSERT INTO `zz_area_code` VALUES (622923000000, '永靖县', 3, 622900000000); +INSERT INTO `zz_area_code` VALUES (622924000000, '广河县', 3, 622900000000); +INSERT INTO `zz_area_code` VALUES (622925000000, '和政县', 3, 622900000000); +INSERT INTO `zz_area_code` VALUES (622926000000, '东乡族自治县', 3, 622900000000); +INSERT INTO `zz_area_code` VALUES (622927000000, '积石山保安族东乡族撒拉族自治县', 3, 622900000000); +INSERT INTO `zz_area_code` VALUES (623000000000, '甘南藏族自治州', 2, 620000000000); +INSERT INTO `zz_area_code` VALUES (623001000000, '合作市', 3, 623000000000); +INSERT INTO `zz_area_code` VALUES (623021000000, '临潭县', 3, 623000000000); +INSERT INTO `zz_area_code` VALUES (623022000000, '卓尼县', 3, 623000000000); +INSERT INTO `zz_area_code` VALUES (623023000000, '舟曲县', 3, 623000000000); +INSERT INTO `zz_area_code` VALUES (623024000000, '迭部县', 3, 623000000000); +INSERT INTO `zz_area_code` VALUES (623025000000, '玛曲县', 3, 623000000000); +INSERT INTO `zz_area_code` VALUES (623026000000, '碌曲县', 3, 623000000000); +INSERT INTO `zz_area_code` VALUES (623027000000, '夏河县', 3, 623000000000); +INSERT INTO `zz_area_code` VALUES (630000000000, '青海省', 1, NULL); +INSERT INTO `zz_area_code` VALUES (630100000000, '西宁市', 2, 630000000000); +INSERT INTO `zz_area_code` VALUES (630101000000, '市辖区', 3, 630100000000); +INSERT INTO `zz_area_code` VALUES (630102000000, '城东区', 3, 630100000000); +INSERT INTO `zz_area_code` VALUES (630103000000, '城中区', 3, 630100000000); +INSERT INTO `zz_area_code` VALUES (630104000000, '城西区', 3, 630100000000); +INSERT INTO `zz_area_code` VALUES (630105000000, '城北区', 3, 630100000000); +INSERT INTO `zz_area_code` VALUES (630121000000, '大通回族土族自治县', 3, 630100000000); +INSERT INTO `zz_area_code` VALUES (630122000000, '湟中县', 3, 630100000000); +INSERT INTO `zz_area_code` VALUES (630123000000, '湟源县', 3, 630100000000); +INSERT INTO `zz_area_code` VALUES (630200000000, '海东市', 2, 630000000000); +INSERT INTO `zz_area_code` VALUES (630202000000, '乐都区', 3, 630200000000); +INSERT INTO `zz_area_code` VALUES (630203000000, '平安区', 3, 630200000000); +INSERT INTO `zz_area_code` VALUES (630222000000, '民和回族土族自治县', 3, 630200000000); +INSERT INTO `zz_area_code` VALUES (630223000000, '互助土族自治县', 3, 630200000000); +INSERT INTO `zz_area_code` VALUES (630224000000, '化隆回族自治县', 3, 630200000000); +INSERT INTO `zz_area_code` VALUES (630225000000, '循化撒拉族自治县', 3, 630200000000); +INSERT INTO `zz_area_code` VALUES (632200000000, '海北藏族自治州', 2, 630000000000); +INSERT INTO `zz_area_code` VALUES (632221000000, '门源回族自治县', 3, 632200000000); +INSERT INTO `zz_area_code` VALUES (632222000000, '祁连县', 3, 632200000000); +INSERT INTO `zz_area_code` VALUES (632223000000, '海晏县', 3, 632200000000); +INSERT INTO `zz_area_code` VALUES (632224000000, '刚察县', 3, 632200000000); +INSERT INTO `zz_area_code` VALUES (632300000000, '黄南藏族自治州', 2, 630000000000); +INSERT INTO `zz_area_code` VALUES (632321000000, '同仁县', 3, 632300000000); +INSERT INTO `zz_area_code` VALUES (632322000000, '尖扎县', 3, 632300000000); +INSERT INTO `zz_area_code` VALUES (632323000000, '泽库县', 3, 632300000000); +INSERT INTO `zz_area_code` VALUES (632324000000, '河南蒙古族自治县', 3, 632300000000); +INSERT INTO `zz_area_code` VALUES (632500000000, '海南藏族自治州', 2, 630000000000); +INSERT INTO `zz_area_code` VALUES (632521000000, '共和县', 3, 632500000000); +INSERT INTO `zz_area_code` VALUES (632522000000, '同德县', 3, 632500000000); +INSERT INTO `zz_area_code` VALUES (632523000000, '贵德县', 3, 632500000000); +INSERT INTO `zz_area_code` VALUES (632524000000, '兴海县', 3, 632500000000); +INSERT INTO `zz_area_code` VALUES (632525000000, '贵南县', 3, 632500000000); +INSERT INTO `zz_area_code` VALUES (632600000000, '果洛藏族自治州', 2, 630000000000); +INSERT INTO `zz_area_code` VALUES (632621000000, '玛沁县', 3, 632600000000); +INSERT INTO `zz_area_code` VALUES (632622000000, '班玛县', 3, 632600000000); +INSERT INTO `zz_area_code` VALUES (632623000000, '甘德县', 3, 632600000000); +INSERT INTO `zz_area_code` VALUES (632624000000, '达日县', 3, 632600000000); +INSERT INTO `zz_area_code` VALUES (632625000000, '久治县', 3, 632600000000); +INSERT INTO `zz_area_code` VALUES (632626000000, '玛多县', 3, 632600000000); +INSERT INTO `zz_area_code` VALUES (632700000000, '玉树藏族自治州', 2, 630000000000); +INSERT INTO `zz_area_code` VALUES (632701000000, '玉树市', 3, 632700000000); +INSERT INTO `zz_area_code` VALUES (632722000000, '杂多县', 3, 632700000000); +INSERT INTO `zz_area_code` VALUES (632723000000, '称多县', 3, 632700000000); +INSERT INTO `zz_area_code` VALUES (632724000000, '治多县', 3, 632700000000); +INSERT INTO `zz_area_code` VALUES (632725000000, '囊谦县', 3, 632700000000); +INSERT INTO `zz_area_code` VALUES (632726000000, '曲麻莱县', 3, 632700000000); +INSERT INTO `zz_area_code` VALUES (632800000000, '海西蒙古族藏族自治州', 2, 630000000000); +INSERT INTO `zz_area_code` VALUES (632801000000, '格尔木市', 3, 632800000000); +INSERT INTO `zz_area_code` VALUES (632802000000, '德令哈市', 3, 632800000000); +INSERT INTO `zz_area_code` VALUES (632803000000, '茫崖市', 3, 632800000000); +INSERT INTO `zz_area_code` VALUES (632821000000, '乌兰县', 3, 632800000000); +INSERT INTO `zz_area_code` VALUES (632822000000, '都兰县', 3, 632800000000); +INSERT INTO `zz_area_code` VALUES (632823000000, '天峻县', 3, 632800000000); +INSERT INTO `zz_area_code` VALUES (632857000000, '大柴旦行政委员会', 3, 632800000000); +INSERT INTO `zz_area_code` VALUES (640000000000, '宁夏回族自治区', 1, NULL); +INSERT INTO `zz_area_code` VALUES (640100000000, '银川市', 2, 640000000000); +INSERT INTO `zz_area_code` VALUES (640101000000, '市辖区', 3, 640100000000); +INSERT INTO `zz_area_code` VALUES (640104000000, '兴庆区', 3, 640100000000); +INSERT INTO `zz_area_code` VALUES (640105000000, '西夏区', 3, 640100000000); +INSERT INTO `zz_area_code` VALUES (640106000000, '金凤区', 3, 640100000000); +INSERT INTO `zz_area_code` VALUES (640121000000, '永宁县', 3, 640100000000); +INSERT INTO `zz_area_code` VALUES (640122000000, '贺兰县', 3, 640100000000); +INSERT INTO `zz_area_code` VALUES (640181000000, '灵武市', 3, 640100000000); +INSERT INTO `zz_area_code` VALUES (640200000000, '石嘴山市', 2, 640000000000); +INSERT INTO `zz_area_code` VALUES (640201000000, '市辖区', 3, 640200000000); +INSERT INTO `zz_area_code` VALUES (640202000000, '大武口区', 3, 640200000000); +INSERT INTO `zz_area_code` VALUES (640205000000, '惠农区', 3, 640200000000); +INSERT INTO `zz_area_code` VALUES (640221000000, '平罗县', 3, 640200000000); +INSERT INTO `zz_area_code` VALUES (640300000000, '吴忠市', 2, 640000000000); +INSERT INTO `zz_area_code` VALUES (640301000000, '市辖区', 3, 640300000000); +INSERT INTO `zz_area_code` VALUES (640302000000, '利通区', 3, 640300000000); +INSERT INTO `zz_area_code` VALUES (640303000000, '红寺堡区', 3, 640300000000); +INSERT INTO `zz_area_code` VALUES (640323000000, '盐池县', 3, 640300000000); +INSERT INTO `zz_area_code` VALUES (640324000000, '同心县', 3, 640300000000); +INSERT INTO `zz_area_code` VALUES (640381000000, '青铜峡市', 3, 640300000000); +INSERT INTO `zz_area_code` VALUES (640400000000, '固原市', 2, 640000000000); +INSERT INTO `zz_area_code` VALUES (640401000000, '市辖区', 3, 640400000000); +INSERT INTO `zz_area_code` VALUES (640402000000, '原州区', 3, 640400000000); +INSERT INTO `zz_area_code` VALUES (640422000000, '西吉县', 3, 640400000000); +INSERT INTO `zz_area_code` VALUES (640423000000, '隆德县', 3, 640400000000); +INSERT INTO `zz_area_code` VALUES (640424000000, '泾源县', 3, 640400000000); +INSERT INTO `zz_area_code` VALUES (640425000000, '彭阳县', 3, 640400000000); +INSERT INTO `zz_area_code` VALUES (640500000000, '中卫市', 2, 640000000000); +INSERT INTO `zz_area_code` VALUES (640501000000, '市辖区', 3, 640500000000); +INSERT INTO `zz_area_code` VALUES (640502000000, '沙坡头区', 3, 640500000000); +INSERT INTO `zz_area_code` VALUES (640521000000, '中宁县', 3, 640500000000); +INSERT INTO `zz_area_code` VALUES (640522000000, '海原县', 3, 640500000000); +INSERT INTO `zz_area_code` VALUES (650000000000, '新疆维吾尔自治区', 1, NULL); +INSERT INTO `zz_area_code` VALUES (650100000000, '乌鲁木齐市', 2, 650000000000); +INSERT INTO `zz_area_code` VALUES (650101000000, '市辖区', 3, 650100000000); +INSERT INTO `zz_area_code` VALUES (650102000000, '天山区', 3, 650100000000); +INSERT INTO `zz_area_code` VALUES (650103000000, '沙依巴克区', 3, 650100000000); +INSERT INTO `zz_area_code` VALUES (650104000000, '新市区', 3, 650100000000); +INSERT INTO `zz_area_code` VALUES (650105000000, '水磨沟区', 3, 650100000000); +INSERT INTO `zz_area_code` VALUES (650106000000, '头屯河区', 3, 650100000000); +INSERT INTO `zz_area_code` VALUES (650107000000, '达坂城区', 3, 650100000000); +INSERT INTO `zz_area_code` VALUES (650109000000, '米东区', 3, 650100000000); +INSERT INTO `zz_area_code` VALUES (650121000000, '乌鲁木齐县', 3, 650100000000); +INSERT INTO `zz_area_code` VALUES (650171000000, '乌鲁木齐经济技术开发区', 3, 650100000000); +INSERT INTO `zz_area_code` VALUES (650172000000, '乌鲁木齐高新技术产业开发区', 3, 650100000000); +INSERT INTO `zz_area_code` VALUES (650200000000, '克拉玛依市', 2, 650000000000); +INSERT INTO `zz_area_code` VALUES (650201000000, '市辖区', 3, 650200000000); +INSERT INTO `zz_area_code` VALUES (650202000000, '独山子区', 3, 650200000000); +INSERT INTO `zz_area_code` VALUES (650203000000, '克拉玛依区', 3, 650200000000); +INSERT INTO `zz_area_code` VALUES (650204000000, '白碱滩区', 3, 650200000000); +INSERT INTO `zz_area_code` VALUES (650205000000, '乌尔禾区', 3, 650200000000); +INSERT INTO `zz_area_code` VALUES (650400000000, '吐鲁番市', 2, 650000000000); +INSERT INTO `zz_area_code` VALUES (650402000000, '高昌区', 3, 650400000000); +INSERT INTO `zz_area_code` VALUES (650421000000, '鄯善县', 3, 650400000000); +INSERT INTO `zz_area_code` VALUES (650422000000, '托克逊县', 3, 650400000000); +INSERT INTO `zz_area_code` VALUES (650500000000, '哈密市', 2, 650000000000); +INSERT INTO `zz_area_code` VALUES (650502000000, '伊州区', 3, 650500000000); +INSERT INTO `zz_area_code` VALUES (650521000000, '巴里坤哈萨克自治县', 3, 650500000000); +INSERT INTO `zz_area_code` VALUES (650522000000, '伊吾县', 3, 650500000000); +INSERT INTO `zz_area_code` VALUES (652300000000, '昌吉回族自治州', 2, 650000000000); +INSERT INTO `zz_area_code` VALUES (652301000000, '昌吉市', 3, 652300000000); +INSERT INTO `zz_area_code` VALUES (652302000000, '阜康市', 3, 652300000000); +INSERT INTO `zz_area_code` VALUES (652323000000, '呼图壁县', 3, 652300000000); +INSERT INTO `zz_area_code` VALUES (652324000000, '玛纳斯县', 3, 652300000000); +INSERT INTO `zz_area_code` VALUES (652325000000, '奇台县', 3, 652300000000); +INSERT INTO `zz_area_code` VALUES (652327000000, '吉木萨尔县', 3, 652300000000); +INSERT INTO `zz_area_code` VALUES (652328000000, '木垒哈萨克自治县', 3, 652300000000); +INSERT INTO `zz_area_code` VALUES (652700000000, '博尔塔拉蒙古自治州', 2, 650000000000); +INSERT INTO `zz_area_code` VALUES (652701000000, '博乐市', 3, 652700000000); +INSERT INTO `zz_area_code` VALUES (652702000000, '阿拉山口市', 3, 652700000000); +INSERT INTO `zz_area_code` VALUES (652722000000, '精河县', 3, 652700000000); +INSERT INTO `zz_area_code` VALUES (652723000000, '温泉县', 3, 652700000000); +INSERT INTO `zz_area_code` VALUES (652800000000, '巴音郭楞蒙古自治州', 2, 650000000000); +INSERT INTO `zz_area_code` VALUES (652801000000, '库尔勒市', 3, 652800000000); +INSERT INTO `zz_area_code` VALUES (652822000000, '轮台县', 3, 652800000000); +INSERT INTO `zz_area_code` VALUES (652823000000, '尉犁县', 3, 652800000000); +INSERT INTO `zz_area_code` VALUES (652824000000, '若羌县', 3, 652800000000); +INSERT INTO `zz_area_code` VALUES (652825000000, '且末县', 3, 652800000000); +INSERT INTO `zz_area_code` VALUES (652826000000, '焉耆回族自治县', 3, 652800000000); +INSERT INTO `zz_area_code` VALUES (652827000000, '和静县', 3, 652800000000); +INSERT INTO `zz_area_code` VALUES (652828000000, '和硕县', 3, 652800000000); +INSERT INTO `zz_area_code` VALUES (652829000000, '博湖县', 3, 652800000000); +INSERT INTO `zz_area_code` VALUES (652871000000, '库尔勒经济技术开发区', 3, 652800000000); +INSERT INTO `zz_area_code` VALUES (652900000000, '阿克苏地区', 2, 650000000000); +INSERT INTO `zz_area_code` VALUES (652901000000, '阿克苏市', 3, 652900000000); +INSERT INTO `zz_area_code` VALUES (652922000000, '温宿县', 3, 652900000000); +INSERT INTO `zz_area_code` VALUES (652923000000, '库车县', 3, 652900000000); +INSERT INTO `zz_area_code` VALUES (652924000000, '沙雅县', 3, 652900000000); +INSERT INTO `zz_area_code` VALUES (652925000000, '新和县', 3, 652900000000); +INSERT INTO `zz_area_code` VALUES (652926000000, '拜城县', 3, 652900000000); +INSERT INTO `zz_area_code` VALUES (652927000000, '乌什县', 3, 652900000000); +INSERT INTO `zz_area_code` VALUES (652928000000, '阿瓦提县', 3, 652900000000); +INSERT INTO `zz_area_code` VALUES (652929000000, '柯坪县', 3, 652900000000); +INSERT INTO `zz_area_code` VALUES (653000000000, '克孜勒苏柯尔克孜自治州', 2, 650000000000); +INSERT INTO `zz_area_code` VALUES (653001000000, '阿图什市', 3, 653000000000); +INSERT INTO `zz_area_code` VALUES (653022000000, '阿克陶县', 3, 653000000000); +INSERT INTO `zz_area_code` VALUES (653023000000, '阿合奇县', 3, 653000000000); +INSERT INTO `zz_area_code` VALUES (653024000000, '乌恰县', 3, 653000000000); +INSERT INTO `zz_area_code` VALUES (653100000000, '喀什地区', 2, 650000000000); +INSERT INTO `zz_area_code` VALUES (653101000000, '喀什市', 3, 653100000000); +INSERT INTO `zz_area_code` VALUES (653121000000, '疏附县', 3, 653100000000); +INSERT INTO `zz_area_code` VALUES (653122000000, '疏勒县', 3, 653100000000); +INSERT INTO `zz_area_code` VALUES (653123000000, '英吉沙县', 3, 653100000000); +INSERT INTO `zz_area_code` VALUES (653124000000, '泽普县', 3, 653100000000); +INSERT INTO `zz_area_code` VALUES (653125000000, '莎车县', 3, 653100000000); +INSERT INTO `zz_area_code` VALUES (653126000000, '叶城县', 3, 653100000000); +INSERT INTO `zz_area_code` VALUES (653127000000, '麦盖提县', 3, 653100000000); +INSERT INTO `zz_area_code` VALUES (653128000000, '岳普湖县', 3, 653100000000); +INSERT INTO `zz_area_code` VALUES (653129000000, '伽师县', 3, 653100000000); +INSERT INTO `zz_area_code` VALUES (653130000000, '巴楚县', 3, 653100000000); +INSERT INTO `zz_area_code` VALUES (653131000000, '塔什库尔干塔吉克自治县', 3, 653100000000); +INSERT INTO `zz_area_code` VALUES (653200000000, '和田地区', 2, 650000000000); +INSERT INTO `zz_area_code` VALUES (653201000000, '和田市', 3, 653200000000); +INSERT INTO `zz_area_code` VALUES (653221000000, '和田县', 3, 653200000000); +INSERT INTO `zz_area_code` VALUES (653222000000, '墨玉县', 3, 653200000000); +INSERT INTO `zz_area_code` VALUES (653223000000, '皮山县', 3, 653200000000); +INSERT INTO `zz_area_code` VALUES (653224000000, '洛浦县', 3, 653200000000); +INSERT INTO `zz_area_code` VALUES (653225000000, '策勒县', 3, 653200000000); +INSERT INTO `zz_area_code` VALUES (653226000000, '于田县', 3, 653200000000); +INSERT INTO `zz_area_code` VALUES (653227000000, '民丰县', 3, 653200000000); +INSERT INTO `zz_area_code` VALUES (654000000000, '伊犁哈萨克自治州', 2, 650000000000); +INSERT INTO `zz_area_code` VALUES (654002000000, '伊宁市', 3, 654000000000); +INSERT INTO `zz_area_code` VALUES (654003000000, '奎屯市', 3, 654000000000); +INSERT INTO `zz_area_code` VALUES (654004000000, '霍尔果斯市', 3, 654000000000); +INSERT INTO `zz_area_code` VALUES (654021000000, '伊宁县', 3, 654000000000); +INSERT INTO `zz_area_code` VALUES (654022000000, '察布查尔锡伯自治县', 3, 654000000000); +INSERT INTO `zz_area_code` VALUES (654023000000, '霍城县', 3, 654000000000); +INSERT INTO `zz_area_code` VALUES (654024000000, '巩留县', 3, 654000000000); +INSERT INTO `zz_area_code` VALUES (654025000000, '新源县', 3, 654000000000); +INSERT INTO `zz_area_code` VALUES (654026000000, '昭苏县', 3, 654000000000); +INSERT INTO `zz_area_code` VALUES (654027000000, '特克斯县', 3, 654000000000); +INSERT INTO `zz_area_code` VALUES (654028000000, '尼勒克县', 3, 654000000000); +INSERT INTO `zz_area_code` VALUES (654200000000, '塔城地区', 2, 650000000000); +INSERT INTO `zz_area_code` VALUES (654201000000, '塔城市', 3, 654200000000); +INSERT INTO `zz_area_code` VALUES (654202000000, '乌苏市', 3, 654200000000); +INSERT INTO `zz_area_code` VALUES (654221000000, '额敏县', 3, 654200000000); +INSERT INTO `zz_area_code` VALUES (654223000000, '沙湾县', 3, 654200000000); +INSERT INTO `zz_area_code` VALUES (654224000000, '托里县', 3, 654200000000); +INSERT INTO `zz_area_code` VALUES (654225000000, '裕民县', 3, 654200000000); +INSERT INTO `zz_area_code` VALUES (654226000000, '和布克赛尔蒙古自治县', 3, 654200000000); +INSERT INTO `zz_area_code` VALUES (654300000000, '阿勒泰地区', 2, 650000000000); +INSERT INTO `zz_area_code` VALUES (654301000000, '阿勒泰市', 3, 654300000000); +INSERT INTO `zz_area_code` VALUES (654321000000, '布尔津县', 3, 654300000000); +INSERT INTO `zz_area_code` VALUES (654322000000, '富蕴县', 3, 654300000000); +INSERT INTO `zz_area_code` VALUES (654323000000, '福海县', 3, 654300000000); +INSERT INTO `zz_area_code` VALUES (654324000000, '哈巴河县', 3, 654300000000); +INSERT INTO `zz_area_code` VALUES (654325000000, '青河县', 3, 654300000000); +INSERT INTO `zz_area_code` VALUES (654326000000, '吉木乃县', 3, 654300000000); +INSERT INTO `zz_area_code` VALUES (659000000000, '自治区直辖县级行政区划', 2, 650000000000); +INSERT INTO `zz_area_code` VALUES (659001000000, '石河子市', 3, 659000000000); +INSERT INTO `zz_area_code` VALUES (659002000000, '阿拉尔市', 3, 659000000000); +INSERT INTO `zz_area_code` VALUES (659003000000, '图木舒克市', 3, 659000000000); +INSERT INTO `zz_area_code` VALUES (659004000000, '五家渠市', 3, 659000000000); +INSERT INTO `zz_area_code` VALUES (659006000000, '铁门关市', 3, 659000000000); +COMMIT; + +SET FOREIGN_KEY_CHECKS = 1; diff --git a/orange-demo-single-service/zz-resource/upload-files/app/image/Course/pictureUrl/eef356943ce74b7b809dcce178cb92d2.png b/orange-demo-single-service/zz-resource/upload-files/app/image/Course/pictureUrl/eef356943ce74b7b809dcce178cb92d2.png new file mode 100644 index 0000000000000000000000000000000000000000..8a9df82d857951b6e634e7f4639e9c6d81138ea7 GIT binary patch literal 806 zcmV+>1KIqEP)Zz)ZD2q3R09LGiiz_K2U@%#47k+NDIEYtGa1*Rndi3 z1+~qj$sR=Qkyhwz^Z|9I=l&48k&L1nPuS`#pTtif$@u- z>ro%Fp>}&RUdP)gVt%a(80(Fz!SzERw0b{0Izp=PIKQ@{tzq!|NM z3qR}P34nuMr}#9fX1{-It(ar1i~9ghcmRkmQp~(nXqK)B7^g%(7^l4LLl@0Bp6|rz%RgxlKSpb5K$f$#}UEx1h7Ie!UTX4eVdLD>XF z-+wF@DiBz%t>K3N9V>F+B$(SsGv#tX1qRE(i6j7Z-ob<^WZ4e7dpMWP7x)tAba)Lc zN`tY>b?P)2ZKTOe*(5%Jz+jGR8L=7v@C-l`>`XD8C)Iel+)yR8(tS7&hqqJQ{9Fm3 kyk<#`RT9LnU9({S0n9-0A0sFb;{X5v07*qoM6N<$f(311>;M1& literal 0 HcmV?d00001 diff --git a/orange-demo-single-web/.browserslistrc b/orange-demo-single-web/.browserslistrc new file mode 100644 index 00000000..d6471a38 --- /dev/null +++ b/orange-demo-single-web/.browserslistrc @@ -0,0 +1,2 @@ +> 1% +last 2 versions diff --git a/orange-demo-single-web/.editorconfig b/orange-demo-single-web/.editorconfig new file mode 100644 index 00000000..7053c49a --- /dev/null +++ b/orange-demo-single-web/.editorconfig @@ -0,0 +1,5 @@ +[*.{js,jsx,ts,tsx,vue}] +indent_style = space +indent_size = 2 +trim_trailing_whitespace = true +insert_final_newline = true diff --git a/orange-demo-single-web/.eslintrc.js b/orange-demo-single-web/.eslintrc.js new file mode 100644 index 00000000..f62621ce --- /dev/null +++ b/orange-demo-single-web/.eslintrc.js @@ -0,0 +1,40 @@ +module.exports = { + root: true, + env: { + node: true + }, + 'extends': [ + 'plugin:vue/essential', + '@vue/standard' + ], + parserOptions: { + parser: 'babel-eslint' + }, + rules: { + 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off', + 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off', + 'semi': ['off', 'always'], + 'prefer-promise-reject-errors': ['error', { 'allowEmptyReject': true }], + 'no-trailing-spaces': ['error', { 'skipBlankLines': true }], + 'prefer-const': ['off'], + 'quote-props': ['off'], + 'object-curly-spacing': ['off'], + 'dot-notation': ['off'], + 'lines-between-class-members': ['off'], + // 'no-undef': ['off', 'always'], + // 'no-unused-vars': ['off', 'always'], + 'no-new-func': ['off', 'always'], + 'no-console': ['off'] + }, + overrides: [ + { + files: [ + '**/__tests__/*.{j,t}s?(x)', + '**/tests/unit/**/*.spec.{j,t}s?(x)' + ], + env: { + jest: true + } + } + ] +} diff --git a/orange-demo-single-web/.gitignore b/orange-demo-single-web/.gitignore new file mode 100644 index 00000000..a0dddc6f --- /dev/null +++ b/orange-demo-single-web/.gitignore @@ -0,0 +1,21 @@ +.DS_Store +node_modules +/dist + +# local env files +.env.local +.env.*.local + +# Log files +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Editor directories and files +.idea +.vscode +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/orange-demo-single-web/README.md b/orange-demo-single-web/README.md new file mode 100644 index 00000000..3b5fbf8e --- /dev/null +++ b/orange-demo-single-web/README.md @@ -0,0 +1,15 @@ +## 橙单代码生成器 +### 构建命令 +``` bash +# install dependencies +npm install + +# serve with hot reload at localhost:8080 +npm run dev + +# build for production with minification +npm run build + +# run all tests +npm test +``` diff --git a/orange-demo-single-web/babel.config.js b/orange-demo-single-web/babel.config.js new file mode 100644 index 00000000..e9558405 --- /dev/null +++ b/orange-demo-single-web/babel.config.js @@ -0,0 +1,5 @@ +module.exports = { + presets: [ + '@vue/cli-plugin-babel/preset' + ] +} diff --git a/orange-demo-single-web/jest.config.js b/orange-demo-single-web/jest.config.js new file mode 100644 index 00000000..0f957914 --- /dev/null +++ b/orange-demo-single-web/jest.config.js @@ -0,0 +1,3 @@ +module.exports = { + preset: '@vue/cli-plugin-unit-jest' +} diff --git a/orange-demo-single-web/package.json b/orange-demo-single-web/package.json new file mode 100644 index 00000000..1fcb6289 --- /dev/null +++ b/orange-demo-single-web/package.json @@ -0,0 +1,61 @@ +{ + "name": "orange-single-page-project", + "version": "1.0.0", + "private": true, + "scripts": { + "serve": "vue-cli-service serve", + "dev": "vue-cli-service serve", + "build": "vue-cli-service build", + "test:unit": "vue-cli-service test:unit", + "lint": "vue-cli-service lint" + }, + "dependencies": { + "axios": "^0.18.0", + "echarts": "^4.2.1", + "element-ui": "^2.13.0", + "jquery": "^3.3.1", + "jsencrypt": "^3.0.0-rc.1", + "json-bigint": "^0.3.0", + "layui-layer": "^1.0.9", + "lodash": "^4.17.5", + "core-js": "^3.6.4", + "register-service-worker": "^1.6.2", + "sortablejs": "^1.7.0", + "v-charts": "^1.19.0", + "vue": "^2.6.11", + "vue-router": "^3.1.5", + "vuex": "^3.1.2", + "wangeditor": "^3.1.1" + }, + "devDependencies": { + "@vue/cli-plugin-babel": "~4.2.0", + "@vue/cli-plugin-eslint": "~4.2.0", + "@vue/cli-plugin-pwa": "~4.2.0", + "@vue/cli-plugin-router": "~4.2.0", + "@vue/cli-plugin-unit-jest": "~4.2.0", + "@vue/cli-plugin-vuex": "~4.2.0", + "@vue/cli-service": "~4.2.0", + "@vue/eslint-config-standard": "^5.1.0", + "@vue/test-utils": "1.0.0-beta.31", + "babel-eslint": "^10.0.3", + "eslint": "^6.7.2", + "eslint-plugin-import": "^2.20.1", + "eslint-plugin-node": "^11.0.0", + "eslint-plugin-promise": "^4.2.1", + "eslint-plugin-standard": "^4.0.0", + "eslint-plugin-vue": "^6.1.2", + "lint-staged": "^9.5.0", + "node-sass": "^4.13.1", + "sass-loader": "^7.3.1", + "vue-template-compiler": "^2.6.11" + }, + "gitHooks": { + "pre-commit": "lint-staged" + }, + "lint-staged": { + "*.{js,jsx,vue}": [ + "vue-cli-service lint", + "git add" + ] + } +} diff --git a/orange-demo-single-web/public/favicon.ico b/orange-demo-single-web/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/orange-demo-single-web/public/img/icons/android-chrome-192x192.png b/orange-demo-single-web/public/img/icons/android-chrome-192x192.png new file mode 100644 index 0000000000000000000000000000000000000000..b02aa64d97167ad649e496908b35f14c603d9249 GIT binary patch literal 9416 zcmaiaXIK+m6y}7Elz=p)MnHo|M?q?+0v{qpLa)*lLYEGqqjV4i=}jOYT}nWZqF?|) zgh-1tgLI@XT{CZOOrNn4PA94gdt+0swRr0GxtN=oJ9)6$5}Z8vu~a z0suCTT&%u4c!A=HwuTyT`R`r$p*$UIq4d$xQKwvhFj3OT{OH^VTlieG)RYbVr#JIl z(mDIH=Ppe(jQxytM}R(c{bw&opbQ^vZuTtH3D0=B_H|CF-g$>FWnM_E<8xJ;6x|$I z5G`a2B~ocHl=45jx%nT5vR43_%##6zzVX(HLh_o0w@uPo%~p-v-(oDb3R6|P%IEF4 z#wIQfyvY8F!v*IL!3%yDDE;^Uec_bR`)5#5OYHbjmxA;8`ENvd^-LYxm>)hTiEF%U zkN$D_^9{A1x73rnLs#ZZ%a11T;`K@VTo(k}RlVtj?cvL>fxM;LcX~c<-x(7x`pVDM zc{OYct-^Hikf}3ECxUyMMsv<| zf+5!5j#w_e_d*z9^^%|Ht-CMXFE${zR!096`Z0Aze9fEWr}|K9QwaZ1^~WBd|8Z8V z8EP!@Bwgvs--tSLM##X-93mjI^{%RgAmi(oeI>jCWazZd{W@fJ*K1Z>Fg%) z*4xn<5M$Q*0RH%LVB<3zd)|M*sP=1-R8QTAD2HS!B@!5EiXUxo?{m*wfcM7589&n@ z$ygP6irp0@_%d_lrF~Sy#}X3HN=*yFtFbTpWKUO5E%xS4?!uLWNuuQL+VKot=;~g* zC_QORR7Q9{Rspt6SeF|hW}YUK5?9a+5NUhH%MzF!lkhsn=*IY$ea%5V$N-?{!_n_Y zcP_fN@MLsZ>*#8BT48Q>j2NG8jkFohb{L;B8zf@s19ZOY2KFv*oDRB9n}z*SA$_W% z>se>krL-Xo9-hf%TffAoA;Dl>5D{V*+g&c5Khq1nOB!aGvJ<8f!n#GjJyxb|XMW{g zb(sGj?LU-ZtV&jrf9ytjp$zw2(<6bg^~W#`31{KDDP?(VKKRo!D<91yKbWm1F^X0j`%4J-3w1y22K9zf$MZa-{{e4%mk z;9`r1Y|z~HuUH|VudeyK9Fl4Y4dQ>>!BdB){T7ir5o) zB)NVqRY?{>SNu|l&XB2l*J%8#Jq*UZd5Ve>>52qkZ5k884j(Rp^jfQVt}v%qeN{bo zOmcyni(CZv!`K#r!iCJN3SDd;tdgr}7aUI`XkcA-De;-{2q*jvW`?fp$bGN;_-^PG zW7FD8#iI&rH1`87=d*9lv>7CY(QSDnpD+p|r)>am9WoZ}l2ZM#y7BfWeL^Y1TYl&x zPt~*lQgjr+CheE00LQdH+H~A;x$wa>B&}MK_RDHr^1+^I`&vAE5 zH^fGpr9CaI;*!s^vio#F39|D^sP8-Z+hGrj;IJ9kCAYpPL$xG%!T?R5ROj$t(=;4N0K zlW+S?iwOe8{x0(?oAS%6a-x9!GpUfOt$Ak9B5ogKhWJ;m?u`Hgc&=Q`)V|wVm}2@P zm^$^?$)f+?pTI!-vaoMaFlC}AO&INra{&NM=Wylv%O>(jK&}B#`*sA^R8B&=cb}Ug z_yu5`sWmZ3dV!uQ!{%AB)?9{g?GSXv`F@3z+P zAyJc8@-Rvt53m)rxfiNMr^KT4UT;kC>a(v*cqq-4ln$zsp1Uw{+IWKwL#aQ~%zBIm zBnzcYAFf)TIRW;!3p44?6E$|OHd4N(`bF~{7NFRZ|71A8K){8kNc_>aU4T{ABTcEH&nS(WU0FZ+)RVtJTFZ&>bl2qQ=54MsACbrcmU%yF{&Q&WJ8gqB3F#;0-7IGQj*Rbg z3%dW(UbN15y1Hv~!Fi$>QO5k;m75hNbC@rkVA!m^*72Mrap%SJbspLaslGqfPpkmv zBQjn<%R?YsNod`Fi-e4~aSJd=QCb)2@J%mcyH7OOZA$6BTAcTD<2bZKNu^U)k^uQQ zzQ=wd+534W?nAp4Z{8ghS;{UB@rp z7mg;eH;eH}a+9Av_%n^-LPQ}Ti`qq@y~R7FeXxz}nRiREHL*Xk6>K~%B!;ynzx%X| zNAI5Xm9R8Pb#;%yxlgo)#x|ua7Oh}ez`Hn{0@;tO{cYU^Gjq8}hn(hn7TyvdMZs<#RPf&O(+W^S`hK9Jl{AD)hkda8T{xw_^ zHq5%9SQ%+#c`F@F5{*$0lg;QhewpRZyj`TP%6VE}n&^)A@vMIOtw3rGnk7#Q=7L7` zF8WB)bx{}m4-gq-Wz8=Krn@*Sg`fA*^jRC2o4jf@1Z>RU4UG&`9Cuhy_Esbhp+6-f z9ZdG4wCha=3Zs4{^l7H2ru>H5tOd}8ImjN1UyD&7PPu5-?$#f|lgin)o^3nkb3hs1 zU-&k~Dg z-6!Q|#o7bEd^qMLIL}LW=59gBqu7oGy@%wbYknIG9x)J(DNGAev%(NvwZF;Y+~RuE zK{vUG$x<<9!|_~s+x`WcPU1_l8l38KQo6n%_a>a@hKvw!O}z}8Rp!R;iZ zP{-zJo1B*Ix8}NXZT)H!{~QBOxuFoY2bk%>r&?#sd5sEk%V$0%+lfe(e1?=)aQlE) zxCken!LMG7tiqawER;WQwbuz8{3)hvsK%M78yYaiiG=I|Z=2VC>C)1K(SU%r`kv&M zx4KnNekRuB0(q$AMlZb1LmxzeM~Kgra|C7o%zG4<6Kl8jXk{gfjVdVeIOfsSb<`)>?6622$sYI3>yQ+x*$LUfve5+91)bZ+X-)EI zT5E#a)5e&~KEp*d{*=p4j41v`eb{!R^QUJGCf@i_+yS)zqIa-B!KGpA%b3p>rYp}T zw4V%n&PKedPZn@T*Rg$Nci6yd&y{{`mL_6MacC$MKN+O57Zd zZ*Q5=S}*S&Gb$8$d3GL&(@~S|MA9-ICP=XpjU}hnP#HUsfwB zg8W_IWHhw0dg3?Z`->OloxKC!l6y$`qt$x@R3^?1PBJ^}emdey>fxDRS(M*q$Easu z)Gu*fJ351(q^nr}-Zt6YPlLWKL@NZzAVw_v^k>Eh>p1{u$`$QyJq@i_}w&}zBhZV{y}FA&aLatrk6I<%+?nPzXUOX2HbI~&(=B)^BY`*c(FS=27Vl?!nsQ(G5bat<~6g!u6red z{pp|oPA>dHMT=#-Ejfm^d9ei<`f(ij*mGa2{jq_@!hlElFuNMa_L&2a3n_q zTXxTFzrDBt>>>~(JIRw)cPCwwR#7b5u3db{jeh63<0Scw>`^Yeq8y9`of6WtO7zaN z16`#6f4X3T_dTimZPvo$+?eVKgg$<4Fb;p5#Q&p<=Yb;RR4=2d_=cTj)(=I-XJ30g zF7%yfD(2sa+0{-A9 ztzXDvW1m*Edlqjzm*{GC%s4hb;VPUsv>IwrYHpVRkY5O#AXvc5gxh~){-C71$*?! zFxSW*jT317Nj6gnS@B=)_rYbQ6YcX}mhQGwGLEF8(k;OL;_ zeF$)BJNnBjL~i7zvZbJPFVzGg#&(R_gT}i|HS>z<%b&7@=5i;hae_p! zd}QeibUf`j`3Hw#_-8ehWYP*;QIVh@cT~tpso2fPHCH6@ke0mk2TjUIeVfib`kjhO zk<74+5VJG(FR#ruObKq+Zn?1sR^fy*x_&)CinKB(G5P-Lq^@e;u{{s*Z7JJ*eJv6@ zBld9PPo=8K-D7TKhWCdzz7o>f>OIT1_C5Iac;_3C85|wo(B}jf&AA0tf=->nI}i8Y z4IOqjE8BJMZcO2&DE=}gQIQkV^^su0JsEnCCyH!a3O3X^h$89n>;xCWaZm+bd9;SI zt)G8!^hXV@6kF$92p`9~_Wocxh1YM%=lR4oeG}kLb&Q{7PWDmX-PT+x8_=kh(*+|; z7j#LAn@Op@2r<)jsMu)X2A}Q#G#+o+k93$)EY2mWAZrAAXPTA#?u!)AjuSfjQ?WCu zfBjB~aafM;bxxdk(yG^(S!CrCVKGz*loI1*xnMvTHq+CdM)F%f6_@aBv9(DHmr23o z!Y1)MLej+arq4#m8jdlJ$0=XM*k%FXAG)#|h2DGbfb9+R?UwJgrGd`bN%k#X`ahE zrRToVHBh>r9X;?x9S>AAShc5x7?`VgHUAy}y(xT^OjDpB!70A^QQYtM$)DcrWjO>z zW~Sv*1vC%zJ3hXZ;uH^)dDN4C?{~dyZAii)(_FKlDEi$2C0E6PRxiJp+n545DDu`##O z6T73~IM|VDT{)}nv_3NYS(;Xwsjxrh{s7b1!nc>$!Vp;2mN(vwf?QL7cY^iSR5}SP zFNfmxZt7cM@Pe=M8NmIn(BWW-(rVTvu-N|p^=4n9S%YZgKiZ= zm-vlJWsnODC7(2z{66ESx)ou8trzx!au_g zCJ#MI)(z!Pd6o_0s@o52xro#RLDns}?Ml#RTa--t%2n1xTy?u4jQifuKNc88uryZ& zBirV&|Hx-OMJ)iV41i>By?;N)E-0h2)=$)_dDx+8ZuuHp>mq8E>0=`$kcK4k+J2kG zgjxrDO~uS+i&x;t*HBK!`hJh|IevImord@z_7}aDIAUg~N7a!c^3*o-jbfY>?3U7==iX7Zes1Ox%{>rJxuV8k9V z@0y};oI0ReI2@Y(RV0-!vIVj{)h^p)-xDFr6x zNNCvO*9(4gBegZZ9@%2Hq-f6^NkE&i^_3ieDM}LrN|Tm=5%oLO@orDze1B^dm4=Y1 ziM*eGKya&YvLm3CSM(IA`v&3bHS5bazbL*TY9LYlTe`?3lEoI}z+B$K&5hM%W5KTB z+7;{Ko30#D3UnSOAgLLm>}S|-bu9@-3Yy=3-e10VMz+Fy1IkBZiZFAc6LT6LF%ro4MlRb(@_t#}D$; zeMw_V%bT4KUEH)xmmVUw3?G6^@45YToPd97+@Q<1hO&4XL_gS>2T)rTmZU|Q{m!CI5Tvg(su~c z0I)ofW9&unE1BsNB5saoRAp^j@NdbT2Y`5BC2kdz{%`tHF%}+)jP5@~wH(em!7^sd zPur0Yg+HWO=DoJ7MS?$YOkS11$GRjZQI8TqrvQee+bQ==&(79R?XM+A5-HgEDK%*dZyhZd(Bu zT_#T}HH;XP;_n8Tq~R842HEliQH>XtD-=TZognmcDpX@^v)p;)FhL`fKI(vyet--( z6)a$eXc|n^&)$}C8WE`7(^LFH&TO@%e*guSBY6MAu%`uQ=}o;XE8A~(u7c<(4?}LU zOo)1KupG*Ja9)D~w0epzpiU-vpX@NQ$H3}9y;D*4Ke>tlm@~j)PKYt+Zj=+G`?5D` zmS5wf%PiML)?*qTOuygycgi@thwuP{?7j!y9fp*7{ZG)+$XDR%(UVpVPfQOK@ZS9W7l=~pbcx1R5dw(y&y>mSX+=FyMPibx`RwB&T`6N053 zVOfjs+SVIz$JGiVFJWK@0L+Gg1J#sANm`(2%!}ZcHYC!QDmzE^fRZ(=RP_^Lz3cVm52|oaoet<69Tp=*Y4P)$I z1pDMNyk?J9-(8so$dtEHJZ~enT_W9I~kYCCff4&hL(WyTx$-2U$^&2ub&_rhl>RdfcW%vVw~Cva7>ni;y$lYB z*OW-*O<_I1nWNWc32CZJ5VW!(QJ{#V-d{h1gJN;)jco0Qa@T9|nw{f|deI6?oJP=5 z9pod*!rwfGTlW7tMGS!`aiL74pMG~4t`9nZDiMONvHj-UED+6al8?$C$}3MxaUyJe z09k?24ya2FK7~fCe3lMg@m-PXOjUeB0AhTqu2(=tGo0R2;>`X&9u0Bkx?Ry=bZHo1 z6ok$sA`IIu{(1<&KLVg%fzZl}&qdhOgvq2H1=fV%FezIve#aj90{J zU_S5FGjc^k;%T`5_*X;)n93^xDG3h4P)ks|6zv1zpt$;8qxI%qKep&EuM0jGTgb%@ z(w|8-RyPaUYC%6>A~YV_H3d$zFm^;k8~ga*+0?~jopT?W~MU{S6fO zlDH0%r6N#G#;777*jKtSa3vOIteIe#z_l%kbtyj;v01wJh8IB7rc{43Y3*bqj~V^J zRRJ3SDKnFo)_9oU6(fg~xgvVhdK%m=~RY@3Rlz8lc4;YBAAA{Bg=iA_6UT=e}B+ruA#^L7f{a^>v0A?w@zZ>;sp@`686n0E53@b0Su z3j5Qft7I#Yp@VSs-hoDLRKWZ~m71!)dZ~@3#2|x@{vFHmdq2sX z&%DJPbNs$7KC6;ICFQkT6vivm#HY04NJzJ|J{qeIT8ns2n&&Y5 zz3w-arou<=)duF5|ClpBb4&nlP?0rKX3_t2{Kqsg2E^C2y^yi8k$?UE_<(h-Woja~ zQRi1zcI*8!8qg?gZLt}(-}1N9G3|+2J|witV6g#j5Lf)~k=m6|dR=3(UQ5weO;BZh zWuMi5ox**n@A8L$y!wS#v-wJqpvD4NDhR6;$*8>%u#}T2law`1nviMLqHC4v6IA&f zs*U|HuIH!i?w!j3S{)LC!M&hE%KQku5u|9PsAciABA#ds>c`FpUY)uiW27*EikbbZ z1Z2A7+VPvmQ1IK$R~+e=a~B-W7{dIO3Q$|rSCPl$z`fW;1q%3^TO{wboP`m&yji}r z2ZJ`r0{38rS|h55nC^QViA^(~*mh`6NRHqcaJ|k$G&%@UlH6sY4d(df6YDdd{BOD` zS!^qrqGa8Fq=wkM+2XX{FK*^t3M2D$j+qK04kh~U&Uilr_o@#p(WM?j_m0$EoI&g8T!~qy_8m~pZ$iwnUX}w zD~myTA`!6Qm$@}(a5Y)TEj8DxQC*Z#kE_0SBW{2rl~vMVunw}PY4jIgQXc^i`rxXv zD~}ESU#|z{D=5?K;rCPZc5 zvhQWdz7J#OJnzxx`}}^_^A|jIbq#0EIm0>cbKkG+F3i|admqa|76^j&>FQ`)f*>UL z5(zOgf|qsQ?j7(#?{vZ70t9`GVBNjW0KON#sdLEyg8U^R2pb?X&k}L#Cq1SJgX9dJUMkWE|~fb zEKvHR4p{~Ykpd&+Kl<5=e?sQw_PgHEF-3@0<+weod@cR@wU*c`t_NL8g2S$oNv;o< zt|s}V!8b-WRE>O6EqV-!bzg?sAHZ7~vl?57z3Ss4zfL%k_r!hryvEtiy1H|s+~1#a zb5besUr$z9XdI4cX2wiU6BvX=|NrvmZ8BFCg%7vgWV^UCDq+O~ZxE`zr%P;i|wi2S_WNa(!*%gh-ltu9F>a^9=Q7}dNI$D{wGd2*x0HkT7(c70xx z5;RLLzTBSXl3z|xT4qgK)p|yC{)ovKvCvpMHn)#QvL*sn8KRetT}e0qC;!}Oo|rz+ zQewgs!|^!HIw8%nZIoVYM5jaOAvuDVTp9Ni>d4m(ZGY{a%7HDSNNu-Opp0eyDCntg zI+?F>)HNa$BeYUTboMyMEH`9$IIOeVl1Ya?g@gN&L?c6))eZ-BYce0cbW2SQ`;#ho zarK3w%lNR|Bl0!uq+WGIX0(dCI4by3tvugy(XF=#;wY87o{FoTfw$rayIEtBc9mK~ zyBSF}2%@uJ&i!j&j?uGm4noXdrHM5x66?K9?SXmu{u0lPZsW{RB3bxgjyK&LSiYd{ zGVI@4jPF#({dG)<=!!P7O+X#DF_t#%o;lLd2_L(^U<(z)aXQ#cLJ;X)A`gPzfxCL+ zNc$wkG3|Re?%jR06@oRxuDjYrK8oOzIMUW$8!c2B90{ZGu(!_^@i7f4$W6%z)hkwUk&M_=(GbZXwSK_RszBXEa` z)y_1>g!8)l%Czdk0e7?XhuM$p3R)sQpjZR8F{%sCB5aS2v(5*BEN=PAu_KaUws@x}V{el(3ooOp;IKVS=LDahDTjMx7_x zq7X%MLyDQvESv%nrAG-CSjRfQyC!Gg14(5&b94+cymj@0~B2qAsbiQCT3 zi5tEAZbH)To|gDAZA=6beAa4-9Q8ZP&Vr*M?N{RHz4ft|Yl~aWpZ8`?zM{9+k>J!ln+)j~lf|AbC#kGqk_*eSCtY2tIk1 z@=bxtIs@PSnY5p($o%_gkE@OELAx*3k1bC5a+v5Z?OchKyOa8D`G*ky$8&=B$vWg$ zx85yyH(g8OG=y}0*wtHcq*FJb&v)H) zsPiV6KO6@)!=%$L^~P$8Vz5YHllQU$%Cv}^!A@)v2y02}u9HZvdQz2lP zWXFnJJjgEmOyCo_?0!ql7YatZj81En{M$`r8%~}N<%O6P<-H1e8b(p_rDnDPA9S&> zw?M;|Yz-=#xb|DfeY2kZRSGLHnE3FN=!*MHKkR6<+rIIea0#4W3NcCMU3ZV$uE>aA zRvWasvzsy%BFDAm52;a$3oaGxBiGM5gEy$4_*1af`XEUP~g)j2rmvY6o+IsfT&JeRy z>h@+dQzkItr8_dzZTD6FG{Xur)@yAG`uq`Nvyu4Fd})W>l)y||wK|*)D-t8#?}+Tb zBTgOKMR;3s5~YdH2OSy-qWI3x$CzchZ86#{MxtNJUr?zn#`LUzfYbe3&OaZ2;2FS; zR;&_t>lVZN(hJuhX70cq%`ZkWI{nFPO~?b!N1~sw1Y9;u)Oa&D;gk|+X?Kz(az`3( z^E0O%hroX1e%f0p7s$B%g)Ct3h`v;v;m9e+APr+H_p}qr{t?jWz6$w9WyB9=?4}rA zLuk!}6F;(vYe$S(Ya{XUDH{{vwKY5&X^f7RjqKELeF){qi`4oL5J=!Zm$eJNChKVEOP$g6; z8hOXHY~|xrsCBMw^3^Cj)jy$X{pgD7Hk07F6)}5lL_Ei5?FTx$$KBTJBUFv3L4TFx zRZ%mTqI5zlxa*3_L&fHTLeH_EPJBk(jXXkaQ>D-y6~sqNV*|J&o9SkdGtdmLke3^u zkk@%8oMw0D*J-cIq7u0aM*_z$dN9|SK$3Jd$)(HiS{LE?w>RGGgh;O2n##I#+nTw2 zQ4fkq>1%!~7p70$*s@{6z(%sLUMe+cr2yY`5jkmscV_BDv={tZFk1hFv)#yxcI9f{ z&u5p9zU*@_z?Ryo#fJ+Ye}?bQ#A+dm9g?XTQ80E223zOJt3IHjkE4hdmXEyS4`}7i z-hl(l+;ES+CgDmEIwQM{;A6t~VQ*)1z^oH3_)B7l(1r7Iqb@00(hqy&%|`^5WG*}i zDXY9}=Y4HE%3HYRMT*DQWbWmO&K*jl5u63K4B!7_^a&O)ct&4(k@&iT*3U>Xy|>n@F6#_`kw4aLDSedr_Ndq z_uKbZvipv*>U%TWTaNLI{iHG)QlX31*LGd_Czx`3zbvzP3#1$X$656X+KPD)G`(kV z!rStCQi?0vx#d_*jKXgx0^)&v7M=B>jI0CBk5s%uN)yBG)`bkM`)(!| zVJEEBxcM%gO}#Pw;&dr@#21)Ko_H=_V_ZF-fR3X*RH>%lqf~O#s73)cMJvd_LphAD0ea^QrY-ve-WC;(VY--YzvP z7txR6IKQ~Esc`+$gwoOamS;gK{HfoS6l0@I@ZDWFuSw-1?oD~RqSP}JX(}Ifaric> zR4Z5#A1__54j=0B|Jtw`(!##}X^UA!3Z7XPx`Uj^!d3Zi!n;dC<@gg0K`z6HDyTA~ zad@Niacg#@>Vsohh^Z>2rw-r)P*GelpPr{}sd><=nBaXivAZ1tPlg8``N(huG-1Pvy5qEsVeG1<-EL0VFc8$4|TAQ z-r_!4A!DH+FYvIZ0dfM5TBC15W`EuK^L`%_%=j1;)WIk`K#vyTNC?BZaMEfuZj!tj zO?zq)@lvtrhsT00D1qax?~^avkM3@DuS>OjI0YRAzsloBuUmr7YIQv@uj$#*3GTd1 zxiOVO^*%6gq7@a79QOEwyS+W}K&Oz|&T=fhv@wh>0hYB5Xan2ntvmE%=}T`)%($17 zzrH0JZL@7YCzdgLu5OdU^H>m{AB3r5p=jHPe~&sPEq$B?+YPBMj~G-{rZx5I_^mtdoD`;w%M&1>N zB<-!fa;x!MTc(D|#tra$ls=XW=PnDNFt&<@6?v6E{IuNchyR*M@KDA<4=@xu`75($ zaz%yD$QH4t-z*rI4u9vPH~T!;~lI-V4lycw6U4U5{$@J8w|(}yY}~@99kJOV4h_xfTH?<_F2cYPK|F9%O zc@Dsmlrn%NNjk<#oZoH!n6HUdFSrXo>@zB!HR917^#qqJ@XOcEW5`Y}qzY6SBltpZ zN^7b3QE$BHV0F!l%S!3Qwmw}}^#Fh?xx=O%f__Y4S#5daO*WOg*R_!jgI|rn+NMFj zEA4j46Zw&rc5dr(SKJikM7#^@?@o;B#Ze@x@7{b7eg@(4=iG`*P$lyl*T6oH2(y=Z z*P`F;9P5Ja{J`J#WlpQyKK@tQvQ_#OD;sRt8VXU}b8 zkO7+*6E5^f=}rRt$UQJdQTevawE+^bw3^JnxFw{CI5|hPU0-MaVoxueA%i}`pySOv zkDQ5Kyzj;%bf0gs>rUz{vf+or(_>9YDT9mMR$xg-O+el|$oTJ9PTEGrxgsSl|+Z#@X#P84Wn!Y@d9y>;^JC_IUF3VG} z)DL?ljK481{qWJdlZEjkD?%0<1tt8WOE~-bWzFh!M%r(3>r&(=1b`fgNsD`UGm}jc zK6&}wOx+k7!zO9?w*CG}m!YtYwzuV&s3iSMz1`#9$QA$IZ$=^}#(-Bg7{K$9C#4I^ z+v1ZJ#q2TUts+m%!`Wg&CZ!pAt_@8j;hTere{(5WE)QIz9>%zcqn`ftwiK=l;^w1Y zT`*w6Jz94OVm0Ia{JfYj-9d$}2a8nbV0H?KJKrvcVeV41fW$DcytBWy2O zuiDz%o`P<^WANv1X7H^+wI|!<-7BFjVxPB#iZ3J)lT3grcvy|`F!x5mt()~M-U1Bq zjRr(HGKCM~xnq?7Id#|PAIQYz(SyB5r=Nvky^kv=3Aq>+g^a($bd-SJMJNozc|_$R z^jc9mZbwKmZ;e&rAp#T$D1*UWgfh~4$O+>utipP|^}wznXGqP38%WmOFViRxeADF(GFd?xAR%1hw^ot@Zg`YdPF`EEy(ooEQ zfVzcX3VLsB*#OBRxcEiNGW>x|S?Zk?>YHXJ#-Bm_2qsR~J$lAo<@1caGA)RZc*_O9 zGIDb8kzr7D(EwPgF%#&{45;IUrwum}{BSu!--)xMF%x&IY&V_W+sv!oBrjQtJ_pD0 z3VFNT^zAb`x#DiSLy0)~LmRT(hTeN3b3uEoUKmYk_jgtXT>0en{JZGyilmy|loxVT z{>R_}Hy~b>pm!9fesia)IN+}Beq3rA1!Xrx3cBfl8W1tx$$3{!dC*fyIjXfq78;bk zO_(PGj4y)rXN#QQx4g@MKDZdQn)1tq^P)Q!-^D7YFLfR1mv49hH2Fy$ph<0nWdy>J zIwcgPzx(_N{2Y3A$2Op9?q}Lf{Yy!vzeI(U+AQF9hJyRHP@QB-V-l53 z6WS!Nv+JK1j*exIJS)eK?X@Z+oVx9Ezt;7wiMa4Fe}ZPt38Ss#ZBRzO#y*DeDHkrR zmO0_6L_uBVov$@+NS^IN9RF_>+a7R%>D{`vm#fU@0S*Tb8VsXhAQ0 z(~y|6Kj<2ivbwN&Ydp*|@Y3AdYbVQ%_B$A|Bq<6^+y(TV&JH#CfUddnl@g37>b|?I zATaUtZ-|^C>S;0KTK7r2*1E!$8^={WTCcd3|J7OAN}DH@7gDI&30j6TImN^yualso zgFTfGtvnw&UA7Q(c!l@Qr>DravZR6P1bczz%JbL+Z+{*_gO~bQAsu=0ad53pPi%n# zHELRThJC#}xBcbEinv>e+^TuM7P=zany3@XFo~G#SHYXT0BAMi1ieC*Om0!|n}!YfCo%@(5s{gldGNzIo^9S}eg(+Qy}dR1qzm z2NrM?{eph-AMx5wN~;tQgRa>tQ*;e>=p+F|dABup;=>u^Qc#>ktAKno7>YAXG46)YHEyo`FXB4UfC;Z#-~ELvbB7!ZVM&Vkj_uJT8;Gu!UnbhqW}&L zQ3)NH%N@hb9B;gUz#}9eyChIdrWl=Dk#`%IuKX=2EX%U2D$;J{3P9lI2SdLXJdO5m z-?OL(G=lbtiat@PiH6Ed@X=kkTTQm8=sQdplzM=6kCo@+A5{u}&xH%$_ULky^j`s=*0pw=5ruil~Cwb;UGBgv(l0YGFXljNaT{l+hWg0=LVa0C&H{bpcp)Ih?k@*H0W`08J%! z=~FL|Qfv)eQ=-3eppAa@8QZhiKcy=GTvpcuszU{p#InWfQw4Q)*D@{KHkMfhCh)ZN zcWOED=(on~M?ezp2r-~{5W3i&(i8rcI%olwIomkuaw@wVL82RhWYCHy@+?&8-#D5-bo-$=vj6gmTE{8WjJrj+}pvxyutrU)jl>>3*^4+}CmR#+&^6I$9sLI?h?B+3LYoXc0IPS-7 zRP7Bi)4OC6U-nK*f;neo0*6IK|L5BPcOA9yTnu~5IN5zt)v7DxQbpH*si1D|Zc$x$QOqFMk!D<$fxRq;L z4perN;nv0uzqKm`q$1A`UIb6>ehRhAjS6)S?;VxVo=GH`YsuVbKillBwGIcsYrhlj%hlX~N5|q^&auc|l&yvRfX0)ejjj?Hub(dvK#_lf;Y(en*_IB)Ld& zj6O;%CVr$)Rf0(70Kk?1Q(DAA0*&^&)%3jXlrJndO0r(OX_vl;xkJZ+_2{?ll+l3j zUzv%Y4X`*vVlE{HptxMVR3I0c9d3Bg#HMa|f#bWf^5I<+V-j7~ITol0V**${4Fk<6 zQ?{doBi(ZYQ+QM5?7ozF&Te6 z=TZFUI}ma2vJHy^P1%qkMCb^lSkrIHRWom1==RXUcVb8lGb?{_*Y#%6u6)@_#NRFq zT7?t;`FAqDG?++D##VW9e~j#P|l5Pc`OeD|1s7f?H>ld z>!Y%aG>OIO`qPYD+ceq@|4Zm4a$Wrcq(jy};5?wiJzunbPoX-6tTIE9mc0BAUq~JP z78T(o^2W6~z2`yM7twtM`8#J<_45u!7C_@sM=~I8-iu%4LM-z5KR+L5kAHZSbx5<{ zmXq@8+b_UeEqh~Nqje#$V1b18RrM>9wFkgN%c`Q4X|1LQ!70TA-W|c9(l?lk?ba=K~2bH%l!B=g3sP?WL{^eI~C;5`Y zdgnu*r%_p2||vm2)ByFc*xZyD44krPNXLybJ#@$ND1#d!&+s#DG7i&Bn&{}Q}p42yz9Fm$_GcHe(r%jqYb6s zDJwu-F?lJTg3OrviE-VYr~>MWZ+|h-UUboT3fIIpx=^{=){c|GMu{R8oPm|pTxe<# z+?hAzl5*IfhH~lIO-M3Ss7JzqG|=3$#p+(=5D82 znEM58zNWKBZZ3DfvT|2FCURH5e{`(~ga7&NcwqK$6zr~p-u4DQ6t3;j_8^nRW;U?8 zHaq_mu(JwQ-)EDgmVJz(i#$M0s{pGzgA)&kvB@V-MOpN=bo%9*E-Tsd-Zkdc)FB0i z=F3V?Pa4TYNva>Zb(U1YZc=BMWJgzLg0CJr_gZjaW(h#F9gebhkJFkso|xLg06a<0 z0r?05yc9SiDTPfwR`=PIDPfD+9WQV>^X|OvRARUrbVEymelv2OL%QSR-%XbmRBEn` zFSwv8=8syPVlR&~t!{xraoN6{`Q^xTf+vy-+ypNIjQb1TFthbJGP7sld59InPth9{ zn2{CjZ#5D~nS=@yOsDV#!GD>Tf0Ul>HHsv z&Yp#3nbLL*NH3}>Ew8H)0rTSYl1X&;3(BT6 zJxhEvH{N>Qsq(4tyOp4;f0-kcBs=&uO*iPI_bTG8H1?h$)_iUu=#BLtPTPb9AV?f< zDCyJRxvReK@IU$wDtrYX^5d^Wz7tp1gxojgZfg8#kxAO_@@N1x)ET>u=#^(>%X+t6 zJa^=Hq0TiPGh6LcTIa6QCN(?o*ww0q^@`NT6bC)wZ`Ls+-@RB92T)_qd?6cgU_J~t z{oF2Y_r+wvJ&|El=9r63-_^>}?VyT3BkJ&PAx-FQBeXIND~zs7Z5%X{ zw^Kg(6IsHAOq-?ydR#9{M5X*G)|kx*ksVLup6AErk=|1$uX;50#MJ{FLOC%#%Tgoj z*--k7?#H3O<9sKlEOWTw$3a1t7JO~SB41Y3g3`J>sUtEizn)Mb4T#k9ec0yI zX?oMSO@Zn;%%$pOVEJrbGE$wSCkdfPO#vPH+(MCFdb@m? z3o2LROUl0=dM)jJZ8slyd+17KVqY-}|DG8wN3;Ot<{sCDSvPWcMaKht zM;mqe1JJ$QPC+LuA3y3mg*XgdoAaO411_EE-j8iDaKtHhjoYpB5%vhp&_f?$0K&#= zWjLq{j(v;+dd%m)bC$k4n>ULkUUr$cIDb|Kc5U2uIndFRGge)vYMZ4H4b>W!!s)2C zhgn~c26yizsJ(SmJ3o72K!!CL&3W<5hq;Now=ehEw=q8*QCJbg31G9v!(!fv!GueX z+T0{{kvr}&*K2SbkCJX?X$YtMRU-ES?MskGEjM?C;xpLre|Aa3xp#Y%7TXV5$?<{CR|_PGjpr$k_h?XU$8^#;y8!G&t&* za#CDScPzovb~8@#3MV97B7@#ZJives4t`g0eehw~y{ms8W$ClHn9&u_iUrgb6G6rQ za^%*HvKwPZ7&D+(-Cb}=Dv9D|M2%a(X@Q0^xp1u6#}#Pk`kr+KS?;GWXu%OWw$$Ac zLzpfMx8}XWG^L0{i;AFaI62aI`w;E2=VpeEou5y>4C?OWTI>5)Tzdc6cq*tMlS_8H zM(b_QKkz&O63nAFFzTjFv;I-A`*Cns?K04y0=Wve(+0scsThLl#hZ|mx(2NAaO!WSSm9vAS+ zpAPM!cG^gK0=S>n`>Ep0zXfx9tCqbGlj2o3TahK>*UCRA*EGxkaqgi+U||9|ZD>df z!gmK_?M@4z&r1;@J7(MenRKQ)E}j5S7m1V>RZVZeyeE< zVOv%&ce4Q0k@p4^4tArVMtVhRXP)?O(dFvmjl9~+)2F<-;MWwYf*{! zSF$7*P1#gyTR)F>Y8mZD85&Wg*2R#D7eL&A|F}|5)Aw@)e7C#hZtqrftRA^uG;5?t zavJ|heLWRO2iXJ0`j^8QYJc%*iBZq7U&T0p`%(E32Suz*0`sCbB=uX;u2|ppnYuY* z`aS}cKBjxf{}(5GlYgSzRNf6-78yb5UF!9xKh*-(Tjf!fHtujWxOWnvD%5XH@as1? z=()!l6Ym-)@v}=1UEQPnN=ib<=CA(?4z5gL030;BeRhH!A%n0O@Tw=QKlD@EsN_xk zXPmS!u!^?{{j=8;?AghdPhD`6GR>#F_&kw{Y%f)N5d4XPp`G2CKAB#J)MT3HPWaS& ztBt8M6@M!xqPiY&XzNM-t*KviWP*K;e$4kbVKqPw5Klg%g zYqKXNQyDO2-ZxHty6_oPRYVy&?KQ@=EXFzSIAssn7#wBVLZ?Nyf zJSnO(_$ST0Qu%k|e=yH+59U26DE{>szg|z6Ie%g+it2syjo}voRM6x*hJ&J!YV@76 zhh+<~d<;Fkublpac|`!`?LvhQ5H&9X4cUOpy}o3P#*ra1<+$XRqB1YPxw={{_rrAt zxa0+lhPxJ_aKk=ig%i0-)VA~mFE{#YMu!z3Mi!L0;OB%u`I3;a9)`y@ZhxX!|MOaB+j2f zo9X`}7UvZXfvSf{f>U8O^b}(*tl5pohQe2_a?1x_A#@yoJZn zpHJgX_j?m8huqR}VK~@?jN!!RBt%9$h}@SZC7mcw(=@*BHa-z1&D$R3)G4pL1#7Nc z-#QBv-fRgff;ExE7Z zgL_a1KlPYCTsfB#gaLixqGw%0=eHJ&@|~^op=6471oXBGZfCT6WdvjQi$VepK`YYO z;xop4*le%Dhb5#Oa>(C}>C~EsuP27Q5}CL-V)sw}KAFBYRcN(hvh^I`Rs%LEAfWI5 zNW$R15w_{h^zHS93ofb?gDNc2JdP*t|;2SN=v79L^KntEFTQpCS@eXX$eF-pQCA;MO6ZscQ^!8#{ zv4F88_Ak3x(5##^65sHyXUs02<%~G-b2KR8yUEbCwJbcxhXG(OWjM zs-86_)ni|{Ljo<+rKh%gV;x^fyTNX}q^kE;;|Xg9z_Mg%z>tOhZlx(#?A&>=FyA>v zuOaq0O7>BeXryf32+3lO!J2j*Xi=n4YG}-4xlGHUe*&BQ+Sa8Lpzd03G&F*p*+zCJ zWpPn;f%p7&nC^W-Kw7P+??B>*yq>eGls{*$N(*xLC{rZ*MzmSFXz5^Oz{J$H{;R%gA|l^7K>##= z+k(Ng8_QE^he%Ps<}l@$iXm}CgF`b4JC9?RphLEo*>D7F9$p-u@L+y5-4bPmY`-O0 z%e3EKWlRg-9f|iYeOepAzS2*)^=7?5uw^v5ckl}EiTRdDe53Tg&#nuNyWjCYkNs6j z{BXb8W2AK0tmk=a+4S(QTM$!08W;0c@-CKh9|f`zaY>b`IX7H3*QqFf%I* zzNdxDV*#N^cZp{%hRgYt1E=>L9sItZlAW^ai37K?2HeV62FDf@KeliZm1T!=yP6Hb@9VZa9e&Yr8(e^l8%45DGyRthD0Z= z!K#eC=fZ;+yuHYUOLAFNBnJ4PCLrZx5RP4XS#}E-x}pTX&&K`q;Ig}_WeF(7*jO^8 z9NpQjwgifv+H#pGAVH3z0o{*p-!p^^zHf?2t!Xof=r5i!;{tuIr@^?$zoae|>a3TOdMR8s}z;k;i~lgI{u z*-la3@Vh~uUg$9EyCE5;>3y%4+^b%BwOkwf*Y&#+(EZ;7ycFW@Ie;5Wc8(21j{pp{}G(Af6l-L~Ca3rL^IS+oN8@fxqiIO@gb zE0F70ilcm7iN5!(vGvNIssbfoAxG3w)g5qOw%I2bg@-=}6ThB8a2?JYIi2D2xRJ)n z2Ma7;_*n4jkehs~SQeaL3F>`YcU$h;OKkM+W^a(4CPw8v=pu`r7Zba4@wE!m7iMk9 zGU94Iy^*d+wE3;}{U`L2HiJM^5`;07B;#@=Ib#>g+IUmXuoso*;~-T^_Bf-k^*|;u zUmA-MDRN6wNF0&vVQo`FJxxSR4m(i2yPCS7$>D<<`KJ+G#d`#VaY6&<5d4jKAd>jm!&HBX#Gb$N%MzeMf&TR;T9b@+ z;o-%^oF5uf>B62}4^3^{(}JRdXlpVszRTur*J+hZwx4qg3RCaM%o$8njkHD?@}L;_ zMEN6#z7|PZp2jxuQ~5g@Yq~49z#t^p!q&Croddj=0-F-tH6SzBk7Z&E z$%Ej+e~AYV9s4XQXn3{YR}bJ4ff09~`>)B$W%`My#R8PJp- zQBU*OIFIo6lQE?pUafB3xn?TY)LwkE z2cdYsdjfCYuCcw3zh0I1>podE)Rh{QjRTQkl+jyxySP0#g)_toD~V)v&BZbB?k#iB zbKWsk{3s?4fmFpg)+u)(yZ*Erwd{j>S3aGWQJpIgs~W{LQ8xv|AbDw;X+DMh&oo~N zTPvfLtD|x-Y&hVfvC)|JMI!#dg`DR z%vr7l12{|ncFS*u6GFhT=4?AhK7NFO`PE?t&@(NR6Gs7(KAy{$0xTnm0$bki_C?>E z+~O!Pim4(86qFxa$ro&KN1t73Yiyl9YD6W6OSL_WyaZ|%b#m18BY;5a!I!#_{r4kc zu4KwRqm|E63A)Zr&hwrE3>Ky!u$5D*TE@mqjWpx3>C3-1uuB~BTDtB#V7s~vfHpoG zrU3Wq{13n&rs?XZ=~ZzfW>)Tn2aen)n9{Ux4V+avAd(^Ci0iWy7aSYq_?3WeN^$9k zjrwK@?Ar%=ICt$nB6V<~lsL^zmq&A)H-z5r)vO0ufIUg{9Djp4F=F#*^WrN()o&ov zpJP?tW_P!9^g}kKgF4P=C$#WZ1})16uIT!Ixk2MS*?JPl*6Iv_-7;J#=O-*^Lz$J8 zm$&xhynLFRH+~%>7DWZOb4ySeih8Bb7=8*$NPi&|f=~2zS?G zQmIlP7mE@AX6GH~wI`sVm09GJq;F4BJad87x#MkV7t{7)`Zc}AeU-GwZ*YH}v8zm9 z+)`0~MV-g&sOqOu5zA8;-62Td<|GS;Ci1ljep=#$`SAHXpItHyRhUeXSQHwkUqj(B z63$O7JKiLYtSo_NSO%n#jP!OUjofPE=}%wy7)&h9B+kqktEDf}U$^L1+Pb@Phxw~P z;xS}TrRpbI*Fvw2?u@Hk~A^61m9m>_6wN_5V0S~4oJSCGLy&`Wz7CHwz^^fwb z44*i>!i?9zl_&8s^d)fLtzP+`!`fEWD60^zYP8o}tIoDUv`#hmV$V2T_v44de;c{6 z@FU`jqR$|RB$uGjWeMR9&xlx~|F>C*4&4$DU2pKRbLzjyhi;2@o5a&7Hw^KiS6k%>DX+7-RcSqn3WgUHR@}9ghu^lkCDNTUN`0TN)GBDb zsPtd&+Q0Vuq}}o&Mu80h@>Cij4!B$a>%}r4IjMU0u0N5&ee+FBE{-n723^x<-!}pjLvtJTc z*=_40Aj2W)$P-e+$DaI1=C%0G^SeZ=bM(zoO&kuXr(<5@r4>XKj?-K`Fe#PCAGo=6 z13iy1-E2%E92|mjl;lLv14>(?`T%jerFA5ay$5Q-z@~!J|spGD^+!kJqWdiCb73ak8|@rSvt0~mfA zh(qik0;y0(g^b{19(3t8RwwPuE$x`F*`RWQhJYH1m9 zppo5$k+rG!4#eLtoNqNR6k}Q)jaz{U_90(MUUX$U_^UroNOikSJoU%{K~R)nn{>Fu z{|E}qlq%VJ58eE8;QjNr|4<`#;5>*i02LZUQ(JD~y1oIzt0+&)7lUqfZz%(m*chs2 z1Y)8MesT(skGw`^A{z*!=ugpUR6uQO2%x$s1AEIh*9NypOBo-WZZk@x56-GPZAs@f zvTJr+^>3hMboqwCg;j0CJ^nWPiXsxf4?#4ylR9YNL zjP@KZ?L>g+CL5zG)#uzogd?3Yq;Lbc)h;bTl_0Qv9k@$u;>iDq6Bve&TNZQU0$wVx zpDZVC^7e>70z+yv|LN)1B)HE82KTfiSPb2`=kJ+JW@J|TEpo*9LW@o1Nl;|fX?c)qU=|_Z=>MFiJ?5m*5**O^xYUyO zv%7dYY%VZGW)k^aap@v`=X(Ia%>w3!>J2+>?+pMT(uUH490zl*;)Bj0VgS+x@eWOZ zz*S7T?UJoRrB@5eY)Of&F9A2a@yBtEC30X@d9EMRB3+Z=sDJxOax4eGkbo*$3QJ$? zP;lye=g?g}kUmJHU+>kUwWNim9XRZh zJ#e;8+vUhZcsF23zb&WiHK}HcQK9_&c$)s>-m_qIB490|7Pi#I?fz&%OCnlxEY$1< z@*z7ZfxBptB0l=-CVW5uQsH7F~0{ zWV@GU+5Gd6rAlDGoiy$MrhQa#c{ zxBumJ=oM?6kD)O0riBASys2l)KVDvqo8L<7Cq2oA`x}^v0Y7q?pH9;OMeR7~JhY*v zT)yN7$ydvjlZ#IO8*&2Ko9}KrQL)=bo{t3a0?O}X(5{A9rc0j+{3lC)v7Ryo7#d*L zGI~k@ki47sQCg0bUajh2-^e$X7I3 z3`{j4C$sk)jNt#TgYoBrTanE28KD1^+fg?W*kw%R@&27_)Mu3uV;iBD-Mpbk-Gjc5NRb)1CD zF$z1l*Im?jQaKhJtxlWO5fm8uzh-s*VQ!6m17DM!s`Rib&b6maCMP+1KpJFtvmX%j z^Px{D;gvw8n8n$6(4j|*B^er&p%r7BMys+m0fVL3y|$#$Vpm-i8c2W-HcA4tUHvbc zNuidUg7m4@kUlc`@;|%c7Q_aHPK9t)E)R==vB6s7hleX9AQJ@p zrBwFp3Qd!Z`@a)D*<(+s1{)3UY9K)3!sV-KMRPF*R5H+&hIWai!{j~}QdIILUkY`v zCAF0wI&zLz4``CApjIBr0d7SGDd&OV#*Qa#9@siGXDU<182L80&evU_eJ}r*L)HZC zUa~lenwdhw-UQ~)2#Z62hC6ekZy6G${2PHqP4fvBbPx?HXA-!Dp~(~pXKj}4zU5{# z2s)Pj7jz86{fNTg?y)|KfOxU}${m4pbR%HG7XP)4hx(hBSqx$ol@Q_J*JtSl zDT?+Gd4!1Smh(24EbQTGlKkCuB(oat5Ck&)*Fv|c7ntvK$hp-##h&eP-7I7=O19=# z-PWd1&n(DG@gpp*{y2k3sDS=hx8%`uAyC+SM323&CN6)LcC)oUqIbkepJrHWo39;JW&YMX%Bm zkQ#L8*&98k^(miSy^&qN9b4leNG6`s6IpzWmL~>$YVg~W;WlD~a~W^JxexU9T!Tm2 zm_Ztrk`E%Sg1}guOaM*F`fh-p+y}q~?Rm!hY$1r2n{}kU!(O@qO@1DZ0hxJq4*d1SE-mFNGd6 zu^gjgDn8ff5Hy$(!AkI9uKjJPPScLS|Gd!qr)nXO_M`+*+v*92#;WeEWc{JDS7xdl zIqlxJnEO`~IAB0pF8`S_ec=qKI>n48KXl{j1RTMeG{2%QimEkC+P-XkSM`r<4p3Z7 zcpS%DJ&iZYujYpoeu}fL?=;_-xQt34;AN$=B_)j|8uDn-e#?(ZW z4idyOoC3Y-ytMOOZefQit8yb(!)5(Fw6QlI3VaItwsqya_Lnif$4&IXpaqz>ICx1* zHV_QzkcdLDls_EG5UU&TChu|6k_kWzk{wu0K8c3zYz#p`|8-YQJ*|yJbkCGm>3>g?grdh zbj=iyxzBtPCmy1~R6XWH@!aVZZ=&Dv`hvD)$(s}TKNOxk4z&Ar8`-bB9T#FLMa-0Q5aNcNQnvS|b_ikvY(SGaGQbg9In7K{uTGk|*W%nt2c6PL&d8%>U zyFZP(AaKq0rT9pRgKRw9xVvd_%# z`wX4ad4Hex@AscG=Ny@No@eg+y07cIwH3vzx^bDn^@rs;=jtBOHb}_27cFT!lC=Qr zoW!u~l8KHgip?XA=V?dz{ZAj~RL}u>@QahcO-}dLLDKzZH|DGU{kB{oc#4)dD5pOR zPC}NWokz}n*i^D{(_wK_kGD^3^4_l(2&IzW5;aV{J8TauBmC|@JOobS+cYQfPB6UT4KSe2XLD@UR)pR3uE&wJ z|6bP=9kIHi?(V#In=Nef71YNM(X9DsF~EQzKKva6lDINsE0t`i`~L{6@toXaz@5D( zQ`^_d=XHU4>D{8RlHwi?Z?= z*JKI|FUN+zZ1l|16U+DbDEpF0BjkzImzS%m>mZ&e;^vI?EcuPJ7%9w4moYD0BIhO2 zwK)#gW_<+bmST^W0b|xeqL_(N9^WW%JKDijKm5%ODi@!3HV0ZLCake%ncn9eqGps& zaHgPNYw2%ZI<2>=XU`aK7E|cae(7^btEKe#p1Z$f`NOQ5B@yQqJnJ&N%(;?ti!NAoZu^7Rmk1e@jK8gV z+ZNTIvn*M593A}jB9`(5)5sM9e7U9mLtLK`phot9o(PT{mV19oGVJtPSxqykP?tT2+l__?FM1?f%ESr~QXwlj$W z8T~?mHqjsGT#N7miN5R=HBWW{|#z0j4R9Pa7Tp(zUqH@3V|Q zi3VXxTJimD;*}s@i+11K&hU34MQh~yf(MNdl(Aj~B6qv*W#X&B#ltdv6ik3;OTemna}sMO=VY7c5$$pc>+9VfkqJiqT~{t@N7xd9uL~aYU&w|sryju1uBkH~M!(E20<78Ndw0>Y zu1M?d#@UpHk|?w|S&{N1mhRIoQp(CvY9>r?;(+~OR7_n)g$*&wEsMebi;Hcu3OH#S z(KInjly}?Jeq+z)qC$~;h7fm4#IG8;0OYo}OT;gYJ~v#3co%-O%0Fl&2fk8B-M&rn zhD&3;v)USn!IrsYY!=(HHSQ4nc;G+r?4?Q+sB;~0F7DouC`@h0H{H64yHzE1_V0{F z1f|yS7ojnneAdtU>OYi*)wA}LqS2h9S9}09G==4f94V-ELgF-%9r^vOoH9LYfq!qG z5{)_HnD1Y9t-5*Hgo@+ZO-l~IrDyI`<#M65pR&G7+lw;r$;7)Pa!&YVlG`BpSS`L; zH(qPnoNW0QDMIDTITcvl{8ibHEg`B3Xz#IER3#8=D5XtN&u#YZPMA#QqwYUUkmjFIh^KSW@1Y4$c&^GA+isq0&QQ+n6lFHyVkb^Xw<}X?h^-JXZRdB*!cp@U0 zVKJ<)7Ko>Ny9HwL&)nDFJYmXD!KZA$Y}8m5Tg06DTrT@huLinV=KF&XXHmpi-Kj^p zs89YPIre?T@#K+2QaLn>O~-Obs~CdA<#Cxkl`eDdtI6t6^5^Bv-Rp|G50a}gx?G4T z2(e#oi}0BD+!*XhsWE_}TkM&D1d6hFy6>+kC|sxK;h0dtS06t|Xyhgg&a)8waOne` z`H5D2m3xc#z$^!UKgG2pmj?hZqyt_M*AgEv5UCsHAf~0p8$bWBStPavwpnO~wvX_P z8_<8$72PSP5V(mM8k|%$J2kRvtLkzXyms8+XA)QpEop$=0X!0#(nvo$JE?41<&%REF~d5Xp>px$;HDM=btLb+E8 znQUAC_K?r{{WTgG>&No6pPec&Z~7)_2o zQ;u<`RAw1{B>hTh&r-5oS6!!hn1o779uwkFWjEwKE zABR6Z$f`YHYu_Oo&+Ku)S2Lm7I$!-Pr^gmYVKa2_^m?khL;}*=D3{#33x?y1 zZOiGCLzD}n`Z=MBT%CAi6PJe^~1~(C}sF&=!jp0qt803M(!VAXzG|w4%%ISr|NsRxYDXnAQ zW+=IEtv;S!Vj+1|OZDDfYnM#PgjF`Tttqt%68M+shP}6+lj6S7Yoq!*p9&F1bx`1R zLkh1RMH+5NM%zs7I*kJMnw^mntiyc9%TWIjar0~hL0d=~8`di&c1+xGkjOv%EEh5z zfej1qG&?eEAg3Jc4raQ?j`E_U$IR0sXmupW0$KZlT9UcZj%hveMnLJE$S)CSV?V{W z!z7-0Z4#HlM;N`D64g|H=B8OI-#Ayi4qa?{HZ{g(;RWXtZJb7D{2W-oom*sR&@B@!55vDw=bn$G6(4x+AzK{B!=789NKXtFd*C_ZZ%xac%XVdZ16xJdTe@U49cINMw~i4?=wk?zODh z?W;f6a`Vp39>ZU1hkkz`S)ziG5E{>;~Ay z&O*-UV&KxYBdj=5>7Nbt^cfPpGkM^Tuj5LJ7H{Pj(Z&REQy{MITIatJNb}LaEBgE( zbek4^zF4c*uve=Bqq2*;osfgzYV0So)sc3?Jtc>8!RW*`al~)nt1nvG(tqdAM`R~K zBm0;K%Ks56W>{->o_^e8jobn$^};rKc8^Hywhy792lVtdw!>`@#Fwhb+0-{*CBbjm zOcZy?=ryjCu(7RR$%(9I)_E}phfG$Sks)FhLx^}0DGIF%YSd$$8`hZXv^Tu! z&nV=v+?N{MViLW~C4K{CDBa(ybH_l`aJ*#;w$6#UN6 z7){;jQVj9CB@z=v&B1rFf#v!?HU5W&P;(Fmz_lE7S02m!g8I6sFb&d5+-(+TQpJP5 z^d^oeu{9b+q{DarqYj%KWYiEKG;71K1G+X?S|mnWvtyUOY_9)P9kM|cZJFo` zplRZVDk3RWLRe`BumZy93D+gl&xz)B1*6_|K6<^`;OB{&$-3qm>%5#F{*K-w8jV9r zXvQCWOF*%6XeMg5y~M8-HeAq9eophUVo~pRsYw-PjnAd|UjF9(w^`QVQvtQ}SxI?x zT+zM{@F zW)$o$JpkrITJgN<7ewR~+^U2u3+#S%BL||vJ2|zHzMY{z{&a0O(fq39IWD_pvZE)V zi(i}2+;b94{t?SW=NzAgtl3ML{v|TRXKvFaAbQ7wG30QTGMHH9=EM5OBd|5CQ!mfZ zi{RYBwkl4m_cUXX@|XpU*)xQ(ITkRnHy@YbHsat74q^0<%KOEw=0M*kpp)-wAx9tS zS^ZyW-a#$K{_cb>Nj$55@DTPAwzl8_q0M7Mto4UA4!gg}b55vmh1a>BV#3T3^_ZFT zSQBWb>dYDwKEV{l6gMwMc5%R$Ub&xvvVTS2Jq$Pg+r2PHlkH^52Oht!-R0K_Id6Ge zqQ>ZbZ(i`Z;DAMg?=!OeUt_F~zirh#E=}bk?{q#3M>-Nb37S~SI-Za&?jeK%{f3v8 z7^uQ=4E?O*mN_loJFqzo=z^^J67p+!hrS_roRd%=I^WN;E4h8Xav}fI?Bacw_)y!6 z9=x4vv!I}jzPnqN9Q0UNgqt;%ptdU|I=zwk9CpQB|7VGT5FEX*HGh^io-{O`z?URB z3y)<47E}Zm-r(5~gCchbMb7QIga6pVDV!7BpvANH7l0)eYm@I9d004VHd`0x6z+mT z1xfwQp5+k1Wdih+K0F?Iavb981(wolf7Wb#epUR!WlRjJ>QOP0&yD-d$;K|DP&j7o zhci{FhOx3p?6MLxnK&oHFc6;nfD4+bP2{KpUzAP|x0M#k>Ycx2*~G(=5i=VuBkP|1 zpX*a!?meh}eH6rMbvDJ4hSv2QZQsWBVmpGcg4pBDlc#p5=P&B;ivRSVw`J0hjaznd zV)ivXi70~zZfU};K*nRkX6^h@VSJ>T7${dWWh%;Tpn-nvy0!lZQ4Yb_M$>`urN>gx^sX zUMRpSXHRTAXg7e@X%m>(X#N-r&MnJaTBGlEJkc2B{iVmXPtv_=F{p>Prjk?K*T9L$ zG?qu5tO+wp0H3gNE~(G(OijkC6j%QW;zgjV4wQ>M~XggHGU{+%MQAXEB zE4R;<+fUMZ>qa?sU(3V=KK#TwJliQ^BgeZWy5-9o1P72*)VGmpN4hTl^uXfQg{v@Y zb+<|ISaL_ZJiLo`L&{9;>hMjJH`Bs5c|3v-C&Onk>w*}fomgy90{6vR9M5NwWI0Tozan>N`GOiEQRYaS(3Mx&?uny3Wi=@q zViwKH_Q_?8K)h%eW-@8lB-=Sxo`}+a63Qv4$bI)+0vr-|znrP3!A9XkQV=>nBI=nT z=-)bDE$iY|h~@hEnR}?@9|c#T%Yh4gsRylGCU^B%f1Vo@%Y?Lf+oU{}a+C{n#`Y4$ zPlp||Vd1kq{J6nPEv9bHUgrYR(buBI`0yg(ScKA?$~XuoZ?5E>^J>w`{r9&IB_5036S9tsiRZdm=v2lcWL2=8~gTjA**M zkJ`Pk0QY;NkfzO!wzwFAzu z+qObpb@Cys3d7YimQKjCf!+r4eXoep{xed|)|IouH~6yd^fywYjpa?_##^3LkVhuC zdG=;kDQfPqWFTN)t#(5JO4hJDNEuM@T_!C!p>IIHKBOO294XLgy%p%2H8p<;Rf?^P z0@~HFLuxbdXr&mbmC?(N_}V%@9;u;!lU+9v@dsB~BrAwiK#5~q;3oarDhq0ghZT!y z9#;LfN1L){7p9HR9Y`5XJbn_g0}DY#h6b)oWR%a3R%3m0#>rX}zO~8j41MrcQqy3S zdSgGm0V^dvLX1c{qP7ad(-VK$D526dW?nJ@v0p+j@u5GX?|u9xFXV$SD;ct|??WaM z6(TB0`z?U11QvT(*fv1%R|h-%E;XN85{8;?jrA#M-Cd|-NrGX7=(BuVi^RL0@Om_` zz41^i*@=ZtalU6G^0Y5v^vmp(EiR)Znc`!7a)d&nM~NXa`HnQ><^UEQe_Lm8Ak<6yYt# z0$-K5F<1deTK7i4MgsWJLEuLlygu5H;8Fe$@o?*NeYhl0-Bf5`*^CZ4ehmK(JS`Sj}%F3Bzt9x9IoRjKLX5F?P&0le3 zBoB{NOAnbMzJL5k5ObN-wL@2}xsj}2`(^>(R41fMqB*J6>nuTBfzQy0U=L4ys9|yM zade7<41PNR1D);@Tw85x88Gwhe*XLXDl;)Y)wd$sCw|YFv;u+4Q#v7W3PVJJDOQVG zEE=wXj^&7X&0q%cyA``)ZLQZ+y}pw21eqiK8a%N~H#pUjP5~3CU6v1DRts&y`JVli z0FPQfyq_pjVXzMw}0 z)nk}np3qfO%v^mTm!Wh`v=O?~Wr*NJOA&tp{OLool=U?TolawQ|Ljb`br;w3)&60x zzjO2W*hVkxxqmQ#Y#-19@eEMYxCvZ0{4ke8HP7OrR^*)1`*B-!KpITKQ&v-O+COr3T4d%>(`k3oCDpjP=cA4e!H1wT|7$4 zvBdktu??(^f42}Lh{Iz4wEPDA*FmF6`6MaywzUFNOy~D802l&`+&(-Zg`t5r#&y{C zsy%&}n7-a6+da#V?7c|hleNq(dYnl=a&RHenrheB7*S@-l%gh|t*GgJ9!aTPkI|}o zQ5ZQe$tFmqbJc7HL=^ciL}Z5SD7Nh_M zEh}tLzfMljHAD0MotwcJUO>yJP? zLnB)XphLYQ32Vm&%T01j$S;c*4z1dTSHk{z;-edyY6>=?tI%D)^3x6;tox!&m?(9z z={=AGSQd_1E{Sn5LS$Z2Pw0Q}p$8;B^xaWI<{x+{pv>uo3?2aBAzA{IU7V*4{BKqH zYue1@`;e#qQc1F4sVOPKe8?7Imblg@jMm6v`Nyc^i&Ioutt7WXD$(b*=fm%>#`Jy$ zC}raHCjNVNM*>4+5w;?|8Vbfn(*b46sQT_pPPkrw0v&RCBj9TR26qhFlljRnnMn=MIO*;zL#^U| zW_-^vf+J})$2tXVjvapi5(9`^ZDvz?uI_rf#fgVUe~C%93(>JuV>s7y%EjChgNA@r2GdwucW@aG>|c%g-q(sz?m zdOb0+!sYz*$EH44i!FAItSd%yuzYq#K?!02qiYxURioVA`Af;6$$ghisd8#?oXHhH zL(goh=nz0e#PMPN2$2Asu~6$bWQfe5L~kYeD_HU(1Kv1&O?m9cnCx{JB9e)`R-wtn zKd-jl`1pRs9!X`f-OjnpYK$t{((A__e2t*-V5UhiemCtmb$zq`pk_-fnizY$?54kV znfyfgLJmv|pW#h+kTvrMxN)HXO*L-Ks((Nsf734gj(O!)!OZN`Z9p1HuJF30TDIkp}i{R>scq?0^*g6_|fE%l9g&e8p`;TnmmE)aV+}V2z z@(>0i{#gP-sa18Bq03TSivesDA;bT>YP{7YK;? zD2v_l;55$DIoaosZw~T5x$lW@)tyn^vo3^qthk(^`+JsYrgmX5pcmj^C~Q@$$Zczc zKik3YPkK0~^O#=;{DuL&r~zOZazKK--vg+c-A;#&%VkOh?cWgWPU38h4I_W?rS7qC zV&3%0JvAG#w&-LWjp))S3)``ItNxmjGVoFxfct3w)jaO2R?>K^7hX)C$)YoH@hl5% z-`1hf1JdLt(4tX891+Z(0^Qfp`OA9}LrZ+`Y#!b3{Yx_pc$r-Oe*=ovOh%0*nq)Y* z{G3dlImAh8aed=UOS-QuAupH))Wc7_gf)Fg|@ZRu7*$Yo|BiXg< znp?XtY~ET9IssXH0T>&}HYg8OIyk+$O4F68hc?=ReI;cF`Q7xIY13p7c<6d2Sur<} zkLD37rp03d38sS^w`>Z8(4fOxRY2l~8z>hwLlK?ZB!`f|ILPh?Vz|g(iT03?D>ELj z8qX<)3lf0PwaV%ctcD6TO*X?|0Ci`X(SQJQ%0Xw(=EKF}c#6+k@uZ-ZyNttN&6q@8&inGmUt0I>k{=Shw?DBW3P}pQF z=r?NJT+DAH={c#cD5tCl(rNh^Z}N#;lY(cU22pZ19PdtS?XjYjgs|d3JfW&3LT}8q z#)zJjT?8OEhl43y~IFDcX|;@l0NlF;$8& zL0zl5McO#}BV{=EYvu>JKLRuNs)I0vSF{S0pzx5f;!h(NP5Z~=Y+oFn zYt(-UQpb?E&rHWn^v3=K8VBlk&Z;DtV-hoJYA8<;BvXcVgv-_Ga{{ApxG3SevNUFB zxy~*V-9fVQt=3jtpzfULoyhm$tmrzy*3o)nCeRN{D(*$qFD#I%P#EDtTz(g<;%we9@4!zivIG@7LnLfbt#5M8uQ zM(j>S;oSRpCVsTzqNl3S($9dVqc*_cFlTlQ=VsPC>8}b`*Z!nrO?<9Opxq~T?8mdt z?T)L7g`Ei%E~A1I;;O4~^OB}ZXA&t9f;>FhL~X+-S#s;CE_B8Z%qkV-`kZtR_;lh8 zHUJaIX;NlAQri8Hg~h%@8+Omcgz7V#By~FZB=y*RgKkV>e@OQ8ai65RMa(e)YUn~@1On8 zFC1~PcRb+vzyHE=OELgQf)k6?%11&2Ui# z(!qcB$^CLg%2H*5K!$FB;&=%a;N9W~KNbwXf!{>kz)6qVmvGx@0bc9FfvoPf*RrD+ zt!t%kcYNpDVeUoh3e|0wD0kcBPtGR#Bf8Dnl(iUlB-OI?@VT;6?n{*VYd(d$Dzr2o z}GjBL6tp)Ts`WdsOd#28IXEO->cnr~wS~O)^t!X@=c&X*Mi$wh93fX`A0g4y%9W z&8@6kX)^tG=#NY`^vxbkxhI@$*e7i_-geUqVM(1oJ_(jn*w+ zkP*kA=^Y!V*2mIJ`n7B0tyDRUQC{!$Ezf}3>+p9U0X0RB&Z1r?rEtrt4!^t}n$Xlz zX65YHHnGi}kQ2?SjB#s2!7hmSYWCmHG+hHBhCL?CI=8X}hE~w$+_5spSX-S7&y8=L zwi#x6cHZZg1Iy*MQUUmnDcNDyZCO7JFa7OW2;gemef_IlKQva9d@YV=k!6>zPF=eP zQA%X&F@`M1dY-`#p^NIVUVKHQyIuvRGZo~{TjYM6UQQUMfRp+ezKPlTS++BMJOB|) z$s`nPGVM@LDAvzAq+_U1-qD!A>aD!c!CEca)9j+NS0uhy$){5)|4H!gbb%R4CAiN) zFbDTEGN`@X-ZHx+&XDj>+*@j<)GCojm$YWd&@b%A zf~-_|%@GYhxNp;V(Uc`Hmopi1omT}Mt7JY;&*TCw-%IC?o<-9=wQbbn>)uwQ9{rF^DT6d1HT0;eV zZ~;+Hj`+GTMS_5=%i7{}YE;)+80`UbTk9p4gJ{tRE|eRvm{e!i=kPhkc)MxgfDEh^}0#%0w+PO32*NwIB3qkbAun@ ziq2JY6`#NdI@&ZXna&H!H?bbUKn`$Ma<{D`LVQ)a{dNR(d}QCb(a6fqm&5aF2SHr7 zlIyIvEhk<}?%0H$NRNcHNAwa^mombU!SJ+8&h$xKPmJn({UQ}Quj%V+zbSk& z;9g6bWRi@g4s|fg?VCckTj|1VQF#p_u=OPGwpWW%+CIB+1w{nNnjmEe0;+I9bQB|R zeVsVQK238o5W&d;tBiZH15uva#YA zt}N^nGkt_!Q?W>Ky@0M)7JoteS={z?-XZ?89}2oj^S^|%GkAX57&8A9GmOEc3gy~= zaVf>G{DA1-7Plh+o+y@E@9J{J8{qkRv~kG9cU-FFml8b+O^ydC$jXic1tjA| zk)4GFb=v;tYKQVwJ*R3)gnIw?+X&0Ts7rC;=rpDnJ9*`Hvc@cdIvEk5N!AqeA>K|? zoy-jcLwHw)v&gc_TzO~mcsg=Zw7*|HkIW7M&NfNolQOPA0JnMTK=!5$t{5GDlO7XG z9Vqqx5CP$$Na<7bZwD|#&WXrtZl`AKYMv+IC^{Ix5ofuxw+A`3l!)Z%%2OBe?TzZ=SVAbZ_hrw^= zib%;TE$H7~0fy||Vwdr_Ek7(J@a#>$LH4fZEv^c&QD?NKq*ahz>kK}ya3>{}2>doQ z*YjT#@4b3(2_Q&S`5?+5&aAHZD+B5L#^)Wzpxw)+=?m$sC_Y_9;BW<%gW_G7-HGxRW;QWF^yQ~qomlv)uVIaBy_4uR6 zf%fOmn*O@Zx3;g*^MkVwxm>IFGNs4$bOgWfokC}oA=#Qx-GI!I+$2v!_Kp4|VMrB` zW2oHo(@nP0O8%wONvb*-R{@=JIc9XZH@lDhGcGwsMx30dBsego3{|kJldvDv@rSEi zo}=I2m~Av)fRrtDq`K9=SnJe17}2!93*z%_zt(ViEp{q^qP_l`il452-SFq{jJ(-KtI5`8Z?<(l3dlhe!g zv76mceV6qzT~3-_eO^S|Tq?|)ZfDRn-qRb#m{WY6p1y^N0xthZZ35;|PAZvvD0b9q z)#8`gch;4?OF)S{uMqf;OSG4pk|z?NKhNel%yeCW?j60aQVRrC67uV3nU0$lo$HUMb#M>)rwpKCi<2` zZ|u~lk^5ny6nmZqagE>y(5=&ztJ8Ty)21(z8jj;Mu7Xj^>aKB9{L2Xakv1B|4g-JT zh2ObGa^WeSbxN{r>t?gL1hUX149=ooDG%xO`TaV*1V{ zXQUB7xMyQXwbnc#jVSOu2sK{GXo}UcIJiS=#M#o8%_IMp>TCpDDOcPWf3eIw`&TXH zT4DjS?a8v~GU|RzOU(97#kW@SOeHTT0>VnDxZaGgj}EwTOl8W9CZ+6Sx*1}VEHIeT$*%J+K7x2 zSbiH%F@xn}U;A&|fpbyC&zc~JA-c2bjT8SA=V=gu*va&mE>WixpSz5#xfH8e6-$4P z`bfg$T0ZeS@0xhOd!3BeuUvYGDYdHmZo#WxHIA@ks!lGD#kIPVKD}*kw>}|Oxr|!= zE5X?VljgRjGo%Z2*wOEu&X`M2QnQicDRBUBCUAAfhbMb?2DciA64px;*L=Hgx+xLQ zCr6>~nk~d13^RF!_ZGaNH^E7P#bii8!$+Kg^>#7j6GBFu_+wr7VjcLbREi{y=_GQ zy~4~a>`k|>guubxNuj|sP?5#|sM^v5L`O00eFr_ZqW&{Te?igQIMoPgauG9@qt_Mf zLyd84?eFf0Q@==zJlP(@YaDN;iJHWBn)Lk4KvQ4%Pa?xCo~P#r2Nzjnq=Qn$K~sh- zuvxN-#YreOiH)ohYY&-In?HdN#ggNv`5(Cy62*c#w5}=&^9C*T`=oNdjnJ7P@iBeM z_(OSzKuC|EGXO>iC;UNcR+_2!#yp+}KNuEM=DCP}w~W=JxVj)AANC7jG4q8irOnGG zkr~{H4XWWX&s32G4v7k;aGqM$9As;{KuN&|rvG7g^mRJYA+AhXsXcUg?LTg%ZT#lx zEMcv&nj@_hr)Ab9)vDUMg%{;RscG&GZ3az5Z4=KE%6OOl>jGD{i`@S=L|H%#rRq@wCYEKlFTW4=1tm9xE|z(M{mO?e{C1i-aG=+_` z9h}O)3bW;SW4rn0axQo`+#&-^X1Qa!l3}xSFA@QQ-S}y3OPPQ z2Xtt2i}|b%_TQKrMi~s=>c#2R2^5Wgc%Qq0Ybi(ym)dK|N_-6a^Q((p1$qPCfgafB zuRfatu@pSAGiot(;B9GidlTz29^fgJa4lQ810io!<*2_7*P8|aC>f9Ujq-Qisg2N5 zMAim9-X2aTw;ghg_bVSikFEHP?lmKwv5+2S_?O=^KrEk5?`VX)NkzJrRP*@hczQWd z!A({w<)0jxf$wTZJ#xyix~Mk;;0voMd95LSgfohvX4fZlLfG7_5gbFA&X?&F=e=@I zlD72eW><8Vyh=`kAiWbE#P@=~>1Iww>i&uPDxd$@9%!F2X*%C|YjA0=`e~T$T|Yyx z;u){>db%BQOU%z>^>V6XJ02}HMvKf`cgXJ>aDs^&5P2M4owY0{oV6lmby;43>Bn~4 zqrDK8_AgrtY2W{l7@jL>dC8sNGM-2hSmp3d>lus?{U%&uPJ*Eg9Gs}~O)5;yLA*A| zlVvf2Ggh#yjqYiZf=_cI_Lk~U@aWm6qm-ionlufqjdvC{(je9su;P_o2k0(HCWpftF>fiFX z#e>|96>mL{{U75R`gM!kr8RnfG$Wo|SCmfFt;Far7aI8)a%qOD-cUywKvWdYD zbPwcY=Cq6zkv^d5PZ_k(O(h2dRnO4 z^`z-6OF9#oiLj5n^q*h)#ruutlUUH{ow)8aVZ_rT^qhQxzMdGWGN4sW^>O6)A1QKH z$t)6w9NGIV)UN=|1T=&+j-cu`2Ac0NL(Mu6243?J0Z9(Z#y>9OTG&NM!=k6LD*Kh; zwEEo3)X?iz-BaozW8Rk?M#hL-CG=*EKKhkW$de8*By*iN zL9|Q4%j;66lc1r4p%e6^v(~Tgz|-J2aP9ROv0WZt{DbFupvtH#=g+u3@qTS9@*00T zQ`+sGQjvvlH31041z~N=$*|o6$6oYe*4`!L@ozx-vk6>B8-4$Vp#bfvCtiK|lq6a{ z{F{A@_BT`Uuai;bSGf1Yz5%uS9dAwXT)tW%NdkzW z{LsLwfC9^$R{)mBm$)g8Dej0`XC%#U&wX;TsOaDBCQ}Z^A3^^T)onu7gvwaGtI%wn!qpU#0>5?blK&%DFG6*ku?7`5jn#u@o?muwqh!HUKgXv zEJ*9uGz*JJ<{J{AY+1KUut!!1tm!GR(^Aqali0HGQJ~W?R9eVDqGE2{3?;nxmO&b2 z9`VR3&}#K>WjPsw3+N?RKwa4M$*$1%4N;&C=KGcG&ucdpdYCJf<{P5WW!cmp76EwM z1B`|^U0K`p9mXqhENIs*+?t?g03yVOkWiArl~T;uv-AA9@@kc2d!OdU8esMPQh2`n zlAWdUKs`y5t&Xy2PjUh~nHAmy^Gl}6 zg&CNxIlk`9rLQmC92GY4+ZC_CY3+pDA+8}^YD>~Kl(z0|DWE{l+n$qqsukb6t6<2H1EU@g#hy>vVsnWzWDB4(>$%neEW10eCZLYNi0q3V=Wd68IMH zyJXi?Y>wcQ3+k3aY_3W2WCtx{3TRam6k^98?H2zKQ_W$?6mHHgF?{i5W7wOJ-?ap* zL;OlKw73%_hUX z{*gRrqL0QGmBb8w<~$7R(*vO^e~bwcDGV&=Arx9~hij>BF~UZhl_0pSRh#VGPgBon z=;xfdF<`9|Swmd#1wBABv=rAjHopRyYE=#HmO6`Sd*f?!)uu8F+QRPo&tNtEZ@}Lg zV}g!H~{aM`dp@PE=R``+vi3A#T5FJ1mGo&)3YUF4<9 zcH^-hisTGGOo_&~puFVG0OPeuiIpLs>tt tIXE6m`vU*OhB3K}4dm^j4weU9wFJ2{E)Ol6_x>$`YZn#4tt+T1bnvV(dFZc4CxD zQTAytn53~Y3}cw}KHi`EzOMVa?myuE<@;r2U8>D13gR6JVP)`&Szu<{EhQVzX;E42r6_@d^(? zii(1p&;1y@L_s^itEA$8b36~eG>8%buOgB#@CrKsUK9=f&oBR<)qwwhV&f^g+4cQ1 zVd)DN?}ee=($!v0ZJUwv|9{Mw56m%Mxtu9fditt4eBYVSB_8Gcixy@x&ElK$yQy=#q^!ll`<}{XxyR%EwmW998#AjX%8kEgnzSZuyEp@}F))FRbk& z`>Tz0)OaOY@4klaQ9rL=h97P$;>sJga>bMW^_!s|`hR}3M_*3~Su5Vrf7>Bjk1Pj| ziv2ARm6h>SS=n!Bz>eQ&ZV`RZ<#O;V3|})cUGcYT(N{jVV<%NV0EhQ}$K(vc zYc&NS33nxEN&2;Nk@LbcVfh5d(TIV?$!vdw@6gHjuiy2OLdBkp`87@HkZfJ>|D4yK zvpaj4dgDUL>n9_QdB1(uYHs3-{`ky=4~xKm{p;~vi=$0`KboPUsx=yiQFDCx>>-T3 zAA>sFqIy9nykFtyP}=UQy5cs>z`IerT6nY4>{rxDi-MHS>hO&#zLTFnxv;k;9aIq6 z2KO1RD%%f*ikyQ*1#nhsrTsbI+xd3BYlMOBmOBoYQpQ#zCD9AzzC6zJIcHZ>*R;?X zxCbLecja?6yY6Jzz4ktFvSaN=$FrBvYth^Z#o<#)c}0$$dUpyIdBP>x`sooAvFyDb zNZY&7Sk9wobp6S#9huI9&uKag)xD>AS$x_b>~*$ip-u81#VF|axFmGuku~&t57x#} zh-`e1z|KP6(s$+HO7VAF`zkoZmWn@b5F@kgvxe5Ado=Rti&)OLYBr&i-FWNfg|o%= z)qc~>kG#F5OvMScuhLUHYTmFrFLrXBOw5L4wo|w0?un*gI;i>w5*n z7pgGE7T;l8zS@;O!c>3CVdDX8n!Hx!j8_IQPUbh&3W5 z=qH|m>g=I3w?OBniI%2;+mvdTcz9u!iQTo247ZqzJwft+!mwmzVhsCY(?W|cd%TkV zlKbO|v+IirboFhoh1mWAS%kfhx#uhK1h9|$#eb50kQv>?Vaw2<;r`X2et-DV(s3DtNRp)Wa5O~~1`cNfksJJ%@)_58EdQ%aG@Cb569NnuK}AEr6gx{F$> z`(%=Yb@wPMC?C0G&n-f0H1(A`bx;gGa3Hxy9)*O<`yL-v!9_m^#a&4HIQ;_R?-E227@=zfYn8G&u|XS{4R7Z zjHp-&NGIY*)(OS>HMz6D#OwG&7bo~4AV0+iaAE}@k6%dvC@=LJlhup8AvXPeDh22ui625*p9Ba;NRi*Ax2!-NpoLT?2e^LNV}{# z`0_ug);3%ubF0wd$3!!?n4kNt{A{^rJ$DPNC=06~IE`r!JZ8j@#YMB~Kbbe;~!#wd9Ve5`~Bh3%Yc5w-L*U|_Bx;U~WF;X(%4Yi9LZcI%4{Rz0M;h zp^HxFFyxi6&td*h@~u&h&0&`q1^;58-vu!1?&6ksT^m&>BJ^*)QQ{4K!ck@7-lUkK zKTvD!@W9U+v1qbyz>xkwnlHmjf8Ui6{A|(+AMk0QR9>XjmGz4Kscp5Up@N^I*0u7O z0aN33^AViuCb8{Zk2>ym2y8(|>&DlWj=ihmzVRzIBC_q8XOUJ1%L8w66hQe|TkeO3 zIZ6h5p&O2)Uxs#xA-hX!1DxcpnHnwzo>UjD`_qZn7{&c7Ax!s$^%=Gv>SNR631a~k zG}P4o%fdz*D5~2v{Q9{HG`(wnc?0Lv+~D>-2+BkgNtIWM{J}c8;+aKEr(Sm5%918o z;{DdR6>O&1H7yTD4)Hb826OYM>Dyx7$gOGI82^;wlpn(53UX&=mNG%cz~WZf89TO3 z`LDkIQn%GC;|8-UO+RAG)I_S3Qc~V7;^)+ucgPAYYPb93&MQFE+!@SlEx~Jn%TF1u zQ&UZ*oK$%8bcMjbecXPsuuk1xZ=-hMYjD0_)R+u&#y=5n+Rb84adZA~stbm<`MI#Tq-ESH^u zJ+q2u`qJ3QN+#c#&b_UKbBaW8CMWLjj6ThN>C2<0lw}O~VOy4&fqYdC8TPluF9=rz z5fm$sqPMd`NioYr9^X7_7*7tz7CEs?)o0VTPIc( z5S*$q>l$VW(+{M-ldozxB!yvV zp7-3>7MdvC8oDbHp~0v#(o5Q6(Aj-L(+v_%(301hO@c^9H5m?~H=O@(b2pmL-Li2L z+c6c^N!!LfQYv4~>Y4o#Rw64b#MA3XIuVuBXSpBN*I6^!8* zV(--~?3-eIMt0J6Ps^0*|FC%*IgV;%;#pPiLlmyGS*#wC9p;h#DP4Z_a(!lW8l zHIQS^PUN1<+jV#HO3CmhJ&eR*r^+VYF!tufw5kxZQH`cydY2bTuj{nJG^G(dv` zrJEs|8W}KC!@0JS$d&p>_a)c6*Q2djt)k*r2zF$;p}>zK47*;Vc>DEN3WB484<5Bb zWB<#3R4?k>{K>{%f#W4iYw#Y`i3%)cJVAk_u*$3Cf{nW5BW18-K0gOav%S}%VHbYX z=U!6Gll=EwBf+UM@vZnlqhGqb)pTj5Yq2N;9n{~+ zvaVj=deeQftFSi+TibJ+QX$uky-^`&S+m#Yv{Cc&YJ1@X@s2D*e>HNo75id0br^t(+X0=Obk@@Iu%eHuaOaoSq zpMC+V2#+{l@}taMUGMMNe~_*mOMNShW>eoUWBb(g+Ez2OrfGwU9H^>OoJsQC$4p!( z+28DCnCX{uzCCB6Z~4m#uU0ykgI1^|bk|ncx7hH0V!qOkH}he{Kx&nZp74cuEK2}u zjmQt@54sCNO>W*&2G1N5zjKugIJcsln}bV2JvO9Cb2IE?7TP5KJ7`p9x2t5PnHcBK zs138=`vU_Zm_GE_>9s}LmP`9$TUbzL;Y95Oe^+zD-|%ts$eM@}PDw=EBVxdpl1}_z zpR%{fmQW@Op|^@>nK2GE^IZ&}il)S@epu9jv5#%{m8XgW{wBY1lzMo6?fSndnDV`j zE8`b_CbM(UDlGw#Roz<$R}>W)Ob|b;YJ%D9x*zgGi5KlOd-?7=Y~@vk6ZIA&{%;mi zA2QcV-41!L-`fgnRlgh$_qMu7iol|!GT*o?jHF|{c(iO!qv(fc66=SDha(kQ`9tsz>y?)BG!d!|lPc`g!2c!tPG1o1CaS;6hL|Ps6q;wGR9wHvAzb zoh$ErV1Q8eZ~@4u%(v!<->7TRT5|KyKSCySex4!*%tT{bwttpaga!|u0}YE>l!B0X zu5)KubwEnDE!N!yDZM*YDP;yBQfj|v*R`77zyy-qVz;A99mSG4B2(WF>R}+C)x=_7 z(9OW;sPDt&wO!jV-#Fftl8o#vK%0P>9XBanwrfsao8Kk_0RGD=Zs1);&ByJeIT3Z9Tdu*N>^@W2J9Vo&rrO2S;t zrIhd%7x1BNO0cvuVi4`t$WZ=KoZI8wfGn#S0gwd%SO!FPsb#P^J=hU8iDD|x%8610 z;QWu1r5b;~JLA>t5u#NxXhUWZASll92T%teKyK%Av)!ei|GWtMb3`y1F|gezT|NhT zqJ+D%5inmj`AsJuwguLl!Jht9%-*B+x$5uI!3QT3bVOfp`0MwEPEB*?XhRgP9gCg3 z{TV$?-qdg7>V^cSIOPxPCie-JIma!S)1BXcmnPC+Ciy~MsL<2}rEOPVBy>Lx9-77t zOW{Aw03EGlY6zJ-$th;5>BUlBMM|{_!zA>iU&sM;_1|173Cw-$CQ4;c==>EW!chvC zjm7w{S>IxuYLY7h&wBP1dmb#9{Qo8*bU!U5zsfif)%b(&*6-E%8)=b&(yr3Gf&m4wSo%c_ zPEcavYj=Y2FWKu^H#+n4h$gd%h0p2DSfY~#?_eC{ z_Bl7Eebq+jNVDQGd7&QLMtkg$x{*e2_6wz_;T~xTK2m2c_9z-iclk=lbr^ z;MFEAFe7aVl(mP6n3kPWh(py&w6)o{)Rmfhs?wy(wMCJZdPyw{3IE&sQy}>$x=lQ2 zwGFrfXiu~3i*{lGZrNA<(s6a$Z;xZh4NvmObRTghZn&JEsfcyTlz_`W3gFbt@aF&k zWb&RV2C!d$pq3z}!}#u#B|i(t(zGkr`>!;YImdw}!XyoY0q zV8t7GzZga261>w-v;8JFw*PhE`LfwR?L)o(^{E-9jX2&R_y&w3L{<%>y1rqIV5erd z?eT=j1a1qZmuA``yPc{K-p(qdT&cg8Hqtq}r{vz)H#JR0=w1E?fW|2#hgF`@Zdhxm zIn2^s4xAsO^s#HyD~!h%CRUPT>=9~AszXYcu^;M%v5F}ZVK=;ZaJbG-B?kg+FwEdG z!H8hSt`#!cxU_M3Llk3C)s%@oa-EUzZ_O;Wo~fY4t95?_&P{z5=zXmn?Q_oNN1s|& zGH`FXQ*+mUCKg2ZU-4aloMc`osa|on9ZoN2U#S^y@okzZiuzau1M|0R#$r%NStid< zWrjIOW0x+(w$l^nFX_8>+ICxa*ddzi3Bbz3t#zX)LF+J_<-+bQhbL#A@rE56$li|^%wCgMU z^1J10#s3Bjg^*8~B9#O39!BZSaQlI5aS*zGz$TTm4<_ehk^mogYL{Y0o!Zmxr|_h7 zG9cK_AXB@!H-sPL{*(KL_)K&+5iqRqb+u7;0*;C2d-3_m_aFh@Qli|zZ4cS^J>Qxj zg;&MBcVY0jB2lyZiAKdK*2ug$mAGT@sO9XlNv>kQ3*dl)BTsjA??tU!5w&uG15Yf$L-3L=PhX%=s=H+QdU=3*fl=WN#}G20{s_Hmta}r?YZ>p#FNQa zw0Om_r+#qBF~<#{V;R=1)`Qkd8o6__g1@R2Z_m!sP0(jk^4zm$-gRQs2PFcYtQKKb z#F=xoG==TC7xnda{toA%U0lZK54aKZn^?ozs18JL+|{kuY;jjyoFb1pfJU9qdx9;F zO=T*a6NIkcc&!W9_zUW+hID3Fz0bzkh4^`6C+5_r>2bB8?ygnb9~n<+O{;)71Agz}P{QB&WEP+QqZFFG{MQbvR z(p^UiOR|^%7Cr;rR10@RVRlMwpRHJ7g!{(1jq@8qPyF#Ytn-Ygd7K_(9oH0sM;%WT zg@cfPctp^#%%$vIQOirzEuYHmJD1g5x?{pk?5e0dw+3oP-RNo+j3Xn#onx;BV!hdh zmb}LS`@TdG4<50>6}ndD(zpe*!xnnyCy+5B&{sPhk$NvFu)8Dak@v=pHXC%YUC6!D zVt_lYDOPPQE+z+d+wEC2LpQJQ_{b}VG&wBCzByJ)WLKZNMPx-pRuccrs#p4~1o2?8 znd;0Q{`eRH|LmCOx0wmk=&R=f+HxSd>=K#9(x1|c<=m%luai6g!*<_sH2s5Q@|CIu z-cUpvrgKeN(EE_V{iqh()y9?p_Bc^2Ss@VtkBnGtE*&%HW}!b@&R!~X{b!Neehw7T zZ6Mzinf`(o9#d9kioty?n(FNJo%HtBG#R&@ANoecE<`=s{`X;Nt*X?BT|hm-Cuk&A zwaDpU^S+bsqA~YHY#bQ9GE31w$nxCX zr(K%o?MUxNH~TC=58^5nZ@c71yMoU3m3-e&piKO*DWL3EOx zFHkCc@*~hgR?lG?*RYgm=eTG_)?-#L&`5T93^Zr-#ULXgL#h79%6KyaVA!*aFLA^@ zMPDgQ-ajlHko2!FKD-FKRpRk>H2M#fZ^7l z*2DW+c$IzVX8wY~bR(#nSU=P|1t893hlXub%!-@j1+bgE76Hi{dJsz8t1r^?!5M9s zDSEpm=*~uH`LND)_N5z0+mInM)7aC~YH3ON>;f@yrtTU;B5{$hSF&lbk=G$?@5T5$ z)c2)P-|EJCEs`(`hI^z4r9zwS5E!g9X8w;w)QB;A?MKry9rQrN1uO#3>!gScxG$l};u z;}pRIQ0kc(3kWHl`CzXwEUC)G=tTT;{q{WVN4qC(^t*o5QzMWDmq4(C9i_pKm^2B{$_^(TTc3{BFU#fx2OAgN(j z3@Xe-wmmJ!yLh?KwgKX-YgV8{_PNX?X_0voyUIHPI;tcb<$LXXwu?YN-6^70j9Tf@J%UU}eD z+BZk}+JTMC3d;@+rdH?0;MNP!ZKVAJyLJI85U$s%WT4i+sFtWc;2JWTA*y{PvAdpA zCsFVHM(F;o_HwTXGH!EC4wZ6J)U8on)u%Ai63zUrMwe5~FS`@7_xb6ITmr>T704$a zTF|LN_vcRZZ}5z^%x%4&x;I2GxX#EkhRoYiIszy!`HBIq9KU{h)-vvjAoLos54vS9 znL4wY>^auJ?w>bi7w5hF7Fql!o2w!9I+y=JScaG9&_Kwi=mj3}QFxHiN(~Ce2GB_js0$=NI z-DQKF)N#28+qwLp6~B0|{QQo8d_%Z&6uJ8oK|^IKsfs9Ty{JZwok9v=_ktO@VuhhK1&GqIYym5FL}&A zsCm9|hPB*-3s$Dsc43R?{s0LV$nrLfcn2Us=>8>BA#VU=wmpdAaE7TxPQC%dW<4Wc z4y0%UT_RwfmLk>F5!w^{elBk=f3E#6_EQIAV4)z zwn{>Rp05D`U=bCnW{^LWjzE>}tHqgrfp(dCxQvq%w6#1g#Q5CRm}wkj^al4a&VK5+ zvth}-RJ#MQWQzT5)(F;TD_EbikYuJrs_5f~QGck^*U`E_*fg`)f9QnSm4=b2{G*yV z9p%r!(*V#NY4iM9$}G*%r|K(;3OG6gi=^mIVQ3g=4fO{V$@5*^EqeTiK%*!1UHYr9 zJCQx({OXfZZ*VW;qfQbk>3Wiv32U6c3btl@=CXt&%wW)ZT9cFFDwa8RU-_wHWKkGq zmesL?v`~~C)f?OKS?tHLyFo5Nm=_gyOXwwcZxz*FA?MS7jv%jr05KM4ZoG^NlFSr3 zTdZ146|2#DU$Rf{gw)|a(Lk(|B5~5YV(xbUyPsi*>nQ8MFXY>C3-<60y8$#iwgVEp z<*jA_N|*AJQ02^HlzPiXYwUOQE|&fk>mQ9A5;O4aP+`Sf=3Lg?gGWhrNlr;9lcHsX z47Od^a{)+>f7{}rkiU}1;4P_4TkWdVi;-D(-jU%X4}Iq#2aKbl*NuRojqb=&DU`&a z(s#ulibouk)!S;tDQiX(5^(6V_0~coKn|~Zn=@prZ(5)Hxi~u0Z-O{qmZ7|JH>Pn@ zqfg9i_MAc%OmSCkVg-~7Y+bSWcYQDOK@4{*lRy~6e?{I-lnX812G~joxb>aY0=Pf^ zr}QLgtP*qRy_splNDA}cqw_-PSQp{a&Tg%-N;>-EW?ky24B%+};2yjs2wg%zmS4bg zoGKOSDR^wtrP?f|sXJ?7aN=br)(`hgzSAmw@sut_ho-|nlO2}cF}0d@L8V~%9JcQq zzim?q6@Wo3OJ7*ExS7yE+0!!9QRlZRfJ|!jyMOdcTqovvQIw0PyiPecK^zxn~IlG0C8YxXIsFCCuTgH5_F&Xqv(qa-1>O`SwKS~>osQj{O@htJg2 zWjcKadn@1`thyRFS`zjt19Ar+M5X7g_)ayrO*u{N+p3ZP06G4KE%}~mQsiHJ2R?u^ z@!piCAP<91T@r#7AG5wQUArIX%0*E=8`l=nIhHGWCI^A0_uT_&)B6Gnd6kYz_eu{a z?JwXaP5ICYBOFiYt)C-p_lzf`)bMfugt8&7rpsNA3#m6gZ*vmbr- zx2$Kn%F3}f`)oSax=)Jnw^(oYO8CitnAAy5UJc~Wka^b6F=<=2h(NcIEuSvoh0XJ_ zMe}unef|7rCud8}?7!_YS^1$8HZnIKK`-+C>fUiBm=!9DTNE#)HBYRMjo^luV;TRvR0j-)PwFZ=KZy~(#3cTowo zl!i0s2FM*<1zjawh@G~JPf2#q3->zugifQVHlWvU)8GwmgF%Zbnmd2fM9lO4C~UV* zKm$1AvwRz%#{d9l6c7!i8K!1QO?vZZzT%qQrljZI+b-stsmohvSLb%*UYxSl=YB#a zIiY#=2sjiWsQ_&=6Z#B-aH;TaEvvt9)TUeD@Ec>9;;lBcoXcG(-b&SS*ach%d39)3 z%$DcxVCi8&UK+vfg$B3WdI~`jpM+rm;t^yrPX%MBSNtnC$`=m4+$dz&BTuI1E-3}c zpX^?`iM?q%cGa;#*RSc$Kh=KyV+6le%ns-`CNCdEe**k-l9^{&VBOtv^tWI%df(v= z4`&`(*jeLkj$EXD$XIq70C}BVIq7B~9XN!AU#50hMy{i%FQc)8JB_9F%`Km---Hwd zx5)@zlmWu4Do)+iDe?)xGug(!sQS9+j)sF#f_T|CV|c>VOWhr59dA3*o3l4XJigngH)S3YIp03P~zI3u(HZsHICaOv!Zc(7eYA)NsUu@)rE=mXF_qj0s zl66bzJMIC8^%QxQ!Xj5d0oZ;e4rxmNHiBz(7aAXt7pf?GI3b8!yTZdR9~0q=z86i(zWN8LmRdMl)?Otw10`~5=@@MdaT-h zs8zrOSjP%pW{3g-w+6VFuCxC3NdPEvRcvroP*=<2OZ@BxcZM?<)`7XH0N`2a8B?4i zC#xeRuP=}fC@POvV@Ubk|8A2oX%+|NU+B{EW)G0p$*|h=?$o=QAq8IdPLYsyS1m)4 zI%a7{#4d{}8*P@qWObsMqp}{8hFhNsU<=eff*_|?azZ`H+u<5g|0KZA>(yCnqxAM_ zHkl;HJfZ)S!tcWG7nq;x$?S4cmSj#w?)>kx)^pmw}!VG@RVkj>azTl2O#C0m~; z4g$d0_1o`S1F}!_+Y;G)fBXs27q2!!4Sq2}w%&c0^E61Z!d+Rhe@5*p&Y9!knTHwOthF|G(vB3olIja`4T`K#uj*^?r%r#_ zq!+)l#ksp~Ok_zyzq4|IXtJ>`bYCvn86{ai(CFG?9{w@7QFOaowk3!%WWQMtYR;tV zVb`-RiJi9o9f3p~n1}Kx+fLgG%Dh`ZZ|_0Mi^3rJBxQM<^Rw~mih$=XO+pY8ri#m| zY9*c=0P66c_uWh1LvC)mx^$4!Rt-l{&ibBBcO2gT)Z!_7DF-YUW64pmXQ8Or5unHbB?9TBawO?VI5@@nMNdt64o;4tv$ z^=ufNt>cb5Vt^$H`4T;C2G;f%(`+Ka$PkKJ$QJ!>CRF(9DPUrK99uQmYaEG_zWW%S zZU@-1SaWmjCGCK4{<1J{DfKff>GjaPN$d;9^(g@exK7^fxH9n)eB>(An~U(`#x_->@q!)!3&muG0o7i0#7-a{0998hXrS+cc}v# z!(09)0#&5PJlymb@wH)7zIZ3vMTHx1u)ge1ah(x`K-7?F4gd=yyy{`ATh}q=gD;5T z*+j;~@@}qIs)4^&140t#LF=lLLD?p_(MMtKTSNt0?4P5f(t_2ig>E~F+@v|t6t=3! zZu%6HpLWLiDIIuM297sh2ySntPwiTefXjU|>mGNUn z`lmdoA3MI>QBer6R~}t2h~=fR+iMR%tycjqGH6R9f&etvx5FIuVJ5~*_tRFjVH*Z9 zpB6A*X?D2hk5iLksq~FugpIyxn(GFh{u(49^5I#=?#si)kF`6Q!Arjl(-q?vX2;a^ zn6};bYUC(-{$#7svy*AjDC{gw3#X20?|XNp^6uc7#^1v{rTBU zq}td&lJ)lwBKx9I^S;M2f{{0WUD(AlJdMUStak~^Va=#+tbsoWYjss%VNBYUBpbu4 z%mFL5VA(8%VZfr$$0L_X}_9E8?dR(aW?pwz4KQ`AY= zY|-i(USpUakAP;-K4Q^znqHK-85`@XNmH<#P%7(ZJ6jBXgjza{8D#gepLU#~-)p5e14HEfycjUdiCvq$O64vv zuj_!q)W|LBFl~N!T0{wl=PDBhBS?`?Mb&puWW4pLPaNcL(hjnp7*|M~8BV0$qlQzl zCV2|19QrtjM$Uh0(;p%EqD9U8+`Hl>pP`zr(X=`m&u?J1aOWfYheh3AajE3LL2q-$ zBo6WgI%plt4*n(pQU;L;bYE0R)IM-HM}G?dtPg;Pwb(tmlmdTz^Eg@$qi}fTb7Cjv ztK846FW5h-JI@p~8Sdy`;i(Z+C{F(w7O)Bsq#FZ1lr_bFKZL~neD1%NfU^|-0Tsu1 zVEV3;+kuYr>U^Sute*Z?G5A7#PCI=~f9(rR7}GJ8OhMJSP}Y5|!j?9{Q1=otL<(%r z$YEa?N2&F9ZR?+(#AkUWow2)x>BzL1~Ir?69 zMBrA8#wyGH;9e&Iw5pZ&5K;>=rpVZ*>ov&X)nQ`K>i@OQ!prft}Shr zT9|E>HwA$B{$Ec?$&^ktO|v2WooNZlEHjb42X$QcY5j6&iNuEnZ|IR3%~<3r{%$5c z^X`u8>k3WxA*jjITP;fY%+Ii5=1F_87Y+*}MeoXa2YiBwCm%d{|FRR~M|kELm_yO3 zp6I{xwcWQpUZ3jK392uzHdldV*J8(Gs_-Yqv2xgX88|dwY)u8#c8eIi=2&r1@Wz#8 zR!8T5UY0lC8|DkXUY9ZeUa$+ znqLcR0#VcC|GEgWc?1+GAJC-dg!)}z8XtU__PvQyx845PwfMP0O=%r@UG;q^&r=kv zc!(>yxoED$NDYaqOC-=x@jx!p^5)ENuh)SMLlk|o5-KEi7fWg$lA}mVGDa-<{ctkC zR>o@^PdoLU-j|2aKNVI?^xm0SuTXCqX|dO~!?Rnq{ML9t&Z#;f^s;rUtXFzxf_-ld7~=RU;p#@nT6#3WMt^gO6!IPGTDi4X1qgPa6>t=x7~gow3Ak#@gNSb4}HpJ1E&pUyYLbz(7CY#!HD zOJR)}ymupDaCz`f7BHo1Qk}@7^G|>;wS#tNtbm!&eD=wg3}a;^WfvWIN62u$5@~$- zyY$8ymRt@rcY;kB$Qg-S8P=@cKNYvGj?7RJjYH2LGMWGz`RWqkW1{NvYt4X1$V9OZ)9Ap z6Vk8K!qpcL-rCS`(R_hqWOs@>LIJ2VBLv`?tfB`4E6A34Z7|9sb{zZ`I7(%80mDY2m=5f1E^|-Fl<%1Lx3G0DK179%B<3SSvoYR1a&+;4#N zBvq7c9q?TkR(wfV3|?TS&O1}}tHJMP>Nn#%z=Pf;ea~IWfIvvCBxubY04>Rh_^$LB ztGDW$m2>e2X z-a`4{QOgZyM$!*QqrkFD-WMV#+rFf~6|DfS8yuT+iw^%xA6KIqb*4N^{?C<;ytoqv zUAzjk^`v}db6}G*H29!c;nrL>!%S}Je$X1c{J;Qn)xbaY0K{%yUI9%=T^Aik&!PiM zb|Al_1oT^kj`mgF@w-ajcYCxMZo0NEIH}<9Ew54Dd%X;QH_jV9RbT0~D|?%^B3Dx@UIDl&VD3`qUJl z^MP0GCg*su2y|>aKzsX%0Eau~6J1iZE0_AOfV0?t7xy-#m$%Shh8)J-Yv{guSgj9QFD)361*@)nzF;~t&E`SQCC;}&tPHG(wqss zkpq+MJnUlC$z|HPPxLefM?!k>l)97grp{v5a$`~9`a=ksIIvH!FopUMvS}sKow+~f z?>b4JIP}zcvA-6;J9<+|@Xxqi<{%NPVDH5X-9MUEkpIVQ+X#JFkG(M;D4i1KD8`q3 zCd(^p&WXt9c;bOeje3r1L^YwB$zkJ!z$5LlDV}x71C@2-D==?+-rIzi2|1p2W;Y(% zZzb)5yF@t0}k zpT!g%cwPWMvFY=0UO1Km9Zgf>LAdEB!cA(&&?DFi$#{ZnO`}ON{<%G`&kq|pjRKY{ zgdRB2;$R|4)-+>O?8B%~WjD~)INvN^JNaL0V{v?rjy`R^CLkBgj&$v2lZ?c2x`9pO zHMK-6*%-kw(c;}{$z>+o0bSpnT;q`c{883IE^oDKf)3gFrn@V?qn+M6l=j*rR!w?JjSNgw<73D$@$1nbN{o}rYR4_2PK)&H8ZIT}#|qqhE@RmN zk_pr4(2LyIp}7tG5OZPbMFq#I(H^O>`kC+(&DY@V*4?o$x9r)0$%{rGKRy%=-aqhe z=6EnGRYwnRTQZtau~2mND0}`>fIh>nto)VBKhNEBVJ8m1j|WHLPBbO*T?0Q6 z$Pr}W=Oe6pL&WFuCxZKHn`&p;uo~i-zfZI<60-Qcn>RHdv3B26UY3irxlk$^cH1e_ zX80bUuy`6iA=N&6uEmEhnpCOFp{wzI==87Hbb34$hf`8;unhaw&1J{n+_7<+b)-z9 zUhUX+I3UrwO-JqZZt0-_;N{)MndRvpX>Cz1BfXqn(@73^uEe)DZu@uUD{AAGB-F!h zuLm%pegzhV68nvl+${{8Fr8DyMkhaZ5ND9 zU7&;9llhbX+O5a8JFg8{(nZg2e5Q9=Q1@&)SM~eA0Mh69sk;TCR4IMvl9|x9i$G{w zAotVMdB=Q$lVbj|tYECC`ke}$Nw1$Ft2uW&U(Gat>mMgq6P|!>;qt5PaBKGxl1u`8 z&^EoX^6n`@&*?5}16;-m-pMg+4Eu>5O-;BC1Yx8y4 z(F2QWo0dhgoy~0PmSlwOD^6DT%S#AOQvnn70f%8g4ZNrRVxqu%4P55(Rz z>87`Nbjl)4G@dx6w6)V{6=*+l54M^0ZMPy%mmEtjTKwXhg8wML6T`eX+R_;JVF5)tfhe72% z?0`OGAl--)eM|y7qJ}Gz@6c#uRci@eBsGJ3K;J?Dr3>(!zD4AdaNhSVSN4L1D$OP3 z8=q;GX$ABytaV_4_$=C~Bw%*`vE++N^XR!ovr)%p@1s;9zYf_Bg_#DvdNcNlG8}r; zDhw|ku=!Y$Lc)no121yFNo7!NrQ z46sgaBP*S1r|>`t!BB$H#hl|a^EzY(?|ykxUIYyV8`rDj_Oja#9fS;&tY5N=qQt>P zmZ+pjpCfdW_}5p2uAJ7RVT;0wgDOML{O36WG~_w{Ux6!Uz;r$g{3q1(vTGoKHT3w+ z8g|I}#yI$uYJdFAk7Jz{zHKYKB#EF=3=P?(0`m5Z2qgI^_XMc|Tmj3Bb_ICf2UN2g z<6Xn}pzze@n9J8m#B!QbV^`zYnsFm@Q=Jcc^i^TMB4prg{gGV+F<5{Ca?BrfdZ%5x zlmn0wPAFk(&YTa4+1}Wdyt={zd{2k0AXa1x40`bL%_h+rsb&yi1jLF@*H#>thdXxY zDU9`{N&zL^Wr5{d1Fj^Q0m8W%a8x@$C_hr#C%9e|1+3gopcdGM{M?4&Z+P7g=YeZCAuhHDwTvc#CtNcHaxx7YxQ$qv8NfIs(`{ zL6G1-{v!$>_*MYqF>M&JV`$b1fI(eVk-dQ-KzCk1x1_0ZOn{H6ksSuQMZs7I%Ay-a zp(G2p7>a%R18TOCt+o|6Y+!!&@}1pQ79~x&bE%*|oGY0tohzFwpQEk7C8gky;L(|d zqNxH?@%uogrpOfffsz*eDPkg3Q(R;F#J6&%asP?b@|--*2#9|$>xo*V;1lp(Rsxx> znR0^s+nJ$;Zuz4wh3_165^sjcsKy`9nUg^wo1Q1Hit&Rm{Sw?>hVX;)P?X!Kml}}h zSUFJLuSw9OBi#*ur}lnAHu*P3CL1$(v3szSydA1=C=*EUhCTUPt}WeG^aEZK{FG1G z$>-n>ltf5+P_wcZFoJey@ftG#`8ke0;0;#Q5#ZUka$A6}-yr^?rccn6Ny@Cz{E=0? zIGv`ejjm}Iy~ZpZH*oSSCh2s`57lo#) z$R5V~+?Y+hy)k3YB+pOa!9@rvwaNihO=0C=sMGHa%s0R(N^RwiVA{pBX9^qsf~i2w^@bW7o2eo!#=u?x;vfj8(KC%3S^U#bg}A{32pW7R7iVe& z%vPIT^j#F0$9e^GZlsCQ1s3QL#|WpOqk>TDi-BX6a^ehmjO6bCu~JXD(G7aTY*r!B z=K4du>=iutgL8G3 zbFV>m{(~%DosbIzYj^x-($`Z2I*O#$@?3-0+6=akZI$y=X1hOp{Cf=y(5@$Y`yr z5^h%o8C`yTiYu+luTur~kzgRt+pi0siF*9J^VbE7#QFV#!V>b_lv(A|rJ$vd!qCi)MZMd~i-; zx(JDJ+!8Y%4pO1xo@La^avj;+cKbZvb$ax3Kij;^iXfn64wOz8_*r$ZS+Nt``>a6>3=wB`%wfVtzMZLWrHhoNSat?9 z?-mRHDsmiCwx(_GlvxZxA?|-oRwtPAE&hUwVZr-bbijC}d|O%G|5OI8qJUswJ}*5# zeCLWv$Fb_ZdFI1l$=f68fbaW%pgM`M3@a^U5R>ill@@r5l;uiN?+CRl{fvdKlCqN$ zlH~23B}n_M5?E|_TbE&}mbKFaownr7;jmCgU;_$hp45#PgQm{*a0Apo3qZ>?cAjO1{bi?Fgn{<%4 zEkH=h47F+gQQ(^36!bi~)-||(SlMFA)f8v6y}!z`9f$*6BWrLy`i(Y@cJBIiPZ?!Z zZ8?bkI@u{C|B4)GVE$P3u<}!?Zx5g?M5d72TG5&>_zr>43y2-bdw)j0w=8c*UyNVY zW3BC-qSsH$yW&qIMFM4d=RRoNiC}KTGwr{QA5ta2fx1-7=9bn+!@E6TZzNvG$TY^= zS)kOYEi1L}=`7J`A!ka*bU6l@{M?Dmm!Z1E*nE&uz5IPd2-ndL1MR(L1P@wG@@O@` zt&W%xZX7qb0)9Wo%z6pH%yM_trG4__V$}BHjdd<4G~UHP2p&)@jeCyVVD*9Kb3nmq z`-#sQd=EKG9E-D8l#Ej2O>oq{usv6Mv&W~^U}8`5=*5}TMpf_p=GQjKtHF(1{4X@w z0@PO1Yq?Zo*5F_8L?O&^y%(koxE3pw=z}Fx^TO0d<|*S0LW&nHbBqD4y5@|d#x)xe z#=`;iU0xm#&B3{`^%nco?&4nob9Ui-#rsJD&?Q4WAaus*kaUEZN9 z;s2%s1y?$6wr}g(uH3wY{2}R{?S|(HYEJOUOyY4Bh(t@^NVtQdI<{o6U9_3=Srj_F z1cD^a3!~yJtMMc}5sJ2%Y~!;CSl$myHOiG5Al9NxF`>KQ-|IYz%@3*WybT-fLmt|V zAIeUWlS44~AY?=;6ls!dv8nApO`$j#Z`y#nKUPyavjIV9?sk!3>BceE!6RKyE{wvK zI3BgY&n872V$WXk(+`%CfQ}^ zyoa?Pik?n!K}uoaJ$yic;F0jdHv7skG~Yqx`?5`;XdK`v!Sw< z`nLu6UyQo5X=hT8Pe9Ajbeqt$tE^hnz!igzloe*C-O%%|j-v1_Igo$a}IH5d36H88SQSDM<$1t#`I2+lSdq8HD z_!lT?yfAM+&5Xai$n>R<^d!A+rc%eBMJdr+9(L61PoGsCbBpMJ7WO*kH9~!|?A+4M zcNbw-^yj5hdF&Q1_pu+xW5~SYxfutB)Yg#eAqGOT5&F=gYcON{92d`YV;4Pke%hF! zcF5;y-=Fw%CqcUt`0+AA*lUuL+;c>IQ4@MRq&INy8G7T1Hd64rvDaHpKd6ne@o=vZbRx z;!rh+44!hRo%D@|9^?~4o&j+aS2B6wJa%#bFGu``m`(s$4^+U4 zNw|xZwb#uM#Kj4E1;1Em6oT!RWTE_xL%q#u+*(-6gBm72G+uv zxEr?ehK*;}b$N9U0dYD{wXi>T{7~Ac)SPSZqp@C|$u*OA3xYScSKHl=pKGy;m;3ka5JT+iXv>66Ee9Y&$bPd)L>7B8drpkUjg;) zt>1t!z-obmDa2b0C+pAR|NfhRq0^hxal`FjETimFjVDkR^q~ZM%Lpbe63%&cuCW&y z#IpK)o|;ChWH!&t-hz*x91r`p0dmB0dkt)vIh+w5CQi5S)G9Ok)me$ZCnT>$TQXIh06aX6I3s)b#`Oiz|K&JWSSjKV>)CRs9S83 z-GFmB)O3Ppfp|(GjOJSf7Yt{aOFEo;uqyI}sUDeCx2Ch@fM0IvFTOFW`R-jxm zz$55dAkvTx=n`X&9HdUec6l{J#XRw53>EL$DpxwsmI}PmxEC9p+H*r!#j`dO(jG`)aS*k;c41}hV$p!>Upvn~obud;}bRfgQoe|u(jB2rVnPu^a^ zj^nCC+%s$Yt5Rk4V3MzyZF@tsIs+570|Z>2m#c;$8iCz44W5N-PkRcbL|cV@1ND`q zP--8Pr;w}5{!-{P>SDly2CCYj{;s974*T$b6fo}3#L}{vUF{rKARcOFp2zXb%jO%& ztR4{b!qC^i&|h!lkI4?iCk}R*VGXp04AXmZ3bzYRDmZ;svoiYFtbd6LIti6M5a(jb zd)&7lwR@Fzu3_Q*7(kxzBb6vr^&CI>+R;)M!iEmDlq}dUFlTPU?T-4o&ngpkIK$Y{ zwiNQZ0NJ4x(1U__WJ0H7> zQtw^cDNl)*zuGv3=V*N{Cn{K8P-~(BO;8dhY4*Urw}bOr+{V!Yb+bNlN_I9uLf!ws z$Adk$D5;NsS0$)l(4?+gj>w{wlf?M1zo^(->PJ?2@3Ym-^|e$Vp9)c#D{kmei^e54 zNh6lSnqwhz7eW6{R9DH=2~+48h}LxgXVDF`0Zl-IBU+e)-to+VxQP$1Z#1Ndg5Gm+ zYAC=Pjo?+RffOV_cLM0^v`?+=CxC!24LX7zXtebSm+zMVytAG!%l$YLlOK>XKPCADu5xq3l0m8g4`PwnJ$>dqD;lH zBM};C_VP|7eD8oDuGb%t3f&xKaPxgYVT^?;(D?ECJcfh1kM#u*Lk5T^HVa0`8V?Ps z4Uo4vvf{sf%>akwR%9-RLxY+R7Y6opcb`ottG3-{tAu(jl*AUGK5`;#%BckYK5oeKgJ-DYv&oy^1$0#l64mkuP!EHlOo+JZ8esNn8(>a$Lg1z6zxl8- zL$|(#5(xV8*X2!qiX}L|x$zv0(0%hPgH~oAJ@}?YV=m~d4jt%tAh-y`3z4m5fxM|B zF2>ZpK%*<6C2#%+kZ~mM1Oxxk>vEw;^}txsUfCz$_-3SMPnWT{yVdGE*1}J!YBkPL zQ+ovt#2?b&K)gH~t^H>bCM=zIFW(e02Q=X+B}d(Ka(krQg&b~2+b$W_)#@=~s^x_k z=`=@RlqHxY%|7LB9hlQw=bcBjP8Hmc_G0IwwBmY+_FA(+h`_(& zK(&A?feu+;z;jE99{?2gfB)gwf9ZzaOvH(AeTxo-&;H1~?j6M_q literal 0 HcmV?d00001 diff --git a/orange-demo-single-web/public/img/icons/apple-touch-icon-120x120.png b/orange-demo-single-web/public/img/icons/apple-touch-icon-120x120.png new file mode 100644 index 0000000000000000000000000000000000000000..1427cf62752646ad7217df0a61aa01fdef7475d1 GIT binary patch literal 3369 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 ROru=^AazZ3N)e9H{|11FNXq~K literal 0 HcmV?d00001 diff --git a/orange-demo-single-web/public/img/icons/apple-touch-icon-152x152.png b/orange-demo-single-web/public/img/icons/apple-touch-icon-152x152.png new file mode 100644 index 0000000000000000000000000000000000000000..f24d454a2ecb8851bb893192b64ee09386d30e24 GIT binary patch literal 4046 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 cK^5JQ0?3d{m_4Kdj*!1;003@kYpI!lw*K!+ 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�MrHbYR_buu=L>f*wO=Er8~{qfkYT+HoHag8)VqJoC-#@ zNT})4xRE%sP-B9?xmL5!2Y8VLa?yj@Y@r1C)6o~9GF9nWG!SI2VJ$>ejtUE%Qv&r_ zYLgZ0h3iIrw7{TyurC(g^$XT%PP5`FB3aFpP&fM-8!J#3I_ujG?;7(Xv5ni%BjYP4 z^+oydy=)_&bdxYJx`X%G5PFkUB%3h6RiOs^F?#ojsB%DbfhqzGhuv4)S1%vw@PDyE z3xWF{Y^0>+=Wg! z{>z@$rD6ej*V- z^$zKIOWOfdN4~7@ndhru01+3cxwD&_Muyja({*O;-5VnF(e$WDALNStE{1{F#ts+VR{o zSlQ*@U=Du8fgKW$lU~)O)b6FS?H1SSnKVIC=DOvbo8IUvM zVf+U4YxG%qLGd%ew7Jp8>@U`ew+A#Q=2oJHNH@_f!WadS20$KZEZ+BHAvU@FB zzRCYN5r+Z#g`C^hrH$yW7ABstwjvMM*CHGzY41bbo2zy$6E8DAOPn zUnHG?e7?u7pQ}Kqbu1jEd+=mcGea4aL6V4g(m*b7x}z|ijsjb3e|tf-3&^JK{=sWz z8sqIu9jy)#J}n}cXqtXmkb-NDVPcAKn=G9uX42zYvufu_OCr>xJ=oTNp8WA5wEqvM z{r~m8;7_C>U68iRr@|rd7UYhON#(-S_+Uf>s)hhPU{{exlxc&eD literal 0 HcmV?d00001 diff --git a/orange-demo-single-web/public/img/icons/apple-touch-icon-60x60.png b/orange-demo-single-web/public/img/icons/apple-touch-icon-60x60.png new file mode 100644 index 0000000000000000000000000000000000000000..cf10a5602e653bb126332934e2b7f34081c19a01 GIT binary patch literal 1491 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

aZW9cb|x>1jZDoAu$NpeWiVk@{x{! zmmBmDgx|qNN?LyIrl9$qmj{KjZ8zpa=4edK3FuFS$KFl}bWPoO*Ax#Z1c2#3JAN(O zYhi>`%H9fSnLkAq|5vs>+?U*bdfMc6TmDu+QqnN9xgfZsG25($^;v7U1nBl9Q^o*i z)&?UaYZ=~7XZa75xPKB1s~MB1m<*dN08pqiy*q!)_Kc|;EZs3&nNdMQ5#LFu+J z?*($vO)$hkMOVc16f-ep;K@_~&Y6t?0t9I0(lBkZBfic|u)3pK$Xv=A@jUQnB2sC` zbI)L9m;VNkWOao}2c3b4_u4+bg zuf-@d1$?asdD1~mORQ02#!&1Xm#41*xz}wETNqKb;kueQ*~OpcAXTpJFYUYcKoA&Z z8Ke=2Vh~cu_uTb&6AH75L!k8zo~&wRsDLs^3YkD2!~;%u6sFrzV2A5(FQ|3}+0-K- zWX)W2yq%?^)iKhyMGPB5*DnWBaLqAHLJ47;r5nvkeq3u_?J{Xaf_}6I+xpLwKS7NC z|KYU%zup)8i85jc)^Yt*I0W8;+zHUI3V7@o;3DUYasdq>DFK%im4J)F?;|B-<=}8R z>HESGa5)KyCnGII|E+YX&h4Y+xCRvyX@oGhhG4 j58+{W$RJv~NLLKlV4)8v^7hU(R-4l(}$teLl` literal 0 HcmV?d00001 diff --git a/orange-demo-single-web/public/img/icons/favicon-16x16.png b/orange-demo-single-web/public/img/icons/favicon-16x16.png new file mode 100644 index 0000000000000000000000000000000000000000..42af00963d81b8e39a30435c60ac482d1f8756e0 GIT binary patch literal 799 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJOS+@4BLl<6e(pbstU$g(vPY0F z14ES>14Ba#1H&(%P{RubhEf9thF1v;3|2E37{m+a>WRE8{w#)hawXn|-Xp4{E;v!=;4B^%-x&;Cm1 zP>^*#n_J!T^1SBMI!C4h-R53dN8`?ylD}d{L%(vZvUKT)~-CgWFQy3lt zIqW5#zOL*K8HL%o&D;R|TePl5?VWhq^wrj^qed%lKKkpp-FogeyEi+p zE?K8rW7E1fuEJ{5jaaAp0~aIt+keS?T)@vXM=*X}V#VGMCm1~v-+0wr{w3CJ-R8wG zS@XVpzqP-5Mf0H?y-zh=XVL>S6E;rKnDmrMQlmoKbK9p$evXN`oe{6g>lvi)-+#c) zb+Al&$zRqtWk1@VTt6MPmq9d7^!kmXZn8k{sFt`!l%ynwlArU1(iRB6fMfqu& zIjIUIl?AB^nFS@u3=9=>9)IHDC=AokIOTu(jOWuJ24-b$y<~1-Wnu5hBFw@HE)6D! wQ<#-EhbWxBaplC3Ge=~Ou%B-5Sm33{@Jd{;RG<|Mp00i_>zopr0DGh}-~a#s literal 0 HcmV?d00001 diff --git a/orange-demo-single-web/public/img/icons/favicon-32x32.png b/orange-demo-single-web/public/img/icons/favicon-32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..46ca04dee251a4fa85a2891a145fbe20cc619d96 GIT binary patch literal 1271 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 + + + +Created by potrace 1.11, written by Peter Selinger 2001-2013 + + + + + diff --git a/orange-demo-single-web/public/index.html b/orange-demo-single-web/public/index.html new file mode 100644 index 00000000..37e411e8 --- /dev/null +++ b/orange-demo-single-web/public/index.html @@ -0,0 +1,17 @@ + + + + + + + + 橙单工程 + + + +

+ + + diff --git a/orange-demo-single-web/public/robots.txt b/orange-demo-single-web/public/robots.txt new file mode 100644 index 00000000..eb053628 --- /dev/null +++ b/orange-demo-single-web/public/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Disallow: diff --git a/orange-demo-single-web/src/App.vue b/orange-demo-single-web/src/App.vue new file mode 100644 index 00000000..907f4e8c --- /dev/null +++ b/orange-demo-single-web/src/App.vue @@ -0,0 +1,19 @@ + + + diff --git a/orange-demo-single-web/src/api/Controller/CourseController.js b/orange-demo-single-web/src/api/Controller/CourseController.js new file mode 100644 index 00000000..daa782e3 --- /dev/null +++ b/orange-demo-single-web/src/api/Controller/CourseController.js @@ -0,0 +1,25 @@ +export default class CourseController { + static list (sender, params, axiosOption, httpOption) { + return sender.doUrl('/admin/app/course/list', 'post', params, axiosOption, httpOption); + } + + static view (sender, params, axiosOption, httpOption) { + return sender.doUrl('/admin/app/course/view', 'get', params, axiosOption, httpOption); + } + + static export (sender, params, fileName) { + return sender.download('/admin/app/course/export', params, fileName); + } + + static add (sender, params, axiosOption, httpOption) { + return sender.doUrl('/admin/app/course/add', 'post', params, axiosOption, httpOption); + } + + static update (sender, params, axiosOption, httpOption) { + return sender.doUrl('/admin/app/course/update', 'post', params, axiosOption, httpOption); + } + + static delete (sender, params, axiosOption, httpOption) { + return sender.doUrl('/admin/app/course/delete', 'post', params, axiosOption, httpOption); + } +} diff --git a/orange-demo-single-web/src/api/Controller/CourseTransStatsController.js b/orange-demo-single-web/src/api/Controller/CourseTransStatsController.js new file mode 100644 index 00000000..9b42412e --- /dev/null +++ b/orange-demo-single-web/src/api/Controller/CourseTransStatsController.js @@ -0,0 +1,17 @@ +export default class CourseTransStatsController { + static list (sender, params, axiosOption, httpOption) { + return sender.doUrl('/admin/app/courseTransStats/list', 'post', params, axiosOption, httpOption); + } + + static view (sender, params, axiosOption, httpOption) { + return sender.doUrl('/admin/app/courseTransStats/view', 'get', params, axiosOption, httpOption); + } + + static export (sender, params, fileName) { + return sender.download('/admin/app/courseTransStats/export', params, fileName); + } + + static listWithGroup (sender, params, axiosOption, httpOption) { + return sender.doUrl('/admin/app/courseTransStats/listWithGroup', 'post', params, axiosOption, httpOption); + } +} diff --git a/orange-demo-single-web/src/api/Controller/DictionaryController.js b/orange-demo-single-web/src/api/Controller/DictionaryController.js new file mode 100644 index 00000000..636ff2e4 --- /dev/null +++ b/orange-demo-single-web/src/api/Controller/DictionaryController.js @@ -0,0 +1,155 @@ +import * as staticDict from '@/staticDict' + +export default class DictionaryController { + static dictSysUserStatus () { + return new Promise((resolve) => { + resolve(staticDict.SysUserStatus); + }); + } + static dictSysUserType () { + return new Promise((resolve) => { + resolve(staticDict.SysUserType); + }); + } + static dictSubject () { + return new Promise((resolve) => { + resolve(staticDict.Subject); + }); + } + static dictStudentActionType () { + return new Promise((resolve) => { + resolve(staticDict.StudentActionType); + }); + } + static dictDeviceType () { + return new Promise((resolve) => { + resolve(staticDict.DeviceType); + }); + } + static dictGender () { + return new Promise((resolve) => { + resolve(staticDict.Gender); + }); + } + static dictExpLevel () { + return new Promise((resolve) => { + resolve(staticDict.ExpLevel); + }); + } + static dictStudentStatus () { + return new Promise((resolve) => { + resolve(staticDict.StudentStatus); + }); + } + static dictClassStatus () { + return new Promise((resolve) => { + resolve(staticDict.ClassStatus); + }); + } + static dictClassLevel () { + return new Promise((resolve) => { + resolve(staticDict.ClassLevel); + }); + } + static dictCourseDifficult () { + return new Promise((resolve) => { + resolve(staticDict.CourseDifficult); + }); + } + static dictAreaCode (sender, params, axiosOption, httpOption) { + return new Promise((resolve, reject) => { + sender.doUrl('/admin/app/areaCode/listDictAreaCode', 'get', params, axiosOption, httpOption).then(res => { + let dictData = new staticDict.DictionaryBase(); + dictData.setList(res.data); + resolve(dictData); + }).catch(err => { + reject(err); + }); + }); + } + static dictAreaCodeByParentId (sender, params, axiosOption, httpOption) { + return new Promise((resolve, reject) => { + sender.doUrl('/admin/app/areaCode/listDictAreaCodeByParentId', 'get', params, axiosOption, httpOption).then(res => { + let dictData = new staticDict.DictionaryBase(); + dictData.setList(res.data); + resolve(dictData); + }).catch(err => { + reject(err); + }); + }); + } + static dictAddAreaCode (sender, params, axiosOption, httpOption) { + return sender.doUrl('', 'post', params, axiosOption, httpOption); + } + static dictDeleteAreaCode (sender, params, axiosOption, httpOption) { + return sender.doUrl('', 'post', params, axiosOption, httpOption); + } + static dictBatchDeleteAreaCode (sender, params, axiosOption, httpOption) { + return sender.doUrl('', 'post', params, axiosOption, httpOption); + } + static dictUpdateAreaCode (sender, params, axiosOption, httpOption) { + return sender.doUrl('', 'post', params, axiosOption, httpOption); + } + static dictReloadAreaCodeCachedData (sender, params, axiosOption, httpOption) { + return sender.doUrl('', 'get', params, axiosOption, httpOption); + } + static dictCourse (sender, params, axiosOption, httpOption) { + return new Promise((resolve, reject) => { + sender.doUrl('/admin/app/course/listDictCourse', 'get', params, axiosOption, httpOption).then(res => { + let dictData = new staticDict.DictionaryBase(); + dictData.setList(res.data); + resolve(dictData); + }).catch(err => { + reject(err); + }); + }); + } + static dictGrade (sender, params, axiosOption, httpOption) { + return new Promise((resolve, reject) => { + sender.doUrl('/admin/app/grade/listDictGrade', 'get', params, axiosOption, httpOption).then(res => { + let dictData = new staticDict.DictionaryBase(); + dictData.setList(res.data); + resolve(dictData); + }).catch(err => { + reject(err); + }); + }); + } + static dictAddGrade (sender, params, axiosOption, httpOption) { + return sender.doUrl('/admin/app/grade/add', 'post', params, axiosOption, httpOption); + } + static dictDeleteGrade (sender, params, axiosOption, httpOption) { + return sender.doUrl('/admin/app/grade/delete', 'post', params, axiosOption, httpOption); + } + static dictBatchDeleteGrade (sender, params, axiosOption, httpOption) { + return sender.doUrl('', 'post', params, axiosOption, httpOption); + } + static dictUpdateGrade (sender, params, axiosOption, httpOption) { + return sender.doUrl('/admin/app/grade/update', 'post', params, axiosOption, httpOption); + } + static dictReloadGradeCachedData (sender, params, axiosOption, httpOption) { + return sender.doUrl('/admin/app/grade/reloadCachedData', 'get', params, axiosOption, httpOption); + } + static dictSchoolInfo (sender, params, axiosOption, httpOption) { + return new Promise((resolve, reject) => { + sender.doUrl('/admin/app/schoolInfo/listDictSchoolInfo', 'get', params, axiosOption, httpOption).then(res => { + let dictData = new staticDict.DictionaryBase(); + dictData.setList(res.data); + resolve(dictData); + }).catch(err => { + reject(err); + }); + }); + } + static dictStudent (sender, params, axiosOption, httpOption) { + return new Promise((resolve, reject) => { + sender.doUrl('/admin/app/student/listDictStudent', 'get', params, axiosOption, httpOption).then(res => { + let dictData = new staticDict.DictionaryBase(); + dictData.setList(res.data); + resolve(dictData); + }).catch(err => { + reject(err); + }); + }); + } +} diff --git a/orange-demo-single-web/src/api/Controller/SchoolInfoController.js b/orange-demo-single-web/src/api/Controller/SchoolInfoController.js new file mode 100644 index 00000000..c66096ee --- /dev/null +++ b/orange-demo-single-web/src/api/Controller/SchoolInfoController.js @@ -0,0 +1,25 @@ +export default class SchoolInfoController { + static list (sender, params, axiosOption, httpOption) { + return sender.doUrl('/admin/app/schoolInfo/list', 'post', params, axiosOption, httpOption); + } + + static view (sender, params, axiosOption, httpOption) { + return sender.doUrl('/admin/app/schoolInfo/view', 'get', params, axiosOption, httpOption); + } + + static export (sender, params, fileName) { + return sender.download('/admin/app/schoolInfo/export', params, fileName); + } + + static add (sender, params, axiosOption, httpOption) { + return sender.doUrl('/admin/app/schoolInfo/add', 'post', params, axiosOption, httpOption); + } + + static update (sender, params, axiosOption, httpOption) { + return sender.doUrl('/admin/app/schoolInfo/update', 'post', params, axiosOption, httpOption); + } + + static delete (sender, params, axiosOption, httpOption) { + return sender.doUrl('/admin/app/schoolInfo/delete', 'post', params, axiosOption, httpOption); + } +} diff --git a/orange-demo-single-web/src/api/Controller/StudentActionStatsController.js b/orange-demo-single-web/src/api/Controller/StudentActionStatsController.js new file mode 100644 index 00000000..8999db45 --- /dev/null +++ b/orange-demo-single-web/src/api/Controller/StudentActionStatsController.js @@ -0,0 +1,17 @@ +export default class StudentActionStatsController { + static list (sender, params, axiosOption, httpOption) { + return sender.doUrl('/admin/app/studentActionStats/list', 'post', params, axiosOption, httpOption); + } + + static view (sender, params, axiosOption, httpOption) { + return sender.doUrl('/admin/app/studentActionStats/view', 'get', params, axiosOption, httpOption); + } + + static export (sender, params, fileName) { + return sender.download('/admin/app/studentActionStats/export', params, fileName); + } + + static listWithGroup (sender, params, axiosOption, httpOption) { + return sender.doUrl('/admin/app/studentActionStats/listWithGroup', 'post', params, axiosOption, httpOption); + } +} diff --git a/orange-demo-single-web/src/api/Controller/StudentActionTransController.js b/orange-demo-single-web/src/api/Controller/StudentActionTransController.js new file mode 100644 index 00000000..bada6b3a --- /dev/null +++ b/orange-demo-single-web/src/api/Controller/StudentActionTransController.js @@ -0,0 +1,25 @@ +export default class StudentActionTransController { + static list (sender, params, axiosOption, httpOption) { + return sender.doUrl('/admin/app/studentActionTrans/list', 'post', params, axiosOption, httpOption); + } + + static view (sender, params, axiosOption, httpOption) { + return sender.doUrl('/admin/app/studentActionTrans/view', 'get', params, axiosOption, httpOption); + } + + static export (sender, params, fileName) { + return sender.download('/admin/app/studentActionTrans/export', params, fileName); + } + + static add (sender, params, axiosOption, httpOption) { + return sender.doUrl('/admin/app/studentActionTrans/add', 'post', params, axiosOption, httpOption); + } + + static update (sender, params, axiosOption, httpOption) { + return sender.doUrl('/admin/app/studentActionTrans/update', 'post', params, axiosOption, httpOption); + } + + static delete (sender, params, axiosOption, httpOption) { + return sender.doUrl('/admin/app/studentActionTrans/delete', 'post', params, axiosOption, httpOption); + } +} diff --git a/orange-demo-single-web/src/api/Controller/StudentClassController.js b/orange-demo-single-web/src/api/Controller/StudentClassController.js new file mode 100644 index 00000000..579b88e8 --- /dev/null +++ b/orange-demo-single-web/src/api/Controller/StudentClassController.js @@ -0,0 +1,65 @@ +export default class StudentClassController { + static list (sender, params, axiosOption, httpOption) { + return sender.doUrl('/admin/app/studentClass/list', 'post', params, axiosOption, httpOption); + } + + static view (sender, params, axiosOption, httpOption) { + return sender.doUrl('/admin/app/studentClass/view', 'get', params, axiosOption, httpOption); + } + + static export (sender, params, fileName) { + return sender.download('/admin/app/studentClass/export', params, fileName); + } + + static add (sender, params, axiosOption, httpOption) { + return sender.doUrl('/admin/app/studentClass/add', 'post', params, axiosOption, httpOption); + } + + static update (sender, params, axiosOption, httpOption) { + return sender.doUrl('/admin/app/studentClass/update', 'post', params, axiosOption, httpOption); + } + + static delete (sender, params, axiosOption, httpOption) { + return sender.doUrl('/admin/app/studentClass/delete', 'post', params, axiosOption, httpOption); + } + + static listClassCourse (sender, params, axiosOption, httpOption) { + return sender.doUrl('/admin/app/studentClass/listClassCourse', 'post', params, axiosOption, httpOption); + } + + static listNotInClassCourse (sender, params, axiosOption, httpOption) { + return sender.doUrl('/admin/app/studentClass/listNotInClassCourse', 'post', params, axiosOption, httpOption); + } + + static addClassCourse (sender, params, axiosOption, httpOption) { + return sender.doUrl('/admin/app/studentClass/addClassCourse', 'post', params, axiosOption, httpOption); + } + + static deleteClassCourse (sender, params, axiosOption, httpOption) { + return sender.doUrl('/admin/app/studentClass/deleteClassCourse', 'post', params, axiosOption, httpOption); + } + + static updateClassCourse (sender, params, axiosOption, httpOption) { + return sender.doUrl('/admin/app/studentClass/updateClassCourse', 'post', params, axiosOption, httpOption); + } + + static listClassStudent (sender, params, axiosOption, httpOption) { + return sender.doUrl('/admin/app/studentClass/listClassStudent', 'post', params, axiosOption, httpOption); + } + + static listNotInClassStudent (sender, params, axiosOption, httpOption) { + return sender.doUrl('/admin/app/studentClass/listNotInClassStudent', 'post', params, axiosOption, httpOption); + } + + static addClassStudent (sender, params, axiosOption, httpOption) { + return sender.doUrl('/admin/app/studentClass/addClassStudent', 'post', params, axiosOption, httpOption); + } + + static deleteClassStudent (sender, params, axiosOption, httpOption) { + return sender.doUrl('/admin/app/studentClass/deleteClassStudent', 'post', params, axiosOption, httpOption); + } + + static updateClassStudent (sender, params, axiosOption, httpOption) { + return sender.doUrl('/admin/app/studentClass/updateClassStudent', 'post', params, axiosOption, httpOption); + } +} diff --git a/orange-demo-single-web/src/api/Controller/StudentController.js b/orange-demo-single-web/src/api/Controller/StudentController.js new file mode 100644 index 00000000..f89892df --- /dev/null +++ b/orange-demo-single-web/src/api/Controller/StudentController.js @@ -0,0 +1,25 @@ +export default class StudentController { + static list (sender, params, axiosOption, httpOption) { + return sender.doUrl('/admin/app/student/list', 'post', params, axiosOption, httpOption); + } + + static view (sender, params, axiosOption, httpOption) { + return sender.doUrl('/admin/app/student/view', 'get', params, axiosOption, httpOption); + } + + static export (sender, params, fileName) { + return sender.download('/admin/app/student/export', params, fileName); + } + + static add (sender, params, axiosOption, httpOption) { + return sender.doUrl('/admin/app/student/add', 'post', params, axiosOption, httpOption); + } + + static update (sender, params, axiosOption, httpOption) { + return sender.doUrl('/admin/app/student/update', 'post', params, axiosOption, httpOption); + } + + static delete (sender, params, axiosOption, httpOption) { + return sender.doUrl('/admin/app/student/delete', 'post', params, axiosOption, httpOption); + } +} diff --git a/orange-demo-single-web/src/api/Controller/SysDataPermController.js b/orange-demo-single-web/src/api/Controller/SysDataPermController.js new file mode 100644 index 00000000..15fd5ccc --- /dev/null +++ b/orange-demo-single-web/src/api/Controller/SysDataPermController.js @@ -0,0 +1,61 @@ +export default class SysDataPermController { + /** + * @param params {dataPermId, dataPermName, deptIdListString} + */ + static add (sender, params, axiosOption, httpOption) { + return sender.doUrl('admin/upms/sysDataPerm/add', 'post', params, axiosOption, httpOption); + } + + /** + * @param params {dataPermId, dataPermName, deptIdListString} + */ + static update (sender, params, axiosOption, httpOption) { + return sender.doUrl('admin/upms/sysDataPerm/update', 'post', params, axiosOption, httpOption); + } + + /** + * @param params {dataPermId} + */ + static delete (sender, params, axiosOption, httpOption) { + return sender.doUrl('admin/upms/sysDataPerm/delete', 'post', params, axiosOption, httpOption); + } + + /** + * @param params {dataPermName} + */ + static list (sender, params, axiosOption, httpOption) { + return sender.doUrl('admin/upms/sysDataPerm/list', 'post', params, axiosOption, httpOption); + } + + /** + * @param params {dataPermId} + */ + static view (sender, params, axiosOption, httpOption) { + return sender.doUrl('admin/upms/sysDataPerm/view', 'get', params, axiosOption, httpOption); + } + + /** + * @param params {dataPermId, searchString} + */ + static listDataPermUser (sender, params, axiosOption, httpOption) { + return sender.doUrl('admin/upms/sysDataPerm/listDataPermUser', 'post', params, axiosOption, httpOption); + } + + /** + * @param params {dataPermId, userIdListString} + */ + static addDataPermUser (sender, params, axiosOption, httpOption) { + return sender.doUrl('admin/upms/sysDataPerm/addDataPermUser', 'post', params, axiosOption, httpOption); + } + + /** + * @param params {dataPermId, userId} + */ + static deleteDataPermUser (sender, params, axiosOption, httpOption) { + return sender.doUrl('admin/upms/sysDataPerm/deleteDataPermUser', 'post', params, axiosOption, httpOption); + } + + static listNotInDataPermUser (sender, params, axiosOption, httpOption) { + return sender.doUrl('admin/upms/sysDataPerm/listNotInDataPermUser', 'post', params, axiosOption, httpOption); + } +} diff --git a/orange-demo-single-web/src/api/Controller/SysUserController.js b/orange-demo-single-web/src/api/Controller/SysUserController.js new file mode 100644 index 00000000..26dec1aa --- /dev/null +++ b/orange-demo-single-web/src/api/Controller/SysUserController.js @@ -0,0 +1,25 @@ +export default class SysUserController { + static list (sender, params, axiosOption, httpOption) { + return sender.doUrl('/admin/upms/sysUser/list', 'post', params, axiosOption, httpOption); + } + + static view (sender, params, axiosOption, httpOption) { + return sender.doUrl('/admin/upms/sysUser/view', 'get', params, axiosOption, httpOption); + } + + static export (sender, params, fileName) { + return sender.download('/admin/upms/sysUser/export', params, fileName); + } + + static add (sender, params, axiosOption, httpOption) { + return sender.doUrl('/admin/upms/sysUser/add', 'post', params, axiosOption, httpOption); + } + + static update (sender, params, axiosOption, httpOption) { + return sender.doUrl('/admin/upms/sysUser/update', 'post', params, axiosOption, httpOption); + } + + static delete (sender, params, axiosOption, httpOption) { + return sender.doUrl('/admin/upms/sysUser/delete', 'post', params, axiosOption, httpOption); + } +} diff --git a/orange-demo-single-web/src/api/Controller/SystemController.js b/orange-demo-single-web/src/api/Controller/SystemController.js new file mode 100644 index 00000000..ea22c72e --- /dev/null +++ b/orange-demo-single-web/src/api/Controller/SystemController.js @@ -0,0 +1,201 @@ +export default class SystemController { + static login (sender, params, axiosOption, httpOption) { + return sender.doUrl('admin/login/doLogin', 'get', params, axiosOption, httpOption); + } + + static logout (sender, params, axiosOption, httpOption) { + return sender.doUrl('admin/login/doLogout', 'post', params, axiosOption, httpOption); + } + + static changePassword (sender, params, axiosOption, httpOption) { + return sender.doUrl('admin/login/changePassword', 'post', params, axiosOption, httpOption); + } + + static getDictList (sender, params, axiosOption, httpOption) { + return sender.doUrl('admin/upms/sysDict/list', 'post', params, axiosOption, httpOption); + } + + static getRoleList (sender, params, axiosOption, httpOption) { + return sender.doUrl('admin/upms/sysRole/list', 'post', params, axiosOption, httpOption); + } + + static getRole (sender, params, axiosOption, httpOption) { + return sender.doUrl('admin/upms/sysRole/view', 'get', params, axiosOption, httpOption); + } + + static deleteRole (sender, params, axiosOption, httpOption) { + return sender.doUrl('admin/upms/sysRole/delete', 'post', params, axiosOption, httpOption); + } + + static addRole (sender, params, axiosOption, httpOption) { + return sender.doUrl('admin/upms/sysRole/add', 'post', params, axiosOption, httpOption); + } + + static updateRole (sender, params, axiosOption, httpOption) { + return sender.doUrl('admin/upms/sysRole/update', 'post', params, axiosOption, httpOption); + } + + static getUserList (sender, params, axiosOption, httpOption) { + return sender.doUrl('admin/upms/sysUser/list', 'post', params, axiosOption, httpOption); + } + + static getUser (sender, params, axiosOption, httpOption) { + return sender.doUrl('admin/upms/sysUser/view', 'get', params, axiosOption, httpOption); + } + + static resetUserPassword (sender, params, axiosOption, httpOption) { + return sender.doUrl('admin/upms/sysUser/resetPassword', 'post', params, axiosOption, httpOption); + } + + static deleteUser (sender, params, axiosOption, httpOption) { + return sender.doUrl('admin/upms/sysUser/delete', 'post', params, axiosOption, httpOption); + } + + static addUser (sender, params, axiosOption, httpOption) { + return sender.doUrl('admin/upms/sysUser/add', 'post', params, axiosOption, httpOption); + } + + static updateUser (sender, params, axiosOption, httpOption) { + return sender.doUrl('admin/upms/sysUser/update', 'post', params, axiosOption, httpOption); + } + + // 菜单接口 + static getMenuPermList (sender, params, axiosOption, httpOption) { + return sender.doUrl('admin/upms/sysMenu/list', 'get', params, axiosOption, httpOption); + } + + static addMenu (sender, params, axiosOption, httpOption) { + return sender.doUrl('admin/upms/sysMenu/add', 'post', params, axiosOption, httpOption); + } + + static updateMenu (sender, params, axiosOption, httpOption) { + return sender.doUrl('admin/upms/sysMenu/update', 'post', params, axiosOption, httpOption); + } + + static deleteMenu (sender, params, axiosOption, httpOption) { + return sender.doUrl('admin/upms/sysMenu/delete', 'post', params, axiosOption, httpOption); + } + + static viewMenu (sender, params, axiosOption, httpOption) { + return sender.doUrl('admin/upms/sysMenu/view', 'get', params, axiosOption, httpOption); + } + + static listMenuPerm (sender, params, axiosOption, httpOption) { + return sender.doUrl('admin/upms/sysMenu/listMenuPerm', 'get', params, axiosOption, httpOption); + } + + // 权限字接口 + static getPermCodeList (sender, params, axiosOption, httpOption) { + return sender.doUrl('admin/upms/sysPermCode/list', 'post', params, axiosOption, httpOption); + } + + static addPermCode (sender, params, axiosOption, httpOption) { + return sender.doUrl('admin/upms/sysPermCode/add', 'post', params, axiosOption, httpOption); + } + + static updatePermCode (sender, params, axiosOption, httpOption) { + return sender.doUrl('admin/upms/sysPermCode/update', 'post', params, axiosOption, httpOption); + } + + static deletePermCode (sender, params, axiosOption, httpOption) { + return sender.doUrl('admin/upms/sysPermCode/delete', 'post', params, axiosOption, httpOption); + } + + static viewPermCode (sender, params, axiosOption, httpOption) { + return sender.doUrl('admin/upms/sysPermCode/view', 'get', params, axiosOption, httpOption); + } + + // 权限资源接口 + static getAllPermList (sender, params, axiosOption, httpOption) { + return sender.doUrl('admin/upms/sysPermModule/listAll', 'get', params, axiosOption, httpOption); + } + + static getPermGroupList (sender, params, axiosOption, httpOption) { + return sender.doUrl('admin/upms/sysPermModule/list', 'get', params, axiosOption, httpOption); + } + + static addPermGroup (sender, params, axiosOption, httpOption) { + return sender.doUrl('admin/upms/sysPermModule/add', 'post', params, axiosOption, httpOption); + } + + static updatePermGroup (sender, params, axiosOption, httpOption) { + return sender.doUrl('admin/upms/sysPermModule/update', 'post', params, axiosOption, httpOption); + } + + static deletePermGroup (sender, params, axiosOption, httpOption) { + return sender.doUrl('admin/upms/sysPermModule/delete', 'post', params, axiosOption, httpOption); + } + + static getPermList (sender, params, axiosOption, httpOption) { + return sender.doUrl('admin/upms/sysPerm/list', 'post', params, axiosOption, httpOption); + } + + static viewPerm (sender, params, axiosOption, httpOption) { + return sender.doUrl('admin/upms/sysPerm/view', 'get', params, axiosOption, httpOption); + } + + static addPerm (sender, params, axiosOption, httpOption) { + return sender.doUrl('admin/upms/sysPerm/add', 'post', params, axiosOption, httpOption); + } + + static updatePerm (sender, params, axiosOption, httpOption) { + return sender.doUrl('admin/upms/sysPerm/update', 'post', params, axiosOption, httpOption); + } + + static deletePerm (sender, params, axiosOption, httpOption) { + return sender.doUrl('admin/upms/sysPerm/delete', 'post', params, axiosOption, httpOption); + } + + /** + * @param params {roleId, searchString} + */ + static listRoleUser (sender, params, axiosOption, httpOption) { + return sender.doUrl('admin/upms/sysRole/listUserRole', 'post', params, axiosOption, httpOption); + } + + static listNotInUserRole (sender, params, axiosOption, httpOption) { + return sender.doUrl('admin/upms/sysRole/listNotInUserRole', 'post', params, axiosOption, httpOption); + } + + /** + * @param params {roleId, userIdListString} + */ + static addRoleUser (sender, params, axiosOption, httpOption) { + return sender.doUrl('admin/upms/sysRole/addUserRole', 'post', params, axiosOption, httpOption); + } + + /** + * @param params {roleId, userId} + */ + static deleteRoleUser (sender, params, axiosOption, httpOption) { + return sender.doUrl('admin/upms/sysRole/deleteUserRole', 'post', params, axiosOption, httpOption); + } + + /** + * @param params {} + */ + static queryRoleByPermCode (sender, params, axiosOption, httpOption) { + return sender.doUrl('admin/upms/sysRole/listAllRolesByPermCode', 'post', params, axiosOption, httpOption); + } + + /** + * @param params {} + */ + static queryRoleByURL (sender, params, axiosOption, httpOption) { + return sender.doUrl('admin/upms/sysRole/listAllRolesByPerm', 'post', params, axiosOption, httpOption); + } + + /** + * @param params {} + */ + static queryPerm (sender, params, axiosOption, httpOption) { + return sender.doUrl('admin/upms/sysUser/listAllPerms', 'post', params, axiosOption, httpOption); + } + + /** + * @param params {} + */ + static queryPermCode (sender, params, axiosOption, httpOption) { + return sender.doUrl('admin/upms/sysRole/deleteUserRole', 'post', params, axiosOption, httpOption); + } +} diff --git a/orange-demo-single-web/src/api/index.js b/orange-demo-single-web/src/api/index.js new file mode 100644 index 00000000..aca4fa48 --- /dev/null +++ b/orange-demo-single-web/src/api/index.js @@ -0,0 +1,25 @@ +import SystemController from './Controller/SystemController' +import SysDataPermController from './Controller/SysDataPermController' +import DictionaryController from './Controller/DictionaryController' +import CourseController from './Controller/CourseController.js' +import SchoolInfoController from './Controller/SchoolInfoController.js' +import StudentController from './Controller/StudentController.js' +import SysUserController from './Controller/SysUserController.js' +import StudentClassController from './Controller/StudentClassController.js' +import CourseTransStatsController from './Controller/CourseTransStatsController.js' +import StudentActionStatsController from './Controller/StudentActionStatsController.js' +import StudentActionTransController from './Controller/StudentActionTransController.js' + +export { + SystemController, + SysDataPermController, + DictionaryController, + CourseController, + SchoolInfoController, + StudentController, + SysUserController, + StudentClassController, + CourseTransStatsController, + StudentActionStatsController, + StudentActionTransController +} diff --git a/orange-demo-single-web/src/assets/img/default-header.jpg b/orange-demo-single-web/src/assets/img/default-header.jpg new file mode 100644 index 0000000000000000000000000000000000000000..222d18daf17197a6cfe48c403c79532ef0e97337 GIT binary patch literal 14882 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 literal 0 HcmV?d00001 diff --git a/orange-demo-single-web/src/assets/img/login_bg.jpg b/orange-demo-single-web/src/assets/img/login_bg.jpg new file mode 100644 index 0000000000000000000000000000000000000000..efc558de20dd14957d804e9b40b46b460545ab41 GIT binary patch literal 494030 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%0AoNd?q3b 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 z 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

GuB`nyB@zO~%}aC&uP$bu*%m;f%36GB_t3 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%0AbXif$T5I2 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%0A%3c;;_6|@S@LMy}8sijYGuu7Z*iV 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 Uc!By~4p5Hu^Zyi8@UJKTA1vf>djJ3c literal 0 HcmV?d00001 diff --git a/orange-demo-single-web/src/assets/img/orange-group1.png b/orange-demo-single-web/src/assets/img/orange-group1.png new file mode 100644 index 0000000000000000000000000000000000000000..efd59f26d4876e5fef2621cce37d9fea62dcef51 GIT binary patch literal 10894 zcmaKSby$>7*FPdim!xzkwWM^eG)gQ>Hv&pX2?D~hfFNBfB4NN1Qj0XwA>h(VgGhHQ zxv;>J@A|yYub%Jg?~gh6HP>~|oHJ);&Y5%0C)Pk;i-MGy6b}!N;-R*>A?|yHYnQ~g zaP$*?-!<-YQweQ4{AzqxN(#~J zw5~-pzU+j87QZb$8|y4Wahahz8Q}Ip#AN>@JyPrAW{Ks|;7#k244Xks`{O_v!B)Zd zYterblDaLtZGLFO)r@={(r0TC=V&Kf0v%R%(rk#k`M=X6Z!$Pf<{$x3jGfxJpfbgZ`@Ml zL4YFG15z|mJ+&$&2t;fabd%vO!Mg)X~k*&e!Pkyz90?XR2APv`# z@+=4Yh4&1PM#TT~_mE4JU3bgLTzn#n4DZPk#&L+LaQU;AJE1r^f1`tgrgSa5`--z6q|0#jnlJpXF9)lk+3s%Jd z>iP4zlcAZJPcx1l#^nGdpPjRT2~4ddTC(=o}jXf1I`>9G4;)?V)!^Y3}S zBL*|l%cWG-kVJB4&?LV0;(b-TDWDr4l~;zqr}#Qvbd+|_(dN!Su$# zYjDO6kd@3Th(#przA)UD8kgdyWteuVzUL?e!(sz<@0|;O zUu0_rS^155UyAZ@RTiaboqB>&FJd>N%0nNXF2k0u&i6nemdZB4H)ThsVTd@=vB~k= ziV87oVr4|9Jvljrqq_sX+Xt4R5p(#36PC$@D4l1rj3ck7###u9Tw+Ou>)v69KN$Qb z=I&2qDka?kUeFG46d7*dZ#+K}_ za`!aH)8=OAO1}7-ZA`a@?U?B(ma~UwXlgXxp^z={tJHqIO|O?vv~^QR0{5s-oJ_nqO?v&@<3A>C50nss#Z6y;`IW%PZ(d z8))Yhp>^VN!I<+|zcCF7JL zcI!m|CK{HFT6riGaTycS)hWPClUrZ$KvF1I#=tZ>DpA2;yphCB*_YZ6gCRC>h|dujyX1r2Q{9vLOUGlNa~vW zJ39KNKS%O?K=kJ?6goLAGAa>-cP))!3SAr3T|D(8ie`9=&OvW5^R?G_>=#XYx#z2P z3s@}<&AVAtFOzSE8PM6&l#dw298cV;S9(f(TBwmH5hf5y?O8{LE%R}2S&#p9H9Vi* z5{K099L==hr>8KSMii{Dzv!L7JT^XavRl`&Uu1a)Qc5#wkt_rL9*!(!k?FDWZ=bTb z7|v;7+C!*%KbkZ=;|BLeSUf;%*6&YT8F$>!x`V_oiYGrw{O+*Tc4 zP}h+EDz!Rt20K$lpR3uO-}0Y1jEq;jmYh2|FQ~|G(F>7I`QO|9PRA)^D9kuq@SS~X zwx2G}u?e^!Tdc)MOPdW0R%eD{Sn~?ifio`{%CFIOV9uX(a%jU`4ti5L>ZF*iZzOda zXQRruFHcwQLZUQRUn`7Jzu9R=25PHuqRwmISZ@KTppx=I{<`zO*Y|yEZ!dRj?&aKF^v+o;N6zL*n zUd{&>WQms62)Jabks@63_1fKQk{;R%a44?EH{^bj9gR#&1*}TXnx5D3wZh&PlMEw8 z)3`+#xp{`Q9J~b<42OY*&g;ef^D>eN85OOGCaXpK-n}BqvGZI)@_|=?M{$*iR_3dz z?3yzIKTK?WOm(0ig`x=Goa|gAwn5I_)+oMbMsY3o1vi`cE>-s;U81gEDv`6o`D0oN zWCHM2c(Xe5VDJfx>Rrb9wY(~W_r?u}KNV7}67JxhCNW{j;(^miSrt6dw(8{dpyuPZ zHOB;gKYGJQ%rm=Ak}ecw}_xYYbZrtuu|**Zw^kzB6mSnd0+kpWX26LVDttHyM~%a;!J@+ zgHj>L;gR`C$4aT})`yh!)`kMZkmG1>CRX@c(-2IYprmnn|7D($L~h;VZfiw5c}!8V z%k9~dgWfxGVvAJ$T|EE@omR;CmxLxJLE2P3!t%*}(c9uQ3?WGmQv5cKEh+&A z*FT!ID1S!shg|k~yUxmd z@pzYe5^viRm1fCxY;lxGxIm*uQO6XO0OBhkrQ$fxylDF)Vq#wrehW5ToCqhP7=L4j z&U!u7%dGF#vQXPk1akXl-34MwENQbCObIh}qUI|1oxIWNBE)`QRMFi5u9$GKQz{)@Ofno^g>eD^HPlV(`+u>gZX6v*D29i+2R-5?hl9+Ii0skUB9F{9=BIM zByfCi7{~02EyO43XO7pTro6RsecSS_j(Nz30kt=sFwYj@g4Qz9Aer)a+`uV0Aq~*a zmXkrfhyD6>Xzl$mfUI!WwJ!+%9nSq#$>%JinWvJ;@&xurY3o3nnxFKM`Rn)S2Q&eq zbP1{@x^yFv!mT8d($a#ZFi_e%-cc9fk58-ln)jZh7N6_uHyfI9eQ@htlor^Vq&;eQ za6}F{yM@dECVY5gkBy(@7r;2Qo4!I>BKEPM8UB{bVtRi@V4zkthBfdo0GmiT<>BS} z!<-%x&2 z)lb{6mx+pOp5S#GJ~U1#s4y`7$`{_Hzs zn9lEs-5TNc#elR2gS`VOo>@-V4|=>@lz^X0y6@gT(u>l7aoca^Rn`x5?k{A!Sg(}D zXWuupFfl0A;Z-s}<*f)h*6BAa~r67>QG7K(?(kBw=P33zl z2X1WIhM3JWt$FB=)pcMtA>qDkE=kvvKHipHk^~Tjhc+HW2v|7Q#!&7l@k@rhT zgFBZJv5Pv5L;Y%ZmhBfmJ_rg5@&PFIOzVkO4{`fZ!PP;w!I0*(+J{Gh9cMB!6FJ(% zeY`?`j&6Wj&-rj#=OFOLqa)5OmJiQQS~#>GKBeFd_6`sP49{6dzJJg`2AcJHX1unc z!k(=BW3q56U}b8L1(R1%gU?d8qi!?pSAUiE+GVbWt-XTj!wUU!nw96P!e(Pi3PV%i zUFQ6uBUyZj8{%utr)WWbe(JWCeM6Y9m;=^(4fmwv9UA+5tZr$Z5TB`9AD`nq8y{y= z!6^HgF{^Q<*S3w0KXH88>SI1VujTaQk{ZWcbnk-Vqkh2fOe;+ga(xmlnV+N^XOH89(!9v!Iw14Vx|t3+E{@KD=y+Y8VS0tTv_)uI)A-*0 z2|e)U`Uqk0|}n*I^7ybyD;_FaC+ZN?~S0oEjZ3sZVy)P19xGD1?zNoJg#!o}YI z3aCXQb?xK5@agHFx&8b>qT*T_Z@1=c4|TZpnn&4n=iw1yt>R4Z`i&XL37dIaFqNg1 zS-X|RJwi{$mRn65_vm7F1MM{&Zaud4Wkb9BuM|36$I2q5#*4}h`c~`t_0H_ftz+h| zf14eohn~osqT!c!C}+H>CdypHO74oYh%tOjaeav1UavD7H;M5K&9aWwB3E8f<`!Xo zl|O{G(e?c1%-!8^GGx1LKFNs$kvY%QyGiWUqwuWr$BE<9fc%yOx9vaqYM+I z03RB?V|eidlMHuxOsalUOs)y<Ox5=nqKBr+!enk%lkz>lJ3do z;YM$chO7q9vTkb%jQytmY{*#n1Vgr_KH<3LyN6UbhocJEG?giDFWhYa&xOJhg|u@* zTqgZ`UYa;aL+zz(1hkn2i7Q9_1&5q}i`EISTLeeD5VJ;R#H))j_p8}>2vcs)3XPWf zYf{5wIGHK5$;x|k#jhM(+(AQqKms_}zgt;U+P* zfzC#$5@bdTVYO<7=Ol72v}z6ArX@*3%GddGv|*rQQ>3y3fT61{NS=4i)i(owP*@1;g+ z#gGFl2MHg6NUZ>MeBHhHFUm?cD*|L6q(r(X-)Q;f=<2BX^m7#=+cI4jV$BT|2HhnT z9^@u8sTnEAj-C(~aLHFu0f_u}KlON|0^;XTrQ28^7m-iTU>o0PLo}>Fk3628t}G8G zv<*T%L4PD5JNQhz?igFCEH`CnpB$;oA=(=&FejtL?$IAt(fAMzVKf_ILzj)&$QfIytXsmE0sCO1$miDNeE*e>!}}n}qB}=qNA7px+UWW4sqh8;$Ac}mJqK>dXp&G}Vt$bbesuvM zC5smV+Fbfo7k2}G^XBO22)Cvms6)@#^hRO{3JwmP?bXVkhU9??t^ru`5 zZgNIskye3e9Q0WMQ61rgz9+|vzGhVJ_e8jSf3Lp*>`ate@XfE+(Fr=ny099{`fr>2 z#Eai%2%$6po5l&if!Iy_C*qm8{kjr!eWo(Q9e}}h+Ap`s z6iO!T=Zzn+oARGMJv#iJv-azrzA z-fOkfbh`@%5odP)TA8H@ztz+A&~vsB>_GhU(YLloLBlK=j5e3XF_HL&`!(>^6XVIH zZeTFO;Pn}yeS0Qa?&5cqLxj3$p2wu^*w-?x^~$=Zwnhe1MG3|ezIRwz)t#N4(X@_t zg)Ufg5Hs<`n>y=tv}3E~LZaPCRPzzFQkV_d@kBe|VKcPFBuCHp~~F ztF7OUnh&m7wJQ!r8zB-^e)x7o7Dp-&u6--!ryp~+M z|5Y)bu0}D2u4c(_C{9NOu)7*=%KX22^rbalJIvb7##cl~aG6Zim}N9zY^>Bang!_3 zA?OMXUQ%j4Enx(|Im+t3q)m@WRUW-s36k9(DYyM*FnA}RKTd32=xyDSeE0f(rA=&f zT47#u<+ljBrVCNrsNJ8+7cj4j*U*zWXx7bC)r%)P-T2N&&t3c zD_+pH8)bC>XTOwN!?#aJ1oaV0hI+Ly7Aj~RTxwm(TsS~&4QFHC_G#8PkE4OX$1tj; z{TG8dFU1yN*(O0QsW#!Jdu&t@Z`L_F0`@GXWu3!SF}89L>*Z)AEVoNSl=@)J5S%^q9b1TA(P|)8HsM}i*VeD z0)>*)&HIymkoHU^a~&G7sCm;RIIOd`!=id}@bchlx{Vf}(IG42%{8p;*y@wQF+*RU zsO&m(A1Tdiwj*v(qr{@mFO3-*#lsdahi63`Ss!i<#Y-0J;*!(7cKJl(Y~x&xltNJ2 zzyl;>iq$6A&L~oxt7aqD#GBZ1DBP*V?*v04&bZ)s60C0toqq=^E0U1EA1OoC7A3)^ zw6V?JZg5>eUK4zAsXw5x?BZq>o1CLER^!o`IJuW5I^@!_D1y}%7H;)^_S`aQYV+ww z3QTGbnV!SK%Czj&+TKd2<%7JkVw&+(+fAk~U-;WAfCQF3DHD4fhp`838)#Y^ueP}T zFC1A_hORrsx{2Iy!J-Mayjx`R>RG|ZBk4NUln~hEhqYUuSeUeTA3lh882KV|mc{Dt z=O+Dl(u}>MUNoV|i=0C5Ymca}{kybbc9yhJhycNb5kEj!L+1rsc<1Z}TV{K!=!JNk zj-rq4#cMHue^N#!IsP@@%z%e zc8Pkjk#g*`@Oe3fIE?D6l=dQODBk2w6Mfyqu$tijZ6+UhU08i5j-J09q2Z@7gKGH8~uX&=<<+MEaY%m~l{Gd`Q8*ldoxyu94SgWf;s77P7Z@y(R~wh9TV zfSrCqr9XxNondI80q`KTJiQE2#IB_Df;OvNJpl5JLCE^)BuD3{{qKwV7yZKz6Z8ka z33u&C=0v3x+lDT9&KzO7#ggu`D)^8uF0#`ph^$1a%RgVTX%6_z@{!~8mS;2O%>~Q3WVYx$^2guqT^@o4@vL9y2uP{YzGR~3DYaCTYvHlS`v7fN?h5jGg&`;vj&M^O^ z^)PeqZrw<9*V(u&RS0$j6|fzdvO!As*jZz3W z+Ty>tGjR?72t~=XbyOw?vYrjjcX)6#$zaL6M_dgJRBp`4DkKC1+yeNsg&&4pzurOt zUwc?h_F`{5Z%j7Zi27mUuS}N~u-bfOGc6M*9u#TK7L&G@D|2ugc?{LXI*GRg@)T_6 zhEYGwt|~%r&LsFL zGbsmh5+W|S-*>-A)eqA_CVCer?$qAVhOcNIQOib?e&x06U z8CFVre+Q<+YUO5*66Cd_ZCJ{(^zc*BG`CZ55936r$b8sHAM=;_`iGKufQq1Q2;GnF zg*XB+MJ2LpU%Z`j&#pOot0!|NY>@9hTXEp%$WX$7m1M0n%sY$xI&y`{uZvOR{`EU# z=%=acx1w>Gx!YoaYq5EIY@LhqEs2;PfFZ-pu$D#ngox#UD`#K_K(r02Y`X;%j`w@^ z4ffbqr9kIopCptMFGwh6lThaBpoS={=%xlT-yy+@Q>fLbY+h^0uG(J7fA?3Mg4Z&DRiN6ehFFTG{Ka zurie|`X`0fN+5eFuJO3y<2*F?b68@p}SS1Wu{KPeIy zGDn>c44uhCq1}E(E;3M8o4NSrd$>wS>$j$5EP?}@+;_s&`k(0K1N1!G53Pups z$&!@!MS%f12c(e7O8E*;+G{F;7a1!LVe+%B@@pw}Fm5<9|Da4}C;msu`5ph|jp4lh z5aF@?Q-Y+SI2l6ynPz7eTPRAY`S>~{DRWx7zf87;TVb^awa4+w$d`m$!YG4%N9%e+ zvh2Et>s^3iz}9$5!1lPZv9W0!ms&1kh4HDncZ&<_8sF;igM|(W0@|EA1Uxj>lg%VS zvtL~fYagS|YIWxJ;3S%vxXO@WfLcyGEB7-GDHGO}URRzn#WA+b#S?&LDxanME|nIScW!mv3j8>%oggoY zD_R?iBdj4pdhp2d3=Uj8Hu$+8o?GID$2Pk@BxMyd$|V!GtfF2J{g?`CU}FPVjzE7R zUSo_kNSJa_)(ldpEOQ~1AT%LX=o6_r{%*J!&DMt0o)Z&{yA2vo&VQ+)RNoX_QiJww z@|3GakF*yZzAZ)R(dYH$caI!doW^0n8h}gPrVD|dvlDXiMfE|kGkj^^ZV}swXZnt8 zZDC>d^)n)L3=FRRhp|Y8(23*>6|FSor>oPuay`lP=Guivwp{3xiIssqd4EEI++Rr!VE>c^x5_ck)I!D>7k9PG## z(S+g#MRM$NRTGHf28lA#&<*rvzaNc{j%|f74q3WsN2w)P5V)w9-ZJfBauE} z3QG={>36AW1(3C{sszjU#S;iy)jmC_W(q4#wnY)qK{L#W%R1p=^a)EydgiQCifGg4 z=`bgAOuzS6;veqDhbfzWJsoC>!%pkn&;HLG=y$WMc_k%)2EU!>!fBh&q9fss?sLs| zV8E*Y^yoNMYGmK{6^3+QOybrV!XG?>ObKG@k~Ke-(+v#;?lz)CpsN78hd6AA<3bs( z>^a$41Tj$ZEX#q|9*H65{xys7U{K@czp+4VeL49>CU)aUF|!>4_Pj=O1XC&~@37hr zWjYgbzVoZj3r>DSu<$hoi~}|t7NsYFKY!$4Xyw*im9WA#{1!(vPszg|n}1MKi)H@< zge)O52*I>EBQ{Nvr&aq&!imF-Y8+zpqY%9M!&DhFq+|EB*=d~WuOOj2z_gOMtaL;A z>Xrh?lai48n57VE%~ZhT)_l<)Fxdr5>Y(r8U*TjiuJIlShuU<^Gmsrs%QCZ{t+Dvl z8CWef-ey*OEj6q5a}NNyCy?zZ7Xnpj)E6Cxpv>!n~lsAqd$KbHCk@GAz|7BdWYDE-Tzk+D37WqO1O<44+st lxP68j$N#$uxmVXz<*&0z{O9~na2Qg&hZ_3oWvY+E{|g$^b6NlZ literal 0 HcmV?d00001 diff --git a/orange-demo-single-web/src/assets/style/base.scss b/orange-demo-single-web/src/assets/style/base.scss new file mode 100644 index 00000000..2ceda7be --- /dev/null +++ b/orange-demo-single-web/src/assets/style/base.scss @@ -0,0 +1,593 @@ +@import "element-color.scss"; +@import "transition.scss"; + +html, body { + padding: 0; + margin: 0; + font-size: 14px; + font-family: "Helvetica Neue",Helvetica,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","微软雅黑",Arial,sans-serif; + background-color: rgb(228,240,255); +} + +*, +*:before, +*:after { + box-sizing: border-box; +} + +$header-height: 60px; + +// 过滤组件长度 +$filter-item-width: 250px; +// 范围选择过滤组件长度 +$filter-item-range-width: 400px; +// 左侧过滤树组件每一项高度 +$tree-node-height: 40px; +// 高级管理表单标题高度 +$advanced-title-height: 50px; +$border-color: rgb(216, 220, 229); +$menuHover: rgba(255,255,255,0.3); +$menu-background-color: transparent; +$tabs-header-margin-bottom: 25px; +$tab-header-background-color: #EBEEF5; +$image-item-width: 65px; +$box-padding-size: 25px; + +/** + * 弹窗样式,封装的layer的弹窗 + **/ +body .layer-dialog .layui-layer-title{ + border-radius: 4px 4px 0px 0px; + border:1px solid #01000000; +} + +body .layer-dialog .layui-layer-setwin {color: #ffffff} + +body .layer-dialog { + border-radius: 4px; + border:1px solid #01000000; +} + +body .layer-dialog .layui-layer-content { + padding: $box-padding-size; +} + + +.demo-project { + .el-main { + padding: 0px; + } + .flex-box { + flex-wrap: wrap; + } + .scrollbar_dropdown__wrap { + overflow-x: hidden; + } + + .icon-btn.el-button { + font-size: 18px; + padding: 5px 0px; + } + + .default-padding-box { + padding: $box-padding-size; + } + + .padding-no-top { + padding: 0px $box-padding-size $box-padding-size $box-padding-size; + } + + .default-border { + border: 1px solid $border-color1; + } + + .default-border-left { + border-left: 1px solid $border-color1; + } + + .default-border-right { + border-right: 1px solid $border-color1; + } + + .default-border-top { + border-top: 1px solid $border-color1; + } + + .default-border-bottom { + border-bottom: 1px solid $border-color1; + } + + .page-close-box { + position: absolute; + background: #13ce66; + transform: rotate(45deg); + height: 60px; + width: 60px; + right: -30px; + top:-30px; + text-align: center; + + .el-button { + transform: rotate(-45deg); + color: white; + margin-top: 30px; + } + } + + /** + * 过滤组件样式 + **/ + .mask-box { + position: absolute; + width: 100%; + height: 100%; + background-color: rgba(0,0,0,0.5); + top: 0; + z-index: 10; + } + + .filter-box { + position: relative; + background-color: white; + padding: $box-padding-size $box-padding-size 0px $box-padding-size; + z-index: 20; + } + + .advance-filter-box { + padding-bottom: 25px; + } + + .filter-item { + width: $filter-item-width; + } + + .cascader-item { + width: 160px!important; + } + + .is-range, .is-search { + width: $filter-item-range-width; + } + + .table-operation-box { + align-self: flex-end; + margin-bottom: 10px; + overflow: hidden; + } + + /** + * 左侧树状组件的样式,用户高级管理表单以及用户管理表单 + **/ + .advanced-left-box { + border-right: 1px solid $border-color; + .el-tree-node__content { + height: $tree-node-height; + } + + .tree-node-item { + height: $tree-node-height; + line-height: $tree-node-height; + width: 100%; + + .tree-node-menu { + display: none; + float: right; + padding-right: 10px; + color: red!important; + } + + &:hover .tree-node-menu { + display: block; + } + } + + .el-tree-node .el-button+.el-button { + margin-left: 5px; + } + } + /** + * form表单输入组件宽度 + **/ + .full-width-input { + .el-select { + width: 100%; + } + + .el-input { + width: 100%; + } + + .el-cascader { + width: 100%; + } + + .el-date-editor { + width: 100%; + } + + .el-input-number { + width: 100%; + } + } + /** + * 左侧菜单样式 + **/ + .sidebar-bg { + background: linear-gradient(#FC8051, #EB6265); + } + + .sidebar-title { + height: 160px; + overflow: hidden; + } + + .sidebar-title-text { + width: 100%; + font-size: 18px; + color: #fff; + text-align: center; + margin: 0px; + } + .el-menu { + background-color: $menu-background-color; + border-right-width: 0px; + } + + .menu-wrapper { + .el-menu { + background: linear-gradient(#FC8051, #EB6265); + } + + .el-menu-item { + color: white; + i { + color: white; + } + &:hover { + background-color: rgba(255,255,255,0.3)!important; + } + } + + .el-submenu { + .el-menu { + background: none; + } + } + } + + .el-submenu__title i { + color: white; + } + + .el-menu--collapse { + .el-submenu__icon-arrow { + display: none; + } + } + + .nest-menu .el-submenu>.el-submenu__title, .el-submenu .el-menu-item { + min-width: 180px!important; + background: $menu-background-color; + } + + .el-menu-item.is-active { + border-left: 3px solid #47ba5a; + background-color: rgba(255,255,255,0.3)!important; + } + + .el-submenu__title { + background-color: $menu-background-color!important; + } + + .el-menu { + border-right-width: 0px; + } + + .menu-collapse-btn { + padding: 0px; + width: 15px; + border-radius: 2px; + border: none; + height: 100px; + background-color: $--color-primary-light-5; + position: fixed; + top: 20%; + z-index: -1; + color: white; + + &:hover { + background-color: $--color-primary-light-7; + } + .chart-border { + border: 1px solid #EBEEF5; + } + } + + /** + * 多tab页表单,tab样式 + **/ + .el-tabs__header { + margin: 0 0 20px; + } + /** + * 表格表头背景色 + **/ + .table-header-gray, .has-gutter .gutter { + background-color: $tab-header-background-color; + } + + /** + * 图片上传以及显示样式 + **/ + .upload-image-item { + font-size: 28px; + color: #8c939d; + width: $image-item-width; + height: $image-item-width; + text-align: center; + display: block; + + .el-upload i { + line-height: $image-item-width; + } + } + + .upload-image-multi { + display: inline; + } + + .upload-image-item .el-upload { + border: 1px dashed #d9d9d9; + border-radius: 6px; + cursor: pointer; + position: relative; + overflow: hidden; + } + .upload-image-item .el-upload:hover { + border-color: #409eff; + } + + .upload-image-show { + width: $image-item-width; + height: $image-item-width; + display: inline; + } + + .table-cell-image { + width: $image-item-width; + height: $image-item-width; + line-height: $image-item-width; + text-align: center; + font-size: $image-item-width; + color: #606266; + margin: 0px 5px; + } + + .upload-image-list .el-upload-list__item { + width: $image-item-width; + height: $image-item-width; + line-height: $image-item-width; + } + + .upload-image-item .el-upload-list--picture-card .el-upload-list__item { + width: $image-item-width; + height: $image-item-width; + } + + .upload-image-item .el-upload.el-upload--text { + width: $image-item-width; + height: $image-item-width; + } + + .upload-image-item .el-upload--picture-card { + width: $image-item-width; + height: $image-item-width; + line-height: $image-item-width; + } + /** + * + **/ + $header-menu-height: 32px; + + .sidebar { + height: 100%; + background-color: #304156; + overflow: hidden; + } + + .header { + display: flex; + height: $header-height; + background-color: white; + } + + .header .menu-column { + margin-right: 20px; + .el-menu-item.is-active { + border-left: 0px solid #47ba5a; + } + } + + .header-menu { + float: right; + height: $header-menu-height; + line-height: $header-menu-height; + margin-top: ($header-height - $header-menu-height) / 2; + } + + .header-img { + width: $header-menu-height; + height: $header-menu-height; + border-radius: 50%; + margin-left: 10px; + float: right; + } + + .user-dropdown { + color: $sub-text-color; + cursor: pointer; + font-size: 12px; + } + .user-dropdown-item { + font-size: 12px; + color: $main-text-color; + } + + .hamburger-container { + line-height: 70px; + height: $header-height; + float: left; + padding: 0 10px; + } + + .el-submenu__title { + background: #00000000; + } + + ::-webkit-scrollbar { + width: 7px; + height: 7px; + background: none; + } + + ::-webkit-scrollbar-thumb { + background: #DDDEE0; + border-radius: 7px; + } + + ::-webkit-scrollbar-thumb:hover { + background: #A8A8A8; + } + .tree-select { + .el-tree-node__content { + height: 34px; + line-height: 34px; + padding-right: 10px; + } + } + + .tree-select.single-select-tree { + .el-tree-node.is-current > .el-tree-node__content > .el-tree-node__label { + color: $--color-primary; + font-weight: 700; + } + } + + .cell { + .operation-cell { + color: #006CDC; + cursor: pointer; + text-decoration: underline; + } + } + + .single-select-tree { + min-width: 200px!important; + } + + .base-card-header { + display: flex; + align-items: center; + height: 50px; + line-height: 50px; + } + + .base-card-operation { + flex-grow: 1; + display: flex; + justify-content: flex-end; + } + + .el-card__header { + padding: 0px 15px; + } + .el-card__body { + padding: 15px; + } + + .custom-cascader { + width: 200px!important; + } + + .no-scroll { + overflow: hidden; + } + + .custom-scroll .el-scrollbar__view { + overflow-x: hidden!important; + } + + .upload-img-del { + position: absolute; + height: 20px; + width: 20px; + line-height: 20px; + font-size: 16px; + top: 2px; + right: 2px; + color: #C0C4CC; + } + + .upload-img-del:hover { + color: #EF5E1C; + } + + .input-label { + display: inline-block; + height: 29px; + line-height: 28px; + } + + .input-progress { + height: 29px; + display: flex; + align-items: center; + } + + .input-item { + width: 100%!important; + } + + .table-header-gray { + background: rgba(237,237,237,1); + } + + .card-header { + display: flex; + justify-content: space-between; + padding: 10px 0px; + line-height: 28px; + } +} + +.ml20 { + margin-left: 20px; +} + +.mr20 { + margin-right: 20px; +} + +.mt20 { + margin-top: 20px; +} + +.mb20 { + margin-bottom: 20px; +} + +.pl20 { + padding-left: 20px; +} + +.pr20 { + padding-right: 20px; +} + +.pt20 { + padding-top: 20px; +} + +.pb20 { + padding-bottom: 20px; +} diff --git a/orange-demo-single-web/src/assets/style/element-color.scss b/orange-demo-single-web/src/assets/style/element-color.scss new file mode 100644 index 00000000..7487d64c --- /dev/null +++ b/orange-demo-single-web/src/assets/style/element-color.scss @@ -0,0 +1,25 @@ +$main-text-color: #303133; +$normal-text-color: #606266; +$sub-text-color: #909399; +$placeholder-text-color: #C0C4CC; + +$border-color1: #DCDFE6; +$border-color2: #E4E7ED; +$border-color3: #EBEEF5; +$border-color4: #F2F6FC; + +$success-color: #67C23A; +$warning-color: #E6A23C; +$danger-color: #F56C6C; +$info-color: #909399; +$--color-white: white; +$--color-primary: #EF5E1C !default; +$--color-primary-light-1: mix($--color-white, $--color-primary, 10%) !default; /* 53a8ff */ +$--color-primary-light-2: mix($--color-white, $--color-primary, 20%) !default; /* 66b1ff */ +$--color-primary-light-3: mix($--color-white, $--color-primary, 30%) !default; /* 79bbff */ +$--color-primary-light-4: mix($--color-white, $--color-primary, 40%) !default; /* 8cc5ff */ +$--color-primary-light-5: mix($--color-white, $--color-primary, 50%) !default; /* a0cfff */ +$--color-primary-light-6: mix($--color-white, $--color-primary, 60%) !default; /* b3d8ff */ +$--color-primary-light-7: mix($--color-white, $--color-primary, 70%) !default; /* c6e2ff */ +$--color-primary-light-8: mix($--color-white, $--color-primary, 80%) !default; /* d9ecff */ +$--color-primary-light-9: mix($--color-white, $--color-primary, 90%) !default; /* ecf5ff */ diff --git a/orange-demo-single-web/src/assets/style/form-style.scss b/orange-demo-single-web/src/assets/style/form-style.scss new file mode 100644 index 00000000..f13e0e01 --- /dev/null +++ b/orange-demo-single-web/src/assets/style/form-style.scss @@ -0,0 +1,112 @@ +.form-advanced-manager { + .advance-filter-box { + position: absolute; + top: 100%; + left: 0px; + background-color: white; + width: 100%; + padding: 10px $box-padding-size 15px $box-padding-size; + } + + .title-box { + border-bottom: 1px solid $border-color; + padding: 0px 20px; + z-index: 20; + background-color: white; + height: $advanced-title-height; + + .title { + line-height: $advanced-title-height; + color: #606266; + } + + .menu-box { + position: absolute; + top: 0px; + right: 10px; + height: $advanced-title-height; + + .el-row { + margin: 10px 0px; + height: $advanced-title-height - 20; + } + } + } + + .advanced-right-box { + padding: 0px; + .gutter-box { + margin: (($advanced-title-height - 16)/2) 0px; + height: 16px; + width: 3px; + background-color: $--color-primary; + float: left + } + } +} + +.form-dict-manager { + .dict-title { + height: 50px; + line-height: 50px; + color: $main-text-color; + border-bottom: 1px solid $border-color1; + font-size: 14px; + + span { + margin-left: 20px; + } + } + + .dict-item { + width: 100%; + height: 40px; + line-height: 40px; + color: #606266; + cursor: pointer; + padding-left: 20px; + + &:hover { + background-color: $--color-primary-light-9; + } + } + + .active-dict-item { + border-left: 3px solid $--color-primary; + color: $--color-primary; + background-color: $--color-primary-light-9 !important; + } + + .el-scrollbar__bar.is-horizontal { + display: none!important; + } +} + + +.form-table-manager { + .advance-filter-box { + position: absolute; + padding: 20px; + top: 100%; + left: 0px; + background-color: white; + width: 100%; + padding: 10px $box-padding-size 15px $box-padding-size; + } +} + +.form-table-multi-select { + // +} + +.form-config { + padding: $box-padding-size; +} + +.form-multi-fragment { + // +} + +.form-single-fragment { + // +} \ No newline at end of file diff --git a/orange-demo-single-web/src/assets/style/index.scss b/orange-demo-single-web/src/assets/style/index.scss new file mode 100644 index 00000000..a88aa046 --- /dev/null +++ b/orange-demo-single-web/src/assets/style/index.scss @@ -0,0 +1,3 @@ +@import "../theme/index.css"; +@import "base.scss"; +@import "form-style.scss"; \ No newline at end of file diff --git a/orange-demo-single-web/src/assets/style/transition.scss b/orange-demo-single-web/src/assets/style/transition.scss new file mode 100644 index 00000000..49d81925 --- /dev/null +++ b/orange-demo-single-web/src/assets/style/transition.scss @@ -0,0 +1,31 @@ +/*fade*/ +.fade-enter-active, +.fade-leave-active { + transition: opacity 0.28s; +} + +.fade-enter, +.fade-leave-active { + opacity: 0; +} + +/*fade*/ +.breadcrumb-enter-active, +.breadcrumb-leave-active { + transition: all .5s; +} + +.breadcrumb-enter, +.breadcrumb-leave-active { + opacity: 0; + transform: translateX(20px); +} + +.breadcrumb-move { + transition: all .5s; +} + +.breadcrumb-leave-active { + position: absolute; +} + diff --git a/orange-demo-single-web/src/assets/theme/fonts/element-icons.ttf b/orange-demo-single-web/src/assets/theme/fonts/element-icons.ttf new file mode 100644 index 0000000000000000000000000000000000000000..91b74de36778b0ff8958d37d07ce70fb3b26f50b GIT binary patch literal 55956 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

%#5t+7yTm^Z{)9pPFdh-)p? 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,.el-table th.is-hidden>*,.el-table--hidden{visibility:hidden}.el-input__suffix,.el-tree.is-dragging .el-tree-node__content *{pointer-events:none}.el-dropdown .el-dropdown-selfdefine:focus:active,.el-dropdown .el-dropdown-selfdefine:focus:not(.focusing),.el-message__closeBtn:focus,.el-message__content:focus,.el-popover:focus,.el-popover:focus:active,.el-popover__reference:focus:hover,.el-popover__reference:focus:not(.focusing),.el-rate:active,.el-rate:focus,.el-tooltip:focus:hover,.el-tooltip:focus:not(.focusing),.el-upload-list__item.is-success:active,.el-upload-list__item.is-success:not(.focusing):focus{outline-width:0}@font-face{font-family:element-icons;src:url(fonts/element-icons.woff) format("woff"),url(fonts/element-icons.ttf) format("truetype");font-weight:400;font-display:"auto";font-style:normal}[class*=" el-icon-"],[class^=el-icon-]{font-family:element-icons!important;speak:none;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;line-height:1;vertical-align:baseline;display:inline-block;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.el-icon-ice-cream-round:before{content:"\e6a0"}.el-icon-ice-cream-square:before{content:"\e6a3"}.el-icon-lollipop:before{content:"\e6a4"}.el-icon-potato-strips:before{content:"\e6a5"}.el-icon-milk-tea:before{content:"\e6a6"}.el-icon-ice-drink:before{content:"\e6a7"}.el-icon-ice-tea:before{content:"\e6a9"}.el-icon-coffee:before{content:"\e6aa"}.el-icon-orange:before{content:"\e6ab"}.el-icon-pear:before{content:"\e6ac"}.el-icon-apple:before{content:"\e6ad"}.el-icon-cherry:before{content:"\e6ae"}.el-icon-watermelon:before{content:"\e6af"}.el-icon-grape:before{content:"\e6b0"}.el-icon-refrigerator:before{content:"\e6b1"}.el-icon-goblet-square-full:before{content:"\e6b2"}.el-icon-goblet-square:before{content:"\e6b3"}.el-icon-goblet-full:before{content:"\e6b4"}.el-icon-goblet:before{content:"\e6b5"}.el-icon-cold-drink:before{content:"\e6b6"}.el-icon-coffee-cup:before{content:"\e6b8"}.el-icon-water-cup:before{content:"\e6b9"}.el-icon-hot-water:before{content:"\e6ba"}.el-icon-ice-cream:before{content:"\e6bb"}.el-icon-dessert:before{content:"\e6bc"}.el-icon-sugar:before{content:"\e6bd"}.el-icon-tableware:before{content:"\e6be"}.el-icon-burger:before{content:"\e6bf"}.el-icon-knife-fork:before{content:"\e6c1"}.el-icon-fork-spoon:before{content:"\e6c2"}.el-icon-chicken:before{content:"\e6c3"}.el-icon-food:before{content:"\e6c4"}.el-icon-dish-1:before{content:"\e6c5"}.el-icon-dish:before{content:"\e6c6"}.el-icon-moon-night:before{content:"\e6ee"}.el-icon-moon:before{content:"\e6f0"}.el-icon-cloudy-and-sunny:before{content:"\e6f1"}.el-icon-partly-cloudy:before{content:"\e6f2"}.el-icon-cloudy:before{content:"\e6f3"}.el-icon-sunny:before{content:"\e6f6"}.el-icon-sunset:before{content:"\e6f7"}.el-icon-sunrise-1:before{content:"\e6f8"}.el-icon-sunrise:before{content:"\e6f9"}.el-icon-heavy-rain:before{content:"\e6fa"}.el-icon-lightning:before{content:"\e6fb"}.el-icon-light-rain:before{content:"\e6fc"}.el-icon-wind-power:before{content:"\e6fd"}.el-icon-baseball:before{content:"\e712"}.el-icon-soccer:before{content:"\e713"}.el-icon-football:before{content:"\e715"}.el-icon-basketball:before{content:"\e716"}.el-icon-ship:before{content:"\e73f"}.el-icon-truck:before{content:"\e740"}.el-icon-bicycle:before{content:"\e741"}.el-icon-mobile-phone:before{content:"\e6d3"}.el-icon-service:before{content:"\e6d4"}.el-icon-key:before{content:"\e6e2"}.el-icon-unlock:before{content:"\e6e4"}.el-icon-lock:before{content:"\e6e5"}.el-icon-watch:before{content:"\e6fe"}.el-icon-watch-1:before{content:"\e6ff"}.el-icon-timer:before{content:"\e702"}.el-icon-alarm-clock:before{content:"\e703"}.el-icon-map-location:before{content:"\e704"}.el-icon-delete-location:before{content:"\e705"}.el-icon-add-location:before{content:"\e706"}.el-icon-location-information:before{content:"\e707"}.el-icon-location-outline:before{content:"\e708"}.el-icon-location:before{content:"\e79e"}.el-icon-place:before{content:"\e709"}.el-icon-discover:before{content:"\e70a"}.el-icon-first-aid-kit:before{content:"\e70b"}.el-icon-trophy-1:before{content:"\e70c"}.el-icon-trophy:before{content:"\e70d"}.el-icon-medal:before{content:"\e70e"}.el-icon-medal-1:before{content:"\e70f"}.el-icon-stopwatch:before{content:"\e710"}.el-icon-mic:before{content:"\e711"}.el-icon-copy-document:before{content:"\e718"}.el-icon-full-screen:before{content:"\e719"}.el-icon-switch-button:before{content:"\e71b"}.el-icon-aim:before{content:"\e71c"}.el-icon-crop:before{content:"\e71d"}.el-icon-odometer:before{content:"\e71e"}.el-icon-time:before{content:"\e71f"}.el-icon-bangzhu:before{content:"\e724"}.el-icon-close-notification:before{content:"\e726"}.el-icon-microphone:before{content:"\e727"}.el-icon-turn-off-microphone:before{content:"\e728"}.el-icon-position:before{content:"\e729"}.el-icon-postcard:before{content:"\e72a"}.el-icon-message:before{content:"\e72b"}.el-icon-chat-line-square:before{content:"\e72d"}.el-icon-chat-dot-square:before{content:"\e72e"}.el-icon-chat-dot-round:before{content:"\e72f"}.el-icon-chat-square:before{content:"\e730"}.el-icon-chat-line-round:before{content:"\e731"}.el-icon-chat-round:before{content:"\e732"}.el-icon-set-up:before{content:"\e733"}.el-icon-turn-off:before{content:"\e734"}.el-icon-open:before{content:"\e735"}.el-icon-connection:before{content:"\e736"}.el-icon-link:before{content:"\e737"}.el-icon-cpu:before{content:"\e738"}.el-icon-thumb:before{content:"\e739"}.el-icon-female:before{content:"\e73a"}.el-icon-male:before{content:"\e73b"}.el-icon-guide:before{content:"\e73c"}.el-icon-news:before{content:"\e73e"}.el-icon-price-tag:before{content:"\e744"}.el-icon-discount:before{content:"\e745"}.el-icon-wallet:before{content:"\e747"}.el-icon-coin:before{content:"\e748"}.el-icon-money:before{content:"\e749"}.el-icon-bank-card:before{content:"\e74a"}.el-icon-box:before{content:"\e74b"}.el-icon-present:before{content:"\e74c"}.el-icon-sell:before{content:"\e6d5"}.el-icon-sold-out:before{content:"\e6d6"}.el-icon-shopping-bag-2:before{content:"\e74d"}.el-icon-shopping-bag-1:before{content:"\e74e"}.el-icon-shopping-cart-2:before{content:"\e74f"}.el-icon-shopping-cart-1:before{content:"\e750"}.el-icon-shopping-cart-full:before{content:"\e751"}.el-icon-smoking:before{content:"\e752"}.el-icon-no-smoking:before{content:"\e753"}.el-icon-house:before{content:"\e754"}.el-icon-table-lamp:before{content:"\e755"}.el-icon-school:before{content:"\e756"}.el-icon-office-building:before{content:"\e757"}.el-icon-toilet-paper:before{content:"\e758"}.el-icon-notebook-2:before{content:"\e759"}.el-icon-notebook-1:before{content:"\e75a"}.el-icon-files:before{content:"\e75b"}.el-icon-collection:before{content:"\e75c"}.el-icon-receiving:before{content:"\e75d"}.el-icon-suitcase-1:before{content:"\e760"}.el-icon-suitcase:before{content:"\e761"}.el-icon-film:before{content:"\e763"}.el-icon-collection-tag:before{content:"\e765"}.el-icon-data-analysis:before{content:"\e766"}.el-icon-pie-chart:before{content:"\e767"}.el-icon-data-board:before{content:"\e768"}.el-icon-data-line:before{content:"\e76d"}.el-icon-reading:before{content:"\e769"}.el-icon-magic-stick:before{content:"\e76a"}.el-icon-coordinate:before{content:"\e76b"}.el-icon-mouse:before{content:"\e76c"}.el-icon-brush:before{content:"\e76e"}.el-icon-headset:before{content:"\e76f"}.el-icon-umbrella:before{content:"\e770"}.el-icon-scissors:before{content:"\e771"}.el-icon-mobile:before{content:"\e773"}.el-icon-attract:before{content:"\e774"}.el-icon-monitor:before{content:"\e775"}.el-icon-search:before{content:"\e778"}.el-icon-takeaway-box:before{content:"\e77a"}.el-icon-paperclip:before{content:"\e77d"}.el-icon-printer:before{content:"\e77e"}.el-icon-document-add:before{content:"\e782"}.el-icon-document:before{content:"\e785"}.el-icon-document-checked:before{content:"\e786"}.el-icon-document-copy:before{content:"\e787"}.el-icon-document-delete:before{content:"\e788"}.el-icon-document-remove:before{content:"\e789"}.el-icon-tickets:before{content:"\e78b"}.el-icon-folder-checked:before{content:"\e77f"}.el-icon-folder-delete:before{content:"\e780"}.el-icon-folder-remove:before{content:"\e781"}.el-icon-folder-add:before{content:"\e783"}.el-icon-folder-opened:before{content:"\e784"}.el-icon-folder:before{content:"\e78a"}.el-icon-edit-outline:before{content:"\e764"}.el-icon-edit:before{content:"\e78c"}.el-icon-date:before{content:"\e78e"}.el-icon-c-scale-to-original:before{content:"\e7c6"}.el-icon-view:before{content:"\e6ce"}.el-icon-loading:before{content:"\e6cf"}.el-icon-rank:before{content:"\e6d1"}.el-icon-sort-down:before{content:"\e7c4"}.el-icon-sort-up:before{content:"\e7c5"}.el-icon-sort:before{content:"\e6d2"}.el-icon-finished:before{content:"\e6cd"}.el-icon-refresh-left:before{content:"\e6c7"}.el-icon-refresh-right:before{content:"\e6c8"}.el-icon-refresh:before{content:"\e6d0"}.el-icon-video-play:before{content:"\e7c0"}.el-icon-video-pause:before{content:"\e7c1"}.el-icon-d-arrow-right:before{content:"\e6dc"}.el-icon-d-arrow-left:before{content:"\e6dd"}.el-icon-arrow-up:before{content:"\e6e1"}.el-icon-arrow-down:before{content:"\e6df"}.el-icon-arrow-right:before{content:"\e6e0"}.el-icon-arrow-left:before{content:"\e6de"}.el-icon-top-right:before{content:"\e6e7"}.el-icon-top-left:before{content:"\e6e8"}.el-icon-top:before{content:"\e6e6"}.el-icon-bottom:before{content:"\e6eb"}.el-icon-right:before{content:"\e6e9"}.el-icon-back:before{content:"\e6ea"}.el-icon-bottom-right:before{content:"\e6ec"}.el-icon-bottom-left:before{content:"\e6ed"}.el-icon-caret-top:before{content:"\e78f"}.el-icon-caret-bottom:before{content:"\e790"}.el-icon-caret-right:before{content:"\e791"}.el-icon-caret-left:before{content:"\e792"}.el-icon-d-caret:before{content:"\e79a"}.el-icon-share:before{content:"\e793"}.el-icon-menu:before{content:"\e798"}.el-icon-s-grid:before{content:"\e7a6"}.el-icon-s-check:before{content:"\e7a7"}.el-icon-s-data:before{content:"\e7a8"}.el-icon-s-opportunity:before{content:"\e7aa"}.el-icon-s-custom:before{content:"\e7ab"}.el-icon-s-claim:before{content:"\e7ad"}.el-icon-s-finance:before{content:"\e7ae"}.el-icon-s-comment:before{content:"\e7af"}.el-icon-s-flag:before{content:"\e7b0"}.el-icon-s-marketing:before{content:"\e7b1"}.el-icon-s-shop:before{content:"\e7b4"}.el-icon-s-open:before{content:"\e7b5"}.el-icon-s-management:before{content:"\e7b6"}.el-icon-s-ticket:before{content:"\e7b7"}.el-icon-s-release:before{content:"\e7b8"}.el-icon-s-home:before{content:"\e7b9"}.el-icon-s-promotion:before{content:"\e7ba"}.el-icon-s-operation:before{content:"\e7bb"}.el-icon-s-unfold:before{content:"\e7bc"}.el-icon-s-fold:before{content:"\e7a9"}.el-icon-s-platform:before{content:"\e7bd"}.el-icon-s-order:before{content:"\e7be"}.el-icon-s-cooperation:before{content:"\e7bf"}.el-icon-bell:before{content:"\e725"}.el-icon-message-solid:before{content:"\e799"}.el-icon-video-camera:before{content:"\e772"}.el-icon-video-camera-solid:before{content:"\e796"}.el-icon-camera:before{content:"\e779"}.el-icon-camera-solid:before{content:"\e79b"}.el-icon-download:before{content:"\e77c"}.el-icon-upload2:before{content:"\e77b"}.el-icon-upload:before{content:"\e7c3"}.el-icon-picture-outline-round:before{content:"\e75f"}.el-icon-picture-outline:before{content:"\e75e"}.el-icon-picture:before{content:"\e79f"}.el-icon-close:before{content:"\e6db"}.el-icon-check:before{content:"\e6da"}.el-icon-plus:before{content:"\e6d9"}.el-icon-minus:before{content:"\e6d8"}.el-icon-help:before{content:"\e73d"}.el-icon-s-help:before{content:"\e7b3"}.el-icon-circle-close:before{content:"\e78d"}.el-icon-circle-check:before{content:"\e720"}.el-icon-circle-plus-outline:before{content:"\e723"}.el-icon-remove-outline:before{content:"\e722"}.el-icon-zoom-out:before{content:"\e776"}.el-icon-zoom-in:before{content:"\e777"}.el-icon-error:before{content:"\e79d"}.el-icon-success:before{content:"\e79c"}.el-icon-circle-plus:before{content:"\e7a0"}.el-icon-remove:before{content:"\e7a2"}.el-icon-info:before{content:"\e7a1"}.el-icon-question:before{content:"\e7a4"}.el-icon-warning-outline:before{content:"\e6c9"}.el-icon-warning:before{content:"\e7a3"}.el-icon-goods:before{content:"\e7c2"}.el-icon-s-goods:before{content:"\e7b2"}.el-icon-star-off:before{content:"\e717"}.el-icon-star-on:before{content:"\e797"}.el-icon-more-outline:before{content:"\e6cc"}.el-icon-more:before{content:"\e794"}.el-icon-phone-outline:before{content:"\e6cb"}.el-icon-phone:before{content:"\e795"}.el-icon-user:before{content:"\e6e3"}.el-icon-user-solid:before{content:"\e7a5"}.el-icon-setting:before{content:"\e6ca"}.el-icon-s-tools:before{content:"\e7ac"}.el-icon-delete:before{content:"\e6d7"}.el-icon-delete-solid:before{content:"\e7c9"}.el-icon-eleme:before{content:"\e7c7"}.el-icon-platform-eleme:before{content:"\e7ca"}.el-icon-loading{-webkit-animation:rotating 2s linear infinite;animation:rotating 2s linear infinite}.el-icon--right{margin-left:5px}.el-icon--left{margin-right:5px}@-webkit-keyframes rotating{0%{-webkit-transform:rotateZ(0);transform:rotateZ(0)}100%{-webkit-transform:rotateZ(360deg);transform:rotateZ(360deg)}}@keyframes rotating{0%{-webkit-transform:rotateZ(0);transform:rotateZ(0)}100%{-webkit-transform:rotateZ(360deg);transform:rotateZ(360deg)}}.el-pagination{white-space:nowrap;padding:2px 5px;color:#303133;font-weight:700}.el-pagination::after,.el-pagination::before{display:table;content:""}.el-pagination::after{clear:both}.el-pagination button,.el-pagination span:not([class*=suffix]){display:inline-block;font-size:13px;min-width:35.5px;height:28px;line-height:28px;vertical-align:top;-webkit-box-sizing:border-box;box-sizing:border-box}.el-pagination .el-input__inner{text-align:center;-moz-appearance:textfield;line-height:normal}.el-pagination .el-input__suffix{right:0;-webkit-transform:scale(.8);transform:scale(.8)}.el-pagination .el-select .el-input{width:100px;margin:0 5px}.el-pagination .el-select .el-input .el-input__inner{padding-right:25px;border-radius:3px}.el-pagination button{border:none;padding:0 6px;background:0 0}.el-pagination button:focus{outline:0}.el-pagination button:hover{color:#FDA833}.el-pagination button:disabled{color:#C0C4CC;background-color:#FFF;cursor:not-allowed}.el-pagination .btn-next,.el-pagination .btn-prev{background:center center no-repeat #FFF;background-size:16px;cursor:pointer;margin:0;color:#303133}.el-pagination .btn-next .el-icon,.el-pagination .btn-prev .el-icon{display:block;font-size:12px;font-weight:700}.el-pagination .btn-prev{padding-right:12px}.el-pagination .btn-next{padding-left:12px}.el-pagination .el-pager li.disabled{color:#C0C4CC;cursor:not-allowed}.el-pager li,.el-pager li.btn-quicknext:hover,.el-pager li.btn-quickprev:hover{cursor:pointer}.el-pagination--small .btn-next,.el-pagination--small .btn-prev,.el-pagination--small .el-pager li,.el-pagination--small .el-pager li.btn-quicknext,.el-pagination--small .el-pager li.btn-quickprev,.el-pagination--small .el-pager li:last-child{border-color:transparent;font-size:12px;line-height:22px;height:22px;min-width:22px}.el-pagination--small .more::before,.el-pagination--small li.more::before{line-height:24px}.el-pagination--small button,.el-pagination--small span:not([class*=suffix]){height:22px;line-height:22px}.el-pagination--small .el-pagination__editor,.el-pagination--small .el-pagination__editor.el-input .el-input__inner{height:22px}.el-pagination__sizes{margin:0 10px 0 0;font-weight:400;color:#606266}.el-pagination__sizes .el-input .el-input__inner{font-size:13px;padding-left:8px}.el-pagination__sizes .el-input .el-input__inner:hover{border-color:#FDA833}.el-pagination__total{margin-right:10px;font-weight:400;color:#606266}.el-pagination__jump{margin-left:24px;font-weight:400;color:#606266}.el-pagination__jump .el-input__inner{padding:0 3px}.el-pagination__rightwrapper{float:right}.el-pagination__editor{line-height:18px;padding:0 2px;height:28px;text-align:center;margin:0 2px;-webkit-box-sizing:border-box;box-sizing:border-box;border-radius:3px}.el-pager,.el-pagination.is-background .btn-next,.el-pagination.is-background .btn-prev{padding:0}.el-pagination__editor.el-input{width:50px}.el-pagination__editor.el-input .el-input__inner{height:28px}.el-pagination__editor .el-input__inner::-webkit-inner-spin-button,.el-pagination__editor .el-input__inner::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.el-pagination.is-background .btn-next,.el-pagination.is-background .btn-prev,.el-pagination.is-background .el-pager li{margin:0 5px;background-color:#f4f4f5;color:#606266;min-width:30px;border-radius:2px}.el-pagination.is-background .btn-next.disabled,.el-pagination.is-background .btn-next:disabled,.el-pagination.is-background .btn-prev.disabled,.el-pagination.is-background .btn-prev:disabled,.el-pagination.is-background .el-pager li.disabled{color:#C0C4CC}.el-pagination.is-background .el-pager li:not(.disabled):hover{color:#FDA833}.el-pagination.is-background .el-pager li:not(.disabled).active{background-color:#FDA833;color:#FFF}.el-dialog,.el-pager li{background:#FFF;-webkit-box-sizing:border-box}.el-pagination.is-background.el-pagination--small .btn-next,.el-pagination.is-background.el-pagination--small .btn-prev,.el-pagination.is-background.el-pagination--small .el-pager li{margin:0 3px;min-width:22px}.el-pager,.el-pager li{vertical-align:top;margin:0;display:inline-block}.el-pager{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;list-style:none;font-size:0}.el-date-table,.el-table th{-webkit-user-select:none;-moz-user-select:none}.el-pager .more::before{line-height:30px}.el-pager li{padding:0 4px;font-size:13px;min-width:35.5px;height:28px;line-height:28px;box-sizing:border-box;text-align:center}.el-menu--collapse .el-menu .el-submenu,.el-menu--popup{min-width:200px}.el-pager li.btn-quicknext,.el-pager li.btn-quickprev{line-height:28px;color:#303133}.el-pager li.btn-quicknext.disabled,.el-pager li.btn-quickprev.disabled{color:#C0C4CC}.el-pager li.active+li{border-left:0}.el-pager li:hover{color:#FDA833}.el-pager li.active{color:#FDA833;cursor:default}@-webkit-keyframes v-modal-in{0%{opacity:0}}@-webkit-keyframes v-modal-out{100%{opacity:0}}.el-dialog{position:relative;margin:0 auto 50px;border-radius:2px;-webkit-box-shadow:0 1px 3px rgba(0,0,0,.3);box-shadow:0 1px 3px rgba(0,0,0,.3);box-sizing:border-box;width:50%}.el-dialog.is-fullscreen{width:100%;margin-top:0;margin-bottom:0;height:100%;overflow:auto}.el-dialog__wrapper{position:fixed;top:0;right:0;bottom:0;left:0;overflow:auto;margin:0}.el-dialog__header{padding:20px 20px 10px}.el-dialog__headerbtn{position:absolute;top:20px;right:20px;padding:0;background:0 0;border:none;outline:0;cursor:pointer;font-size:16px}.el-dialog__headerbtn .el-dialog__close{color:#909399}.el-dialog__headerbtn:focus .el-dialog__close,.el-dialog__headerbtn:hover .el-dialog__close{color:#FDA833}.el-dialog__title{line-height:24px;font-size:18px;color:#303133}.el-dialog__body{padding:30px 20px;color:#606266;font-size:14px;word-break:break-all}.el-dialog__footer{padding:10px 20px 20px;text-align:right;-webkit-box-sizing:border-box;box-sizing:border-box}.el-dialog--center{text-align:center}.el-dialog--center .el-dialog__body{text-align:initial;padding:25px 25px 30px}.el-dialog--center .el-dialog__footer{text-align:inherit}.dialog-fade-enter-active{-webkit-animation:dialog-fade-in .3s;animation:dialog-fade-in .3s}.dialog-fade-leave-active{-webkit-animation:dialog-fade-out .3s;animation:dialog-fade-out .3s}@-webkit-keyframes dialog-fade-in{0%{-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0);opacity:0}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1}}@keyframes dialog-fade-in{0%{-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0);opacity:0}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1}}@-webkit-keyframes dialog-fade-out{0%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1}100%{-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0);opacity:0}}@keyframes dialog-fade-out{0%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1}100%{-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0);opacity:0}}.el-autocomplete{position:relative;display:inline-block}.el-autocomplete-suggestion{margin:5px 0;-webkit-box-shadow:0 2px 12px 0 rgba(0,0,0,.1);box-shadow:0 2px 12px 0 rgba(0,0,0,.1);border-radius:4px;border:1px solid #E4E7ED;-webkit-box-sizing:border-box;box-sizing:border-box;background-color:#FFF}.el-dropdown-menu,.el-menu--collapse .el-submenu .el-menu{z-index:10;-webkit-box-shadow:0 2px 12px 0 rgba(0,0,0,.1)}.el-autocomplete-suggestion__wrap{max-height:280px;padding:10px 0;-webkit-box-sizing:border-box;box-sizing:border-box}.el-autocomplete-suggestion__list{margin:0;padding:0}.el-autocomplete-suggestion li{padding:0 20px;margin:0;line-height:34px;cursor:pointer;color:#606266;font-size:14px;list-style:none;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.el-autocomplete-suggestion li.highlighted,.el-autocomplete-suggestion li:hover{background-color:#F5F7FA}.el-autocomplete-suggestion li.divider{margin-top:6px;border-top:1px solid #000}.el-autocomplete-suggestion li.divider:last-child{margin-bottom:-6px}.el-autocomplete-suggestion.is-loading li{text-align:center;height:100px;line-height:100px;font-size:20px;color:#999}.el-autocomplete-suggestion.is-loading li::after{display:inline-block;content:"";height:100%;vertical-align:middle}.el-autocomplete-suggestion.is-loading li:hover{background-color:#FFF}.el-autocomplete-suggestion.is-loading .el-icon-loading{vertical-align:middle}.el-dropdown{display:inline-block;position:relative;color:#606266;font-size:14px}.el-dropdown .el-button-group{display:block}.el-dropdown .el-button-group .el-button{float:none}.el-dropdown .el-dropdown__caret-button{padding-left:5px;padding-right:5px;position:relative;border-left:none}.el-dropdown .el-dropdown__caret-button::before{content:'';position:absolute;display:block;width:1px;top:5px;bottom:5px;left:0;background:rgba(255,255,255,.5)}.el-dropdown .el-dropdown__caret-button.el-button--default::before{background:rgba(220,223,230,.5)}.el-dropdown .el-dropdown__caret-button:hover::before{top:0;bottom:0}.el-dropdown .el-dropdown__caret-button .el-dropdown__icon{padding-left:0}.el-dropdown__icon{font-size:12px;margin:0 3px}.el-dropdown-menu{position:absolute;top:0;left:0;padding:10px 0;margin:5px 0;background-color:#FFF;border:1px solid #EBEEF5;border-radius:4px;box-shadow:0 2px 12px 0 rgba(0,0,0,.1)}.el-dropdown-menu__item{list-style:none;line-height:36px;padding:0 20px;margin:0;font-size:14px;color:#606266;cursor:pointer;outline:0}.el-dropdown-menu__item:focus,.el-dropdown-menu__item:not(.is-disabled):hover{background-color:rgb(255, 246, 235);color:rgb(253, 185, 92)}.el-dropdown-menu__item i{margin-right:5px}.el-dropdown-menu__item--divided{position:relative;margin-top:6px;border-top:1px solid #EBEEF5}.el-dropdown-menu__item--divided:before{content:'';height:6px;display:block;margin:0 -20px;background-color:#FFF}.el-dropdown-menu__item.is-disabled{cursor:default;color:#bbb;pointer-events:none}.el-dropdown-menu--medium{padding:6px 0}.el-dropdown-menu--medium .el-dropdown-menu__item{line-height:30px;padding:0 17px;font-size:14px}.el-dropdown-menu--medium .el-dropdown-menu__item.el-dropdown-menu__item--divided{margin-top:6px}.el-dropdown-menu--medium .el-dropdown-menu__item.el-dropdown-menu__item--divided:before{height:6px;margin:0 -17px}.el-dropdown-menu--small{padding:6px 0}.el-dropdown-menu--small .el-dropdown-menu__item{line-height:27px;padding:0 15px;font-size:13px}.el-dropdown-menu--small .el-dropdown-menu__item.el-dropdown-menu__item--divided{margin-top:4px}.el-dropdown-menu--small .el-dropdown-menu__item.el-dropdown-menu__item--divided:before{height:4px;margin:0 -15px}.el-dropdown-menu--mini{padding:3px 0}.el-dropdown-menu--mini .el-dropdown-menu__item{line-height:24px;padding:0 10px;font-size:12px}.el-dropdown-menu--mini .el-dropdown-menu__item.el-dropdown-menu__item--divided{margin-top:3px}.el-dropdown-menu--mini .el-dropdown-menu__item.el-dropdown-menu__item--divided:before{height:3px;margin:0 -10px}.el-menu{border-right:solid 1px #e6e6e6;list-style:none;position:relative;margin:0;padding-left:0;background-color:#FFF}.el-menu--horizontal>.el-menu-item:not(.is-disabled):focus,.el-menu--horizontal>.el-menu-item:not(.is-disabled):hover,.el-menu--horizontal>.el-submenu .el-submenu__title:hover{background-color:#fff}.el-menu::after,.el-menu::before{display:table;content:""}.el-menu::after{clear:both}.el-menu.el-menu--horizontal{border-bottom:solid 1px #e6e6e6}.el-menu--horizontal{border-right:none}.el-menu--horizontal>.el-menu-item{float:left;height:60px;line-height:60px;margin:0;border-bottom:2px solid transparent;color:#909399}.el-menu--horizontal>.el-menu-item a,.el-menu--horizontal>.el-menu-item a:hover{color:inherit}.el-menu--horizontal>.el-submenu{float:left}.el-menu--horizontal>.el-submenu:focus,.el-menu--horizontal>.el-submenu:hover{outline:0}.el-menu--horizontal>.el-submenu:focus .el-submenu__title,.el-menu--horizontal>.el-submenu:hover .el-submenu__title{color:#303133}.el-menu--horizontal>.el-submenu.is-active .el-submenu__title{border-bottom:2px solid #FDA833;color:#303133}.el-menu--horizontal>.el-submenu .el-submenu__title{height:60px;line-height:60px;border-bottom:2px solid transparent;color:#909399}.el-menu--horizontal>.el-submenu .el-submenu__icon-arrow{position:static;vertical-align:middle;margin-left:8px;margin-top:-3px}.el-menu--horizontal .el-menu .el-menu-item,.el-menu--horizontal .el-menu .el-submenu__title{background-color:#FFF;float:none;height:36px;line-height:36px;padding:0 10px;color:#909399}.el-menu--horizontal .el-menu .el-menu-item.is-active,.el-menu--horizontal .el-menu .el-submenu.is-active>.el-submenu__title{color:#303133}.el-menu--horizontal .el-menu-item:not(.is-disabled):focus,.el-menu--horizontal .el-menu-item:not(.is-disabled):hover{outline:0;color:#303133}.el-menu--horizontal>.el-menu-item.is-active{border-bottom:2px solid #FDA833;color:#303133}.el-menu--collapse{width:64px}.el-menu--collapse>.el-menu-item [class^=el-icon-],.el-menu--collapse>.el-submenu>.el-submenu__title [class^=el-icon-]{margin:0;vertical-align:middle;width:24px;text-align:center}.el-menu--collapse>.el-menu-item .el-submenu__icon-arrow,.el-menu--collapse>.el-submenu>.el-submenu__title .el-submenu__icon-arrow{display:none}.el-menu--collapse>.el-menu-item span,.el-menu--collapse>.el-submenu>.el-submenu__title span{height:0;width:0;overflow:hidden;visibility:hidden;display:inline-block}.el-menu--collapse>.el-menu-item.is-active i{color:inherit}.el-menu--collapse .el-submenu{position:relative}.el-menu--collapse .el-submenu .el-menu{position:absolute;margin-left:5px;top:0;left:100%;border:1px solid #E4E7ED;border-radius:2px;box-shadow:0 2px 12px 0 rgba(0,0,0,.1)}.el-menu-item,.el-submenu__title{height:56px;line-height:56px;position:relative;-webkit-box-sizing:border-box;white-space:nowrap;list-style:none}.el-menu--collapse .el-submenu.is-opened>.el-submenu__title .el-submenu__icon-arrow{-webkit-transform:none;transform:none}.el-menu--popup{z-index:100;border:none;padding:5px 0;border-radius:2px;-webkit-box-shadow:0 2px 12px 0 rgba(0,0,0,.1);box-shadow:0 2px 12px 0 rgba(0,0,0,.1)}.el-menu--popup-bottom-start{margin-top:5px}.el-menu--popup-right-start{margin-left:5px;margin-right:5px}.el-menu-item{font-size:14px;color:#303133;padding:0 20px;cursor:pointer;-webkit-transition:border-color .3s,background-color .3s,color .3s;transition:border-color .3s,background-color .3s,color .3s;box-sizing:border-box}.el-menu-item *{vertical-align:middle}.el-menu-item i{color:#909399}.el-menu-item:focus,.el-menu-item:hover{outline:0;background-color:rgb(255, 246, 235)}.el-menu-item.is-disabled{opacity:.25;cursor:not-allowed;background:0 0!important}.el-menu-item [class^=el-icon-]{margin-right:5px;width:24px;text-align:center;font-size:18px;vertical-align:middle}.el-menu-item.is-active{color:#FDA833}.el-menu-item.is-active i{color:inherit}.el-submenu{list-style:none;margin:0;padding-left:0}.el-submenu__title{font-size:14px;color:#303133;padding:0 20px;cursor:pointer;-webkit-transition:border-color .3s,background-color .3s,color .3s;transition:border-color .3s,background-color .3s,color .3s;box-sizing:border-box}.el-submenu__title *{vertical-align:middle}.el-submenu__title i{color:#909399}.el-submenu__title:focus,.el-submenu__title:hover{outline:0;background-color:rgb(255, 246, 235)}.el-submenu__title.is-disabled{opacity:.25;cursor:not-allowed;background:0 0!important}.el-submenu__title:hover{background-color:rgb(255, 246, 235)}.el-submenu .el-menu{border:none}.el-submenu .el-menu-item{height:50px;line-height:50px;padding:0 45px;min-width:200px}.el-submenu__icon-arrow{position:absolute;top:50%;right:20px;margin-top:-7px;-webkit-transition:-webkit-transform .3s;transition:-webkit-transform .3s;transition:transform .3s;transition:transform .3s,-webkit-transform .3s;font-size:12px}.el-submenu.is-active .el-submenu__title{border-bottom-color:#FDA833}.el-submenu.is-opened>.el-submenu__title .el-submenu__icon-arrow{-webkit-transform:rotateZ(180deg);transform:rotateZ(180deg)}.el-submenu.is-disabled .el-menu-item,.el-submenu.is-disabled .el-submenu__title{opacity:.25;cursor:not-allowed;background:0 0!important}.el-submenu [class^=el-icon-]{vertical-align:middle;margin-right:5px;width:24px;text-align:center;font-size:18px}.el-menu-item-group>ul{padding:0}.el-menu-item-group__title{padding:7px 0 7px 20px;line-height:normal;font-size:12px;color:#909399}.el-radio-button__inner,.el-radio-group{display:inline-block;line-height:1;vertical-align:middle}.horizontal-collapse-transition .el-submenu__title .el-submenu__icon-arrow{-webkit-transition:.2s;transition:.2s;opacity:0}.el-radio-group{font-size:0}.el-radio-button{position:relative;display:inline-block;outline:0}.el-radio-button__inner{white-space:nowrap;background:#FFF;border:1px solid #DCDFE6;font-weight:500;border-left:0;color:#606266;-webkit-appearance:none;text-align:center;-webkit-box-sizing:border-box;box-sizing:border-box;outline:0;margin:0;position:relative;cursor:pointer;-webkit-transition:all .3s cubic-bezier(.645,.045,.355,1);transition:all .3s cubic-bezier(.645,.045,.355,1);padding:12px 20px;font-size:14px;border-radius:0}.el-radio-button__inner.is-round{padding:12px 20px}.el-radio-button__inner:hover{color:#FDA833}.el-radio-button__inner [class*=el-icon-]{line-height:.9}.el-radio-button__inner [class*=el-icon-]+span{margin-left:5px}.el-radio-button:first-child .el-radio-button__inner{border-left:1px solid #DCDFE6;border-radius:4px 0 0 4px;-webkit-box-shadow:none!important;box-shadow:none!important}.el-radio-button__orig-radio{opacity:0;outline:0;position:absolute;z-index:-1}.el-radio-button__orig-radio:checked+.el-radio-button__inner{color:#FFF;background-color:#FDA833;border-color:#FDA833;-webkit-box-shadow:-1px 0 0 0 #FDA833;box-shadow:-1px 0 0 0 #FDA833}.el-radio-button__orig-radio:disabled+.el-radio-button__inner{color:#C0C4CC;cursor:not-allowed;background-image:none;background-color:#FFF;border-color:#EBEEF5;-webkit-box-shadow:none;box-shadow:none}.el-radio-button__orig-radio:disabled:checked+.el-radio-button__inner{background-color:#F2F6FC}.el-radio-button:last-child .el-radio-button__inner{border-radius:0 4px 4px 0}.el-popover,.el-radio-button:first-child:last-child .el-radio-button__inner{border-radius:4px}.el-radio-button--medium .el-radio-button__inner{padding:10px 20px;font-size:14px;border-radius:0}.el-radio-button--medium .el-radio-button__inner.is-round{padding:10px 20px}.el-radio-button--small .el-radio-button__inner{padding:9px 15px;font-size:12px;border-radius:0}.el-radio-button--small .el-radio-button__inner.is-round{padding:9px 15px}.el-radio-button--mini .el-radio-button__inner{padding:7px 15px;font-size:12px;border-radius:0}.el-radio-button--mini .el-radio-button__inner.is-round{padding:7px 15px}.el-radio-button:focus:not(.is-focus):not(:active):not(.is-disabled){-webkit-box-shadow:0 0 2px 2px #FDA833;box-shadow:0 0 2px 2px #FDA833}.el-switch{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;position:relative;font-size:14px;line-height:20px;height:20px;vertical-align:middle}.el-switch__core,.el-switch__label{display:inline-block;cursor:pointer}.el-switch.is-disabled .el-switch__core,.el-switch.is-disabled .el-switch__label{cursor:not-allowed}.el-switch__label{-webkit-transition:.2s;transition:.2s;height:20px;font-size:14px;font-weight:500;vertical-align:middle;color:#303133}.el-switch__label.is-active{color:#FDA833}.el-switch__label--left{margin-right:10px}.el-switch__label--right{margin-left:10px}.el-switch__label *{line-height:1;font-size:14px;display:inline-block}.el-switch__input{position:absolute;width:0;height:0;opacity:0;margin:0}.el-switch__core{margin:0;position:relative;width:40px;height:20px;border:1px solid #DCDFE6;outline:0;border-radius:10px;-webkit-box-sizing:border-box;box-sizing:border-box;background:#DCDFE6;-webkit-transition:border-color .3s,background-color .3s;transition:border-color .3s,background-color .3s;vertical-align:middle}.el-switch__core:after{content:"";position:absolute;top:1px;left:1px;border-radius:100%;-webkit-transition:all .3s;transition:all .3s;width:16px;height:16px;background-color:#FFF}.el-switch.is-checked .el-switch__core{border-color:#FDA833;background-color:#FDA833}.el-switch.is-checked .el-switch__core::after{left:100%;margin-left:-17px}.el-switch.is-disabled{opacity:.6}.el-switch--wide .el-switch__label.el-switch__label--left span{left:10px}.el-switch--wide .el-switch__label.el-switch__label--right span{right:10px}.el-switch .label-fade-enter,.el-switch .label-fade-leave-active{opacity:0}.el-select-dropdown{position:absolute;z-index:1001;border:1px solid #E4E7ED;border-radius:4px;background-color:#FFF;-webkit-box-shadow:0 2px 12px 0 rgba(0,0,0,.1);box-shadow:0 2px 12px 0 rgba(0,0,0,.1);-webkit-box-sizing:border-box;box-sizing:border-box;margin:5px 0}.el-select-dropdown.is-multiple .el-select-dropdown__item.selected{color:#FDA833;background-color:#FFF}.el-select-dropdown.is-multiple .el-select-dropdown__item.selected.hover{background-color:#F5F7FA}.el-select-dropdown.is-multiple .el-select-dropdown__item.selected::after{position:absolute;right:20px;font-family:element-icons;content:"\e6da";font-size:12px;font-weight:700;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.el-select-dropdown .el-scrollbar.is-empty .el-select-dropdown__list{padding:0}.el-select-dropdown__empty{padding:10px 0;margin:0;text-align:center;color:#999;font-size:14px}.el-select-dropdown__wrap{max-height:274px}.el-select-dropdown__list{list-style:none;padding:6px 0;margin:0;-webkit-box-sizing:border-box;box-sizing:border-box}.el-select-dropdown__item{font-size:14px;padding:0 20px;position:relative;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:#606266;height:34px;line-height:34px;-webkit-box-sizing:border-box;box-sizing:border-box;cursor:pointer}.el-select-dropdown__item.is-disabled{color:#C0C4CC;cursor:not-allowed}.el-select-dropdown__item.is-disabled:hover{background-color:#FFF}.el-select-dropdown__item.hover,.el-select-dropdown__item:hover{background-color:#F5F7FA}.el-select-dropdown__item.selected{color:#FDA833;font-weight:700}.el-select-group{margin:0;padding:0}.el-select-group__wrap{position:relative;list-style:none;margin:0;padding:0}.el-select-group__wrap:not(:last-of-type){padding-bottom:24px}.el-select-group__wrap:not(:last-of-type)::after{content:'';position:absolute;display:block;left:20px;right:20px;bottom:12px;height:1px;background:#E4E7ED}.el-select-group__title{padding-left:20px;font-size:12px;color:#909399;line-height:30px}.el-select-group .el-select-dropdown__item{padding-left:20px}.el-select{display:inline-block;position:relative}.el-select .el-select__tags>span{display:contents}.el-select:hover .el-input__inner{border-color:#C0C4CC}.el-select .el-input__inner{cursor:pointer;padding-right:35px}.el-select .el-input__inner:focus{border-color:#FDA833}.el-select .el-input .el-select__caret{color:#C0C4CC;font-size:14px;-webkit-transition:-webkit-transform .3s;transition:-webkit-transform .3s;transition:transform .3s;transition:transform .3s,-webkit-transform .3s;-webkit-transform:rotateZ(180deg);transform:rotateZ(180deg);cursor:pointer}.el-select .el-input .el-select__caret.is-reverse{-webkit-transform:rotateZ(0);transform:rotateZ(0)}.el-select .el-input .el-select__caret.is-show-close{font-size:14px;text-align:center;-webkit-transform:rotateZ(180deg);transform:rotateZ(180deg);border-radius:100%;color:#C0C4CC;-webkit-transition:color .2s cubic-bezier(.645,.045,.355,1);transition:color .2s cubic-bezier(.645,.045,.355,1)}.el-select .el-input .el-select__caret.is-show-close:hover{color:#909399}.el-select .el-input.is-disabled .el-input__inner{cursor:not-allowed}.el-select .el-input.is-disabled .el-input__inner:hover{border-color:#E4E7ED}.el-select .el-input.is-focus .el-input__inner{border-color:#FDA833}.el-select>.el-input{display:block}.el-select__input{border:none;outline:0;padding:0;margin-left:15px;color:#666;font-size:14px;-webkit-appearance:none;-moz-appearance:none;appearance:none;height:28px;background-color:transparent}.el-select__input.is-mini{height:14px}.el-select__close{cursor:pointer;position:absolute;top:8px;z-index:1000;right:25px;color:#C0C4CC;line-height:18px;font-size:14px}.el-select__close:hover{color:#909399}.el-select__tags{position:absolute;line-height:normal;white-space:normal;z-index:1;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%);display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-ms-flex-wrap:wrap;flex-wrap:wrap}.el-select .el-tag__close{margin-top:-2px}.el-select .el-tag{-webkit-box-sizing:border-box;box-sizing:border-box;border-color:transparent;margin:2px 0 2px 6px;background-color:#f0f2f5}.el-select .el-tag__close.el-icon-close{background-color:#C0C4CC;right:-7px;top:0;color:#FFF}.el-select .el-tag__close.el-icon-close:hover{background-color:#909399}.el-table,.el-table__expanded-cell{background-color:#FFF}.el-select .el-tag__close.el-icon-close::before{display:block;-webkit-transform:translate(0,.5px);transform:translate(0,.5px)}.el-table{position:relative;overflow:hidden;-webkit-box-sizing:border-box;box-sizing:border-box;-webkit-box-flex:1;-ms-flex:1;flex:1;width:100%;max-width:100%;font-size:14px;color:#606266}.el-table--mini,.el-table--small,.el-table__expand-icon{font-size:12px}.el-table__empty-block{min-height:60px;text-align:center;width:100%;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.el-table__empty-text{line-height:60px;width:50%;color:#909399}.el-table__expand-column .cell{padding:0;text-align:center}.el-table__expand-icon{position:relative;cursor:pointer;color:#666;-webkit-transition:-webkit-transform .2s ease-in-out;transition:-webkit-transform .2s ease-in-out;transition:transform .2s ease-in-out;transition:transform .2s ease-in-out,-webkit-transform .2s ease-in-out;height:20px}.el-table__expand-icon--expanded{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.el-table__expand-icon>.el-icon{position:absolute;left:50%;top:50%;margin-left:-5px;margin-top:-5px}.el-table__expanded-cell[class*=cell]{padding:20px 50px}.el-table__expanded-cell:hover{background-color:transparent!important}.el-table__placeholder{display:inline-block;width:20px}.el-table__append-wrapper{overflow:hidden}.el-table--fit{border-right:0;border-bottom:0}.el-table--fit td.gutter,.el-table--fit th.gutter{border-right-width:1px}.el-table--scrollable-x .el-table__body-wrapper{overflow-x:auto}.el-table--scrollable-y .el-table__body-wrapper{overflow-y:auto}.el-table thead{color:#909399;font-weight:500}.el-table thead.is-group th{background:#F5F7FA}.el-table th,.el-table tr{background-color:#FFF}.el-table td,.el-table th{padding:12px 0;min-width:0;-webkit-box-sizing:border-box;box-sizing:border-box;text-overflow:ellipsis;vertical-align:middle;position:relative;text-align:left}.el-table td.is-center,.el-table th.is-center{text-align:center}.el-table td.is-right,.el-table th.is-right{text-align:right}.el-table td.gutter,.el-table th.gutter{width:15px;border-right-width:0;border-bottom-width:0;padding:0}.el-table--medium td,.el-table--medium th{padding:10px 0}.el-table--small td,.el-table--small th{padding:8px 0}.el-table--mini td,.el-table--mini th{padding:6px 0}.el-table .cell,.el-table--border td:first-child .cell,.el-table--border th:first-child .cell{padding-left:10px}.el-table tr input[type=checkbox]{margin:0}.el-table td,.el-table th.is-leaf{border-bottom:1px solid #EBEEF5}.el-table th.is-sortable{cursor:pointer}.el-table th{overflow:hidden;-ms-user-select:none;user-select:none}.el-table th>.cell{display:inline-block;-webkit-box-sizing:border-box;box-sizing:border-box;position:relative;vertical-align:middle;padding-left:10px;padding-right:10px;width:100%}.el-table th>.cell.highlight{color:#FDA833}.el-table th.required>div::before{display:inline-block;content:"";width:8px;height:8px;border-radius:50%;background:#ff4d51;margin-right:5px;vertical-align:middle}.el-table td div{-webkit-box-sizing:border-box;box-sizing:border-box}.el-table td.gutter{width:0}.el-table .cell{-webkit-box-sizing:border-box;box-sizing:border-box;overflow:hidden;text-overflow:ellipsis;white-space:normal;word-break:break-all;line-height:23px;padding-right:10px}.el-table .cell.el-tooltip{white-space:nowrap;min-width:50px}.el-table--border,.el-table--group{border:1px solid #EBEEF5}.el-table--border::after,.el-table--group::after,.el-table::before{content:'';position:absolute;background-color:#EBEEF5;z-index:1}.el-table--border::after,.el-table--group::after{top:0;right:0;width:1px;height:100%}.el-table::before{left:0;bottom:0;width:100%;height:1px}.el-table--border{border-right:none;border-bottom:none}.el-table--border.el-loading-parent--relative{border-color:transparent}.el-table--border td,.el-table--border th,.el-table__body-wrapper .el-table--border.is-scrolling-left~.el-table__fixed{border-right:1px solid #EBEEF5}.el-table--border th.gutter:last-of-type{border-bottom:1px solid #EBEEF5;border-bottom-width:1px}.el-table--border th,.el-table__fixed-right-patch{border-bottom:1px solid #EBEEF5}.el-table__fixed,.el-table__fixed-right{position:absolute;top:0;left:0;overflow-x:hidden;overflow-y:hidden;-webkit-box-shadow:0 0 10px rgba(0,0,0,.12);box-shadow:0 0 10px rgba(0,0,0,.12)}.el-table__fixed-right::before,.el-table__fixed::before{content:'';position:absolute;left:0;bottom:0;width:100%;height:1px;background-color:#EBEEF5;z-index:4}.el-table__fixed-right-patch{position:absolute;top:-1px;right:0;background-color:#FFF}.el-table__fixed-right{top:0;left:auto;right:0}.el-table__fixed-right .el-table__fixed-body-wrapper,.el-table__fixed-right .el-table__fixed-footer-wrapper,.el-table__fixed-right .el-table__fixed-header-wrapper{left:auto;right:0}.el-table__fixed-header-wrapper{position:absolute;left:0;top:0;z-index:3}.el-table__fixed-footer-wrapper{position:absolute;left:0;bottom:0;z-index:3}.el-table__fixed-footer-wrapper tbody td{border-top:1px solid #EBEEF5;background-color:#F5F7FA;color:#606266}.el-table__fixed-body-wrapper{position:absolute;left:0;top:37px;overflow:hidden;z-index:3}.el-table__body-wrapper,.el-table__footer-wrapper,.el-table__header-wrapper{width:100%}.el-table__footer-wrapper{margin-top:-1px}.el-table__footer-wrapper td{border-top:1px solid #EBEEF5}.el-table__body,.el-table__footer,.el-table__header{table-layout:fixed;border-collapse:separate}.el-table__footer-wrapper,.el-table__header-wrapper{overflow:hidden}.el-table__footer-wrapper tbody td,.el-table__header-wrapper tbody td{background-color:#F5F7FA;color:#606266}.el-table__body-wrapper{overflow:hidden;position:relative}.el-table__body-wrapper.is-scrolling-left~.el-table__fixed,.el-table__body-wrapper.is-scrolling-none~.el-table__fixed,.el-table__body-wrapper.is-scrolling-none~.el-table__fixed-right,.el-table__body-wrapper.is-scrolling-right~.el-table__fixed-right{-webkit-box-shadow:none;box-shadow:none}.el-picker-panel,.el-table-filter{-webkit-box-shadow:0 2px 12px 0 rgba(0,0,0,.1)}.el-table__body-wrapper .el-table--border.is-scrolling-right~.el-table__fixed-right{border-left:1px solid #EBEEF5}.el-table .caret-wrapper{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:center;-ms-flex-align:center;align-items:center;height:34px;width:24px;vertical-align:middle;cursor:pointer;overflow:initial;position:relative}.el-table .sort-caret{width:0;height:0;border:5px solid transparent;position:absolute;left:7px}.el-table .sort-caret.ascending{border-bottom-color:#C0C4CC;top:5px}.el-table .sort-caret.descending{border-top-color:#C0C4CC;bottom:7px}.el-table .ascending .sort-caret.ascending{border-bottom-color:#FDA833}.el-table .descending .sort-caret.descending{border-top-color:#FDA833}.el-table .hidden-columns{position:absolute;z-index:-1}.el-table--striped .el-table__body tr.el-table__row--striped td{background:#FAFAFA}.el-table--striped .el-table__body tr.el-table__row--striped.current-row td{background-color:rgb(255, 246, 235)}.el-table__body tr.hover-row.current-row>td,.el-table__body tr.hover-row.el-table__row--striped.current-row>td,.el-table__body tr.hover-row.el-table__row--striped>td,.el-table__body tr.hover-row>td{background-color:#F5F7FA}.el-table__body tr.current-row>td{background-color:rgb(255, 246, 235)}.el-table__column-resize-proxy{position:absolute;left:200px;top:0;bottom:0;width:0;border-left:1px solid #EBEEF5;z-index:10}.el-table__column-filter-trigger{display:inline-block;line-height:34px;cursor:pointer}.el-table__column-filter-trigger i{color:#909399;font-size:12px;-webkit-transform:scale(.75);transform:scale(.75)}.el-table--enable-row-transition .el-table__body td{-webkit-transition:background-color .25s ease;transition:background-color .25s ease}.el-table--enable-row-hover .el-table__body tr:hover>td{background-color:#F5F7FA}.el-table--fluid-height .el-table__fixed,.el-table--fluid-height .el-table__fixed-right{bottom:0;overflow:hidden}.el-table [class*=el-table__row--level] .el-table__expand-icon{display:inline-block;width:20px;line-height:20px;height:20px;text-align:center;margin-right:3px}.el-table-column--selection .cell{padding-left:14px;padding-right:14px}.el-table-filter{border:1px solid #EBEEF5;border-radius:2px;background-color:#FFF;box-shadow:0 2px 12px 0 rgba(0,0,0,.1);-webkit-box-sizing:border-box;box-sizing:border-box;margin:2px 0}.el-date-table td,.el-date-table td div{height:30px;-webkit-box-sizing:border-box}.el-table-filter__list{padding:5px 0;margin:0;list-style:none;min-width:100px}.el-table-filter__list-item{line-height:36px;padding:0 10px;cursor:pointer;font-size:14px}.el-table-filter__list-item:hover{background-color:rgb(255, 246, 235);color:rgb(253, 185, 92)}.el-table-filter__list-item.is-active{background-color:#FDA833;color:#FFF}.el-table-filter__content{min-width:100px}.el-table-filter__bottom{border-top:1px solid #EBEEF5;padding:8px}.el-table-filter__bottom button{background:0 0;border:none;color:#606266;cursor:pointer;font-size:13px;padding:0 3px}.el-date-table td.in-range div,.el-date-table td.in-range div:hover,.el-date-table.is-week-mode .el-date-table__row.current div,.el-date-table.is-week-mode .el-date-table__row:hover div{background-color:#F2F6FC}.el-table-filter__bottom button:hover{color:#FDA833}.el-table-filter__bottom button:focus{outline:0}.el-table-filter__bottom button.is-disabled{color:#C0C4CC;cursor:not-allowed}.el-table-filter__wrap{max-height:280px}.el-table-filter__checkbox-group{padding:10px}.el-table-filter__checkbox-group label.el-checkbox{display:block;margin-right:5px;margin-bottom:8px;margin-left:5px}.el-table-filter__checkbox-group .el-checkbox:last-child{margin-bottom:0}.el-date-table{font-size:12px;-ms-user-select:none;user-select:none}.el-date-table.is-week-mode .el-date-table__row:hover td.available:hover{color:#606266}.el-date-table.is-week-mode .el-date-table__row:hover td:first-child div{margin-left:5px;border-top-left-radius:15px;border-bottom-left-radius:15px}.el-date-table.is-week-mode .el-date-table__row:hover td:last-child div{margin-right:5px;border-top-right-radius:15px;border-bottom-right-radius:15px}.el-date-table td{width:32px;padding:4px 0;box-sizing:border-box;text-align:center;cursor:pointer;position:relative}.el-date-table td div{padding:3px 0;box-sizing:border-box}.el-date-table td span{width:24px;height:24px;display:block;margin:0 auto;line-height:24px;position:absolute;left:50%;-webkit-transform:translateX(-50%);transform:translateX(-50%);border-radius:50%}.el-date-table td.next-month,.el-date-table td.prev-month{color:#C0C4CC}.el-date-table td.today{position:relative}.el-date-table td.today span{color:#FDA833;font-weight:700}.el-date-table td.today.end-date span,.el-date-table td.today.start-date span{color:#FFF}.el-date-table td.available:hover{color:#FDA833}.el-date-table td.current:not(.disabled) span{color:#FFF;background-color:#FDA833}.el-date-table td.end-date div,.el-date-table td.start-date div{color:#FFF}.el-date-table td.end-date span,.el-date-table td.start-date span{background-color:#FDA833}.el-date-table td.start-date div{margin-left:5px;border-top-left-radius:15px;border-bottom-left-radius:15px}.el-date-table td.end-date div{margin-right:5px;border-top-right-radius:15px;border-bottom-right-radius:15px}.el-date-table td.disabled div{background-color:#F5F7FA;opacity:1;cursor:not-allowed;color:#C0C4CC}.el-date-table td.selected div{margin-left:5px;margin-right:5px;background-color:#F2F6FC;border-radius:15px}.el-date-table td.selected div:hover{background-color:#F2F6FC}.el-date-table td.selected span{background-color:#FDA833;color:#FFF;border-radius:15px}.el-date-table td.week{font-size:80%;color:#606266}.el-month-table,.el-year-table{font-size:12px;border-collapse:collapse}.el-date-table th{padding:5px;color:#606266;font-weight:400;border-bottom:solid 1px #EBEEF5}.el-month-table{margin:-1px}.el-month-table td{text-align:center;padding:8px 0;cursor:pointer}.el-month-table td div{height:48px;padding:6px 0;-webkit-box-sizing:border-box;box-sizing:border-box}.el-month-table td.today .cell{color:#FDA833;font-weight:700}.el-month-table td.today.end-date .cell,.el-month-table td.today.start-date .cell{color:#FFF}.el-month-table td.disabled .cell{background-color:#F5F7FA;cursor:not-allowed;color:#C0C4CC}.el-month-table td.disabled .cell:hover{color:#C0C4CC}.el-month-table td .cell{width:60px;height:36px;display:block;line-height:36px;color:#606266;margin:0 auto;border-radius:18px}.el-month-table td .cell:hover{color:#FDA833}.el-month-table td.in-range div,.el-month-table td.in-range div:hover{background-color:#F2F6FC}.el-month-table td.end-date div,.el-month-table td.start-date div{color:#FFF}.el-month-table td.end-date .cell,.el-month-table td.start-date .cell{color:#FFF;background-color:#FDA833}.el-month-table td.start-date div{border-top-left-radius:24px;border-bottom-left-radius:24px}.el-month-table td.end-date div{border-top-right-radius:24px;border-bottom-right-radius:24px}.el-month-table td.current:not(.disabled) .cell{color:#FDA833}.el-year-table{margin:-1px}.el-year-table .el-icon{color:#303133}.el-year-table td{text-align:center;padding:20px 3px;cursor:pointer}.el-year-table td.today .cell{color:#FDA833;font-weight:700}.el-year-table td.disabled .cell{background-color:#F5F7FA;cursor:not-allowed;color:#C0C4CC}.el-year-table td.disabled .cell:hover{color:#C0C4CC}.el-year-table td .cell{width:48px;height:32px;display:block;line-height:32px;color:#606266;margin:0 auto}.el-year-table td .cell:hover,.el-year-table td.current:not(.disabled) .cell{color:#FDA833}.el-date-range-picker{width:646px}.el-date-range-picker.has-sidebar{width:756px}.el-date-range-picker table{table-layout:fixed;width:100%}.el-date-range-picker .el-picker-panel__body{min-width:513px}.el-date-range-picker .el-picker-panel__content{margin:0}.el-date-range-picker__header{position:relative;text-align:center;height:28px}.el-date-range-picker__header [class*=arrow-left]{float:left}.el-date-range-picker__header [class*=arrow-right]{float:right}.el-date-range-picker__header div{font-size:16px;font-weight:500;margin-right:50px}.el-date-range-picker__content{float:left;width:50%;-webkit-box-sizing:border-box;box-sizing:border-box;margin:0;padding:16px}.el-date-range-picker__content.is-left{border-right:1px solid #e4e4e4}.el-date-range-picker__content .el-date-range-picker__header div{margin-left:50px;margin-right:50px}.el-date-range-picker__editors-wrap{-webkit-box-sizing:border-box;box-sizing:border-box;display:table-cell}.el-date-range-picker__editors-wrap.is-right{text-align:right}.el-date-range-picker__time-header{position:relative;border-bottom:1px solid #e4e4e4;font-size:12px;padding:8px 5px 5px;display:table;width:100%;-webkit-box-sizing:border-box;box-sizing:border-box}.el-date-range-picker__time-header>.el-icon-arrow-right{font-size:20px;vertical-align:middle;display:table-cell;color:#303133}.el-date-range-picker__time-picker-wrap{position:relative;display:table-cell;padding:0 5px}.el-date-range-picker__time-picker-wrap .el-picker-panel{position:absolute;top:13px;right:0;z-index:1;background:#FFF}.el-date-picker{width:322px}.el-date-picker.has-sidebar.has-time{width:434px}.el-date-picker.has-sidebar{width:438px}.el-date-picker.has-time .el-picker-panel__body-wrapper{position:relative}.el-date-picker .el-picker-panel__content{width:292px}.el-date-picker table{table-layout:fixed;width:100%}.el-date-picker__editor-wrap{position:relative;display:table-cell;padding:0 5px}.el-date-picker__time-header{position:relative;border-bottom:1px solid #e4e4e4;font-size:12px;padding:8px 5px 5px;display:table;width:100%;-webkit-box-sizing:border-box;box-sizing:border-box}.el-date-picker__header{margin:12px;text-align:center}.el-date-picker__header--bordered{margin-bottom:0;padding-bottom:12px;border-bottom:solid 1px #EBEEF5}.el-date-picker__header--bordered+.el-picker-panel__content{margin-top:0}.el-date-picker__header-label{font-size:16px;font-weight:500;padding:0 5px;line-height:22px;text-align:center;cursor:pointer;color:#606266}.el-date-picker__header-label.active,.el-date-picker__header-label:hover{color:#FDA833}.el-date-picker__prev-btn{float:left}.el-date-picker__next-btn{float:right}.el-date-picker__time-wrap{padding:10px;text-align:center}.el-date-picker__time-label{float:left;cursor:pointer;line-height:30px;margin-left:10px}.time-select{margin:5px 0;min-width:0}.time-select .el-picker-panel__content{max-height:200px;margin:0}.time-select-item{padding:8px 10px;font-size:14px;line-height:20px}.time-select-item.selected:not(.disabled){color:#FDA833;font-weight:700}.time-select-item.disabled{color:#E4E7ED;cursor:not-allowed}.time-select-item:hover{background-color:#F5F7FA;font-weight:700;cursor:pointer}.el-date-editor{position:relative;display:inline-block;text-align:left}.el-date-editor.el-input,.el-date-editor.el-input__inner{width:220px}.el-date-editor--monthrange.el-input,.el-date-editor--monthrange.el-input__inner{width:300px}.el-date-editor--daterange.el-input,.el-date-editor--daterange.el-input__inner,.el-date-editor--timerange.el-input,.el-date-editor--timerange.el-input__inner{width:350px}.el-date-editor--datetimerange.el-input,.el-date-editor--datetimerange.el-input__inner{width:400px}.el-date-editor--dates .el-input__inner{text-overflow:ellipsis;white-space:nowrap}.el-date-editor .el-icon-circle-close{cursor:pointer}.el-date-editor .el-range__icon{font-size:14px;margin-left:-5px;color:#C0C4CC;float:left;line-height:32px}.el-date-editor .el-range-input,.el-date-editor .el-range-separator{height:100%;margin:0;text-align:center;display:inline-block;font-size:14px}.el-date-editor .el-range-input{-webkit-appearance:none;-moz-appearance:none;appearance:none;border:none;outline:0;padding:0;width:39%;color:#606266}.el-date-editor .el-range-input::-webkit-input-placeholder{color:#C0C4CC}.el-date-editor .el-range-input:-ms-input-placeholder{color:#C0C4CC}.el-date-editor .el-range-input::-ms-input-placeholder{color:#C0C4CC}.el-date-editor .el-range-input::placeholder{color:#C0C4CC}.el-date-editor .el-range-separator{padding:0 5px;line-height:32px;width:5%;color:#303133}.el-date-editor .el-range__close-icon{font-size:14px;color:#C0C4CC;width:25px;display:inline-block;float:right;line-height:32px}.el-range-editor.el-input__inner{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding:3px 10px}.el-range-editor .el-range-input{line-height:1}.el-range-editor.is-active,.el-range-editor.is-active:hover{border-color:#FDA833}.el-range-editor--medium.el-input__inner{height:36px}.el-range-editor--medium .el-range-separator{line-height:28px;font-size:14px}.el-range-editor--medium .el-range-input{font-size:14px}.el-range-editor--medium .el-range__close-icon,.el-range-editor--medium .el-range__icon{line-height:28px}.el-range-editor--small.el-input__inner{height:32px}.el-range-editor--small .el-range-separator{line-height:24px;font-size:13px}.el-range-editor--small .el-range-input{font-size:13px}.el-range-editor--small .el-range__close-icon,.el-range-editor--small .el-range__icon{line-height:24px}.el-range-editor--mini.el-input__inner{height:28px}.el-range-editor--mini .el-range-separator{line-height:20px;font-size:12px}.el-range-editor--mini .el-range-input{font-size:12px}.el-range-editor--mini .el-range__close-icon,.el-range-editor--mini .el-range__icon{line-height:20px}.el-range-editor.is-disabled{background-color:#F5F7FA;border-color:#E4E7ED;color:#C0C4CC;cursor:not-allowed}.el-range-editor.is-disabled:focus,.el-range-editor.is-disabled:hover{border-color:#E4E7ED}.el-range-editor.is-disabled input{background-color:#F5F7FA;color:#C0C4CC;cursor:not-allowed}.el-range-editor.is-disabled input::-webkit-input-placeholder{color:#C0C4CC}.el-range-editor.is-disabled input:-ms-input-placeholder{color:#C0C4CC}.el-range-editor.is-disabled input::-ms-input-placeholder{color:#C0C4CC}.el-range-editor.is-disabled input::placeholder{color:#C0C4CC}.el-range-editor.is-disabled .el-range-separator{color:#C0C4CC}.el-picker-panel{color:#606266;border:1px solid #E4E7ED;box-shadow:0 2px 12px 0 rgba(0,0,0,.1);background:#FFF;border-radius:4px;line-height:30px;margin:5px 0}.el-popover,.el-time-panel{-webkit-box-shadow:0 2px 12px 0 rgba(0,0,0,.1)}.el-picker-panel__body-wrapper::after,.el-picker-panel__body::after{content:"";display:table;clear:both}.el-picker-panel__content{position:relative;margin:15px}.el-picker-panel__footer{border-top:1px solid #e4e4e4;padding:4px;text-align:right;background-color:#FFF;position:relative;font-size:0}.el-picker-panel__shortcut{display:block;width:100%;border:0;background-color:transparent;line-height:28px;font-size:14px;color:#606266;padding-left:12px;text-align:left;outline:0;cursor:pointer}.el-picker-panel__shortcut:hover{color:#FDA833}.el-picker-panel__shortcut.active{background-color:#e6f1fe;color:#FDA833}.el-picker-panel__btn{border:1px solid #dcdcdc;color:#333;line-height:24px;border-radius:2px;padding:0 20px;cursor:pointer;background-color:transparent;outline:0;font-size:12px}.el-picker-panel__btn[disabled]{color:#ccc;cursor:not-allowed}.el-picker-panel__icon-btn{font-size:12px;color:#303133;border:0;background:0 0;cursor:pointer;outline:0;margin-top:8px}.el-picker-panel__icon-btn:hover{color:#FDA833}.el-picker-panel__icon-btn.is-disabled{color:#bbb}.el-picker-panel__icon-btn.is-disabled:hover{cursor:not-allowed}.el-picker-panel__link-btn{vertical-align:middle}.el-picker-panel [slot=sidebar],.el-picker-panel__sidebar{position:absolute;top:0;bottom:0;width:110px;border-right:1px solid #e4e4e4;-webkit-box-sizing:border-box;box-sizing:border-box;padding-top:6px;background-color:#FFF;overflow:auto}.el-picker-panel [slot=sidebar]+.el-picker-panel__body,.el-picker-panel__sidebar+.el-picker-panel__body{margin-left:110px}.el-time-spinner.has-seconds .el-time-spinner__wrapper{width:33.3%}.el-time-spinner__wrapper{max-height:190px;overflow:auto;display:inline-block;width:50%;vertical-align:top;position:relative}.el-time-spinner__wrapper .el-scrollbar__wrap:not(.el-scrollbar__wrap--hidden-default){padding-bottom:15px}.el-time-spinner__input.el-input .el-input__inner,.el-time-spinner__list{padding:0;text-align:center}.el-time-spinner__wrapper.is-arrow{-webkit-box-sizing:border-box;box-sizing:border-box;text-align:center;overflow:hidden}.el-time-spinner__wrapper.is-arrow .el-time-spinner__list{-webkit-transform:translateY(-32px);transform:translateY(-32px)}.el-time-spinner__wrapper.is-arrow .el-time-spinner__item:hover:not(.disabled):not(.active){background:#FFF;cursor:default}.el-time-spinner__arrow{font-size:12px;color:#909399;position:absolute;left:0;width:100%;z-index:1;text-align:center;height:30px;line-height:30px;cursor:pointer}.el-time-spinner__arrow:hover{color:#FDA833}.el-time-spinner__arrow.el-icon-arrow-up{top:10px}.el-time-spinner__arrow.el-icon-arrow-down{bottom:10px}.el-time-spinner__input.el-input{width:70%}.el-time-spinner__list{margin:0;list-style:none}.el-time-spinner__list::after,.el-time-spinner__list::before{content:'';display:block;width:100%;height:80px}.el-time-spinner__item{height:32px;line-height:32px;font-size:12px;color:#606266}.el-time-spinner__item:hover:not(.disabled):not(.active){background:#F5F7FA;cursor:pointer}.el-time-spinner__item.active:not(.disabled){color:#303133;font-weight:700}.el-time-spinner__item.disabled{color:#C0C4CC;cursor:not-allowed}.el-time-panel{margin:5px 0;border:1px solid #E4E7ED;background-color:#FFF;box-shadow:0 2px 12px 0 rgba(0,0,0,.1);border-radius:2px;position:absolute;width:180px;left:0;z-index:1000;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-box-sizing:content-box;box-sizing:content-box}.el-slider__button,.el-slider__button-wrapper{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}.el-time-panel__content{font-size:0;position:relative;overflow:hidden}.el-time-panel__content::after,.el-time-panel__content::before{content:"";top:50%;position:absolute;margin-top:-15px;height:32px;z-index:-1;left:0;right:0;-webkit-box-sizing:border-box;box-sizing:border-box;padding-top:6px;text-align:left;border-top:1px solid #E4E7ED;border-bottom:1px solid #E4E7ED}.el-time-panel__content::after{left:50%;margin-left:12%;margin-right:12%}.el-time-panel__content::before{padding-left:50%;margin-right:12%;margin-left:12%}.el-time-panel__content.has-seconds::after{left:calc(100% / 3 * 2)}.el-time-panel__content.has-seconds::before{padding-left:calc(100% / 3)}.el-time-panel__footer{border-top:1px solid #e4e4e4;padding:4px;height:36px;line-height:25px;text-align:right;-webkit-box-sizing:border-box;box-sizing:border-box}.el-time-panel__btn{border:none;line-height:28px;padding:0 5px;margin:0 5px;cursor:pointer;background-color:transparent;outline:0;font-size:12px;color:#303133}.el-time-panel__btn.confirm{font-weight:800;color:#FDA833}.el-time-range-picker{width:354px;overflow:visible}.el-time-range-picker__content{position:relative;text-align:center;padding:10px}.el-time-range-picker__cell{-webkit-box-sizing:border-box;box-sizing:border-box;margin:0;padding:4px 7px 7px;width:50%;display:inline-block}.el-time-range-picker__header{margin-bottom:5px;text-align:center;font-size:14px}.el-time-range-picker__body{border-radius:2px;border:1px solid #E4E7ED}.el-popover{position:absolute;background:#FFF;min-width:150px;border:1px solid #EBEEF5;padding:12px;z-index:2000;color:#606266;line-height:1.4;text-align:justify;font-size:14px;box-shadow:0 2px 12px 0 rgba(0,0,0,.1);word-break:break-all}.el-popover--plain{padding:18px 20px}.el-popover__title{color:#303133;font-size:16px;line-height:1;margin-bottom:12px}.v-modal-enter{-webkit-animation:v-modal-in .2s ease;animation:v-modal-in .2s ease}.v-modal-leave{-webkit-animation:v-modal-out .2s ease forwards;animation:v-modal-out .2s ease forwards}@keyframes v-modal-in{0%{opacity:0}}@keyframes v-modal-out{100%{opacity:0}}.v-modal{position:fixed;left:0;top:0;width:100%;height:100%;opacity:.5;background:#000}.el-popup-parent--hidden{overflow:hidden}.el-message-box{display:inline-block;width:420px;padding-bottom:10px;vertical-align:middle;background-color:#FFF;border-radius:4px;border:1px solid #EBEEF5;font-size:18px;-webkit-box-shadow:0 2px 12px 0 rgba(0,0,0,.1);box-shadow:0 2px 12px 0 rgba(0,0,0,.1);text-align:left;overflow:hidden;-webkit-backface-visibility:hidden;backface-visibility:hidden}.el-message-box__wrapper{position:fixed;top:0;bottom:0;left:0;right:0;text-align:center}.el-message-box__wrapper::after{content:"";display:inline-block;height:100%;width:0;vertical-align:middle}.el-message-box__header{position:relative;padding:15px 15px 10px}.el-message-box__title{padding-left:0;margin-bottom:0;font-size:18px;line-height:1;color:#303133}.el-message-box__headerbtn{position:absolute;top:15px;right:15px;padding:0;border:none;outline:0;background:0 0;font-size:16px;cursor:pointer}.el-form-item.is-error .el-input__inner,.el-form-item.is-error .el-input__inner:focus,.el-form-item.is-error .el-textarea__inner,.el-form-item.is-error .el-textarea__inner:focus,.el-message-box__input input.invalid,.el-message-box__input input.invalid:focus{border-color:#F56C6C}.el-message-box__headerbtn .el-message-box__close{color:#909399}.el-message-box__headerbtn:focus .el-message-box__close,.el-message-box__headerbtn:hover .el-message-box__close{color:#FDA833}.el-message-box__content{padding:10px 15px;color:#606266;font-size:14px}.el-message-box__container{position:relative}.el-message-box__input{padding-top:15px}.el-message-box__status{position:absolute;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%);font-size:24px!important}.el-message-box__status::before{padding-left:1px}.el-message-box__status+.el-message-box__message{padding-left:36px;padding-right:12px}.el-message-box__status.el-icon-success{color:#67C23A}.el-message-box__status.el-icon-info{color:#909399}.el-message-box__status.el-icon-warning{color:#E6A23C}.el-message-box__status.el-icon-error{color:#F56C6C}.el-message-box__message{margin:0}.el-message-box__message p{margin:0;line-height:24px}.el-message-box__errormsg{color:#F56C6C;font-size:12px;min-height:18px;margin-top:2px}.el-message-box__btns{padding:5px 15px 0;text-align:right}.el-message-box__btns button:nth-child(2){margin-left:10px}.el-message-box__btns-reverse{-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse}.el-message-box--center{padding-bottom:30px}.el-message-box--center .el-message-box__header{padding-top:30px}.el-message-box--center .el-message-box__title{position:relative;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.el-message-box--center .el-message-box__status{position:relative;top:auto;padding-right:5px;text-align:center;-webkit-transform:translateY(-1px);transform:translateY(-1px)}.el-message-box--center .el-message-box__message{margin-left:0}.el-message-box--center .el-message-box__btns,.el-message-box--center .el-message-box__content{text-align:center}.el-message-box--center .el-message-box__content{padding-left:27px;padding-right:27px}.msgbox-fade-enter-active{-webkit-animation:msgbox-fade-in .3s;animation:msgbox-fade-in .3s}.msgbox-fade-leave-active{-webkit-animation:msgbox-fade-out .3s;animation:msgbox-fade-out .3s}@-webkit-keyframes msgbox-fade-in{0%{-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0);opacity:0}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1}}@keyframes msgbox-fade-in{0%{-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0);opacity:0}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1}}@-webkit-keyframes msgbox-fade-out{0%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1}100%{-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0);opacity:0}}@keyframes msgbox-fade-out{0%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1}100%{-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0);opacity:0}}.el-breadcrumb{font-size:14px;line-height:1}.el-breadcrumb::after,.el-breadcrumb::before{display:table;content:""}.el-breadcrumb::after{clear:both}.el-breadcrumb__separator{margin:0 9px;font-weight:700;color:#C0C4CC}.el-breadcrumb__separator[class*=icon]{margin:0 6px;font-weight:400}.el-breadcrumb__item{float:left}.el-breadcrumb__inner{color:#606266}.el-breadcrumb__inner a,.el-breadcrumb__inner.is-link{font-weight:700;text-decoration:none;-webkit-transition:color .2s cubic-bezier(.645,.045,.355,1);transition:color .2s cubic-bezier(.645,.045,.355,1);color:#303133}.el-breadcrumb__inner a:hover,.el-breadcrumb__inner.is-link:hover{color:#FDA833;cursor:pointer}.el-breadcrumb__item:last-child .el-breadcrumb__inner,.el-breadcrumb__item:last-child .el-breadcrumb__inner a,.el-breadcrumb__item:last-child .el-breadcrumb__inner a:hover,.el-breadcrumb__item:last-child .el-breadcrumb__inner:hover{font-weight:400;color:#606266;cursor:text}.el-breadcrumb__item:last-child .el-breadcrumb__separator{display:none}.el-form--label-left .el-form-item__label{text-align:left}.el-form--label-top .el-form-item__label{float:none;display:inline-block;text-align:left;padding:0 0 10px}.el-form--inline .el-form-item{display:inline-block;margin-right:10px;vertical-align:top}.el-form--inline .el-form-item__label{float:none;display:inline-block}.el-form--inline .el-form-item__content{display:inline-block;vertical-align:top}.el-form--inline.el-form--label-top .el-form-item__content{display:block}.el-form-item{margin-bottom:22px}.el-form-item::after,.el-form-item::before{display:table;content:""}.el-form-item::after{clear:both}.el-form-item .el-form-item{margin-bottom:0}.el-form-item--mini.el-form-item,.el-form-item--small.el-form-item{margin-bottom:18px}.el-form-item .el-input__validateIcon{display:none}.el-form-item--medium .el-form-item__content,.el-form-item--medium .el-form-item__label{line-height:36px}.el-form-item--small .el-form-item__content,.el-form-item--small .el-form-item__label{line-height:32px}.el-form-item--small .el-form-item__error{padding-top:2px}.el-form-item--mini .el-form-item__content,.el-form-item--mini .el-form-item__label{line-height:28px}.el-form-item--mini .el-form-item__error{padding-top:1px}.el-form-item__label-wrap{float:left}.el-form-item__label-wrap .el-form-item__label{display:inline-block;float:none}.el-form-item__label{text-align:right;vertical-align:middle;float:left;font-size:14px;color:#606266;line-height:40px;padding:0 12px 0 0;-webkit-box-sizing:border-box;box-sizing:border-box}.el-form-item__content{line-height:40px;position:relative;font-size:14px}.el-form-item__content::after,.el-form-item__content::before{display:table;content:""}.el-form-item__content::after{clear:both}.el-form-item__content .el-input-group{vertical-align:top}.el-form-item__error{color:#F56C6C;font-size:12px;line-height:1;padding-top:4px;position:absolute;top:100%;left:0}.el-form-item__error--inline{position:relative;top:auto;left:auto;display:inline-block;margin-left:10px}.el-form-item.is-required:not(.is-no-asterisk) .el-form-item__label-wrap>.el-form-item__label:before,.el-form-item.is-required:not(.is-no-asterisk)>.el-form-item__label:before{content:'*';color:#F56C6C;margin-right:4px}.el-form-item.is-error .el-input-group__append .el-input__inner,.el-form-item.is-error .el-input-group__prepend .el-input__inner{border-color:transparent}.el-form-item.is-error .el-input__validateIcon{color:#F56C6C}.el-form-item--feedback .el-input__validateIcon{display:inline-block}.el-tabs__header{padding:0;position:relative;margin:0 0 15px}.el-tabs__active-bar{position:absolute;bottom:0;left:0;height:2px;background-color:#FDA833;z-index:1;-webkit-transition:-webkit-transform .3s cubic-bezier(.645,.045,.355,1);transition:-webkit-transform .3s cubic-bezier(.645,.045,.355,1);transition:transform .3s cubic-bezier(.645,.045,.355,1);transition:transform .3s cubic-bezier(.645,.045,.355,1),-webkit-transform .3s cubic-bezier(.645,.045,.355,1);list-style:none}.el-tabs__new-tab{float:right;border:1px solid #d3dce6;height:18px;width:18px;line-height:18px;margin:12px 0 9px 10px;border-radius:3px;text-align:center;font-size:12px;color:#d3dce6;cursor:pointer;-webkit-transition:all .15s;transition:all .15s}.el-collapse-item__arrow,.el-tabs__nav{-webkit-transition:-webkit-transform .3s}.el-tabs__new-tab .el-icon-plus{-webkit-transform:scale(.8,.8);transform:scale(.8,.8)}.el-tabs__new-tab:hover{color:#FDA833}.el-tabs__nav-wrap{overflow:hidden;margin-bottom:-1px;position:relative}.el-tabs__nav-wrap::after{content:"";position:absolute;left:0;bottom:0;width:100%;height:2px;background-color:#E4E7ED;z-index:1}.el-tabs--border-card>.el-tabs__header .el-tabs__nav-wrap::after,.el-tabs--card>.el-tabs__header .el-tabs__nav-wrap::after{content:none}.el-tabs__nav-wrap.is-scrollable{padding:0 20px;-webkit-box-sizing:border-box;box-sizing:border-box}.el-tabs__nav-scroll{overflow:hidden}.el-tabs__nav-next,.el-tabs__nav-prev{position:absolute;cursor:pointer;line-height:44px;font-size:12px;color:#909399}.el-tabs__nav-next{right:0}.el-tabs__nav-prev{left:0}.el-tabs__nav{white-space:nowrap;position:relative;transition:-webkit-transform .3s;transition:transform .3s;transition:transform .3s,-webkit-transform .3s;float:left;z-index:2}.el-tabs__nav.is-stretch{min-width:100%;display:-webkit-box;display:-ms-flexbox;display:flex}.el-tabs__nav.is-stretch>*{-webkit-box-flex:1;-ms-flex:1;flex:1;text-align:center}.el-tabs__item{padding:0 20px;height:40px;-webkit-box-sizing:border-box;box-sizing:border-box;line-height:40px;display:inline-block;list-style:none;font-size:14px;font-weight:500;color:#303133;position:relative}.el-tabs__item:focus,.el-tabs__item:focus:active{outline:0}.el-tabs__item:focus.is-active.is-focus:not(:active){-webkit-box-shadow:0 0 2px 2px #FDA833 inset;box-shadow:0 0 2px 2px #FDA833 inset;border-radius:3px}.el-tabs__item .el-icon-close{border-radius:50%;text-align:center;-webkit-transition:all .3s cubic-bezier(.645,.045,.355,1);transition:all .3s cubic-bezier(.645,.045,.355,1);margin-left:5px}.el-tabs__item .el-icon-close:before{-webkit-transform:scale(.9);transform:scale(.9);display:inline-block}.el-tabs__item .el-icon-close:hover{background-color:#C0C4CC;color:#FFF}.el-tabs__item.is-active{color:#FDA833}.el-tabs__item:hover{color:#FDA833;cursor:pointer}.el-tabs__item.is-disabled{color:#C0C4CC;cursor:default}.el-tabs__content{overflow:hidden;position:relative}.el-tabs--card>.el-tabs__header{border-bottom:1px solid #E4E7ED}.el-tabs--card>.el-tabs__header .el-tabs__nav{border:1px solid #E4E7ED;border-bottom:none;border-radius:4px 4px 0 0;-webkit-box-sizing:border-box;box-sizing:border-box}.el-tabs--card>.el-tabs__header .el-tabs__active-bar{display:none}.el-tabs--card>.el-tabs__header .el-tabs__item .el-icon-close{position:relative;font-size:12px;width:0;height:14px;vertical-align:middle;line-height:15px;overflow:hidden;top:-1px;right:-2px;-webkit-transform-origin:100% 50%;transform-origin:100% 50%}.el-tabs--card>.el-tabs__header .el-tabs__item.is-active.is-closable .el-icon-close,.el-tabs--card>.el-tabs__header .el-tabs__item.is-closable:hover .el-icon-close{width:14px}.el-tabs--card>.el-tabs__header .el-tabs__item{border-bottom:1px solid transparent;border-left:1px solid #E4E7ED;-webkit-transition:color .3s cubic-bezier(.645,.045,.355,1),padding .3s cubic-bezier(.645,.045,.355,1);transition:color .3s cubic-bezier(.645,.045,.355,1),padding .3s cubic-bezier(.645,.045,.355,1)}.el-tabs--card>.el-tabs__header .el-tabs__item:first-child{border-left:none}.el-tabs--card>.el-tabs__header .el-tabs__item.is-closable:hover{padding-left:13px;padding-right:13px}.el-tabs--card>.el-tabs__header .el-tabs__item.is-active{border-bottom-color:#FFF}.el-tabs--card>.el-tabs__header .el-tabs__item.is-active.is-closable{padding-left:20px;padding-right:20px}.el-tabs--border-card{background:#FFF;border:1px solid #DCDFE6;-webkit-box-shadow:0 2px 4px 0 rgba(0,0,0,.12),0 0 6px 0 rgba(0,0,0,.04);box-shadow:0 2px 4px 0 rgba(0,0,0,.12),0 0 6px 0 rgba(0,0,0,.04)}.el-tabs--border-card>.el-tabs__content{padding:15px}.el-tabs--border-card>.el-tabs__header{background-color:#F5F7FA;border-bottom:1px solid #E4E7ED;margin:0}.el-tabs--border-card>.el-tabs__header .el-tabs__item{-webkit-transition:all .3s cubic-bezier(.645,.045,.355,1);transition:all .3s cubic-bezier(.645,.045,.355,1);border:1px solid transparent;margin-top:-1px;color:#909399}.el-tabs--border-card>.el-tabs__header .el-tabs__item+.el-tabs__item,.el-tabs--border-card>.el-tabs__header .el-tabs__item:first-child{margin-left:-1px}.el-tabs--border-card>.el-tabs__header .el-tabs__item.is-active{color:#FDA833;background-color:#FFF;border-right-color:#DCDFE6;border-left-color:#DCDFE6}.el-tabs--border-card>.el-tabs__header .el-tabs__item:not(.is-disabled):hover{color:#FDA833}.el-tabs--border-card>.el-tabs__header .el-tabs__item.is-disabled{color:#C0C4CC}.el-tabs--border-card>.el-tabs__header .is-scrollable .el-tabs__item:first-child{margin-left:0}.el-tabs--bottom .el-tabs__item.is-bottom:nth-child(2),.el-tabs--bottom .el-tabs__item.is-top:nth-child(2),.el-tabs--top .el-tabs__item.is-bottom:nth-child(2),.el-tabs--top .el-tabs__item.is-top:nth-child(2){padding-left:0}.el-tabs--bottom .el-tabs__item.is-bottom:last-child,.el-tabs--bottom .el-tabs__item.is-top:last-child,.el-tabs--top .el-tabs__item.is-bottom:last-child,.el-tabs--top .el-tabs__item.is-top:last-child{padding-right:0}.el-tabs--bottom .el-tabs--left>.el-tabs__header .el-tabs__item:nth-child(2),.el-tabs--bottom .el-tabs--right>.el-tabs__header .el-tabs__item:nth-child(2),.el-tabs--bottom.el-tabs--border-card>.el-tabs__header .el-tabs__item:nth-child(2),.el-tabs--bottom.el-tabs--card>.el-tabs__header .el-tabs__item:nth-child(2),.el-tabs--top .el-tabs--left>.el-tabs__header .el-tabs__item:nth-child(2),.el-tabs--top .el-tabs--right>.el-tabs__header .el-tabs__item:nth-child(2),.el-tabs--top.el-tabs--border-card>.el-tabs__header .el-tabs__item:nth-child(2),.el-tabs--top.el-tabs--card>.el-tabs__header .el-tabs__item:nth-child(2){padding-left:20px}.el-tabs--bottom .el-tabs--left>.el-tabs__header .el-tabs__item:last-child,.el-tabs--bottom .el-tabs--right>.el-tabs__header .el-tabs__item:last-child,.el-tabs--bottom.el-tabs--border-card>.el-tabs__header .el-tabs__item:last-child,.el-tabs--bottom.el-tabs--card>.el-tabs__header .el-tabs__item:last-child,.el-tabs--top .el-tabs--left>.el-tabs__header .el-tabs__item:last-child,.el-tabs--top .el-tabs--right>.el-tabs__header .el-tabs__item:last-child,.el-tabs--top.el-tabs--border-card>.el-tabs__header .el-tabs__item:last-child,.el-tabs--top.el-tabs--card>.el-tabs__header .el-tabs__item:last-child{padding-right:20px}.el-tabs--bottom .el-tabs__header.is-bottom{margin-bottom:0;margin-top:10px}.el-tabs--bottom.el-tabs--border-card .el-tabs__header.is-bottom{border-bottom:0;border-top:1px solid #DCDFE6}.el-tabs--bottom.el-tabs--border-card .el-tabs__nav-wrap.is-bottom{margin-top:-1px;margin-bottom:0}.el-tabs--bottom.el-tabs--border-card .el-tabs__item.is-bottom:not(.is-active){border:1px solid transparent}.el-tabs--bottom.el-tabs--border-card .el-tabs__item.is-bottom{margin:0 -1px -1px}.el-tabs--left,.el-tabs--right{overflow:hidden}.el-tabs--left .el-tabs__header.is-left,.el-tabs--left .el-tabs__header.is-right,.el-tabs--left .el-tabs__nav-scroll,.el-tabs--left .el-tabs__nav-wrap.is-left,.el-tabs--left .el-tabs__nav-wrap.is-right,.el-tabs--right .el-tabs__header.is-left,.el-tabs--right .el-tabs__header.is-right,.el-tabs--right .el-tabs__nav-scroll,.el-tabs--right .el-tabs__nav-wrap.is-left,.el-tabs--right .el-tabs__nav-wrap.is-right{height:100%}.el-tabs--left .el-tabs__active-bar.is-left,.el-tabs--left .el-tabs__active-bar.is-right,.el-tabs--right .el-tabs__active-bar.is-left,.el-tabs--right .el-tabs__active-bar.is-right{top:0;bottom:auto;width:2px;height:auto}.el-tabs--left .el-tabs__nav-wrap.is-left,.el-tabs--left .el-tabs__nav-wrap.is-right,.el-tabs--right .el-tabs__nav-wrap.is-left,.el-tabs--right .el-tabs__nav-wrap.is-right{margin-bottom:0}.el-tabs--left .el-tabs__nav-wrap.is-left>.el-tabs__nav-next,.el-tabs--left .el-tabs__nav-wrap.is-left>.el-tabs__nav-prev,.el-tabs--left .el-tabs__nav-wrap.is-right>.el-tabs__nav-next,.el-tabs--left .el-tabs__nav-wrap.is-right>.el-tabs__nav-prev,.el-tabs--right .el-tabs__nav-wrap.is-left>.el-tabs__nav-next,.el-tabs--right .el-tabs__nav-wrap.is-left>.el-tabs__nav-prev,.el-tabs--right .el-tabs__nav-wrap.is-right>.el-tabs__nav-next,.el-tabs--right .el-tabs__nav-wrap.is-right>.el-tabs__nav-prev{height:30px;line-height:30px;width:100%;text-align:center;cursor:pointer}.el-tabs--left .el-tabs__nav-wrap.is-left>.el-tabs__nav-next i,.el-tabs--left .el-tabs__nav-wrap.is-left>.el-tabs__nav-prev i,.el-tabs--left .el-tabs__nav-wrap.is-right>.el-tabs__nav-next i,.el-tabs--left .el-tabs__nav-wrap.is-right>.el-tabs__nav-prev i,.el-tabs--right .el-tabs__nav-wrap.is-left>.el-tabs__nav-next i,.el-tabs--right .el-tabs__nav-wrap.is-left>.el-tabs__nav-prev i,.el-tabs--right .el-tabs__nav-wrap.is-right>.el-tabs__nav-next i,.el-tabs--right .el-tabs__nav-wrap.is-right>.el-tabs__nav-prev i{-webkit-transform:rotateZ(90deg);transform:rotateZ(90deg)}.el-tabs--left .el-tabs__nav-wrap.is-left>.el-tabs__nav-prev,.el-tabs--left .el-tabs__nav-wrap.is-right>.el-tabs__nav-prev,.el-tabs--right .el-tabs__nav-wrap.is-left>.el-tabs__nav-prev,.el-tabs--right .el-tabs__nav-wrap.is-right>.el-tabs__nav-prev{left:auto;top:0}.el-tabs--left .el-tabs__nav-wrap.is-left>.el-tabs__nav-next,.el-tabs--left .el-tabs__nav-wrap.is-right>.el-tabs__nav-next,.el-tabs--right .el-tabs__nav-wrap.is-left>.el-tabs__nav-next,.el-tabs--right .el-tabs__nav-wrap.is-right>.el-tabs__nav-next{right:auto;bottom:0}.el-tabs--left .el-tabs__active-bar.is-left,.el-tabs--left .el-tabs__nav-wrap.is-left::after{right:0;left:auto}.el-tabs--left .el-tabs__nav-wrap.is-left.is-scrollable,.el-tabs--left .el-tabs__nav-wrap.is-right.is-scrollable,.el-tabs--right .el-tabs__nav-wrap.is-left.is-scrollable,.el-tabs--right .el-tabs__nav-wrap.is-right.is-scrollable{padding:30px 0}.el-tabs--left .el-tabs__nav-wrap.is-left::after,.el-tabs--left .el-tabs__nav-wrap.is-right::after,.el-tabs--right .el-tabs__nav-wrap.is-left::after,.el-tabs--right .el-tabs__nav-wrap.is-right::after{height:100%;width:2px;bottom:auto;top:0}.el-tabs--left .el-tabs__nav.is-left,.el-tabs--left .el-tabs__nav.is-right,.el-tabs--right .el-tabs__nav.is-left,.el-tabs--right .el-tabs__nav.is-right{float:none}.el-tabs--left .el-tabs__item.is-left,.el-tabs--left .el-tabs__item.is-right,.el-tabs--right .el-tabs__item.is-left,.el-tabs--right .el-tabs__item.is-right{display:block}.el-tabs--left.el-tabs--card .el-tabs__active-bar.is-left,.el-tabs--right.el-tabs--card .el-tabs__active-bar.is-right{display:none}.el-tabs--left .el-tabs__header.is-left{float:left;margin-bottom:0;margin-right:10px}.el-tabs--left .el-tabs__nav-wrap.is-left{margin-right:-1px}.el-tabs--left .el-tabs__item.is-left{text-align:right}.el-tabs--left.el-tabs--card .el-tabs__item.is-left{border-left:none;border-right:1px solid #E4E7ED;border-bottom:none;border-top:1px solid #E4E7ED;text-align:left}.el-tabs--left.el-tabs--card .el-tabs__item.is-left:first-child{border-right:1px solid #E4E7ED;border-top:none}.el-tabs--left.el-tabs--card .el-tabs__item.is-left.is-active{border:1px solid #E4E7ED;border-right-color:#fff;border-left:none;border-bottom:none}.el-tabs--left.el-tabs--card .el-tabs__item.is-left.is-active:first-child{border-top:none}.el-tabs--left.el-tabs--card .el-tabs__item.is-left.is-active:last-child{border-bottom:none}.el-tabs--left.el-tabs--card .el-tabs__nav{border-radius:4px 0 0 4px;border-bottom:1px solid #E4E7ED;border-right:none}.el-tabs--left.el-tabs--card .el-tabs__new-tab{float:none}.el-tabs--left.el-tabs--border-card .el-tabs__header.is-left{border-right:1px solid #dfe4ed}.el-tabs--left.el-tabs--border-card .el-tabs__item.is-left{border:1px solid transparent;margin:-1px 0 -1px -1px}.el-tabs--left.el-tabs--border-card .el-tabs__item.is-left.is-active{border-color:#d1dbe5 transparent}.el-tabs--right .el-tabs__header.is-right{float:right;margin-bottom:0;margin-left:10px}.el-tabs--right .el-tabs__nav-wrap.is-right{margin-left:-1px}.el-tabs--right .el-tabs__nav-wrap.is-right::after{left:0;right:auto}.el-tabs--right .el-tabs__active-bar.is-right{left:0}.el-tabs--right.el-tabs--card .el-tabs__item.is-right{border-bottom:none;border-top:1px solid #E4E7ED}.el-tabs--right.el-tabs--card .el-tabs__item.is-right:first-child{border-left:1px solid #E4E7ED;border-top:none}.el-tabs--right.el-tabs--card .el-tabs__item.is-right.is-active{border:1px solid #E4E7ED;border-left-color:#fff;border-right:none;border-bottom:none}.el-tabs--right.el-tabs--card .el-tabs__item.is-right.is-active:first-child{border-top:none}.el-tabs--right.el-tabs--card .el-tabs__item.is-right.is-active:last-child{border-bottom:none}.el-tabs--right.el-tabs--card .el-tabs__nav{border-radius:0 4px 4px 0;border-bottom:1px solid #E4E7ED;border-left:none}.el-tabs--right.el-tabs--border-card .el-tabs__header.is-right{border-left:1px solid #dfe4ed}.el-tabs--right.el-tabs--border-card .el-tabs__item.is-right{border:1px solid transparent;margin:-1px -1px -1px 0}.el-tabs--right.el-tabs--border-card .el-tabs__item.is-right.is-active{border-color:#d1dbe5 transparent}.slideInLeft-transition,.slideInRight-transition{display:inline-block}.slideInRight-enter{-webkit-animation:slideInRight-enter .3s;animation:slideInRight-enter .3s}.slideInRight-leave{position:absolute;left:0;right:0;-webkit-animation:slideInRight-leave .3s;animation:slideInRight-leave .3s}.slideInLeft-enter{-webkit-animation:slideInLeft-enter .3s;animation:slideInLeft-enter .3s}.slideInLeft-leave{position:absolute;left:0;right:0;-webkit-animation:slideInLeft-leave .3s;animation:slideInLeft-leave .3s}@-webkit-keyframes slideInRight-enter{0%{opacity:0;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:translateX(100%);transform:translateX(100%)}to{opacity:1;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:translateX(0);transform:translateX(0)}}@keyframes slideInRight-enter{0%{opacity:0;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:translateX(100%);transform:translateX(100%)}to{opacity:1;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:translateX(0);transform:translateX(0)}}@-webkit-keyframes slideInRight-leave{0%{-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:translateX(0);transform:translateX(0);opacity:1}100%{-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:translateX(100%);transform:translateX(100%);opacity:0}}@keyframes slideInRight-leave{0%{-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:translateX(0);transform:translateX(0);opacity:1}100%{-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:translateX(100%);transform:translateX(100%);opacity:0}}@-webkit-keyframes slideInLeft-enter{0%{opacity:0;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:translateX(-100%);transform:translateX(-100%)}to{opacity:1;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:translateX(0);transform:translateX(0)}}@keyframes slideInLeft-enter{0%{opacity:0;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:translateX(-100%);transform:translateX(-100%)}to{opacity:1;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:translateX(0);transform:translateX(0)}}@-webkit-keyframes slideInLeft-leave{0%{-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:translateX(0);transform:translateX(0);opacity:1}100%{-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:translateX(-100%);transform:translateX(-100%);opacity:0}}@keyframes slideInLeft-leave{0%{-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:translateX(0);transform:translateX(0);opacity:1}100%{-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:translateX(-100%);transform:translateX(-100%);opacity:0}}.el-tree{position:relative;cursor:default;background:#FFF;color:#606266}.el-tree__empty-block{position:relative;min-height:60px;text-align:center;width:100%;height:100%}.el-tree__empty-text{position:absolute;left:50%;top:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);color:#909399;font-size:14px}.el-tree__drop-indicator{position:absolute;left:0;right:0;height:1px;background-color:#FDA833}.el-tree-node{white-space:nowrap;outline:0}.el-tree-node:focus>.el-tree-node__content{background-color:#F5F7FA}.el-tree-node.is-drop-inner>.el-tree-node__content .el-tree-node__label{background-color:#FDA833;color:#fff}.el-tree-node__content{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;height:26px;cursor:pointer}.el-tree-node__content>.el-tree-node__expand-icon{padding:6px}.el-tree-node__content>label.el-checkbox{margin-right:8px}.el-tree-node__content:hover{background-color:#F5F7FA}.el-tree.is-dragging .el-tree-node__content{cursor:move}.el-tree.is-dragging.is-drop-not-allow .el-tree-node__content{cursor:not-allowed}.el-tree-node__expand-icon{cursor:pointer;color:#C0C4CC;font-size:12px;-webkit-transform:rotate(0);transform:rotate(0);-webkit-transition:-webkit-transform .3s ease-in-out;transition:-webkit-transform .3s ease-in-out;transition:transform .3s ease-in-out;transition:transform .3s ease-in-out,-webkit-transform .3s ease-in-out}.el-tree-node__expand-icon.expanded{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.el-tree-node__expand-icon.is-leaf{color:transparent;cursor:default}.el-tree-node__label{font-size:14px}.el-tree-node__loading-icon{margin-right:8px;font-size:14px;color:#C0C4CC}.el-tree-node>.el-tree-node__children{overflow:hidden;background-color:transparent}.el-tree-node.is-expanded>.el-tree-node__children{display:block}.el-tree--highlight-current .el-tree-node.is-current>.el-tree-node__content{background-color:#f0f7ff}.el-alert{width:100%;padding:8px 16px;margin:0;-webkit-box-sizing:border-box;box-sizing:border-box;border-radius:4px;position:relative;background-color:#FFF;overflow:hidden;opacity:1;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-transition:opacity .2s;transition:opacity .2s}.el-alert.is-light .el-alert__closebtn{color:#C0C4CC}.el-alert.is-dark .el-alert__closebtn,.el-alert.is-dark .el-alert__description{color:#FFF}.el-alert.is-center{-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.el-alert--success.is-light{background-color:#f0f9eb;color:#67C23A}.el-alert--success.is-light .el-alert__description{color:#67C23A}.el-alert--success.is-dark{background-color:#67C23A;color:#FFF}.el-alert--info.is-light{background-color:#f4f4f5;color:#909399}.el-alert--info.is-dark{background-color:#909399;color:#FFF}.el-alert--info .el-alert__description{color:#909399}.el-alert--warning.is-light{background-color:#fdf6ec;color:#E6A23C}.el-alert--warning.is-light .el-alert__description{color:#E6A23C}.el-alert--warning.is-dark{background-color:#E6A23C;color:#FFF}.el-alert--error.is-light{background-color:#fef0f0;color:#F56C6C}.el-alert--error.is-light .el-alert__description{color:#F56C6C}.el-alert--error.is-dark{background-color:#F56C6C;color:#FFF}.el-alert__content{display:table-cell;padding:0 8px}.el-alert__icon{font-size:16px;width:16px}.el-alert__icon.is-big{font-size:28px;width:28px}.el-alert__title{font-size:13px;line-height:18px}.el-alert__title.is-bold{font-weight:700}.el-alert .el-alert__description{font-size:12px;margin:5px 0 0}.el-alert__closebtn{font-size:12px;opacity:1;position:absolute;top:12px;right:15px;cursor:pointer}.el-alert-fade-enter,.el-alert-fade-leave-active,.el-loading-fade-enter,.el-loading-fade-leave-active,.el-notification-fade-leave-active{opacity:0}.el-alert__closebtn.is-customed{font-style:normal;font-size:13px;top:9px}.el-notification{display:-webkit-box;display:-ms-flexbox;display:flex;width:330px;padding:14px 26px 14px 13px;border-radius:8px;-webkit-box-sizing:border-box;box-sizing:border-box;border:1px solid #EBEEF5;position:fixed;background-color:#FFF;-webkit-box-shadow:0 2px 12px 0 rgba(0,0,0,.1);box-shadow:0 2px 12px 0 rgba(0,0,0,.1);-webkit-transition:opacity .3s,left .3s,right .3s,top .4s,bottom .3s,-webkit-transform .3s;transition:opacity .3s,left .3s,right .3s,top .4s,bottom .3s,-webkit-transform .3s;transition:opacity .3s,transform .3s,left .3s,right .3s,top .4s,bottom .3s;transition:opacity .3s,transform .3s,left .3s,right .3s,top .4s,bottom .3s,-webkit-transform .3s;overflow:hidden}.el-notification.right{right:16px}.el-notification.left{left:16px}.el-notification__group{margin-left:13px;margin-right:8px}.el-notification__title{font-weight:700;font-size:16px;color:#303133;margin:0}.el-notification__content{font-size:14px;line-height:21px;margin:6px 0 0;color:#606266;text-align:justify}.el-notification__content p{margin:0}.el-notification__icon{height:24px;width:24px;font-size:24px}.el-notification__closeBtn{position:absolute;top:18px;right:15px;cursor:pointer;color:#909399;font-size:16px}.el-notification__closeBtn:hover{color:#606266}.el-notification .el-icon-success{color:#67C23A}.el-notification .el-icon-error{color:#F56C6C}.el-notification .el-icon-info{color:#909399}.el-notification .el-icon-warning{color:#E6A23C}.el-notification-fade-enter.right{right:0;-webkit-transform:translateX(100%);transform:translateX(100%)}.el-notification-fade-enter.left{left:0;-webkit-transform:translateX(-100%);transform:translateX(-100%)}.el-input-number{position:relative;display:inline-block;width:180px;line-height:38px}.el-input-number .el-input{display:block}.el-input-number .el-input__inner{-webkit-appearance:none;padding-left:50px;padding-right:50px;text-align:center}.el-input-number__decrease,.el-input-number__increase{position:absolute;z-index:1;top:1px;width:40px;height:auto;text-align:center;background:#F5F7FA;color:#606266;cursor:pointer;font-size:13px}.el-input-number__decrease:hover,.el-input-number__increase:hover{color:#FDA833}.el-input-number__decrease:hover:not(.is-disabled)~.el-input .el-input__inner:not(.is-disabled),.el-input-number__increase:hover:not(.is-disabled)~.el-input .el-input__inner:not(.is-disabled){border-color:#FDA833}.el-input-number__decrease.is-disabled,.el-input-number__increase.is-disabled{color:#C0C4CC;cursor:not-allowed}.el-input-number__increase{right:1px;border-radius:0 4px 4px 0;border-left:1px solid #DCDFE6}.el-input-number__decrease{left:1px;border-radius:4px 0 0 4px;border-right:1px solid #DCDFE6}.el-input-number.is-disabled .el-input-number__decrease,.el-input-number.is-disabled .el-input-number__increase{border-color:#E4E7ED;color:#E4E7ED}.el-input-number.is-disabled .el-input-number__decrease:hover,.el-input-number.is-disabled .el-input-number__increase:hover{color:#E4E7ED;cursor:not-allowed}.el-input-number--medium{width:200px;line-height:34px}.el-input-number--medium .el-input-number__decrease,.el-input-number--medium .el-input-number__increase{width:36px;font-size:14px}.el-input-number--medium .el-input__inner{padding-left:43px;padding-right:43px}.el-input-number--small{width:130px;line-height:30px}.el-input-number--small .el-input-number__decrease,.el-input-number--small .el-input-number__increase{width:32px;font-size:13px}.el-input-number--small .el-input-number__decrease [class*=el-icon],.el-input-number--small .el-input-number__increase [class*=el-icon]{-webkit-transform:scale(.9);transform:scale(.9)}.el-input-number--small .el-input__inner{padding-left:39px;padding-right:39px}.el-input-number--mini{width:130px;line-height:26px}.el-input-number--mini .el-input-number__decrease,.el-input-number--mini .el-input-number__increase{width:28px;font-size:12px}.el-input-number--mini .el-input-number__decrease [class*=el-icon],.el-input-number--mini .el-input-number__increase [class*=el-icon]{-webkit-transform:scale(.8);transform:scale(.8)}.el-input-number--mini .el-input__inner{padding-left:35px;padding-right:35px}.el-input-number.is-without-controls .el-input__inner{padding-left:15px;padding-right:15px}.el-input-number.is-controls-right .el-input__inner{padding-left:15px;padding-right:50px}.el-input-number.is-controls-right .el-input-number__decrease,.el-input-number.is-controls-right .el-input-number__increase{height:auto;line-height:19px}.el-input-number.is-controls-right .el-input-number__decrease [class*=el-icon],.el-input-number.is-controls-right .el-input-number__increase [class*=el-icon]{-webkit-transform:scale(.8);transform:scale(.8)}.el-input-number.is-controls-right .el-input-number__increase{border-radius:0 4px 0 0;border-bottom:1px solid #DCDFE6}.el-input-number.is-controls-right .el-input-number__decrease{right:1px;bottom:1px;top:auto;left:auto;border-right:none;border-left:1px solid #DCDFE6;border-radius:0 0 4px}.el-input-number.is-controls-right[class*=medium] [class*=decrease],.el-input-number.is-controls-right[class*=medium] [class*=increase]{line-height:17px}.el-input-number.is-controls-right[class*=small] [class*=decrease],.el-input-number.is-controls-right[class*=small] [class*=increase]{line-height:15px}.el-input-number.is-controls-right[class*=mini] [class*=decrease],.el-input-number.is-controls-right[class*=mini] [class*=increase]{line-height:13px}.el-tooltip__popper{position:absolute;border-radius:4px;padding:10px;z-index:2000;font-size:12px;line-height:1.2;min-width:10px;word-wrap:break-word}.el-tooltip__popper .popper__arrow,.el-tooltip__popper .popper__arrow::after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.el-tooltip__popper .popper__arrow{border-width:6px}.el-tooltip__popper .popper__arrow::after{content:" ";border-width:5px}.el-progress-bar__inner::after,.el-row::after,.el-row::before,.el-slider::after,.el-slider::before,.el-slider__button-wrapper::after,.el-upload-cover::after{content:""}.el-tooltip__popper[x-placement^=top]{margin-bottom:12px}.el-tooltip__popper[x-placement^=top] .popper__arrow{bottom:-6px;border-top-color:#303133;border-bottom-width:0}.el-tooltip__popper[x-placement^=top] .popper__arrow::after{bottom:1px;margin-left:-5px;border-top-color:#303133;border-bottom-width:0}.el-tooltip__popper[x-placement^=bottom]{margin-top:12px}.el-tooltip__popper[x-placement^=bottom] .popper__arrow{top:-6px;border-top-width:0;border-bottom-color:#303133}.el-tooltip__popper[x-placement^=bottom] .popper__arrow::after{top:1px;margin-left:-5px;border-top-width:0;border-bottom-color:#303133}.el-tooltip__popper[x-placement^=right]{margin-left:12px}.el-tooltip__popper[x-placement^=right] .popper__arrow{left:-6px;border-right-color:#303133;border-left-width:0}.el-tooltip__popper[x-placement^=right] .popper__arrow::after{bottom:-5px;left:1px;border-right-color:#303133;border-left-width:0}.el-tooltip__popper[x-placement^=left]{margin-right:12px}.el-tooltip__popper[x-placement^=left] .popper__arrow{right:-6px;border-right-width:0;border-left-color:#303133}.el-tooltip__popper[x-placement^=left] .popper__arrow::after{right:1px;bottom:-5px;margin-left:-5px;border-right-width:0;border-left-color:#303133}.el-tooltip__popper.is-dark{background:#303133;color:#FFF}.el-tooltip__popper.is-light{background:#FFF;border:1px solid #303133}.el-tooltip__popper.is-light[x-placement^=top] .popper__arrow{border-top-color:#303133}.el-tooltip__popper.is-light[x-placement^=top] .popper__arrow::after{border-top-color:#FFF}.el-tooltip__popper.is-light[x-placement^=bottom] .popper__arrow{border-bottom-color:#303133}.el-tooltip__popper.is-light[x-placement^=bottom] .popper__arrow::after{border-bottom-color:#FFF}.el-tooltip__popper.is-light[x-placement^=left] .popper__arrow{border-left-color:#303133}.el-tooltip__popper.is-light[x-placement^=left] .popper__arrow::after{border-left-color:#FFF}.el-tooltip__popper.is-light[x-placement^=right] .popper__arrow{border-right-color:#303133}.el-tooltip__popper.is-light[x-placement^=right] .popper__arrow::after{border-right-color:#FFF}.el-slider::after,.el-slider::before{display:table}.el-slider__button-wrapper .el-tooltip,.el-slider__button-wrapper::after{vertical-align:middle;display:inline-block}.el-slider::after{clear:both}.el-slider__runway{width:100%;height:6px;margin:16px 0;background-color:#E4E7ED;border-radius:3px;position:relative;cursor:pointer;vertical-align:middle}.el-slider__runway.show-input{margin-right:160px;width:auto}.el-slider__runway.disabled{cursor:default}.el-slider__runway.disabled .el-slider__bar{background-color:#C0C4CC}.el-slider__runway.disabled .el-slider__button{border-color:#C0C4CC}.el-slider__runway.disabled .el-slider__button-wrapper.dragging,.el-slider__runway.disabled .el-slider__button-wrapper.hover,.el-slider__runway.disabled .el-slider__button-wrapper:hover{cursor:not-allowed}.el-slider__runway.disabled .el-slider__button.dragging,.el-slider__runway.disabled .el-slider__button.hover,.el-slider__runway.disabled .el-slider__button:hover{-webkit-transform:scale(1);transform:scale(1);cursor:not-allowed}.el-slider__button-wrapper,.el-slider__stop{-webkit-transform:translateX(-50%);position:absolute}.el-slider__input{float:right;margin-top:3px;width:130px}.el-slider__input.el-input-number--mini{margin-top:5px}.el-slider__input.el-input-number--medium{margin-top:0}.el-slider__input.el-input-number--large{margin-top:-2px}.el-slider__bar{height:6px;background-color:#FDA833;border-top-left-radius:3px;border-bottom-left-radius:3px;position:absolute}.el-slider__button-wrapper{height:36px;width:36px;z-index:1001;top:-15px;transform:translateX(-50%);background-color:transparent;text-align:center;user-select:none;line-height:normal}.el-slider__button-wrapper::after{height:100%}.el-slider__button-wrapper.hover,.el-slider__button-wrapper:hover{cursor:-webkit-grab;cursor:grab}.el-slider__button-wrapper.dragging{cursor:-webkit-grabbing;cursor:grabbing}.el-slider__button{width:16px;height:16px;border:2px solid #FDA833;background-color:#FFF;border-radius:50%;-webkit-transition:.2s;transition:.2s;user-select:none}.el-image-viewer__btn,.el-step__icon-inner{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}.el-slider__button.dragging,.el-slider__button.hover,.el-slider__button:hover{-webkit-transform:scale(1.2);transform:scale(1.2)}.el-slider__button.hover,.el-slider__button:hover{cursor:-webkit-grab;cursor:grab}.el-slider__button.dragging{cursor:-webkit-grabbing;cursor:grabbing}.el-slider__stop{height:6px;width:6px;border-radius:100%;background-color:#FFF;transform:translateX(-50%)}.el-slider__marks{top:0;left:12px;width:18px;height:100%}.el-slider__marks-text{position:absolute;-webkit-transform:translateX(-50%);transform:translateX(-50%);font-size:14px;color:#909399;margin-top:15px}.el-slider.is-vertical{position:relative}.el-slider.is-vertical .el-slider__runway{width:6px;height:100%;margin:0 16px}.el-slider.is-vertical .el-slider__bar{width:6px;height:auto;border-radius:0 0 3px 3px}.el-slider.is-vertical .el-slider__button-wrapper{top:auto;left:-15px;-webkit-transform:translateY(50%);transform:translateY(50%)}.el-slider.is-vertical .el-slider__stop{-webkit-transform:translateY(50%);transform:translateY(50%)}.el-slider.is-vertical.el-slider--with-input{padding-bottom:58px}.el-slider.is-vertical.el-slider--with-input .el-slider__input{overflow:visible;float:none;position:absolute;bottom:22px;width:36px;margin-top:15px}.el-slider.is-vertical.el-slider--with-input .el-slider__input .el-input__inner{text-align:center;padding-left:5px;padding-right:5px}.el-slider.is-vertical.el-slider--with-input .el-slider__input .el-input-number__decrease,.el-slider.is-vertical.el-slider--with-input .el-slider__input .el-input-number__increase{top:32px;margin-top:-1px;border:1px solid #DCDFE6;line-height:20px;-webkit-box-sizing:border-box;box-sizing:border-box;-webkit-transition:border-color .2s cubic-bezier(.645,.045,.355,1);transition:border-color .2s cubic-bezier(.645,.045,.355,1)}.el-slider.is-vertical.el-slider--with-input .el-slider__input .el-input-number__decrease{width:18px;right:18px;border-bottom-left-radius:4px}.el-slider.is-vertical.el-slider--with-input .el-slider__input .el-input-number__increase{width:19px;border-bottom-right-radius:4px}.el-slider.is-vertical.el-slider--with-input .el-slider__input .el-input-number__increase~.el-input .el-input__inner{border-bottom-left-radius:0;border-bottom-right-radius:0}.el-slider.is-vertical.el-slider--with-input .el-slider__input:hover .el-input-number__decrease,.el-slider.is-vertical.el-slider--with-input .el-slider__input:hover .el-input-number__increase{border-color:#C0C4CC}.el-slider.is-vertical.el-slider--with-input .el-slider__input:active .el-input-number__decrease,.el-slider.is-vertical.el-slider--with-input .el-slider__input:active .el-input-number__increase{border-color:#FDA833}.el-slider.is-vertical .el-slider__marks-text{margin-top:0;left:15px;-webkit-transform:translateY(50%);transform:translateY(50%)}.el-loading-parent--relative{position:relative!important}.el-loading-parent--hidden{overflow:hidden!important}.el-loading-mask{position:absolute;z-index:2000;background-color:rgba(255,255,255,.9);margin:0;top:0;right:0;bottom:0;left:0;-webkit-transition:opacity .3s;transition:opacity .3s}.el-loading-mask.is-fullscreen{position:fixed}.el-loading-mask.is-fullscreen .el-loading-spinner{margin-top:-25px}.el-loading-mask.is-fullscreen .el-loading-spinner .circular{height:50px;width:50px}.el-loading-spinner{top:50%;margin-top:-21px;width:100%;text-align:center;position:absolute}.el-col-pull-0,.el-col-pull-1,.el-col-pull-10,.el-col-pull-11,.el-col-pull-13,.el-col-pull-14,.el-col-pull-15,.el-col-pull-16,.el-col-pull-17,.el-col-pull-18,.el-col-pull-19,.el-col-pull-2,.el-col-pull-20,.el-col-pull-21,.el-col-pull-22,.el-col-pull-23,.el-col-pull-24,.el-col-pull-3,.el-col-pull-4,.el-col-pull-5,.el-col-pull-6,.el-col-pull-7,.el-col-pull-8,.el-col-pull-9,.el-col-push-0,.el-col-push-1,.el-col-push-10,.el-col-push-11,.el-col-push-12,.el-col-push-13,.el-col-push-14,.el-col-push-15,.el-col-push-16,.el-col-push-17,.el-col-push-18,.el-col-push-19,.el-col-push-2,.el-col-push-20,.el-col-push-21,.el-col-push-22,.el-col-push-23,.el-col-push-24,.el-col-push-3,.el-col-push-4,.el-col-push-5,.el-col-push-6,.el-col-push-7,.el-col-push-8,.el-col-push-9,.el-row{position:relative}.el-loading-spinner .el-loading-text{color:#FDA833;margin:3px 0;font-size:14px}.el-loading-spinner .circular{height:42px;width:42px;-webkit-animation:loading-rotate 2s linear infinite;animation:loading-rotate 2s linear infinite}.el-loading-spinner .path{-webkit-animation:loading-dash 1.5s ease-in-out infinite;animation:loading-dash 1.5s ease-in-out infinite;stroke-dasharray:90,150;stroke-dashoffset:0;stroke-width:2;stroke:#FDA833;stroke-linecap:round}.el-loading-spinner i{color:#FDA833}@-webkit-keyframes loading-rotate{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes loading-rotate{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@-webkit-keyframes loading-dash{0%{stroke-dasharray:1,200;stroke-dashoffset:0}50%{stroke-dasharray:90,150;stroke-dashoffset:-40px}100%{stroke-dasharray:90,150;stroke-dashoffset:-120px}}@keyframes loading-dash{0%{stroke-dasharray:1,200;stroke-dashoffset:0}50%{stroke-dasharray:90,150;stroke-dashoffset:-40px}100%{stroke-dasharray:90,150;stroke-dashoffset:-120px}}.el-row{-webkit-box-sizing:border-box;box-sizing:border-box}.el-row::after,.el-row::before{display:table}.el-row::after{clear:both}.el-row--flex{display:-webkit-box;display:-ms-flexbox;display:flex}.el-col-0,.el-row--flex:after,.el-row--flex:before{display:none}.el-row--flex.is-justify-center{-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.el-row--flex.is-justify-end{-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end}.el-row--flex.is-justify-space-between{-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.el-row--flex.is-justify-space-around{-ms-flex-pack:distribute;justify-content:space-around}.el-row--flex.is-align-middle{-webkit-box-align:center;-ms-flex-align:center;align-items:center}.el-row--flex.is-align-bottom{-webkit-box-align:end;-ms-flex-align:end;align-items:flex-end}[class*=el-col-]{float:left;-webkit-box-sizing:border-box;box-sizing:border-box}.el-upload--picture-card,.el-upload-dragger{-webkit-box-sizing:border-box;cursor:pointer}.el-col-0{width:0%}.el-col-offset-0{margin-left:0}.el-col-pull-0{right:0}.el-col-push-0{left:0}.el-col-1{width:4.16667%}.el-col-offset-1{margin-left:4.16667%}.el-col-pull-1{right:4.16667%}.el-col-push-1{left:4.16667%}.el-col-2{width:8.33333%}.el-col-offset-2{margin-left:8.33333%}.el-col-pull-2{right:8.33333%}.el-col-push-2{left:8.33333%}.el-col-3{width:12.5%}.el-col-offset-3{margin-left:12.5%}.el-col-pull-3{right:12.5%}.el-col-push-3{left:12.5%}.el-col-4{width:16.66667%}.el-col-offset-4{margin-left:16.66667%}.el-col-pull-4{right:16.66667%}.el-col-push-4{left:16.66667%}.el-col-5{width:20.83333%}.el-col-offset-5{margin-left:20.83333%}.el-col-pull-5{right:20.83333%}.el-col-push-5{left:20.83333%}.el-col-6{width:25%}.el-col-offset-6{margin-left:25%}.el-col-pull-6{right:25%}.el-col-push-6{left:25%}.el-col-7{width:29.16667%}.el-col-offset-7{margin-left:29.16667%}.el-col-pull-7{right:29.16667%}.el-col-push-7{left:29.16667%}.el-col-8{width:33.33333%}.el-col-offset-8{margin-left:33.33333%}.el-col-pull-8{right:33.33333%}.el-col-push-8{left:33.33333%}.el-col-9{width:37.5%}.el-col-offset-9{margin-left:37.5%}.el-col-pull-9{right:37.5%}.el-col-push-9{left:37.5%}.el-col-10{width:41.66667%}.el-col-offset-10{margin-left:41.66667%}.el-col-pull-10{right:41.66667%}.el-col-push-10{left:41.66667%}.el-col-11{width:45.83333%}.el-col-offset-11{margin-left:45.83333%}.el-col-pull-11{right:45.83333%}.el-col-push-11{left:45.83333%}.el-col-12{width:50%}.el-col-offset-12{margin-left:50%}.el-col-pull-12{position:relative;right:50%}.el-col-push-12{left:50%}.el-col-13{width:54.16667%}.el-col-offset-13{margin-left:54.16667%}.el-col-pull-13{right:54.16667%}.el-col-push-13{left:54.16667%}.el-col-14{width:58.33333%}.el-col-offset-14{margin-left:58.33333%}.el-col-pull-14{right:58.33333%}.el-col-push-14{left:58.33333%}.el-col-15{width:62.5%}.el-col-offset-15{margin-left:62.5%}.el-col-pull-15{right:62.5%}.el-col-push-15{left:62.5%}.el-col-16{width:66.66667%}.el-col-offset-16{margin-left:66.66667%}.el-col-pull-16{right:66.66667%}.el-col-push-16{left:66.66667%}.el-col-17{width:70.83333%}.el-col-offset-17{margin-left:70.83333%}.el-col-pull-17{right:70.83333%}.el-col-push-17{left:70.83333%}.el-col-18{width:75%}.el-col-offset-18{margin-left:75%}.el-col-pull-18{right:75%}.el-col-push-18{left:75%}.el-col-19{width:79.16667%}.el-col-offset-19{margin-left:79.16667%}.el-col-pull-19{right:79.16667%}.el-col-push-19{left:79.16667%}.el-col-20{width:83.33333%}.el-col-offset-20{margin-left:83.33333%}.el-col-pull-20{right:83.33333%}.el-col-push-20{left:83.33333%}.el-col-21{width:87.5%}.el-col-offset-21{margin-left:87.5%}.el-col-pull-21{right:87.5%}.el-col-push-21{left:87.5%}.el-col-22{width:91.66667%}.el-col-offset-22{margin-left:91.66667%}.el-col-pull-22{right:91.66667%}.el-col-push-22{left:91.66667%}.el-col-23{width:95.83333%}.el-col-offset-23{margin-left:95.83333%}.el-col-pull-23{right:95.83333%}.el-col-push-23{left:95.83333%}.el-col-24{width:100%}.el-col-offset-24{margin-left:100%}.el-col-pull-24{right:100%}.el-col-push-24{left:100%}@media only screen and (max-width:767px){.el-col-xs-0{display:none;width:0%}.el-col-xs-offset-0{margin-left:0}.el-col-xs-pull-0{position:relative;right:0}.el-col-xs-push-0{position:relative;left:0}.el-col-xs-1{width:4.16667%}.el-col-xs-offset-1{margin-left:4.16667%}.el-col-xs-pull-1{position:relative;right:4.16667%}.el-col-xs-push-1{position:relative;left:4.16667%}.el-col-xs-2{width:8.33333%}.el-col-xs-offset-2{margin-left:8.33333%}.el-col-xs-pull-2{position:relative;right:8.33333%}.el-col-xs-push-2{position:relative;left:8.33333%}.el-col-xs-3{width:12.5%}.el-col-xs-offset-3{margin-left:12.5%}.el-col-xs-pull-3{position:relative;right:12.5%}.el-col-xs-push-3{position:relative;left:12.5%}.el-col-xs-4{width:16.66667%}.el-col-xs-offset-4{margin-left:16.66667%}.el-col-xs-pull-4{position:relative;right:16.66667%}.el-col-xs-push-4{position:relative;left:16.66667%}.el-col-xs-5{width:20.83333%}.el-col-xs-offset-5{margin-left:20.83333%}.el-col-xs-pull-5{position:relative;right:20.83333%}.el-col-xs-push-5{position:relative;left:20.83333%}.el-col-xs-6{width:25%}.el-col-xs-offset-6{margin-left:25%}.el-col-xs-pull-6{position:relative;right:25%}.el-col-xs-push-6{position:relative;left:25%}.el-col-xs-7{width:29.16667%}.el-col-xs-offset-7{margin-left:29.16667%}.el-col-xs-pull-7{position:relative;right:29.16667%}.el-col-xs-push-7{position:relative;left:29.16667%}.el-col-xs-8{width:33.33333%}.el-col-xs-offset-8{margin-left:33.33333%}.el-col-xs-pull-8{position:relative;right:33.33333%}.el-col-xs-push-8{position:relative;left:33.33333%}.el-col-xs-9{width:37.5%}.el-col-xs-offset-9{margin-left:37.5%}.el-col-xs-pull-9{position:relative;right:37.5%}.el-col-xs-push-9{position:relative;left:37.5%}.el-col-xs-10{width:41.66667%}.el-col-xs-offset-10{margin-left:41.66667%}.el-col-xs-pull-10{position:relative;right:41.66667%}.el-col-xs-push-10{position:relative;left:41.66667%}.el-col-xs-11{width:45.83333%}.el-col-xs-offset-11{margin-left:45.83333%}.el-col-xs-pull-11{position:relative;right:45.83333%}.el-col-xs-push-11{position:relative;left:45.83333%}.el-col-xs-12{width:50%}.el-col-xs-offset-12{margin-left:50%}.el-col-xs-pull-12{position:relative;right:50%}.el-col-xs-push-12{position:relative;left:50%}.el-col-xs-13{width:54.16667%}.el-col-xs-offset-13{margin-left:54.16667%}.el-col-xs-pull-13{position:relative;right:54.16667%}.el-col-xs-push-13{position:relative;left:54.16667%}.el-col-xs-14{width:58.33333%}.el-col-xs-offset-14{margin-left:58.33333%}.el-col-xs-pull-14{position:relative;right:58.33333%}.el-col-xs-push-14{position:relative;left:58.33333%}.el-col-xs-15{width:62.5%}.el-col-xs-offset-15{margin-left:62.5%}.el-col-xs-pull-15{position:relative;right:62.5%}.el-col-xs-push-15{position:relative;left:62.5%}.el-col-xs-16{width:66.66667%}.el-col-xs-offset-16{margin-left:66.66667%}.el-col-xs-pull-16{position:relative;right:66.66667%}.el-col-xs-push-16{position:relative;left:66.66667%}.el-col-xs-17{width:70.83333%}.el-col-xs-offset-17{margin-left:70.83333%}.el-col-xs-pull-17{position:relative;right:70.83333%}.el-col-xs-push-17{position:relative;left:70.83333%}.el-col-xs-18{width:75%}.el-col-xs-offset-18{margin-left:75%}.el-col-xs-pull-18{position:relative;right:75%}.el-col-xs-push-18{position:relative;left:75%}.el-col-xs-19{width:79.16667%}.el-col-xs-offset-19{margin-left:79.16667%}.el-col-xs-pull-19{position:relative;right:79.16667%}.el-col-xs-push-19{position:relative;left:79.16667%}.el-col-xs-20{width:83.33333%}.el-col-xs-offset-20{margin-left:83.33333%}.el-col-xs-pull-20{position:relative;right:83.33333%}.el-col-xs-push-20{position:relative;left:83.33333%}.el-col-xs-21{width:87.5%}.el-col-xs-offset-21{margin-left:87.5%}.el-col-xs-pull-21{position:relative;right:87.5%}.el-col-xs-push-21{position:relative;left:87.5%}.el-col-xs-22{width:91.66667%}.el-col-xs-offset-22{margin-left:91.66667%}.el-col-xs-pull-22{position:relative;right:91.66667%}.el-col-xs-push-22{position:relative;left:91.66667%}.el-col-xs-23{width:95.83333%}.el-col-xs-offset-23{margin-left:95.83333%}.el-col-xs-pull-23{position:relative;right:95.83333%}.el-col-xs-push-23{position:relative;left:95.83333%}.el-col-xs-24{width:100%}.el-col-xs-offset-24{margin-left:100%}.el-col-xs-pull-24{position:relative;right:100%}.el-col-xs-push-24{position:relative;left:100%}}@media only screen and (min-width:768px){.el-col-sm-0{display:none;width:0%}.el-col-sm-offset-0{margin-left:0}.el-col-sm-pull-0{position:relative;right:0}.el-col-sm-push-0{position:relative;left:0}.el-col-sm-1{width:4.16667%}.el-col-sm-offset-1{margin-left:4.16667%}.el-col-sm-pull-1{position:relative;right:4.16667%}.el-col-sm-push-1{position:relative;left:4.16667%}.el-col-sm-2{width:8.33333%}.el-col-sm-offset-2{margin-left:8.33333%}.el-col-sm-pull-2{position:relative;right:8.33333%}.el-col-sm-push-2{position:relative;left:8.33333%}.el-col-sm-3{width:12.5%}.el-col-sm-offset-3{margin-left:12.5%}.el-col-sm-pull-3{position:relative;right:12.5%}.el-col-sm-push-3{position:relative;left:12.5%}.el-col-sm-4{width:16.66667%}.el-col-sm-offset-4{margin-left:16.66667%}.el-col-sm-pull-4{position:relative;right:16.66667%}.el-col-sm-push-4{position:relative;left:16.66667%}.el-col-sm-5{width:20.83333%}.el-col-sm-offset-5{margin-left:20.83333%}.el-col-sm-pull-5{position:relative;right:20.83333%}.el-col-sm-push-5{position:relative;left:20.83333%}.el-col-sm-6{width:25%}.el-col-sm-offset-6{margin-left:25%}.el-col-sm-pull-6{position:relative;right:25%}.el-col-sm-push-6{position:relative;left:25%}.el-col-sm-7{width:29.16667%}.el-col-sm-offset-7{margin-left:29.16667%}.el-col-sm-pull-7{position:relative;right:29.16667%}.el-col-sm-push-7{position:relative;left:29.16667%}.el-col-sm-8{width:33.33333%}.el-col-sm-offset-8{margin-left:33.33333%}.el-col-sm-pull-8{position:relative;right:33.33333%}.el-col-sm-push-8{position:relative;left:33.33333%}.el-col-sm-9{width:37.5%}.el-col-sm-offset-9{margin-left:37.5%}.el-col-sm-pull-9{position:relative;right:37.5%}.el-col-sm-push-9{position:relative;left:37.5%}.el-col-sm-10{width:41.66667%}.el-col-sm-offset-10{margin-left:41.66667%}.el-col-sm-pull-10{position:relative;right:41.66667%}.el-col-sm-push-10{position:relative;left:41.66667%}.el-col-sm-11{width:45.83333%}.el-col-sm-offset-11{margin-left:45.83333%}.el-col-sm-pull-11{position:relative;right:45.83333%}.el-col-sm-push-11{position:relative;left:45.83333%}.el-col-sm-12{width:50%}.el-col-sm-offset-12{margin-left:50%}.el-col-sm-pull-12{position:relative;right:50%}.el-col-sm-push-12{position:relative;left:50%}.el-col-sm-13{width:54.16667%}.el-col-sm-offset-13{margin-left:54.16667%}.el-col-sm-pull-13{position:relative;right:54.16667%}.el-col-sm-push-13{position:relative;left:54.16667%}.el-col-sm-14{width:58.33333%}.el-col-sm-offset-14{margin-left:58.33333%}.el-col-sm-pull-14{position:relative;right:58.33333%}.el-col-sm-push-14{position:relative;left:58.33333%}.el-col-sm-15{width:62.5%}.el-col-sm-offset-15{margin-left:62.5%}.el-col-sm-pull-15{position:relative;right:62.5%}.el-col-sm-push-15{position:relative;left:62.5%}.el-col-sm-16{width:66.66667%}.el-col-sm-offset-16{margin-left:66.66667%}.el-col-sm-pull-16{position:relative;right:66.66667%}.el-col-sm-push-16{position:relative;left:66.66667%}.el-col-sm-17{width:70.83333%}.el-col-sm-offset-17{margin-left:70.83333%}.el-col-sm-pull-17{position:relative;right:70.83333%}.el-col-sm-push-17{position:relative;left:70.83333%}.el-col-sm-18{width:75%}.el-col-sm-offset-18{margin-left:75%}.el-col-sm-pull-18{position:relative;right:75%}.el-col-sm-push-18{position:relative;left:75%}.el-col-sm-19{width:79.16667%}.el-col-sm-offset-19{margin-left:79.16667%}.el-col-sm-pull-19{position:relative;right:79.16667%}.el-col-sm-push-19{position:relative;left:79.16667%}.el-col-sm-20{width:83.33333%}.el-col-sm-offset-20{margin-left:83.33333%}.el-col-sm-pull-20{position:relative;right:83.33333%}.el-col-sm-push-20{position:relative;left:83.33333%}.el-col-sm-21{width:87.5%}.el-col-sm-offset-21{margin-left:87.5%}.el-col-sm-pull-21{position:relative;right:87.5%}.el-col-sm-push-21{position:relative;left:87.5%}.el-col-sm-22{width:91.66667%}.el-col-sm-offset-22{margin-left:91.66667%}.el-col-sm-pull-22{position:relative;right:91.66667%}.el-col-sm-push-22{position:relative;left:91.66667%}.el-col-sm-23{width:95.83333%}.el-col-sm-offset-23{margin-left:95.83333%}.el-col-sm-pull-23{position:relative;right:95.83333%}.el-col-sm-push-23{position:relative;left:95.83333%}.el-col-sm-24{width:100%}.el-col-sm-offset-24{margin-left:100%}.el-col-sm-pull-24{position:relative;right:100%}.el-col-sm-push-24{position:relative;left:100%}}@media only screen and (min-width:992px){.el-col-md-0{display:none;width:0%}.el-col-md-offset-0{margin-left:0}.el-col-md-pull-0{position:relative;right:0}.el-col-md-push-0{position:relative;left:0}.el-col-md-1{width:4.16667%}.el-col-md-offset-1{margin-left:4.16667%}.el-col-md-pull-1{position:relative;right:4.16667%}.el-col-md-push-1{position:relative;left:4.16667%}.el-col-md-2{width:8.33333%}.el-col-md-offset-2{margin-left:8.33333%}.el-col-md-pull-2{position:relative;right:8.33333%}.el-col-md-push-2{position:relative;left:8.33333%}.el-col-md-3{width:12.5%}.el-col-md-offset-3{margin-left:12.5%}.el-col-md-pull-3{position:relative;right:12.5%}.el-col-md-push-3{position:relative;left:12.5%}.el-col-md-4{width:16.66667%}.el-col-md-offset-4{margin-left:16.66667%}.el-col-md-pull-4{position:relative;right:16.66667%}.el-col-md-push-4{position:relative;left:16.66667%}.el-col-md-5{width:20.83333%}.el-col-md-offset-5{margin-left:20.83333%}.el-col-md-pull-5{position:relative;right:20.83333%}.el-col-md-push-5{position:relative;left:20.83333%}.el-col-md-6{width:25%}.el-col-md-offset-6{margin-left:25%}.el-col-md-pull-6{position:relative;right:25%}.el-col-md-push-6{position:relative;left:25%}.el-col-md-7{width:29.16667%}.el-col-md-offset-7{margin-left:29.16667%}.el-col-md-pull-7{position:relative;right:29.16667%}.el-col-md-push-7{position:relative;left:29.16667%}.el-col-md-8{width:33.33333%}.el-col-md-offset-8{margin-left:33.33333%}.el-col-md-pull-8{position:relative;right:33.33333%}.el-col-md-push-8{position:relative;left:33.33333%}.el-col-md-9{width:37.5%}.el-col-md-offset-9{margin-left:37.5%}.el-col-md-pull-9{position:relative;right:37.5%}.el-col-md-push-9{position:relative;left:37.5%}.el-col-md-10{width:41.66667%}.el-col-md-offset-10{margin-left:41.66667%}.el-col-md-pull-10{position:relative;right:41.66667%}.el-col-md-push-10{position:relative;left:41.66667%}.el-col-md-11{width:45.83333%}.el-col-md-offset-11{margin-left:45.83333%}.el-col-md-pull-11{position:relative;right:45.83333%}.el-col-md-push-11{position:relative;left:45.83333%}.el-col-md-12{width:50%}.el-col-md-offset-12{margin-left:50%}.el-col-md-pull-12{position:relative;right:50%}.el-col-md-push-12{position:relative;left:50%}.el-col-md-13{width:54.16667%}.el-col-md-offset-13{margin-left:54.16667%}.el-col-md-pull-13{position:relative;right:54.16667%}.el-col-md-push-13{position:relative;left:54.16667%}.el-col-md-14{width:58.33333%}.el-col-md-offset-14{margin-left:58.33333%}.el-col-md-pull-14{position:relative;right:58.33333%}.el-col-md-push-14{position:relative;left:58.33333%}.el-col-md-15{width:62.5%}.el-col-md-offset-15{margin-left:62.5%}.el-col-md-pull-15{position:relative;right:62.5%}.el-col-md-push-15{position:relative;left:62.5%}.el-col-md-16{width:66.66667%}.el-col-md-offset-16{margin-left:66.66667%}.el-col-md-pull-16{position:relative;right:66.66667%}.el-col-md-push-16{position:relative;left:66.66667%}.el-col-md-17{width:70.83333%}.el-col-md-offset-17{margin-left:70.83333%}.el-col-md-pull-17{position:relative;right:70.83333%}.el-col-md-push-17{position:relative;left:70.83333%}.el-col-md-18{width:75%}.el-col-md-offset-18{margin-left:75%}.el-col-md-pull-18{position:relative;right:75%}.el-col-md-push-18{position:relative;left:75%}.el-col-md-19{width:79.16667%}.el-col-md-offset-19{margin-left:79.16667%}.el-col-md-pull-19{position:relative;right:79.16667%}.el-col-md-push-19{position:relative;left:79.16667%}.el-col-md-20{width:83.33333%}.el-col-md-offset-20{margin-left:83.33333%}.el-col-md-pull-20{position:relative;right:83.33333%}.el-col-md-push-20{position:relative;left:83.33333%}.el-col-md-21{width:87.5%}.el-col-md-offset-21{margin-left:87.5%}.el-col-md-pull-21{position:relative;right:87.5%}.el-col-md-push-21{position:relative;left:87.5%}.el-col-md-22{width:91.66667%}.el-col-md-offset-22{margin-left:91.66667%}.el-col-md-pull-22{position:relative;right:91.66667%}.el-col-md-push-22{position:relative;left:91.66667%}.el-col-md-23{width:95.83333%}.el-col-md-offset-23{margin-left:95.83333%}.el-col-md-pull-23{position:relative;right:95.83333%}.el-col-md-push-23{position:relative;left:95.83333%}.el-col-md-24{width:100%}.el-col-md-offset-24{margin-left:100%}.el-col-md-pull-24{position:relative;right:100%}.el-col-md-push-24{position:relative;left:100%}}@media only screen and (min-width:1200px){.el-col-lg-0{display:none;width:0%}.el-col-lg-offset-0{margin-left:0}.el-col-lg-pull-0{position:relative;right:0}.el-col-lg-push-0{position:relative;left:0}.el-col-lg-1{width:4.16667%}.el-col-lg-offset-1{margin-left:4.16667%}.el-col-lg-pull-1{position:relative;right:4.16667%}.el-col-lg-push-1{position:relative;left:4.16667%}.el-col-lg-2{width:8.33333%}.el-col-lg-offset-2{margin-left:8.33333%}.el-col-lg-pull-2{position:relative;right:8.33333%}.el-col-lg-push-2{position:relative;left:8.33333%}.el-col-lg-3{width:12.5%}.el-col-lg-offset-3{margin-left:12.5%}.el-col-lg-pull-3{position:relative;right:12.5%}.el-col-lg-push-3{position:relative;left:12.5%}.el-col-lg-4{width:16.66667%}.el-col-lg-offset-4{margin-left:16.66667%}.el-col-lg-pull-4{position:relative;right:16.66667%}.el-col-lg-push-4{position:relative;left:16.66667%}.el-col-lg-5{width:20.83333%}.el-col-lg-offset-5{margin-left:20.83333%}.el-col-lg-pull-5{position:relative;right:20.83333%}.el-col-lg-push-5{position:relative;left:20.83333%}.el-col-lg-6{width:25%}.el-col-lg-offset-6{margin-left:25%}.el-col-lg-pull-6{position:relative;right:25%}.el-col-lg-push-6{position:relative;left:25%}.el-col-lg-7{width:29.16667%}.el-col-lg-offset-7{margin-left:29.16667%}.el-col-lg-pull-7{position:relative;right:29.16667%}.el-col-lg-push-7{position:relative;left:29.16667%}.el-col-lg-8{width:33.33333%}.el-col-lg-offset-8{margin-left:33.33333%}.el-col-lg-pull-8{position:relative;right:33.33333%}.el-col-lg-push-8{position:relative;left:33.33333%}.el-col-lg-9{width:37.5%}.el-col-lg-offset-9{margin-left:37.5%}.el-col-lg-pull-9{position:relative;right:37.5%}.el-col-lg-push-9{position:relative;left:37.5%}.el-col-lg-10{width:41.66667%}.el-col-lg-offset-10{margin-left:41.66667%}.el-col-lg-pull-10{position:relative;right:41.66667%}.el-col-lg-push-10{position:relative;left:41.66667%}.el-col-lg-11{width:45.83333%}.el-col-lg-offset-11{margin-left:45.83333%}.el-col-lg-pull-11{position:relative;right:45.83333%}.el-col-lg-push-11{position:relative;left:45.83333%}.el-col-lg-12{width:50%}.el-col-lg-offset-12{margin-left:50%}.el-col-lg-pull-12{position:relative;right:50%}.el-col-lg-push-12{position:relative;left:50%}.el-col-lg-13{width:54.16667%}.el-col-lg-offset-13{margin-left:54.16667%}.el-col-lg-pull-13{position:relative;right:54.16667%}.el-col-lg-push-13{position:relative;left:54.16667%}.el-col-lg-14{width:58.33333%}.el-col-lg-offset-14{margin-left:58.33333%}.el-col-lg-pull-14{position:relative;right:58.33333%}.el-col-lg-push-14{position:relative;left:58.33333%}.el-col-lg-15{width:62.5%}.el-col-lg-offset-15{margin-left:62.5%}.el-col-lg-pull-15{position:relative;right:62.5%}.el-col-lg-push-15{position:relative;left:62.5%}.el-col-lg-16{width:66.66667%}.el-col-lg-offset-16{margin-left:66.66667%}.el-col-lg-pull-16{position:relative;right:66.66667%}.el-col-lg-push-16{position:relative;left:66.66667%}.el-col-lg-17{width:70.83333%}.el-col-lg-offset-17{margin-left:70.83333%}.el-col-lg-pull-17{position:relative;right:70.83333%}.el-col-lg-push-17{position:relative;left:70.83333%}.el-col-lg-18{width:75%}.el-col-lg-offset-18{margin-left:75%}.el-col-lg-pull-18{position:relative;right:75%}.el-col-lg-push-18{position:relative;left:75%}.el-col-lg-19{width:79.16667%}.el-col-lg-offset-19{margin-left:79.16667%}.el-col-lg-pull-19{position:relative;right:79.16667%}.el-col-lg-push-19{position:relative;left:79.16667%}.el-col-lg-20{width:83.33333%}.el-col-lg-offset-20{margin-left:83.33333%}.el-col-lg-pull-20{position:relative;right:83.33333%}.el-col-lg-push-20{position:relative;left:83.33333%}.el-col-lg-21{width:87.5%}.el-col-lg-offset-21{margin-left:87.5%}.el-col-lg-pull-21{position:relative;right:87.5%}.el-col-lg-push-21{position:relative;left:87.5%}.el-col-lg-22{width:91.66667%}.el-col-lg-offset-22{margin-left:91.66667%}.el-col-lg-pull-22{position:relative;right:91.66667%}.el-col-lg-push-22{position:relative;left:91.66667%}.el-col-lg-23{width:95.83333%}.el-col-lg-offset-23{margin-left:95.83333%}.el-col-lg-pull-23{position:relative;right:95.83333%}.el-col-lg-push-23{position:relative;left:95.83333%}.el-col-lg-24{width:100%}.el-col-lg-offset-24{margin-left:100%}.el-col-lg-pull-24{position:relative;right:100%}.el-col-lg-push-24{position:relative;left:100%}}@media only screen and (min-width:1920px){.el-col-xl-0{display:none;width:0%}.el-col-xl-offset-0{margin-left:0}.el-col-xl-pull-0{position:relative;right:0}.el-col-xl-push-0{position:relative;left:0}.el-col-xl-1{width:4.16667%}.el-col-xl-offset-1{margin-left:4.16667%}.el-col-xl-pull-1{position:relative;right:4.16667%}.el-col-xl-push-1{position:relative;left:4.16667%}.el-col-xl-2{width:8.33333%}.el-col-xl-offset-2{margin-left:8.33333%}.el-col-xl-pull-2{position:relative;right:8.33333%}.el-col-xl-push-2{position:relative;left:8.33333%}.el-col-xl-3{width:12.5%}.el-col-xl-offset-3{margin-left:12.5%}.el-col-xl-pull-3{position:relative;right:12.5%}.el-col-xl-push-3{position:relative;left:12.5%}.el-col-xl-4{width:16.66667%}.el-col-xl-offset-4{margin-left:16.66667%}.el-col-xl-pull-4{position:relative;right:16.66667%}.el-col-xl-push-4{position:relative;left:16.66667%}.el-col-xl-5{width:20.83333%}.el-col-xl-offset-5{margin-left:20.83333%}.el-col-xl-pull-5{position:relative;right:20.83333%}.el-col-xl-push-5{position:relative;left:20.83333%}.el-col-xl-6{width:25%}.el-col-xl-offset-6{margin-left:25%}.el-col-xl-pull-6{position:relative;right:25%}.el-col-xl-push-6{position:relative;left:25%}.el-col-xl-7{width:29.16667%}.el-col-xl-offset-7{margin-left:29.16667%}.el-col-xl-pull-7{position:relative;right:29.16667%}.el-col-xl-push-7{position:relative;left:29.16667%}.el-col-xl-8{width:33.33333%}.el-col-xl-offset-8{margin-left:33.33333%}.el-col-xl-pull-8{position:relative;right:33.33333%}.el-col-xl-push-8{position:relative;left:33.33333%}.el-col-xl-9{width:37.5%}.el-col-xl-offset-9{margin-left:37.5%}.el-col-xl-pull-9{position:relative;right:37.5%}.el-col-xl-push-9{position:relative;left:37.5%}.el-col-xl-10{width:41.66667%}.el-col-xl-offset-10{margin-left:41.66667%}.el-col-xl-pull-10{position:relative;right:41.66667%}.el-col-xl-push-10{position:relative;left:41.66667%}.el-col-xl-11{width:45.83333%}.el-col-xl-offset-11{margin-left:45.83333%}.el-col-xl-pull-11{position:relative;right:45.83333%}.el-col-xl-push-11{position:relative;left:45.83333%}.el-col-xl-12{width:50%}.el-col-xl-offset-12{margin-left:50%}.el-col-xl-pull-12{position:relative;right:50%}.el-col-xl-push-12{position:relative;left:50%}.el-col-xl-13{width:54.16667%}.el-col-xl-offset-13{margin-left:54.16667%}.el-col-xl-pull-13{position:relative;right:54.16667%}.el-col-xl-push-13{position:relative;left:54.16667%}.el-col-xl-14{width:58.33333%}.el-col-xl-offset-14{margin-left:58.33333%}.el-col-xl-pull-14{position:relative;right:58.33333%}.el-col-xl-push-14{position:relative;left:58.33333%}.el-col-xl-15{width:62.5%}.el-col-xl-offset-15{margin-left:62.5%}.el-col-xl-pull-15{position:relative;right:62.5%}.el-col-xl-push-15{position:relative;left:62.5%}.el-col-xl-16{width:66.66667%}.el-col-xl-offset-16{margin-left:66.66667%}.el-col-xl-pull-16{position:relative;right:66.66667%}.el-col-xl-push-16{position:relative;left:66.66667%}.el-col-xl-17{width:70.83333%}.el-col-xl-offset-17{margin-left:70.83333%}.el-col-xl-pull-17{position:relative;right:70.83333%}.el-col-xl-push-17{position:relative;left:70.83333%}.el-col-xl-18{width:75%}.el-col-xl-offset-18{margin-left:75%}.el-col-xl-pull-18{position:relative;right:75%}.el-col-xl-push-18{position:relative;left:75%}.el-col-xl-19{width:79.16667%}.el-col-xl-offset-19{margin-left:79.16667%}.el-col-xl-pull-19{position:relative;right:79.16667%}.el-col-xl-push-19{position:relative;left:79.16667%}.el-col-xl-20{width:83.33333%}.el-col-xl-offset-20{margin-left:83.33333%}.el-col-xl-pull-20{position:relative;right:83.33333%}.el-col-xl-push-20{position:relative;left:83.33333%}.el-col-xl-21{width:87.5%}.el-col-xl-offset-21{margin-left:87.5%}.el-col-xl-pull-21{position:relative;right:87.5%}.el-col-xl-push-21{position:relative;left:87.5%}.el-col-xl-22{width:91.66667%}.el-col-xl-offset-22{margin-left:91.66667%}.el-col-xl-pull-22{position:relative;right:91.66667%}.el-col-xl-push-22{position:relative;left:91.66667%}.el-col-xl-23{width:95.83333%}.el-col-xl-offset-23{margin-left:95.83333%}.el-col-xl-pull-23{position:relative;right:95.83333%}.el-col-xl-push-23{position:relative;left:95.83333%}.el-col-xl-24{width:100%}.el-col-xl-offset-24{margin-left:100%}.el-col-xl-pull-24{position:relative;right:100%}.el-col-xl-push-24{position:relative;left:100%}}@-webkit-keyframes progress{0%{background-position:0 0}100%{background-position:32px 0}}.el-upload{display:inline-block;text-align:center;cursor:pointer;outline:0}.el-upload__input{display:none}.el-upload__tip{font-size:12px;color:#606266;margin-top:7px}.el-upload iframe{position:absolute;z-index:-1;top:0;left:0;opacity:0;filter:alpha(opacity=0)}.el-upload--picture-card{background-color:#fbfdff;border:1px dashed #c0ccda;border-radius:6px;box-sizing:border-box;width:148px;height:148px;line-height:146px;vertical-align:top}.el-upload--picture-card i{font-size:28px;color:#8c939d}.el-upload--picture-card:hover,.el-upload:focus{border-color:#FDA833;color:#FDA833}.el-upload:focus .el-upload-dragger{border-color:#FDA833}.el-upload-dragger{background-color:#fff;border:1px dashed #d9d9d9;border-radius:6px;box-sizing:border-box;width:360px;height:180px;text-align:center;position:relative;overflow:hidden}.el-upload-dragger .el-icon-upload{font-size:67px;color:#C0C4CC;margin:40px 0 16px;line-height:50px}.el-upload-dragger+.el-upload__tip{text-align:center}.el-upload-dragger~.el-upload__files{border-top:1px solid #DCDFE6;margin-top:7px;padding-top:5px}.el-upload-dragger .el-upload__text{color:#606266;font-size:14px;text-align:center}.el-upload-dragger .el-upload__text em{color:#FDA833;font-style:normal}.el-upload-dragger:hover{border-color:#FDA833}.el-upload-dragger.is-dragover{background-color:rgba(32,159,255,.06);border:2px dashed #FDA833}.el-upload-list{margin:0;padding:0;list-style:none}.el-upload-list__item{-webkit-transition:all .5s cubic-bezier(.55,0,.1,1);transition:all .5s cubic-bezier(.55,0,.1,1);font-size:14px;color:#606266;line-height:1.8;margin-top:5px;position:relative;-webkit-box-sizing:border-box;box-sizing:border-box;border-radius:4px;width:100%}.el-upload-list__item .el-progress{position:absolute;top:20px;width:100%}.el-upload-list__item .el-progress__text{position:absolute;right:0;top:-13px}.el-upload-list__item .el-progress-bar{margin-right:0;padding-right:0}.el-upload-list__item:first-child{margin-top:10px}.el-upload-list__item .el-icon-upload-success{color:#67C23A}.el-upload-list__item .el-icon-close{display:none;position:absolute;top:5px;right:5px;cursor:pointer;opacity:.75;color:#606266}.el-upload-list__item .el-icon-close:hover{opacity:1}.el-upload-list__item .el-icon-close-tip{display:none;position:absolute;top:5px;right:5px;font-size:12px;cursor:pointer;opacity:1;color:#FDA833}.el-upload-list__item:hover{background-color:#F5F7FA}.el-upload-list__item:hover .el-icon-close{display:inline-block}.el-upload-list__item:hover .el-progress__text{display:none}.el-upload-list__item.is-success .el-upload-list__item-status-label{display:block}.el-upload-list__item.is-success .el-upload-list__item-name:focus,.el-upload-list__item.is-success .el-upload-list__item-name:hover{color:#FDA833;cursor:pointer}.el-upload-list__item.is-success:focus:not(:hover) .el-icon-close-tip{display:inline-block}.el-upload-list__item.is-success:active .el-icon-close-tip,.el-upload-list__item.is-success:focus .el-upload-list__item-status-label,.el-upload-list__item.is-success:hover .el-upload-list__item-status-label,.el-upload-list__item.is-success:not(.focusing):focus .el-icon-close-tip{display:none}.el-upload-list.is-disabled .el-upload-list__item:hover .el-upload-list__item-status-label{display:block}.el-upload-list__item-name{color:#606266;display:block;margin-right:40px;overflow:hidden;padding-left:4px;text-overflow:ellipsis;-webkit-transition:color .3s;transition:color .3s;white-space:nowrap}.el-upload-list__item-name [class^=el-icon]{height:100%;margin-right:7px;color:#909399;line-height:inherit}.el-upload-list__item-status-label{position:absolute;right:5px;top:0;line-height:inherit;display:none}.el-upload-list__item-delete{position:absolute;right:10px;top:0;font-size:12px;color:#606266;display:none}.el-upload-list__item-delete:hover{color:#FDA833}.el-upload-list--picture-card{margin:0;display:inline;vertical-align:top}.el-upload-list--picture-card .el-upload-list__item{overflow:hidden;background-color:#fff;border:1px solid #c0ccda;border-radius:6px;-webkit-box-sizing:border-box;box-sizing:border-box;width:148px;height:148px;margin:0 8px 8px 0;display:inline-block}.el-upload-list--picture-card .el-upload-list__item .el-icon-check,.el-upload-list--picture-card .el-upload-list__item .el-icon-circle-check{color:#FFF}.el-upload-list--picture-card .el-upload-list__item .el-icon-close,.el-upload-list--picture-card .el-upload-list__item:hover .el-upload-list__item-status-label{display:none}.el-upload-list--picture-card .el-upload-list__item:hover .el-progress__text{display:block}.el-upload-list--picture-card .el-upload-list__item-name{display:none}.el-upload-list--picture-card .el-upload-list__item-thumbnail{width:100%;height:100%}.el-upload-list--picture-card .el-upload-list__item-status-label{position:absolute;right:-15px;top:-6px;width:40px;height:24px;background:#13ce66;text-align:center;-webkit-transform:rotate(45deg);transform:rotate(45deg);-webkit-box-shadow:0 0 1pc 1px rgba(0,0,0,.2);box-shadow:0 0 1pc 1px rgba(0,0,0,.2)}.el-upload-list--picture-card .el-upload-list__item-status-label i{font-size:12px;margin-top:11px;-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}.el-upload-list--picture-card .el-upload-list__item-actions{position:absolute;width:100%;height:100%;left:0;top:0;cursor:default;text-align:center;color:#fff;opacity:0;font-size:20px;background-color:rgba(0,0,0,.5);-webkit-transition:opacity .3s;transition:opacity .3s}.el-upload-list--picture-card .el-upload-list__item-actions::after{display:inline-block;content:"";height:100%;vertical-align:middle}.el-upload-list--picture-card .el-upload-list__item-actions span{display:none;cursor:pointer}.el-upload-list--picture-card .el-upload-list__item-actions span+span{margin-left:15px}.el-upload-list--picture-card .el-upload-list__item-actions .el-upload-list__item-delete{position:static;font-size:inherit;color:inherit}.el-upload-list--picture-card .el-upload-list__item-actions:hover{opacity:1}.el-upload-list--picture-card .el-upload-list__item-actions:hover span{display:inline-block}.el-upload-list--picture-card .el-progress{top:50%;left:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);bottom:auto;width:126px}.el-upload-list--picture-card .el-progress .el-progress__text{top:50%}.el-upload-list--picture .el-upload-list__item{overflow:hidden;z-index:0;background-color:#fff;border:1px solid #c0ccda;border-radius:6px;-webkit-box-sizing:border-box;box-sizing:border-box;margin-top:10px;padding:10px 10px 10px 90px;height:92px}.el-upload-list--picture .el-upload-list__item .el-icon-check,.el-upload-list--picture .el-upload-list__item .el-icon-circle-check{color:#FFF}.el-upload-list--picture .el-upload-list__item:hover .el-upload-list__item-status-label{background:0 0;-webkit-box-shadow:none;box-shadow:none;top:-2px;right:-12px}.el-upload-list--picture .el-upload-list__item:hover .el-progress__text{display:block}.el-upload-list--picture .el-upload-list__item.is-success .el-upload-list__item-name{line-height:70px;margin-top:0}.el-upload-list--picture .el-upload-list__item.is-success .el-upload-list__item-name i{display:none}.el-upload-list--picture .el-upload-list__item-thumbnail{vertical-align:middle;display:inline-block;width:70px;height:70px;float:left;position:relative;z-index:1;margin-left:-80px;background-color:#FFF}.el-upload-list--picture .el-upload-list__item-name{display:block;margin-top:20px}.el-upload-list--picture .el-upload-list__item-name i{font-size:70px;line-height:1;position:absolute;left:9px;top:10px}.el-upload-list--picture .el-upload-list__item-status-label{position:absolute;right:-17px;top:-7px;width:46px;height:26px;background:#13ce66;text-align:center;-webkit-transform:rotate(45deg);transform:rotate(45deg);-webkit-box-shadow:0 1px 1px #ccc;box-shadow:0 1px 1px #ccc}.el-upload-list--picture .el-upload-list__item-status-label i{font-size:12px;margin-top:12px;-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}.el-upload-list--picture .el-progress{position:relative;top:-7px}.el-upload-cover{position:absolute;left:0;top:0;width:100%;height:100%;overflow:hidden;z-index:10;cursor:default}.el-upload-cover::after{display:inline-block;height:100%;vertical-align:middle}.el-upload-cover img{display:block;width:100%;height:100%}.el-upload-cover__label{position:absolute;right:-15px;top:-6px;width:40px;height:24px;background:#13ce66;text-align:center;-webkit-transform:rotate(45deg);transform:rotate(45deg);-webkit-box-shadow:0 0 1pc 1px rgba(0,0,0,.2);box-shadow:0 0 1pc 1px rgba(0,0,0,.2)}.el-upload-cover__label i{font-size:12px;margin-top:11px;-webkit-transform:rotate(-45deg);transform:rotate(-45deg);color:#fff}.el-upload-cover__progress{display:inline-block;vertical-align:middle;position:static;width:243px}.el-upload-cover__progress+.el-upload__inner{opacity:0}.el-upload-cover__content{position:absolute;top:0;left:0;width:100%;height:100%}.el-upload-cover__interact{position:absolute;bottom:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,.72);text-align:center}.el-upload-cover__interact .btn{display:inline-block;color:#FFF;font-size:14px;cursor:pointer;vertical-align:middle;-webkit-transition:opacity .3s cubic-bezier(.23,1,.32,1),-webkit-transform .3s cubic-bezier(.23,1,.32,1);transition:opacity .3s cubic-bezier(.23,1,.32,1),-webkit-transform .3s cubic-bezier(.23,1,.32,1);transition:transform .3s cubic-bezier(.23,1,.32,1),opacity .3s cubic-bezier(.23,1,.32,1);transition:transform .3s cubic-bezier(.23,1,.32,1),opacity .3s cubic-bezier(.23,1,.32,1),-webkit-transform .3s cubic-bezier(.23,1,.32,1);margin-top:60px}.el-upload-cover__interact .btn span{opacity:0;-webkit-transition:opacity .15s linear;transition:opacity .15s linear}.el-upload-cover__interact .btn:not(:first-child){margin-left:35px}.el-upload-cover__interact .btn:hover{-webkit-transform:translateY(-13px);transform:translateY(-13px)}.el-upload-cover__interact .btn:hover span{opacity:1}.el-upload-cover__interact .btn i{color:#FFF;display:block;font-size:24px;line-height:inherit;margin:0 auto 5px}.el-upload-cover__title{position:absolute;bottom:0;left:0;background-color:#FFF;height:36px;width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:400;text-align:left;padding:0 10px;margin:0;line-height:36px;font-size:14px;color:#303133}.el-upload-cover+.el-upload__inner{opacity:0;position:relative;z-index:1}.el-progress{position:relative;line-height:1}.el-progress__text{font-size:14px;color:#606266;display:inline-block;vertical-align:middle;margin-left:10px;line-height:1}.el-progress__text i{vertical-align:middle;display:block}.el-progress--circle,.el-progress--dashboard{display:inline-block}.el-progress--circle .el-progress__text,.el-progress--dashboard .el-progress__text{position:absolute;top:50%;left:0;width:100%;text-align:center;margin:0;-webkit-transform:translate(0,-50%);transform:translate(0,-50%)}.el-progress--circle .el-progress__text i,.el-progress--dashboard .el-progress__text i{vertical-align:middle;display:inline-block}.el-progress--without-text .el-progress__text{display:none}.el-progress--without-text .el-progress-bar{padding-right:0;margin-right:0;display:block}.el-progress-bar,.el-progress-bar__inner::after,.el-progress-bar__innerText,.el-spinner{display:inline-block;vertical-align:middle}.el-progress--text-inside .el-progress-bar{padding-right:0;margin-right:0}.el-progress.is-success .el-progress-bar__inner{background-color:#67C23A}.el-progress.is-success .el-progress__text{color:#67C23A}.el-progress.is-warning .el-progress-bar__inner{background-color:#E6A23C}.el-progress.is-warning .el-progress__text{color:#E6A23C}.el-progress.is-exception .el-progress-bar__inner{background-color:#F56C6C}.el-progress.is-exception .el-progress__text{color:#F56C6C}.el-progress-bar{padding-right:50px;width:100%;margin-right:-55px;-webkit-box-sizing:border-box;box-sizing:border-box}.el-progress-bar__outer{height:6px;border-radius:100px;background-color:#EBEEF5;overflow:hidden;position:relative;vertical-align:middle}.el-progress-bar__inner{position:absolute;left:0;top:0;height:100%;background-color:#FDA833;text-align:right;border-radius:100px;line-height:1;white-space:nowrap;-webkit-transition:width .6s ease;transition:width .6s ease}.el-card,.el-message{border-radius:4px;overflow:hidden}.el-progress-bar__inner::after{height:100%}.el-progress-bar__innerText{color:#FFF;font-size:12px;margin:0 5px}@keyframes progress{0%{background-position:0 0}100%{background-position:32px 0}}.el-time-spinner{width:100%;white-space:nowrap}.el-spinner-inner{-webkit-animation:rotate 2s linear infinite;animation:rotate 2s linear infinite;width:50px;height:50px}.el-spinner-inner .path{stroke:#ececec;stroke-linecap:round;-webkit-animation:dash 1.5s ease-in-out infinite;animation:dash 1.5s ease-in-out infinite}@-webkit-keyframes rotate{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes rotate{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@-webkit-keyframes dash{0%{stroke-dasharray:1,150;stroke-dashoffset:0}50%{stroke-dasharray:90,150;stroke-dashoffset:-35}100%{stroke-dasharray:90,150;stroke-dashoffset:-124}}@keyframes dash{0%{stroke-dasharray:1,150;stroke-dashoffset:0}50%{stroke-dasharray:90,150;stroke-dashoffset:-35}100%{stroke-dasharray:90,150;stroke-dashoffset:-124}}.el-message{min-width:380px;-webkit-box-sizing:border-box;box-sizing:border-box;border-width:1px;border-style:solid;border-color:#EBEEF5;position:fixed;left:50%;top:20px;-webkit-transform:translateX(-50%);transform:translateX(-50%);background-color:#edf2fc;-webkit-transition:opacity .3s,top .4s,-webkit-transform .4s;transition:opacity .3s,top .4s,-webkit-transform .4s;transition:opacity .3s,transform .4s,top .4s;transition:opacity .3s,transform .4s,top .4s,-webkit-transform .4s;padding:15px 15px 15px 20px;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.el-message.is-center{-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.el-message.is-closable .el-message__content{padding-right:16px}.el-message p{margin:0}.el-message--info .el-message__content{color:#909399}.el-message--success{background-color:#f0f9eb;border-color:#e1f3d8}.el-message--success .el-message__content{color:#67C23A}.el-message--warning{background-color:#fdf6ec;border-color:#faecd8}.el-message--warning .el-message__content{color:#E6A23C}.el-message--error{background-color:#fef0f0;border-color:#fde2e2}.el-message--error .el-message__content{color:#F56C6C}.el-message__icon{margin-right:10px}.el-message__content{padding:0;font-size:14px;line-height:1}.el-message__closeBtn{position:absolute;top:50%;right:15px;-webkit-transform:translateY(-50%);transform:translateY(-50%);cursor:pointer;color:#C0C4CC;font-size:16px}.el-message__closeBtn:hover{color:#909399}.el-message .el-icon-success{color:#67C23A}.el-message .el-icon-error{color:#F56C6C}.el-message .el-icon-info{color:#909399}.el-message .el-icon-warning{color:#E6A23C}.el-message-fade-enter,.el-message-fade-leave-active{opacity:0;-webkit-transform:translate(-50%,-100%);transform:translate(-50%,-100%)}.el-badge{position:relative;vertical-align:middle;display:inline-block}.el-badge__content{background-color:#F56C6C;border-radius:10px;color:#FFF;display:inline-block;font-size:12px;height:18px;line-height:18px;padding:0 6px;text-align:center;white-space:nowrap;border:1px solid #FFF}.el-badge__content.is-fixed{position:absolute;top:0;right:10px;-webkit-transform:translateY(-50%) translateX(100%);transform:translateY(-50%) translateX(100%)}.el-rate__icon,.el-rate__item{position:relative;display:inline-block}.el-badge__content.is-fixed.is-dot{right:5px}.el-badge__content.is-dot{height:8px;width:8px;padding:0;right:0;border-radius:50%}.el-badge__content--primary{background-color:#FDA833}.el-badge__content--success{background-color:#67C23A}.el-badge__content--warning{background-color:#E6A23C}.el-badge__content--info{background-color:#909399}.el-badge__content--danger{background-color:#F56C6C}.el-card{border:1px solid #EBEEF5;background-color:#FFF;color:#303133;-webkit-transition:.3s;transition:.3s}.el-card.is-always-shadow,.el-card.is-hover-shadow:focus,.el-card.is-hover-shadow:hover{-webkit-box-shadow:0 2px 12px 0 rgba(0,0,0,.1);box-shadow:0 2px 12px 0 rgba(0,0,0,.1)}.el-card__header{padding:18px 20px;border-bottom:1px solid #EBEEF5;-webkit-box-sizing:border-box;box-sizing:border-box}.el-card__body{padding:20px}.el-rate{height:20px;line-height:1}.el-rate__item{font-size:0;vertical-align:middle}.el-rate__icon{font-size:18px;margin-right:6px;color:#C0C4CC;-webkit-transition:.3s;transition:.3s}.el-rate__decimal,.el-rate__icon .path2{position:absolute;top:0;left:0}.el-rate__icon.hover{-webkit-transform:scale(1.15);transform:scale(1.15)}.el-rate__decimal{display:inline-block;overflow:hidden}.el-step.is-vertical,.el-steps{display:-webkit-box;display:-ms-flexbox}.el-rate__text{font-size:14px;vertical-align:middle}.el-steps{display:flex}.el-steps--simple{padding:13px 8%;border-radius:4px;background:#F5F7FA}.el-steps--horizontal{white-space:nowrap}.el-steps--vertical{height:100%;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-flow:column;flex-flow:column}.el-step{position:relative;-ms-flex-negative:1;flex-shrink:1}.el-step:last-of-type .el-step__line{display:none}.el-step:last-of-type.is-flex{-ms-flex-preferred-size:auto!important;flex-basis:auto!important;-ms-flex-negative:0;flex-shrink:0;-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0}.el-step:last-of-type .el-step__description,.el-step:last-of-type .el-step__main{padding-right:0}.el-step__head{position:relative;width:100%}.el-step__head.is-process{color:#303133;border-color:#303133}.el-step__head.is-wait{color:#C0C4CC;border-color:#C0C4CC}.el-step__head.is-success{color:#67C23A;border-color:#67C23A}.el-step__head.is-error{color:#F56C6C;border-color:#F56C6C}.el-step__head.is-finish{color:#FDA833;border-color:#FDA833}.el-step__icon{position:relative;z-index:1;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;width:24px;height:24px;font-size:14px;-webkit-box-sizing:border-box;box-sizing:border-box;background:#FFF;-webkit-transition:.15s ease-out;transition:.15s ease-out}.el-step__icon.is-text{border-radius:50%;border:2px solid;border-color:inherit}.el-step__icon.is-icon{width:40px}.el-step__icon-inner{display:inline-block;user-select:none;text-align:center;font-weight:700;line-height:1;color:inherit}.el-step__icon-inner[class*=el-icon]:not(.is-status){font-size:25px;font-weight:400}.el-step__icon-inner.is-status{-webkit-transform:translateY(1px);transform:translateY(1px)}.el-step__line{position:absolute;border-color:inherit;background-color:#C0C4CC}.el-step__line-inner{display:block;border-width:1px;border-style:solid;border-color:inherit;-webkit-transition:.15s ease-out;transition:.15s ease-out;-webkit-box-sizing:border-box;box-sizing:border-box;width:0;height:0}.el-step__main{white-space:normal;text-align:left}.el-step__title{font-size:16px;line-height:38px}.el-step__title.is-process{font-weight:700;color:#303133}.el-step__title.is-wait{color:#C0C4CC}.el-step__title.is-success{color:#67C23A}.el-step__title.is-error{color:#F56C6C}.el-step__title.is-finish{color:#FDA833}.el-step__description{padding-right:10%;margin-top:-5px;font-size:12px;line-height:20px;font-weight:400}.el-step__description.is-process{color:#303133}.el-step__description.is-wait{color:#C0C4CC}.el-step__description.is-success{color:#67C23A}.el-step__description.is-error{color:#F56C6C}.el-step__description.is-finish{color:#FDA833}.el-step.is-horizontal{display:inline-block}.el-step.is-horizontal .el-step__line{height:2px;top:11px;left:0;right:0}.el-step.is-vertical{display:flex}.el-step.is-vertical .el-step__head{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;width:24px}.el-step.is-vertical .el-step__main{padding-left:10px;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1}.el-step.is-vertical .el-step__title{line-height:24px;padding-bottom:8px}.el-step.is-vertical .el-step__line{width:2px;top:0;bottom:0;left:11px}.el-step.is-vertical .el-step__icon.is-icon{width:24px}.el-step.is-center .el-step__head,.el-step.is-center .el-step__main{text-align:center}.el-step.is-center .el-step__description{padding-left:20%;padding-right:20%}.el-step.is-center .el-step__line{left:50%;right:-50%}.el-step.is-simple{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.el-step.is-simple .el-step__head{width:auto;font-size:0;padding-right:10px}.el-step.is-simple .el-step__icon{background:0 0;width:16px;height:16px;font-size:12px}.el-step.is-simple .el-step__icon-inner[class*=el-icon]:not(.is-status){font-size:18px}.el-step.is-simple .el-step__icon-inner.is-status{-webkit-transform:scale(.8) translateY(1px);transform:scale(.8) translateY(1px)}.el-step.is-simple .el-step__main{position:relative;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1}.el-step.is-simple .el-step__title{font-size:16px;line-height:20px}.el-step.is-simple:not(:last-of-type) .el-step__title{max-width:50%;word-break:break-all}.el-step.is-simple .el-step__arrow{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.el-step.is-simple .el-step__arrow::after,.el-step.is-simple .el-step__arrow::before{content:'';display:inline-block;position:absolute;height:15px;width:1px;background:#C0C4CC}.el-step.is-simple .el-step__arrow::before{-webkit-transform:rotate(-45deg) translateY(-4px);transform:rotate(-45deg) translateY(-4px);-webkit-transform-origin:0 0;transform-origin:0 0}.el-step.is-simple .el-step__arrow::after{-webkit-transform:rotate(45deg) translateY(4px);transform:rotate(45deg) translateY(4px);-webkit-transform-origin:100% 100%;transform-origin:100% 100%}.el-step.is-simple:last-of-type .el-step__arrow{display:none}.el-carousel{position:relative}.el-carousel--horizontal{overflow-x:hidden}.el-carousel--vertical{overflow-y:hidden}.el-carousel__container{position:relative;height:300px}.el-carousel__arrow{border:none;outline:0;padding:0;margin:0;height:36px;width:36px;cursor:pointer;-webkit-transition:.3s;transition:.3s;border-radius:50%;background-color:rgba(31,45,61,.11);color:#FFF;position:absolute;top:50%;z-index:10;-webkit-transform:translateY(-50%);transform:translateY(-50%);text-align:center;font-size:12px}.el-carousel__arrow--left{left:16px}.el-carousel__arrow--right{right:16px}.el-carousel__arrow:hover{background-color:rgba(31,45,61,.23)}.el-carousel__arrow i{cursor:pointer}.el-carousel__indicators{position:absolute;list-style:none;margin:0;padding:0;z-index:2}.el-carousel__indicators--horizontal{bottom:0;left:50%;-webkit-transform:translateX(-50%);transform:translateX(-50%)}.el-carousel__indicators--vertical{right:0;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%)}.el-carousel__indicators--outside{bottom:26px;text-align:center;position:static;-webkit-transform:none;transform:none}.el-carousel__indicators--outside .el-carousel__indicator:hover button{opacity:.64}.el-carousel__indicators--outside button{background-color:#C0C4CC;opacity:.24}.el-carousel__indicators--labels{left:0;right:0;-webkit-transform:none;transform:none;text-align:center}.el-carousel__indicators--labels .el-carousel__button{height:auto;width:auto;padding:2px 18px;font-size:12px}.el-carousel__indicators--labels .el-carousel__indicator{padding:6px 4px}.el-carousel__indicator{background-color:transparent;cursor:pointer}.el-carousel__indicator:hover button{opacity:.72}.el-carousel__indicator--horizontal{display:inline-block;padding:12px 4px}.el-carousel__indicator--vertical{padding:4px 12px}.el-carousel__indicator--vertical .el-carousel__button{width:2px;height:15px}.el-carousel__indicator.is-active button{opacity:1}.el-carousel__button{display:block;opacity:.48;width:30px;height:2px;background-color:#FFF;border:none;outline:0;padding:0;margin:0;cursor:pointer;-webkit-transition:.3s;transition:.3s}.el-carousel__item,.el-carousel__mask{height:100%;top:0;left:0;position:absolute}.carousel-arrow-left-enter,.carousel-arrow-left-leave-active{-webkit-transform:translateY(-50%) translateX(-10px);transform:translateY(-50%) translateX(-10px);opacity:0}.carousel-arrow-right-enter,.carousel-arrow-right-leave-active{-webkit-transform:translateY(-50%) translateX(10px);transform:translateY(-50%) translateX(10px);opacity:0}.el-carousel__item{width:100%;display:inline-block;overflow:hidden;z-index:0}.el-carousel__item.is-active{z-index:2}.el-carousel__item.is-animating{-webkit-transition:-webkit-transform .4s ease-in-out;transition:-webkit-transform .4s ease-in-out;transition:transform .4s ease-in-out;transition:transform .4s ease-in-out,-webkit-transform .4s ease-in-out}.el-carousel__item--card{width:50%;-webkit-transition:-webkit-transform .4s ease-in-out;transition:-webkit-transform .4s ease-in-out;transition:transform .4s ease-in-out;transition:transform .4s ease-in-out,-webkit-transform .4s ease-in-out}.el-carousel__item--card.is-in-stage{cursor:pointer;z-index:1}.el-carousel__item--card.is-in-stage.is-hover .el-carousel__mask,.el-carousel__item--card.is-in-stage:hover .el-carousel__mask{opacity:.12}.el-carousel__item--card.is-active{z-index:2}.el-carousel__mask{width:100%;background-color:#FFF;opacity:.24;-webkit-transition:.2s;transition:.2s}.el-fade-in-enter,.el-fade-in-leave-active,.el-fade-in-linear-enter,.el-fade-in-linear-leave,.el-fade-in-linear-leave-active,.fade-in-linear-enter,.fade-in-linear-leave,.fade-in-linear-leave-active{opacity:0}.fade-in-linear-enter-active,.fade-in-linear-leave-active{-webkit-transition:opacity .2s linear;transition:opacity .2s linear}.el-fade-in-linear-enter-active,.el-fade-in-linear-leave-active{-webkit-transition:opacity .2s linear;transition:opacity .2s linear}.el-fade-in-enter-active,.el-fade-in-leave-active{-webkit-transition:all .3s cubic-bezier(.55,0,.1,1);transition:all .3s cubic-bezier(.55,0,.1,1)}.el-zoom-in-center-enter-active,.el-zoom-in-center-leave-active{-webkit-transition:all .3s cubic-bezier(.55,0,.1,1);transition:all .3s cubic-bezier(.55,0,.1,1)}.el-zoom-in-center-enter,.el-zoom-in-center-leave-active{opacity:0;-webkit-transform:scaleX(0);transform:scaleX(0)}.el-zoom-in-top-enter-active,.el-zoom-in-top-leave-active{opacity:1;-webkit-transform:scaleY(1);transform:scaleY(1);-webkit-transition:opacity .3s cubic-bezier(.23,1,.32,1),-webkit-transform .3s cubic-bezier(.23,1,.32,1);transition:opacity .3s cubic-bezier(.23,1,.32,1),-webkit-transform .3s cubic-bezier(.23,1,.32,1);transition:transform .3s cubic-bezier(.23,1,.32,1),opacity .3s cubic-bezier(.23,1,.32,1);transition:transform .3s cubic-bezier(.23,1,.32,1),opacity .3s cubic-bezier(.23,1,.32,1),-webkit-transform .3s cubic-bezier(.23,1,.32,1);-webkit-transform-origin:center top;transform-origin:center top}.el-zoom-in-top-enter,.el-zoom-in-top-leave-active{opacity:0;-webkit-transform:scaleY(0);transform:scaleY(0)}.el-zoom-in-bottom-enter-active,.el-zoom-in-bottom-leave-active{opacity:1;-webkit-transform:scaleY(1);transform:scaleY(1);-webkit-transition:opacity .3s cubic-bezier(.23,1,.32,1),-webkit-transform .3s cubic-bezier(.23,1,.32,1);transition:opacity .3s cubic-bezier(.23,1,.32,1),-webkit-transform .3s cubic-bezier(.23,1,.32,1);transition:transform .3s cubic-bezier(.23,1,.32,1),opacity .3s cubic-bezier(.23,1,.32,1);transition:transform .3s cubic-bezier(.23,1,.32,1),opacity .3s cubic-bezier(.23,1,.32,1),-webkit-transform .3s cubic-bezier(.23,1,.32,1);-webkit-transform-origin:center bottom;transform-origin:center bottom}.el-zoom-in-bottom-enter,.el-zoom-in-bottom-leave-active{opacity:0;-webkit-transform:scaleY(0);transform:scaleY(0)}.el-zoom-in-left-enter-active,.el-zoom-in-left-leave-active{opacity:1;-webkit-transform:scale(1,1);transform:scale(1,1);-webkit-transition:opacity .3s cubic-bezier(.23,1,.32,1),-webkit-transform .3s cubic-bezier(.23,1,.32,1);transition:opacity .3s cubic-bezier(.23,1,.32,1),-webkit-transform .3s cubic-bezier(.23,1,.32,1);transition:transform .3s cubic-bezier(.23,1,.32,1),opacity .3s cubic-bezier(.23,1,.32,1);transition:transform .3s cubic-bezier(.23,1,.32,1),opacity .3s cubic-bezier(.23,1,.32,1),-webkit-transform .3s cubic-bezier(.23,1,.32,1);-webkit-transform-origin:top left;transform-origin:top left}.el-zoom-in-left-enter,.el-zoom-in-left-leave-active{opacity:0;-webkit-transform:scale(.45,.45);transform:scale(.45,.45)}.collapse-transition{-webkit-transition:.3s height ease-in-out,.3s padding-top ease-in-out,.3s padding-bottom ease-in-out;transition:.3s height ease-in-out,.3s padding-top ease-in-out,.3s padding-bottom ease-in-out}.horizontal-collapse-transition{-webkit-transition:.3s width ease-in-out,.3s padding-left ease-in-out,.3s padding-right ease-in-out;transition:.3s width ease-in-out,.3s padding-left ease-in-out,.3s padding-right ease-in-out}.el-list-enter-active,.el-list-leave-active{-webkit-transition:all 1s;transition:all 1s}.el-list-enter,.el-list-leave-active{opacity:0;-webkit-transform:translateY(-30px);transform:translateY(-30px)}.el-opacity-transition{-webkit-transition:opacity .3s cubic-bezier(.55,0,.1,1);transition:opacity .3s cubic-bezier(.55,0,.1,1)}.el-collapse{border-top:1px solid #EBEEF5;border-bottom:1px solid #EBEEF5}.el-collapse-item.is-disabled .el-collapse-item__header{color:#bbb;cursor:not-allowed}.el-collapse-item__header{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;height:48px;line-height:48px;background-color:#FFF;color:#303133;cursor:pointer;border-bottom:1px solid #EBEEF5;font-size:13px;font-weight:500;-webkit-transition:border-bottom-color .3s;transition:border-bottom-color .3s;outline:0}.el-collapse-item__arrow{margin:0 8px 0 auto;transition:-webkit-transform .3s;transition:transform .3s;transition:transform .3s,-webkit-transform .3s;font-weight:300}.el-collapse-item__arrow.is-active{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.el-collapse-item__header.focusing:focus:not(:hover){color:#FDA833}.el-collapse-item__header.is-active{border-bottom-color:transparent}.el-collapse-item__wrap{will-change:height;background-color:#FFF;overflow:hidden;-webkit-box-sizing:border-box;box-sizing:border-box;border-bottom:1px solid #EBEEF5}.el-cascader__tags,.el-tag{-webkit-box-sizing:border-box}.el-collapse-item__content{padding-bottom:25px;font-size:13px;color:#303133;line-height:1.769230769230769}.el-collapse-item:last-child{margin-bottom:-1px}.el-popper .popper__arrow,.el-popper .popper__arrow::after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.el-popper .popper__arrow{border-width:6px;-webkit-filter:drop-shadow(0 2px 12px rgba(0, 0, 0, .03));filter:drop-shadow(0 2px 12px rgba(0, 0, 0, .03))}.el-popper .popper__arrow::after{content:" ";border-width:6px}.el-popper[x-placement^=top]{margin-bottom:12px}.el-popper[x-placement^=top] .popper__arrow{bottom:-6px;left:50%;margin-right:3px;border-top-color:#EBEEF5;border-bottom-width:0}.el-popper[x-placement^=top] .popper__arrow::after{bottom:1px;margin-left:-6px;border-top-color:#FFF;border-bottom-width:0}.el-popper[x-placement^=bottom]{margin-top:12px}.el-popper[x-placement^=bottom] .popper__arrow{top:-6px;left:50%;margin-right:3px;border-top-width:0;border-bottom-color:#EBEEF5}.el-popper[x-placement^=bottom] .popper__arrow::after{top:1px;margin-left:-6px;border-top-width:0;border-bottom-color:#FFF}.el-popper[x-placement^=right]{margin-left:12px}.el-popper[x-placement^=right] .popper__arrow{top:50%;left:-6px;margin-bottom:3px;border-right-color:#EBEEF5;border-left-width:0}.el-popper[x-placement^=right] .popper__arrow::after{bottom:-6px;left:1px;border-right-color:#FFF;border-left-width:0}.el-popper[x-placement^=left]{margin-right:12px}.el-popper[x-placement^=left] .popper__arrow{top:50%;right:-6px;margin-bottom:3px;border-right-width:0;border-left-color:#EBEEF5}.el-popper[x-placement^=left] .popper__arrow::after{right:1px;bottom:-6px;margin-left:-6px;border-right-width:0;border-left-color:#FFF}.el-tag{background-color:rgb(255, 246, 235);border-color:rgb(255, 238, 214);display:inline-block;height:32px;padding:0 10px;line-height:30px;font-size:12px;color:#FDA833;border-width:1px;border-style:solid;border-radius:4px;box-sizing:border-box;white-space:nowrap}.el-tag.is-hit{border-color:#FDA833}.el-tag .el-tag__close{color:#FDA833}.el-tag .el-tag__close:hover{color:#FFF;background-color:#FDA833}.el-tag.el-tag--info{background-color:#f4f4f5;border-color:#e9e9eb;color:#909399}.el-tag.el-tag--info.is-hit{border-color:#909399}.el-tag.el-tag--info .el-tag__close{color:#909399}.el-tag.el-tag--info .el-tag__close:hover{color:#FFF;background-color:#909399}.el-tag.el-tag--success{background-color:#f0f9eb;border-color:#e1f3d8;color:#67c23a}.el-tag.el-tag--success.is-hit{border-color:#67C23A}.el-tag.el-tag--success .el-tag__close{color:#67c23a}.el-tag.el-tag--success .el-tag__close:hover{color:#FFF;background-color:#67c23a}.el-tag.el-tag--warning{background-color:#fdf6ec;border-color:#faecd8;color:#e6a23c}.el-tag.el-tag--warning.is-hit{border-color:#E6A23C}.el-tag.el-tag--warning .el-tag__close{color:#e6a23c}.el-tag.el-tag--warning .el-tag__close:hover{color:#FFF;background-color:#e6a23c}.el-tag.el-tag--danger{background-color:#fef0f0;border-color:#fde2e2;color:#f56c6c}.el-tag.el-tag--danger.is-hit{border-color:#F56C6C}.el-tag.el-tag--danger .el-tag__close{color:#f56c6c}.el-tag.el-tag--danger .el-tag__close:hover{color:#FFF;background-color:#f56c6c}.el-tag .el-icon-close{border-radius:50%;text-align:center;position:relative;cursor:pointer;font-size:12px;height:16px;width:16px;line-height:16px;vertical-align:middle;top:-1px;right:-5px}.el-tag .el-icon-close::before{display:block}.el-tag--dark{background-color:#FDA833;border-color:#FDA833;color:#fff}.el-tag--dark.is-hit{border-color:#FDA833}.el-tag--dark .el-tag__close{color:#fff}.el-tag--dark .el-tag__close:hover{color:#FFF;background-color:rgb(253, 185, 92)}.el-tag--dark.el-tag--info{background-color:#909399;border-color:#909399;color:#fff}.el-tag--dark.el-tag--info.is-hit{border-color:#909399}.el-tag--dark.el-tag--info .el-tag__close{color:#fff}.el-tag--dark.el-tag--info .el-tag__close:hover{color:#FFF;background-color:#a6a9ad}.el-tag--dark.el-tag--success{background-color:#67c23a;border-color:#67c23a;color:#fff}.el-tag--dark.el-tag--success.is-hit{border-color:#67C23A}.el-tag--dark.el-tag--success .el-tag__close{color:#fff}.el-tag--dark.el-tag--success .el-tag__close:hover{color:#FFF;background-color:#85ce61}.el-tag--dark.el-tag--warning{background-color:#e6a23c;border-color:#e6a23c;color:#fff}.el-tag--dark.el-tag--warning.is-hit{border-color:#E6A23C}.el-tag--dark.el-tag--warning .el-tag__close{color:#fff}.el-tag--dark.el-tag--warning .el-tag__close:hover{color:#FFF;background-color:#ebb563}.el-tag--dark.el-tag--danger{background-color:#f56c6c;border-color:#f56c6c;color:#fff}.el-tag--dark.el-tag--danger.is-hit{border-color:#F56C6C}.el-tag--dark.el-tag--danger .el-tag__close{color:#fff}.el-tag--dark.el-tag--danger .el-tag__close:hover{color:#FFF;background-color:#f78989}.el-tag--plain{background-color:#fff;border-color:rgb(254, 220, 173);color:#FDA833}.el-tag--plain.is-hit{border-color:#FDA833}.el-tag--plain .el-tag__close{color:#FDA833}.el-tag--plain .el-tag__close:hover{color:#FFF;background-color:#FDA833}.el-tag--plain.el-tag--info{background-color:#fff;border-color:#d3d4d6;color:#909399}.el-tag--plain.el-tag--info.is-hit{border-color:#909399}.el-tag--plain.el-tag--info .el-tag__close{color:#909399}.el-tag--plain.el-tag--info .el-tag__close:hover{color:#FFF;background-color:#909399}.el-tag--plain.el-tag--success{background-color:#fff;border-color:#c2e7b0;color:#67c23a}.el-tag--plain.el-tag--success.is-hit{border-color:#67C23A}.el-tag--plain.el-tag--success .el-tag__close{color:#67c23a}.el-tag--plain.el-tag--success .el-tag__close:hover{color:#FFF;background-color:#67c23a}.el-tag--plain.el-tag--warning{background-color:#fff;border-color:#f5dab1;color:#e6a23c}.el-tag--plain.el-tag--warning.is-hit{border-color:#E6A23C}.el-tag--plain.el-tag--warning .el-tag__close{color:#e6a23c}.el-tag--plain.el-tag--warning .el-tag__close:hover{color:#FFF;background-color:#e6a23c}.el-tag--plain.el-tag--danger{background-color:#fff;border-color:#fbc4c4;color:#f56c6c}.el-tag--plain.el-tag--danger.is-hit{border-color:#F56C6C}.el-tag--plain.el-tag--danger .el-tag__close{color:#f56c6c}.el-tag--plain.el-tag--danger .el-tag__close:hover{color:#FFF;background-color:#f56c6c}.el-tag--medium{height:28px;line-height:26px}.el-tag--medium .el-icon-close{-webkit-transform:scale(.8);transform:scale(.8)}.el-tag--small{height:24px;padding:0 8px;line-height:22px}.el-tag--small .el-icon-close{-webkit-transform:scale(.8);transform:scale(.8)}.el-tag--mini{height:20px;padding:0 5px;line-height:19px}.el-tag--mini .el-icon-close{margin-left:-3px;-webkit-transform:scale(.7);transform:scale(.7)}.el-cascader{display:inline-block;position:relative;font-size:14px;line-height:40px}.el-cascader:not(.is-disabled):hover .el-input__inner{cursor:pointer;border-color:#C0C4CC}.el-cascader .el-input .el-input__inner:focus,.el-cascader .el-input.is-focus .el-input__inner{border-color:#FDA833}.el-cascader .el-input{cursor:pointer}.el-cascader .el-input .el-input__inner{text-overflow:ellipsis}.el-cascader .el-input .el-icon-arrow-down{-webkit-transition:-webkit-transform .3s;transition:-webkit-transform .3s;transition:transform .3s;transition:transform .3s,-webkit-transform .3s;font-size:14px}.el-cascader .el-input .el-icon-arrow-down.is-reverse{-webkit-transform:rotateZ(180deg);transform:rotateZ(180deg)}.el-cascader .el-input .el-icon-circle-close:hover{color:#909399}.el-cascader--medium{font-size:14px;line-height:36px}.el-cascader--small{font-size:13px;line-height:32px}.el-cascader--mini{font-size:12px;line-height:28px}.el-cascader.is-disabled .el-cascader__label{z-index:2;color:#C0C4CC}.el-cascader__dropdown{margin:5px 0;font-size:14px;background:#FFF;border:1px solid #E4E7ED;border-radius:4px;-webkit-box-shadow:0 2px 12px 0 rgba(0,0,0,.1);box-shadow:0 2px 12px 0 rgba(0,0,0,.1)}.el-cascader__tags{position:absolute;left:0;right:30px;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%);display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;line-height:normal;text-align:left;box-sizing:border-box}.el-cascader__tags .el-tag{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;max-width:100%;margin:2px 0 2px 6px;text-overflow:ellipsis;background:#f0f2f5}.el-cascader__tags .el-tag:not(.is-hit){border-color:transparent}.el-cascader__tags .el-tag>span{-webkit-box-flex:1;-ms-flex:1;flex:1;overflow:hidden;text-overflow:ellipsis}.el-cascader__tags .el-tag .el-icon-close{-webkit-box-flex:0;-ms-flex:none;flex:none;background-color:#C0C4CC;color:#FFF}.el-cascader__tags .el-tag .el-icon-close:hover{background-color:#909399}.el-cascader__suggestion-panel{border-radius:4px}.el-cascader__suggestion-list{max-height:204px;margin:0;padding:6px 0;font-size:14px;color:#606266;text-align:center}.el-cascader__suggestion-item{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;-webkit-box-align:center;-ms-flex-align:center;align-items:center;height:34px;padding:0 15px;text-align:left;outline:0;cursor:pointer}.el-cascader__suggestion-item:focus,.el-cascader__suggestion-item:hover{background:#F5F7FA}.el-cascader__suggestion-item.is-checked{color:#FDA833;font-weight:700}.el-cascader__suggestion-item>span{margin-right:10px}.el-cascader__empty-text{margin:10px 0;color:#C0C4CC}.el-cascader__search-input{-webkit-box-flex:1;-ms-flex:1;flex:1;height:24px;min-width:60px;margin:2px 0 2px 15px;padding:0;color:#606266;border:none;outline:0;-webkit-box-sizing:border-box;box-sizing:border-box}.el-cascader__search-input::-webkit-input-placeholder{color:#C0C4CC}.el-cascader__search-input:-ms-input-placeholder{color:#C0C4CC}.el-cascader__search-input::-ms-input-placeholder{color:#C0C4CC}.el-cascader__search-input::placeholder{color:#C0C4CC}.el-color-predefine{display:-webkit-box;display:-ms-flexbox;display:flex;font-size:12px;margin-top:8px;width:280px}.el-color-predefine__colors{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-ms-flex:1;flex:1;-ms-flex-wrap:wrap;flex-wrap:wrap}.el-color-predefine__color-selector{margin:0 0 8px 8px;width:20px;height:20px;border-radius:4px;cursor:pointer}.el-color-predefine__color-selector:nth-child(10n+1){margin-left:0}.el-color-predefine__color-selector.selected{-webkit-box-shadow:0 0 3px 2px #FDA833;box-shadow:0 0 3px 2px #FDA833}.el-color-predefine__color-selector>div{display:-webkit-box;display:-ms-flexbox;display:flex;height:100%;border-radius:3px}.el-color-predefine__color-selector.is-alpha{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==)}.el-color-hue-slider{position:relative;-webkit-box-sizing:border-box;box-sizing:border-box;width:280px;height:12px;background-color:red;padding:0 2px}.el-color-hue-slider__bar{position:relative;background:-webkit-gradient(linear,left top,right top,from(red),color-stop(17%,#ff0),color-stop(33%,#0f0),color-stop(50%,#0ff),color-stop(67%,#00f),color-stop(83%,#f0f),to(red));background:linear-gradient(to right,red 0,#ff0 17%,#0f0 33%,#0ff 50%,#00f 67%,#f0f 83%,red 100%);height:100%}.el-color-hue-slider__thumb{position:absolute;cursor:pointer;-webkit-box-sizing:border-box;box-sizing:border-box;left:0;top:0;width:4px;height:100%;border-radius:1px;background:#fff;border:1px solid #f0f0f0;-webkit-box-shadow:0 0 2px rgba(0,0,0,.6);box-shadow:0 0 2px rgba(0,0,0,.6);z-index:1}.el-color-hue-slider.is-vertical{width:12px;height:180px;padding:2px 0}.el-color-hue-slider.is-vertical .el-color-hue-slider__bar{background:-webkit-gradient(linear,left top,left bottom,from(red),color-stop(17%,#ff0),color-stop(33%,#0f0),color-stop(50%,#0ff),color-stop(67%,#00f),color-stop(83%,#f0f),to(red));background:linear-gradient(to bottom,red 0,#ff0 17%,#0f0 33%,#0ff 50%,#00f 67%,#f0f 83%,red 100%)}.el-color-hue-slider.is-vertical .el-color-hue-slider__thumb{left:0;top:0;width:100%;height:4px}.el-color-svpanel{position:relative;width:280px;height:180px}.el-color-svpanel__black,.el-color-svpanel__white{position:absolute;top:0;left:0;right:0;bottom:0}.el-color-svpanel__white{background:-webkit-gradient(linear,left top,right top,from(#fff),to(rgba(255,255,255,0)));background:linear-gradient(to right,#fff,rgba(255,255,255,0))}.el-color-svpanel__black{background:-webkit-gradient(linear,left bottom,left top,from(#000),to(rgba(0,0,0,0)));background:linear-gradient(to top,#000,rgba(0,0,0,0))}.el-color-svpanel__cursor{position:absolute}.el-color-svpanel__cursor>div{cursor:head;width:4px;height:4px;-webkit-box-shadow:0 0 0 1.5px #fff,inset 0 0 1px 1px rgba(0,0,0,.3),0 0 1px 2px rgba(0,0,0,.4);box-shadow:0 0 0 1.5px #fff,inset 0 0 1px 1px rgba(0,0,0,.3),0 0 1px 2px rgba(0,0,0,.4);border-radius:50%;-webkit-transform:translate(-2px,-2px);transform:translate(-2px,-2px)}.el-color-alpha-slider{position:relative;-webkit-box-sizing:border-box;box-sizing:border-box;width:280px;height:12px;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==)}.el-color-alpha-slider__bar{position:relative;background:-webkit-gradient(linear,left top,right top,from(rgba(255,255,255,0)),to(white));background:linear-gradient(to right,rgba(255,255,255,0) 0,#fff 100%);height:100%}.el-color-alpha-slider__thumb{position:absolute;cursor:pointer;-webkit-box-sizing:border-box;box-sizing:border-box;left:0;top:0;width:4px;height:100%;border-radius:1px;background:#fff;border:1px solid #f0f0f0;-webkit-box-shadow:0 0 2px rgba(0,0,0,.6);box-shadow:0 0 2px rgba(0,0,0,.6);z-index:1}.el-color-alpha-slider.is-vertical{width:20px;height:180px}.el-color-alpha-slider.is-vertical .el-color-alpha-slider__bar{background:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,0)),to(white));background:linear-gradient(to bottom,rgba(255,255,255,0) 0,#fff 100%)}.el-color-alpha-slider.is-vertical .el-color-alpha-slider__thumb{left:0;top:0;width:100%;height:4px}.el-color-dropdown{width:300px}.el-color-dropdown__main-wrapper{margin-bottom:6px}.el-color-dropdown__main-wrapper::after{content:"";display:table;clear:both}.el-color-dropdown__btns{margin-top:6px;text-align:right}.el-color-dropdown__value{float:left;line-height:26px;font-size:12px;color:#000;width:160px}.el-color-dropdown__btn{border:1px solid #dcdcdc;color:#333;line-height:24px;border-radius:2px;padding:0 20px;cursor:pointer;background-color:transparent;outline:0;font-size:12px}.el-color-dropdown__btn[disabled]{color:#ccc;cursor:not-allowed}.el-color-dropdown__btn:hover{color:#FDA833;border-color:#FDA833}.el-color-dropdown__link-btn{cursor:pointer;color:#FDA833;text-decoration:none;padding:15px;font-size:12px}.el-color-dropdown__link-btn:hover{color:tint(primary,20%)}.el-color-picker{display:inline-block;position:relative;line-height:normal;height:40px}.el-color-picker.is-disabled .el-color-picker__trigger{cursor:not-allowed}.el-color-picker--medium{height:36px}.el-color-picker--medium .el-color-picker__trigger{height:36px;width:36px}.el-color-picker--medium .el-color-picker__mask{height:34px;width:34px}.el-color-picker--small{height:32px}.el-color-picker--small .el-color-picker__trigger{height:32px;width:32px}.el-color-picker--small .el-color-picker__mask{height:30px;width:30px}.el-color-picker--small .el-color-picker__empty,.el-color-picker--small .el-color-picker__icon{-webkit-transform:translate3d(-50%,-50%,0) scale(.8);transform:translate3d(-50%,-50%,0) scale(.8)}.el-color-picker--mini{height:28px}.el-color-picker--mini .el-color-picker__trigger{height:28px;width:28px}.el-color-picker--mini .el-color-picker__mask{height:26px;width:26px}.el-color-picker--mini .el-color-picker__empty,.el-color-picker--mini .el-color-picker__icon{-webkit-transform:translate3d(-50%,-50%,0) scale(.8);transform:translate3d(-50%,-50%,0) scale(.8)}.el-color-picker__mask{height:38px;width:38px;border-radius:4px;position:absolute;top:1px;left:1px;z-index:1;cursor:not-allowed;background-color:rgba(255,255,255,.7)}.el-color-picker__trigger{display:inline-block;-webkit-box-sizing:border-box;box-sizing:border-box;height:40px;width:40px;padding:4px;border:1px solid #e6e6e6;border-radius:4px;font-size:0;position:relative;cursor:pointer}.el-color-picker__color{position:relative;display:block;-webkit-box-sizing:border-box;box-sizing:border-box;border:1px solid #999;border-radius:2px;width:100%;height:100%;text-align:center}.el-color-picker__color.is-alpha{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==)}.el-color-picker__color-inner{position:absolute;left:0;top:0;right:0;bottom:0}.el-color-picker__empty,.el-color-picker__icon{top:50%;left:50%;font-size:12px;position:absolute}.el-color-picker__empty{color:#999;-webkit-transform:translate3d(-50%,-50%,0);transform:translate3d(-50%,-50%,0)}.el-color-picker__icon{display:inline-block;width:100%;-webkit-transform:translate3d(-50%,-50%,0);transform:translate3d(-50%,-50%,0);color:#FFF;text-align:center}.el-color-picker__panel{position:absolute;z-index:10;padding:6px;-webkit-box-sizing:content-box;box-sizing:content-box;background-color:#FFF;border:1px solid #EBEEF5;border-radius:4px;-webkit-box-shadow:0 2px 12px 0 rgba(0,0,0,.1);box-shadow:0 2px 12px 0 rgba(0,0,0,.1)}.el-textarea{position:relative;display:inline-block;width:100%;vertical-align:bottom;font-size:14px}.el-textarea__inner{display:block;resize:vertical;padding:5px 15px;line-height:1.5;-webkit-box-sizing:border-box;box-sizing:border-box;width:100%;font-size:inherit;color:#606266;background-color:#FFF;background-image:none;border:1px solid #DCDFE6;border-radius:4px;-webkit-transition:border-color .2s cubic-bezier(.645,.045,.355,1);transition:border-color .2s cubic-bezier(.645,.045,.355,1)}.el-textarea__inner::-webkit-input-placeholder{color:#C0C4CC}.el-textarea__inner:-ms-input-placeholder{color:#C0C4CC}.el-textarea__inner::-ms-input-placeholder{color:#C0C4CC}.el-textarea__inner::placeholder{color:#C0C4CC}.el-textarea__inner:hover{border-color:#C0C4CC}.el-textarea__inner:focus{outline:0;border-color:#FDA833}.el-textarea .el-input__count{color:#909399;background:#FFF;position:absolute;font-size:12px;bottom:5px;right:10px}.el-textarea.is-disabled .el-textarea__inner{background-color:#F5F7FA;border-color:#E4E7ED;color:#C0C4CC;cursor:not-allowed}.el-textarea.is-disabled .el-textarea__inner::-webkit-input-placeholder{color:#C0C4CC}.el-textarea.is-disabled .el-textarea__inner:-ms-input-placeholder{color:#C0C4CC}.el-textarea.is-disabled .el-textarea__inner::-ms-input-placeholder{color:#C0C4CC}.el-textarea.is-disabled .el-textarea__inner::placeholder{color:#C0C4CC}.el-textarea.is-exceed .el-textarea__inner{border-color:#F56C6C}.el-textarea.is-exceed .el-input__count{color:#F56C6C}.el-input{position:relative;font-size:14px;display:inline-block;width:100%}.el-input::-webkit-scrollbar{z-index:11;width:6px}.el-input::-webkit-scrollbar:horizontal{height:6px}.el-input::-webkit-scrollbar-thumb{border-radius:5px;width:6px;background:#b4bccc}.el-input::-webkit-scrollbar-corner{background:#fff}.el-input::-webkit-scrollbar-track{background:#fff}.el-input::-webkit-scrollbar-track-piece{background:#fff;width:6px}.el-input .el-input__clear{color:#C0C4CC;font-size:14px;cursor:pointer;-webkit-transition:color .2s cubic-bezier(.645,.045,.355,1);transition:color .2s cubic-bezier(.645,.045,.355,1)}.el-input .el-input__clear:hover{color:#909399}.el-input .el-input__count{height:100%;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;color:#909399;font-size:12px}.el-input .el-input__count .el-input__count-inner{background:#FFF;line-height:initial;display:inline-block;padding:0 5px}.el-input__inner{-webkit-appearance:none;background-color:#FFF;background-image:none;border-radius:4px;border:1px solid #DCDFE6;-webkit-box-sizing:border-box;box-sizing:border-box;color:#606266;display:inline-block;font-size:inherit;height:40px;line-height:40px;outline:0;padding:0 15px;-webkit-transition:border-color .2s cubic-bezier(.645,.045,.355,1);transition:border-color .2s cubic-bezier(.645,.045,.355,1);width:100%}.el-input__prefix,.el-input__suffix{position:absolute;top:0;-webkit-transition:all .3s;height:100%;color:#C0C4CC;text-align:center}.el-input__inner::-webkit-input-placeholder{color:#C0C4CC}.el-input__inner:-ms-input-placeholder{color:#C0C4CC}.el-input__inner::-ms-input-placeholder{color:#C0C4CC}.el-input__inner::placeholder{color:#C0C4CC}.el-input__inner:hover{border-color:#C0C4CC}.el-input.is-active .el-input__inner,.el-input__inner:focus{border-color:#FDA833;outline:0}.el-input__suffix{right:5px;transition:all .3s}.el-input__suffix-inner{pointer-events:all}.el-input__prefix{left:5px;transition:all .3s}.el-input__icon{height:100%;width:25px;text-align:center;-webkit-transition:all .3s;transition:all .3s;line-height:40px}.el-input__icon:after{content:'';height:100%;width:0;display:inline-block;vertical-align:middle}.el-input__validateIcon{pointer-events:none}.el-input.is-disabled .el-input__inner{background-color:#F5F7FA;border-color:#E4E7ED;color:#C0C4CC;cursor:not-allowed}.el-input.is-disabled .el-input__inner::-webkit-input-placeholder{color:#C0C4CC}.el-input.is-disabled .el-input__inner:-ms-input-placeholder{color:#C0C4CC}.el-input.is-disabled .el-input__inner::-ms-input-placeholder{color:#C0C4CC}.el-input.is-disabled .el-input__inner::placeholder{color:#C0C4CC}.el-input.is-disabled .el-input__icon{cursor:not-allowed}.el-link,.el-transfer-panel__filter .el-icon-circle-close{cursor:pointer}.el-input.is-exceed .el-input__inner{border-color:#F56C6C}.el-input.is-exceed .el-input__suffix .el-input__count{color:#F56C6C}.el-input--suffix .el-input__inner{padding-right:30px}.el-input--prefix .el-input__inner{padding-left:30px}.el-input--medium{font-size:14px}.el-input--medium .el-input__inner{height:36px;line-height:36px}.el-input--medium .el-input__icon{line-height:36px}.el-input--small{font-size:13px}.el-input--small .el-input__inner{height:32px;line-height:32px}.el-input--small .el-input__icon{line-height:32px}.el-input--mini{font-size:12px}.el-input--mini .el-input__inner{height:28px;line-height:28px}.el-input--mini .el-input__icon{line-height:28px}.el-input-group{line-height:normal;display:inline-table;width:100%;border-collapse:separate;border-spacing:0}.el-input-group>.el-input__inner{vertical-align:middle;display:table-cell}.el-input-group__append,.el-input-group__prepend{background-color:#F5F7FA;color:#909399;vertical-align:middle;display:table-cell;position:relative;border:1px solid #DCDFE6;border-radius:4px;padding:0 20px;width:1px;white-space:nowrap}.el-input-group--prepend .el-input__inner,.el-input-group__append{border-top-left-radius:0;border-bottom-left-radius:0}.el-input-group--append .el-input__inner,.el-input-group__prepend{border-top-right-radius:0;border-bottom-right-radius:0}.el-input-group__append:focus,.el-input-group__prepend:focus{outline:0}.el-input-group__append .el-button,.el-input-group__append .el-select,.el-input-group__prepend .el-button,.el-input-group__prepend .el-select{display:inline-block;margin:-10px -20px}.el-input-group__append button.el-button,.el-input-group__append div.el-select .el-input__inner,.el-input-group__append div.el-select:hover .el-input__inner,.el-input-group__prepend button.el-button,.el-input-group__prepend div.el-select .el-input__inner,.el-input-group__prepend div.el-select:hover .el-input__inner{border-color:transparent;background-color:transparent;color:inherit;border-top:0;border-bottom:0}.el-input-group__append .el-button,.el-input-group__append .el-input,.el-input-group__prepend .el-button,.el-input-group__prepend .el-input{font-size:inherit}.el-input-group__prepend{border-right:0}.el-input-group__append{border-left:0}.el-input-group--append .el-select .el-input.is-focus .el-input__inner,.el-input-group--prepend .el-select .el-input.is-focus .el-input__inner{border-color:transparent}.el-input__inner::-ms-clear{display:none;width:0;height:0}.el-transfer{font-size:14px}.el-transfer__buttons{display:inline-block;vertical-align:middle;padding:0 30px}.el-transfer__button{display:block;margin:0 auto;padding:10px;border-radius:50%;color:#FFF;background-color:#FDA833;font-size:0}.el-transfer__button.is-with-texts{border-radius:4px}.el-transfer__button.is-disabled,.el-transfer__button.is-disabled:hover{border:1px solid #DCDFE6;background-color:#F5F7FA;color:#C0C4CC}.el-transfer__button:first-child{margin-bottom:10px}.el-transfer__button:nth-child(2){margin:0}.el-transfer__button i,.el-transfer__button span{font-size:14px}.el-transfer__button [class*=el-icon-]+span{margin-left:0}.el-transfer-panel{border:1px solid #EBEEF5;border-radius:4px;overflow:hidden;background:#FFF;display:inline-block;vertical-align:middle;width:200px;max-height:100%;-webkit-box-sizing:border-box;box-sizing:border-box;position:relative}.el-transfer-panel__body{height:246px}.el-transfer-panel__body.is-with-footer{padding-bottom:40px}.el-transfer-panel__list{margin:0;padding:6px 0;list-style:none;height:246px;overflow:auto;-webkit-box-sizing:border-box;box-sizing:border-box}.el-transfer-panel__list.is-filterable{height:194px;padding-top:0}.el-transfer-panel__item{height:30px;line-height:30px;padding-left:15px;display:block}.el-transfer-panel__item+.el-transfer-panel__item{margin-left:0;display:block!important}.el-transfer-panel__item.el-checkbox{color:#606266}.el-transfer-panel__item:hover{color:#FDA833}.el-transfer-panel__item.el-checkbox .el-checkbox__label{width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:block;-webkit-box-sizing:border-box;box-sizing:border-box;padding-left:24px;line-height:30px}.el-transfer-panel__item .el-checkbox__input{position:absolute;top:8px}.el-transfer-panel__filter{text-align:center;margin:15px;-webkit-box-sizing:border-box;box-sizing:border-box;display:block;width:auto}.el-transfer-panel__filter .el-input__inner{height:32px;width:100%;font-size:12px;display:inline-block;-webkit-box-sizing:border-box;box-sizing:border-box;border-radius:16px;padding-right:10px;padding-left:30px}.el-transfer-panel__filter .el-input__icon{margin-left:5px}.el-transfer-panel .el-transfer-panel__header{height:40px;line-height:40px;background:#F5F7FA;margin:0;padding-left:15px;border-bottom:1px solid #EBEEF5;-webkit-box-sizing:border-box;box-sizing:border-box;color:#000}.el-transfer-panel .el-transfer-panel__header .el-checkbox{display:block;line-height:40px}.el-transfer-panel .el-transfer-panel__header .el-checkbox .el-checkbox__label{font-size:16px;color:#303133;font-weight:400}.el-transfer-panel .el-transfer-panel__header .el-checkbox .el-checkbox__label span{position:absolute;right:15px;color:#909399;font-size:12px;font-weight:400}.el-divider__text,.el-link{font-weight:500;font-size:14px}.el-transfer-panel .el-transfer-panel__footer{height:40px;background:#FFF;margin:0;padding:0;border-top:1px solid #EBEEF5;position:absolute;bottom:0;left:0;width:100%;z-index:1}.el-transfer-panel .el-transfer-panel__footer::after{display:inline-block;content:"";height:100%;vertical-align:middle}.el-container,.el-timeline-item__node{display:-webkit-box;display:-ms-flexbox}.el-transfer-panel .el-transfer-panel__footer .el-checkbox{padding-left:20px;color:#606266}.el-transfer-panel .el-transfer-panel__empty{margin:0;height:30px;line-height:30px;padding:6px 15px 0;color:#909399;text-align:center}.el-transfer-panel .el-checkbox__label{padding-left:8px}.el-transfer-panel .el-checkbox__inner{height:14px;width:14px;border-radius:3px}.el-transfer-panel .el-checkbox__inner::after{height:6px;width:3px;left:4px}.el-container{display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-flex:1;-ms-flex:1;flex:1;-ms-flex-preferred-size:auto;flex-basis:auto;-webkit-box-sizing:border-box;box-sizing:border-box;min-width:0}.el-container.is-vertical,.el-drawer{-webkit-box-orient:vertical;-webkit-box-direction:normal}.el-aside,.el-header{-webkit-box-sizing:border-box}.el-container.is-vertical{-ms-flex-direction:column;flex-direction:column}.el-header{padding:0 20px;box-sizing:border-box;-ms-flex-negative:0;flex-shrink:0}.el-aside{overflow:auto;box-sizing:border-box;-ms-flex-negative:0;flex-shrink:0}.el-footer,.el-main{-webkit-box-sizing:border-box}.el-main{display:block;-webkit-box-flex:1;-ms-flex:1;flex:1;-ms-flex-preferred-size:auto;flex-basis:auto;overflow:auto;box-sizing:border-box;padding:20px}.el-footer{padding:0 20px;box-sizing:border-box;-ms-flex-negative:0;flex-shrink:0}.el-timeline{margin:0;font-size:14px;list-style:none}.el-timeline .el-timeline-item:last-child .el-timeline-item__tail{display:none}.el-timeline-item{position:relative;padding-bottom:20px}.el-timeline-item__wrapper{position:relative;padding-left:28px;top:-3px}.el-timeline-item__tail{position:absolute;left:4px;height:100%;border-left:2px solid #E4E7ED}.el-timeline-item__icon{color:#FFF;font-size:13px}.el-timeline-item__node{position:absolute;background-color:#E4E7ED;border-radius:50%;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.el-image__error,.el-timeline-item__dot{display:-webkit-box;display:-ms-flexbox}.el-timeline-item__node--normal{left:-1px;width:12px;height:12px}.el-timeline-item__node--large{left:-2px;width:14px;height:14px}.el-timeline-item__node--primary{background-color:#FDA833}.el-timeline-item__node--success{background-color:#67C23A}.el-timeline-item__node--warning{background-color:#E6A23C}.el-timeline-item__node--danger{background-color:#F56C6C}.el-timeline-item__node--info{background-color:#909399}.el-timeline-item__dot{position:absolute;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.el-timeline-item__content{color:#303133}.el-timeline-item__timestamp{color:#909399;line-height:1;font-size:13px}.el-timeline-item__timestamp.is-top{margin-bottom:8px;padding-top:4px}.el-timeline-item__timestamp.is-bottom{margin-top:8px}.el-link{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;vertical-align:middle;position:relative;text-decoration:none;outline:0;padding:0}.el-link.is-underline:hover:after{content:"";position:absolute;left:0;right:0;height:0;bottom:0;border-bottom:1px solid #FDA833}.el-link.el-link--default:after,.el-link.el-link--primary.is-underline:hover:after,.el-link.el-link--primary:after{border-color:#FDA833}.el-link.is-disabled{cursor:not-allowed}.el-link [class*=el-icon-]+span{margin-left:5px}.el-link.el-link--default{color:#606266}.el-link.el-link--default:hover{color:#FDA833}.el-link.el-link--default.is-disabled{color:#C0C4CC}.el-link.el-link--primary{color:#FDA833}.el-link.el-link--primary:hover{color:rgb(253, 185, 92)}.el-link.el-link--primary.is-disabled{color:rgb(254, 212, 153)}.el-link.el-link--danger.is-underline:hover:after,.el-link.el-link--danger:after{border-color:#F56C6C}.el-link.el-link--danger{color:#F56C6C}.el-link.el-link--danger:hover{color:#f78989}.el-link.el-link--danger.is-disabled{color:#fab6b6}.el-link.el-link--success.is-underline:hover:after,.el-link.el-link--success:after{border-color:#67C23A}.el-link.el-link--success{color:#67C23A}.el-link.el-link--success:hover{color:#85ce61}.el-link.el-link--success.is-disabled{color:#b3e19d}.el-link.el-link--warning.is-underline:hover:after,.el-link.el-link--warning:after{border-color:#E6A23C}.el-link.el-link--warning{color:#E6A23C}.el-link.el-link--warning:hover{color:#ebb563}.el-link.el-link--warning.is-disabled{color:#f3d19e}.el-link.el-link--info.is-underline:hover:after,.el-link.el-link--info:after{border-color:#909399}.el-link.el-link--info{color:#909399}.el-link.el-link--info:hover{color:#a6a9ad}.el-link.el-link--info.is-disabled{color:#c8c9cc}.el-divider{background-color:#DCDFE6;position:relative}.el-divider--horizontal{display:block;height:1px;width:100%;margin:24px 0}.el-divider--vertical{display:inline-block;width:1px;height:1em;margin:0 8px;vertical-align:middle;position:relative}.el-divider__text{position:absolute;background-color:#FFF;padding:0 20px;color:#303133}.el-image__error,.el-image__placeholder{background:#F5F7FA}.el-divider__text.is-left{left:20px;-webkit-transform:translateY(-50%);transform:translateY(-50%)}.el-divider__text.is-center{left:50%;-webkit-transform:translateX(-50%) translateY(-50%);transform:translateX(-50%) translateY(-50%)}.el-divider__text.is-right{right:20px;-webkit-transform:translateY(-50%);transform:translateY(-50%)}.el-image__error,.el-image__inner,.el-image__placeholder{width:100%;height:100%}.el-image{position:relative;display:inline-block;overflow:hidden}.el-image__inner{vertical-align:top}.el-image__inner--center{position:relative;top:50%;left:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);display:block}.el-image__error{display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;font-size:14px;color:#C0C4CC;vertical-align:middle}.el-image__preview{cursor:pointer}.el-image-viewer__wrapper{position:fixed;top:0;right:0;bottom:0;left:0}.el-image-viewer__btn{position:absolute;z-index:1;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;border-radius:50%;opacity:.8;cursor:pointer;-webkit-box-sizing:border-box;box-sizing:border-box;user-select:none}.el-button,.el-checkbox{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}.el-image-viewer__close{top:40px;right:40px;width:40px;height:40px;font-size:40px}.el-image-viewer__canvas{width:100%;height:100%;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.el-image-viewer__actions{left:50%;bottom:30px;-webkit-transform:translateX(-50%);transform:translateX(-50%);width:282px;height:44px;padding:0 23px;background-color:#606266;border-color:#fff;border-radius:22px}.el-image-viewer__actions__inner{width:100%;height:100%;text-align:justify;cursor:default;font-size:23px;color:#fff;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-ms-flex-pack:distribute;justify-content:space-around}.el-image-viewer__next,.el-image-viewer__prev{top:50%;width:44px;height:44px;font-size:24px;color:#fff;background-color:#606266;border-color:#fff}.el-image-viewer__prev{-webkit-transform:translateY(-50%);transform:translateY(-50%);left:40px}.el-image-viewer__next{-webkit-transform:translateY(-50%);transform:translateY(-50%);right:40px;text-indent:2px}.el-image-viewer__mask{position:absolute;width:100%;height:100%;top:0;left:0;opacity:.5;background:#000}.viewer-fade-enter-active{-webkit-animation:viewer-fade-in .3s;animation:viewer-fade-in .3s}.viewer-fade-leave-active{-webkit-animation:viewer-fade-out .3s;animation:viewer-fade-out .3s}@-webkit-keyframes viewer-fade-in{0%{-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0);opacity:0}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1}}@keyframes viewer-fade-in{0%{-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0);opacity:0}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1}}@-webkit-keyframes viewer-fade-out{0%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1}100%{-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0);opacity:0}}@keyframes viewer-fade-out{0%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1}100%{-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0);opacity:0}}.el-button{display:inline-block;line-height:1;white-space:nowrap;cursor:pointer;background:#FFF;border:1px solid #DCDFE6;color:#606266;-webkit-appearance:none;text-align:center;-webkit-box-sizing:border-box;box-sizing:border-box;outline:0;margin:0;-webkit-transition:.1s;transition:.1s;font-weight:500;padding:12px 20px;font-size:14px;border-radius:4px}.el-button+.el-button{margin-left:10px}.el-button:focus,.el-button:hover{color:#FDA833;border-color:rgb(254, 229, 194);background-color:rgb(255, 246, 235)}.el-button:active{color:rgb(228, 151, 46);border-color:rgb(228, 151, 46);outline:0}.el-button::-moz-focus-inner{border:0}.el-button [class*=el-icon-]+span{margin-left:5px}.el-button.is-plain:focus,.el-button.is-plain:hover{background:#FFF;border-color:#FDA833;color:#FDA833}.el-button.is-active,.el-button.is-plain:active{color:rgb(228, 151, 46);border-color:rgb(228, 151, 46)}.el-button.is-plain:active{background:#FFF;outline:0}.el-button.is-disabled,.el-button.is-disabled:focus,.el-button.is-disabled:hover{color:#C0C4CC;cursor:not-allowed;background-image:none;background-color:#FFF;border-color:#EBEEF5}.el-button.is-disabled.el-button--text{background-color:transparent}.el-button.is-disabled.is-plain,.el-button.is-disabled.is-plain:focus,.el-button.is-disabled.is-plain:hover{background-color:#FFF;border-color:#EBEEF5;color:#C0C4CC}.el-button.is-loading{position:relative;pointer-events:none}.el-button.is-loading:before{pointer-events:none;content:'';position:absolute;left:-1px;top:-1px;right:-1px;bottom:-1px;border-radius:inherit;background-color:rgba(255,255,255,.35)}.el-button.is-round{border-radius:20px;padding:12px 23px}.el-button.is-circle{border-radius:50%;padding:12px}.el-button--primary{color:#FFF;background-color:#FDA833;border-color:#FDA833}.el-button--primary:focus,.el-button--primary:hover{background:rgb(253, 185, 92);border-color:rgb(253, 185, 92);color:#FFF}.el-button--primary.is-active,.el-button--primary:active{background:rgb(228, 151, 46);border-color:rgb(228, 151, 46);color:#FFF}.el-button--primary:active{outline:0}.el-button--primary.is-disabled,.el-button--primary.is-disabled:active,.el-button--primary.is-disabled:focus,.el-button--primary.is-disabled:hover{color:#FFF;background-color:rgb(254, 212, 153);border-color:rgb(254, 212, 153)}.el-button--primary.is-plain{color:#FDA833;background:rgb(255, 246, 235);border-color:rgb(254, 220, 173)}.el-button--primary.is-plain:focus,.el-button--primary.is-plain:hover{background:#FDA833;border-color:#FDA833;color:#FFF}.el-button--primary.is-plain:active{background:rgb(228, 151, 46);border-color:rgb(228, 151, 46);color:#FFF;outline:0}.el-button--primary.is-plain.is-disabled,.el-button--primary.is-plain.is-disabled:active,.el-button--primary.is-plain.is-disabled:focus,.el-button--primary.is-plain.is-disabled:hover{color:rgb(254, 203, 133);background-color:rgb(255, 246, 235);border-color:rgb(255, 238, 214)}.el-button--success{color:#FFF;background-color:#67C23A;border-color:#67C23A}.el-button--success:focus,.el-button--success:hover{background:#85ce61;border-color:#85ce61;color:#FFF}.el-button--success.is-active,.el-button--success:active{background:#5daf34;border-color:#5daf34;color:#FFF}.el-button--success:active{outline:0}.el-button--success.is-disabled,.el-button--success.is-disabled:active,.el-button--success.is-disabled:focus,.el-button--success.is-disabled:hover{color:#FFF;background-color:#b3e19d;border-color:#b3e19d}.el-button--success.is-plain{color:#67C23A;background:#f0f9eb;border-color:#c2e7b0}.el-button--success.is-plain:focus,.el-button--success.is-plain:hover{background:#67C23A;border-color:#67C23A;color:#FFF}.el-button--success.is-plain:active{background:#5daf34;border-color:#5daf34;color:#FFF;outline:0}.el-button--success.is-plain.is-disabled,.el-button--success.is-plain.is-disabled:active,.el-button--success.is-plain.is-disabled:focus,.el-button--success.is-plain.is-disabled:hover{color:#a4da89;background-color:#f0f9eb;border-color:#e1f3d8}.el-button--warning{color:#FFF;background-color:#E6A23C;border-color:#E6A23C}.el-button--warning:focus,.el-button--warning:hover{background:#ebb563;border-color:#ebb563;color:#FFF}.el-button--warning.is-active,.el-button--warning:active{background:#cf9236;border-color:#cf9236;color:#FFF}.el-button--warning:active{outline:0}.el-button--warning.is-disabled,.el-button--warning.is-disabled:active,.el-button--warning.is-disabled:focus,.el-button--warning.is-disabled:hover{color:#FFF;background-color:#f3d19e;border-color:#f3d19e}.el-button--warning.is-plain{color:#E6A23C;background:#fdf6ec;border-color:#f5dab1}.el-button--warning.is-plain:focus,.el-button--warning.is-plain:hover{background:#E6A23C;border-color:#E6A23C;color:#FFF}.el-button--warning.is-plain:active{background:#cf9236;border-color:#cf9236;color:#FFF;outline:0}.el-button--warning.is-plain.is-disabled,.el-button--warning.is-plain.is-disabled:active,.el-button--warning.is-plain.is-disabled:focus,.el-button--warning.is-plain.is-disabled:hover{color:#f0c78a;background-color:#fdf6ec;border-color:#faecd8}.el-button--danger{color:#FFF;background-color:#F56C6C;border-color:#F56C6C}.el-button--danger:focus,.el-button--danger:hover{background:#f78989;border-color:#f78989;color:#FFF}.el-button--danger.is-active,.el-button--danger:active{background:#dd6161;border-color:#dd6161;color:#FFF}.el-button--danger:active{outline:0}.el-button--danger.is-disabled,.el-button--danger.is-disabled:active,.el-button--danger.is-disabled:focus,.el-button--danger.is-disabled:hover{color:#FFF;background-color:#fab6b6;border-color:#fab6b6}.el-button--danger.is-plain{color:#F56C6C;background:#fef0f0;border-color:#fbc4c4}.el-button--danger.is-plain:focus,.el-button--danger.is-plain:hover{background:#F56C6C;border-color:#F56C6C;color:#FFF}.el-button--danger.is-plain:active{background:#dd6161;border-color:#dd6161;color:#FFF;outline:0}.el-button--danger.is-plain.is-disabled,.el-button--danger.is-plain.is-disabled:active,.el-button--danger.is-plain.is-disabled:focus,.el-button--danger.is-plain.is-disabled:hover{color:#f9a7a7;background-color:#fef0f0;border-color:#fde2e2}.el-button--info{color:#FFF;background-color:#909399;border-color:#909399}.el-button--info:focus,.el-button--info:hover{background:#a6a9ad;border-color:#a6a9ad;color:#FFF}.el-button--info.is-active,.el-button--info:active{background:#82848a;border-color:#82848a;color:#FFF}.el-button--info:active{outline:0}.el-button--info.is-disabled,.el-button--info.is-disabled:active,.el-button--info.is-disabled:focus,.el-button--info.is-disabled:hover{color:#FFF;background-color:#c8c9cc;border-color:#c8c9cc}.el-button--info.is-plain{color:#909399;background:#f4f4f5;border-color:#d3d4d6}.el-button--info.is-plain:focus,.el-button--info.is-plain:hover{background:#909399;border-color:#909399;color:#FFF}.el-button--info.is-plain:active{background:#82848a;border-color:#82848a;color:#FFF;outline:0}.el-button--info.is-plain.is-disabled,.el-button--info.is-plain.is-disabled:active,.el-button--info.is-plain.is-disabled:focus,.el-button--info.is-plain.is-disabled:hover{color:#bcbec2;background-color:#f4f4f5;border-color:#e9e9eb}.el-button--text,.el-button--text.is-disabled,.el-button--text.is-disabled:focus,.el-button--text.is-disabled:hover,.el-button--text:active{border-color:transparent}.el-button--medium{padding:10px 20px;font-size:14px;border-radius:4px}.el-button--mini,.el-button--small{font-size:12px;border-radius:3px}.el-button--medium.is-round{padding:10px 20px}.el-button--medium.is-circle{padding:10px}.el-button--small,.el-button--small.is-round{padding:9px 15px}.el-button--small.is-circle{padding:9px}.el-button--mini,.el-button--mini.is-round{padding:7px 15px}.el-button--mini.is-circle{padding:7px}.el-button--text{color:#FDA833;background:0 0;padding-left:0;padding-right:0}.el-button--text:focus,.el-button--text:hover{color:rgb(253, 185, 92);border-color:transparent;background-color:transparent}.el-button--text:active{color:rgb(228, 151, 46);background-color:transparent}.el-button-group{display:inline-block;vertical-align:middle}.el-button-group::after,.el-button-group::before{display:table;content:""}.el-button-group::after{clear:both}.el-button-group>.el-button{float:left;position:relative}.el-button-group>.el-button+.el-button{margin-left:0}.el-button-group>.el-button.is-disabled{z-index:1}.el-button-group>.el-button:first-child{border-top-right-radius:0;border-bottom-right-radius:0}.el-button-group>.el-button:last-child{border-top-left-radius:0;border-bottom-left-radius:0}.el-button-group>.el-button:first-child:last-child{border-radius:4px}.el-button-group>.el-button:first-child:last-child.is-round{border-radius:20px}.el-button-group>.el-button:first-child:last-child.is-circle{border-radius:50%}.el-button-group>.el-button:not(:first-child):not(:last-child){border-radius:0}.el-button-group>.el-button:not(:last-child){margin-right:-1px}.el-button-group>.el-button.is-active,.el-button-group>.el-button:active,.el-button-group>.el-button:focus,.el-button-group>.el-button:hover{z-index:1}.el-button-group>.el-dropdown>.el-button{border-top-left-radius:0;border-bottom-left-radius:0;border-left-color:rgba(255,255,255,.5)}.el-button-group .el-button--primary:first-child{border-right-color:rgba(255,255,255,.5)}.el-button-group .el-button--primary:last-child{border-left-color:rgba(255,255,255,.5)}.el-button-group .el-button--primary:not(:first-child):not(:last-child){border-left-color:rgba(255,255,255,.5);border-right-color:rgba(255,255,255,.5)}.el-button-group .el-button--success:first-child{border-right-color:rgba(255,255,255,.5)}.el-button-group .el-button--success:last-child{border-left-color:rgba(255,255,255,.5)}.el-button-group .el-button--success:not(:first-child):not(:last-child){border-left-color:rgba(255,255,255,.5);border-right-color:rgba(255,255,255,.5)}.el-button-group .el-button--warning:first-child{border-right-color:rgba(255,255,255,.5)}.el-button-group .el-button--warning:last-child{border-left-color:rgba(255,255,255,.5)}.el-button-group .el-button--warning:not(:first-child):not(:last-child){border-left-color:rgba(255,255,255,.5);border-right-color:rgba(255,255,255,.5)}.el-button-group .el-button--danger:first-child{border-right-color:rgba(255,255,255,.5)}.el-button-group .el-button--danger:last-child{border-left-color:rgba(255,255,255,.5)}.el-button-group .el-button--danger:not(:first-child):not(:last-child){border-left-color:rgba(255,255,255,.5);border-right-color:rgba(255,255,255,.5)}.el-button-group .el-button--info:first-child{border-right-color:rgba(255,255,255,.5)}.el-button-group .el-button--info:last-child{border-left-color:rgba(255,255,255,.5)}.el-button-group .el-button--info:not(:first-child):not(:last-child){border-left-color:rgba(255,255,255,.5);border-right-color:rgba(255,255,255,.5)}.el-calendar{background-color:#fff}.el-calendar__header{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;padding:12px 20px;border-bottom:1px solid #EBEEF5}.el-backtop,.el-page-header{display:-webkit-box;display:-ms-flexbox}.el-calendar__title{color:#000;-ms-flex-item-align:center;align-self:center}.el-calendar__body{padding:12px 20px 35px}.el-calendar-table{table-layout:fixed;width:100%}.el-calendar-table thead th{padding:12px 0;color:#606266;font-weight:400}.el-calendar-table:not(.is-range) td.next,.el-calendar-table:not(.is-range) td.prev{color:#C0C4CC}.el-backtop,.el-calendar-table td.is-today{color:#FDA833}.el-calendar-table td{border-bottom:1px solid #EBEEF5;border-right:1px solid #EBEEF5;vertical-align:top;-webkit-transition:background-color .2s ease;transition:background-color .2s ease}.el-calendar-table td.is-selected{background-color:#F2F8FE}.el-calendar-table tr:first-child td{border-top:1px solid #EBEEF5}.el-calendar-table tr td:first-child{border-left:1px solid #EBEEF5}.el-calendar-table tr.el-calendar-table__row--hide-border td{border-top:none}.el-calendar-table .el-calendar-day{-webkit-box-sizing:border-box;box-sizing:border-box;padding:8px;height:85px}.el-calendar-table .el-calendar-day:hover{cursor:pointer;background-color:#F2F8FE}.el-backtop{position:fixed;background-color:#FFF;width:40px;height:40px;border-radius:50%;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;font-size:20px;-webkit-box-shadow:0 0 6px rgba(0,0,0,.12);box-shadow:0 0 6px rgba(0,0,0,.12);cursor:pointer;z-index:5}.el-backtop:hover{background-color:#F2F6FC}.el-page-header{display:flex;line-height:24px}.el-page-header__left{display:-webkit-box;display:-ms-flexbox;display:flex;cursor:pointer;margin-right:40px;position:relative}.el-page-header__left::after{content:"";position:absolute;width:1px;height:16px;right:-20px;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%);background-color:#DCDFE6}.el-checkbox,.el-checkbox__input{display:inline-block;position:relative;white-space:nowrap}.el-page-header__left .el-icon-back{font-size:18px;margin-right:6px;-ms-flex-item-align:center;align-self:center}.el-page-header__title{font-size:14px;font-weight:500}.el-page-header__content{font-size:18px;color:#303133}.el-checkbox{color:#606266;font-weight:500;font-size:14px;cursor:pointer;user-select:none;margin-right:30px}.el-checkbox-button__inner,.el-radio{font-weight:500;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none}.el-checkbox.is-bordered{padding:9px 20px 9px 10px;border-radius:4px;border:1px solid #DCDFE6;-webkit-box-sizing:border-box;box-sizing:border-box;line-height:normal;height:40px}.el-checkbox.is-bordered.is-checked{border-color:#FDA833}.el-checkbox.is-bordered.is-disabled{border-color:#EBEEF5;cursor:not-allowed}.el-checkbox.is-bordered+.el-checkbox.is-bordered{margin-left:10px}.el-checkbox.is-bordered.el-checkbox--medium{padding:7px 20px 7px 10px;border-radius:4px;height:36px}.el-checkbox.is-bordered.el-checkbox--medium .el-checkbox__label{line-height:17px;font-size:14px}.el-checkbox.is-bordered.el-checkbox--medium .el-checkbox__inner{height:14px;width:14px}.el-checkbox.is-bordered.el-checkbox--small{padding:5px 15px 5px 10px;border-radius:3px;height:32px}.el-checkbox.is-bordered.el-checkbox--small .el-checkbox__label{line-height:15px;font-size:12px}.el-checkbox.is-bordered.el-checkbox--small .el-checkbox__inner{height:12px;width:12px}.el-checkbox.is-bordered.el-checkbox--small .el-checkbox__inner::after{height:6px;width:2px}.el-checkbox.is-bordered.el-checkbox--mini{padding:3px 15px 3px 10px;border-radius:3px;height:28px}.el-checkbox.is-bordered.el-checkbox--mini .el-checkbox__label{line-height:12px;font-size:12px}.el-checkbox.is-bordered.el-checkbox--mini .el-checkbox__inner{height:12px;width:12px}.el-checkbox.is-bordered.el-checkbox--mini .el-checkbox__inner::after{height:6px;width:2px}.el-checkbox__input{cursor:pointer;outline:0;line-height:1;vertical-align:middle}.el-checkbox__input.is-disabled .el-checkbox__inner{background-color:#edf2fc;border-color:#DCDFE6;cursor:not-allowed}.el-checkbox__input.is-disabled .el-checkbox__inner::after{cursor:not-allowed;border-color:#C0C4CC}.el-checkbox__input.is-disabled .el-checkbox__inner+.el-checkbox__label{cursor:not-allowed}.el-checkbox__input.is-disabled.is-checked .el-checkbox__inner{background-color:#F2F6FC;border-color:#DCDFE6}.el-checkbox__input.is-disabled.is-checked .el-checkbox__inner::after{border-color:#C0C4CC}.el-checkbox__input.is-disabled.is-indeterminate .el-checkbox__inner{background-color:#F2F6FC;border-color:#DCDFE6}.el-checkbox__input.is-disabled.is-indeterminate .el-checkbox__inner::before{background-color:#C0C4CC;border-color:#C0C4CC}.el-checkbox__input.is-checked .el-checkbox__inner,.el-checkbox__input.is-indeterminate .el-checkbox__inner{background-color:#FDA833;border-color:#FDA833}.el-checkbox__input.is-disabled+span.el-checkbox__label{color:#C0C4CC;cursor:not-allowed}.el-checkbox__input.is-checked .el-checkbox__inner::after{-webkit-transform:rotate(45deg) scaleY(1);transform:rotate(45deg) scaleY(1)}.el-checkbox__input.is-checked+.el-checkbox__label{color:#FDA833}.el-checkbox__input.is-focus .el-checkbox__inner{border-color:#FDA833}.el-checkbox__input.is-indeterminate .el-checkbox__inner::before{content:'';position:absolute;display:block;background-color:#FFF;height:2px;-webkit-transform:scale(.5);transform:scale(.5);left:0;right:0;top:5px}.el-checkbox__input.is-indeterminate .el-checkbox__inner::after{display:none}.el-checkbox__inner{display:inline-block;position:relative;border:1px solid #DCDFE6;border-radius:2px;-webkit-box-sizing:border-box;box-sizing:border-box;width:14px;height:14px;background-color:#FFF;z-index:1;-webkit-transition:border-color .25s cubic-bezier(.71,-.46,.29,1.46),background-color .25s cubic-bezier(.71,-.46,.29,1.46);transition:border-color .25s cubic-bezier(.71,-.46,.29,1.46),background-color .25s cubic-bezier(.71,-.46,.29,1.46)}.el-checkbox__inner:hover{border-color:#FDA833}.el-checkbox__inner::after{-webkit-box-sizing:content-box;box-sizing:content-box;content:"";border:1px solid #FFF;border-left:0;border-top:0;height:7px;left:4px;position:absolute;top:1px;-webkit-transform:rotate(45deg) scaleY(0);transform:rotate(45deg) scaleY(0);width:3px;-webkit-transition:-webkit-transform .15s ease-in .05s;transition:-webkit-transform .15s ease-in .05s;transition:transform .15s ease-in .05s;transition:transform .15s ease-in .05s,-webkit-transform .15s ease-in .05s;-webkit-transform-origin:center;transform-origin:center}.el-checkbox__original{opacity:0;outline:0;position:absolute;margin:0;width:0;height:0;z-index:-1}.el-checkbox-button,.el-checkbox-button__inner{display:inline-block;position:relative}.el-checkbox__label{display:inline-block;padding-left:10px;line-height:19px;font-size:14px}.el-checkbox:last-of-type{margin-right:0}.el-checkbox-button__inner{line-height:1;white-space:nowrap;vertical-align:middle;cursor:pointer;background:#FFF;border:1px solid #DCDFE6;border-left:0;color:#606266;-webkit-appearance:none;text-align:center;-webkit-box-sizing:border-box;box-sizing:border-box;outline:0;margin:0;-webkit-transition:all .3s cubic-bezier(.645,.045,.355,1);transition:all .3s cubic-bezier(.645,.045,.355,1);padding:12px 20px;font-size:14px;border-radius:0}.el-checkbox-button__inner.is-round{padding:12px 20px}.el-checkbox-button__inner:hover{color:#FDA833}.el-checkbox-button__inner [class*=el-icon-]{line-height:.9}.el-radio,.el-radio__input{line-height:1;outline:0;white-space:nowrap}.el-checkbox-button__inner [class*=el-icon-]+span{margin-left:5px}.el-checkbox-button__original{opacity:0;outline:0;position:absolute;margin:0;z-index:-1}.el-radio,.el-radio__inner,.el-radio__input{position:relative;display:inline-block}.el-checkbox-button.is-checked .el-checkbox-button__inner{color:#FFF;background-color:#FDA833;border-color:#FDA833;-webkit-box-shadow:-1px 0 0 0 rgb(254, 203, 133);box-shadow:-1px 0 0 0 rgb(254, 203, 133)}.el-checkbox-button.is-checked:first-child .el-checkbox-button__inner{border-left-color:#FDA833}.el-checkbox-button.is-disabled .el-checkbox-button__inner{color:#C0C4CC;cursor:not-allowed;background-image:none;background-color:#FFF;border-color:#EBEEF5;-webkit-box-shadow:none;box-shadow:none}.el-checkbox-button.is-disabled:first-child .el-checkbox-button__inner{border-left-color:#EBEEF5}.el-checkbox-button:first-child .el-checkbox-button__inner{border-left:1px solid #DCDFE6;border-radius:4px 0 0 4px;-webkit-box-shadow:none!important;box-shadow:none!important}.el-checkbox-button.is-focus .el-checkbox-button__inner{border-color:#FDA833}.el-checkbox-button:last-child .el-checkbox-button__inner{border-radius:0 4px 4px 0}.el-checkbox-button--medium .el-checkbox-button__inner{padding:10px 20px;font-size:14px;border-radius:0}.el-checkbox-button--medium .el-checkbox-button__inner.is-round{padding:10px 20px}.el-checkbox-button--small .el-checkbox-button__inner{padding:9px 15px;font-size:12px;border-radius:0}.el-checkbox-button--small .el-checkbox-button__inner.is-round{padding:9px 15px}.el-checkbox-button--mini .el-checkbox-button__inner{padding:7px 15px;font-size:12px;border-radius:0}.el-checkbox-button--mini .el-checkbox-button__inner.is-round{padding:7px 15px}.el-checkbox-group{font-size:0}.el-radio,.el-radio--medium.is-bordered .el-radio__label{font-size:14px}.el-radio{color:#606266;cursor:pointer;margin-right:30px}.el-cascader-node>.el-radio,.el-radio:last-child{margin-right:0}.el-radio.is-bordered{padding:12px 20px 0 10px;border-radius:4px;border:1px solid #DCDFE6;-webkit-box-sizing:border-box;box-sizing:border-box;height:40px}.el-radio.is-bordered.is-checked{border-color:#FDA833}.el-radio.is-bordered.is-disabled{cursor:not-allowed;border-color:#EBEEF5}.el-radio__input.is-disabled .el-radio__inner,.el-radio__input.is-disabled.is-checked .el-radio__inner{background-color:#F5F7FA;border-color:#E4E7ED}.el-radio.is-bordered+.el-radio.is-bordered{margin-left:10px}.el-radio--medium.is-bordered{padding:10px 20px 0 10px;border-radius:4px;height:36px}.el-radio--mini.is-bordered .el-radio__label,.el-radio--small.is-bordered .el-radio__label{font-size:12px}.el-radio--medium.is-bordered .el-radio__inner{height:14px;width:14px}.el-radio--small.is-bordered{padding:8px 15px 0 10px;border-radius:3px;height:32px}.el-radio--small.is-bordered .el-radio__inner{height:12px;width:12px}.el-radio--mini.is-bordered{padding:6px 15px 0 10px;border-radius:3px;height:28px}.el-radio--mini.is-bordered .el-radio__inner{height:12px;width:12px}.el-radio__input{cursor:pointer;vertical-align:middle}.el-radio__input.is-disabled .el-radio__inner{cursor:not-allowed}.el-radio__input.is-disabled .el-radio__inner::after{cursor:not-allowed;background-color:#F5F7FA}.el-radio__input.is-disabled .el-radio__inner+.el-radio__label{cursor:not-allowed}.el-radio__input.is-disabled.is-checked .el-radio__inner::after{background-color:#C0C4CC}.el-radio__input.is-disabled+span.el-radio__label{color:#C0C4CC;cursor:not-allowed}.el-radio__input.is-checked .el-radio__inner{border-color:#FDA833;background:#FDA833}.el-radio__input.is-checked .el-radio__inner::after{-webkit-transform:translate(-50%,-50%) scale(1);transform:translate(-50%,-50%) scale(1)}.el-radio__input.is-checked+.el-radio__label{color:#FDA833}.el-radio__input.is-focus .el-radio__inner{border-color:#FDA833}.el-radio__inner{border:1px solid #DCDFE6;border-radius:100%;width:14px;height:14px;background-color:#FFF;cursor:pointer;-webkit-box-sizing:border-box;box-sizing:border-box}.el-radio__inner:hover{border-color:#FDA833}.el-radio__inner::after{width:4px;height:4px;border-radius:100%;background-color:#FFF;content:"";position:absolute;left:50%;top:50%;-webkit-transform:translate(-50%,-50%) scale(0);transform:translate(-50%,-50%) scale(0);-webkit-transition:-webkit-transform .15s ease-in;transition:-webkit-transform .15s ease-in;transition:transform .15s ease-in;transition:transform .15s ease-in,-webkit-transform .15s ease-in}.el-radio__original{opacity:0;outline:0;position:absolute;z-index:-1;top:0;left:0;right:0;bottom:0;margin:0}.el-radio:focus:not(.is-focus):not(:active):not(.is-disabled) .el-radio__inner{-webkit-box-shadow:0 0 2px 2px #FDA833;box-shadow:0 0 2px 2px #FDA833}.el-radio__label{font-size:14px;padding-left:10px}.el-scrollbar{overflow:hidden;position:relative}.el-scrollbar:active>.el-scrollbar__bar,.el-scrollbar:focus>.el-scrollbar__bar,.el-scrollbar:hover>.el-scrollbar__bar{opacity:1;-webkit-transition:opacity 340ms ease-out;transition:opacity 340ms ease-out}.el-scrollbar__wrap{overflow:scroll;height:100%}.el-scrollbar__wrap--hidden-default{scrollbar-width:none}.el-scrollbar__wrap--hidden-default::-webkit-scrollbar{width:0;height:0}.el-scrollbar__thumb{position:relative;display:block;width:0;height:0;cursor:pointer;border-radius:inherit;background-color:rgba(144,147,153,.3);-webkit-transition:.3s background-color;transition:.3s background-color}.el-scrollbar__thumb:hover{background-color:rgba(144,147,153,.5)}.el-scrollbar__bar{position:absolute;right:2px;bottom:2px;z-index:1;border-radius:4px;opacity:0;-webkit-transition:opacity 120ms ease-out;transition:opacity 120ms ease-out}.el-scrollbar__bar.is-vertical{width:6px;top:2px}.el-scrollbar__bar.is-vertical>div{width:100%}.el-scrollbar__bar.is-horizontal{height:6px;left:2px}.el-scrollbar__bar.is-horizontal>div{height:100%}.el-cascader-panel{display:-webkit-box;display:-ms-flexbox;display:flex;border-radius:4px;font-size:14px}.el-cascader-panel.is-bordered{border:1px solid #E4E7ED;border-radius:4px}.el-cascader-menu{min-width:180px;-webkit-box-sizing:border-box;box-sizing:border-box;color:#606266;border-right:solid 1px #E4E7ED}.el-cascader-menu:last-child{border-right:none}.el-cascader-menu:last-child .el-cascader-node{padding-right:20px}.el-cascader-menu__wrap{height:204px}.el-cascader-menu__list{position:relative;min-height:100%;margin:0;padding:6px 0;list-style:none;-webkit-box-sizing:border-box;box-sizing:border-box}.el-avatar,.el-drawer{-webkit-box-sizing:border-box;overflow:hidden}.el-cascader-menu__hover-zone{position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:none}.el-cascader-menu__empty-text{position:absolute;top:50%;left:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);text-align:center;color:#C0C4CC}.el-cascader-node{position:relative;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding:0 30px 0 20px;height:34px;line-height:34px;outline:0}.el-cascader-node.is-selectable.in-active-path{color:#606266}.el-cascader-node.in-active-path,.el-cascader-node.is-active,.el-cascader-node.is-selectable.in-checked-path{color:#FDA833;font-weight:700}.el-cascader-node:not(.is-disabled){cursor:pointer}.el-cascader-node:not(.is-disabled):focus,.el-cascader-node:not(.is-disabled):hover{background:#F5F7FA}.el-cascader-node.is-disabled{color:#C0C4CC;cursor:not-allowed}.el-cascader-node__prefix{position:absolute;left:10px}.el-cascader-node__postfix{position:absolute;right:10px}.el-cascader-node__label{-webkit-box-flex:1;-ms-flex:1;flex:1;padding:0 10px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.el-cascader-node>.el-radio .el-radio__label{padding-left:0}.el-avatar{display:inline-block;box-sizing:border-box;text-align:center;color:#fff;background:#C0C4CC;width:40px;height:40px;line-height:40px;font-size:14px}.el-avatar>img{display:block;height:100%;vertical-align:middle}.el-drawer,.el-drawer__header{display:-webkit-box;display:-ms-flexbox}.el-avatar--circle{border-radius:50%}.el-avatar--square{border-radius:4px}.el-avatar--icon{font-size:18px}.el-avatar--large{width:40px;height:40px;line-height:40px}.el-avatar--medium{width:36px;height:36px;line-height:36px}.el-avatar--small{width:28px;height:28px;line-height:28px}.el-drawer.btt,.el-drawer.ttb,.el-drawer__container{left:0;right:0;width:100%}.el-drawer.ltr,.el-drawer.rtl,.el-drawer__container{top:0;bottom:0;height:100%}@-webkit-keyframes el-drawer-fade-in{0%{opacity:0}100%{opacity:1}}@keyframes el-drawer-fade-in{0%{opacity:0}100%{opacity:1}}@-webkit-keyframes rtl-drawer-in{0%{-webkit-transform:translate(100%,0);transform:translate(100%,0)}100%{-webkit-transform:translate(0,0);transform:translate(0,0)}}@keyframes rtl-drawer-in{0%{-webkit-transform:translate(100%,0);transform:translate(100%,0)}100%{-webkit-transform:translate(0,0);transform:translate(0,0)}}@-webkit-keyframes rtl-drawer-out{0%{-webkit-transform:translate(0,0);transform:translate(0,0)}100%{-webkit-transform:translate(100%,0);transform:translate(100%,0)}}@keyframes rtl-drawer-out{0%{-webkit-transform:translate(0,0);transform:translate(0,0)}100%{-webkit-transform:translate(100%,0);transform:translate(100%,0)}}@-webkit-keyframes ltr-drawer-in{0%{-webkit-transform:translate(-100%,0);transform:translate(-100%,0)}100%{-webkit-transform:translate(0,0);transform:translate(0,0)}}@keyframes ltr-drawer-in{0%{-webkit-transform:translate(-100%,0);transform:translate(-100%,0)}100%{-webkit-transform:translate(0,0);transform:translate(0,0)}}@-webkit-keyframes ltr-drawer-out{0%{-webkit-transform:translate(0,0);transform:translate(0,0)}100%{-webkit-transform:translate(-100%,0);transform:translate(-100%,0)}}@keyframes ltr-drawer-out{0%{-webkit-transform:translate(0,0);transform:translate(0,0)}100%{-webkit-transform:translate(-100%,0);transform:translate(-100%,0)}}@-webkit-keyframes ttb-drawer-in{0%{-webkit-transform:translate(0,-100%);transform:translate(0,-100%)}100%{-webkit-transform:translate(0,0);transform:translate(0,0)}}@keyframes ttb-drawer-in{0%{-webkit-transform:translate(0,-100%);transform:translate(0,-100%)}100%{-webkit-transform:translate(0,0);transform:translate(0,0)}}@-webkit-keyframes ttb-drawer-out{0%{-webkit-transform:translate(0,0);transform:translate(0,0)}100%{-webkit-transform:translate(0,-100%);transform:translate(0,-100%)}}@keyframes ttb-drawer-out{0%{-webkit-transform:translate(0,0);transform:translate(0,0)}100%{-webkit-transform:translate(0,-100%);transform:translate(0,-100%)}}@-webkit-keyframes btt-drawer-in{0%{-webkit-transform:translate(0,100%);transform:translate(0,100%)}100%{-webkit-transform:translate(0,0);transform:translate(0,0)}}@keyframes btt-drawer-in{0%{-webkit-transform:translate(0,100%);transform:translate(0,100%)}100%{-webkit-transform:translate(0,0);transform:translate(0,0)}}@-webkit-keyframes btt-drawer-out{0%{-webkit-transform:translate(0,0);transform:translate(0,0)}100%{-webkit-transform:translate(0,100%);transform:translate(0,100%)}}@keyframes btt-drawer-out{0%{-webkit-transform:translate(0,0);transform:translate(0,0)}100%{-webkit-transform:translate(0,100%);transform:translate(0,100%)}}.el-drawer{position:absolute;box-sizing:border-box;background-color:#FFF;display:flex;-ms-flex-direction:column;flex-direction:column;-webkit-box-shadow:0 8px 10px -5px rgba(0,0,0,.2),0 16px 24px 2px rgba(0,0,0,.14),0 6px 30px 5px rgba(0,0,0,.12);box-shadow:0 8px 10px -5px rgba(0,0,0,.2),0 16px 24px 2px rgba(0,0,0,.14),0 6px 30px 5px rgba(0,0,0,.12)}.el-drawer.rtl{-webkit-animation:rtl-drawer-out .3s;animation:rtl-drawer-out .3s;right:0}.el-drawer__open .el-drawer.rtl{-webkit-animation:rtl-drawer-in .3s 1ms;animation:rtl-drawer-in .3s 1ms}.el-drawer.ltr{-webkit-animation:ltr-drawer-out .3s;animation:ltr-drawer-out .3s;left:0}.el-drawer__open .el-drawer.ltr{-webkit-animation:ltr-drawer-in .3s 1ms;animation:ltr-drawer-in .3s 1ms}.el-drawer.ttb{-webkit-animation:ttb-drawer-out .3s;animation:ttb-drawer-out .3s;top:0}.el-drawer__open .el-drawer.ttb{-webkit-animation:ttb-drawer-in .3s 1ms;animation:ttb-drawer-in .3s 1ms}.el-drawer.btt{-webkit-animation:btt-drawer-out .3s;animation:btt-drawer-out .3s;bottom:0}.el-drawer__open .el-drawer.btt{-webkit-animation:btt-drawer-in .3s 1ms;animation:btt-drawer-in .3s 1ms}.el-drawer__wrapper{position:fixed;top:0;right:0;bottom:0;left:0;overflow:hidden;margin:0}.el-drawer__header{-webkit-box-align:center;-ms-flex-align:center;align-items:center;color:#72767b;display:flex;margin-bottom:32px;padding:20px 20px 0}.el-drawer__header>:first-child{-webkit-box-flex:1;-ms-flex:1;flex:1}.el-drawer__title{margin:0;-webkit-box-flex:1;-ms-flex:1;flex:1;line-height:inherit;font-size:1rem}.el-drawer__close-btn{border:none;cursor:pointer;font-size:20px;color:inherit;background-color:transparent}.el-drawer__body{-webkit-box-flex:1;-ms-flex:1;flex:1}.el-drawer__body>*{-webkit-box-sizing:border-box;box-sizing:border-box}.el-drawer__container{position:relative}.el-drawer-fade-enter-active{-webkit-animation:el-drawer-fade-in .3s;animation:el-drawer-fade-in .3s}.el-drawer-fade-leave-active{animation:el-drawer-fade-in .3s reverse}.el-popconfirm__main{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.el-popconfirm__icon{margin-right:5px}.el-popconfirm__action{text-align:right;margin:0} \ No newline at end of file diff --git a/orange-demo-single-web/src/components/DateRange/index.vue b/orange-demo-single-web/src/components/DateRange/index.vue new file mode 100644 index 00000000..f4dd2c0b --- /dev/null +++ b/orange-demo-single-web/src/components/DateRange/index.vue @@ -0,0 +1,305 @@ + + + + + diff --git a/orange-demo-single-web/src/components/Dialog/index.js b/orange-demo-single-web/src/components/Dialog/index.js new file mode 100644 index 00000000..0e5c545f --- /dev/null +++ b/orange-demo-single-web/src/components/Dialog/index.js @@ -0,0 +1,77 @@ +import $ from 'jquery'; +import Vue from 'vue'; +import router from '@/router'; +import store from '@/store'; + +window.jQuery = $; +const layer = require('layui-layer'); + +class Dialog { + /** + * 关闭弹窗 + * @param {*} index 要关闭的弹窗的index + */ + static close (index) { + layer.close(index); + } + /** + * 关闭所有弹窗 + */ + static closeAll () { + layer.closeAll(); + } + /** + * 打开弹窗 + * @param {*} title 弹窗标题 + * @param {*} component 弹窗内容的组件 + * @param {*} options 弹窗设置(详情请见layui官网) + * @param {*} params 弹窗组件参数 + */ + static show (title, component, options, params) { + return new Promise((resolve, reject) => { + let layerOptions = { + title: title, + type: 1, + skin: 'layer-dialog', + resize: false, + offset: 'auto', + zIndex: 1000, + index: 0, + contentDom: null + }; + + layerOptions = {...layerOptions, ...options}; + layerOptions.end = () => { + if (layerOptions.contentDom) document.body.removeChild(layerOptions.contentDom); + } + + let observer = { + cancel: function (isSuccess = false) { + layer.close(this.index); + if (isSuccess) { + resolve(); + } else { + reject(); + } + }, + index: -1 + } + layerOptions.cancel = () => { + reject(); + } + let dom = document.createElement('div'); + document.body.appendChild(dom); + let Content = Vue.extend(component); + let vueObj = new Content({router: router, store: store, propsData: params}); + vueObj.observer = observer; + vueObj.$mount(dom); + layerOptions.contentDom = vueObj.$el; + layerOptions.content = $(layerOptions.contentDom); + observer.index = layer.open(layerOptions); + }); + } +} + +Vue.prototype.$dialog = Dialog; + +export default Dialog; diff --git a/orange-demo-single-web/src/components/FilterBox/index.vue b/orange-demo-single-web/src/components/FilterBox/index.vue new file mode 100644 index 00000000..d7350358 --- /dev/null +++ b/orange-demo-single-web/src/components/FilterBox/index.vue @@ -0,0 +1,134 @@ + + + + + diff --git a/orange-demo-single-web/src/components/Hamburger/index.vue b/orange-demo-single-web/src/components/Hamburger/index.vue new file mode 100644 index 00000000..6df80299 --- /dev/null +++ b/orange-demo-single-web/src/components/Hamburger/index.vue @@ -0,0 +1,44 @@ + + + + + diff --git a/orange-demo-single-web/src/components/IconSelect/icon.json b/orange-demo-single-web/src/components/IconSelect/icon.json new file mode 100644 index 00000000..13f2f58b --- /dev/null +++ b/orange-demo-single-web/src/components/IconSelect/icon.json @@ -0,0 +1,280 @@ +[ + "el-icon-delete-solid", + "el-icon-delete", + "el-icon-s-tools", + "el-icon-setting", + "el-icon-user-solid", + "el-icon-user", + "el-icon-phone", + "el-icon-phone-outline", + "el-icon-more", + "el-icon-more-outline", + "el-icon-star-on", + "el-icon-star-off", + "el-icon-s-goods", + "el-icon-goods", + "el-icon-warning", + "el-icon-warning-outline", + "el-icon-question", + "el-icon-info", + "el-icon-remove", + "el-icon-circle-plus", + "el-icon-success", + "el-icon-error", + "el-icon-zoom-in", + "el-icon-zoom-out", + "el-icon-remove-outline", + "el-icon-circle-plus-outline", + "el-icon-circle-check", + "el-icon-circle-close", + "el-icon-s-help", + "el-icon-help", + "el-icon-minus", + "el-icon-plus", + "el-icon-check", + "el-icon-close", + "el-icon-picture", + "el-icon-picture-outline", + "el-icon-picture-outline-round", + "el-icon-upload", + "el-icon-upload2", + "el-icon-download", + "el-icon-camera-solid", + "el-icon-camera", + "el-icon-video-camera-solid", + "el-icon-video-camera", + "el-icon-message-solid", + "el-icon-bell", + "el-icon-s-cooperation", + "el-icon-s-order", + "el-icon-s-platform", + "el-icon-s-fold", + "el-icon-s-unfold", + "el-icon-s-operation", + "el-icon-s-promotion", + "el-icon-s-home", + "el-icon-s-release", + "el-icon-s-ticket", + "el-icon-s-management", + "el-icon-s-open", + "el-icon-s-shop", + "el-icon-s-marketing", + "el-icon-s-flag", + "el-icon-s-comment", + "el-icon-s-finance", + "el-icon-s-claim", + "el-icon-s-custom", + "el-icon-s-opportunity", + "el-icon-s-data", + "el-icon-s-check", + "el-icon-s-grid", + "el-icon-menu", + "el-icon-share", + "el-icon-d-caret", + "el-icon-caret-left", + "el-icon-caret-right", + "el-icon-caret-bottom", + "el-icon-caret-top", + "el-icon-bottom-left", + "el-icon-bottom-right", + "el-icon-back", + "el-icon-right", + "el-icon-bottom", + "el-icon-top", + "el-icon-top-left", + "el-icon-top-right", + "el-icon-arrow-left", + "el-icon-arrow-right", + "el-icon-arrow-down", + "el-icon-arrow-up", + "el-icon-d-arrow-left", + "el-icon-d-arrow-right", + "el-icon-video-pause", + "el-icon-video-play", + "el-icon-refresh", + "el-icon-refresh-right", + "el-icon-refresh-left", + "el-icon-finished", + "el-icon-sort", + "el-icon-sort-up", + "el-icon-sort-down", + "el-icon-rank", + "el-icon-loading", + "el-icon-view", + "el-icon-c-scale-to-original", + "el-icon-date", + "el-icon-edit", + "el-icon-edit-outline", + "el-icon-folder", + "el-icon-folder-opened", + "el-icon-folder-add", + "el-icon-folder-remove", + "el-icon-folder-delete", + "el-icon-folder-checked", + "el-icon-tickets", + "el-icon-document-remove", + "el-icon-document-delete", + "el-icon-document-copy", + "el-icon-document-checked", + "el-icon-document", + "el-icon-document-add", + "el-icon-printer", + "el-icon-paperclip", + "el-icon-takeaway-box", + "el-icon-search", + "el-icon-monitor", + "el-icon-attract", + "el-icon-mobile", + "el-icon-scissors", + "el-icon-umbrella", + "el-icon-headset", + "el-icon-brush", + "el-icon-mouse", + "el-icon-coordinate", + "el-icon-magic-stick", + "el-icon-reading", + "el-icon-data-line", + "el-icon-data-board", + "el-icon-pie-chart", + "el-icon-data-analysis", + "el-icon-collection-tag", + "el-icon-film", + "el-icon-suitcase", + "el-icon-suitcase-1", + "el-icon-receiving", + "el-icon-collection", + "el-icon-files", + "el-icon-notebook-1", + "el-icon-notebook-2", + "el-icon-toilet-paper", + "el-icon-office-building", + "el-icon-school", + "el-icon-table-lamp", + "el-icon-house", + "el-icon-no-smoking", + "el-icon-smoking", + "el-icon-shopping-cart-full", + "el-icon-shopping-cart-1", + "el-icon-shopping-cart-2", + "el-icon-shopping-bag-1", + "el-icon-shopping-bag-2", + "el-icon-sold-out", + "el-icon-sell", + "el-icon-present", + "el-icon-box", + "el-icon-bank-card", + "el-icon-money", + "el-icon-coin", + "el-icon-wallet", + "el-icon-discount", + "el-icon-price-tag", + "el-icon-news", + "el-icon-guide", + "el-icon-male", + "el-icon-female", + "el-icon-thumb", + "el-icon-cpu", + "el-icon-link", + "el-icon-connection", + "el-icon-open", + "el-icon-turn-off", + "el-icon-set-up", + "el-icon-chat-round", + "el-icon-chat-line-round", + "el-icon-chat-square", + "el-icon-chat-dot-round", + "el-icon-chat-dot-square", + "el-icon-chat-line-square", + "el-icon-message", + "el-icon-postcard", + "el-icon-position", + "el-icon-turn-off-microphone", + "el-icon-microphone", + "el-icon-close-notification", + "el-icon-bangzhu", + "el-icon-time", + "el-icon-odometer", + "el-icon-crop", + "el-icon-aim", + "el-icon-switch-button", + "el-icon-full-screen", + "el-icon-copy-document", + "el-icon-mic", + "el-icon-stopwatch", + "el-icon-medal-1", + "el-icon-medal", + "el-icon-trophy", + "el-icon-trophy-1", + "el-icon-first-aid-kit", + "el-icon-discover", + "el-icon-place", + "el-icon-location", + "el-icon-location-outline", + "el-icon-location-information", + "el-icon-add-location", + "el-icon-delete-location", + "el-icon-map-location", + "el-icon-alarm-clock", + "el-icon-timer", + "el-icon-watch-1", + "el-icon-watch", + "el-icon-lock", + "el-icon-unlock", + "el-icon-key", + "el-icon-service", + "el-icon-mobile-phone", + "el-icon-bicycle", + "el-icon-truck", + "el-icon-ship", + "el-icon-basketball", + "el-icon-football", + "el-icon-soccer", + "el-icon-baseball", + "el-icon-wind-power", + "el-icon-light-rain", + "el-icon-lightning", + "el-icon-heavy-rain", + "el-icon-sunrise", + "el-icon-sunrise-1", + "el-icon-sunset", + "el-icon-sunny", + "el-icon-cloudy", + "el-icon-partly-cloudy", + "el-icon-cloudy-and-sunny", + "el-icon-moon", + "el-icon-moon-night", + "el-icon-dish", + "el-icon-dish-1", + "el-icon-food", + "el-icon-chicken", + "el-icon-fork-spoon", + "el-icon-knife-fork", + "el-icon-burger", + "el-icon-tableware", + "el-icon-sugar", + "el-icon-dessert", + "el-icon-ice-cream", + "el-icon-hot-water", + "el-icon-water-cup", + "el-icon-coffee-cup", + "el-icon-cold-drink", + "el-icon-goblet", + "el-icon-goblet-full", + "el-icon-goblet-square", + "el-icon-goblet-square-full", + "el-icon-refrigerator", + "el-icon-grape", + "el-icon-watermelon", + "el-icon-cherry", + "el-icon-apple", + "el-icon-pear", + "el-icon-orange", + "el-icon-coffee", + "el-icon-ice-tea", + "el-icon-ice-drink", + "el-icon-milk-tea", + "el-icon-potato-strips", + "el-icon-lollipop", + "el-icon-ice-cream-square", + "el-icon-ice-cream-round" +] \ No newline at end of file diff --git a/orange-demo-single-web/src/components/IconSelect/index.vue b/orange-demo-single-web/src/components/IconSelect/index.vue new file mode 100644 index 00000000..06be852b --- /dev/null +++ b/orange-demo-single-web/src/components/IconSelect/index.vue @@ -0,0 +1,104 @@ + + + + + diff --git a/orange-demo-single-web/src/components/InputNumberRange/index.vue b/orange-demo-single-web/src/components/InputNumberRange/index.vue new file mode 100644 index 00000000..94f59ba4 --- /dev/null +++ b/orange-demo-single-web/src/components/InputNumberRange/index.vue @@ -0,0 +1,226 @@ + + + + + diff --git a/orange-demo-single-web/src/components/Progress/index.vue b/orange-demo-single-web/src/components/Progress/index.vue new file mode 100644 index 00000000..2225e489 --- /dev/null +++ b/orange-demo-single-web/src/components/Progress/index.vue @@ -0,0 +1,44 @@ + + + diff --git a/orange-demo-single-web/src/components/RichEditor/index.vue b/orange-demo-single-web/src/components/RichEditor/index.vue new file mode 100644 index 00000000..d839a475 --- /dev/null +++ b/orange-demo-single-web/src/components/RichEditor/index.vue @@ -0,0 +1,129 @@ + + + + + diff --git a/orange-demo-single-web/src/components/TableProgressColumn/index.vue b/orange-demo-single-web/src/components/TableProgressColumn/index.vue new file mode 100644 index 00000000..7e82a4eb --- /dev/null +++ b/orange-demo-single-web/src/components/TableProgressColumn/index.vue @@ -0,0 +1,119 @@ + + + diff --git a/orange-demo-single-web/src/components/TreeSelect/index.vue b/orange-demo-single-web/src/components/TreeSelect/index.vue new file mode 100644 index 00000000..9099558f --- /dev/null +++ b/orange-demo-single-web/src/components/TreeSelect/index.vue @@ -0,0 +1,300 @@ + + + + + diff --git a/orange-demo-single-web/src/core/config/development.js b/orange-demo-single-web/src/core/config/development.js new file mode 100644 index 00000000..c866c9ed --- /dev/null +++ b/orange-demo-single-web/src/core/config/development.js @@ -0,0 +1,4 @@ +module.exports = { + baseUrl: 'http://localhost:8082/', + projectName: '橙单生成器项目' +} diff --git a/orange-demo-single-web/src/core/config/index.js b/orange-demo-single-web/src/core/config/index.js new file mode 100644 index 00000000..be8f130e --- /dev/null +++ b/orange-demo-single-web/src/core/config/index.js @@ -0,0 +1,12 @@ +const projectConfig = require('../config/' + process.env.NODE_ENV); + +export const globalConfig = { + httpOption: { + showMask: true, + showError: true + }, + axiosOption: { + } +}; + +export default projectConfig; diff --git a/orange-demo-single-web/src/core/config/production.js b/orange-demo-single-web/src/core/config/production.js new file mode 100644 index 00000000..c866c9ed --- /dev/null +++ b/orange-demo-single-web/src/core/config/production.js @@ -0,0 +1,4 @@ +module.exports = { + baseUrl: 'http://localhost:8082/', + projectName: '橙单生成器项目' +} diff --git a/orange-demo-single-web/src/core/directive/sortable.js b/orange-demo-single-web/src/core/directive/sortable.js new file mode 100644 index 00000000..410de2d9 --- /dev/null +++ b/orange-demo-single-web/src/core/directive/sortable.js @@ -0,0 +1,14 @@ +import Vue from 'vue' +import { SortableData } from './sortableData'; + +/** + * 拖拽排序指令 + */ +Vue.directive('sortable', { + inserted: function (el, binding, vnode) { + let sortableData = binding.value; + if (sortableData == null || !(sortableData instanceof SortableData)) return; + + sortableData.init(vnode.elm); + } +}); diff --git a/orange-demo-single-web/src/core/directive/sortableData.js b/orange-demo-single-web/src/core/directive/sortableData.js new file mode 100644 index 00000000..4993e08a --- /dev/null +++ b/orange-demo-single-web/src/core/directive/sortableData.js @@ -0,0 +1,60 @@ +import sortable from 'sortablejs' +/** + * 拖拽排序对象 + * expample + *
    + *
  • A
  • + *
  • B
  • + *
  • C
  • + *
  • D
  • + *
+ */ +export class SortableData { + constructor (data, group) { + this.list = data; + this.group = group; + this.ghostClass = 'sortable-ghost'; + this.sortable = null; + this.disabled = false; + }; + + setData (list) { + this.list = list; + } + + getElement (el) { + return el; + }; + + onEnd (oldIndex, newIndex) { + if (oldIndex === newIndex || this.list == null) return; + let targetRow = this.list.splice(oldIndex, 1)[0] + this.list.splice(newIndex, 0, targetRow); + }; + + init (el) { + var _this = this; + + var _option = {}; + if (this.ghostClass != null) _option.ghostClass = this.ghostClass; + if (this.group != null) _option.group = this.group; + if (this.disabled != null) _option.disabled = this.disabled; + // 列表中能拖动的dom的选择器(例如:.drag-item) + if (this.draggable != null) _option.draggable = this.draggable; + // 列表中拖动项,拖动把柄的选择器,只有点击这个选择出来的dom才可以开始拖动(例如:.drag-handle) + if (this.handle != null) _option.handle = this.handle; + _option.setData = function (dataTransfer) { + dataTransfer.setData('Text', ''); + }; + _option.onEnd = function (evt) { + _this.onEnd(evt.oldIndex, evt.newIndex); + }; + + this.sortable = sortable.create(_this.getElement(el), _option); + }; + + release () { + if (this.sortable != null) this.sortable.destroy(); + this.sortable = null; + } +}; diff --git a/orange-demo-single-web/src/core/http/index.js b/orange-demo-single-web/src/core/http/index.js new file mode 100644 index 00000000..ed4b2be0 --- /dev/null +++ b/orange-demo-single-web/src/core/http/index.js @@ -0,0 +1,185 @@ +import Vue from 'vue'; +import { Loading, Message } from 'element-ui'; +import request from './request'; +import requestUrl from './requestUrl'; +import merge from 'lodash/merge'; +import { globalConfig } from '@/core/config'; + +/** + * 遮罩管理,多次调用支持引用计数 + */ +class LoadingManager { + constructor (options) { + this.options = options; + this.refCount = 0; + this.loading = undefined; + } + + showMask () { + this.loading = Loading.service(this.options); + this.refCount++; + } + + hideMask () { + if (this.refCount <= 1 && this.loading != null) { + this.loading.close(); + this.loading = null; + } + this.refCount--; + this.refCount = Math.max(0, this.refCount); + } +} + +const loadingManager = new LoadingManager({ + fullscreen: true, + background: 'rgba(0, 0, 0, 0.1)' +}); + +/** + * post请求 + * @param {String} url 请求的url + * @param {Object} params 请求参数 + * @param {Object} options axios设置项 + * @returns {Promise} + */ +const fetchPost = function (url, params, options) { + if (options == null) return {}; + let tempOptions = { + ...options, + method: 'post', + url: requestUrl(url), + data: params + }; + + return request(tempOptions); +}; +/** + * get请求 + * @param {String} url 请求的url + * @param {Object} params 请求参数 + * @param {Object} options axios设置项 + * @returns {Promise} + */ +const fetchGet = function (url, params, options) { + if (options == null) return {}; + let tempOptions = { + ...options, + method: 'get', + url: requestUrl(url), + params + }; + return request(tempOptions); +}; +/** + * 下载请求 + * @param {String} url 请求的url + * @param {Object} params 请求参数 + * @param {String} fileName 下载后保存的文件名 + * @returns {Promise} + */ +const fetchDownload = function (url, params, fileName) { + return new Promise((resolve, reject) => { + request({ + url: requestUrl(url), + method: 'post', + data: params, + responseType: 'blob', + transformResponse: function (data) { + return (data instanceof Blob && data.size > 0) ? data : undefined; + } + }).then(res => { + if (res.data == null) { + reject(new Error('下载文件失败')); + } else { + let blobData = new Blob([res.data], { type: 'application/octet-stream' }); + let blobUrl = window.URL.createObjectURL(blobData); + let linkDom = document.createElement('a'); + linkDom.style.display = 'none'; + linkDom.href = blobUrl; + linkDom.setAttribute('download', fileName); + if (typeof linkDom.download === 'undefined') { + linkDom.setAttribute('target', '_blank'); + } + document.body.appendChild(linkDom); + linkDom.click(); + document.body.removeChild(linkDom); + window.URL.revokeObjectURL(blobData); + resolve(); + } + }).catch(e => { + if (e instanceof Blob) { + let reader = new FileReader(); + reader.onload = function () { + let jsonObj = JSON.parse(reader.result); + reject((jsonObj || {}).errorMessage || '下载文件失败'); + } + reader.readAsText(e); + } else { + reject(e); + } + }); + }); +} +/** + * 数据请求 + * @param {String} url 请求的url + * @param {String} type 请求类型(get,post) + * @param {Object} params 请求参数 + * @param {Object} axiosOption axios设置 + * @param {Object} options 显示设置 + */ +const doUrl = function (url, type, params, axiosOption, options) { + options = merge(globalConfig.httpOption, options); + axiosOption = merge(globalConfig.axiosOption, axiosOption); + if (type == null || type === '') type = 'post'; + + return new Promise((resolve, reject) => { + if (options.showMask) loadingManager.showMask(); + let ajaxCall = null; + if (type.toLowerCase() === 'get') { + ajaxCall = fetchGet(url, params, axiosOption); + } else if (type.toLowerCase() === 'post') { + ajaxCall = fetchPost(url, params, axiosOption); + } + + if (ajaxCall != null) { + ajaxCall.then(res => { + if (options.showMask) loadingManager.hideMask(); + if (res.data && res.data.success) { + resolve(res.data); + } else { + if (options.showError) { + Message.error({ + showClose: true, + message: res.data.errorMessage ? res.data.errorMessage : '数据请求失败' + }); + } + reject(res.data); + } + }).catch(e => { + if (options.showMask) loadingManager.hideMask(); + if (options.showError) { + Message.error({ + showClose: true, + message: e.errorMessage ? e.errorMessage : '网络请求错误' + }); + } + reject(e); + }); + } else { + if (options.showMask) loadingManager.hideMask(); + reject(new Error('错误的请求类型 - ' + type)); + } + }); +}; + +Vue.prototype.download = fetchDownload; +Vue.prototype.doUrl = doUrl; +Vue.prototype.loadingManager = loadingManager; + +export default { + doUrl, + fetchPost, + fetchGet, + fetchDownload +} diff --git a/orange-demo-single-web/src/core/http/request.js b/orange-demo-single-web/src/core/http/request.js new file mode 100644 index 00000000..939ed4ce --- /dev/null +++ b/orange-demo-single-web/src/core/http/request.js @@ -0,0 +1,73 @@ +import axios from 'axios'; +import router from '@/router'; +import dialog from '@/components/Dialog'; +import JSONbig from 'json-bigint'; + +// 创建axios实例 +const service = axios.create({ + timeout: 1000 * 30, + withCredentials: true, + headers: { + // 'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8' + 'Content-Type': 'application/json; charset=utf-8' + }, + transformResponse: [ + function (data) { + if (typeof data === 'string') { + const JSONbigString = new JSONbig({storeAsString: true}); + return JSONbigString.parse(data); + } else { + return data; + } + } + ] +}) + +// request拦截器 +service.interceptors.request.use( + config => { + let token = window.sessionStorage.getItem('token'); + let menuIdJsonStr = window.sessionStorage.getItem('currentMenuId'); + let currentMenuId; + if (menuIdJsonStr != null) { + currentMenuId = (JSON.parse(menuIdJsonStr) || {}).data; + } + if (token != null) config.headers['Authorization'] = token; + if (currentMenuId != null) config.headers['MenuId'] = currentMenuId; + return config + }, error => { + return Promise.reject(error) + } +); + +// response拦截器 +service.interceptors.response.use( + response => { + if (response.data && response.data.errorCode === 'UNAUTHORIZED_LOGIN') { // 401, token失效 + dialog.closeAll(); + router.push({ name: 'login' }) + } else { + if (response.headers['refreshedtoken'] != null) { + window.sessionStorage.setItem('token', response.headers['refreshedtoken']); + } + } + return response + }, error => { + let response = error.response; + + if (response && response.data) { + if (response.data.errorCode === 'UNAUTHORIZED_LOGIN') { + dialog.closeAll(); + router.push({ name: 'login' }); + } + + return Promise.reject(response.data); + } else { + return Promise.reject(new Error({ + errorMessage: '数据获取失败,请稍后再试' + })); + } + } +); + +export default service diff --git a/orange-demo-single-web/src/core/http/requestUrl.js b/orange-demo-single-web/src/core/http/requestUrl.js new file mode 100644 index 00000000..96a921e1 --- /dev/null +++ b/orange-demo-single-web/src/core/http/requestUrl.js @@ -0,0 +1,27 @@ +import projectConfig from '@/core/config'; +import { objectToQueryString } from '@/utils'; +console.log(process.env.NODE_ENV, projectConfig); + +/** + * 请求地址统一处理/组装 + * @param actionName action方法名称 + */ +export default function (actionName) { + if (actionName != null && actionName !== '') { + if (actionName.substr(0, 1) === '/') actionName = actionName.substr(1); + } + return projectConfig.baseUrl + actionName; +} + +export function buildGetUrl (actionName, params) { + let queryString = objectToQueryString(params); + if (actionName != null && actionName !== '') { + if (actionName.substr(0, 1) === '/') actionName = actionName.substr(1); + } + + return projectConfig.baseUrl + actionName + (queryString == null ? '' : ('?' + queryString)); +} + +export { + projectConfig +} diff --git a/orange-demo-single-web/src/core/mixins/global.js b/orange-demo-single-web/src/core/mixins/global.js new file mode 100644 index 00000000..eb756b40 --- /dev/null +++ b/orange-demo-single-web/src/core/mixins/global.js @@ -0,0 +1,117 @@ +import Vue from 'vue'; +import Request from '@/core/http/request.js'; +import { mapMutations, mapGetters } from 'vuex'; + +// 全局mixin对象 +const globalMixin = { + data () { + return { + isHttpLoading: false + } + }, + methods: { + /** + * 是否显示遮罩 + * @param {Boolean} isShow 是否显示 + */ + showMask (isShow) { + isShow ? this.loadingManager.showMask() : this.loadingManager.hideMask(); + }, + /** + * 判读用户是否有权限 + * @param {String} permCode 权限字 + */ + checkPermCodeExist (permCode) { + if (this.getUserInfo.permCodeSet != null) { + return this.getUserInfo.permCodeSet.has(permCode); + } else { + return this.getUserInfo.isAdmin; + } + }, + /** + * 将输入的值转换成指定的类型 + * @param {Any} value + * @param {String} type 要转换的类型(integer、float、boolean、string) + */ + parseParams (value, type = 'string') { + if (value == null) return value; + switch (type) { + case 'integer': return Number.parseInt(value); + case 'float': return Number.parseFloat(value); + case 'boolean': return (value === 'true' || value); + default: return String(value); + } + }, + /** + * 将输入值转换为执行的类型数组 + * @param {Array} value 输入数组 + * @param {String} type 要转换的类型(integer、float、boolean、string) + */ + parseArrayParams (value, type = 'string') { + if (Array.isArray(value)) { + return value.map((item) => { + switch (type) { + case 'integer': return Number.parseInt(item); + case 'float': return Number.parseFloat(item); + case 'boolean': return (item === 'true' || item); + default: return String(item); + } + }); + } else { + return []; + } + }, + /** + * 下载上传的文件 + * @param {*} url 下载文件的url + * @param {*} fileName 下载文件名 + */ + downloadFile (url, fileName) { + console.log(fileName); + Request({ + url: url, + method: 'get', + responseType: 'blob', + transformResponse: function (data) { + console.log(data); + return data; + } + }).then(res => { + console.log(res); + let data = res.data; + if (res.status === 200 && data instanceof Blob) { + let url = window.URL.createObjectURL(data); + let link = document.createElement('a'); + link.style.display = 'none'; + link.href = url; + link.setAttribute('download', fileName); + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + } else { + this.$message.error('下载文件失败'); + } + }).catch(e => { + let reader = new FileReader(); + reader.onload = () => { + let jsonObj = JSON.parse(reader.result); + this.$message.error((jsonObj || {}).errorMessage || '下载文件失败'); + } + reader.readAsText(e); + }); + }, + ...mapMutations(['setLoadingStatus']) + }, + computed: { + ...mapGetters(['getUserInfo']) + }, + watch: { + 'loadingManager.loading': { + handler: function (newValue) { + this.isHttpLoading = (newValue != null); + } + } + } +} + +Vue.mixin(globalMixin); diff --git a/orange-demo-single-web/src/core/mixins/index.js b/orange-demo-single-web/src/core/mixins/index.js new file mode 100644 index 00000000..8a18b8b2 --- /dev/null +++ b/orange-demo-single-web/src/core/mixins/index.js @@ -0,0 +1,293 @@ +import projectConfig from '@/core/config'; +import { buildGetUrl } from '@/core/http/requestUrl.js'; +import { formatDate, parseDate } from 'element-ui/src/utils/date-util'; +import { mapMutations } from 'vuex'; +/** + * 上传文件组件相关方法 + */ +const uploadMixin = { + methods: { + /** + * 解析返回的上传文件数据 + * @param {String} jsonData 上传文件数据,[{name, downloadUri, filename}] + * @param {Object} params 上传文件的参数 + * @returns {Array} 上传文件信息,[{name, downloadUri, filename, url}] + */ + parseUploadData (jsonData, params) { + let pathList = []; + if (jsonData != null) { + try { + pathList = JSON.parse(jsonData); + } catch (e) { + console.error(e); + } + } + + return pathList.map((item) => { + let downloadParams = {...params}; + downloadParams.filename = item.filename; + return { + ...item, + url: this.getUploadFileUrl(item, downloadParams) + } + }); + }, + /** + * 获得上传文件url列表 + * @param {*} jsonData 上传文件数据,[{name, downloadUri, filename}] + * @param {*} params 上传文件的参数 + * @returns {Array} 文件url列表 + */ + getPictureList (jsonData, params) { + let tempList = this.parseUploadData(jsonData, params); + if (Array.isArray(tempList)) { + return tempList.map(item => item.url); + } else { + return []; + } + }, + /** + * 将选中文件信息格式化成json信息 + * @param {Array} fileList 上传文件列表,[{name, fileUrl, data}] + */ + fileListToJson (fileList) { + if (Array.isArray(fileList)) { + return JSON.stringify(fileList.map((item) => { + return { + name: item.name, + downloadUri: item.downloadUri || item.response.data.downloadUri, + filename: item.filename || item.response.data.filename + } + })); + } else { + return undefined; + } + }, + /** + * 获得上传文件url + * @param {*} item 上传文件 + * @param {*} params 上传文件的参数 + */ + getUploadFileUrl (item, params) { + if (item == null || item.downloadUri == null) { + return null; + } else { + let menuIdJsonStr = window.sessionStorage.getItem('currentMenuId'); + let currentMenuId; + if (menuIdJsonStr != null) { + currentMenuId = (JSON.parse(menuIdJsonStr) || {}).data; + } + params.Authorization = window.sessionStorage.getItem('token'); + params.MenuId = currentMenuId; + return buildGetUrl(item.downloadUri, params); + } + }, + /** + * 获得上传接口 + * @param {*} url 上传路径 + */ + getUploadActionUrl (url) { + if (url != null && url[0] === '/') { + url = url.substr(1); + } + return projectConfig.baseUrl + url; + }, + /** + * 上传文件是否图片文件 + * @param {*} file 上传文件 + */ + pictureFile (file) { + if (['image/jpeg', 'image/jpg', 'image/png'].indexOf(file.type) !== -1) { + return true; + } else { + this.$message.error('图片文件格式不正确,请重新选择'); + return false; + } + } + }, + computed: { + getUploadHeaders () { + let token = window.sessionStorage.getItem('token'); + return { + Authorization: token + } + } + } +}; + +const allowStatsType = [ + 'time', + 'datetime', + 'day', + 'month', + 'year' +]; +/** + * 日期相关方法 + */ +const statsDateRangeMixin = { + methods: { + /** + * 根据输入的日期获得日期范围(例如:输入2019-12-12,输出['2019-12-12 00:00:00', '2019-12-12 23:59:59']) + * @param {Date|String} date 要转换的日期 + * @param {String} statsType 转换类型(day, month, year) + * @param {String} format 输出格式 + */ + getDateRangeFilter (date, statsType = 'day', format = 'yyyy-MM-dd HH:mm:ss') { + if (date == null) return []; + + statsType = allowStatsType.indexOf(statsType) === -1 ? 'day' : statsType; + date = date.substr(0, date.indexOf(' ')); + let tempList = date.split('-'); + let year = Number.parseInt(tempList[0]); + let month = Number.parseInt(tempList[1]); + let day = Number.parseInt(tempList[2]); + if (isNaN(year) || isNaN(month) || isNaN(day)) { + return []; + } + let tempDate = new Date(year, month - 1, day); + // 判断是否正确的日期 + if (isNaN(tempDate.getTime())) return []; + + tempDate.setHours(0, 0, 0, 0); + let retDate; + switch (statsType) { + case 'day': + retDate = [ + new Date(tempDate), + new Date(tempDate.setDate(tempDate.getDate() + 1)) + ]; + break; + case 'month': + tempDate.setDate(1); + retDate = [ + new Date(tempDate), + new Date(tempDate.setMonth(tempDate.getMonth() + 1)) + ]; + break; + case 'year': + tempDate.setDate(1); + tempDate.setMonth(0); + retDate = [ + new Date(tempDate), + new Date(tempDate.setFullYear(tempDate.getFullYear() + 1)) + ] + } + + retDate[1] = new Date(retDate[1].getTime() - 1); + + return [ + formatDate(retDate[0], format), + formatDate(retDate[1], format) + ]; + }, + /** + * 格式化日期 + * @param {Date|String} date 要格式化的日期 + * @param {String} statsType 输出日期类型 + * @param {String} format 输入日期的格式 + */ + formatDateByStatsType (date, statsType = 'day', format = 'yyyy-MM-dd') { + if (date == null) return undefined; + statsType = allowStatsType.indexOf(statsType) === -1 ? 'day' : statsType; + if (statsType === 'datetime') format = 'yyyy-MM-dd HH:mm:ss'; + + let tempDate = ((date instanceof Date) ? date : parseDate(date, format)); + if (!tempDate) return undefined; + switch (statsType) { + case 'time': + return formatDate(tempDate, 'HH:mm:ss'); + case 'datetime': + return formatDate(tempDate, 'yyyy-MM-dd HH:mm:ss'); + case 'day': + return formatDate(tempDate, 'yyyy-MM-dd'); + case 'month': + return formatDate(tempDate, 'yyyy-MM'); + case 'year': + return formatDate(tempDate, 'yyyy'); + default: + return formatDate(tempDate, 'yyyy-MM-dd'); + } + }, + /** + * 获得统计类型中文名称 + * @param {String} statsType 统计类型(day, month, year) + */ + getStatsTypeShowName (statsType) { + statsType = allowStatsType.indexOf(statsType) === -1 ? 'day' : statsType; + switch (statsType) { + case 'day': return '日统计'; + case 'month': return '月统计'; + case 'year': return '年统计'; + } + }, + /** + * 获取统计类型字典列表 + * @param {Array} statsTypeList 统计类型列表 + */ + getAllowStatsTypeList (statsTypeList) { + if (Array.isArray(statsTypeList) && statsTypeList.length > 0) { + return statsTypeList.map((item) => { + return { + id: item, + name: this.getStatsTypeShowName(item) + } + }); + } else { + return []; + } + } + } +} +/** + * 页面缓存相关方法 + */ +const cachePageMixin = { + methods: { + /** + * 移除缓存页面 + * @param {*} name 缓存组件的名称 + */ + removeCachePage (name) { + this.removeCachePage(name); + }, + /** + * 从跳转页面返回并且刷新当前页面时调用 + */ + onResume () { + }, + ...mapMutations(['addCachePage', 'removeCachePage']) + }, + created () { + this.addCachePage(this.$options.name); + }, + activated () { + if (this.$route && this.$route.meta && this.$route.meta.refresh) { + this.onResume(); + this.$route.meta.refresh = false; + } + } +} +/** + * 缓存页面跳转页面相关方法 + */ +const cachedPageChildMixin = { + data () { + return { + // 是否刷新父页面 + refreshParentCachedPage: false + } + }, + beforeRouteLeave (to, from, next) { + if (to.meta == null) to.meta = {}; + to.meta.refresh = this.refreshParentCachedPage; + next(); + } +} + +export { + uploadMixin, + statsDateRangeMixin, + cachePageMixin, + cachedPageChildMixin +} diff --git a/orange-demo-single-web/src/main.js b/orange-demo-single-web/src/main.js new file mode 100644 index 00000000..fcdd3963 --- /dev/null +++ b/orange-demo-single-web/src/main.js @@ -0,0 +1,36 @@ +import '@/core/http'; +import '@/components/Dialog'; +import Vue from 'vue'; +import ElementUI from 'element-ui'; +// import 'element-ui/lib/theme-chalk/index.css' +import '@/assets/style/index.scss'; +import '@/core/mixins/global.js'; +import App from './App'; +import router from './router'; +import store from './store'; +import TreeSelect from '@/components/TreeSelect'; +import RichEditor from '@/components/RichEditor'; +import InputNumberRange from '@/components/InputNumberRange'; +import DateRange from '@/components/DateRange'; +import FilterBox from '@/components/FilterBox'; +import TableProgressColumn from '@/components/TableProgressColumn'; +import VCharts from 'v-charts'; + +Vue.component('tree-select', TreeSelect); +Vue.component('rich-editor', RichEditor); +Vue.component('input-number-range', InputNumberRange); +Vue.component('date-range', DateRange); +Vue.component('filter-box', FilterBox); +Vue.component('table-progress-column', TableProgressColumn); + +Vue.use(ElementUI); +Vue.use(VCharts); + +Vue.config.productionTip = false; + +/* eslint-disable no-new */ +new Vue({ + router, + store, + render: h => h(App) +}).$mount('#app'); diff --git a/orange-demo-single-web/src/registerServiceWorker.js b/orange-demo-single-web/src/registerServiceWorker.js new file mode 100644 index 00000000..76cede07 --- /dev/null +++ b/orange-demo-single-web/src/registerServiceWorker.js @@ -0,0 +1,32 @@ +/* eslint-disable no-console */ + +import { register } from 'register-service-worker' + +if (process.env.NODE_ENV === 'production') { + register(`${process.env.BASE_URL}service-worker.js`, { + ready () { + console.log( + 'App is being served from cache by a service worker.\n' + + 'For more details, visit https://goo.gl/AFskqB' + ) + }, + registered () { + console.log('Service worker has been registered.') + }, + cached () { + console.log('Content has been cached for offline use.') + }, + updatefound () { + console.log('New content is downloading.') + }, + updated () { + console.log('New content is available; please refresh.') + }, + offline () { + console.log('No internet connection found. App is running in offline mode.') + }, + error (error) { + console.error('Error during service worker registration:', error) + } + }) +} diff --git a/orange-demo-single-web/src/router/import-development.js b/orange-demo-single-web/src/router/import-development.js new file mode 100644 index 00000000..b29a72d9 --- /dev/null +++ b/orange-demo-single-web/src/router/import-development.js @@ -0,0 +1 @@ +module.exports = file => require('../views/' + file + '.vue').default diff --git a/orange-demo-single-web/src/router/import-production.js b/orange-demo-single-web/src/router/import-production.js new file mode 100644 index 00000000..10d919de --- /dev/null +++ b/orange-demo-single-web/src/router/import-production.js @@ -0,0 +1 @@ +module.exports = file => () => import('../views/' + file + '.vue') diff --git a/orange-demo-single-web/src/router/index.js b/orange-demo-single-web/src/router/index.js new file mode 100644 index 00000000..77356d50 --- /dev/null +++ b/orange-demo-single-web/src/router/index.js @@ -0,0 +1,30 @@ +import Vue from 'vue'; +import Router from 'vue-router'; +import routers from './systemRouters.js'; +import dialog from '@/components/Dialog'; + +Vue.use(Router) + +const router = new Router({ + mode: 'hash', + routes: routers +}); + +/** + * 路由跳转的时候判断token是否存在 + */ +router.beforeResolve((to, from, next) => { + if (to.name === 'login') { + next(); + } else { + let token = sessionStorage.getItem('token'); + if (!token || !/\S/.test(token)) { + dialog.closeAll(); + next({ name: 'login' }) + } else { + next(); + } + } +}); + +export default router; diff --git a/orange-demo-single-web/src/router/systemRouters.js b/orange-demo-single-web/src/router/systemRouters.js new file mode 100644 index 00000000..992adf39 --- /dev/null +++ b/orange-demo-single-web/src/router/systemRouters.js @@ -0,0 +1,52 @@ +import state from '../store/state.js'; +// 开发环境不使用懒加载, 因为懒加载页面太多的话会造成webpack热更新太慢, 所以只有开发环境使用懒加载 +const _import = require('./import-' + process.env.NODE_ENV) + +function getProps (route) { + return route.query; +} + +// 系统生成路由 +const routers = [ + { path: '/login', component: _import('login/index'), name: 'login', props: getProps, desc: '登录' }, + { + path: '/', + component: _import('login/index'), + name: 'root' + }, + { + path: '/main', + component: _import('layout/index'), + name: 'main', + props: getProps, + redirect: { + name: 'welcome' + }, + meta: { + title: '主页', + showOnly: true + }, + children: [ + {path: 'welcome', component: _import('welcome/index'), name: 'welcome', meta: {title: '欢迎'}}, + {path: 'formSysUser', component: _import('upms/formSysUser/index'), name: 'formSysUser', meta: {title: '用户管理'}}, + {path: 'formSysRole', component: _import('upms/formSysRole/index'), name: 'formSysRole', meta: {title: '角色管理'}}, + {path: 'formSysMenu', component: _import(state.supportColumn ? 'upms/formSysMenu/formSysColumnMenu' : 'upms/formSysMenu/index'), name: 'formSysMenu', meta: {title: '菜单列表'}}, + {path: 'formSysDict', component: _import('upms/formDictManagement/index'), name: 'formSysDict', meta: {title: '字典管理'}}, + {path: 'formSysPermCode', component: _import('upms/formSysPermCode/index'), name: 'formSysPermCode', meta: {title: '权限字管理'}}, + {path: 'formSysPerm', component: _import('upms/formSysPerm/index'), name: 'formSysPerm', meta: {title: '权限资源管理'}}, + {path: 'formSchool', component: _import('generated/formSchool/index'), name: 'formSchool', props: getProps, meta: {title: '校区管理'}}, + {path: 'formStudent', component: _import('generated/formStudent/index'), name: 'formStudent', props: getProps, meta: {title: '学生管理'}}, + {path: 'formCourse', component: _import('generated/formCourse/index'), name: 'formCourse', props: getProps, meta: {title: '课程管理'}}, + {path: 'formClass', component: _import('generated/formClass/index'), name: 'formClass', props: getProps, meta: {title: '班级管理'}}, + {path: 'formClassStudent', component: _import('generated/formClassStudent/index'), name: 'formClassStudent', props: getProps, meta: {title: '班级学生'}}, + {path: 'formClassCourse', component: _import('generated/formClassCourse/index'), name: 'formClassCourse', props: getProps, meta: {title: '班级课程'}}, + {path: 'formSetClassStudent', component: _import('generated/formSetClassStudent/index'), name: 'formSetClassStudent', props: getProps, meta: {title: '设置班级学生'}}, + {path: 'formSetClassCourse', component: _import('generated/formSetClassCourse/index'), name: 'formSetClassCourse', props: getProps, meta: {title: '设置班级课程'}}, + {path: 'formCourseStats', component: _import('generated/formCourseStats/index'), name: 'formCourseStats', props: getProps, meta: {title: '课程统计'}}, + {path: 'formStudentActionStats', component: _import('generated/formStudentActionStats/index'), name: 'formStudentActionStats', props: getProps, meta: {title: '学生行为统计'}}, + {path: 'formStudentActionDetail', component: _import('generated/formStudentActionDetail/index'), name: 'formStudentActionDetail', props: getProps, meta: {title: '学生行为详情'}} + ] + } +]; + +export default routers; diff --git a/orange-demo-single-web/src/staticDict/index.js b/orange-demo-single-web/src/staticDict/index.js new file mode 100644 index 00000000..1f3cb72c --- /dev/null +++ b/orange-demo-single-web/src/staticDict/index.js @@ -0,0 +1,351 @@ +/** + * 常量字典数据 + */ +import Vue from 'vue'; + +class DictionaryBase extends Map { + constructor (dataList, keyId = 'id', symbolId = 'symbol') { + super(); + this.setList(dataList, keyId, symbolId); + } + + setList (dataList, keyId = 'id', symbolId = 'symbol') { + this.clear(); + if (Array.isArray(dataList)) { + dataList.forEach((item) => { + this.set(item[keyId], item); + if (item[symbolId] != null) { + Object.defineProperty(this, item[symbolId], { + get: function () { + return item[keyId]; + } + }); + } + }); + } + } + + getList (valueId = 'name', parentIdKey = 'parentId', filter) { + let temp = []; + this.forEach((value, key) => { + let obj = { + id: key, + name: (typeof value === 'string') ? value : value[valueId], + parentId: value[parentIdKey] + }; + if (typeof filter !== 'function' || filter(obj)) { + temp.push(obj); + } + }); + + return temp; + } + + getValue (id, valueId = 'name') { + return (this.get(id) || {})[valueId]; + } +} + +const SysUserStatus = new DictionaryBase([ + { + id: 0, + name: '正常状态', + symbol: 'NORMAL' + }, + { + id: 1, + name: '锁定状态', + symbol: 'LOCKED' + } +]); +Vue.prototype.SysUserStatus = SysUserStatus; + +const SysUserType = new DictionaryBase([ + { + id: 0, + name: '管理员', + symbol: 'ADMIN' + }, + { + id: 1, + name: '系统操作员', + symbol: 'SYSTEM' + }, + { + id: 2, + name: '普通操作员', + symbol: 'OPERATOR' + } +]); +Vue.prototype.SysUserType = SysUserType; + +const Subject = new DictionaryBase([ + { + id: 0, + name: '语文', + symbol: 'CHINESE' + }, + { + id: 1, + name: '数学', + symbol: 'MATCH' + }, + { + id: 2, + name: '英语', + symbol: 'ENGLISH' + } +]); +Vue.prototype.Subject = Subject; + +const StudentActionType = new DictionaryBase([ + { + id: 0, + name: '充值', + symbol: 'RECHARGE' + }, + { + id: 1, + name: '购课', + symbol: 'BUY_COURSE' + }, + { + id: 2, + name: '上课签到', + symbol: 'SIGNIN_COURSE' + }, + { + id: 3, + name: '上课签退', + symbol: 'SIGNOUT_COURSE' + }, + { + id: 4, + name: '看视频课', + symbol: 'WATCH_VIDEO' + }, + { + id: 5, + name: '做作业', + symbol: 'DO_PAPER' + }, + { + id: 6, + name: '刷题', + symbol: 'REFRESH_EXERCISE' + }, + { + id: 7, + name: '献花', + symbol: 'PRESENT_FLOWER' + }, + { + id: 8, + name: '购买视频', + symbol: 'BUY_VIDEO_COURSE' + }, + { + id: 9, + name: '购买鲜花', + symbol: 'BUY_FLOWER' + }, + { + id: 10, + name: '购买作业', + symbol: 'BUY_PAPER' + } +]); +Vue.prototype.StudentActionType = StudentActionType; + +const DeviceType = new DictionaryBase([ + { + id: 0, + name: 'iOS', + symbol: 'IOS' + }, + { + id: 1, + name: 'Android', + symbol: 'ANDROID' + }, + { + id: 2, + name: 'PC', + symbol: 'PC' + } +]); +Vue.prototype.DeviceType = DeviceType; + +const Gender = new DictionaryBase([ + { + id: 1, + name: '男', + symbol: 'MALE' + }, + { + id: 0, + name: '女', + symbol: 'FEMALE' + } +]); +Vue.prototype.Gender = Gender; + +const ExpLevel = new DictionaryBase([ + { + id: 0, + name: '初级学员', + symbol: 'LOWER' + }, + { + id: 1, + name: '中级学员', + symbol: 'MIDDLE' + }, + { + id: 2, + name: '高级学员', + symbol: 'HIGH' + } +]); +Vue.prototype.ExpLevel = ExpLevel; + +const StudentStatus = new DictionaryBase([ + { + id: 0, + name: '正常', + symbol: 'NORMAL' + }, + { + id: 1, + name: '锁定', + symbol: 'LOCKED' + }, + { + id: 2, + name: '注销', + symbol: 'DELETED' + } +]); +Vue.prototype.StudentStatus = StudentStatus; + +const ClassStatus = new DictionaryBase([ + { + id: 1, + name: '正常', + symbol: 'NORAML' + }, + { + id: -1, + name: '解散', + symbol: 'DELETED' + } +]); +Vue.prototype.ClassStatus = ClassStatus; + +const ClassLevel = new DictionaryBase([ + { + id: 0, + name: '初级班', + symbol: 'NORMAL' + }, + { + id: 1, + name: '中级班', + symbol: 'MIDDLE' + }, + { + id: 2, + name: '高级班', + symbol: 'HIGH' + } +]); +Vue.prototype.ClassLevel = ClassLevel; + +const CourseDifficult = new DictionaryBase([ + { + id: 0, + name: '容易', + symbol: 'NORMAL' + }, + { + id: 1, + name: '普通', + symbol: 'MIDDLE' + }, + { + id: 2, + name: '困难', + symbol: 'HIGH' + } +]); +Vue.prototype.CourseDifficult = CourseDifficult; + +const SysPermModuleType = new DictionaryBase([ + { + id: 0, + name: '分组模块', + symbol: 'GROUP' + }, { + id: 1, + name: '接口模块', + symbol: 'CONTROLLER' + } +]); +Vue.prototype.SysPermModuleType = SysPermModuleType; + +const SysPermCodeType = new DictionaryBase([{ + id: 0, + name: '表单', + symbol: 'FORM' +}, { + id: 1, + name: '片段', + symbol: 'FRAGMENT' +}, { + id: 2, + name: '操作', + symbol: 'OPERATION' +}]); +Vue.prototype.SysPermCodeType = SysPermCodeType; + +const SysMenuType = new DictionaryBase([ + { + id: 0, + name: '目录', + symbol: 'DIRECTORY' + }, + { + id: 1, + name: '表单', + symbol: 'MENU' + }, + { + id: 2, + name: '片段', + symbol: 'FRAGMENT' + }, + { + id: 3, + name: '按钮', + symbol: 'BUTTON' + } +]); +Vue.prototype.SysMenuType = SysMenuType; + +export { + DictionaryBase, + SysUserStatus, + SysUserType, + Subject, + StudentActionType, + DeviceType, + Gender, + ExpLevel, + StudentStatus, + ClassStatus, + ClassLevel, + CourseDifficult, + SysPermModuleType, + SysPermCodeType, + SysMenuType +} diff --git a/orange-demo-single-web/src/store/actions.js b/orange-demo-single-web/src/store/actions.js new file mode 100644 index 00000000..b1c6ea43 --- /dev/null +++ b/orange-demo-single-web/src/store/actions.js @@ -0,0 +1 @@ +export default {} diff --git a/orange-demo-single-web/src/store/getters.js b/orange-demo-single-web/src/store/getters.js new file mode 100644 index 00000000..ee6e1881 --- /dev/null +++ b/orange-demo-single-web/src/store/getters.js @@ -0,0 +1,80 @@ +import { findMenuItem } from './utils'; +import * as StaticDict from '@/staticDict'; + +export default { + getMultiTags: (state) => { + return state.supportTags; + }, + getCollapse: (state) => { + return state.isCollapse; + }, + getClientHeight: (state) => { + return state.documentClientHeight; + }, + getMainContextHeight: (state) => { + return state.documentClientHeight - (state.supportTags ? 130 : 90); + }, + getUserInfo: (state) => { + return state.userInfo; + }, + getCachePages: (state) => { + return state.cachePages; + }, + getTagList: (state) => { + return state.tagList; + }, + getMenuList: (state) => { + if (state.supportColumn) { + if (state.currentColumnId == null || state.currentColumnId === '') return []; + for (let i = 0; i < state.menuList.length; i++) { + if (state.menuList[i].menuId === state.currentColumnId) { + return state.menuList[i].children || []; + } + } + + return []; + } else { + return state.menuList; + } + }, + getColumnList: (state) => { + if (!state.supportColumn) return []; + return state.menuList.map(menu => { + if (menu.menuType === StaticDict.SysMenuType.DIRECTORY) { + return { + columnId: menu.menuId, + columnName: menu.menuName + } + } + }).filter(item => item != null); + }, + getCurrentMenuId: (state) => { + return state.currentMenuId; + }, + getMenuItem: (state) => { + if (Array.isArray(state.menuList)) { + for (let i = 0; i < state.menuList.length; i++) { + let temp = findMenuItem(state.menuList[i], state.currentMenuId); + if (temp != null) return temp; + } + } + return null; + }, + getCurrentMenuPath: (state) => { + let menuPath = []; + if (Array.isArray(state.menuList)) { + for (let i = 0; i < state.menuList.length; i++) { + let temp = findMenuItem(state.menuList[i], state.currentMenuId, menuPath); + if (temp != null) break; + } + } + + return menuPath; + }, + getMultiColumn: (state) => { + return state.supportColumn; + }, + getCurrentColumnId: (state) => { + return state.currentColumnId; + } +} diff --git a/orange-demo-single-web/src/store/index.js b/orange-demo-single-web/src/store/index.js new file mode 100644 index 00000000..5fc44198 --- /dev/null +++ b/orange-demo-single-web/src/store/index.js @@ -0,0 +1,15 @@ +import Vue from 'vue'; +import Vuex from 'vuex'; +import state from './state.js'; +import getters from './getters.js'; +import mutations from './mutations.js'; +import actions from './actions.js'; + +Vue.use(Vuex); +export default new Vuex.Store({ + state, + getters, + mutations, + actions, + strict: process.env.NODE_ENV !== 'production' +}); diff --git a/orange-demo-single-web/src/store/mutations.js b/orange-demo-single-web/src/store/mutations.js new file mode 100644 index 00000000..41b411ac --- /dev/null +++ b/orange-demo-single-web/src/store/mutations.js @@ -0,0 +1,145 @@ +import { initUserInfo, findMenuItem } from './utils'; +import { setObjectToSessionStorage, findItemFromList, treeDataTranslate } from '@/utils'; + +export default { + setCollapse: (state, isCollapse) => { + state.isCollapse = isCollapse; + }, + setClientHeight: (state, height) => { + state.documentClientHeight = height; + }, + setUserInfo: (state, info) => { + setObjectToSessionStorage('userInfo', info); + state.userInfo = initUserInfo(info); + }, + addCachePage (state, name) { + if (state.cachePages.indexOf(name) === -1) { + let temp = [...state.cachePages]; + temp.push(name); + setObjectToSessionStorage('cachePages', temp); + state.cachePages = temp; + } + }, + removeCachePage (state, name) { + let pos = state.cachePages.indexOf(name); + if (pos !== -1) { + let temp = [...state.cachePages]; + temp.splice(pos, 1); + setObjectToSessionStorage('cachePages', temp); + state.cachePages = temp; + } + }, + clearCachePage (state) { + setObjectToSessionStorage('cachePages', []); + state.cachePages = []; + }, + addTag (state, id) { + if (id == null || id === '') return; + // 新增的标签是否存在 + let tagList = state.tagList; + let tagItem = null; + if (Array.isArray(tagList)) { + tagItem = findItemFromList(tagList, id, 'menuId'); + } + if (tagItem != null) return; + // 添加新增标签以及更新页面缓存 + let menuList = state.menuList; + let menuObject = null; + if (Array.isArray(menuList)) { + for (let i = 0; i < menuList.length; i++) { + menuObject = findMenuItem(menuList[i], id); + if (menuObject != null) break; + } + } + if (menuObject != null) { + state.tagList = [...state.tagList, menuObject]; + if (Array.isArray(state.cachePages) && state.cachePages.indexOf(menuObject.formRouterName) === -1) { + state.cachePages = [...state.cachePages, menuObject.formRouterName]; + } + } + setObjectToSessionStorage('cachePages', state.cachePages); + setObjectToSessionStorage('tagList', state.tagList); + }, + removeTag (state, id) { + if (id == null || id === '') return; + // 移除标签 + let nextPos = -1; + let tagItem = null; + for (let i = 0; i < state.tagList.length; i++) { + if (state.tagList[i].menuId === id) { + tagItem = state.tagList[i]; + state.tagList.splice(i, 1); + nextPos = Math.min(i, state.tagList.length - 1); + } + } + // let tagItem = findItemFromList(state.tagList, id, 'menuId', true); + if (tagItem == null) return; + // 移除页面缓存 + findItemFromList(state.cachePages, tagItem.formRouterName, undefined, true); + setObjectToSessionStorage('cachePages', state.cachePages); + setObjectToSessionStorage('tagList', state.tagList); + // 如果移除的是当前显示页面,重新选择显示页面 + let showTag = null; + if (state.currentMenuId === id) { + showTag = state.tagList[nextPos]; + let tempId = (showTag || {}).menuId; + if (setObjectToSessionStorage('currentMenuId', tempId)) state.currentMenuId = tempId; + } + }, + closeOtherTags (state, id) { + if (id == null || id === '') return; + // 移除其他所有标签 + if (Array.isArray(state.tagList)) { + state.tagList = state.tagList.filter((item) => { + return item.menuId === id; + }); + } + + let menuObject = state.tagList[0]; + if (menuObject && menuObject.formRouterName && menuObject.formRouterName !== '') { + state.cachePages = [menuObject.formRouterName]; + if (setObjectToSessionStorage('currentMenuId', menuObject.menuId)) state.currentMenuId = menuObject.menuId; + } + setObjectToSessionStorage('cachePages', state.cachePages); + setObjectToSessionStorage('tagList', state.tagList); + }, + clearAllTags (state) { + if (setObjectToSessionStorage('currentMenuId', undefined)) state.currentMenuId = undefined; + if (setObjectToSessionStorage('cachePages', [])) state.cachePages = []; + if (setObjectToSessionStorage('tagList', [])) state.tagList = []; + }, + setMenuList: (state, list) => { + if (Array.isArray(list)) { + if (setObjectToSessionStorage('menuList', list)) state.menuList = treeDataTranslate(list, 'menuId', 'parentId'); + let columnId = (state.menuList[0] || {}).menuId; + if (setObjectToSessionStorage('currentColumnId', columnId)) state.currentColumnId = columnId; + } + }, + setCurrentMenuId: (state, menuId) => { + let menuItem = null; + if (setObjectToSessionStorage('currentMenuId', menuId)) state.currentMenuId = menuId; + if (Array.isArray(state.tagList) && Array.isArray(state.menuList)) { + for (let i = 0; i < state.menuList.length; i++) { + menuItem = findMenuItem(state.menuList[i], menuId, 'menuId'); + if (menuItem != null) { + // 添加新的tag + let tagItem = findItemFromList(state.tagList, menuId, 'menuId'); + if (tagItem == null) { + state.tagList = [...state.tagList, menuItem]; + setObjectToSessionStorage('tagList', state.tagList); + } + // 添加新缓存 + if (Array.isArray(state.cachePages) && state.cachePages.indexOf(menuItem.formRouterName) === -1) { + state.cachePages = [...state.cachePages, menuItem.formRouterName]; + setObjectToSessionStorage('cachePages', state.cachePages); + } + break; + } + } + } + }, + setCurrentColumnId: (state, columnId) => { + if (setObjectToSessionStorage('currentColumnId', columnId)) state.currentColumnId = columnId; + if (setObjectToSessionStorage('currentMenuId', null)) state.currentMenuId = null; + } +} diff --git a/orange-demo-single-web/src/store/state.js b/orange-demo-single-web/src/store/state.js new file mode 100644 index 00000000..ebde637f --- /dev/null +++ b/orange-demo-single-web/src/store/state.js @@ -0,0 +1,25 @@ +import { initUserInfo } from './utils'; +import { getObjectFromSessionStorage, treeDataTranslate } from '@/utils'; + +export default { + // 是否左侧菜单折叠 + isCollapse: false, + // 是否多栏目 + supportColumn: false, + // 是否多标签 + supportTags: false, + // 浏览器客户区高度 + documentClientHeight: 100, + // 用户登录信息 + userInfo: initUserInfo(), + // 缓存页面 + cachePages: getObjectFromSessionStorage('cachePages', []), + // 当前标签 + tagList: getObjectFromSessionStorage('tagList', []), + // 菜单列表 + menuList: treeDataTranslate(getObjectFromSessionStorage('menuList', []), 'menuId', 'parentId'), + // 当前菜单 + currentMenuId: getObjectFromSessionStorage('currentMenuId', undefined), + // 当前栏目 + currentColumnId: getObjectFromSessionStorage('currentColumnId', undefined) +} diff --git a/orange-demo-single-web/src/store/utils/index.js b/orange-demo-single-web/src/store/utils/index.js new file mode 100644 index 00000000..ec129435 --- /dev/null +++ b/orange-demo-single-web/src/store/utils/index.js @@ -0,0 +1,36 @@ +import { getObjectFromSessionStorage } from '@/utils'; + +function findMenuItem (menuItem, menuId, path) { + if (Array.isArray(path)) path.push(menuItem); + if ((menuItem.menuId + '') === (menuId + '')) return menuItem; + + let bFind = false; + let findItem = null; + if (Array.isArray(menuItem.children)) { + for (let i = 0; i < menuItem.children.length; i++) { + findItem = findMenuItem(menuItem.children[i], menuId, path); + if (findItem != null) { + bFind = true; + break; + } + } + } + + if (!bFind && Array.isArray(path)) path.pop(); + return bFind ? findItem : null; +} + +function initUserInfo (userInfo) { + if (userInfo == null) userInfo = getObjectFromSessionStorage('userInfo'); + + if (userInfo != null && userInfo.permCodeList != null && Array.isArray(userInfo.permCodeList)) { + userInfo.permCodeSet = new Set(userInfo.permCodeList); + } + + return userInfo; +} + +export { + findMenuItem, + initUserInfo +} diff --git a/orange-demo-single-web/src/utils/chartOption.js b/orange-demo-single-web/src/utils/chartOption.js new file mode 100644 index 00000000..76b12e02 --- /dev/null +++ b/orange-demo-single-web/src/utils/chartOption.js @@ -0,0 +1,56 @@ +const defaultLineChartOption = { + grid: { + left: '3%', + right: '4%', + bottom: '20px', + containLabel: true + }, + xAxis: { + axisLabel: { + interval: 0, + showMaxLabel: true + } + }, + legend: { + top: '3%' + } +} + +const defaultBarChartOption = { + grid: { + left: '3%', + right: '4%', + bottom: '20px', + containLabel: true + }, + xAxis: { + axisLabel: { + interval: 0, + showMaxLabel: true + } + }, + legend: { + top: '3%' + } +} + +const defaultPieChartOption = { + grid: { + left: '3%', + right: '4%', + bottom: '20px', + containLabel: true + }, + legend: { + top: '3%' + }, + series: { + center: ['50%', '60%'] + } +} + +export { + defaultLineChartOption, + defaultBarChartOption, + defaultPieChartOption +} diff --git a/orange-demo-single-web/src/utils/index.js b/orange-demo-single-web/src/utils/index.js new file mode 100644 index 00000000..7c48d739 --- /dev/null +++ b/orange-demo-single-web/src/utils/index.js @@ -0,0 +1,222 @@ +import JSEncrypt from 'jsencrypt'; + +/** + * 列表数据转换树形数据 + * @param {Array} data 要转换的列表 + * @param {String} id 主键字段字段名 + * @param {String} pid 父字段字段名 + * @returns {Array} 转换后的树数据 + */ +export function treeDataTranslate (data, id = 'id', pid = 'parentId') { + var res = [] + var temp = {} + for (var i = 0; i < data.length; i++) { + temp[data[i][id]] = data[i] + } + for (var k = 0; k < data.length; k++) { + if (temp[data[k][pid]] && data[k][id] !== data[k][pid]) { + if (!temp[data[k][pid]]['children']) { + temp[data[k][pid]]['children'] = [] + } + if (!temp[data[k][pid]]['_level']) { + temp[data[k][pid]]['_level'] = 1 + } + data[k]['_level'] = temp[data[k][pid]]._level + 1 + data[k]['_parent'] = data[k][pid] + temp[data[k][pid]]['children'].push(data[k]) + } else { + res.push(data[k]) + } + } + + return res +} +/** + * 获取字符串字节长度(中文算2个字符) + * @param {String} str 要获取长度的字符串 + */ +export function getStringLength (str) { + return str.replace(/[\u4e00-\u9fa5\uff00-\uffff]/g, '**').length +} +/** + * 获取uuid + */ +export function getUUID () { + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => { + return (c === 'x' ? (Math.random() * 16 | 0) : ('r&0x3' | '0x8')).toString(16) + }); +} +/** + * 大小驼峰变换函数 + * @param name 要转换的字符串 + * @param type 转换的类型0:转换成小驼峰,1:转换成大驼峰 + */ +export function nameTranslate (name, type) { + name = name.toLowerCase(); + let nameArray = name.split('_'); + nameArray.forEach((item, index) => { + if (index === 0) { + name = type === 1 ? item.slice(0, 1).toUpperCase() + item.slice(1) : item; + } else { + name = name + item.slice(0, 1).toUpperCase() + item.slice(1); + } + }); + + nameArray = name.split('-'); + nameArray.forEach((item, index) => { + if (index === 0) { + name = type === 1 ? item.slice(0, 1).toUpperCase() + item.slice(1) : item; + } else { + name = name + item.slice(0, 1).toUpperCase() + item.slice(1); + } + }); + return name; +} +/** + * 通过id从树中获取指定的节点 + * @param {Object} node 根节点 + * @param {String|Nubmer} id 键值 + * @param {Array} list 保存查询路径 + * @param {String} idKey 主键字段名 + * @param {String} childKey 子节点字段名 + */ +function findNode (node, id, list, idKey = 'id', childKey = 'children') { + if (Array.isArray(list)) list.push(node[idKey]); + if (node[idKey] === id) { + return node; + } + + if (node[childKey] != null && Array.isArray(node[childKey])) { + for (let i = 0; i < node[childKey].length; i++) { + let tempNode = findNode(node[childKey][i], id, list, idKey, childKey); + if (tempNode) return tempNode; + } + } + + if (Array.isArray(list)) list.pop(); +} +/** + * 通过id返回从根节点到指定节点的路径 + * @param {Array} treeRoot 树根节点数组 + * @param {*} id 要查询的节点的id + * @param {*} idKey 主键字段名 + * @param {*} childKey 子节点字段名 + */ +export function findTreeNodePath (treeRoot, id, idKey = 'id', childKey = 'children') { + let tempList = []; + for (let i = 0; i < treeRoot.length; i++) { + if (findNode(treeRoot[i], id, tempList, idKey, childKey)) { + return tempList; + } + } + + return []; +} +/** + * 通过id从树中查找节点 + * @param {Array} treeRoot 根节点数组 + * @param {*} id 要查找的节点的id + * @param {*} idKey 主键字段名 + * @param {*} childKey 子节点字段名 + */ +export function findTreeNode (treeRoot, id, idKey = 'id', childKey = 'children') { + for (let i = 0; i < treeRoot.length; i++) { + let tempNode = findNode(treeRoot[i], id, undefined, idKey, childKey); + if (tempNode) return tempNode; + } +} +/** + * 把Object转换成query字符串 + * @param {Object} params 要转换的Object + */ +export function objectToQueryString (params) { + if (params == null) { + return null; + } else { + return Object.keys(params).map((key) => { + return `${key}=${params[key]}`; + }).join('&'); + } +} +/** + * 从数组中查找某一项 + * @param {Array} list 要查找的数组 + * @param {String} id 要查找的节点id + * @param {String} idKey 主键字段名(如果为null则直接比较) + * @param {Boolean} removeItem 是否从数组中移除查找到的节点 + * @returns {Object} 找到返回节点,没找到返回undefined + */ +export function findItemFromList (list, id, idKey, removeItem = false) { + if (Array.isArray(list) && list.length > 0 && id != null) { + for (let i = 0; i < list.length; i++) { + let item = list[i]; + if (((idKey == null || idKey === '') && item === id) || (idKey != null && item[idKey] === id)) { + if (removeItem) list.splice(i, 1); + return item; + } + } + } + return null; +} +/** + * 将数据保存到sessionStorage + * @param {*} key sessionStorage的键值 + * @param {*} value 要保存的数据 + */ +export function setObjectToSessionStorage (key, value) { + if (key == null || key === '') return false; + if (value == null) { + window.sessionStorage.removeItem(key); + return true; + } else { + let jsonObj = { + data: value + } + window.sessionStorage.setItem(key, JSON.stringify(jsonObj)); + return true; + } +} +/** + * 从sessionStorage里面获取数据 + * @param {String} key 键值 + * @param {*} defaultValue 默认值 + */ +export function getObjectFromSessionStorage (key, defaultValue) { + let jsonObj = null; + try { + jsonObj = JSON.parse(window.sessionStorage.getItem(key)); + jsonObj = (jsonObj || {}).data; + } catch (e) { + jsonObj = defaultValue; + }; + return (jsonObj != null) ? jsonObj : defaultValue; +} +/** + * 判读字符串是否一个数字 + * @param {String} str 要判断的字符串 + */ +export function isNumber (str) { + let num = Number.parseFloat(str); + if (Number.isNaN(num)) return false; + return num.toString() === str; +} +/** + * 生成随机数 + * @param {Integer} min 随机数最小值 + * @param {Integer} max 随机数最大值 + */ +export function random (min, max) { + let base = Math.random(); + return min + base * (max - min); +} +/** + * 加密 + * @param {*} value 要加密的字符串 + */ +const publicKey = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCpC4QMnbTrQOFriJJCCFFWhlruBJThAEBfRk7pRx1jsAhyNVL3CqJb0tRvpnbCnJhrRAEPdgFHXv5A0RrvFp+5Cw7QoFH6O9rKB8+0H7+aVQeKITMUHf/XMXioymw6Iq4QfWd8RhdtM1KM6eGTy8aU7SO2s69Mc1LXefg/x3yw6wIDAQAB'; +export function encrypt (value) { + if (value == null || value === '') return null; + let encrypt = new JSEncrypt(); + encrypt.setPublicKey(publicKey); + return encodeURIComponent(encrypt.encrypt(value)); +} diff --git a/orange-demo-single-web/src/utils/validate.js b/orange-demo-single-web/src/utils/validate.js new file mode 100644 index 00000000..5b148e39 --- /dev/null +++ b/orange-demo-single-web/src/utils/validate.js @@ -0,0 +1,33 @@ +const pattern = { + mobie: /^((\+?86)|(\(\+86\)))?(13[012356789][0-9]{8}|15[012356789][0-9]{8}|18[02356789][0-9]{8}|147[0-9]{8}|1349[0-9]{7})$/, + english: /^[a-zA-Z]+$/, + englishAndNumber: /^[a-zA-Z0-9]+$/ +} + +/** + * 邮箱 + * @param str + */ +export function isEmail (str) { + return /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((.[a-zA-Z0-9_-]{2,3}){1,2})$/.test(str) +} + +/** + * 手机号码 + * @param str + */ +export function isMobile (str) { + return pattern.mobie.test(str) +} + +/** + * 电话号码 + * @param str + */ +export function isPhone (str) { + return /^([0-9]{3,4}-)?[0-9]{7,8}$/.test(str) +} + +export default { + pattern +} diff --git a/orange-demo-single-web/src/utils/widget.js b/orange-demo-single-web/src/utils/widget.js new file mode 100644 index 00000000..db2cfa81 --- /dev/null +++ b/orange-demo-single-web/src/utils/widget.js @@ -0,0 +1,297 @@ +import { Message } from 'element-ui'; +import { treeDataTranslate } from '@/utils'; + +const DEFAULT_PAGE_SIZE = 10; + +export class DropdownWidget { + /** + * 下拉组件(Select、Cascade、TreeSelect等) + * @param {function () : Promise} loadDropdownData 下拉数据获取函数 + * @param {Boolean} isTree 是否是树数据 + * @param {String} idKey 键字段字段名 + * @param {String} parentIdKey 父字段字段名 + */ + constructor (loadDropdownData, isTree = false, idKey = 'id', parentIdKey = 'parentId') { + this.loading = false; + this.dirty = true; + this.dropdownList = []; + this.isTree = isTree; + this.idKey = idKey; + this.parentIdKey = parentIdKey; + this.loadDropdownData = loadDropdownData; + this.setDropdownList = this.setDropdownList.bind(this); + this.onVisibleChange = this.onVisibleChange.bind(this); + } + /** + * 重新获取下拉数据 + */ + reloadDropdownData () { + return new Promise((resolve, reject) => { + if (!this.loading) { + if (typeof this.loadDropdownData === 'function') { + this.loading = true; + this.loadDropdownData().then(dataList => { + this.setDropdownList(dataList); + this.loading = false; + this.dirty = false; + resolve(this.dropdownList); + }).catch(e => { + this.setDropdownList([]); + this.loading = false; + reject(this.dropdownList); + }); + } else { + reject(new Error('获取下拉数据失败')); + } + } else { + resolve(this.dropdownList); + } + }); + } + /** + * 下拉框显示或隐藏时调用 + * @param {Boolean} isShow 正在显示或者隐藏 + */ + onVisibleChange (isShow) { + return new Promise((resolve, reject) => { + if (isShow && this.dirty && !this.loading) { + this.reloadDropdownData().then(res => { + resolve(res); + }).catch(e => { + reject(e); + }); + } else { + resolve(this.dropdownList); + } + }); + } + /** + * 设置下拉数据 + * @param {Array} dataList 要显示的下拉数据 + */ + setDropdownList (dataList) { + if (Array.isArray(dataList)) { + this.dropdownList = this.isTree ? treeDataTranslate(dataList, this.idKey, this.parentIdKey) : dataList; + } + } +} + +export class TableWidget { + /** + * 表格组件 + * @param {function (params: Object) : Promise} loadTableData 表数据获取函数 + * @param {function () : Boolean} verifyTableParameter 表数据获取检验函数 + * @param {Boolean} paged 是否支持分页 + * @param {String} orderFieldName 默认排序字段 + * @param {Boolean} ascending 默认排序方式(true为正序,false为倒序) + * @param {String} dateAggregateBy 默认排序字段的日期统计类型 + */ + constructor (loadTableData, verifyTableParameter, paged, orderFieldName, ascending, dateAggregateBy) { + this.oldPage = 0; + this.currentPage = 1; + this.oldPageSize = DEFAULT_PAGE_SIZE; + this.pageSize = DEFAULT_PAGE_SIZE; + this.totalCount = 0; + this.dataList = []; + this.orderInfo = { + fieldName: orderFieldName, + asc: ascending, + dateAggregateBy: dateAggregateBy + }; + this.paged = paged; + this.searchVerify = verifyTableParameter || function () { return true; }; + this.loadTableData = loadTableData || function () { return Promise.resolve(); }; + this.onCurrentPageChange = this.onCurrentPageChange.bind(this); + this.onPageSizeChange = this.onPageSizeChange.bind(this); + this.onSortChange = this.onSortChange.bind(this); + this.getTableIndex = this.getTableIndex.bind(this); + } + /** + * 表格分页变化 + * @param {Integer} newCurrentPage 变化后的显示页面 + */ + onCurrentPageChange (newCurrentPage) { + this.loadTableDataImpl(newCurrentPage, this.pageSize).then(() => { + this.oldPage = this.currentPage = newCurrentPage; + }).catch(() => { + this.currentPage = this.oldPage; + }); + } + /** + * 表格分页每页显示数量变化 + * @param {Integer} newPageSize 变化后的每页显示数量 + */ + onPageSizeChange (newPageSize) { + this.loadTableDataImpl(1, newPageSize).then(() => { + this.oldPage = this.currentPage = 1; + this.oldPageSize = this.pageSize = newPageSize; + }).catch(e => { + this.currentPage = this.oldPage; + this.pageSize = this.oldPageSize; + }); + } + /** + * 表格排序字段变化 + * @param {String} prop 排序字段的字段名 + * @param {String} order 正序还是倒序 + */ + onSortChange ({ prop, order }) { + this.orderInfo.fieldName = prop; + this.orderInfo.asc = (order === 'ascending'); + this.refreshTable(); + } + /** + * 获取每一行的index信息 + * @param {Integer} index 表格在本页位置 + */ + getTableIndex (index) { + return this.paged ? ((this.currentPage - 1) * this.pageSize + (index + 1)) : (index + 1); + } + /** + * 获取表格数据 + * @param {Integer} pageNum 当前分页 + * @param {Integer} pageSize 每页数量 + * @param {Boolean} reload 是否重新获取数据 + */ + loadTableDataImpl (pageNum, pageSize, reload = false) { + return new Promise((resolve, reject) => { + if (typeof this.loadTableData !== 'function') { + reject(); + } else { + // 如果pageSize和pageNum没有变化,并且不强制刷新 + if (this.paged && !reload && this.oldPage === pageNum && this.oldPageSize === pageSize) { + resolve(); + } else { + let params = {}; + if (this.orderInfo.fieldName != null) params.orderParam = [this.orderInfo]; + if (this.paged) { + params.pageParam = { + pageNum, + pageSize + } + } + this.loadTableData(params).then(tableData => { + this.dataList = tableData.dataList; + this.totalCount = tableData.totalCount; + resolve(); + }).catch(e => { + reject(e); + }); + } + } + }); + } + /** + * 刷新表格数据 + * @param {Boolean} research 是否按照新的查询条件重新查询(调用verify函数) + * @param {Integer} pageNum 当前页面 + */ + refreshTable (research = false, pageNum = undefined, showMsg = false) { + let reload = false; + if (research) { + if (typeof this.searchVerify === 'function' && !this.searchVerify()) return; + reload = true; + } + + if (Number.isInteger(pageNum) && pageNum !== this.currentPage) { + this.loadTableDataImpl(pageNum, this.pageSize, reload).then(res => { + this.oldPage = this.currentPage = pageNum; + if (research && showMsg) Message.success('查询成功'); + }).catch(e => { + this.currentPage = this.oldPage; + }); + } else { + this.loadTableDataImpl(this.currentPage, this.pageSize, true).catch(e => {}); + } + } +} + +export class UploadWidget { + /** + * 上传组件 + * @param {Integer} maxCount 最大上传数量 + */ + constructor (maxCount = 1) { + this.maxCount = maxCount; + this.fileList = []; + this.onFileChange = this.onFileChange.bind(this); + } + /** + * 上传文件列表改变 + * @param {Object} file 改变的文件 + * @param {Array} fileList 改变后的文件列表 + */ + onFileChange (file, fileList) { + if (Array.isArray(fileList) && fileList.length > 0) { + if (this.maxCount === 1) { + this.fileList = [fileList[fileList.length - 1]]; + } else { + this.fileList = fileList; + } + } else { + this.fileList = []; + } + return this.fileList; + } +} + +export class ChartWidget { + /** + * 图表组件 + * @param {function (params) : Promise} loadTableData chart数据获取函数 + * @param {function () : Boolean} verifyTableParameter 数据参数检验函数 + * @param {Array} columns 数据列 + */ + constructor (loadTableData, verifyTableParameter, columns) { + this.columns = columns; + this.loading = false; + this.dataEmpty = false; + this.chartData = undefined; + this.chartObject = undefined; + this.dimensionMaps = new Map(); + this.chartSetting = undefined; + this.searchVerify = verifyTableParameter || function () { return true; }; + this.loadTableData = loadTableData || function () { return Promise.resolve(); }; + } + /** + * 获取图表数据 + * @param {Boolean} reload 是否重新获取数据 + */ + loadChartDataImpl (reload = false) { + return new Promise((resolve, reject) => { + if (typeof this.loadTableData !== 'function') { + reject(); + } else { + if (!reload) { + resolve(); + } else { + this.loading = true; + this.loadTableData().then(tableData => { + this.chartData = { + columns: this.columns, + rows: tableData.dataList + } + this.loading = false; + if (this.chartObject) this.chartObject.resize(); + resolve(); + }).catch(e => { + console.error(e); + this.loading = false; + reject(e); + }); + } + } + }); + } + /** + * 刷新图表数据 + * @param {Boolean} research 是否按照新的查询条件重新查询(调用verify函数) + */ + refreshChart (research = false) { + if (research) { + if (typeof this.searchVerify === 'function' && !this.searchVerify()) return; + } + + this.loadChartDataImpl(true).catch(e => {}); + } +} diff --git a/orange-demo-single-web/src/views/generated/formClass/index.vue b/orange-demo-single-web/src/views/generated/formClass/index.vue new file mode 100644 index 00000000..196c5948 --- /dev/null +++ b/orange-demo-single-web/src/views/generated/formClass/index.vue @@ -0,0 +1,290 @@ + + + diff --git a/orange-demo-single-web/src/views/generated/formClassCourse/index.vue b/orange-demo-single-web/src/views/generated/formClassCourse/index.vue new file mode 100644 index 00000000..63b69c2e --- /dev/null +++ b/orange-demo-single-web/src/views/generated/formClassCourse/index.vue @@ -0,0 +1,175 @@ + + + diff --git a/orange-demo-single-web/src/views/generated/formClassStudent/index.vue b/orange-demo-single-web/src/views/generated/formClassStudent/index.vue new file mode 100644 index 00000000..ae00f090 --- /dev/null +++ b/orange-demo-single-web/src/views/generated/formClassStudent/index.vue @@ -0,0 +1,169 @@ + + + diff --git a/orange-demo-single-web/src/views/generated/formCourse/index.vue b/orange-demo-single-web/src/views/generated/formCourse/index.vue new file mode 100644 index 00000000..1dcfdb7e --- /dev/null +++ b/orange-demo-single-web/src/views/generated/formCourse/index.vue @@ -0,0 +1,308 @@ + + + diff --git a/orange-demo-single-web/src/views/generated/formCourseStats/index.vue b/orange-demo-single-web/src/views/generated/formCourseStats/index.vue new file mode 100644 index 00000000..5c4376e0 --- /dev/null +++ b/orange-demo-single-web/src/views/generated/formCourseStats/index.vue @@ -0,0 +1,314 @@ + + + diff --git a/orange-demo-single-web/src/views/generated/formCreateClass/index.vue b/orange-demo-single-web/src/views/generated/formCreateClass/index.vue new file mode 100644 index 00000000..75984899 --- /dev/null +++ b/orange-demo-single-web/src/views/generated/formCreateClass/index.vue @@ -0,0 +1,276 @@ + + + diff --git a/orange-demo-single-web/src/views/generated/formCreateCourse/index.vue b/orange-demo-single-web/src/views/generated/formCreateCourse/index.vue new file mode 100644 index 00000000..bd006e71 --- /dev/null +++ b/orange-demo-single-web/src/views/generated/formCreateCourse/index.vue @@ -0,0 +1,310 @@ + + + diff --git a/orange-demo-single-web/src/views/generated/formCreateSchool/index.vue b/orange-demo-single-web/src/views/generated/formCreateSchool/index.vue new file mode 100644 index 00000000..477960ac --- /dev/null +++ b/orange-demo-single-web/src/views/generated/formCreateSchool/index.vue @@ -0,0 +1,197 @@ + + + diff --git a/orange-demo-single-web/src/views/generated/formCreateStudent/index.vue b/orange-demo-single-web/src/views/generated/formCreateStudent/index.vue new file mode 100644 index 00000000..3729a77b --- /dev/null +++ b/orange-demo-single-web/src/views/generated/formCreateStudent/index.vue @@ -0,0 +1,429 @@ + + + diff --git a/orange-demo-single-web/src/views/generated/formEditClass/index.vue b/orange-demo-single-web/src/views/generated/formEditClass/index.vue new file mode 100644 index 00000000..a8850b54 --- /dev/null +++ b/orange-demo-single-web/src/views/generated/formEditClass/index.vue @@ -0,0 +1,280 @@ + + + diff --git a/orange-demo-single-web/src/views/generated/formEditCourse/index.vue b/orange-demo-single-web/src/views/generated/formEditCourse/index.vue new file mode 100644 index 00000000..b2fd7bb1 --- /dev/null +++ b/orange-demo-single-web/src/views/generated/formEditCourse/index.vue @@ -0,0 +1,345 @@ + + + diff --git a/orange-demo-single-web/src/views/generated/formEditSchool/index.vue b/orange-demo-single-web/src/views/generated/formEditSchool/index.vue new file mode 100644 index 00000000..f1176b99 --- /dev/null +++ b/orange-demo-single-web/src/views/generated/formEditSchool/index.vue @@ -0,0 +1,225 @@ + + + diff --git a/orange-demo-single-web/src/views/generated/formEditStudent/index.vue b/orange-demo-single-web/src/views/generated/formEditStudent/index.vue new file mode 100644 index 00000000..d2702c80 --- /dev/null +++ b/orange-demo-single-web/src/views/generated/formEditStudent/index.vue @@ -0,0 +1,519 @@ + + + diff --git a/orange-demo-single-web/src/views/generated/formSchool/index.vue b/orange-demo-single-web/src/views/generated/formSchool/index.vue new file mode 100644 index 00000000..7500d6b6 --- /dev/null +++ b/orange-demo-single-web/src/views/generated/formSchool/index.vue @@ -0,0 +1,263 @@ + + + diff --git a/orange-demo-single-web/src/views/generated/formSetClassCourse/index.vue b/orange-demo-single-web/src/views/generated/formSetClassCourse/index.vue new file mode 100644 index 00000000..a6c1ed4c --- /dev/null +++ b/orange-demo-single-web/src/views/generated/formSetClassCourse/index.vue @@ -0,0 +1,281 @@ + + + diff --git a/orange-demo-single-web/src/views/generated/formSetClassStudent/index.vue b/orange-demo-single-web/src/views/generated/formSetClassStudent/index.vue new file mode 100644 index 00000000..04979609 --- /dev/null +++ b/orange-demo-single-web/src/views/generated/formSetClassStudent/index.vue @@ -0,0 +1,207 @@ + + + diff --git a/orange-demo-single-web/src/views/generated/formStudent/index.vue b/orange-demo-single-web/src/views/generated/formStudent/index.vue new file mode 100644 index 00000000..89630002 --- /dev/null +++ b/orange-demo-single-web/src/views/generated/formStudent/index.vue @@ -0,0 +1,327 @@ + + + diff --git a/orange-demo-single-web/src/views/generated/formStudentActionDetail/index.vue b/orange-demo-single-web/src/views/generated/formStudentActionDetail/index.vue new file mode 100644 index 00000000..129c6a1d --- /dev/null +++ b/orange-demo-single-web/src/views/generated/formStudentActionDetail/index.vue @@ -0,0 +1,240 @@ + + + diff --git a/orange-demo-single-web/src/views/generated/formStudentActionStats/index.vue b/orange-demo-single-web/src/views/generated/formStudentActionStats/index.vue new file mode 100644 index 00000000..02b32705 --- /dev/null +++ b/orange-demo-single-web/src/views/generated/formStudentActionStats/index.vue @@ -0,0 +1,315 @@ + + + diff --git a/orange-demo-single-web/src/views/layout/components/breadcrumb/index.vue b/orange-demo-single-web/src/views/layout/components/breadcrumb/index.vue new file mode 100644 index 00000000..de4573a8 --- /dev/null +++ b/orange-demo-single-web/src/views/layout/components/breadcrumb/index.vue @@ -0,0 +1,53 @@ + + + + + diff --git a/orange-demo-single-web/src/views/layout/components/formModifyPassword/index.vue b/orange-demo-single-web/src/views/layout/components/formModifyPassword/index.vue new file mode 100644 index 00000000..f85c24e2 --- /dev/null +++ b/orange-demo-single-web/src/views/layout/components/formModifyPassword/index.vue @@ -0,0 +1,95 @@ + + + + + diff --git a/orange-demo-single-web/src/views/layout/components/sidebar/menu-item.vue b/orange-demo-single-web/src/views/layout/components/sidebar/menu-item.vue new file mode 100644 index 00000000..3a28543f --- /dev/null +++ b/orange-demo-single-web/src/views/layout/components/sidebar/menu-item.vue @@ -0,0 +1,59 @@ + + + diff --git a/orange-demo-single-web/src/views/layout/components/sidebar/sidebar.vue b/orange-demo-single-web/src/views/layout/components/sidebar/sidebar.vue new file mode 100644 index 00000000..de79cada --- /dev/null +++ b/orange-demo-single-web/src/views/layout/components/sidebar/sidebar.vue @@ -0,0 +1,72 @@ + + + diff --git a/orange-demo-single-web/src/views/layout/components/tags/tagItem.vue b/orange-demo-single-web/src/views/layout/components/tags/tagItem.vue new file mode 100644 index 00000000..80c21563 --- /dev/null +++ b/orange-demo-single-web/src/views/layout/components/tags/tagItem.vue @@ -0,0 +1,70 @@ + + + + + diff --git a/orange-demo-single-web/src/views/layout/components/tags/tagPanel.vue b/orange-demo-single-web/src/views/layout/components/tags/tagPanel.vue new file mode 100644 index 00000000..adaed9e1 --- /dev/null +++ b/orange-demo-single-web/src/views/layout/components/tags/tagPanel.vue @@ -0,0 +1,213 @@ + + + + + diff --git a/orange-demo-single-web/src/views/layout/index.vue b/orange-demo-single-web/src/views/layout/index.vue new file mode 100644 index 00000000..c7ca7762 --- /dev/null +++ b/orange-demo-single-web/src/views/layout/index.vue @@ -0,0 +1,168 @@ + + + + + diff --git a/orange-demo-single-web/src/views/login/index.vue b/orange-demo-single-web/src/views/login/index.vue new file mode 100644 index 00000000..01b3bf67 --- /dev/null +++ b/orange-demo-single-web/src/views/login/index.vue @@ -0,0 +1,102 @@ + + + + + diff --git a/orange-demo-single-web/src/views/upms/formDictManagement/index.vue b/orange-demo-single-web/src/views/upms/formDictManagement/index.vue new file mode 100644 index 00000000..766505ee --- /dev/null +++ b/orange-demo-single-web/src/views/upms/formDictManagement/index.vue @@ -0,0 +1,128 @@ + + + diff --git a/orange-demo-single-web/src/views/upms/formEditDict/index.vue b/orange-demo-single-web/src/views/upms/formEditDict/index.vue new file mode 100644 index 00000000..07a664b3 --- /dev/null +++ b/orange-demo-single-web/src/views/upms/formEditDict/index.vue @@ -0,0 +1,82 @@ + + + + + diff --git a/orange-demo-single-web/src/views/upms/formEditSysMenu/editColumn.vue b/orange-demo-single-web/src/views/upms/formEditSysMenu/editColumn.vue new file mode 100644 index 00000000..41a7b4dc --- /dev/null +++ b/orange-demo-single-web/src/views/upms/formEditSysMenu/editColumn.vue @@ -0,0 +1,108 @@ + + + diff --git a/orange-demo-single-web/src/views/upms/formEditSysMenu/index.vue b/orange-demo-single-web/src/views/upms/formEditSysMenu/index.vue new file mode 100644 index 00000000..d2cce28a --- /dev/null +++ b/orange-demo-single-web/src/views/upms/formEditSysMenu/index.vue @@ -0,0 +1,283 @@ + + + diff --git a/orange-demo-single-web/src/views/upms/formEditSysPerm/index.vue b/orange-demo-single-web/src/views/upms/formEditSysPerm/index.vue new file mode 100644 index 00000000..15b2b621 --- /dev/null +++ b/orange-demo-single-web/src/views/upms/formEditSysPerm/index.vue @@ -0,0 +1,169 @@ + + + diff --git a/orange-demo-single-web/src/views/upms/formEditSysPermCode/index.vue b/orange-demo-single-web/src/views/upms/formEditSysPermCode/index.vue new file mode 100644 index 00000000..f85ef0ef --- /dev/null +++ b/orange-demo-single-web/src/views/upms/formEditSysPermCode/index.vue @@ -0,0 +1,221 @@ + + + diff --git a/orange-demo-single-web/src/views/upms/formEditSysPermModule/index.vue b/orange-demo-single-web/src/views/upms/formEditSysPermModule/index.vue new file mode 100644 index 00000000..33b66617 --- /dev/null +++ b/orange-demo-single-web/src/views/upms/formEditSysPermModule/index.vue @@ -0,0 +1,185 @@ + + + diff --git a/orange-demo-single-web/src/views/upms/formEditSysRole/index.vue b/orange-demo-single-web/src/views/upms/formEditSysRole/index.vue new file mode 100644 index 00000000..5d9d5a5b --- /dev/null +++ b/orange-demo-single-web/src/views/upms/formEditSysRole/index.vue @@ -0,0 +1,157 @@ + + + + + diff --git a/orange-demo-single-web/src/views/upms/formEditSysUser/index.vue b/orange-demo-single-web/src/views/upms/formEditSysUser/index.vue new file mode 100644 index 00000000..0ac0e506 --- /dev/null +++ b/orange-demo-single-web/src/views/upms/formEditSysUser/index.vue @@ -0,0 +1,167 @@ + + + + + diff --git a/orange-demo-single-web/src/views/upms/formMenuPerm/index.vue b/orange-demo-single-web/src/views/upms/formMenuPerm/index.vue new file mode 100644 index 00000000..cb9bf241 --- /dev/null +++ b/orange-demo-single-web/src/views/upms/formMenuPerm/index.vue @@ -0,0 +1,150 @@ + + + + + diff --git a/orange-demo-single-web/src/views/upms/formPermQuery/index.vue b/orange-demo-single-web/src/views/upms/formPermQuery/index.vue new file mode 100644 index 00000000..5d5ab6dc --- /dev/null +++ b/orange-demo-single-web/src/views/upms/formPermQuery/index.vue @@ -0,0 +1,416 @@ + + + + + diff --git a/orange-demo-single-web/src/views/upms/formSetRoleUsers/index.vue b/orange-demo-single-web/src/views/upms/formSetRoleUsers/index.vue new file mode 100644 index 00000000..3dff9c99 --- /dev/null +++ b/orange-demo-single-web/src/views/upms/formSetRoleUsers/index.vue @@ -0,0 +1,216 @@ + + + + + diff --git a/orange-demo-single-web/src/views/upms/formSysMenu/formSysColumnMenu.vue b/orange-demo-single-web/src/views/upms/formSysMenu/formSysColumnMenu.vue new file mode 100644 index 00000000..24fd5abb --- /dev/null +++ b/orange-demo-single-web/src/views/upms/formSysMenu/formSysColumnMenu.vue @@ -0,0 +1,305 @@ + + + diff --git a/orange-demo-single-web/src/views/upms/formSysMenu/index.vue b/orange-demo-single-web/src/views/upms/formSysMenu/index.vue new file mode 100644 index 00000000..e8fd646b --- /dev/null +++ b/orange-demo-single-web/src/views/upms/formSysMenu/index.vue @@ -0,0 +1,239 @@ + + + diff --git a/orange-demo-single-web/src/views/upms/formSysPerm/index.vue b/orange-demo-single-web/src/views/upms/formSysPerm/index.vue new file mode 100644 index 00000000..cab60de3 --- /dev/null +++ b/orange-demo-single-web/src/views/upms/formSysPerm/index.vue @@ -0,0 +1,398 @@ + + + + + diff --git a/orange-demo-single-web/src/views/upms/formSysPermCode/index.vue b/orange-demo-single-web/src/views/upms/formSysPermCode/index.vue new file mode 100644 index 00000000..3ac871fd --- /dev/null +++ b/orange-demo-single-web/src/views/upms/formSysPermCode/index.vue @@ -0,0 +1,254 @@ + + + diff --git a/orange-demo-single-web/src/views/upms/formSysRole/index.vue b/orange-demo-single-web/src/views/upms/formSysRole/index.vue new file mode 100644 index 00000000..d5096d72 --- /dev/null +++ b/orange-demo-single-web/src/views/upms/formSysRole/index.vue @@ -0,0 +1,455 @@ + + + diff --git a/orange-demo-single-web/src/views/upms/formSysRoleUser/index.vue b/orange-demo-single-web/src/views/upms/formSysRoleUser/index.vue new file mode 100644 index 00000000..9796777c --- /dev/null +++ b/orange-demo-single-web/src/views/upms/formSysRoleUser/index.vue @@ -0,0 +1,224 @@ + + + diff --git a/orange-demo-single-web/src/views/upms/formSysUser/index.vue b/orange-demo-single-web/src/views/upms/formSysUser/index.vue new file mode 100644 index 00000000..126e7893 --- /dev/null +++ b/orange-demo-single-web/src/views/upms/formSysUser/index.vue @@ -0,0 +1,253 @@ + + + diff --git a/orange-demo-single-web/src/views/welcome/index.vue b/orange-demo-single-web/src/views/welcome/index.vue new file mode 100644 index 00000000..a067c0ef --- /dev/null +++ b/orange-demo-single-web/src/views/welcome/index.vue @@ -0,0 +1,156 @@ + + + + + + + diff --git a/orange-demo-single-web/static/.gitkeep b/orange-demo-single-web/static/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/orange-demo-single-web/vue.config.js b/orange-demo-single-web/vue.config.js new file mode 100644 index 00000000..41f99a21 --- /dev/null +++ b/orange-demo-single-web/vue.config.js @@ -0,0 +1,5 @@ +module.exports = { + devServer: { + port: 8085 + } +}