From 49ac45ca050a71b2db3c7136b554e659ee4b2b93 Mon Sep 17 00:00:00 2001 From: eibons Date: Fri, 15 Aug 2025 20:58:57 +0800 Subject: [PATCH] init --- .idea/.gitignore | 8 + .idea/encodings.xml | 6 + .idea/misc.xml | 57 + .idea/vcs.xml | 6 + cool-admin-java/.gitignore | 37 + cool-admin-java/Dockerfile | 14 + cool-admin-java/LICENSE | 21 + cool-admin-java/README.md | 103 + cool-admin-java/docker-compose.yml | 43 + cool-admin-java/pom.xml | 213 + .../main/java/com/cool/CoolApplication.java | 74 + .../src/main/java/com/cool/Welcome.java | 17 + .../com/cool/core/annotation/CoolPlugin.java | 12 + .../core/annotation/CoolRestController.java | 34 + .../com/cool/core/annotation/EpsField.java | 14 + .../core/annotation/IgnoreRecycleData.java | 12 + .../cool/core/annotation/NoRepeatSubmit.java | 12 + .../com/cool/core/annotation/TokenIgnore.java | 15 + .../cool/core/aop/NoRepeatSubmitAspect.java | 39 + .../com/cool/core/base/BaseController.java | 277 + .../java/com/cool/core/base/BaseEntity.java | 38 + .../java/com/cool/core/base/BaseService.java | 175 + .../com/cool/core/base/BaseServiceImpl.java | 137 + .../java/com/cool/core/base/ModifyEnum.java | 13 + .../java/com/cool/core/base/TenantEntity.java | 16 + .../base/service/MapperProviderService.java | 52 + .../java/com/cool/core/cache/CoolCache.java | 180 + .../com/cool/core/code/CodeGenerator.java | 108 + .../java/com/cool/core/code/CodeModel.java | 36 + .../java/com/cool/core/code/CodeTypeEnum.java | 21 + .../com/cool/core/config/CoolProperties.java | 23 + .../core/config/CustomOpenApiResource.java | 40 + .../com/cool/core/config/FileModeEnum.java | 28 + .../com/cool/core/config/FileProperties.java | 22 + .../com/cool/core/config/JacksonConfig.java | 67 + .../cool/core/config/LocalFileProperties.java | 30 + .../cool/core/config/LogDiscardPolicy.java | 13 + .../com/cool/core/config/LogProperties.java | 28 + .../core/config/MyBatisFlexConfiguration.java | 27 + .../cool/core/config/OssFileProperties.java | 24 + .../java/com/cool/core/config/PluginJson.java | 57 + .../com/cool/core/config/SwaggerConfig.java | 16 + .../cool/core/config/ThreadPoolConfig.java | 41 + .../com/cool/core/config/TokenProperties.java | 18 + .../core/config/cache/CaffeineConfig.java | 122 + .../cool/core/config/cache/RedisConfig.java | 29 + .../cool/core/enums/AdminComponentsEnum.java | 105 + .../main/java/com/cool/core/enums/Apis.java | 13 + .../com/cool/core/enums/QueryModeEnum.java | 10 + .../com/cool/core/enums/UserTypeEnum.java | 10 + .../main/java/com/cool/core/eps/CoolEps.java | 410 + .../main/java/com/cool/core/eps/EpsEvent.java | 26 + .../cool/core/exception/CoolException.java | 43 + .../core/exception/CoolExceptionHandler.java | 71 + .../core/exception/CoolPreconditions.java | 102 + .../core/file/FileUploadStrategyFactory.java | 53 + .../com/cool/core/file/UpLoadModeType.java | 26 + .../strategy/CloudFileUploadStrategy.java | 33 + .../file/strategy/FileUploadStrategy.java | 38 + .../strategy/LocalFileUploadStrategy.java | 74 + .../com/cool/core/i18n/I18nGenerator.java | 219 + .../com/cool/core/init/CoolPluginInit.java | 24 + .../com/cool/core/init/DBFromJsonInit.java | 252 + .../java/com/cool/core/init/IDGenInit.java | 24 + .../java/com/cool/core/leaf/IDGenService.java | 6 + .../com/cool/core/leaf/common/CheckVO.java | 27 + .../com/cool/core/leaf/common/Result.java | 39 + .../com/cool/core/leaf/common/Status.java | 6 + .../java/com/cool/core/leaf/package-info.java | 5 + .../core/leaf/segment/SegmentIDGenImpl.java | 310 + .../leaf/segment/entity/LeafAllocEntity.java | 27 + .../leaf/segment/mapper/LeafAllocMapper.java | 7 + .../cool/core/leaf/segment/model/Segment.java | 59 + .../leaf/segment/model/SegmentBuffer.java | 129 + .../java/com/cool/core/lock/CoolLock.java | 108 + .../mybatis/handler/BaseJsonTypeHandler.java | 48 + .../mybatis/handler/Fastjson2TypeHandler.java | 73 + .../mybatis/handler/JacksonTypeHandler.java | 68 + .../pg/PostgresSequenceSyncService.java | 66 + .../com/cool/core/request/CrudOption.java | 202 + .../com/cool/core/request/PageResult.java | 33 + .../main/java/com/cool/core/request/R.java | 74 + .../core/request/RequestParamsFilter.java | 114 + .../cool/core/request/RestInterceptor.java | 39 + .../prefix/AutoPrefixConfiguration.java | 17 + .../request/prefix/AutoPrefixUrlMapping.java | 103 + .../EntryPointUnauthorizedHandler.java | 34 + .../core/security/IgnoredUrlsProperties.java | 22 + .../JwtAuthenticationTokenFilter.java | 110 + .../cool/core/security/JwtSecurityConfig.java | 152 + .../security/MyAccessDecisionManager.java | 61 + .../security/MyFilterSecurityInterceptor.java | 68 + .../security/RestAccessDeniedHandler.java | 34 + .../cool/core/security/jwt/JwtTokenUtil.java | 165 + .../com/cool/core/security/jwt/JwtUser.java | 78 + .../cool/core/tenant/CoolTenantFactory.java | 14 + .../com/cool/core/util/AnnotationUtils.java | 73 + .../com/cool/core/util/AutoTypeConverter.java | 27 + .../BodyReaderHttpServletRequestWrapper.java | 119 + .../com/cool/core/util/CompilerUtils.java | 180 + .../java/com/cool/core/util/ConvertUtil.java | 257 + .../cool/core/util/CoolPluginInvokers.java | 165 + .../com/cool/core/util/CoolSecurityUtil.java | 110 + .../cool/core/util/DatabaseDialectUtils.java | 56 + .../java/com/cool/core/util/EntityUtils.java | 121 + .../java/com/cool/core/util/I18nUtil.java | 125 + .../main/java/com/cool/core/util/IPUtils.java | 46 + .../java/com/cool/core/util/MapExtUtil.java | 30 + .../com/cool/core/util/MappingAlgorithm.java | 21 + .../java/com/cool/core/util/PathUtils.java | 70 + .../cool/core/util/SpringContextUtils.java | 45 + .../java/com/cool/core/util/TenantUtil.java | 14 + .../admin/AdminBaseCodingController.java | 43 + .../admin/AdminBaseCommController.java | 107 + .../admin/AdminBaseOpenController.java | 121 + .../sys/AdminBaseSysDepartmentController.java | 35 + .../admin/sys/AdminBaseSysLogController.java | 57 + .../admin/sys/AdminBaseSysMenuController.java | 66 + .../sys/AdminBaseSysParamController.java | 33 + .../admin/sys/AdminBaseSysRoleController.java | 37 + .../admin/sys/AdminBaseSysUserController.java | 34 + .../controller/app/AppBaseCommController.java | 71 + .../modules/base/dto/sys/BaseSysLoginDto.java | 30 + .../modules/base/dto/sys/CodeContentDto.java | 9 + .../base/entity/sys/BaseSysConfEntity.java | 24 + .../entity/sys/BaseSysDepartmentEntity.java | 30 + .../base/entity/sys/BaseSysLogEntity.java | 34 + .../base/entity/sys/BaseSysMenuEntity.java | 52 + .../base/entity/sys/BaseSysParamEntity.java | 29 + .../sys/BaseSysRoleDepartmentEntity.java | 20 + .../base/entity/sys/BaseSysRoleEntity.java | 43 + .../entity/sys/BaseSysRoleMenuEntity.java | 19 + .../base/entity/sys/BaseSysUserEntity.java | 72 + .../entity/sys/BaseSysUserRoleEntity.java | 21 + .../modules/base/filter/BaseLogFilter.java | 33 + .../base/mapper/sys/BaseSysConfMapper.java | 11 + .../mapper/sys/BaseSysDepartmentMapper.java | 10 + .../base/mapper/sys/BaseSysLogMapper.java | 10 + .../base/mapper/sys/BaseSysMenuMapper.java | 20 + .../base/mapper/sys/BaseSysParamMapper.java | 10 + .../sys/BaseSysRoleDepartmentMapper.java | 10 + .../base/mapper/sys/BaseSysRoleMapper.java | 10 + .../mapper/sys/BaseSysRoleMenuMapper.java | 18 + .../base/mapper/sys/BaseSysUserMapper.java | 11 + .../mapper/sys/BaseSysUserRoleMapper.java | 10 + .../security/JwtUserDetailsServiceImpl.java | 57 + .../security/MySecurityMetadataSource.java | 81 + .../base/service/sys/BaseCodingService.java | 11 + .../base/service/sys/BaseSysConfService.java | 41 + .../service/sys/BaseSysDepartmentService.java | 18 + .../base/service/sys/BaseSysLogService.java | 27 + .../base/service/sys/BaseSysLoginService.java | 48 + .../base/service/sys/BaseSysMenuService.java | 18 + .../base/service/sys/BaseSysParamService.java | 25 + .../base/service/sys/BaseSysPermsService.java | 160 + .../base/service/sys/BaseSysRoleService.java | 10 + .../base/service/sys/BaseSysUserService.java | 25 + .../sys/impl/BaseCodingServiceImpl.java | 83 + .../sys/impl/BaseSysConfServiceImpl.java | 58 + .../impl/BaseSysDepartmentServiceImpl.java | 84 + .../sys/impl/BaseSysLogServiceImpl.java | 115 + .../sys/impl/BaseSysLoginServiceImpl.java | 137 + .../sys/impl/BaseSysMenuServiceImpl.java | 180 + .../sys/impl/BaseSysParamServiceImpl.java | 53 + .../sys/impl/BaseSysPermsServiceImpl.java | 262 + .../sys/impl/BaseSysRoleServiceImpl.java | 98 + .../sys/impl/BaseSysUserServiceImpl.java | 187 + .../admin/AdminDictInfoController.java | 57 + .../admin/AdminDictTypeController.java | 36 + .../controller/app/AppDictInfoController.java | 34 + .../modules/dict/entity/DictInfoEntity.java | 32 + .../modules/dict/entity/DictTypeEntity.java | 21 + .../modules/dict/mapper/DictInfoMapper.java | 10 + .../modules/dict/mapper/DictTypeMapper.java | 10 + .../modules/dict/service/DictInfoService.java | 21 + .../modules/dict/service/DictTypeService.java | 10 + .../service/impl/DictInfoServiceImpl.java | 134 + .../service/impl/DictTypeServiceImpl.java | 50 + .../modules/recycle/aop/DeleteAspect.java | 112 + .../admin/AdminRecycleDataController.java | 40 + .../recycle/entity/RecycleDataEntity.java | 56 + .../recycle/mapper/RecycleDataMapper.java | 7 + .../recycle/service/RecycleDataService.java | 21 + .../service/impl/RecycleDataServiceImpl.java | 118 + .../admin/AdminSpaceInfoController.java | 24 + .../admin/AdminSpaceTypeController.java | 23 + .../modules/space/entity/SpaceInfoEntity.java | 57 + .../modules/space/entity/SpaceTypeEntity.java | 21 + .../modules/space/mapper/SpaceInfoMapper.java | 10 + .../modules/space/mapper/SpaceTypeMapper.java | 10 + .../space/service/SpaceInfoService.java | 10 + .../space/service/SpaceTypeService.java | 10 + .../service/impl/SpaceInfoServiceImpl.java | 15 + .../service/impl/SpaceTypeServiceImpl.java | 15 + .../modules/task/config/ScheduleConfig.java | 21 + .../admin/AdminTaskInfoController.java | 60 + .../modules/task/entity/TaskInfoEntity.java | 62 + .../modules/task/entity/TaskLogEntity.java | 29 + .../cool/modules/task/event/TaskEvent.java | 25 + .../modules/task/mapper/TaskInfoMapper.java | 8 + .../modules/task/mapper/TaskLogMapper.java | 8 + .../cool/modules/task/run/ScheduleJob.java | 107 + .../modules/task/run/ScheduleRunnable.java | 101 + .../task/service/TaskInfoLogService.java | 10 + .../modules/task/service/TaskInfoService.java | 48 + .../service/impl/TaskInfoLogServiceImpl.java | 12 + .../service/impl/TaskInfoServiceImpl.java | 139 + .../modules/task/utils/ScheduleUtils.java | 251 + .../admin/AdminUserInfoController.java | 24 + .../app/AppUserAddressController.java | 49 + .../controller/app/AppUserInfoController.java | 70 + .../app/AppUserLoginController.java | 182 + .../controller/app/params/CaptchaParam.java | 12 + .../controller/app/params/LoginParam.java | 34 + .../app/params/RefreshTokenParam.java | 13 + .../controller/app/params/SmsCodeParam.java | 12 + .../user/entity/UserAddressEntity.java | 43 + .../modules/user/entity/UserInfoEntity.java | 40 + .../modules/user/entity/UserWxEntity.java | 47 + .../user/mapper/UserAddressMapper.java | 10 + .../modules/user/mapper/UserInfoMapper.java | 7 + .../modules/user/mapper/UserWxMapper.java | 10 + .../com/cool/modules/user/proxy/WxProxy.java | 36 + .../user/service/UserAddressService.java | 15 + .../modules/user/service/UserInfoService.java | 28 + .../user/service/UserLoginService.java | 57 + .../modules/user/service/UserWxService.java | 15 + .../service/impl/UserAddressServiceImpl.java | 21 + .../service/impl/UserInfoServiceImpl.java | 52 + .../service/impl/UserLoginServiceImpl.java | 192 + .../user/service/impl/UserWxServiceImpl.java | 60 + .../cool/modules/user/util/UserSmsUtil.java | 90 + .../cool/modules/user/util/UserWxUtil.java | 12 + .../pgsql/builder/ColumnSqlBuilder.java | 53 + .../quartz/QuartzAutoConfiguration.java | 159 + .../src/main/resources/application-local.yml | 42 + .../src/main/resources/application-prod.yml | 27 + .../src/main/resources/application.yml | 162 + cool-admin-java/src/main/resources/banner.txt | 8 + .../resources/cool/captcha/bgimages/48.jpg | Bin 0 -> 126519 bytes .../resources/cool/captcha/bgimages/a.jpg | Bin 0 -> 39380 bytes .../resources/cool/captcha/bgimages/b.jpg | Bin 0 -> 50207 bytes .../resources/cool/captcha/bgimages/c.jpg | Bin 0 -> 38739 bytes .../resources/cool/captcha/bgimages/d.jpg | Bin 0 -> 40185 bytes .../resources/cool/captcha/bgimages/e.jpg | Bin 0 -> 53838 bytes .../resources/cool/captcha/bgimages/g.jpg | Bin 0 -> 131652 bytes .../resources/cool/captcha/bgimages/h.jpg | Bin 0 -> 80101 bytes .../resources/cool/captcha/bgimages/i.jpg | Bin 0 -> 133325 bytes .../resources/cool/captcha/bgimages/j.jpg | Bin 0 -> 144883 bytes .../main/resources/cool/code/controller.th | 22 + .../resources/cool/code/mapper/interface.th | 10 + .../main/resources/cool/code/service/impl.th | 14 + .../resources/cool/code/service/interface.th | 10 + .../src/main/resources/cool/data/db/base.json | 121 + .../main/resources/cool/data/menu/menu.json | 813 ++ .../resources/cool/data/menu/menu_8.0.json | 158 + .../src/main/resources/static/css/welcome.css | 89 + .../src/main/resources/static/favicon.ico | Bin 0 -> 67646 bytes .../src/main/resources/static/js/welcome.js | 14 + .../src/main/resources/templates/welcome.html | 25 + .../cool/CoolAdminJavaApplicationTests.java | 13 + .../java/com/cool/CoolCodeGeneratorTest.java | 56 + cool-admin-vue/.cursorrules | 74 + cool-admin-vue/.dockerignore | 5 + cool-admin-vue/.editorconfig | 7 + cool-admin-vue/.env | 5 + cool-admin-vue/.gitattributes | 4 + cool-admin-vue/.gitignore | 20 + cool-admin-vue/.hintrc | 16 + cool-admin-vue/.prettierrc.json | 10 + cool-admin-vue/Dockerfile | 14 + cool-admin-vue/LICENSE | 33 + cool-admin-vue/README.md | 78 + cool-admin-vue/env.d.ts | 10 + cool-admin-vue/eslint.config.js | 73 + cool-admin-vue/index.html | 178 + cool-admin-vue/nginx.conf | 72 + cool-admin-vue/package-lock.json | 8907 +++++++++++++++++ cool-admin-vue/package.json | 75 + cool-admin-vue/pnpm-lock.yaml | 5655 +++++++++++ cool-admin-vue/pnpm-workspace.yaml | 6 + cool-admin-vue/postcss.config.js | 6 + cool-admin-vue/src/App.vue | 8 + cool-admin-vue/src/config/dev.ts | 9 + cool-admin-vue/src/config/index.ts | 62 + cool-admin-vue/src/config/prod.ts | 17 + cool-admin-vue/src/config/proxy.ts | 18 + cool-admin-vue/src/cool/bootstrap/eps.ts | 62 + cool-admin-vue/src/cool/bootstrap/index.ts | 24 + cool-admin-vue/src/cool/bootstrap/module.ts | 126 + cool-admin-vue/src/cool/hooks/browser.ts | 41 + cool-admin-vue/src/cool/hooks/hmr.ts | 32 + cool-admin-vue/src/cool/hooks/index.ts | 58 + cool-admin-vue/src/cool/hooks/mitt.ts | 9 + cool-admin-vue/src/cool/index.ts | 7 + cool-admin-vue/src/cool/index.vue | 39 + cool-admin-vue/src/cool/module/index.ts | 43 + cool-admin-vue/src/cool/router/index.ts | 247 + cool-admin-vue/src/cool/service/base.ts | 86 + cool-admin-vue/src/cool/service/index.ts | 10 + cool-admin-vue/src/cool/service/request.ts | 168 + cool-admin-vue/src/cool/service/stream.ts | 103 + cool-admin-vue/src/cool/types/index.ts | 60 + cool-admin-vue/src/cool/utils/index.ts | 301 + cool-admin-vue/src/cool/utils/loading.ts | 37 + cool-admin-vue/src/cool/utils/storage.ts | 83 + cool-admin-vue/src/main.ts | 14 + .../modules/base/components/avatar/index.tsx | 53 + .../src/modules/base/components/code/json.vue | 156 + .../modules/base/components/dept/check.vue | 111 + .../modules/base/components/dept/select.vue | 87 + .../modules/base/components/editor/index.tsx | 44 + .../src/modules/base/components/icon/svg.vue | 41 + .../modules/base/components/image/index.vue | 111 + .../modules/base/components/link/index.vue | 75 + .../modules/base/components/menu/check.vue | 99 + .../src/modules/base/components/menu/file.vue | 174 + .../src/modules/base/components/menu/icon.vue | 84 + .../modules/base/components/menu/perms.vue | 95 + .../modules/base/components/menu/select.vue | 86 + .../src/modules/base/components/num/index.vue | 61 + cool-admin-vue/src/modules/base/config.ts | 94 + .../src/modules/base/directives/permission.ts | 13 + cool-admin-vue/src/modules/base/index.ts | 9 + .../src/modules/base/locales/en.json | 143 + .../src/modules/base/locales/zh-cn.json | 143 + .../src/modules/base/locales/zh-tw.json | 143 + .../src/modules/base/pages/error/401.vue | 11 + .../src/modules/base/pages/error/403.vue | 11 + .../src/modules/base/pages/error/404.vue | 11 + .../src/modules/base/pages/error/500.vue | 11 + .../src/modules/base/pages/error/502.vue | 11 + .../pages/error/components/error-page.vue | 140 + .../pages/login/components/pic-captcha.vue | 110 + .../src/modules/base/pages/login/index.vue | 307 + .../modules/base/pages/login/static/bg.svg | 39 + .../base/pages/main/components/amenu.vue | 151 + .../base/pages/main/components/bmenu.tsx | 153 + .../base/pages/main/components/global.vue | 37 + .../base/pages/main/components/process.vue | 279 + .../base/pages/main/components/route-nav.vue | 87 + .../base/pages/main/components/slider.vue | 188 + .../base/pages/main/components/topbar.vue | 219 + .../base/pages/main/components/views.vue | 99 + .../src/modules/base/pages/main/index.vue | 132 + .../src/modules/base/static/css/index.scss | 81 + .../src/modules/base/static/svg/amount.svg | 1 + .../src/modules/base/static/svg/back.svg | 17 + .../modules/base/static/svg/close-border.svg | 1 + .../src/modules/base/static/svg/close.svg | 21 + .../src/modules/base/static/svg/delete.svg | 1 + .../src/modules/base/static/svg/edit.svg | 21 + .../src/modules/base/static/svg/exit.svg | 25 + .../src/modules/base/static/svg/expand.svg | 1 + .../src/modules/base/static/svg/export.svg | 1 + .../src/modules/base/static/svg/fail.svg | 1 + .../src/modules/base/static/svg/fold.svg | 1 + .../src/modules/base/static/svg/github.svg | 17 + .../src/modules/base/static/svg/home.svg | 17 + .../modules/base/static/svg/icon-activity.svg | 1 + .../modules/base/static/svg/icon-amount.svg | 9 + .../src/modules/base/static/svg/icon-app.svg | 1 + .../modules/base/static/svg/icon-approve.svg | 1 + .../src/modules/base/static/svg/icon-auth.svg | 1 + .../src/modules/base/static/svg/icon-ban.svg | 1 + .../src/modules/base/static/svg/icon-call.svg | 1 + .../modules/base/static/svg/icon-camera.svg | 1 + .../src/modules/base/static/svg/icon-card.svg | 1 + .../src/modules/base/static/svg/icon-cart.svg | 1 + .../modules/base/static/svg/icon-common.svg | 1 + .../base/static/svg/icon-component.svg | 17 + .../modules/base/static/svg/icon-count.svg | 1 + .../modules/base/static/svg/icon-crown.svg | 1 + .../src/modules/base/static/svg/icon-data.svg | 9 + .../src/modules/base/static/svg/icon-db.svg | 15 + .../modules/base/static/svg/icon-delete.svg | 1 + .../src/modules/base/static/svg/icon-dept.svg | 9 + .../modules/base/static/svg/icon-design.svg | 12 + .../modules/base/static/svg/icon-device.svg | 9 + .../src/modules/base/static/svg/icon-dict.svg | 1 + .../modules/base/static/svg/icon-discover.svg | 1 + .../src/modules/base/static/svg/icon-doc.svg | 1 + .../modules/base/static/svg/icon-download.svg | 1 + .../modules/base/static/svg/icon-emoji.svg | 1 + .../modules/base/static/svg/icon-favor.svg | 1 + .../src/modules/base/static/svg/icon-file.svg | 1 + .../modules/base/static/svg/icon-folder.svg | 1 + .../modules/base/static/svg/icon-goods.svg | 1 + .../src/modules/base/static/svg/icon-home.svg | 1 + .../src/modules/base/static/svg/icon-hot.svg | 1 + .../src/modules/base/static/svg/icon-info.svg | 1 + .../src/modules/base/static/svg/icon-iot.svg | 43 + .../modules/base/static/svg/icon-light.svg | 1 + .../src/modules/base/static/svg/icon-like.svg | 1 + .../src/modules/base/static/svg/icon-list.svg | 9 + .../modules/base/static/svg/icon-local.svg | 1 + .../src/modules/base/static/svg/icon-log.svg | 1 + .../src/modules/base/static/svg/icon-map.svg | 1 + .../modules/base/static/svg/icon-match.svg | 1 + .../src/modules/base/static/svg/icon-menu.svg | 1 + .../modules/base/static/svg/icon-monitor.svg | 9 + .../src/modules/base/static/svg/icon-msg.svg | 1 + .../src/modules/base/static/svg/icon-news.svg | 1 + .../modules/base/static/svg/icon-notice.svg | 1 + .../modules/base/static/svg/icon-params.svg | 9 + .../modules/base/static/svg/icon-phone.svg | 9 + .../src/modules/base/static/svg/icon-pic.svg | 1 + .../modules/base/static/svg/icon-question.svg | 1 + .../modules/base/static/svg/icon-quick.svg | 1 + .../src/modules/base/static/svg/icon-rank.svg | 1 + .../modules/base/static/svg/icon-reward.svg | 1 + .../modules/base/static/svg/icon-search.svg | 1 + .../src/modules/base/static/svg/icon-set.svg | 1 + .../src/modules/base/static/svg/icon-tag.svg | 1 + .../src/modules/base/static/svg/icon-task.svg | 1 + .../src/modules/base/static/svg/icon-time.svg | 1 + .../modules/base/static/svg/icon-tutorial.svg | 1 + .../modules/base/static/svg/icon-unlock.svg | 1 + .../src/modules/base/static/svg/icon-user.svg | 1 + .../modules/base/static/svg/icon-video.svg | 1 + .../src/modules/base/static/svg/icon-vip.svg | 1 + .../src/modules/base/static/svg/icon-warn.svg | 1 + .../src/modules/base/static/svg/icon-work.svg | 1 + .../base/static/svg/icon-workbench.svg | 1 + .../src/modules/base/static/svg/image.svg | 17 + .../src/modules/base/static/svg/import.svg | 1 + .../src/modules/base/static/svg/left.svg | 1 + .../src/modules/base/static/svg/my.svg | 21 + .../src/modules/base/static/svg/order.svg | 1 + .../src/modules/base/static/svg/play.svg | 1 + .../modules/base/static/svg/plus-border.svg | 1 + .../src/modules/base/static/svg/plus.svg | 1 + .../src/modules/base/static/svg/refresh.svg | 21 + .../src/modules/base/static/svg/right.svg | 1 + .../modules/base/static/svg/screen-full.svg | 17 + .../modules/base/static/svg/screen-normal.svg | 17 + .../src/modules/base/static/svg/search.svg | 1 + .../src/modules/base/static/svg/set.svg | 1 + .../src/modules/base/static/svg/sort.svg | 1 + .../src/modules/base/static/svg/stats.svg | 1 + .../src/modules/base/static/svg/success.svg | 1 + .../src/modules/base/static/svg/team.svg | 1 + .../src/modules/base/static/svg/trend.svg | 1 + cool-admin-vue/src/modules/base/store/app.ts | 69 + .../src/modules/base/store/index.ts | 18 + cool-admin-vue/src/modules/base/store/menu.ts | 205 + .../src/modules/base/store/process.ts | 74 + cool-admin-vue/src/modules/base/store/user.ts | 88 + .../src/modules/base/types/index.d.ts | 52 + .../src/modules/base/utils/index.ts | 9 + .../src/modules/base/utils/permission.ts | 30 + .../src/modules/base/views/frame.vue | 49 + .../src/modules/base/views/info.vue | 119 + cool-admin-vue/src/modules/base/views/log.vue | 153 + .../base/views/menu/components/exp.vue | 109 + .../base/views/menu/components/imp.vue | 122 + .../src/modules/base/views/menu/index.vue | 404 + .../src/modules/base/views/param.vue | 226 + .../src/modules/base/views/role.vue | 165 + .../base/views/user/components/dept-list.vue | 503 + .../base/views/user/components/user-move.vue | 74 + .../src/modules/base/views/user/index.vue | 342 + cool-admin-vue/src/modules/demo/config.ts | 27 + .../src/modules/demo/directives/color.ts | 5 + .../src/modules/demo/locales/en.json | 54 + .../src/modules/demo/locales/zh-cn.json | 54 + .../src/modules/demo/locales/zh-tw.json | 54 + .../views/crud/components/adv-search/base.vue | 138 + .../crud/components/adv-search/custom.vue | 152 + .../demo/views/crud/components/code.vue | 45 + .../demo/views/crud/components/crud/all.vue | 578 ++ .../demo/views/crud/components/crud/base.vue | 145 + .../demo/views/crud/components/crud/dict.vue | 164 + .../demo/views/crud/components/crud/event.vue | 182 + .../crud/components/crud/select-table.vue | 155 + .../views/crud/components/crud/service.vue | 179 + .../crud/components/crud/user-select.vue | 77 + .../views/crud/components/form/children.vue | 118 + .../crud/components/form/component/index.vue | 124 + .../form/component/select-labels.vue | 42 + .../form/component/select-status.vue | 47 + .../components/form/component/select-work.vue | 63 + .../form/component/select-work2.vue | 42 + .../views/crud/components/form/config.vue | 122 + .../demo/views/crud/components/form/crud.vue | 151 + .../views/crud/components/form/disabled.vue | 64 + .../demo/views/crud/components/form/event.vue | 93 + .../demo/views/crud/components/form/group.vue | 105 + .../views/crud/components/form/hidden.vue | 77 + .../views/crud/components/form/layout.vue | 98 + .../demo/views/crud/components/form/open.vue | 84 + .../views/crud/components/form/options.vue | 172 + .../crud/components/form/plugin/index.vue | 109 + .../views/crud/components/form/plugin/role.ts | 20 + .../views/crud/components/form/required.vue | 94 + .../demo/views/crud/components/form/rules.vue | 123 + .../views/crud/components/form/setFocus.vue | 63 + .../crud/components/other/context-menu.vue | 71 + .../demo/views/crud/components/other/tips.vue | 150 + .../crud/components/other/tsx/index.scss | 28 + .../views/crud/components/other/tsx/index.tsx | 109 + .../views/crud/components/search/base.vue | 147 + .../views/crud/components/search/collapse.vue | 110 + .../views/crud/components/search/custom.vue | 176 + .../views/crud/components/search/layout.vue | 149 + .../views/crud/components/search/plugin.vue | 128 + .../demo/views/crud/components/table/base.vue | 109 + .../views/crud/components/table/children.vue | 95 + .../crud/components/table/column-custom.vue | 108 + .../crud/components/table/component/index.vue | 108 + .../components/table/component/user-info.vue | 34 + .../crud/components/table/context-menu.vue | 191 + .../demo/views/crud/components/table/dict.vue | 156 + .../views/crud/components/table/formatter.vue | 95 + .../views/crud/components/table/hidden.vue | 127 + .../demo/views/crud/components/table/op.vue | 182 + .../crud/components/table/plugin/base.vue | 130 + .../crud/components/table/plugin/row-edit.vue | 124 + .../crud/components/table/plugin/to-tree.vue | 87 + .../views/crud/components/table/search.vue | 137 + .../views/crud/components/table/selection.vue | 109 + .../demo/views/crud/components/table/slot.vue | 97 + .../crud/components/table/span-method.vue | 115 + .../views/crud/components/table/summary.vue | 95 + .../views/crud/components/upsert/base.vue | 133 + .../views/crud/components/upsert/event.vue | 210 + .../crud/components/upsert/hook/index.vue | 200 + .../crud/components/upsert/hook/reg-pca2.ts | 14 + .../views/crud/components/upsert/mode.vue | 146 + .../src/modules/demo/views/crud/index.vue | 327 + .../views/home/components/category-ratio.vue | 69 + .../views/home/components/count-effect.vue | 89 + .../demo/views/home/components/count-paid.vue | 30 + .../demo/views/home/components/count-user.vue | 58 + .../views/home/components/count-views.vue | 110 + .../demo/views/home/components/hot-goods.vue | 179 + .../demo/views/home/components/tab-chart.vue | 152 + .../src/modules/demo/views/home/index.vue | 106 + .../src/modules/demo/views/test/route.vue | 52 + cool-admin-vue/src/modules/dict/config.ts | 16 + cool-admin-vue/src/modules/dict/index.ts | 7 + .../src/modules/dict/locales/en.json | 16 + .../src/modules/dict/locales/zh-cn.json | 16 + .../src/modules/dict/locales/zh-tw.json | 16 + cool-admin-vue/src/modules/dict/store/dict.ts | 65 + .../src/modules/dict/store/index.ts | 9 + .../src/modules/dict/types/index.d.ts | 15 + .../src/modules/dict/utils/index.ts | 31 + .../src/modules/dict/views/list.vue | 281 + .../modules/helper/components/ai-code/btn.vue | 71 + .../modules/helper/components/ai-code/dev.vue | 76 + .../modules/helper/components/auto-menu.vue | 217 + .../modules/helper/components/auto-perms.vue | 213 + cool-admin-vue/src/modules/helper/config.ts | 30 + .../src/modules/helper/hooks/index.ts | 2 + .../src/modules/helper/hooks/menu.ts | 93 + .../src/modules/helper/hooks/plugin.ts | 120 + .../src/modules/helper/locales/en.json | 66 + .../src/modules/helper/locales/zh-cn.json | 66 + .../src/modules/helper/locales/zh-tw.json | 66 + .../src/modules/helper/static/index.scss | 119 + .../modules/helper/static/svg/icon-vue.svg | 18 + .../src/modules/helper/types/index.d.ts | 35 + .../src/modules/helper/views/ai-code.vue | 246 + .../src/modules/helper/views/plugins.vue | 1033 ++ .../src/modules/recycle/locales/en.json | 14 + .../src/modules/recycle/locales/zh-cn.json | 14 + .../src/modules/recycle/locales/zh-tw.json | 14 + .../src/modules/recycle/views/data.vue | 144 + .../modules/space/components/space-inner.vue | 454 + .../src/modules/space/components/space.vue | 172 + cool-admin-vue/src/modules/space/config.ts | 24 + .../src/modules/space/hooks/index.ts | 19 + .../src/modules/space/locales/en.json | 20 + .../src/modules/space/locales/zh-cn.json | 20 + .../src/modules/space/locales/zh-tw.json | 20 + .../src/modules/space/views/list.vue | 11 + .../src/modules/task/components/logs.vue | 119 + .../src/modules/task/locales/en.json | 34 + .../src/modules/task/locales/zh-cn.json | 34 + .../src/modules/task/locales/zh-tw.json | 34 + .../src/modules/task/views/list.vue | 499 + .../modules/user/components/user-select.vue | 67 + cool-admin-vue/src/modules/user/config.ts | 5 + .../src/modules/user/locales/en.json | 20 + .../src/modules/user/locales/zh-cn.json | 20 + .../src/modules/user/locales/zh-tw.json | 20 + .../src/modules/user/views/list.vue | 208 + cool-admin-vue/src/plugins/crud/comm/index.ts | 10 + .../crud/components/column-custom/index.vue | 186 + .../plugins/crud/components/date/picker.vue | 184 + .../src/plugins/crud/components/date/text.vue | 24 + .../plugins/crud/components/dict/index.tsx | 146 + .../plugins/crud/components/number/range.vue | 78 + .../plugins/crud/components/render/index.tsx | 18 + .../plugins/crud/components/select/button.tsx | 32 + .../plugins/crud/components/select/index.scss | 35 + .../plugins/crud/components/select/index.tsx | 275 + .../plugins/crud/components/select/table.vue | 433 + .../plugins/crud/components/switch/index.tsx | 130 + .../plugins/crud/components/text/index.tsx | 28 + .../plugins/crud/components/user/select.vue | 385 + cool-admin-vue/src/plugins/crud/config.ts | 68 + cool-admin-vue/src/plugins/crud/index.ts | 2 + .../src/plugins/crud/locales/en.json | 35 + .../src/plugins/crud/locales/zh-cn.json | 35 + .../src/plugins/crud/locales/zh-tw.json | 35 + .../src/plugins/crud/plugins/form/index.ts | 5 + .../src/plugins/crud/plugins/form/setFocus.ts | 47 + .../src/plugins/crud/plugins/index.ts | 9 + .../src/plugins/crud/plugins/search/index.ts | 5 + .../plugins/crud/plugins/search/setAuto.ts | 125 + .../src/plugins/crud/plugins/table/index.ts | 7 + .../plugins/crud/plugins/table/rowEdit.tsx | 135 + .../src/plugins/crud/plugins/table/toTree.ts | 116 + .../plugins/dev-tools/components/account.vue | 159 + .../src/plugins/dev-tools/components/dict.vue | 139 + .../src/plugins/dev-tools/components/doc.vue | 148 + .../src/plugins/dev-tools/components/eps.vue | 158 + .../plugins/dev-tools/components/index.vue | 297 + .../plugins/dev-tools/components/proxy.vue | 86 + .../src/plugins/dev-tools/config.ts | 9 + .../src/plugins/dev-tools/locales/en.json | 14 + .../src/plugins/dev-tools/locales/zh-cn.json | 14 + .../src/plugins/dev-tools/locales/zh-tw.json | 14 + .../src/plugins/dev-tools/static/cool.png | Bin 0 -> 4427 bytes .../src/plugins/dev-tools/static/echarts.png | Bin 0 -> 1074 bytes .../plugins/dev-tools/static/element-plus.png | Bin 0 -> 938 bytes .../src/plugins/dev-tools/static/lodash.png | Bin 0 -> 1765 bytes .../src/plugins/dev-tools/static/logo.png | Bin 0 -> 1180 bytes .../src/plugins/dev-tools/static/pinia.png | Bin 0 -> 11675 bytes .../plugins/dev-tools/static/tailwindcss.png | Bin 0 -> 741 bytes .../src/plugins/dev-tools/static/vite.png | Bin 0 -> 9733 bytes .../src/plugins/dev-tools/static/vue.png | Bin 0 -> 918 bytes .../src/plugins/dev-tools/utils/index.ts | 7 + .../plugins/distpicker/components/index.tsx | 52 + .../src/plugins/distpicker/config.ts | 37 + .../src/plugins/distpicker/data/pca.json | 5300 ++++++++++ .../src/plugins/distpicker/demo/base.vue | 10 + cool-admin-vue/src/plugins/echarts/config.ts | 20 + .../editor-preview/components/preview.vue | 230 + .../src/plugins/editor-preview/config.ts | 20 + .../src/plugins/editor-preview/demo/base.vue | 11 + .../plugins/editor-preview/locales/en.json | 9 + .../plugins/editor-preview/locales/zh-cn.json | 9 + .../plugins/editor-preview/locales/zh-tw.json | 9 + .../plugins/editor-wang/components/wang.vue | 236 + .../src/plugins/editor-wang/config.ts | 21 + .../src/plugins/editor-wang/demo/base.vue | 11 + .../src/plugins/editor-wang/locales/en.json | 3 + .../plugins/editor-wang/locales/zh-cn.json | 3 + .../plugins/editor-wang/locales/zh-tw.json | 3 + .../src/plugins/element-ui/config.ts | 33 + .../src/plugins/element-ui/css/index.scss | 126 + .../plugins/excel/components/export-btn.tsx | 209 + .../plugins/excel/components/import-btn.vue | 413 + cool-admin-vue/src/plugins/excel/config.ts | 23 + .../src/plugins/excel/demo/base.vue | 78 + .../src/plugins/excel/locales/en.json | 17 + .../src/plugins/excel/locales/zh-cn.json | 17 + .../src/plugins/excel/locales/zh-tw.json | 17 + .../src/plugins/excel/utils/index.ts | 226 + .../src/plugins/github/components/code.vue | 11 + cool-admin-vue/src/plugins/github/config.ts | 9 + .../src/plugins/i18n/components/switch.vue | 72 + cool-admin-vue/src/plugins/i18n/config.ts | 31 + cool-admin-vue/src/plugins/i18n/index.ts | 16 + .../src/plugins/i18n/static/svg/lang.svg | 17 + cool-admin-vue/src/plugins/iconfont/config.ts | 21 + cool-admin-vue/src/plugins/iconfont/index.ts | 1 + .../src/plugins/iconfont/utils/index.ts | 13 + cool-admin-vue/src/plugins/tailwind/config.ts | 14 + .../src/plugins/tailwind/static/index.css | 3 + .../src/plugins/theme/components/theme.vue | 201 + cool-admin-vue/src/plugins/theme/config.ts | 75 + .../src/plugins/theme/hooks/index.ts | 151 + cool-admin-vue/src/plugins/theme/index.ts | 1 + .../src/plugins/theme/locales/en.json | 16 + .../src/plugins/theme/locales/zh-cn.json | 16 + .../src/plugins/theme/locales/zh-tw.json | 16 + .../src/plugins/theme/static/css/index.scss | 32 + .../src/plugins/theme/static/svg/dark.svg | 1 + .../src/plugins/theme/static/svg/light.svg | 1 + .../src/plugins/theme/static/svg/theme.svg | 12 + .../src/plugins/theme/types/index.d.ts | 7 + .../src/plugins/theme/utils/index.ts | 16 + .../upload/components/upload-item/index.vue | 445 + .../upload/components/upload-item/viewer.vue | 112 + .../src/plugins/upload/components/upload.vue | 642 ++ cool-admin-vue/src/plugins/upload/config.ts | 132 + .../src/plugins/upload/demo/base.vue | 9 + .../src/plugins/upload/demo/check.vue | 20 + .../src/plugins/upload/demo/custom.vue | 27 + .../src/plugins/upload/demo/drag.vue | 11 + .../src/plugins/upload/demo/file.vue | 9 + .../src/plugins/upload/demo/multiple.vue | 9 + .../src/plugins/upload/demo/small.vue | 9 + .../src/plugins/upload/demo/space.vue | 66 + .../src/plugins/upload/hooks/index.ts | 191 + cool-admin-vue/src/plugins/upload/index.ts | 2 + .../src/plugins/upload/locales/en.json | 22 + .../src/plugins/upload/locales/zh-cn.json | 22 + .../src/plugins/upload/locales/zh-tw.json | 22 + .../src/plugins/upload/static/svg/audio.svg | 30 + .../src/plugins/upload/static/svg/excel.svg | 30 + .../src/plugins/upload/static/svg/file.svg | 48 + .../src/plugins/upload/static/svg/image.svg | 30 + .../src/plugins/upload/static/svg/pdf.svg | 30 + .../src/plugins/upload/static/svg/ppt.svg | 30 + .../src/plugins/upload/static/svg/rar.svg | 71 + .../src/plugins/upload/static/svg/video.svg | 26 + .../src/plugins/upload/static/svg/word.svg | 30 + .../src/plugins/upload/types/index.d.ts | 36 + .../src/plugins/upload/utils/index.ts | 74 + .../src/plugins/view/components/group.vue | 701 ++ .../src/plugins/view/components/head.vue | 65 + cool-admin-vue/src/plugins/view/config.ts | 24 + .../src/plugins/view/demo/group.vue | 19 + cool-admin-vue/src/plugins/view/demo/head.vue | 5 + .../src/plugins/view/hooks/group.ts | 13 + .../src/plugins/view/hooks/index.ts | 1 + cool-admin-vue/src/plugins/view/index.ts | 1 + .../src/plugins/view/locales/en.json | 15 + .../src/plugins/view/locales/zh-cn.json | 15 + .../src/plugins/view/locales/zh-tw.json | 15 + .../src/plugins/view/types/index.d.ts | 69 + cool-admin-vue/src/shims-vue.d.ts | 8 + cool-admin-vue/tailwind.config.js | 4 + cool-admin-vue/tsconfig.json | 26 + cool-admin-vue/vite.config.ts | 108 + 730 files changed, 68015 insertions(+) create mode 100644 .idea/.gitignore create mode 100644 .idea/encodings.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/vcs.xml create mode 100644 cool-admin-java/.gitignore create mode 100644 cool-admin-java/Dockerfile create mode 100644 cool-admin-java/LICENSE create mode 100644 cool-admin-java/README.md create mode 100644 cool-admin-java/docker-compose.yml create mode 100644 cool-admin-java/pom.xml create mode 100644 cool-admin-java/src/main/java/com/cool/CoolApplication.java create mode 100644 cool-admin-java/src/main/java/com/cool/Welcome.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/annotation/CoolPlugin.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/annotation/CoolRestController.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/annotation/EpsField.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/annotation/IgnoreRecycleData.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/annotation/NoRepeatSubmit.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/annotation/TokenIgnore.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/aop/NoRepeatSubmitAspect.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/base/BaseController.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/base/BaseEntity.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/base/BaseService.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/base/BaseServiceImpl.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/base/ModifyEnum.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/base/TenantEntity.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/base/service/MapperProviderService.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/cache/CoolCache.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/code/CodeGenerator.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/code/CodeModel.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/code/CodeTypeEnum.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/config/CoolProperties.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/config/CustomOpenApiResource.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/config/FileModeEnum.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/config/FileProperties.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/config/JacksonConfig.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/config/LocalFileProperties.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/config/LogDiscardPolicy.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/config/LogProperties.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/config/MyBatisFlexConfiguration.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/config/OssFileProperties.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/config/PluginJson.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/config/SwaggerConfig.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/config/ThreadPoolConfig.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/config/TokenProperties.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/config/cache/CaffeineConfig.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/config/cache/RedisConfig.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/enums/AdminComponentsEnum.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/enums/Apis.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/enums/QueryModeEnum.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/enums/UserTypeEnum.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/eps/CoolEps.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/eps/EpsEvent.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/exception/CoolException.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/exception/CoolExceptionHandler.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/exception/CoolPreconditions.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/file/FileUploadStrategyFactory.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/file/UpLoadModeType.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/file/strategy/CloudFileUploadStrategy.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/file/strategy/FileUploadStrategy.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/file/strategy/LocalFileUploadStrategy.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/i18n/I18nGenerator.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/init/CoolPluginInit.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/init/DBFromJsonInit.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/init/IDGenInit.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/leaf/IDGenService.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/leaf/common/CheckVO.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/leaf/common/Result.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/leaf/common/Status.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/leaf/package-info.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/leaf/segment/SegmentIDGenImpl.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/leaf/segment/entity/LeafAllocEntity.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/leaf/segment/mapper/LeafAllocMapper.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/leaf/segment/model/Segment.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/leaf/segment/model/SegmentBuffer.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/lock/CoolLock.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/mybatis/handler/BaseJsonTypeHandler.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/mybatis/handler/Fastjson2TypeHandler.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/mybatis/handler/JacksonTypeHandler.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/mybatis/pg/PostgresSequenceSyncService.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/request/CrudOption.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/request/PageResult.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/request/R.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/request/RequestParamsFilter.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/request/RestInterceptor.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/request/prefix/AutoPrefixConfiguration.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/request/prefix/AutoPrefixUrlMapping.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/security/EntryPointUnauthorizedHandler.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/security/IgnoredUrlsProperties.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/security/JwtAuthenticationTokenFilter.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/security/JwtSecurityConfig.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/security/MyAccessDecisionManager.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/security/MyFilterSecurityInterceptor.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/security/RestAccessDeniedHandler.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/security/jwt/JwtTokenUtil.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/security/jwt/JwtUser.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/tenant/CoolTenantFactory.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/util/AnnotationUtils.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/util/AutoTypeConverter.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/util/BodyReaderHttpServletRequestWrapper.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/util/CompilerUtils.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/util/ConvertUtil.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/util/CoolPluginInvokers.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/util/CoolSecurityUtil.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/util/DatabaseDialectUtils.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/util/EntityUtils.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/util/I18nUtil.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/util/IPUtils.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/util/MapExtUtil.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/util/MappingAlgorithm.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/util/PathUtils.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/util/SpringContextUtils.java create mode 100644 cool-admin-java/src/main/java/com/cool/core/util/TenantUtil.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/controller/admin/AdminBaseCodingController.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/controller/admin/AdminBaseCommController.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/controller/admin/AdminBaseOpenController.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/controller/admin/sys/AdminBaseSysDepartmentController.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/controller/admin/sys/AdminBaseSysLogController.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/controller/admin/sys/AdminBaseSysMenuController.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/controller/admin/sys/AdminBaseSysParamController.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/controller/admin/sys/AdminBaseSysRoleController.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/controller/admin/sys/AdminBaseSysUserController.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/controller/app/AppBaseCommController.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/dto/sys/BaseSysLoginDto.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/dto/sys/CodeContentDto.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/entity/sys/BaseSysConfEntity.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/entity/sys/BaseSysDepartmentEntity.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/entity/sys/BaseSysLogEntity.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/entity/sys/BaseSysMenuEntity.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/entity/sys/BaseSysParamEntity.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/entity/sys/BaseSysRoleDepartmentEntity.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/entity/sys/BaseSysRoleEntity.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/entity/sys/BaseSysRoleMenuEntity.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/entity/sys/BaseSysUserEntity.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/entity/sys/BaseSysUserRoleEntity.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/filter/BaseLogFilter.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/mapper/sys/BaseSysConfMapper.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/mapper/sys/BaseSysDepartmentMapper.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/mapper/sys/BaseSysLogMapper.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/mapper/sys/BaseSysMenuMapper.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/mapper/sys/BaseSysParamMapper.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/mapper/sys/BaseSysRoleDepartmentMapper.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/mapper/sys/BaseSysRoleMapper.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/mapper/sys/BaseSysRoleMenuMapper.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/mapper/sys/BaseSysUserMapper.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/mapper/sys/BaseSysUserRoleMapper.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/security/JwtUserDetailsServiceImpl.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/security/MySecurityMetadataSource.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/service/sys/BaseCodingService.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/service/sys/BaseSysConfService.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/service/sys/BaseSysDepartmentService.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/service/sys/BaseSysLogService.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/service/sys/BaseSysLoginService.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/service/sys/BaseSysMenuService.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/service/sys/BaseSysParamService.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/service/sys/BaseSysPermsService.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/service/sys/BaseSysRoleService.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/service/sys/BaseSysUserService.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/service/sys/impl/BaseCodingServiceImpl.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysConfServiceImpl.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysDepartmentServiceImpl.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysLogServiceImpl.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysLoginServiceImpl.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysMenuServiceImpl.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysParamServiceImpl.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysPermsServiceImpl.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysRoleServiceImpl.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysUserServiceImpl.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/dict/controller/admin/AdminDictInfoController.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/dict/controller/admin/AdminDictTypeController.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/dict/controller/app/AppDictInfoController.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/dict/entity/DictInfoEntity.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/dict/entity/DictTypeEntity.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/dict/mapper/DictInfoMapper.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/dict/mapper/DictTypeMapper.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/dict/service/DictInfoService.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/dict/service/DictTypeService.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/dict/service/impl/DictInfoServiceImpl.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/dict/service/impl/DictTypeServiceImpl.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/recycle/aop/DeleteAspect.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/recycle/controller/admin/AdminRecycleDataController.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/recycle/entity/RecycleDataEntity.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/recycle/mapper/RecycleDataMapper.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/recycle/service/RecycleDataService.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/recycle/service/impl/RecycleDataServiceImpl.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/space/controller/admin/AdminSpaceInfoController.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/space/controller/admin/AdminSpaceTypeController.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/space/entity/SpaceInfoEntity.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/space/entity/SpaceTypeEntity.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/space/mapper/SpaceInfoMapper.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/space/mapper/SpaceTypeMapper.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/space/service/SpaceInfoService.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/space/service/SpaceTypeService.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/space/service/impl/SpaceInfoServiceImpl.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/space/service/impl/SpaceTypeServiceImpl.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/task/config/ScheduleConfig.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/task/controller/admin/AdminTaskInfoController.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/task/entity/TaskInfoEntity.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/task/entity/TaskLogEntity.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/task/event/TaskEvent.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/task/mapper/TaskInfoMapper.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/task/mapper/TaskLogMapper.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/task/run/ScheduleJob.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/task/run/ScheduleRunnable.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/task/service/TaskInfoLogService.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/task/service/TaskInfoService.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/task/service/impl/TaskInfoLogServiceImpl.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/task/service/impl/TaskInfoServiceImpl.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/task/utils/ScheduleUtils.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/user/controller/admin/AdminUserInfoController.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/user/controller/app/AppUserAddressController.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/user/controller/app/AppUserInfoController.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/user/controller/app/AppUserLoginController.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/user/controller/app/params/CaptchaParam.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/user/controller/app/params/LoginParam.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/user/controller/app/params/RefreshTokenParam.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/user/controller/app/params/SmsCodeParam.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/user/entity/UserAddressEntity.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/user/entity/UserInfoEntity.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/user/entity/UserWxEntity.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/user/mapper/UserAddressMapper.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/user/mapper/UserInfoMapper.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/user/mapper/UserWxMapper.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/user/proxy/WxProxy.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/user/service/UserAddressService.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/user/service/UserInfoService.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/user/service/UserLoginService.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/user/service/UserWxService.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/user/service/impl/UserAddressServiceImpl.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/user/service/impl/UserInfoServiceImpl.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/user/service/impl/UserLoginServiceImpl.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/user/service/impl/UserWxServiceImpl.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/user/util/UserSmsUtil.java create mode 100644 cool-admin-java/src/main/java/com/cool/modules/user/util/UserWxUtil.java create mode 100644 cool-admin-java/src/main/java/org/dromara/autotable/core/strategy/pgsql/builder/ColumnSqlBuilder.java create mode 100644 cool-admin-java/src/main/java/org/springframework/boot/autoconfigure/quartz/QuartzAutoConfiguration.java create mode 100644 cool-admin-java/src/main/resources/application-local.yml create mode 100644 cool-admin-java/src/main/resources/application-prod.yml create mode 100644 cool-admin-java/src/main/resources/application.yml create mode 100644 cool-admin-java/src/main/resources/banner.txt create mode 100644 cool-admin-java/src/main/resources/cool/captcha/bgimages/48.jpg create mode 100644 cool-admin-java/src/main/resources/cool/captcha/bgimages/a.jpg create mode 100644 cool-admin-java/src/main/resources/cool/captcha/bgimages/b.jpg create mode 100644 cool-admin-java/src/main/resources/cool/captcha/bgimages/c.jpg create mode 100644 cool-admin-java/src/main/resources/cool/captcha/bgimages/d.jpg create mode 100644 cool-admin-java/src/main/resources/cool/captcha/bgimages/e.jpg create mode 100644 cool-admin-java/src/main/resources/cool/captcha/bgimages/g.jpg create mode 100644 cool-admin-java/src/main/resources/cool/captcha/bgimages/h.jpg create mode 100644 cool-admin-java/src/main/resources/cool/captcha/bgimages/i.jpg create mode 100644 cool-admin-java/src/main/resources/cool/captcha/bgimages/j.jpg create mode 100644 cool-admin-java/src/main/resources/cool/code/controller.th create mode 100644 cool-admin-java/src/main/resources/cool/code/mapper/interface.th create mode 100644 cool-admin-java/src/main/resources/cool/code/service/impl.th create mode 100644 cool-admin-java/src/main/resources/cool/code/service/interface.th create mode 100644 cool-admin-java/src/main/resources/cool/data/db/base.json create mode 100644 cool-admin-java/src/main/resources/cool/data/menu/menu.json create mode 100644 cool-admin-java/src/main/resources/cool/data/menu/menu_8.0.json create mode 100644 cool-admin-java/src/main/resources/static/css/welcome.css create mode 100644 cool-admin-java/src/main/resources/static/favicon.ico create mode 100644 cool-admin-java/src/main/resources/static/js/welcome.js create mode 100644 cool-admin-java/src/main/resources/templates/welcome.html create mode 100644 cool-admin-java/src/test/java/com/cool/CoolAdminJavaApplicationTests.java create mode 100644 cool-admin-java/src/test/java/com/cool/CoolCodeGeneratorTest.java create mode 100644 cool-admin-vue/.cursorrules create mode 100644 cool-admin-vue/.dockerignore create mode 100644 cool-admin-vue/.editorconfig create mode 100644 cool-admin-vue/.env create mode 100644 cool-admin-vue/.gitattributes create mode 100644 cool-admin-vue/.gitignore create mode 100644 cool-admin-vue/.hintrc create mode 100644 cool-admin-vue/.prettierrc.json create mode 100644 cool-admin-vue/Dockerfile create mode 100644 cool-admin-vue/LICENSE create mode 100644 cool-admin-vue/README.md create mode 100644 cool-admin-vue/env.d.ts create mode 100644 cool-admin-vue/eslint.config.js create mode 100644 cool-admin-vue/index.html create mode 100644 cool-admin-vue/nginx.conf create mode 100644 cool-admin-vue/package-lock.json create mode 100644 cool-admin-vue/package.json create mode 100644 cool-admin-vue/pnpm-lock.yaml create mode 100644 cool-admin-vue/pnpm-workspace.yaml create mode 100644 cool-admin-vue/postcss.config.js create mode 100644 cool-admin-vue/src/App.vue create mode 100644 cool-admin-vue/src/config/dev.ts create mode 100644 cool-admin-vue/src/config/index.ts create mode 100644 cool-admin-vue/src/config/prod.ts create mode 100644 cool-admin-vue/src/config/proxy.ts create mode 100644 cool-admin-vue/src/cool/bootstrap/eps.ts create mode 100644 cool-admin-vue/src/cool/bootstrap/index.ts create mode 100644 cool-admin-vue/src/cool/bootstrap/module.ts create mode 100644 cool-admin-vue/src/cool/hooks/browser.ts create mode 100644 cool-admin-vue/src/cool/hooks/hmr.ts create mode 100644 cool-admin-vue/src/cool/hooks/index.ts create mode 100644 cool-admin-vue/src/cool/hooks/mitt.ts create mode 100644 cool-admin-vue/src/cool/index.ts create mode 100644 cool-admin-vue/src/cool/index.vue create mode 100644 cool-admin-vue/src/cool/module/index.ts create mode 100644 cool-admin-vue/src/cool/router/index.ts create mode 100644 cool-admin-vue/src/cool/service/base.ts create mode 100644 cool-admin-vue/src/cool/service/index.ts create mode 100644 cool-admin-vue/src/cool/service/request.ts create mode 100644 cool-admin-vue/src/cool/service/stream.ts create mode 100644 cool-admin-vue/src/cool/types/index.ts create mode 100644 cool-admin-vue/src/cool/utils/index.ts create mode 100644 cool-admin-vue/src/cool/utils/loading.ts create mode 100644 cool-admin-vue/src/cool/utils/storage.ts create mode 100644 cool-admin-vue/src/main.ts create mode 100644 cool-admin-vue/src/modules/base/components/avatar/index.tsx create mode 100644 cool-admin-vue/src/modules/base/components/code/json.vue create mode 100644 cool-admin-vue/src/modules/base/components/dept/check.vue create mode 100644 cool-admin-vue/src/modules/base/components/dept/select.vue create mode 100644 cool-admin-vue/src/modules/base/components/editor/index.tsx create mode 100644 cool-admin-vue/src/modules/base/components/icon/svg.vue create mode 100644 cool-admin-vue/src/modules/base/components/image/index.vue create mode 100644 cool-admin-vue/src/modules/base/components/link/index.vue create mode 100644 cool-admin-vue/src/modules/base/components/menu/check.vue create mode 100644 cool-admin-vue/src/modules/base/components/menu/file.vue create mode 100644 cool-admin-vue/src/modules/base/components/menu/icon.vue create mode 100644 cool-admin-vue/src/modules/base/components/menu/perms.vue create mode 100644 cool-admin-vue/src/modules/base/components/menu/select.vue create mode 100644 cool-admin-vue/src/modules/base/components/num/index.vue create mode 100644 cool-admin-vue/src/modules/base/config.ts create mode 100644 cool-admin-vue/src/modules/base/directives/permission.ts create mode 100644 cool-admin-vue/src/modules/base/index.ts create mode 100644 cool-admin-vue/src/modules/base/locales/en.json create mode 100644 cool-admin-vue/src/modules/base/locales/zh-cn.json create mode 100644 cool-admin-vue/src/modules/base/locales/zh-tw.json create mode 100644 cool-admin-vue/src/modules/base/pages/error/401.vue create mode 100644 cool-admin-vue/src/modules/base/pages/error/403.vue create mode 100644 cool-admin-vue/src/modules/base/pages/error/404.vue create mode 100644 cool-admin-vue/src/modules/base/pages/error/500.vue create mode 100644 cool-admin-vue/src/modules/base/pages/error/502.vue create mode 100644 cool-admin-vue/src/modules/base/pages/error/components/error-page.vue create mode 100644 cool-admin-vue/src/modules/base/pages/login/components/pic-captcha.vue create mode 100644 cool-admin-vue/src/modules/base/pages/login/index.vue create mode 100644 cool-admin-vue/src/modules/base/pages/login/static/bg.svg create mode 100644 cool-admin-vue/src/modules/base/pages/main/components/amenu.vue create mode 100644 cool-admin-vue/src/modules/base/pages/main/components/bmenu.tsx create mode 100644 cool-admin-vue/src/modules/base/pages/main/components/global.vue create mode 100644 cool-admin-vue/src/modules/base/pages/main/components/process.vue create mode 100644 cool-admin-vue/src/modules/base/pages/main/components/route-nav.vue create mode 100644 cool-admin-vue/src/modules/base/pages/main/components/slider.vue create mode 100644 cool-admin-vue/src/modules/base/pages/main/components/topbar.vue create mode 100644 cool-admin-vue/src/modules/base/pages/main/components/views.vue create mode 100644 cool-admin-vue/src/modules/base/pages/main/index.vue create mode 100644 cool-admin-vue/src/modules/base/static/css/index.scss create mode 100644 cool-admin-vue/src/modules/base/static/svg/amount.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/back.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/close-border.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/close.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/delete.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/edit.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/exit.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/expand.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/export.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/fail.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/fold.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/github.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/home.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-activity.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-amount.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-app.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-approve.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-auth.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-ban.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-call.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-camera.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-card.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-cart.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-common.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-component.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-count.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-crown.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-data.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-db.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-delete.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-dept.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-design.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-device.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-dict.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-discover.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-doc.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-download.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-emoji.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-favor.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-file.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-folder.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-goods.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-home.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-hot.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-info.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-iot.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-light.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-like.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-list.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-local.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-log.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-map.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-match.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-menu.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-monitor.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-msg.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-news.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-notice.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-params.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-phone.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-pic.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-question.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-quick.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-rank.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-reward.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-search.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-set.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-tag.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-task.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-time.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-tutorial.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-unlock.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-user.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-video.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-vip.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-warn.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-work.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/icon-workbench.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/image.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/import.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/left.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/my.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/order.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/play.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/plus-border.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/plus.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/refresh.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/right.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/screen-full.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/screen-normal.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/search.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/set.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/sort.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/stats.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/success.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/team.svg create mode 100644 cool-admin-vue/src/modules/base/static/svg/trend.svg create mode 100644 cool-admin-vue/src/modules/base/store/app.ts create mode 100644 cool-admin-vue/src/modules/base/store/index.ts create mode 100644 cool-admin-vue/src/modules/base/store/menu.ts create mode 100644 cool-admin-vue/src/modules/base/store/process.ts create mode 100644 cool-admin-vue/src/modules/base/store/user.ts create mode 100644 cool-admin-vue/src/modules/base/types/index.d.ts create mode 100644 cool-admin-vue/src/modules/base/utils/index.ts create mode 100644 cool-admin-vue/src/modules/base/utils/permission.ts create mode 100644 cool-admin-vue/src/modules/base/views/frame.vue create mode 100644 cool-admin-vue/src/modules/base/views/info.vue create mode 100644 cool-admin-vue/src/modules/base/views/log.vue create mode 100644 cool-admin-vue/src/modules/base/views/menu/components/exp.vue create mode 100644 cool-admin-vue/src/modules/base/views/menu/components/imp.vue create mode 100644 cool-admin-vue/src/modules/base/views/menu/index.vue create mode 100644 cool-admin-vue/src/modules/base/views/param.vue create mode 100644 cool-admin-vue/src/modules/base/views/role.vue create mode 100644 cool-admin-vue/src/modules/base/views/user/components/dept-list.vue create mode 100644 cool-admin-vue/src/modules/base/views/user/components/user-move.vue create mode 100644 cool-admin-vue/src/modules/base/views/user/index.vue create mode 100644 cool-admin-vue/src/modules/demo/config.ts create mode 100644 cool-admin-vue/src/modules/demo/directives/color.ts create mode 100644 cool-admin-vue/src/modules/demo/locales/en.json create mode 100644 cool-admin-vue/src/modules/demo/locales/zh-cn.json create mode 100644 cool-admin-vue/src/modules/demo/locales/zh-tw.json create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/adv-search/base.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/adv-search/custom.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/code.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/crud/all.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/crud/base.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/crud/dict.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/crud/event.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/crud/select-table.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/crud/service.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/crud/user-select.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/form/children.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/form/component/index.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/form/component/select-labels.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/form/component/select-status.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/form/component/select-work.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/form/component/select-work2.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/form/config.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/form/crud.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/form/disabled.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/form/event.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/form/group.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/form/hidden.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/form/layout.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/form/open.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/form/options.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/form/plugin/index.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/form/plugin/role.ts create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/form/required.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/form/rules.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/form/setFocus.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/other/context-menu.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/other/tips.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/other/tsx/index.scss create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/other/tsx/index.tsx create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/search/base.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/search/collapse.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/search/custom.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/search/layout.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/search/plugin.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/table/base.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/table/children.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/table/column-custom.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/table/component/index.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/table/component/user-info.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/table/context-menu.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/table/dict.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/table/formatter.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/table/hidden.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/table/op.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/table/plugin/base.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/table/plugin/row-edit.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/table/plugin/to-tree.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/table/search.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/table/selection.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/table/slot.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/table/span-method.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/table/summary.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/upsert/base.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/upsert/event.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/upsert/hook/index.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/upsert/hook/reg-pca2.ts create mode 100644 cool-admin-vue/src/modules/demo/views/crud/components/upsert/mode.vue create mode 100644 cool-admin-vue/src/modules/demo/views/crud/index.vue create mode 100644 cool-admin-vue/src/modules/demo/views/home/components/category-ratio.vue create mode 100644 cool-admin-vue/src/modules/demo/views/home/components/count-effect.vue create mode 100644 cool-admin-vue/src/modules/demo/views/home/components/count-paid.vue create mode 100644 cool-admin-vue/src/modules/demo/views/home/components/count-user.vue create mode 100644 cool-admin-vue/src/modules/demo/views/home/components/count-views.vue create mode 100644 cool-admin-vue/src/modules/demo/views/home/components/hot-goods.vue create mode 100644 cool-admin-vue/src/modules/demo/views/home/components/tab-chart.vue create mode 100644 cool-admin-vue/src/modules/demo/views/home/index.vue create mode 100644 cool-admin-vue/src/modules/demo/views/test/route.vue create mode 100644 cool-admin-vue/src/modules/dict/config.ts create mode 100644 cool-admin-vue/src/modules/dict/index.ts create mode 100644 cool-admin-vue/src/modules/dict/locales/en.json create mode 100644 cool-admin-vue/src/modules/dict/locales/zh-cn.json create mode 100644 cool-admin-vue/src/modules/dict/locales/zh-tw.json create mode 100644 cool-admin-vue/src/modules/dict/store/dict.ts create mode 100644 cool-admin-vue/src/modules/dict/store/index.ts create mode 100644 cool-admin-vue/src/modules/dict/types/index.d.ts create mode 100644 cool-admin-vue/src/modules/dict/utils/index.ts create mode 100644 cool-admin-vue/src/modules/dict/views/list.vue create mode 100644 cool-admin-vue/src/modules/helper/components/ai-code/btn.vue create mode 100644 cool-admin-vue/src/modules/helper/components/ai-code/dev.vue create mode 100644 cool-admin-vue/src/modules/helper/components/auto-menu.vue create mode 100644 cool-admin-vue/src/modules/helper/components/auto-perms.vue create mode 100644 cool-admin-vue/src/modules/helper/config.ts create mode 100644 cool-admin-vue/src/modules/helper/hooks/index.ts create mode 100644 cool-admin-vue/src/modules/helper/hooks/menu.ts create mode 100644 cool-admin-vue/src/modules/helper/hooks/plugin.ts create mode 100644 cool-admin-vue/src/modules/helper/locales/en.json create mode 100644 cool-admin-vue/src/modules/helper/locales/zh-cn.json create mode 100644 cool-admin-vue/src/modules/helper/locales/zh-tw.json create mode 100644 cool-admin-vue/src/modules/helper/static/index.scss create mode 100644 cool-admin-vue/src/modules/helper/static/svg/icon-vue.svg create mode 100644 cool-admin-vue/src/modules/helper/types/index.d.ts create mode 100644 cool-admin-vue/src/modules/helper/views/ai-code.vue create mode 100644 cool-admin-vue/src/modules/helper/views/plugins.vue create mode 100644 cool-admin-vue/src/modules/recycle/locales/en.json create mode 100644 cool-admin-vue/src/modules/recycle/locales/zh-cn.json create mode 100644 cool-admin-vue/src/modules/recycle/locales/zh-tw.json create mode 100644 cool-admin-vue/src/modules/recycle/views/data.vue create mode 100644 cool-admin-vue/src/modules/space/components/space-inner.vue create mode 100644 cool-admin-vue/src/modules/space/components/space.vue create mode 100644 cool-admin-vue/src/modules/space/config.ts create mode 100644 cool-admin-vue/src/modules/space/hooks/index.ts create mode 100644 cool-admin-vue/src/modules/space/locales/en.json create mode 100644 cool-admin-vue/src/modules/space/locales/zh-cn.json create mode 100644 cool-admin-vue/src/modules/space/locales/zh-tw.json create mode 100644 cool-admin-vue/src/modules/space/views/list.vue create mode 100644 cool-admin-vue/src/modules/task/components/logs.vue create mode 100644 cool-admin-vue/src/modules/task/locales/en.json create mode 100644 cool-admin-vue/src/modules/task/locales/zh-cn.json create mode 100644 cool-admin-vue/src/modules/task/locales/zh-tw.json create mode 100644 cool-admin-vue/src/modules/task/views/list.vue create mode 100644 cool-admin-vue/src/modules/user/components/user-select.vue create mode 100644 cool-admin-vue/src/modules/user/config.ts create mode 100644 cool-admin-vue/src/modules/user/locales/en.json create mode 100644 cool-admin-vue/src/modules/user/locales/zh-cn.json create mode 100644 cool-admin-vue/src/modules/user/locales/zh-tw.json create mode 100644 cool-admin-vue/src/modules/user/views/list.vue create mode 100644 cool-admin-vue/src/plugins/crud/comm/index.ts create mode 100644 cool-admin-vue/src/plugins/crud/components/column-custom/index.vue create mode 100644 cool-admin-vue/src/plugins/crud/components/date/picker.vue create mode 100644 cool-admin-vue/src/plugins/crud/components/date/text.vue create mode 100644 cool-admin-vue/src/plugins/crud/components/dict/index.tsx create mode 100644 cool-admin-vue/src/plugins/crud/components/number/range.vue create mode 100644 cool-admin-vue/src/plugins/crud/components/render/index.tsx create mode 100644 cool-admin-vue/src/plugins/crud/components/select/button.tsx create mode 100644 cool-admin-vue/src/plugins/crud/components/select/index.scss create mode 100644 cool-admin-vue/src/plugins/crud/components/select/index.tsx create mode 100644 cool-admin-vue/src/plugins/crud/components/select/table.vue create mode 100644 cool-admin-vue/src/plugins/crud/components/switch/index.tsx create mode 100644 cool-admin-vue/src/plugins/crud/components/text/index.tsx create mode 100644 cool-admin-vue/src/plugins/crud/components/user/select.vue create mode 100644 cool-admin-vue/src/plugins/crud/config.ts create mode 100644 cool-admin-vue/src/plugins/crud/index.ts create mode 100644 cool-admin-vue/src/plugins/crud/locales/en.json create mode 100644 cool-admin-vue/src/plugins/crud/locales/zh-cn.json create mode 100644 cool-admin-vue/src/plugins/crud/locales/zh-tw.json create mode 100644 cool-admin-vue/src/plugins/crud/plugins/form/index.ts create mode 100644 cool-admin-vue/src/plugins/crud/plugins/form/setFocus.ts create mode 100644 cool-admin-vue/src/plugins/crud/plugins/index.ts create mode 100644 cool-admin-vue/src/plugins/crud/plugins/search/index.ts create mode 100644 cool-admin-vue/src/plugins/crud/plugins/search/setAuto.ts create mode 100644 cool-admin-vue/src/plugins/crud/plugins/table/index.ts create mode 100644 cool-admin-vue/src/plugins/crud/plugins/table/rowEdit.tsx create mode 100644 cool-admin-vue/src/plugins/crud/plugins/table/toTree.ts create mode 100644 cool-admin-vue/src/plugins/dev-tools/components/account.vue create mode 100644 cool-admin-vue/src/plugins/dev-tools/components/dict.vue create mode 100644 cool-admin-vue/src/plugins/dev-tools/components/doc.vue create mode 100644 cool-admin-vue/src/plugins/dev-tools/components/eps.vue create mode 100644 cool-admin-vue/src/plugins/dev-tools/components/index.vue create mode 100644 cool-admin-vue/src/plugins/dev-tools/components/proxy.vue create mode 100644 cool-admin-vue/src/plugins/dev-tools/config.ts create mode 100644 cool-admin-vue/src/plugins/dev-tools/locales/en.json create mode 100644 cool-admin-vue/src/plugins/dev-tools/locales/zh-cn.json create mode 100644 cool-admin-vue/src/plugins/dev-tools/locales/zh-tw.json create mode 100644 cool-admin-vue/src/plugins/dev-tools/static/cool.png create mode 100644 cool-admin-vue/src/plugins/dev-tools/static/echarts.png create mode 100644 cool-admin-vue/src/plugins/dev-tools/static/element-plus.png create mode 100644 cool-admin-vue/src/plugins/dev-tools/static/lodash.png create mode 100644 cool-admin-vue/src/plugins/dev-tools/static/logo.png create mode 100644 cool-admin-vue/src/plugins/dev-tools/static/pinia.png create mode 100644 cool-admin-vue/src/plugins/dev-tools/static/tailwindcss.png create mode 100644 cool-admin-vue/src/plugins/dev-tools/static/vite.png create mode 100644 cool-admin-vue/src/plugins/dev-tools/static/vue.png create mode 100644 cool-admin-vue/src/plugins/dev-tools/utils/index.ts create mode 100644 cool-admin-vue/src/plugins/distpicker/components/index.tsx create mode 100644 cool-admin-vue/src/plugins/distpicker/config.ts create mode 100644 cool-admin-vue/src/plugins/distpicker/data/pca.json create mode 100644 cool-admin-vue/src/plugins/distpicker/demo/base.vue create mode 100644 cool-admin-vue/src/plugins/echarts/config.ts create mode 100644 cool-admin-vue/src/plugins/editor-preview/components/preview.vue create mode 100644 cool-admin-vue/src/plugins/editor-preview/config.ts create mode 100644 cool-admin-vue/src/plugins/editor-preview/demo/base.vue create mode 100644 cool-admin-vue/src/plugins/editor-preview/locales/en.json create mode 100644 cool-admin-vue/src/plugins/editor-preview/locales/zh-cn.json create mode 100644 cool-admin-vue/src/plugins/editor-preview/locales/zh-tw.json create mode 100644 cool-admin-vue/src/plugins/editor-wang/components/wang.vue create mode 100644 cool-admin-vue/src/plugins/editor-wang/config.ts create mode 100644 cool-admin-vue/src/plugins/editor-wang/demo/base.vue create mode 100644 cool-admin-vue/src/plugins/editor-wang/locales/en.json create mode 100644 cool-admin-vue/src/plugins/editor-wang/locales/zh-cn.json create mode 100644 cool-admin-vue/src/plugins/editor-wang/locales/zh-tw.json create mode 100644 cool-admin-vue/src/plugins/element-ui/config.ts create mode 100644 cool-admin-vue/src/plugins/element-ui/css/index.scss create mode 100644 cool-admin-vue/src/plugins/excel/components/export-btn.tsx create mode 100644 cool-admin-vue/src/plugins/excel/components/import-btn.vue create mode 100644 cool-admin-vue/src/plugins/excel/config.ts create mode 100644 cool-admin-vue/src/plugins/excel/demo/base.vue create mode 100644 cool-admin-vue/src/plugins/excel/locales/en.json create mode 100644 cool-admin-vue/src/plugins/excel/locales/zh-cn.json create mode 100644 cool-admin-vue/src/plugins/excel/locales/zh-tw.json create mode 100644 cool-admin-vue/src/plugins/excel/utils/index.ts create mode 100644 cool-admin-vue/src/plugins/github/components/code.vue create mode 100644 cool-admin-vue/src/plugins/github/config.ts create mode 100644 cool-admin-vue/src/plugins/i18n/components/switch.vue create mode 100644 cool-admin-vue/src/plugins/i18n/config.ts create mode 100644 cool-admin-vue/src/plugins/i18n/index.ts create mode 100644 cool-admin-vue/src/plugins/i18n/static/svg/lang.svg create mode 100644 cool-admin-vue/src/plugins/iconfont/config.ts create mode 100644 cool-admin-vue/src/plugins/iconfont/index.ts create mode 100644 cool-admin-vue/src/plugins/iconfont/utils/index.ts create mode 100644 cool-admin-vue/src/plugins/tailwind/config.ts create mode 100644 cool-admin-vue/src/plugins/tailwind/static/index.css create mode 100644 cool-admin-vue/src/plugins/theme/components/theme.vue create mode 100644 cool-admin-vue/src/plugins/theme/config.ts create mode 100644 cool-admin-vue/src/plugins/theme/hooks/index.ts create mode 100644 cool-admin-vue/src/plugins/theme/index.ts create mode 100644 cool-admin-vue/src/plugins/theme/locales/en.json create mode 100644 cool-admin-vue/src/plugins/theme/locales/zh-cn.json create mode 100644 cool-admin-vue/src/plugins/theme/locales/zh-tw.json create mode 100644 cool-admin-vue/src/plugins/theme/static/css/index.scss create mode 100644 cool-admin-vue/src/plugins/theme/static/svg/dark.svg create mode 100644 cool-admin-vue/src/plugins/theme/static/svg/light.svg create mode 100644 cool-admin-vue/src/plugins/theme/static/svg/theme.svg create mode 100644 cool-admin-vue/src/plugins/theme/types/index.d.ts create mode 100644 cool-admin-vue/src/plugins/theme/utils/index.ts create mode 100644 cool-admin-vue/src/plugins/upload/components/upload-item/index.vue create mode 100644 cool-admin-vue/src/plugins/upload/components/upload-item/viewer.vue create mode 100644 cool-admin-vue/src/plugins/upload/components/upload.vue create mode 100644 cool-admin-vue/src/plugins/upload/config.ts create mode 100644 cool-admin-vue/src/plugins/upload/demo/base.vue create mode 100644 cool-admin-vue/src/plugins/upload/demo/check.vue create mode 100644 cool-admin-vue/src/plugins/upload/demo/custom.vue create mode 100644 cool-admin-vue/src/plugins/upload/demo/drag.vue create mode 100644 cool-admin-vue/src/plugins/upload/demo/file.vue create mode 100644 cool-admin-vue/src/plugins/upload/demo/multiple.vue create mode 100644 cool-admin-vue/src/plugins/upload/demo/small.vue create mode 100644 cool-admin-vue/src/plugins/upload/demo/space.vue create mode 100644 cool-admin-vue/src/plugins/upload/hooks/index.ts create mode 100644 cool-admin-vue/src/plugins/upload/index.ts create mode 100644 cool-admin-vue/src/plugins/upload/locales/en.json create mode 100644 cool-admin-vue/src/plugins/upload/locales/zh-cn.json create mode 100644 cool-admin-vue/src/plugins/upload/locales/zh-tw.json create mode 100644 cool-admin-vue/src/plugins/upload/static/svg/audio.svg create mode 100644 cool-admin-vue/src/plugins/upload/static/svg/excel.svg create mode 100644 cool-admin-vue/src/plugins/upload/static/svg/file.svg create mode 100644 cool-admin-vue/src/plugins/upload/static/svg/image.svg create mode 100644 cool-admin-vue/src/plugins/upload/static/svg/pdf.svg create mode 100644 cool-admin-vue/src/plugins/upload/static/svg/ppt.svg create mode 100644 cool-admin-vue/src/plugins/upload/static/svg/rar.svg create mode 100644 cool-admin-vue/src/plugins/upload/static/svg/video.svg create mode 100644 cool-admin-vue/src/plugins/upload/static/svg/word.svg create mode 100644 cool-admin-vue/src/plugins/upload/types/index.d.ts create mode 100644 cool-admin-vue/src/plugins/upload/utils/index.ts create mode 100644 cool-admin-vue/src/plugins/view/components/group.vue create mode 100644 cool-admin-vue/src/plugins/view/components/head.vue create mode 100644 cool-admin-vue/src/plugins/view/config.ts create mode 100644 cool-admin-vue/src/plugins/view/demo/group.vue create mode 100644 cool-admin-vue/src/plugins/view/demo/head.vue create mode 100644 cool-admin-vue/src/plugins/view/hooks/group.ts create mode 100644 cool-admin-vue/src/plugins/view/hooks/index.ts create mode 100644 cool-admin-vue/src/plugins/view/index.ts create mode 100644 cool-admin-vue/src/plugins/view/locales/en.json create mode 100644 cool-admin-vue/src/plugins/view/locales/zh-cn.json create mode 100644 cool-admin-vue/src/plugins/view/locales/zh-tw.json create mode 100644 cool-admin-vue/src/plugins/view/types/index.d.ts create mode 100644 cool-admin-vue/src/shims-vue.d.ts create mode 100644 cool-admin-vue/tailwind.config.js create mode 100644 cool-admin-vue/tsconfig.json create mode 100644 cool-admin-vue/vite.config.ts diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..35410ca --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# 默认忽略的文件 +/shelf/ +/workspace.xml +# 基于编辑器的 HTTP 客户端请求 +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..0a44435 --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..a9b9ff2 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + EditorConfig + + + Java + + + JavaScript 和 TypeScript + + + Markdown + + + XPath + + + 代码样式问题JavaScript 和 TypeScript + + + 可移植性Java + + + 国际化 + + + 国际化Java + + + 属性文件Java + + + + + 用户定义 + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/cool-admin-java/.gitignore b/cool-admin-java/.gitignore new file mode 100644 index 0000000..d5ae312 --- /dev/null +++ b/cool-admin-java/.gitignore @@ -0,0 +1,37 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +assets/ +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ +.DS_Store +lib +plugin \ No newline at end of file diff --git a/cool-admin-java/Dockerfile b/cool-admin-java/Dockerfile new file mode 100644 index 0000000..1108bb7 --- /dev/null +++ b/cool-admin-java/Dockerfile @@ -0,0 +1,14 @@ +# 使用 GraalVM 17 作为基础镜像 +FROM ghcr.io/graalvm/graalvm-ce:latest + +# 设置容器内的工作目录 +WORKDIR /app + +# 将可执行的jar文件复制到容器内 +COPY target/cool-admin-8.0.0.jar /app/cool-admin-8.0.0.jar + +# 暴露Spring Boot应用程序运行的端口 +EXPOSE 8001 + +# 运行Spring Boot应用程序的命令 +ENTRYPOINT ["java", "-jar", "/app/cool-admin-8.0.0.jar", "--spring.profiles.active=prod"] diff --git a/cool-admin-java/LICENSE b/cool-admin-java/LICENSE new file mode 100644 index 0000000..5a6831d --- /dev/null +++ b/cool-admin-java/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 cool-team-official + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/cool-admin-java/README.md b/cool-admin-java/README.md new file mode 100644 index 0000000..02f0c7e --- /dev/null +++ b/cool-admin-java/README.md @@ -0,0 +1,103 @@ + +

+ Midway Logo +

+

cool-admin(java版)后台权限管理系统,开源免费,Ai编码、流程编排、模块化、插件化,用于快速构建后台应用程序,详情可到官网 进一步了解。 +

+ GitHub license + GitHub tag + GitHub tag +

+ +## 技术栈 + +- 后端:**`Springboot3` `Mybatis-Flex`** +- 前端:**`Vue3` `Vite` `Element-Ui` `Typescript`** +- 数据库:**`Mysql` `Postgresql` `Sqlite(适配中)` `...`** + +## 特性 + +Ai时代,很多老旧的框架已经无法满足现代化的开发需求,Cool-Admin开发了一系列的功能,让开发变得更简单、更快速、更高效。 + +- **Ai编码**:通过微调大模型学习框架特有写法,实现简单功能从Api接口到前端页面的一键生成[详情](https://java.cool-admin.com/src/guide/ai.html) +- **流程编排**:通过拖拽编排方式,即可实现类似像智能客服这样的功能[详情](https://cool-js.com/plugin/118) +- **多租户**:支持多租户,采用全局动态注入查询条件[详情](https://java.cool-admin.com/src/guide/tenant.html) +- **多语言**:基于大模型自动翻译,无需更改原有代码[详情](https://java.cool-admin.com/src/guide/i18n.html) +- **模块化**:代码是模块化的,清晰明了,方便维护 +- **插件化**:插件化的设计,可以通过安装插件的方式扩展如:支付、短信、邮件等功能 +- **自动初始化**:数据自动化,无需再手动维护,启动时自动生成数据库表和表结构数据 +- **cool-admin-java-plus**: [详情](https://gitee.com/hlc4417/cool-admin-java-plus) +- ...... +![](https://cool-show.oss-cn-shanghai.aliyuncs.com/admin/flow.png) + +## 地址 + +- 官网:[https://cool-admin.com](https://cool-admin.com) +- 文档:[https://java.cool-admin.com](https://java.cool-admin.com) +- 商城项目:[https://cool-js.com/plugin/140](https://cool-js.com/plugin/140) +- Ai流程编排+知识库项目:[https://cool-js.com/plugin/118](https://cool-js.com/plugin/118) +- cool-admin-java-plus:https://gitee.com/hlc4417/cool-admin-java-plus + +## 演示 + +[https://show.cool-admin.com](https://show.cool-admin.com) + +- 账户:admin +- 密码:123456 + +![](https://cool-show.oss-cn-shanghai.aliyuncs.com/admin/home-mini.png) + +#### 项目前端 + +系统是前后端分离的,启动完成后,还需要启动前端项目,前端项目地址: + +[https://github.com/cool-team-official/cool-admin-vue](https://github.com/cool-team-official/cool-admin-vue) + +或 + +[https://gitee.com/cool-team-official/cool-admin-vue](https://gitee.com/cool-team-official/cool-admin-vue) + +或 + +[https://gitcode.com/cool_team/cool-admin-vue](https://gitcode.com/cool_team/cool-admin-vue) + +## 微信群 + +Admin Wechat + +## 运行 + +### 环境要求 + +- Java Graalvm 17+ +- Maven 3.6+ + +### 配置 + +修改数据库配置,配置文件位于`src/resources/application-local.yml` + +以 Mysql 为例,其他数据库适配中... + +Mysql(`>=5.7版本`),建议 8.0,首次启动会自动初始化并导入数据 + +```yaml +# mysql,驱动已经内置,无需安装 +spring: + datasource: + url: jdbc:mysql://127.0.0.1:3306/cool?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2b8 + username: root + password: 123456 + driver-class-name: com.mysql.cj.jdbc.Driver +``` + +### 启动 + +注:项目使用到了[Mybatis-Flex 的Apt功能](https://mybatis-flex.com/zh/others/apt.html),如果启动报错,请先执行`mvn compile`编译 + +1、启动文件:`src/main/java/com/cool/CoolApplication.java` + +2、启动完成后,访问:[http://localhost:8001](http://localhost:8001) + +3、如果看到以下界面,说明启动成功。这时候再启动前端项目即可,数据库会自动初始化,默认账号:admin,密码:123456 + +![](https://cool-show.oss-cn-shanghai.aliyuncs.com/admin/run.png) diff --git a/cool-admin-java/docker-compose.yml b/cool-admin-java/docker-compose.yml new file mode 100644 index 0000000..7c9130b --- /dev/null +++ b/cool-admin-java/docker-compose.yml @@ -0,0 +1,43 @@ +# 本地数据库环境 +# 数据存放在当前目录下的 data里 +# 推荐使用安装了docker扩展的vscode打开目录 在本文件上右键可以快速启动,停止 +# 如不需要相关容器开机自启动,可注释掉 restart: always +# 如遇端口冲突 可调整ports下 :前面的端口号 +version: "3.9" + +services: + mysql: + image: mysql # 使用官方 MySQL 镜像,你可以根据需要选择版本 + environment: + MYSQL_ROOT_PASSWORD: "123456" # 设置 root 用户密码 + MYSQL_DATABASE: "cool" # 创建一个初始数据库 + networks: + - backend + ports: + - "3306:3306" # 将主机的 3306 端口映射到容器的 3306 端口 + volumes: + - mysql-data:/var/lib/mysql # 挂载数据卷以持久化数据 + + redis: + image: redis:latest + # command: --requirepass "12345678" # Uncomment if you need a password + restart: always + environment: + TZ: Asia/Shanghai # 指定时区 + volumes: + - ./data/redis/:/data/ + networks: + - backend + ports: + - 6379:6379 + + +networks: + backend: + driver: bridge + +volumes: + mysql-data: + driver: local + redis-data: + driver: local \ No newline at end of file diff --git a/cool-admin-java/pom.xml b/cool-admin-java/pom.xml new file mode 100644 index 0000000..bb33e1a --- /dev/null +++ b/cool-admin-java/pom.xml @@ -0,0 +1,213 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 3.2.5 + + + + com.cool + cool-admin + 8.0.0 + cool-admin + cool admin for java + + 17 + 1.18.34 + 1.10.9 + 1.10.9.125 + 5.8.26 + 3.3.2 + 2.0.51 + 2.5.0 + 0.9.16 + 4.7.0 + + + + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-cache + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.boot + spring-boot-starter-quartz + + + + + org.springframework.boot + spring-boot-starter-data-redis + + + + + org.springframework.boot + spring-boot-configuration-processor + + + org.springframework.boot + spring-boot-starter-aop + + + + com.github.ben-manes.caffeine + caffeine + + + com.mysql + mysql-connector-j + runtime + + + org.postgresql + postgresql + + + com.zaxxer + HikariCP + + + org.projectlombok + lombok + true + + + cn.hutool + hutool-all + ${hutool.version} + + + ognl + ognl + ${ognl.version} + + + com.alibaba.fastjson2 + fastjson2 + ${fastjson2.version} + + + + com.tangzc + mybatis-flex-ext-spring-boot3-starter + ${mybatis-flex.ext.version} + + + org.springdoc + springdoc-openapi-starter-webmvc-ui + ${springdoc-openapi.version} + + + + com.github.binarywang + weixin-java-miniapp + ${weixin-java.version} + + + com.github.binarywang + weixin-java-mp + ${weixin-java.version} + + + com.github.binarywang + weixin-java-pay + ${weixin-java.version} + + + + jakarta.servlet + jakarta.servlet-api + provided + + + com.fasterxml.jackson.core + jackson-databind + + + org.perf4j + perf4j + ${perf4j.version} + + + + + + + org.graalvm.buildtools + native-maven-plugin + + + org.springframework.boot + spring-boot-maven-plugin + + + + org.projectlombok + lombok + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + org.projectlombok + lombok + ${lombok.version} + + + com.mybatis-flex + mybatis-flex-processor + ${mybatis-flex.version} + + + + + + + + + + local + + true + + + local + + + + prod + + prod + + + + + \ No newline at end of file diff --git a/cool-admin-java/src/main/java/com/cool/CoolApplication.java b/cool-admin-java/src/main/java/com/cool/CoolApplication.java new file mode 100644 index 0000000..b5fac06 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/CoolApplication.java @@ -0,0 +1,74 @@ +package com.cool; + +import com.cool.core.util.PathUtils; +import java.util.List; +import lombok.extern.slf4j.Slf4j; +import org.dromara.autotable.springboot.EnableAutoTable; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.ApplicationArguments; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.scheduling.annotation.EnableAsync; + +/** + * CoolApplication - 应用程序的主类 + * 该类配置并运行应用程序。 + */ +@Slf4j +@EnableAutoTable // 开启自动建表 +@EnableAsync // 开启异步处理 +@EnableCaching // 开启缓存 +@SpringBootApplication +@MapperScan("com.cool.**.mapper") // 扫描指定包中的MyBatis映射器 +public class CoolApplication { + + private static volatile ConfigurableApplicationContext context; + private static ClassLoader mainThreadClassLoader; + + public static void main(String[] args) { + mainThreadClassLoader = Thread.currentThread().getContextClassLoader(); + context = SpringApplication.run(CoolApplication.class, args); + } + + /** + * 通过关闭当前上下文并启动新上下文来重启应用程序。 + */ + public static void restart(List javaPathList) { + // 从当前上下文获取应用程序参数 + ApplicationArguments args = context.getBean(ApplicationArguments.class); + + // 创建新线程来重启应用程序 + Thread thread = new Thread(() -> { + try { + // 关闭当前应用程序上下文 + context.close(); + // 等待上下文完全关闭 + while (context.isActive()) { + Thread.sleep(100); + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + // 加载动态生成的代码 + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + javaPathList.forEach(javaPath -> { + try { + classLoader.loadClass(PathUtils.getClassName(javaPath)); + } catch (ClassNotFoundException e) { + log.error("loadClassErr {}", javaPath, e); + } + }); + // 使用相同的参数运行Spring Boot应用程序并设置上下文 + context = SpringApplication.run(CoolApplication.class, args.getSourceArgs()); + }); + // 设置线程的上下文类加载器 + thread.setContextClassLoader(mainThreadClassLoader); + // 确保线程不是守护线程 + thread.setDaemon(false); + // 启动线程 + thread.start(); + } + +} diff --git a/cool-admin-java/src/main/java/com/cool/Welcome.java b/cool-admin-java/src/main/java/com/cool/Welcome.java new file mode 100644 index 0000000..e34071a --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/Welcome.java @@ -0,0 +1,17 @@ +package com.cool; + +import com.cool.core.annotation.TokenIgnore; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; + +@Controller +@RequiredArgsConstructor +public class Welcome { + + @RequestMapping("/") + @TokenIgnore + public String welcome() { + return "welcome"; + } +} diff --git a/cool-admin-java/src/main/java/com/cool/core/annotation/CoolPlugin.java b/cool-admin-java/src/main/java/com/cool/core/annotation/CoolPlugin.java new file mode 100644 index 0000000..a010335 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/annotation/CoolPlugin.java @@ -0,0 +1,12 @@ +package com.cool.core.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface CoolPlugin { + String value() default ""; +} diff --git a/cool-admin-java/src/main/java/com/cool/core/annotation/CoolRestController.java b/cool-admin-java/src/main/java/com/cool/core/annotation/CoolRestController.java new file mode 100644 index 0000000..c13be69 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/annotation/CoolRestController.java @@ -0,0 +1,34 @@ +package com.cool.core.annotation; + +import java.lang.annotation.*; +import org.springframework.core.annotation.AliasFor; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 自定义路由注解 + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@RestController +@RequestMapping +public @interface CoolRestController { + + @AliasFor(annotation = RequestMapping.class) + String name() default ""; + + @AliasFor(annotation = RequestMapping.class) + String[] value() default {}; + + String[] api() default {}; + + /** + * 如前缀: /admin/goods/searchKeyword + * 没指定该字段 cname="searchKeyword", + * 按规则是解析为: /admin/goods/search/keyword + * 前端和node版本已经定义为 searchKeyword,没按规则解析,使用该字段自定义规则 进行兼容 + * com.cool.core.request.prefix.AutoPrefixUrlMapping#getCName(java.lang.Class, java.lang.String) + */ + String cname() default ""; +} diff --git a/cool-admin-java/src/main/java/com/cool/core/annotation/EpsField.java b/cool-admin-java/src/main/java/com/cool/core/annotation/EpsField.java new file mode 100644 index 0000000..1e59245 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/annotation/EpsField.java @@ -0,0 +1,14 @@ +package com.cool.core.annotation; + +import com.cool.core.enums.AdminComponentsEnum; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE}) +@Retention(RetentionPolicy.RUNTIME) +public @interface EpsField { + String component() default AdminComponentsEnum.INPUT; +} diff --git a/cool-admin-java/src/main/java/com/cool/core/annotation/IgnoreRecycleData.java b/cool-admin-java/src/main/java/com/cool/core/annotation/IgnoreRecycleData.java new file mode 100644 index 0000000..6ceb893 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/annotation/IgnoreRecycleData.java @@ -0,0 +1,12 @@ +package com.cool.core.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface IgnoreRecycleData { + String value() default ""; +} diff --git a/cool-admin-java/src/main/java/com/cool/core/annotation/NoRepeatSubmit.java b/cool-admin-java/src/main/java/com/cool/core/annotation/NoRepeatSubmit.java new file mode 100644 index 0000000..818c473 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/annotation/NoRepeatSubmit.java @@ -0,0 +1,12 @@ +package com.cool.core.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface NoRepeatSubmit { + long expireTime() default 2000; // 默认2秒过期时间,单位毫秒 +} diff --git a/cool-admin-java/src/main/java/com/cool/core/annotation/TokenIgnore.java b/cool-admin-java/src/main/java/com/cool/core/annotation/TokenIgnore.java new file mode 100644 index 0000000..b2d46aa --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/annotation/TokenIgnore.java @@ -0,0 +1,15 @@ +package com.cool.core.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 忽略Token验证 + */ +@Target({ElementType.TYPE, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface TokenIgnore { + String[] value() default {}; +} diff --git a/cool-admin-java/src/main/java/com/cool/core/aop/NoRepeatSubmitAspect.java b/cool-admin-java/src/main/java/com/cool/core/aop/NoRepeatSubmitAspect.java new file mode 100644 index 0000000..501b771 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/aop/NoRepeatSubmitAspect.java @@ -0,0 +1,39 @@ +package com.cool.core.aop; + +import com.cool.core.annotation.NoRepeatSubmit; +import com.cool.core.exception.CoolPreconditions; +import com.cool.core.lock.CoolLock; +import com.cool.core.util.CoolSecurityUtil; +import jakarta.servlet.http.HttpServletRequest; +import java.time.Duration; +import java.util.Objects; +import lombok.RequiredArgsConstructor; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +@Aspect +@Component +@RequiredArgsConstructor +public class NoRepeatSubmitAspect { + + private final CoolLock coolLock; + + @Around("@annotation(noRepeatSubmit)") + public Object around(ProceedingJoinPoint joinPoint, NoRepeatSubmit noRepeatSubmit) throws Throwable { + HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull( + RequestContextHolder.getRequestAttributes())).getRequest(); + String key = request.getRequestURI() + ":" + CoolSecurityUtil.getCurrentUserId(); + // 加锁 + CoolPreconditions.check(!coolLock.tryLock(key, Duration.ofMillis(noRepeatSubmit.expireTime())), "请勿重复操作"); + try { + return joinPoint.proceed(); + } finally { + // 移除锁 + coolLock.unlock(key); + } + } +} diff --git a/cool-admin-java/src/main/java/com/cool/core/base/BaseController.java b/cool-admin-java/src/main/java/com/cool/core/base/BaseController.java new file mode 100644 index 0000000..32fc3f2 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/base/BaseController.java @@ -0,0 +1,277 @@ +package com.cool.core.base; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.convert.Convert; +import cn.hutool.core.lang.Dict; +import cn.hutool.core.lang.Editor; +import cn.hutool.core.util.ObjUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.core.util.TypeUtil; +import cn.hutool.json.JSONArray; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import com.cool.core.enums.QueryModeEnum; +import com.cool.core.exception.CoolPreconditions; +import com.cool.core.request.CrudOption; +import com.cool.core.request.PageResult; +import com.cool.core.request.R; +import com.mybatisflex.core.paginate.Page; +import io.swagger.v3.oas.annotations.Operation; +import jakarta.servlet.http.HttpServletRequest; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import lombok.Getter; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestAttribute; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +/** + * 控制层基类 + * + * @param + * @param + */ +public abstract class BaseController, T extends BaseEntity> { + + @Getter + @Autowired + protected S service; + protected Class entityClass; + + protected final String COOL_PAGE_OP = "COOL_PAGE_OP"; + protected final String COOL_LIST_OP = "COOL_LIST_OP"; + protected final String COOL_INFO_OP = "COOL_INFO_OP"; + + private final ThreadLocal> pageOption = new ThreadLocal<>(); + private final ThreadLocal> listOption = new ThreadLocal<>(); + private final ThreadLocal> infoOption = new ThreadLocal<>(); + private final ThreadLocal requestParams = new ThreadLocal<>(); + + @ModelAttribute + protected void preHandle(HttpServletRequest request, + @RequestAttribute JSONObject requestParams) { + String requestPath = ((ServletRequestAttributes) Objects.requireNonNull( + RequestContextHolder.getRequestAttributes())).getRequest().getRequestURI(); + if (!requestPath.endsWith("/page") && !requestPath.endsWith("/list") + && !requestPath.endsWith("/info")) { + // 非page或list不执行 + return; + } + this.pageOption.set(new CrudOption<>(requestParams)); + this.listOption.set(new CrudOption<>(requestParams)); + this.infoOption.set(new CrudOption<>(requestParams)); + this.requestParams.set(requestParams); + init(request, requestParams); + request.setAttribute(COOL_PAGE_OP, this.pageOption.get()); + request.setAttribute(COOL_LIST_OP, this.listOption.get()); + request.setAttribute(COOL_INFO_OP, this.infoOption.get()); + + removeThreadLocal(); + } + + /** + * 手动移除变量 + */ + private void removeThreadLocal() { + this.listOption.remove(); + this.pageOption.remove(); + this.requestParams.remove(); + } + + public CrudOption createOp() { + return new CrudOption<>(this.requestParams.get()); + } + + public void setInfoOption(CrudOption infoOption) { + this.infoOption.set(infoOption); + } + + public void setListOption(CrudOption listOption) { + this.listOption.set(listOption); + } + + public void setPageOption(CrudOption pageOption) { + this.pageOption.set(pageOption); + } + + protected abstract void init(HttpServletRequest request, JSONObject requestParams); + + /** + * 新增 + *

+ * // * @param t 实体对象 + */ + @Operation(summary = "新增", description = "新增信息,对应后端的实体类") + @PostMapping("/add") + protected R add(@RequestAttribute() JSONObject requestParams) { + String body = requestParams.getStr("body"); + if (JSONUtil.isTypeJSONArray(body)) { + JSONArray array = JSONUtil.parseArray(body); + return R.ok(Dict.create() + .set("id", service.addBatch(requestParams, array.toList(currentEntityClass())))); + } else { + return R.ok(Dict.create().set("id", + service.add(requestParams, requestParams.toBean(currentEntityClass())))); + } + } + + /** + * 删除 + * + * @param params 请求参数 ids 数组 或者按","隔开 + */ + @Operation(summary = "删除", description = "支持批量删除 请求参数 ids 数组 或者按\",\"隔开") + @PostMapping("/delete") + protected R delete(HttpServletRequest request, @RequestBody Map params, + @RequestAttribute() JSONObject requestParams) { + service.delete(requestParams, Convert.toLongArray(getIds(params))); + return R.ok(); + } + + /** + * 修改 + * + * @param t 修改对象 + */ + @Operation(summary = "修改", description = "根据ID修改") + @PostMapping("/update") + protected R update(@RequestBody T t, @RequestAttribute() JSONObject requestParams) { + Long id = t.getId(); + JSONObject info = JSONUtil.parseObj(JSONUtil.toJsonStr(service.getById(id))); + requestParams.forEach(info::set); + info.set("updateTime", new Date()); + service.update(requestParams, JSONUtil.toBean(info, currentEntityClass())); + return R.ok(); + } + + /** + * 信息 + * + * @param id ID + */ + @Operation(summary = "信息", description = "根据ID查询单个信息") + @GetMapping("/info") + protected R info(@RequestAttribute() JSONObject requestParams, + @RequestParam() Long id, + @RequestAttribute(COOL_INFO_OP) CrudOption option) { + T info = (T) service.info(requestParams, id); + invokerTransform(option, info); + return R.ok(info); + } + + /** + * 列表查询 + * + * @param requestParams 请求参数 + */ + @Operation(summary = "查询", description = "查询多个信息") + @PostMapping("/list") + protected R> list(@RequestAttribute() JSONObject requestParams, + @RequestAttribute(COOL_LIST_OP) CrudOption option) { + QueryModeEnum queryModeEnum = option.getQueryModeEnum(); + List list = (List) switch (queryModeEnum) { + case ENTITY_WITH_RELATIONS -> service.listWithRelations(requestParams, option.getQueryWrapper(currentEntityClass())); + case CUSTOM -> transformList(service.list(requestParams, option.getQueryWrapper(currentEntityClass()), option.getAsType()), option.getAsType()); + default -> service.list(requestParams, option.getQueryWrapper(currentEntityClass())); + }; + invokerTransform(option, list); + return R.ok(list); + } + + /** + * 分页查询 + * + * @param requestParams 请求参数 + */ + @Operation(summary = "分页", description = "分页查询多个信息") + @PostMapping("/page") + protected R> page(@RequestAttribute() JSONObject requestParams, + @RequestAttribute(COOL_PAGE_OP) CrudOption option) { + Integer page = requestParams.getInt("page", 1); + Integer size = requestParams.getInt("size", 20); + QueryModeEnum queryModeEnum = option.getQueryModeEnum(); + Object obj = switch (queryModeEnum) { + case ENTITY_WITH_RELATIONS -> service.pageWithRelations(requestParams, new Page<>(page, size), option.getQueryWrapper(currentEntityClass())); + case CUSTOM -> transformPage(service.page(requestParams, new Page<>(page, size), option.getQueryWrapper(currentEntityClass()), option.getAsType()), option.getAsType()); + default -> service.page(requestParams, new Page<>(page, size), option.getQueryWrapper(currentEntityClass())); + }; + Page pageResult = (Page) obj; + invokerTransform(option, pageResult.getRecords()); + return R.ok(pageResult(pageResult)); + } + + /** + * 转换参数,组装数据 + */ + private void invokerTransform(CrudOption option, Object obj) { + if (ObjUtil.isNotEmpty(option.getTransform())) { + if (obj instanceof List) { + ((List)obj).forEach(o -> { + option.getTransform().apply(o); + }); + } else { + option.getTransform().apply(obj); + } + } + } + + /** + * 分页结果 + * + * @param page 分页返回数据 + */ + protected PageResult pageResult(Page page) { + return PageResult.of(page); + } + + public Class currentEntityClass() { + if (entityClass != null) { + return this.entityClass; + } + // 使用 获取泛型参数类型 + Type type = TypeUtil.getTypeArgument(this.getClass(), 1); // 获取第二个泛型参数 + if (type instanceof Class) { + entityClass = (Class) type; + return entityClass; + } + throw new IllegalStateException("Unable to determine entity class type"); + } + + protected List getIds(Map params) { + Object ids = params.get("ids"); + CoolPreconditions.checkEmpty(ids, "ids 参数错误"); + if (!(ids instanceof ArrayList)) { + ids = ids.toString().split(","); + } + return Convert.toList(Long.class, ids); + } + + /** + * 适用于自定义返回值为 map,map 的key为数据库字段,转驼峰命名 + */ + protected List transformList(List records, Class asType) { + if (ObjUtil.isEmpty(asType) || !Map.class.isAssignableFrom(asType)) { + return records; + } + List list = new ArrayList<>(); + Editor keyEditor = property -> StrUtil.toCamelCase(property); + records.forEach(o -> + list.add(BeanUtil.beanToMap(o, new HashMap(), false, keyEditor))); + return list; + } + protected Page transformPage(Page page, Class asType) { + page.setRecords(transformList(page.getRecords(), asType)); + return page; + } +} \ No newline at end of file diff --git a/cool-admin-java/src/main/java/com/cool/core/base/BaseEntity.java b/cool-admin-java/src/main/java/com/cool/core/base/BaseEntity.java new file mode 100644 index 0000000..08f153f --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/base/BaseEntity.java @@ -0,0 +1,38 @@ +package com.cool.core.base; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.mybatisflex.annotation.Column; +import com.mybatisflex.annotation.Id; +import com.mybatisflex.annotation.KeyType; +import com.mybatisflex.core.activerecord.Model; +import com.mybatisflex.core.query.QueryWrapper; +import com.tangzc.mybatisflex.autotable.annotation.ColumnDefine; +import java.io.Serializable; +import java.util.Date; +import lombok.Getter; +import lombok.Setter; +import org.dromara.autotable.annotation.Ignore; + +/** + * 基础实体类 + */ +@Getter +@Setter +public abstract class BaseEntity> extends Model implements Serializable { + + @Id(keyType = KeyType.Auto, comment = "ID") + protected Long id; + + @Column(onInsertValue = "now()") + @ColumnDefine(comment = "创建时间") + protected Date createTime; + + @Column(onInsertValue = "now()", onUpdateValue = "now()") + @ColumnDefine(comment = "更新时间") + protected Date updateTime; + + @Ignore + @Column(ignore = true) + @JsonIgnore + private QueryWrapper queryWrapper; +} \ No newline at end of file diff --git a/cool-admin-java/src/main/java/com/cool/core/base/BaseService.java b/cool-admin-java/src/main/java/com/cool/core/base/BaseService.java new file mode 100644 index 0000000..dff2fda --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/base/BaseService.java @@ -0,0 +1,175 @@ +package com.cool.core.base; + +import cn.hutool.json.JSONObject; +import com.mybatisflex.core.paginate.Page; +import com.mybatisflex.core.query.QueryWrapper; +import com.mybatisflex.core.service.IService; +import java.util.List; + +/** + * 基础service类 + * + * @param 实体 + */ +public interface BaseService extends IService { + /** + * 新增 + * + * @param entity 对应的实体 + */ + Long add(T entity); + + /** + * 新增 + * + * @param requestParams 请求参数 + * @param entity 对应的实体 + * @return ID + */ + Object add(JSONObject requestParams, T entity); + + /** + * 批量添加 + * + * @param requestParams 请求参数 + * @param entitys 请求参数 + * @return ID 集合 + */ + Object addBatch(JSONObject requestParams, List entitys); + + /** + * 删除, 支持单个或者批量删除 + * + * @param ids ID数组 + */ + boolean delete(Long... ids); + + /** + * 多个删除,带请求参数 + * + * @param requestParams 请求参数 + * @param ids ID数组 + */ + boolean delete(JSONObject requestParams, Long... ids); + + /** + * 更新 + * + * @param entity 实体 + */ + boolean update(T entity); + + /** + * 更新 + * + * @param requestParams 请求参数 + * @param entity 实体 + */ + boolean update(JSONObject requestParams, T entity); + + /** + * 查询所有 + * + * @param requestParams 请求参数 + * @param queryWrapper 查询条件 + * @return 列表信息 + */ + Object list(JSONObject requestParams, QueryWrapper queryWrapper); + + /** + * 查询所有 + * + * @param requestParams 请求参数 + * @param queryWrapper 查询条件 + * @return 列表信息 + */ + List list(JSONObject requestParams, QueryWrapper queryWrapper, Class asType); + + /** + * 查询所有 + * 带关联查询 + * @param requestParams 请求参数 + * @param queryWrapper 查询条件 + * @return 列表信息 + */ + Object listWithRelations(JSONObject requestParams, QueryWrapper queryWrapper); + + /** + * 分页查询 + * + * @param requestParams 请求参数 + * @param page 分页信息 + * @param queryWrapper 查询条件 + * @return 分页信息 + */ + Object page(JSONObject requestParams, Page page, QueryWrapper queryWrapper); + + /** + * 分页查询 + * + * @param requestParams 请求参数 + * @param page 分页信息 + * @param queryWrapper 查询条件 + * @return 分页信息 + */ + Page page(JSONObject requestParams, Page page, QueryWrapper queryWrapper, Class asType); + + /** + * 分页查询 + * 带关联查询 + * @param requestParams 请求参数 + * @param page 分页信息 + * @param queryWrapper 查询条件 + * @return 分页信息 + */ + Object pageWithRelations(JSONObject requestParams, Page page, QueryWrapper queryWrapper); + + /** + * 查询信息 + * + * @param id ID + */ + Object info(Long id); + + /** + * 查询信息 + * + * @param requestParams 请求参数 + * @param id ID + */ + Object info(JSONObject requestParams, Long id); + + /** + * 修改之后 + * + * @param requestParams 请求参数 + * @param t 对应实体 + */ + void modifyAfter(JSONObject requestParams, T t); + + /** + * 修改之后 + * + * @param requestParams 请求参数 + * @param t 对应实体 + * @param type 修改类型 + */ + void modifyAfter(JSONObject requestParams, T t, ModifyEnum type); + + /** + * 修改之前 + * + * @param requestParams 请求参数 + * @param t 对应实体 + */ + void modifyBefore(JSONObject requestParams, T t); + + /** + * 修改之前 + * + * @param requestParams 请求参数 + * @param t 对应实体 + * @param type 修改类型 + */ + void modifyBefore(JSONObject requestParams, T t, ModifyEnum type); +} diff --git a/cool-admin-java/src/main/java/com/cool/core/base/BaseServiceImpl.java b/cool-admin-java/src/main/java/com/cool/core/base/BaseServiceImpl.java new file mode 100644 index 0000000..f4380cc --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/base/BaseServiceImpl.java @@ -0,0 +1,137 @@ +package com.cool.core.base; + +import cn.hutool.json.JSONObject; +import com.mybatisflex.core.BaseMapper; +import com.mybatisflex.core.paginate.Page; +import com.mybatisflex.core.query.QueryWrapper; +import com.mybatisflex.spring.service.impl.ServiceImpl; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * 基础service实现类 + * + * @param Mapper 类 + * @param 实体 + */ +public class BaseServiceImpl, T extends BaseEntity> extends + ServiceImpl + implements BaseService { + + @Override + public Long add(T entity) { + mapper.insertSelective(entity); + return entity.getId(); + } + + @Override + public Object add(JSONObject requestParams, T entity) { + this.modifyBefore(requestParams, entity, ModifyEnum.ADD); + this.add(entity); + this.modifyAfter(requestParams, entity, ModifyEnum.ADD); + return entity.getId(); + } + + @Override + public Object addBatch(JSONObject requestParams, List entitys) { + this.modifyBefore(requestParams, null, ModifyEnum.ADD); + List ids = new ArrayList<>(); + entitys.forEach(e -> ids.add(this.add(e))); + requestParams.set("ids", ids); + this.modifyAfter(requestParams, null, ModifyEnum.ADD); + return ids; + } + + @Override + public boolean delete(Long... ids) { + return mapper.deleteBatchByIds(Arrays.asList(ids)) > 0; + } + + @Override + public boolean delete(JSONObject requestParams, Long... ids) { + this.modifyBefore(requestParams, null, ModifyEnum.DELETE); + boolean flag = this.delete(ids); + if (flag) { + this.modifyAfter(requestParams, null, ModifyEnum.DELETE); + } + return flag; + } + + @Override + public boolean update(T entity) { + return mapper.update(entity) > 0; + } + + @Override + public boolean update(JSONObject requestParams, T entity) { + this.modifyBefore(requestParams, entity, ModifyEnum.UPDATE); + boolean flag = this.update(entity); + if (flag) { + this.modifyAfter(requestParams, entity, ModifyEnum.UPDATE); + } + return flag; + } + + @Override + public Object list(JSONObject requestParams, QueryWrapper queryWrapper) { + return this.list(queryWrapper); + } + + @Override + public List list(JSONObject requestParams, QueryWrapper queryWrapper, Class asType) { + return mapper.selectListByQueryAs(queryWrapper, asType); + } + + @Override + public Object listWithRelations(JSONObject requestParams, QueryWrapper queryWrapper) { + return mapper.selectListWithRelationsByQuery(queryWrapper); + } + + @Override + public Object page(JSONObject requestParams, Page page, QueryWrapper queryWrapper) { + return this.page(page, queryWrapper); + } + + @Override + public Page page(JSONObject requestParams, Page page, QueryWrapper queryWrapper, + Class asType) { + return mapper.paginateAs(page, queryWrapper, asType); + } + + @Override + public Object pageWithRelations(JSONObject requestParams, Page page, + QueryWrapper queryWrapper) { + return mapper.paginateWithRelations(page, queryWrapper); + } + + @Override + public Object info(JSONObject requestParams, Long id) { + return info(id); + } + + @Override + public Object info(Long id) { + return mapper.selectOneById(id); + } + + @Override + public void modifyAfter(JSONObject requestParams, T t) { + + } + + @Override + public void modifyAfter(JSONObject requestParams, T t, ModifyEnum type) { + modifyAfter(requestParams, t); + } + + @Override + public void modifyBefore(JSONObject requestParams, T t) { + + } + + @Override + public void modifyBefore(JSONObject requestParams, T t, ModifyEnum type) { + + } +} diff --git a/cool-admin-java/src/main/java/com/cool/core/base/ModifyEnum.java b/cool-admin-java/src/main/java/com/cool/core/base/ModifyEnum.java new file mode 100644 index 0000000..22b0d85 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/base/ModifyEnum.java @@ -0,0 +1,13 @@ +package com.cool.core.base; + +/** + * 修改枚举 + */ +public enum ModifyEnum { + // 新增 + ADD, + // 修改 + UPDATE, + // 删除 + DELETE +} diff --git a/cool-admin-java/src/main/java/com/cool/core/base/TenantEntity.java b/cool-admin-java/src/main/java/com/cool/core/base/TenantEntity.java new file mode 100644 index 0000000..4e258d5 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/base/TenantEntity.java @@ -0,0 +1,16 @@ +package com.cool.core.base; + +import com.mybatisflex.core.activerecord.Model; +import com.tangzc.mybatisflex.autotable.annotation.ColumnDefine; +import lombok.Getter; +import lombok.Setter; +import org.dromara.autotable.annotation.Index; + +/** 租户ID实体类 */ +@Getter +@Setter +public class TenantEntity> extends BaseEntity { + @Index + @ColumnDefine(comment = "租户id") + protected Long tenantId; +} \ No newline at end of file diff --git a/cool-admin-java/src/main/java/com/cool/core/base/service/MapperProviderService.java b/cool-admin-java/src/main/java/com/cool/core/base/service/MapperProviderService.java new file mode 100644 index 0000000..8492857 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/base/service/MapperProviderService.java @@ -0,0 +1,52 @@ +package com.cool.core.base.service; + +import cn.hutool.core.util.ObjUtil; +import cn.hutool.core.util.TypeUtil; +import com.cool.core.util.SpringContextUtils; +import com.mybatisflex.core.BaseMapper; +import java.lang.reflect.Type; +import java.util.HashMap; +import java.util.Map; +import org.springframework.stereotype.Service; + +@Service +public class MapperProviderService { + + private Map, BaseMapper> mapperMap; + + /** + * 初始化mapperMap,key 为entityClass,value 为 mapper + */ + private void init() { + // 获取所有BaseMapper类型的Bean + Map beansOfType = SpringContextUtils.getBeansOfType(BaseMapper.class); + mapperMap = new HashMap<>(); + for (BaseMapper mapper : beansOfType.values()) { + // 通过反射获取泛型参数,即实体类 + Class entityClass = getGenericType(mapper); + if (entityClass != null) { + mapperMap.put(entityClass, mapper); + } + } + } + + /** + * 通过entity类获取 对应的mapper接口 + */ + public BaseMapper getMapperByEntityClass(Class entityClass) { + if (ObjUtil.isEmpty(mapperMap)) { + init(); + } + return (BaseMapper) mapperMap.get(entityClass); + } + + /** + * 获取mapper对应的entity对象 + */ + private Class getGenericType(BaseMapper mapper) { + // 使用 获取泛型参数类型 + Type[] types = mapper.getClass().getGenericInterfaces(); + Type typeArgument = TypeUtil.getTypeArgument(types[0], 0); + return ObjUtil.isEmpty(typeArgument) ? null : (Class) typeArgument; + } +} \ No newline at end of file diff --git a/cool-admin-java/src/main/java/com/cool/core/cache/CoolCache.java b/cool-admin-java/src/main/java/com/cool/core/cache/CoolCache.java new file mode 100644 index 0000000..aa6d381 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/cache/CoolCache.java @@ -0,0 +1,180 @@ +package com.cool.core.cache; + +import cn.hutool.core.util.ObjUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.json.JSONUtil; +import com.cool.core.util.ConvertUtil; +import jakarta.annotation.PostConstruct; +import java.time.Duration; +import java.util.Arrays; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.cache.CacheType; +import org.springframework.cache.Cache; +import org.springframework.cache.CacheManager; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.cache.RedisCacheWriter; +import org.springframework.stereotype.Component; + +/** + * 缓存工具类 + */ +@EnableCaching +@Configuration +@Component +@RequiredArgsConstructor +public class CoolCache { + + // 缓存类型 + @Value("${spring.cache.type}") + private String type; + + // redis + public RedisCacheWriter redisCache; + + private Cache cache; + + @Value("${cool.cacheName}") + private String cacheName; + + private final static String NULL_VALUE = "@_NULL_VALUE$@"; + + final private CacheManager cacheManager; + + @PostConstruct + private void init() { + cache = cacheManager.getCache(cacheName); + this.type = type.toLowerCase(); + assert cache != null : "Cache not found: " + cacheName; // Ensure cache is not null + if (type.equalsIgnoreCase(CacheType.REDIS.name())) { + redisCache = (RedisCacheWriter) cache.getNativeCache(); + } + } + + /** + * 数据来源 + */ + public interface ToCacheData { + Object apply(); + } + + /** + * 删除缓存 + * + * @param keys 一个或多个key + */ + public void del(String... keys) { + if (type.equalsIgnoreCase(CacheType.CAFFEINE.name())) { + Arrays.stream(keys).forEach(o -> cache.evict(o)); + } + if (type.equalsIgnoreCase(CacheType.REDIS.name())) { + Arrays.stream(keys).forEach(key -> redisCache.remove(cacheName, key.getBytes())); + } + } + + /** + * 普通缓存获取 + * + * @param key 键 + */ + public Object get(String key) { + Object ifNullValue = getIfNullValue(key); + if (ObjUtil.equals(ifNullValue, NULL_VALUE)) { + return null; + } + return ifNullValue; + } + + /** + * 普通缓存获取 + * + * @param key 键 + */ + public Object get(String key, Duration duration, ToCacheData toCacheData) { + Object ifNullValue = getIfNullValue(key); + if (ObjUtil.equals(ifNullValue, NULL_VALUE)) { + return null; + } + if (ObjUtil.isEmpty(ifNullValue)) { + Object obj = toCacheData.apply(); + set(key, obj, duration.toSeconds()); + return obj; + } + return ifNullValue; + } + + private Object getIfNullValue(String key) { + if (type.equalsIgnoreCase(CacheType.CAFFEINE.name())) { + Cache.ValueWrapper valueWrapper = cache.get(key); + if (valueWrapper != null) { + return valueWrapper.get(); // 获取实际的缓存值 + } + } + if (type.equalsIgnoreCase(CacheType.REDIS.name())) { + byte[] bytes = redisCache.get(cacheName, key.getBytes()); + if (bytes != null && bytes.length > 0) { + return ConvertUtil.toObject(bytes); + } + } + return null; + } + + /** + * 获得对象 + * + * @param key 键 + * @param valueType 值类型 + */ + public T get(String key, Class valueType) { + Object result = get(key); + if (result != null && JSONUtil.isTypeJSONObject(result.toString())) { + return JSONUtil.parseObj(result).toBean(valueType); + } + return result != null ? (T) result : null; + } + + /** + * 获得缓存类型 + */ + public String getMode() { + return this.type; + } + + /** + * 获得原生缓存实例 + */ + public Object getMetaCache() { + return this.cache; + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + */ + public void set(String key, Object value) { + set(key, value, 0); + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param ttl 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + */ + public void set(String key, Object value, long ttl) { + if (ObjUtil.isNull(value)) { + value = NULL_VALUE; + } + if (type.equalsIgnoreCase(CacheType.CAFFEINE.name())) { + // 放入缓存 + cache.put(key, value); + } else if (type.equalsIgnoreCase(CacheType.REDIS.name())) { + redisCache.put(cacheName, key.getBytes(), ObjectUtil.serialize(value), + java.time.Duration.ofSeconds(ttl)); + } + } +} diff --git a/cool-admin-java/src/main/java/com/cool/core/code/CodeGenerator.java b/cool-admin-java/src/main/java/com/cool/core/code/CodeGenerator.java new file mode 100644 index 0000000..37a8400 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/code/CodeGenerator.java @@ -0,0 +1,108 @@ +package com.cool.core.code; + +import cn.hutool.core.io.file.FileWriter; +import cn.hutool.core.lang.Dict; +import cn.hutool.core.util.StrUtil; +import cn.hutool.extra.template.Template; +import cn.hutool.extra.template.TemplateConfig; +import cn.hutool.extra.template.TemplateEngine; +import cn.hutool.extra.template.TemplateUtil; +import jakarta.annotation.PostConstruct; +import org.springframework.stereotype.Component; + +/** + * 代码生成器 + */ +@Component +public class CodeGenerator { + + private TemplateEngine templateEngine; + + private String baseSrcPath; + + private String baseResPath; + + @PostConstruct + public void init() { + templateEngine = coolTemplateEngine(); + baseSrcPath = System.getProperty("user.dir") + "/src/main/java/com/cool/modules/"; + baseResPath = System.getProperty("user.dir") + "/src/main/resources/"; + } + + public TemplateEngine coolTemplateEngine() { + return TemplateUtil.createEngine( + new TemplateConfig("cool/code", TemplateConfig.ResourceMode.CLASSPATH)); + } + + private String filePath(CodeModel codeModel, String type) { + if (type.equals("controller")) { + return StrUtil.isEmpty(codeModel.getSubModule()) + ? baseSrcPath + codeModel.getModule() + "/" + type + "/" + codeModel.getType() + .value() + : baseSrcPath + codeModel.getModule() + "/" + type + "/" + codeModel.getType() + .value() + "/" + + codeModel.getSubModule(); + } + if (type.equals("xmlMapper")) { + return StrUtil.isEmpty(codeModel.getSubModule()) ? baseResPath + "mapper/" + + codeModel.getModule() + : baseResPath + "mapper/" + codeModel.getModule() + "/" + codeModel.getSubModule(); + } + return StrUtil.isEmpty(codeModel.getSubModule()) ? baseSrcPath + codeModel.getModule() + "/" + + type + : baseSrcPath + codeModel.getModule() + "/" + type + "/" + codeModel.getSubModule(); + } + + /** + * 生成Mapper + * + * @param codeModel 代码模型 + */ + public void mapper(CodeModel codeModel) { + Template template = templateEngine.getTemplate("/mapper/interface.th"); + String result = template.render(Dict.parse(codeModel)); + FileWriter writer = new FileWriter( + filePath(codeModel, "mapper") + "/" + codeModel.getEntity() + "Mapper.java"); + writer.write(result); + } + + /** + * 生成Service + * + * @param codeModel 代码模型 + */ + public void service(CodeModel codeModel) { + Template interfaceTemplate = templateEngine.getTemplate("/service/interface.th"); + String interfaceResult = interfaceTemplate.render(Dict.parse(codeModel)); + FileWriter interfaceWriter = new FileWriter( + filePath(codeModel, "service") + "/" + codeModel.getEntity() + "Service.java"); + interfaceWriter.write(interfaceResult); + + Template template = templateEngine.getTemplate("/service/impl.th"); + String result = template.render(Dict.parse(codeModel)); + FileWriter writer = new FileWriter( + filePath(codeModel, "service") + "/impl/" + codeModel.getEntity() + "ServiceImpl.java"); + writer.write(result); + } + + /** + * 生成Controller + * + * @param codeModel 代码模型 + */ + public void controller(CodeModel codeModel) { + Template template = templateEngine.getTemplate("controller.th"); + System.out.println(codeModel.getType().value()); + Dict data = Dict.create().set("upperType", StrUtil.upperFirst(codeModel.getType().value())) + .set("url", + "/" + codeModel.getType() + "/" + StrUtil.toUnderlineCase(codeModel.getEntity()) + .replace("_", "/")); + data.putAll(Dict.parse(codeModel)); + data.set("type", codeModel.getType().value()); + String result = template.render(data); + FileWriter writer = new FileWriter(filePath(codeModel, "controller") + "/" + + StrUtil.upperFirst(codeModel.getType().value()) + codeModel.getEntity() + + "Controller.java"); + writer.write(result); + } +} diff --git a/cool-admin-java/src/main/java/com/cool/core/code/CodeModel.java b/cool-admin-java/src/main/java/com/cool/core/code/CodeModel.java new file mode 100644 index 0000000..a2566fd --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/code/CodeModel.java @@ -0,0 +1,36 @@ +package com.cool.core.code; + +import lombok.Data; + +/** + * 代码模型 + */ +@Data +public class CodeModel { + /** + * 类型 后台还是对外的接口 admin app + */ + private CodeTypeEnum type; + /** + * 名称 + */ + private String name; + /** + * 模块 + */ + private String module; + + /** + * 子模块 + */ + private String subModule; + + /** + * 实体类 + */ + private String entity; + + public void setEntity(Class entity) { + this.entity = entity.getSimpleName().replace("Entity", ""); + } +} diff --git a/cool-admin-java/src/main/java/com/cool/core/code/CodeTypeEnum.java b/cool-admin-java/src/main/java/com/cool/core/code/CodeTypeEnum.java new file mode 100644 index 0000000..873ef49 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/code/CodeTypeEnum.java @@ -0,0 +1,21 @@ +package com.cool.core.code; + +/** + * 代码类型 + */ +public enum CodeTypeEnum { + ADMIN("admin", "后端接口"), APP("app", "对外接口"); + + private String value; + + private String des; + + CodeTypeEnum(String value, String des) { + this.value = value; + this.des = des; + } + + public String value() { + return this.value; + } +} diff --git a/cool-admin-java/src/main/java/com/cool/core/config/CoolProperties.java b/cool-admin-java/src/main/java/com/cool/core/config/CoolProperties.java new file mode 100644 index 0000000..88e3fe9 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/config/CoolProperties.java @@ -0,0 +1,23 @@ +package com.cool.core.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.NestedConfigurationProperty; +import org.springframework.context.annotation.Configuration; + +/** + * cool的配置 + */ +@Data +@Configuration +@ConfigurationProperties(prefix = "cool") +public class CoolProperties { + // 是否自动导入数据 + private Boolean initData = false; + // token配置 + @NestedConfigurationProperty + private TokenProperties token; + // 文件配置 + @NestedConfigurationProperty + private FileProperties file; +} diff --git a/cool-admin-java/src/main/java/com/cool/core/config/CustomOpenApiResource.java b/cool-admin-java/src/main/java/com/cool/core/config/CustomOpenApiResource.java new file mode 100644 index 0000000..e01d325 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/config/CustomOpenApiResource.java @@ -0,0 +1,40 @@ +package com.cool.core.config; + +import com.fasterxml.jackson.core.JsonProcessingException; +import jakarta.servlet.http.HttpServletRequest; +import java.util.Locale; +import org.springdoc.core.customizers.SpringDocCustomizers; +import org.springdoc.core.properties.SpringDocConfigProperties; +import org.springdoc.core.providers.SpringDocProviders; +import org.springdoc.core.service.AbstractRequestService; +import org.springdoc.core.service.GenericResponseService; +import org.springdoc.core.service.OpenAPIService; +import org.springdoc.core.service.OperationService; +import org.springdoc.webmvc.api.OpenApiResource; +import org.springframework.beans.factory.ObjectFactory; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Component; + +/** + * 自定义 OpenApiResource + */ +@Component +@ConditionalOnProperty( + name = "springdoc.api-docs.enabled", + havingValue = "true" +) +public class CustomOpenApiResource extends OpenApiResource { + + public CustomOpenApiResource(ObjectFactory openAPIBuilderObjectFactory, AbstractRequestService requestBuilder, GenericResponseService responseBuilder, OperationService operationParser, SpringDocConfigProperties springDocConfigProperties, SpringDocProviders springDocProviders, SpringDocCustomizers springDocCustomizers) { + super("springdocDefault", openAPIBuilderObjectFactory, requestBuilder, responseBuilder, operationParser, springDocConfigProperties, springDocProviders, springDocCustomizers); + } + + @Override + protected String getServerUrl(HttpServletRequest request, String apiDocsUrl) { + return ""; + } + + public byte[] getOpenApiJson() throws JsonProcessingException { + return writeJsonValue(getOpenApi(Locale.getDefault())); + } +} \ No newline at end of file diff --git a/cool-admin-java/src/main/java/com/cool/core/config/FileModeEnum.java b/cool-admin-java/src/main/java/com/cool/core/config/FileModeEnum.java new file mode 100644 index 0000000..243520b --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/config/FileModeEnum.java @@ -0,0 +1,28 @@ +package com.cool.core.config; + +/** + * 文件模式 + */ +public enum FileModeEnum { + LOCAL("local", "local", "本地"), CLOUD("cloud", "oss", "云存储"), OTHER("other", "other", "其他"); + + private String value; + + private String type; + + private String des; + + FileModeEnum(String value, String type, String des) { + this.value = value; + this.type = type; + this.des = des; + } + + public String value() { + return this.value; + } + + public String type() { + return this.type; + } +} diff --git a/cool-admin-java/src/main/java/com/cool/core/config/FileProperties.java b/cool-admin-java/src/main/java/com/cool/core/config/FileProperties.java new file mode 100644 index 0000000..4af01c0 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/config/FileProperties.java @@ -0,0 +1,22 @@ +package com.cool.core.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.NestedConfigurationProperty; +import org.springframework.context.annotation.Configuration; + +/** + * 文件 + */ +@Data +@Configuration +@ConfigurationProperties(prefix = "cool.file") +public class FileProperties { + // 上传模式 + private FileModeEnum mode; + // 上传类型 + private String type; + // 本地文件上传 + @NestedConfigurationProperty + private LocalFileProperties local; +} diff --git a/cool-admin-java/src/main/java/com/cool/core/config/JacksonConfig.java b/cool-admin-java/src/main/java/com/cool/core/config/JacksonConfig.java new file mode 100644 index 0000000..8351306 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/config/JacksonConfig.java @@ -0,0 +1,67 @@ +package com.cool.core.config; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.fasterxml.jackson.databind.ser.std.NumberSerializer; +import java.io.IOException; +import java.math.BigInteger; +import java.text.SimpleDateFormat; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; + +@Configuration +public class JacksonConfig { + + @Bean + public MappingJackson2HttpMessageConverter jackson2HttpMessageConverter() { + final Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder(); + final ObjectMapper objectMapper = builder.build(); + SimpleModule simpleModule = new SimpleModule(); + // Long,BigInteger 转为 String 防止 js 丢失精度 + simpleModule.addSerializer(Long.class, BigNumberSerializer.INSTANCE); + simpleModule.addSerializer(Long.TYPE, BigNumberSerializer.INSTANCE); + simpleModule.addSerializer(BigInteger.class, BigNumberSerializer.INSTANCE); + objectMapper.registerModule(simpleModule); + // 配置日期格式为 yyyy-MM-dd HH:mm:ss + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + objectMapper.setDateFormat(dateFormat); + return new MappingJackson2HttpMessageConverter(objectMapper); + } + + /** + * 超出 JS 最大最小值 处理 + */ + @JacksonStdImpl + public static class BigNumberSerializer extends NumberSerializer { + + /** + * 根据 JS Number.MAX_SAFE_INTEGER 与 Number.MIN_SAFE_INTEGER 得来 + */ + private static final long MAX_SAFE_INTEGER = 9007199254740991L; + private static final long MIN_SAFE_INTEGER = -9007199254740991L; + + /** + * 提供实例 + */ + public static final BigNumberSerializer INSTANCE = new BigNumberSerializer(Number.class); + + public BigNumberSerializer(Class rawType) { + super(rawType); + } + + @Override + public void serialize(Number value, JsonGenerator gen, SerializerProvider provider) throws IOException { + // 超出范围 序列化位字符串 + if (value.longValue() > MIN_SAFE_INTEGER && value.longValue() < MAX_SAFE_INTEGER) { + super.serialize(value, gen, provider); + } else { + gen.writeString(value.toString()); + } + } + } +} \ No newline at end of file diff --git a/cool-admin-java/src/main/java/com/cool/core/config/LocalFileProperties.java b/cool-admin-java/src/main/java/com/cool/core/config/LocalFileProperties.java new file mode 100644 index 0000000..5ecad6f --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/config/LocalFileProperties.java @@ -0,0 +1,30 @@ +package com.cool.core.config; + +import com.cool.core.util.PathUtils; +import java.io.File; +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +/** + * 文件 + */ +@Data +@Configuration +@ConfigurationProperties(prefix = "cool.file.local") +public class LocalFileProperties { + + // 跟域名 + private String baseUrl; + + private String uploadPath = "assets/public/upload"; + + public String getAbsoluteUploadFolder() { + if (!PathUtils.isAbsolutePath(uploadPath)) { + // 相对路径 + return System.getProperty("user.dir") + File.separator + uploadPath; + } + // 绝对路径 + return uploadPath; + } +} diff --git a/cool-admin-java/src/main/java/com/cool/core/config/LogDiscardPolicy.java b/cool-admin-java/src/main/java/com/cool/core/config/LogDiscardPolicy.java new file mode 100644 index 0000000..a661aaa --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/config/LogDiscardPolicy.java @@ -0,0 +1,13 @@ +package com.cool.core.config; + +import java.util.concurrent.RejectedExecutionHandler; +import java.util.concurrent.ThreadPoolExecutor; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class LogDiscardPolicy implements RejectedExecutionHandler { + + public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) { + log.warn("logTaskExecutor 当前已超过线程池最大队列容量,拒绝策略为丢弃该线程 {}", r.toString()); + } +} \ No newline at end of file diff --git a/cool-admin-java/src/main/java/com/cool/core/config/LogProperties.java b/cool-admin-java/src/main/java/com/cool/core/config/LogProperties.java new file mode 100644 index 0000000..0452ff8 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/config/LogProperties.java @@ -0,0 +1,28 @@ +package com.cool.core.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +@Data +@Component +@ConfigurationProperties(prefix = "cool.log") +public class LogProperties { + + /** + * 请求参数最大字节,超过请求参数不记录 + */ + private int maxByteLength; + /** + * 核心线程数的倍数 + */ + private int corePoolSizeMultiplier; + /** + * 最大线程数的倍数 + */ + private int maxPoolSizeMultiplier; + /** + * 队列容量的倍数 + */ + private int queueCapacityMultiplier; +} diff --git a/cool-admin-java/src/main/java/com/cool/core/config/MyBatisFlexConfiguration.java b/cool-admin-java/src/main/java/com/cool/core/config/MyBatisFlexConfiguration.java new file mode 100644 index 0000000..e7dcfa1 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/config/MyBatisFlexConfiguration.java @@ -0,0 +1,27 @@ +package com.cool.core.config; + +import com.cool.core.tenant.CoolTenantFactory; +import com.mybatisflex.core.FlexGlobalConfig; +import com.mybatisflex.core.tenant.TenantFactory; +import com.mybatisflex.spring.boot.MyBatisFlexCustomizer; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class MyBatisFlexConfiguration implements MyBatisFlexCustomizer { + + @Override + public void customize(FlexGlobalConfig globalConfig) { + // 我们可以在这里进行一些列的初始化配置 + + // 指定多租户列的列名 + FlexGlobalConfig.getDefaultConfig().setTenantColumn("tenant_id"); + } + + @Bean + @ConditionalOnProperty(name = "cool.multi-tenant.enable", havingValue = "true") + public TenantFactory tenantFactory(){ + return new CoolTenantFactory(); + } +} \ No newline at end of file diff --git a/cool-admin-java/src/main/java/com/cool/core/config/OssFileProperties.java b/cool-admin-java/src/main/java/com/cool/core/config/OssFileProperties.java new file mode 100644 index 0000000..1f02b3d --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/config/OssFileProperties.java @@ -0,0 +1,24 @@ +package com.cool.core.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +/** + * 文件 + */ +@Data +@Configuration +@ConfigurationProperties(prefix = "cool.file.oss") +public class OssFileProperties { + // accessKeyId + private String accessKeyId; + // accessKeySecret + private String accessKeySecret; + // 文件空间 + private String bucket; + // 地址 + private String endpoint; + // 超时时间 + private Long timeout; +} diff --git a/cool-admin-java/src/main/java/com/cool/core/config/PluginJson.java b/cool-admin-java/src/main/java/com/cool/core/config/PluginJson.java new file mode 100644 index 0000000..ad39263 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/config/PluginJson.java @@ -0,0 +1,57 @@ +package com.cool.core.config; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +import java.util.Map; + +@Data +public class PluginJson { + /** + * 插件名称 + */ + private String name; + /** + * 插件标识 + */ + private String key; + /** + * 插件钩子,比如替换系统的上传组件,upload + */ + private String hook; + /** + * 版本号 + */ + private String version; + /** + * 插件描述 + */ + private String description; + /** + * 作者 + */ + private String author; + /** + * 插件 logo,建议尺寸 256x256 + */ + private String logo; + /** + * 插件介绍,会展示在插件的详情中 + */ + private String readme; + /** + * 插件配置, 每个插件的配置各不相同 + */ + private Map config; + + /** + * jar包存放路径 + */ + private String jarPath; + + /** + * 同名hook id + */ + @JsonIgnore + private Long sameHookId; +} diff --git a/cool-admin-java/src/main/java/com/cool/core/config/SwaggerConfig.java b/cool-admin-java/src/main/java/com/cool/core/config/SwaggerConfig.java new file mode 100644 index 0000000..8772d16 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/config/SwaggerConfig.java @@ -0,0 +1,16 @@ +package com.cool.core.config; + +import io.swagger.v3.oas.annotations.ExternalDocumentation; +import io.swagger.v3.oas.annotations.OpenAPIDefinition; +import io.swagger.v3.oas.annotations.enums.SecuritySchemeIn; +import io.swagger.v3.oas.annotations.enums.SecuritySchemeType; +import io.swagger.v3.oas.annotations.info.Contact; +import io.swagger.v3.oas.annotations.info.Info; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.security.SecurityScheme; + +@OpenAPIDefinition(info = @Info(title = "COOL-ADMIN", version = "4.0", description = "一个很酷的后台权限管理系统开发框架", contact = @Contact(name = "闪酷科技")), security = @SecurityRequirement(name = "Authorization"), externalDocs = @ExternalDocumentation(description = "参考文档", url = "https://cool-js.com")) +@SecurityScheme(type = SecuritySchemeType.APIKEY, name = "Authorization", in = SecuritySchemeIn.HEADER) +public class SwaggerConfig { + +} diff --git a/cool-admin-java/src/main/java/com/cool/core/config/ThreadPoolConfig.java b/cool-admin-java/src/main/java/com/cool/core/config/ThreadPoolConfig.java new file mode 100644 index 0000000..9fc6dc7 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/config/ThreadPoolConfig.java @@ -0,0 +1,41 @@ +package com.cool.core.config; + +import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; + +@Configuration +@RequiredArgsConstructor +public class ThreadPoolConfig { + + private final LogProperties logProperties; + + @Bean(name = "logTaskExecutor") + public Executor loggingTaskExecutor() { + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + + int corePoolSize = Runtime.getRuntime().availableProcessors() * logProperties.getCorePoolSizeMultiplier(); + int maxPoolSize = corePoolSize * logProperties.getMaxPoolSizeMultiplier(); + int queueCapacity = maxPoolSize * logProperties.getQueueCapacityMultiplier(); + + executor.setCorePoolSize(corePoolSize); + executor.setMaxPoolSize(maxPoolSize); + executor.setQueueCapacity(queueCapacity); + executor.setThreadNamePrefix("logTask-"); + + // 自定义拒绝策略 + executor.setRejectedExecutionHandler(new LogDiscardPolicy()); + executor.initialize(); + return executor; + } + + @Bean(name = "cachedThreadPool") + public ExecutorService cachedThreadPool() { + // 创建一个虚拟线程池,每个任务使用一个虚拟线程执行 + return Executors.newCachedThreadPool(); + } +} diff --git a/cool-admin-java/src/main/java/com/cool/core/config/TokenProperties.java b/cool-admin-java/src/main/java/com/cool/core/config/TokenProperties.java new file mode 100644 index 0000000..12cd713 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/config/TokenProperties.java @@ -0,0 +1,18 @@ +package com.cool.core.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +/** + * token配置 + */ +@Data +@Configuration +@ConfigurationProperties(prefix = "cool.token") +public class TokenProperties { + // token 过期时间 + private Long expire; + // refreshToken 过期时间 + private Long refreshExpire; +} diff --git a/cool-admin-java/src/main/java/com/cool/core/config/cache/CaffeineConfig.java b/cool-admin-java/src/main/java/com/cool/core/config/cache/CaffeineConfig.java new file mode 100644 index 0000000..d22204c --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/config/cache/CaffeineConfig.java @@ -0,0 +1,122 @@ +package com.cool.core.config.cache; + +import com.github.benmanes.caffeine.cache.Caffeine; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.HashMap; +import java.util.Map; + +import jakarta.annotation.PostConstruct; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.cache.Cache; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.cache.caffeine.CaffeineCacheManager; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.event.ContextClosedEvent; +import org.springframework.context.event.EventListener; +import org.springframework.scheduling.annotation.Scheduled; + +@Slf4j +@Configuration +@EnableCaching +@ConditionalOnProperty(name = "spring.cache.type", havingValue = "CAFFEINE") +public class CaffeineConfig { + + @Value("${spring.cache.file}") + private String cacheFile; + + @Value("${cool.cacheName}") + private String cacheName; + + @Bean + public Caffeine caffeine() { + return Caffeine.newBuilder().maximumSize(10000); + } + + @Bean + public CaffeineCacheManager cacheManager(Caffeine caffeine) { + CaffeineCacheManager cacheManager = new CaffeineCacheManager(); + cacheManager.setCaffeine(caffeine); + loadCache(cacheManager); + return cacheManager; + } + + @PostConstruct + public void init() { + File cacheDir = new File(cacheFile).getParentFile(); + if (!cacheDir.exists()) { + if (cacheDir.mkdirs()) { + log.info("Created directory: " + cacheDir.getAbsolutePath()); + } else { + log.error("Failed to create directory: " + cacheDir.getAbsolutePath()); + } + } + } + + private void loadCache(CaffeineCacheManager cacheManager) { + if (cacheManager == null) { + log.error("CacheManager is null"); + return; + } + + if (cacheFile == null || cacheFile.isEmpty()) { + log.error("Cache file path is null or empty"); + return; + } + + File file = new File(cacheFile); + if (!file.exists()) { + log.warn("Cache file does not exist: " + cacheFile); + return; + } + try (ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream(file))) { + Map cacheMap = (Map) inputStream.readObject(); + com.github.benmanes.caffeine.cache.Cache caffeineCache = Caffeine.newBuilder() + .build(); + caffeineCache.putAll(cacheMap); + cacheManager.registerCustomCache(cacheName, caffeineCache); + } catch (IOException | ClassNotFoundException e) { + log.error("loadCacheErr", e); + } + } + + @Bean + public CacheLoader cacheLoader(CaffeineCacheManager cacheManager) { + return new CacheLoader(cacheManager, cacheFile); + } + + class CacheLoader { + + private final CaffeineCacheManager cacheManager; + private final String cacheFile; + + public CacheLoader(CaffeineCacheManager cacheManager, String cacheFile) { + this.cacheManager = cacheManager; + this.cacheFile = cacheFile; + } + + @EventListener(ContextClosedEvent.class) + @Scheduled(fixedRate = 10000) + public void persistCache() { + Cache cache = cacheManager.getCache(cacheName); + if (cache != null + && cache.getNativeCache() instanceof com.github.benmanes.caffeine.cache.Cache) { + Map cacheMap = ((com.github.benmanes.caffeine.cache.Cache) cache + .getNativeCache()).asMap(); + try (ObjectOutputStream outputStream = new ObjectOutputStream( + new FileOutputStream(cacheFile))) { + outputStream.writeObject(new HashMap<>(cacheMap)); + } catch (IOException e) { + log.error("persistCacheErr", e); + } + } + } + } +} diff --git a/cool-admin-java/src/main/java/com/cool/core/config/cache/RedisConfig.java b/cool-admin-java/src/main/java/com/cool/core/config/cache/RedisConfig.java new file mode 100644 index 0000000..9da37da --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/config/cache/RedisConfig.java @@ -0,0 +1,29 @@ +package com.cool.core.config.cache; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.cache.CacheManager; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.cache.RedisCacheManager; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; + +@Configuration +@EnableCaching +@ConditionalOnProperty(name = "spring.cache.type", havingValue = "redis") +public class RedisConfig { + + @Bean + public RedisTemplate redisTemplate( + RedisConnectionFactory redisConnectionFactory) { + RedisTemplate template = new RedisTemplate<>(); + template.setConnectionFactory(redisConnectionFactory); + return template; + } + + @Bean + public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) { + return RedisCacheManager.create(redisConnectionFactory); + } +} diff --git a/cool-admin-java/src/main/java/com/cool/core/enums/AdminComponentsEnum.java b/cool-admin-java/src/main/java/com/cool/core/enums/AdminComponentsEnum.java new file mode 100644 index 0000000..e4c95f1 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/enums/AdminComponentsEnum.java @@ -0,0 +1,105 @@ +package com.cool.core.enums; + +public class AdminComponentsEnum { + + + /** + * 省市区选择器 - 用户选择省市区 + */ + public static final String PCA = "pca"; + + /** + * 文本输入 - 文本编辑框 + */ + public static final String INPUT = "input"; + + /** + * 文本域 - 多行文本编辑框 + */ + public static final String TEXTAREA = "textarea"; + + /** + * 富文本编辑器 - 用于文章,商品详情的编辑 + */ + public static final String EDITOR_RICH = "editor-rich"; + + /** + * 代码编辑器 - 用于开发人员编写代码,支持多种语言,支持代码高亮,支持代码格式化 + */ + public static final String CODING = "coding"; + + /** + * 数字输入 - 数字输入编辑框 + */ + public static final String INPUT_NUMBER = "input-number"; + + /** + * 日期选择器 - 用户选择 年-月-日 + */ + public static final String DATE = "date"; + + /** + * 日期范围选择器 - 用户选择起始 年-月-日 + */ + public static final String DATERANGE = "daterange"; + + /** + * 时间选择器 - 用户选择 时:分:秒 + */ + public static final String DATETIME = "datetime"; + + /** + * 时间范围选择器 - 用户选择起始 年-月-日 时:分:秒 + */ + public static final String DATETIMERANGE = "datetimerange"; + + /** + * 单图上传 - 用户上传单张图片,如:头像、logo、封面 + */ + public static final String UPLOAD_IMG = "upload-img"; + + /** + * 多图上传 - 用户上传多张图片, 如:照片、图片 + */ + public static final String UPLOAD_IMG_MULTIPLE = "upload-img-multiple"; + + /** + * 单个文件上传 - 用户上传单个文件 + */ + public static final String UPLOAD_FILE = "upload-file"; + + /** + * 多个文件上传 - 用户上传多个文件 + */ + public static final String UPLOAD_FILE_MULTIPLE = "upload-file-multiple"; + + /** + * 状态选择器 - 用户开启或者关闭操作,如:是否启用、是否推荐、是否默认、置顶、启用禁用等 + */ + public static final String SWITCH = "switch"; + + /** + * 评分选择器 - 用户评分 + */ + public static final String RATE = "rate"; + + /** + * 滑块选择器 - 在一个固定区间内进行选择, 如:进度 + */ + public static final String PROGRESS = "progress"; + + /** + * 单选框 - 在一组备选项中进行单选,如:审批状态 + */ + public static final String RADIO = "radio"; + + /** + * 多选框 - 适用于选项比较少的情况,在一组备选项中进行多选, 如:学历、爱好等 + */ + public static final String CHECKBOX = "checkbox"; + + /** + * 下拉框 - 适用于当选项过多时,使用下拉菜单展示并选择内容,如:分类、标签等 + */ + public static final String SELECT = "select"; +} diff --git a/cool-admin-java/src/main/java/com/cool/core/enums/Apis.java b/cool-admin-java/src/main/java/com/cool/core/enums/Apis.java new file mode 100644 index 0000000..b8a4509 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/enums/Apis.java @@ -0,0 +1,13 @@ +package com.cool.core.enums; + +public class Apis { + public static final String ADD = "add"; + public static final String DELETE = "delete"; + public static final String UPDATE = "update"; + public static final String PAGE = "page"; + public static final String LIST = "list"; + public static final String INFO = "info"; + + + public static final String[] ALL_API = new String[]{ ADD, DELETE, UPDATE, PAGE, LIST, INFO }; +} diff --git a/cool-admin-java/src/main/java/com/cool/core/enums/QueryModeEnum.java b/cool-admin-java/src/main/java/com/cool/core/enums/QueryModeEnum.java new file mode 100644 index 0000000..8ab1e25 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/enums/QueryModeEnum.java @@ -0,0 +1,10 @@ +package com.cool.core.enums; + +/** + * 查询模式决定返回值 + */ +public enum QueryModeEnum { + ENTITY, // 实体(默认) + ENTITY_WITH_RELATIONS, // 实体关联查询(如实体字段上加 @RelationOneToMany 等注解) + CUSTOM , // 自定义,默认为Map +} diff --git a/cool-admin-java/src/main/java/com/cool/core/enums/UserTypeEnum.java b/cool-admin-java/src/main/java/com/cool/core/enums/UserTypeEnum.java new file mode 100644 index 0000000..a35be7c --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/enums/UserTypeEnum.java @@ -0,0 +1,10 @@ +package com.cool.core.enums; + +/** + * 用户类型 + */ +public enum UserTypeEnum { + ADMIN, // 后台 + APP, // app + UNKNOWN, // 未知 +} diff --git a/cool-admin-java/src/main/java/com/cool/core/eps/CoolEps.java b/cool-admin-java/src/main/java/com/cool/core/eps/CoolEps.java new file mode 100644 index 0000000..cf9e3b9 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/eps/CoolEps.java @@ -0,0 +1,410 @@ +package com.cool.core.eps; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.lang.Dict; +import cn.hutool.core.thread.ThreadUtil; +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.ClassUtil; +import cn.hutool.core.util.ObjUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.extra.spring.SpringUtil; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import com.cool.core.annotation.EpsField; +import com.cool.core.annotation.TokenIgnore; +import com.cool.core.config.CustomOpenApiResource; +import com.mybatisflex.annotation.Table; +import com.tangzc.mybatisflex.autotable.annotation.ColumnDefine; +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; +import java.util.*; +import java.util.stream.Collectors; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.annotation.AnnotatedElementUtils; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Component; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.mvc.method.RequestMappingInfo; +import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; + +/** + * 实体信息与路径 + */ +@Getter +@Component +@Slf4j +@RequiredArgsConstructor +public class CoolEps { + + @Value("${server.port}") + private int serverPort; + + private Dict entityInfo; + + private Dict menuInfo; + + private JSONObject swaggerInfo; + + @Value("${springdoc.api-docs.enabled:false}") + private boolean apiDocsEnabled; + + public Dict admin; + + public Dict app; + + final private RequestMappingHandlerMapping requestMappingHandlerMapping; + + @Async + public void init() { + if (!apiDocsEnabled) { + log.info("服务启动成功,端口:{}", serverPort); + return; + } + entityInfo = Dict.create(); + menuInfo = Dict.create(); + swaggerInfo = swaggerInfo(); + Runnable task = () -> { + entity(); + urls(); + log.info("初始化eps完成,服务启动成功,端口:{}", serverPort); + }; + // ThreadUtil.safeSleep(3000); + ThreadUtil.execute(task); + } + + /** + * 清空所有的数据 + */ + public void clear() { + admin = Dict.create(); + app = Dict.create(); + } + + /** + * 构建所有的url + */ + private void urls() { + Dict admin = Dict.create(); + Dict app = Dict.create(); + ArrayList emptyList = new ArrayList<>(); + Map map = requestMappingHandlerMapping.getHandlerMethods(); + for (Map.Entry methodEntry : map.entrySet()) { + RequestMappingInfo info = methodEntry.getKey(); + HandlerMethod method = methodEntry.getValue(); + TokenIgnore tokenIgnore = method.getMethodAnnotation(TokenIgnore.class); + String module = getModule(method); + if (StrUtil.isNotEmpty(module)) { + String entityName = getEntity(method.getBeanType()); + String methodPath = getMethodUrl(method); + String escapedMethodPath = methodPath.replace("{", "\\{").replace("}", "\\}"); + String prefix = Objects.requireNonNull(getUrl(info)) + .replaceFirst("(?s)(.*)" + escapedMethodPath, "$1"); + Dict result; + int type = 0; + if (prefix.startsWith("/admin")) { + result = admin; + } else if (prefix.startsWith("/app")) { + result = app; + type = 1; + } else { + continue; + } + if (result.get(module) == null) { + result.set(module, new ArrayList()); + } + + List urls = result.getBean(module); + Dict item = CollUtil.findOne(urls, dict -> { + if (dict != null) { + return dict.getStr("module").equals(module) + && dict.getStr("controller") + .equals(method.getBeanType().getSimpleName()); + } else { + return false; + } + }); + if (item != null) { + item.set("api", apis(prefix, methodPath, item.getBean("api"), tokenIgnore)); + } else { + item = Dict.create(); + item.set("controller", method.getBeanType().getSimpleName()); + item.set("module", module); + item.set("info", Dict.create().set("type", + Dict.create() + .set("name", getLastPathSegment(prefix)) + .set("description", "") + )); + item.set("api", apis(prefix, methodPath, item.getBean("api"), tokenIgnore)); + item.set("name", entityName); + item.set("columns", entityInfo.get(entityName)); + item.set("pageQueryOp", Dict.create().set("keyWordLikeFields", emptyList) + .set("fieldEq", emptyList) + .set("fieldLike", emptyList)); + item.set("prefix", prefix); + item.set("menu", menuInfo.get(entityName)); + urls.add(item); + } + if (type == 0) { + admin.set(module, urls); + } + if (type == 1) { + app.set(module, urls); + } + + } + } + this.admin = admin; + this.app = app; + + } + /** + * 提取URL路径中的最后一个路径段 + * 示例:输入 "/api/getData" 返回 "getData" + */ + private String getLastPathSegment(String url) { + if (StrUtil.isBlank(url)) { + return ""; + } + + int queryIndex = url.indexOf('?'); + if (queryIndex != -1) { + url = url.substring(0, queryIndex); + } + + int slashIndex = url.lastIndexOf('/'); + if (slashIndex != -1 && slashIndex < url.length() - 1) { + return url.substring(slashIndex + 1); + } else { + return url; + } + } + + + /** + * 设置所有的api + * + * @param prefix 路由前缀 + * @param methodPath 方法路由 + * @param list api列表 + * @return api列表 + */ + private List apis(String prefix, String methodPath, List list, TokenIgnore tokenIgnore) { + if (ObjUtil.isNull(list)) { + list = new ArrayList<>(); + } + Dict item = Dict.create(); + item.set("path", methodPath); + item.set("tag", ""); + item.set("dts", Dict.create()); + item.set("ignoreToken", false); + if (tokenIgnore != null) { + item.set("ignoreToken", true); + } + setSwaggerInfo(item, prefix + methodPath); + list.add(item); + return list; + } + + /** + * 设置swagger相关信息 + * + * @param item 信息载体 + * @param url url地址 + */ + private void setSwaggerInfo(Dict item, String url) { + JSONObject paths = swaggerInfo.getJSONObject("paths"); + JSONObject urlInfo = paths.getJSONObject(url); + String method = urlInfo.keySet().iterator().next(); + JSONObject methodInfo = urlInfo.getJSONObject(method); + item.set("method", method); + item.set("summary", methodInfo.getStr("summary")); + } + + /** + * 获得方法的url地址 + * + * @param handlerMethod 方法 + * @return 方法url地址 + */ + private String getMethodUrl(HandlerMethod handlerMethod) { + String url = ""; + Method method = handlerMethod.getMethod(); + Annotation[] annotations = method.getDeclaredAnnotations(); + + for (Annotation annotation : annotations) { + Class annotationType = annotation.annotationType(); + if (annotationType.getName().contains("org.springframework.web.bind.annotation")) { + Map attributes = Arrays.stream(annotationType.getDeclaredMethods()) + .collect(Collectors.toMap(Method::getName, m -> { + try { + return m.invoke(annotation); + } catch (Exception e) { + throw new IllegalStateException("Failed to access annotation attribute", + e); + } + })); + + if (attributes.containsKey("value") && ObjUtil.isNotEmpty(attributes.get("value"))) { + url = ((String[]) attributes.get("value"))[0]; + } + break; + } + } + + return url; + } + + /** + * 获得url地址 + * + * @param info 路由信息 + * @return url地址 + */ + private String getUrl(RequestMappingInfo info) { + if (info.getPathPatternsCondition() == null) { + return null; + } + Set paths = info.getPathPatternsCondition().getPatternValues(); + return paths.iterator().next(); + } + + /** + * 获得模块 + * + * @param method 方法 + * @return 模块 + */ + private String getModule(HandlerMethod method) { + String beanName = method.getBeanType().getName(); + String[] beanNames = beanName.split("[.]"); + int index = ArrayUtil.indexOf(beanNames, "modules"); + if (index > 0) { + return beanNames[index + 1]; + } + return null; + } + + /** + * 获得swagger的json信息 + */ + private JSONObject swaggerInfo() { + try { + byte[] bytes = SpringUtil.getBean(CustomOpenApiResource.class).getOpenApiJson(); + return JSONUtil.parseObj(new String(bytes)); + } catch (Exception e) { + return new JSONObject(); + } + } + + /** + * 获得Controller上的实体类型 + * + * @param controller Controller类 + * @return 实体名称 + */ + private String getEntity(Class controller) { + try { + ParameterizedType parameterizedType = (ParameterizedType) controller.getGenericSuperclass(); + Class entityClass = (Class) parameterizedType.getActualTypeArguments()[1]; + return entityClass.getSimpleName(); + } catch (Exception e) { + return ""; + } + } + + private void entity() { + // 扫描所有的实体类 + Set> classes = ClassUtil.scanPackageByAnnotation("", Table.class); + classes.forEach(e -> { + // 获得属性 + Field[] fields = getAllDeclaredFields(e); + List columns = columns(fields); + entityInfo.set(e.getSimpleName(), columns); + + + Table mergedAnnotation = AnnotatedElementUtils.findMergedAnnotation(e, Table.class); + + menuInfo.set(e.getSimpleName(), mergedAnnotation.comment()); + + + }); + } + + /** + * 获取类及其所有父类中声明的字段 + * + * @param clazz 要检查的类 + * @return 包含类及其所有父类中声明的所有字段的数组 + */ + public static Field[] getAllDeclaredFields(Class clazz) { + // 参数校验 + if (clazz == null) { + throw new IllegalArgumentException("Class cannot be null"); + } + + List allFields = new ArrayList<>(); + Class currentClass = clazz; + + // 循环遍历类及其父类 + while (currentClass != null) { + Field[] declaredFields = currentClass.getDeclaredFields(); + allFields.addAll(Arrays.asList(declaredFields)); + currentClass = currentClass.getSuperclass(); + } + + // 将列表转换为数组返回 + return allFields.toArray(new Field[0]); + } + + /** + * 获得所有的列 + * + * @param fields 字段名 + * @return 所有的列 + */ + private List columns(Field[] fields) { + List dictList = new ArrayList<>(); + for (Field field : fields) { + Dict dict = Dict.create(); + + EpsField epsField = AnnotatedElementUtils.findMergedAnnotation(field, EpsField.class); + if (epsField != null) { + dict.set("component", epsField.component()); + } + + ColumnDefine columnInfo = AnnotatedElementUtils.findMergedAnnotation(field, ColumnDefine.class); + if (columnInfo == null) { + continue; + } + dict.set("comment", columnInfo.comment()); + dict.set("length", columnInfo.length()); + dict.set("propertyName", field.getName()); + dict.set("type", matchType(field.getType().getName())); + dict.set("nullable", !columnInfo.notNull()); + dict.set("source", "a." + field.getName()); + dictList.add(dict); + } + return dictList; + } + + /** + * java类型转换成JavaScript对应的类型 + * + * @param type 类型 + * @return JavaScript类型 + */ + private String matchType(String type) { + return switch (type) { + case "java.lang.Boolean" -> "boolean"; + case "java.lang.Long", "java.lang.Integer", "java.lang.Short", "java.lang.Float", + "java.lang.Double" -> "number"; + case "java.util.Date" -> "date"; + default -> "string"; + }; + } +} diff --git a/cool-admin-java/src/main/java/com/cool/core/eps/EpsEvent.java b/cool-admin-java/src/main/java/com/cool/core/eps/EpsEvent.java new file mode 100644 index 0000000..1e40b01 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/eps/EpsEvent.java @@ -0,0 +1,26 @@ +package com.cool.core.eps; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.annotation.Profile; +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Component; + +/** + * 事件监听 + */ +@Slf4j +@Component +@Profile({"local"}) +@RequiredArgsConstructor +public class EpsEvent { + + final private CoolEps coolEps; + + @EventListener + public void onApplicationEvent(ApplicationReadyEvent event) { + coolEps.init(); + log.info("构建eps信息"); + } +} diff --git a/cool-admin-java/src/main/java/com/cool/core/exception/CoolException.java b/cool-admin-java/src/main/java/com/cool/core/exception/CoolException.java new file mode 100644 index 0000000..90498a5 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/exception/CoolException.java @@ -0,0 +1,43 @@ +package com.cool.core.exception; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 自定义异常处理 + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class CoolException extends RuntimeException { + private static final long serialVersionUID = 1L; + + private String msg; + private int code = 500; + private Object data; + + public CoolException(String msg) { + super(msg); + this.msg = msg; + } + + public CoolException(String msg, Throwable e) { + super(msg, e); + this.msg = msg; + } + + public CoolException(String msg, int code) { + super(msg); + this.msg = msg; + this.code = code; + } + + public CoolException(String msg, int code, Throwable e) { + super(msg, e); + this.msg = msg; + this.code = code; + } + + public CoolException(Object data) { + this.data = data; + } +} diff --git a/cool-admin-java/src/main/java/com/cool/core/exception/CoolExceptionHandler.java b/cool-admin-java/src/main/java/com/cool/core/exception/CoolExceptionHandler.java new file mode 100644 index 0000000..01dec57 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/exception/CoolExceptionHandler.java @@ -0,0 +1,71 @@ +package com.cool.core.exception; + +import cn.hutool.core.util.ObjUtil; +import com.cool.core.request.R; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.error.WxErrorException; +import org.springframework.dao.DuplicateKeyException; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.web.HttpRequestMethodNotSupportedException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +/** + * 异常处理器 + */ +@RestControllerAdvice +@Slf4j +public class CoolExceptionHandler { + + @ExceptionHandler(CoolException.class) + public R handleRRException(CoolException e) { + R r = new R(); + if (ObjUtil.isNotEmpty(e.getData())) { + r.setData( e.getData() ); + } else { + r.setCode( e.getCode() ); + r.setMessage( e.getMessage() ); + } + if (ObjUtil.isNotEmpty(e.getCause())) { + log.error(e.getCause().getMessage(), e.getCause()); + } + return r; + } + + @ExceptionHandler(DuplicateKeyException.class) + public R handleDuplicateKeyException(DuplicateKeyException e) { + log.error(e.getMessage(), e); + return R.error("已存在该记录或值不能重复"); + } + + @ExceptionHandler(BadCredentialsException.class) + public R handleBadCredentialsException(BadCredentialsException e) { + log.error(e.getMessage(), e); + return R.error("账户密码不正确"); + } + + @ExceptionHandler(HttpRequestMethodNotSupportedException.class) + public R handleHttpRequestMethodNotSupportedException( + HttpRequestMethodNotSupportedException e) { + log.error(e.getMessage(), e); + return R.error("不支持该请求方式,请区分POST、GET等请求方式是否正确"); + } + + @ExceptionHandler(IllegalArgumentException.class) + public R handleIllegalArgumentException(IllegalArgumentException e) { + log.error(e.getMessage(), e); + return R.error(e.getMessage()); + } + + @ExceptionHandler(Exception.class) + public R handleException(Exception e) { + log.error(e.getMessage(), e); + return R.error(); + } + + @ExceptionHandler(WxErrorException.class) + public R handleException(WxErrorException e) { + log.error(e.getMessage(), e); + return R.error(e.getMessage()); + } +} diff --git a/cool-admin-java/src/main/java/com/cool/core/exception/CoolPreconditions.java b/cool-admin-java/src/main/java/com/cool/core/exception/CoolPreconditions.java new file mode 100644 index 0000000..8779f3a --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/exception/CoolPreconditions.java @@ -0,0 +1,102 @@ +package com.cool.core.exception; + +import cn.hutool.core.util.ObjectUtil; +import com.cool.core.util.I18nUtil; +import java.util.Arrays; +import java.util.Optional; +import lombok.Getter; +import lombok.Setter; + +/** + * 校验处理 + */ +public class CoolPreconditions { + + /** + * 条件如果为真 就抛异常 如 CoolPreconditions.check(StrUtil.isEmptyIfStr(name), 500, + * "名称不能为空"); name 字段如果为 null或空字符串,就抛异常 + */ + public static void check(boolean flag, int code, String message, Object... arguments) { + if (flag) { + throw getCoolException(message, code, arguments); + } + } + + public static void check(boolean flag, String message, Object... arguments) { + if (flag) { + throw getCoolException(message, arguments); + } + } + + public static void alwaysThrow(String message, Object... arguments) { + throw getCoolException(message, arguments); + } + + private static CoolException getCoolException(String message, Object... arguments) { + Optional first = Arrays.stream(arguments).filter(o -> o instanceof Throwable) + .findFirst(); + return new CoolException(formatMessage(message, arguments), (Throwable) first.orElse(null)); + } + + private static CoolException getCoolException(String message, int code, Object... arguments) { + Optional first = Arrays.stream(arguments).filter(o -> o instanceof Throwable) + .findFirst(); + return new CoolException(formatMessage(message, arguments), code, (Throwable) first.orElse(null)); + } + + + /** + * 返回data + */ + public static void returnData(boolean flag, Object data) { + if (flag) { + throw new CoolException(data); + } + } + + public static void returnData(Object data) { + returnData(true, data); + } + + /** + * 对象如果为空 就抛异常 + */ + public static void checkEmpty(Object object, String message, Object... arguments) { + check(ObjectUtil.isEmpty(object), formatMessage(message, arguments)); + } + + public static void checkEmpty(Object object) { + check(ObjectUtil.isEmpty(object), "参数不能为空"); + } + + private static String formatMessage(String messagePattern, Object... arguments) { + messagePattern = I18nUtil.getI18nMsg(messagePattern); + StringBuilder sb = new StringBuilder(); + int argumentIndex = 0; + int placeholderIndex = messagePattern.indexOf("{}"); + while (placeholderIndex != -1) { + sb.append(messagePattern, 0, placeholderIndex); + if (argumentIndex < arguments.length) { + sb.append(arguments[argumentIndex++]); + } else { + sb.append("{}"); // 如果参数不足,保留原样 + } + messagePattern = messagePattern.substring(placeholderIndex + 2); + placeholderIndex = messagePattern.indexOf("{}"); + } + sb.append(messagePattern); // 添加剩余部分 + return sb.toString(); + } + + @Setter + @Getter + public static class ReturnData { + private Integer type; + private String message; + + public ReturnData(Integer type, String message, Object... arguments) { + this.type = type; + this.message = formatMessage(message, arguments); + } + } +} diff --git a/cool-admin-java/src/main/java/com/cool/core/file/FileUploadStrategyFactory.java b/cool-admin-java/src/main/java/com/cool/core/file/FileUploadStrategyFactory.java new file mode 100644 index 0000000..ccbc7f4 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/file/FileUploadStrategyFactory.java @@ -0,0 +1,53 @@ +package com.cool.core.file; + +import static com.cool.core.plugin.consts.PluginConsts.uploadHook; + +import cn.hutool.core.util.ObjUtil; +import com.cool.core.exception.CoolPreconditions; +import com.cool.core.file.strategy.FileUploadStrategy; +import com.cool.core.plugin.service.CoolPluginService; +import com.cool.modules.plugin.entity.PluginInfoEntity; +import jakarta.servlet.http.HttpServletRequest; +import java.io.IOException; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.ApplicationContext; +import org.springframework.stereotype.Component; +import org.springframework.web.multipart.MultipartFile; + +@Slf4j +@Component +@RequiredArgsConstructor +public class FileUploadStrategyFactory { + + final private ApplicationContext applicationContext; + + final private CoolPluginService coolPluginService; + + private FileUploadStrategy getStrategy(PluginInfoEntity pluginInfoEntity) { + if (ObjUtil.isEmpty(pluginInfoEntity)) { + return applicationContext.getBean("localFileUploadStrategy", FileUploadStrategy.class); + } + return applicationContext.getBean("cloudFileUploadStrategy", FileUploadStrategy.class); + } + + public Object upload(MultipartFile[] files, HttpServletRequest request) { + PluginInfoEntity pluginInfoEntity = coolPluginService.getPluginInfoEntityByHook(uploadHook); + try { + return getStrategy(pluginInfoEntity).upload(files, request, pluginInfoEntity); + } catch (IOException e) { + log.error("上传文件失败", e); + CoolPreconditions.alwaysThrow("上传文件失败 {}", e.getMessage()); + } + return null; + } + + public Object getMode() { + PluginInfoEntity pluginInfoEntity = coolPluginService.getPluginInfoEntityByHook(uploadHook); + String key = null; + if (ObjUtil.isNotEmpty(pluginInfoEntity)) { + key = pluginInfoEntity.getKey(); + } + return getStrategy(pluginInfoEntity).getMode(key); + } +} \ No newline at end of file diff --git a/cool-admin-java/src/main/java/com/cool/core/file/UpLoadModeType.java b/cool-admin-java/src/main/java/com/cool/core/file/UpLoadModeType.java new file mode 100644 index 0000000..eb99140 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/file/UpLoadModeType.java @@ -0,0 +1,26 @@ +package com.cool.core.file; + +import com.cool.core.config.FileModeEnum; +import lombok.Data; + +/** + * 上传模式类型 + */ +@Data +public class UpLoadModeType { + + /** + * 模式 + */ + private FileModeEnum mode; + + /** + * 类型 + */ + private String type; + + public UpLoadModeType(FileModeEnum mode) { + this.mode = mode; + this.type = mode.type(); + } +} diff --git a/cool-admin-java/src/main/java/com/cool/core/file/strategy/CloudFileUploadStrategy.java b/cool-admin-java/src/main/java/com/cool/core/file/strategy/CloudFileUploadStrategy.java new file mode 100644 index 0000000..4e449a0 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/file/strategy/CloudFileUploadStrategy.java @@ -0,0 +1,33 @@ +package com.cool.core.file.strategy; + +import com.cool.core.config.FileModeEnum; +import com.cool.core.util.CoolPluginInvokers; +import com.cool.modules.plugin.entity.PluginInfoEntity; +import jakarta.servlet.http.HttpServletRequest; +import java.io.IOException; +import java.util.Map; +import java.util.Objects; +import org.springframework.stereotype.Component; +import org.springframework.web.multipart.MultipartFile; + +@Component("cloudFileUploadStrategy") +public class CloudFileUploadStrategy implements FileUploadStrategy { + + @Override + public Object upload(MultipartFile[] files, HttpServletRequest request, PluginInfoEntity pluginInfoEntity) + throws IOException { + return CoolPluginInvokers.invokePlugin(pluginInfoEntity.getKey()); + } + + @Override + public Map getMode(String key) { + try{ + Object mode = CoolPluginInvokers.invoke(key, "getMode"); + if (Objects.nonNull(mode)) { + return (Map) mode; + } + } catch (Exception ignore){} + return Map.of("mode", FileModeEnum.CLOUD.value(), + "type", FileModeEnum.CLOUD.type()); + } +} diff --git a/cool-admin-java/src/main/java/com/cool/core/file/strategy/FileUploadStrategy.java b/cool-admin-java/src/main/java/com/cool/core/file/strategy/FileUploadStrategy.java new file mode 100644 index 0000000..47bd605 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/file/strategy/FileUploadStrategy.java @@ -0,0 +1,38 @@ +package com.cool.core.file.strategy; + +import com.cool.modules.plugin.entity.PluginInfoEntity; +import jakarta.servlet.http.HttpServletRequest; +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Map; +import org.springframework.web.multipart.MultipartFile; + +public interface FileUploadStrategy { + + /** + * 文件上传 + */ + Object upload(MultipartFile[] files, HttpServletRequest request, PluginInfoEntity pluginInfoEntity) + throws IOException; + + /** + * 文件上传模式 + * + * @return 上传模式 + */ + Map getMode(String key); + + default boolean isAbsolutePath(String pathStr) { + Path path = Paths.get(pathStr); + return path.isAbsolute(); + } + + default String getExtensionName(String fileName) { + if (fileName.contains(".")) { + String[] names = fileName.split("[.]"); + return "." + names[names.length - 1]; + } + return ""; + } +} diff --git a/cool-admin-java/src/main/java/com/cool/core/file/strategy/LocalFileUploadStrategy.java b/cool-admin-java/src/main/java/com/cool/core/file/strategy/LocalFileUploadStrategy.java new file mode 100644 index 0000000..0be9d8e --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/file/strategy/LocalFileUploadStrategy.java @@ -0,0 +1,74 @@ +package com.cool.core.file.strategy; + +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.util.StrUtil; +import com.cool.core.config.FileModeEnum; +import com.cool.core.config.LocalFileProperties; +import com.cool.core.exception.CoolException; +import com.cool.core.exception.CoolPreconditions; +import com.cool.modules.plugin.entity.PluginInfoEntity; +import jakarta.servlet.http.HttpServletRequest; +import java.io.File; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; +import org.springframework.web.multipart.MultipartFile; + +@Component("localFileUploadStrategy") +@RequiredArgsConstructor +public class LocalFileUploadStrategy implements FileUploadStrategy { + + final private LocalFileProperties localFileProperties; + + /** + * 上传文件 + * + * @param files 上传的文件 + * @return 文件路径 + */ + @Override + public Object upload(MultipartFile[] files, HttpServletRequest request, + PluginInfoEntity pluginInfoEntity) { + CoolPreconditions.check(StrUtil.isEmpty(localFileProperties.getBaseUrl()), + "filePath 或 baseUrl 未配置"); + try { + List fileUrls = new ArrayList<>(); + String baseUrl = localFileProperties.getBaseUrl(); + String date = DateUtil.format(new Date(), + DatePattern.PURE_DATE_PATTERN); + String absoluteUploadFolder = localFileProperties.getAbsoluteUploadFolder(); + String fullPath = absoluteUploadFolder + "/" + date; + FileUtil.mkdir(fullPath); + for (MultipartFile file : files) { + // 保存文件 + String fileName = StrUtil.uuid().replaceAll("-", "") + getExtensionName( + Objects.requireNonNull(file.getOriginalFilename())); + file.transferTo(new File(fullPath + + "/" + fileName)); + fileUrls.add(baseUrl + "/" + date + "/" + fileName); + } + if (fileUrls.size() == 1) { + return fileUrls.get(0); + } + return fileUrls; + } catch (Exception e) { + throw new CoolException("文件上传失败", e); + } + } + + /** + * 文件上传模式 + * + * @return 上传模式 + */ + public Map getMode(String key) { + return Map.of("mode", FileModeEnum.LOCAL.value(), + "type", FileModeEnum.LOCAL.type()); + } +} diff --git a/cool-admin-java/src/main/java/com/cool/core/i18n/I18nGenerator.java b/cool-admin-java/src/main/java/com/cool/core/i18n/I18nGenerator.java new file mode 100644 index 0000000..40741a5 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/i18n/I18nGenerator.java @@ -0,0 +1,219 @@ +package com.cool.core.i18n; + +import static com.cool.core.util.I18nUtil.*; + +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.util.ObjUtil; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import com.cool.core.lock.CoolLock; +import com.cool.core.util.CoolPluginInvokers; +import com.cool.core.util.I18nUtil; +import com.cool.core.util.PathUtils; +import com.cool.modules.base.entity.sys.BaseSysMenuEntity; +import com.cool.modules.base.service.sys.BaseSysMenuService; +import com.cool.modules.dict.entity.DictInfoEntity; +import com.cool.modules.dict.entity.DictTypeEntity; +import com.cool.modules.dict.service.DictInfoService; +import com.cool.modules.dict.service.DictTypeService; +import com.mybatisflex.core.query.QueryWrapper; +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.time.Duration; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.core.io.Resource; +import org.springframework.core.io.support.PathMatchingResourcePatternResolver; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Component; + +@Slf4j +@Component +@RequiredArgsConstructor +public class I18nGenerator { + private final BaseSysMenuService baseSysMenuService; + private final DictTypeService dictTypeService; + private final DictInfoService dictInfoService; + private final CoolLock coolLock; + private final I18nUtil i18nUtil; + + private List languages; + private static final Duration DURATION = Duration.ofSeconds(30); + public void run(Map map) { + log.info("国际化 翻译..."); + languages = (List) map.getOrDefault("languages", List.of("zh-cn", "zh-tw", "en")); + path = (String) map.getOrDefault("path", "assets/i18n"); + init(); + log.info("✅国际化 翻译 成功!!!"); + enable = true; + } + + public void init() { + // 四个任务并发执行 + CompletableFuture futureMsg = CompletableFuture.runAsync(this::genBaseMsg); + CompletableFuture futureMenu = CompletableFuture.runAsync(this::genBaseMenu); + CompletableFuture futureDictInfo = CompletableFuture.runAsync(this::genBaseDictInfo); + CompletableFuture futureDictType = CompletableFuture.runAsync(this::genBaseDictType); + + // 等待全部执行完成 + CompletableFuture.allOf(futureMsg, futureMenu, futureDictInfo, futureDictType).join(); + } + + private void genBaseMsg() { + try { + Map msgMap = new HashMap<>(); + // 从idea本地启动时,从项目目录中读取 + Files.walk(Paths.get(System.getProperty("user.dir"))) + .filter(Files::isRegularFile) + .filter(path -> path.toString().endsWith(".java")) + .filter(path -> !path.toString().contains("/target/") && !path.toString().contains("/.git/")) + .forEach(path -> msgMap.putAll(processFile(path))); + if (ObjUtil.isNotEmpty(msgMap)) { + // 系统异常信息,输出到resources/i18n 文件夹下,只有本地运行会生成 + File msgfile = FileUtil.file(PathUtils.getUserDir(), + "src", "main", "resources", "cool", "i18n", "msg", "template.json"); + // 确保父目录存在 + FileUtil.mkParentDirs(msgfile); + // 写入内容 + FileUtil.writeUtf8String(JSONUtil.toJsonStr(msgMap), msgfile); + } else { + try { + // jar启动时,从jar包中读取 + PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); + Resource resource = resolver.getResource("classpath:cool/i18n/msg/template.json"); + String content = FileUtil.readUtf8String(resource.getFile()); + msgMap.putAll(JSONUtil.toBean(content, Map.class)); + } catch (Exception e) { + log.error("获取系统异常信息失败", e); + } + } + extracted(MSG_PREFIX, msgMap); + } catch (Exception e) { + log.error("国际化系统异常信息失败", e); + } + } + + /** + * 生成菜单信息国际化 + */ + @Async + public void asyncGenBaseMenu() { + if (coolLock.tryLock(MENU_PREFIX, DURATION)) { + genBaseMenu(); + coolLock.unlock(MENU_PREFIX); + } + } + private void genBaseMenu() { + try { + Map menuMap = baseSysMenuService.list(QueryWrapper.create().select(BaseSysMenuEntity::getName)) + .stream() + .collect(Collectors.toMap( + BaseSysMenuEntity::getName, + BaseSysMenuEntity::getName, + (oldValue, newValue) -> oldValue + )); + extracted(MENU_PREFIX, menuMap); + } catch (Exception e) { + log.error("国际化菜单信息失败", e); + } + } + @Async + public void asyncGenBaseDictType() { + if (coolLock.tryLock(DICT_TYPE_PREFIX, DURATION)) { + genBaseDictType(); + coolLock.unlock(DICT_TYPE_PREFIX); + } + } + private void genBaseDictType() { + try { + Map dataMap = dictTypeService.list(QueryWrapper.create().select(DictTypeEntity::getName)) + .stream() + .collect(Collectors.toMap( + DictTypeEntity::getName, + DictTypeEntity::getName, + (oldValue, newValue) -> oldValue + )); + extracted(DICT_TYPE_PREFIX, dataMap); + } catch (Exception e) { + log.error("国际化字段类型信息失败", e); + } + } + @Async + public void asyncGenBaseDictInfo() { + if (coolLock.tryLock(DICT_INFO_PREFIX, DURATION)) { + genBaseDictInfo(); + coolLock.unlock(DICT_INFO_PREFIX); + } + } + private void genBaseDictInfo() { + try { + Map dataMap = dictInfoService.list(QueryWrapper.create().select(DictInfoEntity::getName)) + .stream() + .collect(Collectors.toMap( + DictInfoEntity::getName, + DictInfoEntity::getName, + (oldValue, newValue) -> oldValue + )); + extracted(DICT_INFO_PREFIX, dataMap); + } catch (Exception e) { + log.error("国际化字段类型信息失败", e); + } + } + + private void extracted(String prefix, Map dataMap) { + languages.forEach(language -> { + String key = prefix + language; + if (!i18nUtil.exist(key)) { + JSONObject jsonObject = invokeTranslate(dataMap, language); + if (ObjUtil.isNotNull(jsonObject)) { + i18nUtil.update(key, jsonObject); + } + } + }); + } + + private JSONObject invokeTranslate(Map map, String language) { + return (JSONObject) CoolPluginInvokers.invoke("i18n", "invokeTranslate", map, language); + } + + // 匹配 CoolPreconditions 抛异常语句中的中文字符串 + private static final Pattern EXCEPTION_PATTERN = Pattern.compile( + "CoolPreconditions\\.(\\w+)\\s*\\([^;]*?\"([^\"]*[\u4e00-\u9fa5]+[^\"]*)\"", Pattern.MULTILINE + ); + + private static Map processFile(Path path) { + Map map = new HashMap<>(); + try { + String content = Files.readString(path, StandardCharsets.UTF_8); + // 去掉注释 + content = removeComments(content); + + // 仅查找方法体内的 CoolPreconditions 调用 + Matcher matcher = EXCEPTION_PATTERN.matcher(content); + while (matcher.find()) { + String chineseText = matcher.group(2).trim(); + map.put(chineseText, chineseText); + } + } catch (IOException e) { + e.printStackTrace(); + } + return map; + } + + // 移除注释(单行与多行) + private static String removeComments(String code) { + String noMultiLine = code.replaceAll("/\\*.*?\\*/", ""); // 多行注释 + return noMultiLine.replaceAll("//.*", ""); // 单行注释 + } +} \ No newline at end of file diff --git a/cool-admin-java/src/main/java/com/cool/core/init/CoolPluginInit.java b/cool-admin-java/src/main/java/com/cool/core/init/CoolPluginInit.java new file mode 100644 index 0000000..846be54 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/init/CoolPluginInit.java @@ -0,0 +1,24 @@ +package com.cool.core.init; + +import com.cool.core.plugin.service.CoolPluginService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Component; + +/** + * 历史安装过的插件执行初始化 + **/ +@Slf4j +@Component +@RequiredArgsConstructor +public class CoolPluginInit { + + final private CoolPluginService coolPluginService; + + @EventListener(ApplicationReadyEvent.class) + public void run() { + coolPluginService.init(); + } +} diff --git a/cool-admin-java/src/main/java/com/cool/core/init/DBFromJsonInit.java b/cool-admin-java/src/main/java/com/cool/core/init/DBFromJsonInit.java new file mode 100644 index 0000000..9f01048 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/init/DBFromJsonInit.java @@ -0,0 +1,252 @@ +package com.cool.core.init; + + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.io.IoUtil; +import cn.hutool.core.util.ObjUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONArray; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import com.cool.core.base.service.MapperProviderService; +import com.cool.core.mybatis.pg.PostgresSequenceSyncService; +import com.cool.core.util.DatabaseDialectUtils; +import com.cool.core.util.EntityUtils; +import com.cool.modules.base.entity.sys.BaseSysConfEntity; +import com.cool.modules.base.entity.sys.BaseSysMenuEntity; +import com.cool.modules.base.service.sys.BaseSysConfService; +import com.cool.modules.base.service.sys.BaseSysMenuService; +import com.mybatisflex.core.BaseMapper; +import com.mybatisflex.core.query.QueryWrapper; +import java.io.File; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.nio.charset.StandardCharsets; +import java.util.Map; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.context.event.EventListener; +import org.springframework.core.io.Resource; +import org.springframework.core.io.support.PathMatchingResourcePatternResolver; +import org.springframework.stereotype.Component; + +/** + * 数据库初始数据初始化 在 classpath:cool/data/db 目录下创建.json文件 并定义表数据, 由该类统一执行初始化 + **/ +@Slf4j +@Component +@RequiredArgsConstructor +public class DBFromJsonInit { + + final private BaseSysConfService baseSysConfService; + + final private BaseSysMenuService baseSysMenuService; + + final private MapperProviderService mapperProviderService; + + final private ApplicationEventPublisher eventPublisher; + + final private PostgresSequenceSyncService postgresSequenceSyncService; + + @Value("${cool.initData}") + private boolean initData; + + @EventListener(ApplicationReadyEvent.class) + public void run() { + if (!initData) { + return; + } + // 初始化自定义的数据 + boolean initFlag = extractedDb(); + // 初始化菜单数据 + initFlag = extractedMenu() || initFlag; + // 发送数据库初始化完成事件 + eventPublisher.publishEvent(new DbInitCompleteEvent(this)); + if (initFlag) { + // 如果是postgresql,同步序列 + syncIdentitySequences(); + } + log.info("数据初始化完成!"); + } + + private void syncIdentitySequences() { + if (DatabaseDialectUtils.isPostgresql()) { + postgresSequenceSyncService.syncIdentitySequences(); + } + } + + @Getter + public static class DbInitCompleteEvent { + private final Object source; + + public DbInitCompleteEvent(Object source) { + this.source = source; + } + + } + + /** + * 解析插入业务数据 + */ + private boolean extractedDb() { + try { + // 加载 JSON 文件 + PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); + Resource[] resources = resolver.getResources("classpath:cool/data/db/*.json"); + // 遍历所有.json文件 + return analysisResources(resources); + } catch (Exception e) { + log.error("Failed to initialize data", e); + } + return false; + } + + private boolean analysisResources(Resource[] resources) + throws IOException, NoSuchMethodException, IllegalAccessException, InvocationTargetException { + String prefix = "db_"; + boolean isInit = false; + for (Resource resource : resources) { + File resourceFile = new File(resource.getURL().getFile()); + String fileName = prefix + resourceFile.getName(); + String value = baseSysConfService.getValue(fileName); + if (StrUtil.isNotEmpty(value)) { + log.info("{} 业务数据已初始化过...", fileName); + continue; + } + String jsonStr = IoUtil.read(resource.getInputStream(), StandardCharsets.UTF_8); + JSONObject jsonObject = JSONUtil.parseObj(jsonStr); + // 遍历 JSON 文件中的数据 + analysisJson(jsonObject); + + BaseSysConfEntity baseSysUserEntity = new BaseSysConfEntity(); + baseSysUserEntity.setCKey(fileName); + baseSysUserEntity.setCValue("success"); + // 当前文件已加载 + baseSysConfService.add(baseSysUserEntity); + isInit = true; + log.info("{} 业务数据初始化成功...", fileName); + } + return isInit; + } + + private void analysisJson(JSONObject jsonObject) + throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { + Map> tableMap = EntityUtils.findTableMap(); + for (String tableName : jsonObject.keySet()) { + JSONArray records = jsonObject.getJSONArray(tableName); + // 根据表名生成实体类名和 Mapper 接口名 + Class entityClass = tableMap.get(tableName); + BaseMapper baseMapper = mapperProviderService.getMapperByEntityClass(entityClass); + // 插入 + insertList(baseMapper, entityClass, records); + } + } + + /** + * 插入列表数据 + */ + private void insertList(BaseMapper baseMapper, Class entityClass, + JSONArray records) + throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { + // 插入数据 + for (int i = 0; i < records.size(); i++) { + JSONObject record = records.getJSONObject(i); + Object entity = JSONUtil.toBean(record, entityClass); + Method getIdMethod = entityClass.getMethod("getId"); + Object id = getIdMethod.invoke(entity); + if (ObjUtil.isNotEmpty(id) && ObjUtil.isNotEmpty( + baseMapper.selectOneById((Long) id))) { + // 数据库已经有值了 + continue; + } + if (ObjUtil.isNotEmpty(id)) { + // 带id插入 + baseMapper.insertSelectiveWithPk(entity); + } else { + baseMapper.insert(entity); + } + } + } + + /** + * 解析插入菜单数据 + */ + public boolean extractedMenu() { + boolean initFlag = false; + try { + String prefix = "menu_"; + PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); + Resource[] resources = resolver.getResources("classpath:cool/data/menu/*.json"); + // 遍历所有.json文件 + for (Resource resource : resources) { + File resourceFile = new File(resource.getURL().getFile()); + String fileName = prefix + resourceFile.getName(); + String value = baseSysConfService.getValue(fileName); + if (StrUtil.isNotEmpty(value)) { + log.info("{} 菜单数据已初始化过...", fileName); + continue; + } + analysisResources(resource, fileName); + initFlag = true; + } + } catch (Exception e) { + log.error("Failed to initialize data", e); + } + return initFlag; + } + + private void analysisResources(Resource resource, String fileName) throws IOException { + String jsonStr = IoUtil.read(resource.getInputStream(), StandardCharsets.UTF_8); + + // 使用 解析 JSON 字符串 + JSONArray jsonArray = JSONUtil.parseArray(jsonStr); + + // 遍历 JSON 数组 + for (Object obj : jsonArray) { + JSONObject jsonObj = (JSONObject) obj; + // 将 JSON 对象转换为 Menu 对象 + parseMenu(jsonObj, null); + } + BaseSysConfEntity baseSysUserEntity = new BaseSysConfEntity(); + baseSysUserEntity.setCKey(fileName); + baseSysUserEntity.setCValue("success"); + // 当前文件已加载 + baseSysConfService.add(baseSysUserEntity); + log.info("{} 菜单数据初始化成功...", fileName); + } + + // 递归解析 JSON 对象为 Menu 对象 + private void parseMenu(JSONObject jsonObj, BaseSysMenuEntity parentMenuEntity) { + BaseSysMenuEntity menuEntity = BeanUtil.copyProperties(jsonObj, BaseSysMenuEntity.class); + if (ObjUtil.isNotEmpty(parentMenuEntity)) { + menuEntity.setParentName(parentMenuEntity.getName()); + menuEntity.setParentId(parentMenuEntity.getId()); + } + QueryWrapper queryWrapper = QueryWrapper.create() + .eq(BaseSysMenuEntity::getName, menuEntity.getName()); + if (ObjUtil.isNull(menuEntity.getParentId())) { + queryWrapper.isNull(BaseSysMenuEntity::getParentId); + } else { + queryWrapper.eq(BaseSysMenuEntity::getParentId, menuEntity.getParentId()); + } + BaseSysMenuEntity dbBaseSysMenuEntity = baseSysMenuService.getOne(queryWrapper); + if (ObjUtil.isNull(dbBaseSysMenuEntity)) { + baseSysMenuService.add(menuEntity); + } else { + menuEntity = dbBaseSysMenuEntity; + } + // 递归处理子菜单 + JSONArray childMenus = jsonObj.getJSONArray("childMenus"); + if (childMenus != null) { + for (Object obj : childMenus) { + JSONObject childObj = (JSONObject) obj; + parseMenu(childObj, menuEntity); + } + } + } +} diff --git a/cool-admin-java/src/main/java/com/cool/core/init/IDGenInit.java b/cool-admin-java/src/main/java/com/cool/core/init/IDGenInit.java new file mode 100644 index 0000000..446e59a --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/init/IDGenInit.java @@ -0,0 +1,24 @@ +package com.cool.core.init; + +import com.cool.core.leaf.IDGenService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Component; + +/** + * 唯一ID 组件初始化 + **/ +@Slf4j +@Component +@RequiredArgsConstructor +public class IDGenInit { + + final private IDGenService idGenService; + + @EventListener(ApplicationReadyEvent.class) + public void run() { + idGenService.init(); + } +} diff --git a/cool-admin-java/src/main/java/com/cool/core/leaf/IDGenService.java b/cool-admin-java/src/main/java/com/cool/core/leaf/IDGenService.java new file mode 100644 index 0000000..b004ce6 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/leaf/IDGenService.java @@ -0,0 +1,6 @@ +package com.cool.core.leaf; + +public interface IDGenService { + long next(String key); + void init(); +} diff --git a/cool-admin-java/src/main/java/com/cool/core/leaf/common/CheckVO.java b/cool-admin-java/src/main/java/com/cool/core/leaf/common/CheckVO.java new file mode 100644 index 0000000..0d207a7 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/leaf/common/CheckVO.java @@ -0,0 +1,27 @@ +package com.cool.core.leaf.common; + +public class CheckVO { + private long timestamp; + private int workID; + + public CheckVO(long timestamp, int workID) { + this.timestamp = timestamp; + this.workID = workID; + } + + public long getTimestamp() { + return timestamp; + } + + public void setTimestamp(long timestamp) { + this.timestamp = timestamp; + } + + public int getWorkID() { + return workID; + } + + public void setWorkID(int workID) { + this.workID = workID; + } +} diff --git a/cool-admin-java/src/main/java/com/cool/core/leaf/common/Result.java b/cool-admin-java/src/main/java/com/cool/core/leaf/common/Result.java new file mode 100644 index 0000000..d85b1c6 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/leaf/common/Result.java @@ -0,0 +1,39 @@ +package com.cool.core.leaf.common; + +public class Result { + private long id; + private Status status; + + public Result() { + + } + public Result(long id, Status status) { + this.id = id; + this.status = status; + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public Status getStatus() { + return status; + } + + public void setStatus(Status status) { + this.status = status; + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder("Result{"); + sb.append("id=").append(id); + sb.append(", status=").append(status); + sb.append('}'); + return sb.toString(); + } +} diff --git a/cool-admin-java/src/main/java/com/cool/core/leaf/common/Status.java b/cool-admin-java/src/main/java/com/cool/core/leaf/common/Status.java new file mode 100644 index 0000000..ec615e9 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/leaf/common/Status.java @@ -0,0 +1,6 @@ +package com.cool.core.leaf.common; + +public enum Status { + SUCCESS, + EXCEPTION +} diff --git a/cool-admin-java/src/main/java/com/cool/core/leaf/package-info.java b/cool-admin-java/src/main/java/com/cool/core/leaf/package-info.java new file mode 100644 index 0000000..8278bae --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/leaf/package-info.java @@ -0,0 +1,5 @@ +/** + * 全局唯一id生成 + * 来源美团:https://github.com/Meituan-Dianping/Leaf + */ +package com.cool.core.leaf; diff --git a/cool-admin-java/src/main/java/com/cool/core/leaf/segment/SegmentIDGenImpl.java b/cool-admin-java/src/main/java/com/cool/core/leaf/segment/SegmentIDGenImpl.java new file mode 100644 index 0000000..0c5825b --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/leaf/segment/SegmentIDGenImpl.java @@ -0,0 +1,310 @@ +package com.cool.core.leaf.segment; + +import static com.cool.core.leaf.segment.entity.table.LeafAllocEntityTableDef.LEAF_ALLOC_ENTITY; + +import com.cool.core.exception.CoolPreconditions; +import com.cool.core.leaf.IDGenService; +import com.cool.core.leaf.common.Result; +import com.cool.core.leaf.common.Status; +import com.cool.core.leaf.segment.entity.LeafAllocEntity; +import com.cool.core.leaf.segment.mapper.LeafAllocMapper; +import com.cool.core.leaf.segment.model.Segment; +import com.cool.core.leaf.segment.model.SegmentBuffer; +import com.mybatisflex.core.query.QueryWrapper; +import com.mybatisflex.core.update.UpdateChain; +import java.util.*; +import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicLong; +import lombok.RequiredArgsConstructor; +import org.perf4j.StopWatch; +import org.perf4j.slf4j.Slf4JStopWatch; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.DisposableBean; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class SegmentIDGenImpl implements IDGenService, DisposableBean { + + private static final Logger logger = LoggerFactory.getLogger(SegmentIDGenImpl.class); + + @Value("${leaf.segment.enable:false}") + private boolean enable; + + /** + * IDCache未初始化成功时的异常码 + */ + private static final long EXCEPTION_ID_IDCACHE_INIT_FALSE = -1; + /** + * key不存在时的异常码 + */ + private static final long EXCEPTION_ID_KEY_NOT_EXISTS = -2; + /** + * SegmentBuffer中的两个Segment均未从DB中装载时的异常码 + */ + private static final long EXCEPTION_ID_TWO_SEGMENTS_ARE_NULL = -3; + /** + * 最大步长不超过100,0000 + */ + private static final int MAX_STEP = 1000000; + /** + * 一个Segment维持时间为15分钟 + */ + private static final long SEGMENT_DURATION = 15 * 60 * 1000L; + private final ExecutorService executorService = new ThreadPoolExecutor(5, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<>(), new UpdateThreadFactory()); + private final ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(r -> { + Thread t = new Thread(r); + t.setName("check-idCache-thread"); + t.setDaemon(true); + return t; + }); + private volatile boolean initOK = false; + private final Map cache = new ConcurrentHashMap<>(); + private final LeafAllocMapper leafAllocMapper; + + public static class UpdateThreadFactory implements ThreadFactory { + + private static int threadInitNumber = 0; + + private static synchronized int nextThreadNum() { + return threadInitNumber++; + } + + @Override + public Thread newThread(Runnable r) { + return new Thread(r, "Thread-Segment-Update-" + nextThreadNum()); + } + } + + @Override + public long next(String key) { + Result result = get(key); + CoolPreconditions.check(result.getId() < 0, "获取失败,code值: {}", result.getId()); + return result.getId(); + } + + @Override + public void init() { + if (enable) { + // 确保加载到kv后才初始化成功 + updateCacheFromDb(); + initOK = true; + updateCacheFromDbAtEveryMinute(); + logger.info("唯一ID组件初始化成功 ..."); + } + } + + private void updateCacheFromDbAtEveryMinute() { + scheduledExecutorService.scheduleWithFixedDelay(this::updateCacheFromDb, 60, 60, TimeUnit.SECONDS); + } + + private void updateCacheFromDb() { + logger.info("update cache from db"); + StopWatch sw = new Slf4JStopWatch(); + try { + List dbTags = leafAllocMapper.selectListByQuery(QueryWrapper.create().select( + LeafAllocEntity::getKey)).stream().map(LeafAllocEntity::getKey).toList(); + if (dbTags.isEmpty()) { + return; + } + List cacheTags = new ArrayList(cache.keySet()); + Set insertTagsSet = new HashSet<>(dbTags); + Set removeTagsSet = new HashSet<>(cacheTags); + //db中新加的tags灌进cache + for (String tmp : cacheTags) { + insertTagsSet.remove(tmp); + } + for (String tag : insertTagsSet) { + SegmentBuffer buffer = new SegmentBuffer(); + buffer.setKey(tag); + Segment segment = buffer.getCurrent(); + segment.setValue(new AtomicLong(0)); + segment.setMax(0); + segment.setStep(0); + cache.put(tag, buffer); + logger.info("Add tag {} from db to IdCache, SegmentBuffer {}", tag, buffer); + } + //cache中已失效的tags从cache删除 + for (String tmp : dbTags) { + removeTagsSet.remove(tmp); + } + for (String tag : removeTagsSet) { + cache.remove(tag); + logger.info("Remove tag {} from IdCache", tag); + } + } catch (Exception e) { + logger.warn("update cache from db exception", e); + } finally { + sw.stop("updateCacheFromDb"); + } + } + + private Result get(final String key) { + if (!initOK) { + return new Result(EXCEPTION_ID_IDCACHE_INIT_FALSE, Status.EXCEPTION); + } + CoolPreconditions.check(!initOK, "IDCache未初始化成功"); + if (cache.containsKey(key)) { + SegmentBuffer buffer = cache.get(key); + if (!buffer.isInitOk()) { + synchronized (buffer) { + if (!buffer.isInitOk()) { + try { + updateSegmentFromDb(key, buffer.getCurrent()); + logger.info("Init buffer. Update leafkey {} {} from db", key, buffer.getCurrent()); + buffer.setInitOk(true); + } catch (Exception e) { + logger.warn("Init buffer {} exception", buffer.getCurrent(), e); + } + } + } + } + return getIdFromSegmentBuffer(cache.get(key)); + } + return new Result(EXCEPTION_ID_KEY_NOT_EXISTS, Status.EXCEPTION); + } + + public void updateSegmentFromDb(String key, Segment segment) { + StopWatch sw = new Slf4JStopWatch(); + SegmentBuffer buffer = segment.getBuffer(); + LeafAllocEntity leafAllocEntity; + if (!buffer.isInitOk()) { + leafAllocEntity = updateMaxIdAndGetLeafAlloc(key); + buffer.setStep(leafAllocEntity.getStep()); + buffer.setMinStep(leafAllocEntity.getStep());//leafAlloc中的step为DB中的step + } else if (buffer.getUpdateTimestamp() == 0) { + leafAllocEntity = updateMaxIdAndGetLeafAlloc(key); + buffer.setUpdateTimestamp(System.currentTimeMillis()); + buffer.setStep(leafAllocEntity.getStep()); + buffer.setMinStep(leafAllocEntity.getStep());//leafAlloc中的step为DB中的step + } else { + long duration = System.currentTimeMillis() - buffer.getUpdateTimestamp(); + int nextStep = buffer.getStep(); + if (duration < SEGMENT_DURATION) { + if (nextStep * 2 > MAX_STEP) { + //do nothing + } else { + nextStep = nextStep * 2; + } + } else if (duration < SEGMENT_DURATION * 2) { + //do nothing with nextStep + } else { + nextStep = nextStep / 2 >= buffer.getMinStep() ? nextStep / 2 : nextStep; + } + logger.info("leafKey[{}], step[{}], duration[{}mins], nextStep[{}]", key, buffer.getStep(), String.format("%.2f",((double)duration / (1000 * 60))), nextStep); + LeafAllocEntity temp = new LeafAllocEntity(); + temp.setKey(key); + temp.setStep(nextStep); + leafAllocEntity = updateMaxIdByCustomStepAndGetLeafAlloc(temp); + buffer.setUpdateTimestamp(System.currentTimeMillis()); + buffer.setStep(nextStep); + buffer.setMinStep(leafAllocEntity.getStep());//leafAlloc的step为DB中的step + } + // must set value before set max + long value = leafAllocEntity.getMaxId() - buffer.getStep(); + segment.getValue().set(value); + segment.setMax(leafAllocEntity.getMaxId()); + segment.setStep(buffer.getStep()); + sw.stop("updateSegmentFromDb", key + " " + segment); + } + + private LeafAllocEntity updateMaxIdByCustomStepAndGetLeafAlloc(LeafAllocEntity temp) { + UpdateChain.of(LeafAllocEntity.class) + .setRaw(LeafAllocEntity::getMaxId, LEAF_ALLOC_ENTITY.MAX_ID.getName() + " + " + temp.getStep()) + .where(LeafAllocEntity::getKey).eq(temp.getKey()) + .update(); + return leafAllocMapper.selectOneByQuery(QueryWrapper.create().select( + LEAF_ALLOC_ENTITY.KEY, LEAF_ALLOC_ENTITY.MAX_ID, LEAF_ALLOC_ENTITY.STEP).eq(LeafAllocEntity::getKey, temp.getKey())); + } + + private LeafAllocEntity updateMaxIdAndGetLeafAlloc(String key) { + UpdateChain.of(LeafAllocEntity.class) + .setRaw(LeafAllocEntity::getMaxId, LEAF_ALLOC_ENTITY.MAX_ID.getName() + " + " + LEAF_ALLOC_ENTITY.STEP.getName()) + .where(LeafAllocEntity::getKey).eq(key) + .update(); + return leafAllocMapper.selectOneByQuery(QueryWrapper.create().select( + LEAF_ALLOC_ENTITY.KEY, LEAF_ALLOC_ENTITY.MAX_ID, LEAF_ALLOC_ENTITY.STEP).eq(LeafAllocEntity::getKey, key)); + } + + public Result getIdFromSegmentBuffer(final SegmentBuffer buffer) { + while (true) { + buffer.rLock().lock(); + try { + final Segment segment = buffer.getCurrent(); + if (!buffer.isNextReady() && (segment.getIdle() < 0.9 * segment.getStep()) && buffer.getThreadRunning().compareAndSet(false, true)) { + executorService.execute(() -> { + Segment next = buffer.getSegments()[buffer.nextPos()]; + boolean updateOk = false; + try { + updateSegmentFromDb(buffer.getKey(), next); + updateOk = true; + logger.info("update segment {} from db {}", buffer.getKey(), next); + } catch (Exception e) { + logger.warn(buffer.getKey() + " updateSegmentFromDb exception", e); + } finally { + if (updateOk) { + buffer.wLock().lock(); + buffer.setNextReady(true); + buffer.getThreadRunning().set(false); + buffer.wLock().unlock(); + } else { + buffer.getThreadRunning().set(false); + } + } + }); + } + long value = segment.getValue().getAndIncrement(); + if (value < segment.getMax()) { + return new Result(value, Status.SUCCESS); + } + } finally { + buffer.rLock().unlock(); + } + waitAndSleep(buffer); + buffer.wLock().lock(); + try { + final Segment segment = buffer.getCurrent(); + long value = segment.getValue().getAndIncrement(); + if (value < segment.getMax()) { + return new Result(value, Status.SUCCESS); + } + if (buffer.isNextReady()) { + buffer.switchPos(); + buffer.setNextReady(false); + } else { + logger.error("Both two segments in {} are not ready!", buffer); + return new Result(EXCEPTION_ID_TWO_SEGMENTS_ARE_NULL, Status.EXCEPTION); + } + } finally { + buffer.wLock().unlock(); + } + } + } + + private void waitAndSleep(SegmentBuffer buffer) { + int roll = 0; + while (buffer.getThreadRunning().get()) { + roll += 1; + if(roll > 10000) { + try { + TimeUnit.MILLISECONDS.sleep(10); + break; + } catch (InterruptedException e) { + logger.warn("Thread {} Interrupted",Thread.currentThread().getName()); + break; + } + } + } + } + + @Override + public void destroy() throws Exception { + executorService.shutdown(); + executorService.awaitTermination(10, TimeUnit.SECONDS); + + scheduledExecutorService.shutdown(); + scheduledExecutorService.awaitTermination(10, TimeUnit.SECONDS); + } +} diff --git a/cool-admin-java/src/main/java/com/cool/core/leaf/segment/entity/LeafAllocEntity.java b/cool-admin-java/src/main/java/com/cool/core/leaf/segment/entity/LeafAllocEntity.java new file mode 100644 index 0000000..a78caba --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/leaf/segment/entity/LeafAllocEntity.java @@ -0,0 +1,27 @@ +package com.cool.core.leaf.segment.entity; + +import com.cool.core.base.BaseEntity; +import com.mybatisflex.annotation.Table; +import com.tangzc.mybatisflex.autotable.annotation.ColumnDefine; +import com.tangzc.mybatisflex.autotable.annotation.UniIndex; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@Table(value = "leaf_alloc", comment = "唯一id分配") +public class LeafAllocEntity extends BaseEntity { + + @UniIndex(name = "uk_key") + @ColumnDefine(comment = "业务key ,比如orderId", length = 20, notNull = true) + private String key; + + @ColumnDefine(comment = "当前最大id", defaultValue = "1", notNull = true) + private Long maxId; + + @ColumnDefine(comment = "步长", defaultValue = "500", notNull = true) + private Integer step; + + @ColumnDefine(comment = "描述") + private String description; +} diff --git a/cool-admin-java/src/main/java/com/cool/core/leaf/segment/mapper/LeafAllocMapper.java b/cool-admin-java/src/main/java/com/cool/core/leaf/segment/mapper/LeafAllocMapper.java new file mode 100644 index 0000000..1f492b6 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/leaf/segment/mapper/LeafAllocMapper.java @@ -0,0 +1,7 @@ +package com.cool.core.leaf.segment.mapper; + +import com.cool.core.leaf.segment.entity.LeafAllocEntity; +import com.mybatisflex.core.BaseMapper; + +public interface LeafAllocMapper extends BaseMapper { +} diff --git a/cool-admin-java/src/main/java/com/cool/core/leaf/segment/model/Segment.java b/cool-admin-java/src/main/java/com/cool/core/leaf/segment/model/Segment.java new file mode 100644 index 0000000..6908a36 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/leaf/segment/model/Segment.java @@ -0,0 +1,59 @@ +package com.cool.core.leaf.segment.model; + +import java.util.concurrent.atomic.AtomicLong; + +public class Segment { + private AtomicLong value = new AtomicLong(0); + private volatile long max; + private volatile int step; + private SegmentBuffer buffer; + + public Segment(SegmentBuffer buffer) { + this.buffer = buffer; + } + + public AtomicLong getValue() { + return value; + } + + public void setValue(AtomicLong value) { + this.value = value; + } + + public long getMax() { + return max; + } + + public void setMax(long max) { + this.max = max; + } + + public int getStep() { + return step; + } + + public void setStep(int step) { + this.step = step; + } + + public SegmentBuffer getBuffer() { + return buffer; + } + + public long getIdle() { + return this.getMax() - getValue().get(); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder("Segment("); + sb.append("value:"); + sb.append(value); + sb.append(",max:"); + sb.append(max); + sb.append(",step:"); + sb.append(step); + sb.append(")"); + return sb.toString(); + } +} diff --git a/cool-admin-java/src/main/java/com/cool/core/leaf/segment/model/SegmentBuffer.java b/cool-admin-java/src/main/java/com/cool/core/leaf/segment/model/SegmentBuffer.java new file mode 100644 index 0000000..44c33da --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/leaf/segment/model/SegmentBuffer.java @@ -0,0 +1,129 @@ +package com.cool.core.leaf.segment.model; + +import java.util.Arrays; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +/** + * 双buffer + */ +public class SegmentBuffer { + private String key; + private Segment[] segments; //双buffer + private volatile int currentPos; //当前的使用的segment的index + private volatile boolean nextReady; //下一个segment是否处于可切换状态 + private volatile boolean initOk; //是否初始化完成 + private final AtomicBoolean threadRunning; //线程是否在运行中 + private final ReadWriteLock lock; + + private volatile int step; + private volatile int minStep; + private volatile long updateTimestamp; + + public SegmentBuffer() { + segments = new Segment[]{new Segment(this), new Segment(this)}; + currentPos = 0; + nextReady = false; + initOk = false; + threadRunning = new AtomicBoolean(false); + lock = new ReentrantReadWriteLock(); + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public Segment[] getSegments() { + return segments; + } + + public Segment getCurrent() { + return segments[currentPos]; + } + + public int getCurrentPos() { + return currentPos; + } + + public int nextPos() { + return (currentPos + 1) % 2; + } + + public void switchPos() { + currentPos = nextPos(); + } + + public boolean isInitOk() { + return initOk; + } + + public void setInitOk(boolean initOk) { + this.initOk = initOk; + } + + public boolean isNextReady() { + return nextReady; + } + + public void setNextReady(boolean nextReady) { + this.nextReady = nextReady; + } + + public AtomicBoolean getThreadRunning() { + return threadRunning; + } + + public Lock rLock() { + return lock.readLock(); + } + + public Lock wLock() { + return lock.writeLock(); + } + + public int getStep() { + return step; + } + + public void setStep(int step) { + this.step = step; + } + + public int getMinStep() { + return minStep; + } + + public void setMinStep(int minStep) { + this.minStep = minStep; + } + + public long getUpdateTimestamp() { + return updateTimestamp; + } + + public void setUpdateTimestamp(long updateTimestamp) { + this.updateTimestamp = updateTimestamp; + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder("SegmentBuffer{"); + sb.append("key='").append(key).append('\''); + sb.append(", segments=").append(Arrays.toString(segments)); + sb.append(", currentPos=").append(currentPos); + sb.append(", nextReady=").append(nextReady); + sb.append(", initOk=").append(initOk); + sb.append(", threadRunning=").append(threadRunning); + sb.append(", step=").append(step); + sb.append(", minStep=").append(minStep); + sb.append(", updateTimestamp=").append(updateTimestamp); + sb.append('}'); + return sb.toString(); + } +} diff --git a/cool-admin-java/src/main/java/com/cool/core/lock/CoolLock.java b/cool-admin-java/src/main/java/com/cool/core/lock/CoolLock.java new file mode 100644 index 0000000..8ff0a80 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/lock/CoolLock.java @@ -0,0 +1,108 @@ +package com.cool.core.lock; + + +import jakarta.annotation.PostConstruct; +import java.time.Duration; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.cache.CacheType; +import org.springframework.cache.CacheManager; +import org.springframework.data.redis.cache.RedisCacheWriter; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +public class CoolLock { + // 缓存类型 + @Value("${spring.cache.type}") + private String type; + + @Value("${cool.cacheName}") + private String cacheName; + + private final CacheManager cacheManager; + private RedisCacheWriter redisCache ; + + // 非redis方式时使用 + private static final Map lockMap = new ConcurrentHashMap<>(); + + private static final String LOCK_PREFIX = "lock:"; + + @PostConstruct + private void init() { + this.type = type.toLowerCase(); + if (type.equalsIgnoreCase(CacheType.REDIS.name())) { + redisCache = (RedisCacheWriter) Objects.requireNonNull(cacheManager.getCache(cacheName)) + .getNativeCache(); + } + } + /** + * 尝试获取锁 + * + * @param key 锁的 key + * @param expireTime 锁的过期时间 + * @return 如果成功获取锁则返回 true,否则返回 false + */ + public boolean tryLock(String key, Duration expireTime) { + String lockKey = getLockKey(key); + if (type.equalsIgnoreCase(CacheType.CAFFEINE.name())) { + Lock lock = lockMap.computeIfAbsent(lockKey, k -> new ReentrantLock()); + return lock.tryLock(); + } + byte[] lockKeyBytes = lockKey.getBytes(); + // 使用 putIfAbsent 来尝试设置锁,如果成功返回 true,否则返回 false + return redisCache.putIfAbsent(cacheName, lockKeyBytes, new byte[0], expireTime) == null; + } + + /** + * 释放锁 + */ + public void unlock(String key) { + String lockKey = getLockKey(key); + if (type.equalsIgnoreCase(CacheType.CAFFEINE.name())) { + Lock lock = lockMap.get(lockKey); + if (lock != null && lock.tryLock()) { + lock.unlock(); + lockMap.remove(lockKey); + } + return; + } + redisCache.remove(cacheName, lockKey.getBytes()); + } + + /** + * 拼接锁前缀 + */ + private String getLockKey(String key) { + return LOCK_PREFIX + key; + } + + /** + * 等待锁 + * + * @param key 锁的 key + * @param expireTime 锁的过期时间 + * @return 如果成功获取锁则返回 true,否则返回 false + */ + public boolean waitForLock(String key, Duration expireTime, Duration waitTime) { + long endTime = System.currentTimeMillis() + waitTime.toMillis(); + while (System.currentTimeMillis() < endTime) { + if (tryLock(key, expireTime)) { + return true; + } + // 等待锁释放 + try { + Thread.sleep(100); // 可以根据需要调整等待时间 + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + return false; + } + } + return false; + } +} diff --git a/cool-admin-java/src/main/java/com/cool/core/mybatis/handler/BaseJsonTypeHandler.java b/cool-admin-java/src/main/java/com/cool/core/mybatis/handler/BaseJsonTypeHandler.java new file mode 100644 index 0000000..a403c46 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/mybatis/handler/BaseJsonTypeHandler.java @@ -0,0 +1,48 @@ +package com.cool.core.mybatis.handler; + +import com.cool.core.util.DatabaseDialectUtils; +import com.mybatisflex.core.util.StringUtil; +import org.apache.ibatis.type.BaseTypeHandler; +import org.apache.ibatis.type.JdbcType; +import org.postgresql.util.PGobject; +import java.sql.CallableStatement; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +public abstract class BaseJsonTypeHandler extends BaseTypeHandler { + + @Override + public void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException { + if (DatabaseDialectUtils.isPostgresql()) { + PGobject jsonObject = new PGobject(); + jsonObject.setType("json"); + jsonObject.setValue(toJson(parameter)); + ps.setObject(i, jsonObject); + } else { + ps.setString(i, toJson(parameter)); + } + } + + @Override + public T getNullableResult(ResultSet rs, String columnName) throws SQLException { + final String json = rs.getString(columnName); + return StringUtil.noText(json) ? null : parseJson(json); + } + + @Override + public T getNullableResult(ResultSet rs, int columnIndex) throws SQLException { + final String json = rs.getString(columnIndex); + return StringUtil.noText(json) ? null : parseJson(json); + } + + @Override + public T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { + final String json = cs.getString(columnIndex); + return StringUtil.noText(json) ? null : parseJson(json); + } + + protected abstract T parseJson(String json); + + protected abstract String toJson(T object); + +} diff --git a/cool-admin-java/src/main/java/com/cool/core/mybatis/handler/Fastjson2TypeHandler.java b/cool-admin-java/src/main/java/com/cool/core/mybatis/handler/Fastjson2TypeHandler.java new file mode 100644 index 0000000..aad475e --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/mybatis/handler/Fastjson2TypeHandler.java @@ -0,0 +1,73 @@ +package com.cool.core.mybatis.handler; + +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONReader; +import com.alibaba.fastjson2.JSONWriter; +import com.alibaba.fastjson2.TypeReference; + +import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.Collection; + +public class Fastjson2TypeHandler extends BaseJsonTypeHandler { + + private final Class propertyType; + private Class genericType; + private Type type; + + private boolean supportAutoType = false; + + public Fastjson2TypeHandler(Class propertyType) { + this.propertyType = propertyType; + this.supportAutoType = propertyType.isInterface() || Modifier.isAbstract(propertyType.getModifiers()); + } + + + public Fastjson2TypeHandler(Class propertyType, Class genericType) { + this.propertyType = propertyType; + this.genericType = genericType; + this.type = TypeReference.collectionType((Class) propertyType, genericType); + + Type actualTypeArgument = ((ParameterizedType) type).getActualTypeArguments()[0]; + if (actualTypeArgument instanceof Class) { + this.supportAutoType = ((Class) actualTypeArgument).isInterface() + || Modifier.isAbstract(((Class) actualTypeArgument).getModifiers()); + } + } + + @Override + protected Object parseJson(String json) { + if (genericType != null && Collection.class.isAssignableFrom(propertyType)) { + if (supportAutoType) { + return JSON.parseArray(json, Object.class, JSONReader.Feature.SupportAutoType); + } else { + return JSON.parseObject(json, type); + } + + } else { + if (supportAutoType) { + return JSON.parseObject(json, Object.class, JSONReader.Feature.SupportAutoType); + } else { + return JSON.parseObject(json, propertyType); + } + } + } + + @Override + protected String toJson(Object object) { + if (supportAutoType) { + return JSON.toJSONString(object + , JSONWriter.Feature.WriteMapNullValue + , JSONWriter.Feature.WriteNullListAsEmpty + , JSONWriter.Feature.WriteNullStringAsEmpty, JSONWriter.Feature.WriteClassName + ); + } else { + return JSON.toJSONString(object + , JSONWriter.Feature.WriteMapNullValue + , JSONWriter.Feature.WriteNullListAsEmpty + , JSONWriter.Feature.WriteNullStringAsEmpty + ); + } + } +} diff --git a/cool-admin-java/src/main/java/com/cool/core/mybatis/handler/JacksonTypeHandler.java b/cool-admin-java/src/main/java/com/cool/core/mybatis/handler/JacksonTypeHandler.java new file mode 100644 index 0000000..e92d096 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/mybatis/handler/JacksonTypeHandler.java @@ -0,0 +1,68 @@ +package com.cool.core.mybatis.handler; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.mybatisflex.core.exception.FlexExceptions; + +import java.io.IOException; +import java.util.Collection; + +public class JacksonTypeHandler extends BaseJsonTypeHandler { + + private static ObjectMapper objectMapper; + private final Class propertyType; + private Class genericType; + private JavaType javaType; + + public JacksonTypeHandler(Class propertyType) { + this.propertyType = propertyType; + } + + public JacksonTypeHandler(Class propertyType, Class genericType) { + this.propertyType = propertyType; + this.genericType = genericType; + } + + @Override + protected Object parseJson(String json) { + try { + if (genericType != null && Collection.class.isAssignableFrom(propertyType)) { + return getObjectMapper().readValue(json, getJavaType()); + } else { + return getObjectMapper().readValue(json, propertyType); + } + } catch (IOException e) { + throw FlexExceptions.wrap(e, "Can not parseJson by JacksonTypeHandler: " + json); + } + } + + @Override + protected String toJson(Object object) { + try { + return getObjectMapper().writeValueAsString(object); + } catch (JsonProcessingException e) { + throw FlexExceptions.wrap(e, "Can not convert object to Json by JacksonTypeHandler: " + object); + } + } + + + public JavaType getJavaType() { + if (javaType == null){ + javaType = getObjectMapper().getTypeFactory().constructCollectionType((Class) propertyType, genericType); + } + return javaType; + } + + public static ObjectMapper getObjectMapper() { + if (null == objectMapper) { + objectMapper = new ObjectMapper(); + } + return objectMapper; + } + + public static void setObjectMapper(ObjectMapper objectMapper) { + JacksonTypeHandler.objectMapper = objectMapper; + } + +} \ No newline at end of file diff --git a/cool-admin-java/src/main/java/com/cool/core/mybatis/pg/PostgresSequenceSyncService.java b/cool-admin-java/src/main/java/com/cool/core/mybatis/pg/PostgresSequenceSyncService.java new file mode 100644 index 0000000..d54b34c --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/mybatis/pg/PostgresSequenceSyncService.java @@ -0,0 +1,66 @@ +package com.cool.core.mybatis.pg; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.jdbc.core.JdbcTemplate; + +import java.util.List; +import java.util.Map; +/** + * PostgreSQL Identity 序列同步服务 + * 解决PostgreSQL 默认的序列机制,序列会自动递增,当手动插入指定id时需调用同步接口,否则id会重复。 + */ +@Slf4j +@Service +public class PostgresSequenceSyncService { + + private final JdbcTemplate jdbcTemplate; + + public PostgresSequenceSyncService(JdbcTemplate jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + } + + public void syncIdentitySequences() { + log.info("⏳ 开始同步 PostgreSQL Identity 序列..."); + + // 查询所有 identity 字段 + String identityColumnQuery = """ + SELECT table_schema, table_name, column_name + FROM information_schema.columns + WHERE is_identity = 'YES' + AND table_schema = 'public' + """; + + List> identityColumns = jdbcTemplate.queryForList(identityColumnQuery); + + for (Map col : identityColumns) { + String schema = (String) col.get("table_schema"); + String table = (String) col.get("table_name"); + String column = (String) col.get("column_name"); + + String fullTable = schema + "." + table; + + // 获取对应的序列名 + String seqNameSql = "SELECT pg_get_serial_sequence(?, ?)"; + String seqName = jdbcTemplate.queryForObject(seqNameSql, String.class, fullTable, column); + + if (seqName == null) { + log.warn("⚠️ 无法获取序列:{}.{}", table, column); + continue; + } + + // 获取当前最大 ID + Long maxId = jdbcTemplate.queryForObject( + String.format("SELECT COALESCE(MAX(%s), 0) FROM %s", column, fullTable), + Long.class + ); + + if (maxId != null && maxId > 0) { // 正确的:setval 有返回值,必须用 queryForObject + String setvalSql = "SELECT setval(?, ?)"; + Long newVal = jdbcTemplate.queryForObject(setvalSql, Long.class, seqName, maxId); + log.info("✅ 同步序列 [{}] -> 当前最大 ID: {}", seqName, newVal); + } + } + + log.info("✅ PostgreSQL Identity 序列同步完成。"); + } +} \ No newline at end of file diff --git a/cool-admin-java/src/main/java/com/cool/core/request/CrudOption.java b/cool-admin-java/src/main/java/com/cool/core/request/CrudOption.java new file mode 100644 index 0000000..c16954b --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/request/CrudOption.java @@ -0,0 +1,202 @@ +package com.cool.core.request; + + +import cn.hutool.core.annotation.AnnotationUtil; +import cn.hutool.core.util.ObjUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.ReflectUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.extra.spring.SpringUtil; +import cn.hutool.json.JSONArray; +import cn.hutool.json.JSONObject; +import com.cool.core.enums.QueryModeEnum; +import com.cool.core.util.ConvertUtil; +import com.mybatisflex.annotation.Table; +import com.mybatisflex.core.query.QueryColumn; +import com.mybatisflex.core.query.QueryCondition; +import com.mybatisflex.core.query.QueryTable; +import com.mybatisflex.core.query.QueryWrapper; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import lombok.Data; +import org.springframework.core.env.Environment; + +/** + * 查询构建器 + * + * @param + */ +@Data +public class CrudOption { + + private QueryWrapper queryWrapper; + private QueryColumn[] fieldEq; + private QueryColumn[] keyWordLikeFields; + private QueryColumn[] select; + private JSONObject requestParams; + + private QueryModeEnum queryModeEnum; + + private Transform transform; + + public interface Transform { + void apply(B obj); + } + + /** + * queryModeEnum 为 CUSTOM,可设置 默认为Map + */ + private Class asType; + + private Environment evn; + + public CrudOption(JSONObject requestParams) { + this.requestParams = requestParams; + this.queryWrapper = QueryWrapper.create(); + this.evn = SpringUtil.getBean(Environment.class); + queryModeEnum = QueryModeEnum.ENTITY; + } + + public QueryWrapper getQueryWrapper(Class entityClass) { + return build(this.queryWrapper, entityClass); + } + + public CrudOption queryWrapper(QueryWrapper queryWrapper) { + this.queryWrapper = queryWrapper; + return this; + } + + /** + * 按前端传上来的字段值做eq + */ + public CrudOption fieldEq(QueryColumn... fields) { + this.fieldEq = fields; + return this; + } + + /** + * 按前端传上来的字段值做like + */ + public CrudOption keyWordLikeFields(QueryColumn... fields) { + this.keyWordLikeFields = fields; + return this; + } + + /** + * 需要返回给前端的字段 + */ + public CrudOption select(QueryColumn... selects) { + this.select = selects; + return this; + } + + /** + * 查询模式决定返回值 + * 目前有三种模式,按实体查询返回、关联查询返回(实体字段上加 @RelationOneToMany 等注解)、自定义返回结果 + */ + public CrudOption queryModeEnum(QueryModeEnum queryModeEnum) { + this.queryModeEnum = queryModeEnum; + if (ObjUtil.equal(queryModeEnum, QueryModeEnum.CUSTOM) + && ObjUtil.isEmpty(asType)) { + asType = Map.class; + } + return this; + } + + /** + * 自定义返回结果对象类型 + */ + public CrudOption asType(Class asType) { + this.asType = asType; + return this; + } + + /** + * 转换参数,组装数据 + */ + public CrudOption transform(Transform transform) { + this.transform = transform; + return this; + } + + /** + * 构建查询条件 + * + * @return QueryWrapper + */ + private QueryWrapper build(QueryWrapper queryWrapper, Class entityClass) { + if (ObjectUtil.isNotEmpty(fieldEq)) { + Arrays.stream(fieldEq).toList().forEach(filed -> { + String filedName = StrUtil.toCamelCase(filed.getName()); + Object obj = requestParams.get(filedName); + if (ObjUtil.isEmpty(obj)) { + return; + } + if (obj instanceof JSONArray) { + // 集合 + queryWrapper.and(filed.in(ConvertUtil.covertListByClass(filedName, (JSONArray)obj, entityClass).toArray())); + } else { + // 对象 + queryWrapper.and(filed.eq(ConvertUtil.convertByClass(filedName, obj, entityClass))); + } + }); + } + if (ObjectUtil.isNotEmpty(this.keyWordLikeFields)) { + Object keyWord = requestParams.get("keyWord"); + if (ObjectUtil.isEmpty(keyWord)) { + // // keyWord值为空,遍历keyWordLikeFields字段,根据queryColumn字段名构建查询条件 + for (QueryColumn queryColumn : keyWordLikeFields) { + String fieldName = queryColumn.getName(); + String paramName = StrUtil.toCamelCase(fieldName); + String paramValue = requestParams.getStr(paramName); + if (ObjectUtil.isNotEmpty(paramValue)) { + queryWrapper.and(queryColumn.like(paramValue)); + } + } + } else { + // keyWord值非空,使用keyWord构建 + // 初始化一个空的 QueryCondition + QueryCondition orCondition = null; + for (QueryColumn queryColumn : keyWordLikeFields) { + QueryCondition condition = queryColumn.like(keyWord); + if (orCondition == null) { + orCondition = condition; + } else { + orCondition = orCondition.or(condition); + } + } + queryWrapper.and(orCondition); + } + } + if (ObjectUtil.isNotEmpty(select)) { + queryWrapper.select(select); + } + // 排序 + order(queryWrapper, entityClass); + return queryWrapper; + } + + private void order(QueryWrapper queryWrapper, Class entityClass) { + Table tableAnnotation = AnnotationUtil.getAnnotation(entityClass, Table.class); + if (ObjectUtil.isEmpty(tableAnnotation)) { + // 该对象没有@Table注解,非Entity对象 + return; + } + String tableAlias = ""; + List queryTables = (List) ReflectUtil.getFieldValue(queryWrapper, "queryTables"); + if (ObjectUtil.isNotEmpty(queryTables)) { + // 取主表作为排序字段别名 + QueryTable queryTable = queryTables.get(0); + tableAlias = queryTable.getName() + "."; + } + String order = requestParams.getStr("order", + tableAnnotation.camelToUnderline() ? "create_time" : "createTime"); + String sort = requestParams.getStr("sort", "desc"); + if (StrUtil.isNotEmpty(order) && StrUtil.isNotEmpty(sort)) { + queryWrapper.orderBy( + tableAlias + (tableAnnotation.camelToUnderline() ? StrUtil.toUnderlineCase(order) : order), + sort.equals("asc")); + } + } +} diff --git a/cool-admin-java/src/main/java/com/cool/core/request/PageResult.java b/cool-admin-java/src/main/java/com/cool/core/request/PageResult.java new file mode 100644 index 0000000..314a96f --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/request/PageResult.java @@ -0,0 +1,33 @@ +package com.cool.core.request; + +import java.util.List; +import com.mybatisflex.core.paginate.Page; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +@Schema( title = "分页数据模型" ) +public class PageResult { + @Schema( title = "分页数据" ) + private List list; + private Pagination pagination = new Pagination(); + + @Data + public static class Pagination { + @Schema( title = "页码" ) + private Long page; + @Schema( title = "本页数量" ) + private Long size; + @Schema( title = "总页数" ) + private Long total; + } + + static public PageResult of(Page page ){ + PageResult result = new PageResult(); + result.setList(page.getRecords()); + result.pagination.setPage( page.getPageNumber() ); + result.pagination.setSize( page.getPageSize() ); + result.pagination.setTotal( page.getTotalRow() ); + return result; + } +} \ No newline at end of file diff --git a/cool-admin-java/src/main/java/com/cool/core/request/R.java b/cool-admin-java/src/main/java/com/cool/core/request/R.java new file mode 100644 index 0000000..c152ff9 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/request/R.java @@ -0,0 +1,74 @@ +package com.cool.core.request; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; + +/** + * 返回信息 + */ +@Schema(title = "响应数据结构") +@Data +public class R implements Serializable { + private static final long serialVersionUID = 1L; + + + @Schema(title = "编码:1000表示成功,其他值表示失败") + private int code = 1000; + + @Schema(title = "消息内容") + private String message = "success"; + + @Schema(title = "响应数据") + private T data; + + public R() { + + } + + public R( int code, String message, T data ) { + this.code = code; + this.message = message; + this.data = data; + } + + public static R error() { + return error(1001, "请求方式不正确或服务出现异常"); + } + + public static R error(String msg) { + return error(1001, msg); + } + + public static R error(int code, String msg) { + R r = new R(); + r.code = code; + r.message = msg; + return r; + } + + public static R okMsg(String msg) { + R r = new R(); + r.message = msg; + return r; + } + + public static R ok() { + return new R(); + } + + public static R ok(B data) { + return new R(1000 , "success", data); + } + + + public R put(String key, Object value) { + switch (key) { + case "code" -> this.code = (int) value; + case "message" -> this.message = (String) value; + case "data" -> this.data = (T) value; + } + return this; + } +} \ No newline at end of file diff --git a/cool-admin-java/src/main/java/com/cool/core/request/RequestParamsFilter.java b/cool-admin-java/src/main/java/com/cool/core/request/RequestParamsFilter.java new file mode 100644 index 0000000..cbcc551 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/request/RequestParamsFilter.java @@ -0,0 +1,114 @@ +package com.cool.core.request; + +import cn.hutool.core.util.ObjUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import cn.hutool.jwt.JWT; +import com.cool.core.enums.UserTypeEnum; +import com.cool.core.util.BodyReaderHttpServletRequestWrapper; +import com.cool.core.util.CoolSecurityUtil; +import jakarta.servlet.*; +import jakarta.servlet.http.HttpServletRequest; +import java.io.IOException; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +/** + * 封装请求参数 URL参数 和 body JSON 到同一个 JSONObject 方便读取 + */ +@Component +@Order(2) +public class RequestParamsFilter implements Filter { + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + Filter.super.init(filterConfig); + } + + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) + throws IOException, ServletException { + // 防止流读取一次后就没有了, 所以需要将流继续写出去 + HttpServletRequest request = (HttpServletRequest) servletRequest; + JSONObject requestParams = new JSONObject(); + String language = request.getHeader("language"); + String coolEid = request.getHeader("cool-admin-eid"); + Long tenantId = StrUtil.isEmpty(coolEid) ? null : Long.parseLong(coolEid); + if (StrUtil.isNotEmpty(request.getContentType()) && request.getContentType().contains("multipart/form-data")) { + servletRequest.setAttribute("requestParams", requestParams); + servletRequest.setAttribute("cool-language", language); + servletRequest.setAttribute("tenantId", tenantId); + filterChain.doFilter(servletRequest, servletResponse); + } else { + BodyReaderHttpServletRequestWrapper requestWrapper = new BodyReaderHttpServletRequestWrapper(request); + String body = requestWrapper.getBodyString(requestWrapper); + if (StrUtil.isNotEmpty(body) && JSONUtil.isTypeJSON(body) && !JSONUtil.isTypeJSONArray( + body)) { + requestParams = JSONUtil.parseObj(body); + } + Object jwtObj = request.getAttribute("tokenInfo"); + if (jwtObj != null) { + requestParams.set("tokenInfo", ((JWT) jwtObj).getPayload().getClaimsJson()); + } + // 登录状态,设置用户id + Long currTenantId = setUserId(requestParams); + if (ObjUtil.isNotNull(currTenantId)) { + tenantId = currTenantId; + } + requestWrapper.setAttribute("cool-language", language); + request.setAttribute("tenantId", tenantId); + requestParams.set("body", body); + requestParams.putAll(getAllRequestParam(request)); + + requestWrapper.setAttribute("requestParams", requestParams); + filterChain.doFilter(requestWrapper, servletResponse); + } + } + + private Long setUserId(JSONObject requestParams) { + UserTypeEnum userTypeEnum = CoolSecurityUtil.getCurrentUserType(); + switch (userTypeEnum) { + // 只有登录了,才有用户类型, 不然为 UNKNOWN 状态 + case ADMIN -> { + // 管理后台由于之前已经有逻辑再了,怕会影响到,如果自己有传了值不覆盖 + Object o = requestParams.get("userId"); + if (ObjUtil.isNull(o)) { + requestParams.set("userId", CoolSecurityUtil.getCurrentUserId()); + } + } + // app端,userId 为当前登录的用户id + case APP -> requestParams.set("userId", CoolSecurityUtil.getCurrentUserId()); + } + return CoolSecurityUtil.getTenantId(requestParams); + } + + /** + * 获取客户端请求参数中所有的信息 + * + */ + private Map getAllRequestParam(final HttpServletRequest request) { + Map res = new HashMap<>(); + Enumeration temp = request.getParameterNames(); + if (null != temp) { + while (temp.hasMoreElements()) { + String en = (String) temp.nextElement(); + String value = request.getParameter(en); + res.put(en, value); + // 如果字段的值为空,判断若值为空,则删除这个字段> + if (null == res.get(en) || "".equals(res.get(en))) { + res.remove(en); + } + } + } + return res; + } + + @Override + public void destroy() { + Filter.super.destroy(); + } +} diff --git a/cool-admin-java/src/main/java/com/cool/core/request/RestInterceptor.java b/cool-admin-java/src/main/java/com/cool/core/request/RestInterceptor.java new file mode 100644 index 0000000..21a85cb --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/request/RestInterceptor.java @@ -0,0 +1,39 @@ +package com.cool.core.request; + +import com.cool.core.annotation.CoolRestController; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Component; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.HandlerInterceptor; + +import jakarta.servlet.http.HttpServletRequest; +import java.util.Arrays; + +/** + * 通用方法rest接口 + */ +@Component +public class RestInterceptor implements HandlerInterceptor { + private final static String[] rests = { "add", "delete", "update", "info", "list", "page" }; + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { + // 判断有无通用方法 + if (handler instanceof HandlerMethod) { + HandlerMethod handlerMethod = (HandlerMethod) handler; + CoolRestController coolRestController = handlerMethod.getBeanType().getAnnotation(CoolRestController.class); + if (null != coolRestController) { + String[] urls = request.getRequestURI().split("/"); + String rest = urls[urls.length - 1]; + if (Arrays.asList(rests).contains(rest)) { + if (!Arrays.asList(coolRestController.api()).contains(rest)) { + response.setStatus(HttpStatus.NOT_FOUND.value()); + return false; + } + } + } + } + return true; + } +} diff --git a/cool-admin-java/src/main/java/com/cool/core/request/prefix/AutoPrefixConfiguration.java b/cool-admin-java/src/main/java/com/cool/core/request/prefix/AutoPrefixConfiguration.java new file mode 100644 index 0000000..c699a80 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/request/prefix/AutoPrefixConfiguration.java @@ -0,0 +1,17 @@ +package com.cool.core.request.prefix; + +import org.springframework.boot.autoconfigure.web.servlet.WebMvcRegistrations; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; + +/** + * 自定义路由规则 + */ +@Component +public class AutoPrefixConfiguration implements WebMvcRegistrations { + + @Override + public RequestMappingHandlerMapping getRequestMappingHandlerMapping() { + return new AutoPrefixUrlMapping(); + } +} diff --git a/cool-admin-java/src/main/java/com/cool/core/request/prefix/AutoPrefixUrlMapping.java b/cool-admin-java/src/main/java/com/cool/core/request/prefix/AutoPrefixUrlMapping.java new file mode 100644 index 0000000..01f04ea --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/request/prefix/AutoPrefixUrlMapping.java @@ -0,0 +1,103 @@ +package com.cool.core.request.prefix; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.ObjUtil; +import com.cool.core.annotation.CoolRestController; +import com.cool.core.enums.Apis; +import com.cool.core.util.ConvertUtil; +import java.lang.reflect.Method; +import java.util.List; +import java.util.Set; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.servlet.mvc.method.RequestMappingInfo; +import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; + +/** + * 自动配置模块的路由 + */ +@Slf4j +public class AutoPrefixUrlMapping extends RequestMappingHandlerMapping { + + @Override + protected RequestMappingInfo getMappingForMethod(Method method, Class handlerType) { + CoolRestController[] annotations = handlerType.getAnnotationsByType(CoolRestController.class); + RequestMappingInfo info = super.getMappingForMethod(method, handlerType); + String packageName = handlerType.getPackage().getName(); + if (info != null && annotations.length > 0 && annotations[0].value().length == 0 + && packageName.contains("modules")) { + if (!checkApis(annotations, info)) { + return null; + } + String prefix = getPrefix(packageName); + String cName = getCName(annotations[0].cname(), handlerType, prefix); + info = info.mutate().paths(prefix + "/" + cName).build().combine(info); + } + return info; + } + + /** + * 根据配置检查是否构建路由 + * + * @param annotations 注解 + * @param info 路由信息 + * @return 是否需要构建路由 + */ + private boolean checkApis(CoolRestController[] annotations, RequestMappingInfo info) { + String[] apis = Apis.ALL_API; + if (info.getPathPatternsCondition() == null) { + return true; + } + List setApis; + if (ArrayUtil.isNotEmpty(annotations)) { + CoolRestController coolRestController = annotations[0]; + setApis = CollUtil.toList(coolRestController.api()); + + Set methodPaths = info.getPathPatternsCondition().getPatternValues(); + String methodPath = methodPaths.iterator().next().replace("/", ""); + if (!CollUtil.toList(apis).contains(methodPath)) { + return true; + } else { + return setApis.contains(methodPath); + } + } + return false; + } + + /** + * 根据Controller名称构建路由地址 + * + * @param handlerType 类 + * @param prefix 路由前缀 + * @return url地址 + */ + private String getCName(String cname, Class handlerType, String prefix) { + if (ObjUtil.isNotEmpty(cname)) { + return cname; + } + String name = handlerType.getName(); + String[] names = name.split("[.]"); + name = names[names.length - 1]; + return ConvertUtil.extractController2Path(ConvertUtil.pathToClassName(prefix), name); + } + + /** + * 构建路由前缀 + * + * @param packageName 包名 + * @return 返回路由前缀 + */ + private String getPrefix(String packageName) { + String dotPath = packageName.split("modules")[1]; // 将包路径中多于的部分截取掉 + String[] dotPaths = dotPath.replace(".controller", "").split("[.]"); + List paths = CollUtil.toList(dotPaths); + paths.removeIf(String::isEmpty); + // 第一和第二位互换位置 + String p0 = paths.get(0); + String p1 = paths.get(1); + paths.set(0, p1); + paths.set(1, p0); + dotPath = "/" + CollUtil.join(paths, "/"); + return dotPath; + } +} \ No newline at end of file diff --git a/cool-admin-java/src/main/java/com/cool/core/security/EntryPointUnauthorizedHandler.java b/cool-admin-java/src/main/java/com/cool/core/security/EntryPointUnauthorizedHandler.java new file mode 100644 index 0000000..1d86f8a --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/security/EntryPointUnauthorizedHandler.java @@ -0,0 +1,34 @@ +package com.cool.core.security; + +import cn.hutool.json.JSONUtil; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.stereotype.Component; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.HashMap; + +/** + * 自定401返回值 + */ +@Component +public class EntryPointUnauthorizedHandler implements AuthenticationEntryPoint { + + @Override + public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) + throws IOException { + response.setHeader("Access-Control-Allow-Origin", "*"); + response.setCharacterEncoding("UTF-8"); + response.setContentType("application/json; charset=utf-8"); + response.getWriter().write(JSONUtil.toJsonStr(new HashMap() { + { + put("code", "401"); + put("message", "未登录"); + } + })); + response.setStatus(401); + } + +} \ No newline at end of file diff --git a/cool-admin-java/src/main/java/com/cool/core/security/IgnoredUrlsProperties.java b/cool-admin-java/src/main/java/com/cool/core/security/IgnoredUrlsProperties.java new file mode 100644 index 0000000..2443dae --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/security/IgnoredUrlsProperties.java @@ -0,0 +1,22 @@ +package com.cool.core.security; + +import java.util.ArrayList; +import java.util.List; +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +/** + * 忽略地址配置 + */ +@Data +@Configuration +@ConfigurationProperties(prefix = "ignored") +public class IgnoredUrlsProperties { + + // 忽略后台校验权限列表 + private List adminAuthUrls = new ArrayList<>(); + + // 忽略记录请求日志列表 + private List logUrls = new ArrayList<>(); +} diff --git a/cool-admin-java/src/main/java/com/cool/core/security/JwtAuthenticationTokenFilter.java b/cool-admin-java/src/main/java/com/cool/core/security/JwtAuthenticationTokenFilter.java new file mode 100644 index 0000000..05209df --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/security/JwtAuthenticationTokenFilter.java @@ -0,0 +1,110 @@ +package com.cool.core.security; + +import cn.hutool.core.convert.Convert; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.jwt.JWT; +import com.cool.core.cache.CoolCache; +import com.cool.core.enums.UserTypeEnum; +import com.cool.core.security.jwt.JwtTokenUtil; +import com.cool.core.security.jwt.JwtUser; +import com.cool.core.util.PathUtils; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Objects; +import lombok.RequiredArgsConstructor; +import org.springframework.core.annotation.Order; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; +import org.springframework.stereotype.Component; +import org.springframework.web.filter.OncePerRequestFilter; + +/** + * Token过滤器 + */ +@Order(1) +@Component +@RequiredArgsConstructor +public class JwtAuthenticationTokenFilter extends OncePerRequestFilter { + + final private JwtTokenUtil jwtTokenUtil; + final private CoolCache coolCache; + final private IgnoredUrlsProperties ignoredUrlsProperties; + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, + FilterChain chain) + throws ServletException, IOException { + String requestURI = request.getRequestURI(); + if (PathUtils.isMatch(ignoredUrlsProperties.getAdminAuthUrls(), requestURI)) { + // 请求路径在忽略后台鉴权url里支持通配符,放行 + chain.doFilter(request, response); + return; + } + String authToken = request.getHeader("Authorization"); + if (!StrUtil.isEmpty(authToken)) { + JWT jwt = jwtTokenUtil.getTokenInfo(authToken); + + Object userType = jwt.getPayload("userType"); + if (Objects.equals(userType, UserTypeEnum.APP.name())) { + // app + handlerAppRequest(request, jwt, authToken); + } else { + // admin + handlerAdminRequest(request, jwt, authToken); + } + } + chain.doFilter(request, response); + } + /** + * 处理app请求 + */ + private void handlerAppRequest(HttpServletRequest request, JWT jwt, String authToken) { + String userId = jwt.getPayload("userId").toString(); + if (ObjectUtil.isNotEmpty(userId) + && SecurityContextHolder.getContext().getAuthentication() == null) { + UserDetails userDetails = coolCache.get("app:userDetails:" + userId, + JwtUser.class); + if (jwtTokenUtil.validateToken(authToken) && userDetails != null) { + UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken( + userDetails, null, userDetails.getAuthorities()); + authentication.setDetails( + new WebAuthenticationDetailsSource().buildDetails(request)); + SecurityContextHolder.getContext().setAuthentication(authentication); + request.setAttribute("userId", jwt.getPayload("userId")); + request.setAttribute("tokenInfo", jwt); + } + } + } + + /** + * 处理后台请求 + */ + private void handlerAdminRequest(HttpServletRequest request, JWT jwt, String authToken) { + String username = jwt.getPayload("username").toString(); + if (username != null + && SecurityContextHolder.getContext().getAuthentication() == null) { + UserDetails userDetails = coolCache.get("admin:userDetails:" + username, + JwtUser.class); + Integer passwordV = Convert.toInt(jwt.getPayload("passwordVersion")); + Integer rv = coolCache.get("admin:passwordVersion:" + jwt.getPayload("userId"), + Integer.class); + if (jwtTokenUtil.validateToken(authToken, username) && Objects.equals(passwordV, rv) + && userDetails != null) { + UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken( + userDetails, null, userDetails.getAuthorities()); + authentication.setDetails( + new WebAuthenticationDetailsSource().buildDetails(request)); + SecurityContextHolder.getContext().setAuthentication(authentication); + request.setAttribute("adminUsername", jwt.getPayload("username")); + request.setAttribute("adminUserId", jwt.getPayload("userId")); + request.setAttribute("tokenInfo", jwt); + } + } + } +} diff --git a/cool-admin-java/src/main/java/com/cool/core/security/JwtSecurityConfig.java b/cool-admin-java/src/main/java/com/cool/core/security/JwtSecurityConfig.java new file mode 100644 index 0000000..6f9e722 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/security/JwtSecurityConfig.java @@ -0,0 +1,152 @@ +package com.cool.core.security; + +import com.cool.core.annotation.TokenIgnore; +import com.cool.core.enums.UserTypeEnum; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.annotation.AnnotatedElementUtils; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.AuthenticationProvider; +import org.springframework.security.authentication.dao.DaoAuthenticationProvider; +import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; +import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer.FrameOptionsConfig; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import org.springframework.util.DigestUtils; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.mvc.method.RequestMappingInfo; +import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; +import org.springframework.web.util.pattern.PathPattern; + +@EnableWebSecurity +@Configuration +@Slf4j +@RequiredArgsConstructor +public class JwtSecurityConfig { + + // 用户详情 + final private UserDetailsService userDetailsService; + final private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter; + // 401 + final private EntryPointUnauthorizedHandler entryPointUnauthorizedHandler; + // 403 + final private RestAccessDeniedHandler restAccessDeniedHandler; + // 忽略权限控制的地址 + final private IgnoredUrlsProperties ignoredUrlsProperties; + + final private RequestMappingHandlerMapping requestMappingHandlerMapping; + + @Bean + public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception { + // 动态获取忽略的URL + configureIgnoredUrls(); + + return httpSecurity + .authorizeHttpRequests( + conf -> { + conf.requestMatchers( + ignoredUrlsProperties.getAdminAuthUrls().toArray(String[]::new)) + .permitAll(); + conf.requestMatchers("/admin/**").authenticated(); + conf.requestMatchers("/app/**").hasRole(UserTypeEnum.APP.name()); + }) + .headers(config -> config.frameOptions(FrameOptionsConfig::disable)) + // 允许网页iframe + .csrf(AbstractHttpConfigurer::disable) + .sessionManagement(conf -> conf.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) + .addFilterBefore(jwtAuthenticationTokenFilter, + UsernamePasswordAuthenticationFilter.class) + .exceptionHandling(config -> { + config.authenticationEntryPoint(entryPointUnauthorizedHandler); + config.accessDeniedHandler(restAccessDeniedHandler); + }).build(); + } + + private void configureIgnoredUrls() { + Map mappings = requestMappingHandlerMapping.getHandlerMethods(); + List handlerCtr = new ArrayList<>(); + mappings.forEach((requestMappingInfo, handlerMethod) -> { + Method method = handlerMethod.getMethod(); + TokenIgnore tokenIgnore = AnnotatedElementUtils.findMergedAnnotation(method, TokenIgnore.class); + TokenIgnore tokenIgnoreCtr = AnnotatedElementUtils.findMergedAnnotation(handlerMethod.getBeanType(), TokenIgnore.class); + if (!handlerCtr.contains(handlerMethod.getBeanType().getName()) && tokenIgnoreCtr != null) { + requestMappingInfo.getPathPatternsCondition().getPatterns().forEach(pathPattern -> { + String[] prefixs = pathPattern.getPatternString().split("/"); + // 去除最后一个路径 + List urls = new ArrayList<>(); + for (int i = 0; i < prefixs.length - 1; i++) { + urls.add(prefixs[i]); + } + // 遍历 tokenIgnoreCtr.value() + for (String path : tokenIgnoreCtr.value()) { + ignoredUrlsProperties.getAdminAuthUrls().add(String.join("/", urls) + "/" + path); + } + if (tokenIgnoreCtr.value().length == 0) { + // 通配 + ignoredUrlsProperties.getAdminAuthUrls().add(String.join("/", urls)+ "/**"); + } + handlerCtr.add(handlerMethod.getBeanType().getName()); + }); + } + if (tokenIgnore != null) { + StringBuilder url = new StringBuilder(); + RequestMapping classRequestMapping = AnnotatedElementUtils.findMergedAnnotation(handlerMethod.getBeanType(), RequestMapping.class); + if (classRequestMapping != null) { + for (String path : classRequestMapping.value()) { + url.append(path); + } + } + if (requestMappingInfo.getPathPatternsCondition() == null) { + return; + } + for (PathPattern path : requestMappingInfo.getPathPatternsCondition().getPatterns()) { + url.append(path); + } + ignoredUrlsProperties.getAdminAuthUrls().add(url.toString()); + } + }); + } + + @Bean + public PasswordEncoder passwordEncoder() { + return new PasswordEncoder() { + @Override + public String encode(CharSequence rawPassword) { + return DigestUtils.md5DigestAsHex(((String) rawPassword).getBytes()); + } + + @Override + public boolean matches(CharSequence rawPassword, String encodedPassword) { + return encodedPassword.equals( + DigestUtils.md5DigestAsHex(((String) rawPassword).getBytes())); + } + }; + } + + @Bean + public AuthenticationProvider authenticationProvider() { + DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider(); + authProvider.setUserDetailsService(userDetailsService); + authProvider.setPasswordEncoder(passwordEncoder()); + return authProvider; + } + + @Bean + public AuthenticationManager authenticationManager(AuthenticationConfiguration config) + throws Exception { + return config.getAuthenticationManager(); + } +} diff --git a/cool-admin-java/src/main/java/com/cool/core/security/MyAccessDecisionManager.java b/cool-admin-java/src/main/java/com/cool/core/security/MyAccessDecisionManager.java new file mode 100644 index 0000000..3c410af --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/security/MyAccessDecisionManager.java @@ -0,0 +1,61 @@ +package com.cool.core.security; + +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.AccessDecisionManager; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.access.ConfigAttribute; +import org.springframework.security.authentication.InsufficientAuthenticationException; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.web.FilterInvocation; +import org.springframework.stereotype.Component; + +/** + * 权限管理决断器 判断用户拥有的权限或角色是否有资源访问权限 + */ +@RequiredArgsConstructor +@Slf4j +@Component +public class MyAccessDecisionManager implements AccessDecisionManager { + // 忽略权限控制的地址 + final private IgnoredUrlsProperties ignoredUrlsProperties; + + @Override + public void decide(Authentication authentication, Object o, Collection configAttributes) + throws AccessDeniedException, InsufficientAuthenticationException { + if (configAttributes == null) { + return; + } + List urls = ignoredUrlsProperties.getAdminAuthUrls(); + String url = ((FilterInvocation) o).getRequestUrl().split("[?]")[0]; + if (urls.contains(url)) { + return; + } + Iterator iterator = configAttributes.iterator(); + while (iterator.hasNext()) { + ConfigAttribute c = iterator.next(); + String needPerm = c.getAttribute(); + for (GrantedAuthority ga : authentication.getAuthorities()) { + // 匹配用户拥有的ga 和 系统中的needPerm + if (needPerm.trim().equals(ga.getAuthority())) { + return; + } + } + } + throw new AccessDeniedException("抱歉,您没有访问权限"); + } + + @Override + public boolean supports(ConfigAttribute configAttribute) { + return true; + } + + @Override + public boolean supports(Class aClass) { + return true; + } +} diff --git a/cool-admin-java/src/main/java/com/cool/core/security/MyFilterSecurityInterceptor.java b/cool-admin-java/src/main/java/com/cool/core/security/MyFilterSecurityInterceptor.java new file mode 100644 index 0000000..f22165b --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/security/MyFilterSecurityInterceptor.java @@ -0,0 +1,68 @@ +package com.cool.core.security; + +import jakarta.annotation.Resource; +import jakarta.servlet.Filter; +import jakarta.servlet.FilterChain; +import jakarta.servlet.FilterConfig; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import java.io.IOException; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.SecurityMetadataSource; +import org.springframework.security.access.intercept.AbstractSecurityInterceptor; +import org.springframework.security.access.intercept.InterceptorStatusToken; +import org.springframework.security.web.FilterInvocation; +import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource; +import org.springframework.stereotype.Component; + +/** + * 权限管理拦截器 监控用户行为 + */ +@Slf4j +@Component +@RequiredArgsConstructor +public class MyFilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter { + + final private FilterInvocationSecurityMetadataSource securityMetadataSource; + + @Resource + public void setMyAccessDecisionManager(MyAccessDecisionManager myAccessDecisionManager) { + super.setAccessDecisionManager(myAccessDecisionManager); + } + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException { + FilterInvocation fi = new FilterInvocation(request, response, chain); + invoke(fi); + } + + public void invoke(FilterInvocation fi) throws IOException, ServletException { + InterceptorStatusToken token = super.beforeInvocation(fi); + try { + fi.getChain().doFilter(fi.getRequest(), fi.getResponse()); + } finally { + super.afterInvocation(token, null); + } + } + + @Override + public void destroy() { + } + + @Override + public Class getSecureObjectClass() { + return FilterInvocation.class; + } + + @Override + public SecurityMetadataSource obtainSecurityMetadataSource() { + return this.securityMetadataSource; + } +} \ No newline at end of file diff --git a/cool-admin-java/src/main/java/com/cool/core/security/RestAccessDeniedHandler.java b/cool-admin-java/src/main/java/com/cool/core/security/RestAccessDeniedHandler.java new file mode 100644 index 0000000..7954d05 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/security/RestAccessDeniedHandler.java @@ -0,0 +1,34 @@ +package com.cool.core.security; + +import cn.hutool.json.JSONUtil; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.web.access.AccessDeniedHandler; +import org.springframework.stereotype.Component; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.HashMap; + +/** + * 自定403返回值 + */ +@Component +public class RestAccessDeniedHandler implements AccessDeniedHandler { + + @Override + public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException e) + throws IOException { + response.setHeader("Access-Control-Allow-Origin", "*"); + response.setCharacterEncoding("UTF-8"); + response.setContentType("application/json; charset=utf-8"); + response.getWriter().write(JSONUtil.toJsonStr(new HashMap() { + { + put("code", "403"); + put("message", "无权限"); + } + })); + response.setStatus(403); + } + +} \ No newline at end of file diff --git a/cool-admin-java/src/main/java/com/cool/core/security/jwt/JwtTokenUtil.java b/cool-admin-java/src/main/java/com/cool/core/security/jwt/JwtTokenUtil.java new file mode 100644 index 0000000..5335726 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/security/jwt/JwtTokenUtil.java @@ -0,0 +1,165 @@ +package com.cool.core.security.jwt; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.jwt.JWT; +import cn.hutool.jwt.JWTUtil; +import cn.hutool.jwt.JWTValidator; +import com.cool.core.config.CoolProperties; +import com.cool.modules.base.service.sys.BaseSysConfService; +import java.io.Serializable; +import java.util.Date; +import java.util.Map; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +/** + * JWT工具类 + */ +@Component +@RequiredArgsConstructor +public class JwtTokenUtil implements Serializable { + + final private CoolProperties coolProperties; + final private BaseSysConfService baseSysConfService; + final String tokenKey = "JWT_SECRET_TOKEN"; + final String refreshTokenKey = "JWT_SECRET_REFRESH_TOKEN"; + + public long getExpire() { + return this.coolProperties.getToken().getExpire(); + } + + public long getRefreshExpire() { + return this.coolProperties.getToken().getRefreshExpire(); + } + + public String getTokenSecret() { + String secret = baseSysConfService.getValueWithCache(tokenKey); + if (StrUtil.isBlank(secret)) { + secret = StrUtil.uuid().replaceAll("-", ""); + baseSysConfService.setValue(tokenKey, secret); + } + return secret; + } + + public String getRefreshTokenSecret() { + String secret = baseSysConfService.getValueWithCache(refreshTokenKey); + if (StrUtil.isBlank(secret)) { + secret = StrUtil.uuid().replaceAll("-", ""); + baseSysConfService.setValue(refreshTokenKey, secret); + } + return secret; + } + + /** + * 生成令牌 + * + * @param tokenInfo 保存的用户信息 + * @return 令牌 + */ + public String generateToken(Map tokenInfo) { + tokenInfo.put("isRefresh", false); + Date expirationDate = new Date(System.currentTimeMillis() + getExpire() * 1000); + JWT jwt = JWT.create().setExpiresAt(expirationDate).setKey(getTokenSecret().getBytes()) + .setPayload("created", new Date()); + tokenInfo.forEach(jwt::setPayload); + return jwt.sign(); + } + + /** + * 生成令牌 + * + * @param tokenInfo 保存的用户信息 + * @return 令牌 + */ + public String generateRefreshToken(Map tokenInfo) { + tokenInfo.put("isRefresh", true); + Date expirationDate = new Date(System.currentTimeMillis() + getRefreshExpire() * 1000); + JWT jwt = JWT.create().setExpiresAt(expirationDate).setKey(getRefreshTokenSecret().getBytes()) + .setPayload("created", new Date()); + tokenInfo.forEach(jwt::setPayload); + return jwt.sign(); + } + + /** + * 从令牌中获取用户名 + * + * @param token 令牌 + * @return 用户名 + */ + public String getUsernameFromToken(String token) { + JWT jwt = JWT.of(token); + return jwt.getPayload("username").toString(); + } + + /** + * 获得token信息 + * + * @param token 令牌 + * @return token信息 + */ + public JWT getTokenInfo(String token) { + return JWT.of(token); + } + + /** + * 判断令牌是否过期 + * + * @param token 令牌 + * @return 是否过期 + */ + public Boolean isTokenExpired(String token) { + try { + JWTValidator.of(token).validateDate(DateUtil.date()); + return false; + } catch (Exception e) { + return true; + } + } + + /** + * 验证令牌 + * + * @param token 令牌 + * @param username 用户 + * @return 是否有效 + */ + public Boolean validateToken(String token, String username) { + if (ObjectUtil.isEmpty(token)) { + return false; + } + String tokenUsername = getUsernameFromToken(token); + String secret = getTokenSecret(); + boolean isValidSignature = JWTUtil.verify(token, secret.getBytes()); + return (tokenUsername.equals(username) && !isTokenExpired(token) && isValidSignature); + } + + /** + * 校验token是否有效 + * @param token + * @return + */ + public Boolean validateToken(String token) { + if (ObjectUtil.isEmpty(token)) { + return false; + } + String secret = getTokenSecret(); + boolean isValidSignature = JWTUtil.verify(token, secret.getBytes()); + return (!isTokenExpired(token) && isValidSignature); + } + + /** + * 校验refresh token是否有效 + * @param token + * @return + */ + public Boolean validateRefreshToken(String token) { + if (ObjectUtil.isEmpty(token)) { + return false; + } + String secret = getRefreshTokenSecret(); + boolean isValidSignature = JWTUtil.verify(token, secret.getBytes()); + return (!isTokenExpired(token) && isValidSignature); + } +} diff --git a/cool-admin-java/src/main/java/com/cool/core/security/jwt/JwtUser.java b/cool-admin-java/src/main/java/com/cool/core/security/jwt/JwtUser.java new file mode 100644 index 0000000..c69cf9e --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/security/jwt/JwtUser.java @@ -0,0 +1,78 @@ +package com.cool.core.security.jwt; + +import com.cool.core.enums.UserTypeEnum; +import java.util.Collection; +import java.util.List; +import lombok.Data; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; + +/** + * 后台用户信息 + */ +@Data +public class JwtUser implements UserDetails { + + /****** + * 后台用户 + * ********/ + private Long userId; + private String username; + private String password; + private Boolean status; + private UserTypeEnum userTypeEnum; + private List perms; + public JwtUser(Long userId, String username, String password, List perms, Boolean status) { + this.userId = userId; + this.username = username; + this.password = password; + this.perms = perms; + this.status = status; + this.userTypeEnum = UserTypeEnum.ADMIN; + } + + /****** + * app用户 + * ********/ + public JwtUser(Long userId, List perms, Boolean status) { + this.userId = userId; + this.perms = perms; + this.status = status; + this.userTypeEnum = UserTypeEnum.APP; + } + + @Override + public Collection getAuthorities() { + return perms; + } + + @Override + public String getPassword() { + return password; + } + + @Override + public String getUsername() { + return username; + } + + @Override + public boolean isAccountNonExpired() { + return true; + } + + @Override + public boolean isAccountNonLocked() { + return true; + } + + @Override + public boolean isCredentialsNonExpired() { + return true; + } + + @Override + public boolean isEnabled() { + return status; + } +} diff --git a/cool-admin-java/src/main/java/com/cool/core/tenant/CoolTenantFactory.java b/cool-admin-java/src/main/java/com/cool/core/tenant/CoolTenantFactory.java new file mode 100644 index 0000000..f79ebef --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/tenant/CoolTenantFactory.java @@ -0,0 +1,14 @@ +package com.cool.core.tenant; + +import com.cool.core.util.TenantUtil; +import com.mybatisflex.core.tenant.TenantFactory; + +public class CoolTenantFactory implements TenantFactory { + public Object[] getTenantIds(){ + Long tenantId = TenantUtil.getTenantId(); + if (tenantId == null) { + return null; + } + return new Object[]{tenantId}; + } +} diff --git a/cool-admin-java/src/main/java/com/cool/core/util/AnnotationUtils.java b/cool-admin-java/src/main/java/com/cool/core/util/AnnotationUtils.java new file mode 100644 index 0000000..b65d6a3 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/util/AnnotationUtils.java @@ -0,0 +1,73 @@ +package com.cool.core.util; + +import com.cool.core.annotation.CoolPlugin; +import java.lang.annotation.Annotation; +import java.lang.reflect.Modifier; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Configuration; +import org.springframework.stereotype.Component; +import org.springframework.stereotype.Controller; +import org.springframework.stereotype.Repository; +import org.springframework.stereotype.Service; + +@Slf4j +public class AnnotationUtils { + + /** + * 判断一个类是否有 Spring 核心注解 + * + * @param clazz 要检查的类 + * @return true 如果该类上添加了相应的 Spring 注解;否则返回 false + */ + public static boolean hasSpringAnnotation(Class clazz) { + if (clazz == null) { + return false; + } + // 是否是接口 + if (clazz.isInterface()) { + return false; + } + // 是否是抽象类 + if (Modifier.isAbstract(clazz.getModifiers())) { + return false; + } + + try { + if (clazz.getAnnotation(Component.class) != null || clazz.getAnnotation(Repository.class) != null + || clazz.getAnnotation(Service.class) != null || clazz.getAnnotation(Controller.class) != null + || clazz.getAnnotation(Configuration.class) != null) { + return true; + } + } catch (Exception e) { + log.error("出现异常:{}", e.getMessage()); + } + return false; + } + + /** + * 插件 + */ + public static boolean hasCoolPluginAnnotation(Class clazz) { + if (clazz == null) { + return false; + } + // 是否是接口 + if (clazz.isInterface()) { + return false; + } + // 是否是抽象类 + if (Modifier.isAbstract(clazz.getModifiers())) { + return false; + } + try { + ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); + if (clazz.getAnnotation( + (Class) contextClassLoader.loadClass(CoolPlugin.class.getName())) != null) { + return true; + } + } catch (Exception e) { + log.error("出现异常:{}", e.getMessage(), e); + } + return false; + } +} \ No newline at end of file diff --git a/cool-admin-java/src/main/java/com/cool/core/util/AutoTypeConverter.java b/cool-admin-java/src/main/java/com/cool/core/util/AutoTypeConverter.java new file mode 100644 index 0000000..45ed11c --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/util/AutoTypeConverter.java @@ -0,0 +1,27 @@ +package com.cool.core.util; + +import cn.hutool.core.convert.Convert; +import cn.hutool.core.util.NumberUtil; + +import java.io.Serializable; + +public class AutoTypeConverter { + /** + * 将字符串自动转换为数字或保留为字符串 + * + * @param input 输入字符串 + * @return Integer / Long / String + */ + public static Serializable autoConvert(Object input) { + if (input == null) { + return null; + } + if (NumberUtil.isInteger(input.toString())) { + return Convert.convert(Integer.class, input); + } else if (NumberUtil.isLong(input.toString())) { + return Convert.convert(Long.class, input); + } else { + return (Serializable) input; + } + } +} diff --git a/cool-admin-java/src/main/java/com/cool/core/util/BodyReaderHttpServletRequestWrapper.java b/cool-admin-java/src/main/java/com/cool/core/util/BodyReaderHttpServletRequestWrapper.java new file mode 100644 index 0000000..2c783d2 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/util/BodyReaderHttpServletRequestWrapper.java @@ -0,0 +1,119 @@ +package com.cool.core.util; + +import jakarta.servlet.ReadListener; +import jakarta.servlet.ServletInputStream; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequestWrapper; +import lombok.extern.slf4j.Slf4j; + +import java.io.*; +import java.nio.charset.Charset; + +/** + * 保存流 + */ +@Slf4j +public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper { + + private final byte[] body; + + public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException { + super(request); + String sessionStream = getBodyString(request); + body = sessionStream.getBytes(Charset.forName("UTF-8")); + } + + /** + * 获取请求Body + * + * @param request + * @return + */ + public String getBodyString(final ServletRequest request) { + StringBuilder sb = new StringBuilder(); + InputStream inputStream = null; + BufferedReader reader = null; + try { + inputStream = cloneInputStream(request.getInputStream()); + reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8"))); + String line = ""; + while ((line = reader.readLine()) != null) { + sb.append(line); + } + } catch (IOException e) { + log.error("err", e); + } finally { + if (inputStream != null) { + try { + inputStream.close(); + } catch (IOException e) { + log.error("err", e); + } + } + if (reader != null) { + try { + reader.close(); + } catch (IOException e) { + log.error("err", e); + } + } + } + return sb.toString(); + } + + /** + * Description: 复制输入流
+ * + * @param inputStream + * @return
+ */ + public InputStream cloneInputStream(ServletInputStream inputStream) { + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + byte[] buffer = new byte[1024]; + int len; + try { + while ((len = inputStream.read(buffer)) > -1) { + byteArrayOutputStream.write(buffer, 0, len); + } + byteArrayOutputStream.flush(); + } catch (IOException e) { + log.error("err", e); + } + InputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray()); + return byteArrayInputStream; + } + + @Override + public BufferedReader getReader() throws IOException { + return new BufferedReader(new InputStreamReader(getInputStream())); + } + + @Override + public ServletInputStream getInputStream() throws IOException { + + final ByteArrayInputStream bais = new ByteArrayInputStream(body); + + return new ServletInputStream() { + + @Override + public int read() throws IOException { + return bais.read(); + } + + @Override + public boolean isFinished() { + return false; + } + + @Override + public boolean isReady() { + return false; + } + + @Override + public void setReadListener(ReadListener readListener) { + } + }; + } +} diff --git a/cool-admin-java/src/main/java/com/cool/core/util/CompilerUtils.java b/cool-admin-java/src/main/java/com/cool/core/util/CompilerUtils.java new file mode 100644 index 0000000..3e6506f --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/util/CompilerUtils.java @@ -0,0 +1,180 @@ +package com.cool.core.util; + +import cn.hutool.core.io.FileUtil; +import com.mybatisflex.processor.MybatisFlexProcessor; +import java.io.File; +import java.io.IOException; +import java.lang.management.ManagementFactory; +import java.lang.management.RuntimeMXBean; +import java.nio.charset.StandardCharsets; +import java.util.List; +import javax.annotation.processing.Processor; +import javax.tools.JavaCompiler; +import javax.tools.JavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.StandardLocation; +import javax.tools.ToolProvider; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class CompilerUtils { + + public final static String META_INF_VERSIONS = "META-INF/versions/"; + + // jdk版本 + private static String JVM_VERSION = null; + + /** + * 获取jdk版本 + */ + public static String getJdkVersion() { + if (JVM_VERSION == null) { + RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean(); + JVM_VERSION = runtimeMXBean.getSpecVersion(); + } + return JVM_VERSION; + } + + /** + * 创建文件, 先删除在创建 + */ + public static void createFile(String content, String filePathStr) { + FileUtil.del(filePathStr); + File file = FileUtil.touch(filePathStr); + FileUtil.appendString(content, file, StandardCharsets.UTF_8.name()); + compileAndSave(filePathStr); + } + + public static String createMapper(String actModulePath, String fileName, String mapper) { + String pathStr = actModulePath + File.separator + "mapper" + File.separator; + String filePathStr = pathStr + fileName + "Mapper.java"; + createFile(mapper, filePathStr); + return filePathStr; + } + + public static String createServiceImpl(String actModulePath, String fileName, + String serviceImpl) { + String pathStr = actModulePath + File.separator + "service" + File.separator + "impl" + File.separator; + String filePathStr = pathStr + fileName + "ServiceImpl.java"; + createFile(serviceImpl, filePathStr); + return filePathStr; + } + + public static String createService(String actModulePath, String fileName, String service) { + String pathStr = actModulePath + File.separator + "service" + File.separator; + String filePathStr = pathStr + fileName + "Service.java"; + createFile(service, filePathStr); + return filePathStr; + } + + public static String createEntity(String actModulePath, String fileName, String entity) { + String pathStr = actModulePath + File.separator + "entity" + File.separator; + String filePathStr = pathStr + fileName + "Entity.java"; + createFile(entity, filePathStr); + return filePathStr; + } + + public static String createController(String actModulePath, String fileName, String controller) { + String pathStr = actModulePath + File.separator + "controller" + File.separator + "admin" + File.separator; + String filePathStr = pathStr + "Admin" + fileName + "Controller.java"; + createFile(controller, filePathStr); + return filePathStr; + } + + public static String createModule(String modulesPath, String module) { + String pathStr = modulesPath + File.separator + module; + PathUtils.noExistsMk(pathStr); + return pathStr; + } + + public static boolean compileAndSave(String sourceFile) { + // 获取系统 Java 编译器 + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + + // 获取标准文件管理器 + try (StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null)) { + + // 设置编译输出目录 + fileManager.setLocation(StandardLocation.CLASS_OUTPUT, List.of(new File("target" + File.separator + "classes"))); + + // 获取源文件 + List javaFiles = List.of(new File(sourceFile)); + Iterable compilationUnits = fileManager.getJavaFileObjectsFromFiles(javaFiles); + + // 创建编译任务 + JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, null, null, null, compilationUnits); + // 执行编译任务 + return task.call(); + } catch (IOException e) { + e.printStackTrace(); + return false; + } + } + + public static void compilerEntityTableDef(String actModulePath, String fileName, String entityPath, List javaPathList) { + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + try (StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null)) { + Iterable compilationUnits = fileManager.getJavaFileObjects( + entityPath); + // 设置注解处理器 + Iterable processors = List.of(new MybatisFlexProcessor()); + // 添加 -proc:only 选项 + List options = List.of("-proc:only"); + JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, null, options, + null, compilationUnits); + task.setProcessors(processors); + task.call(); + compilationUnits = fileManager.getJavaFileObjects( + javaPathList.toArray(new String[0])); + // 设置编译输出目录 + fileManager.setLocation(StandardLocation.CLASS_OUTPUT, List.of(new File("target/classes"))); + + task = compiler.getTask(null, fileManager, null, null, null, compilationUnits); + String pathStr = actModulePath + File.separator + "entity" + File.separator + "table" + File.separator; + String filePathStr = pathStr + fileName + "EntityTableDef.java"; + // 需在entity之后加载 + javaPathList.add(1, filePathStr); + boolean success = task.call(); + if (success) { + System.out.println("Compilation and annotation processing completed successfully."); + // 指定源文件夹和目标文件夹 + File sourceDir = new File("com"); + File destinationDir = new File(PathUtils.getTargetGeneratedAnnotations()); + // 确保目标文件夹存在 + destinationDir.mkdirs(); + // 移动源文件夹内容到目标文件夹 + if (sourceDir.exists()) { + FileUtil.move(sourceDir, destinationDir, true); + } + if (countFiles(sourceDir) <= 1) { + FileUtil.clean(sourceDir); + FileUtil.del(sourceDir); + } + } else { + System.out.println("Compilation and annotation processing failed."); + } + } catch (IOException e) { + log.error("compilerEntityTableDefError", e); + } + } + private static int countFiles(File directory) { + File[] files = directory.listFiles(); + if (files == null) { + return 0; + } + + int count = 0; + for (File file : files) { + if (file.isFile()) { + count++; + } else if (file.isDirectory()) { + count += countFiles(file); + } + // If more than one file is found, no need to continue counting + if (count > 1) { + break; + } + } + return count; + } +} diff --git a/cool-admin-java/src/main/java/com/cool/core/util/ConvertUtil.java b/cool-admin-java/src/main/java/com/cool/core/util/ConvertUtil.java new file mode 100644 index 0000000..be72f86 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/util/ConvertUtil.java @@ -0,0 +1,257 @@ +package com.cool.core.util; + +import cn.hutool.core.convert.Convert; +import cn.hutool.core.util.ReflectUtil; +import cn.hutool.core.util.StrUtil; + +import java.io.*; +import java.lang.reflect.Field; +import java.util.Collections; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.springframework.web.multipart.MultipartFile; + +/** + * 转换 + */ +public class ConvertUtil { + + /** + * 对象转数组 + * + * @param obj + * @return + */ + public static byte[] toByteArray(Object obj) { + byte[] bytes = null; + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + try { + ObjectOutputStream oos = new ObjectOutputStream(bos); + oos.writeObject(obj); + oos.flush(); + bytes = bos.toByteArray(); + oos.close(); + bos.close(); + } catch (IOException ex) { + ex.printStackTrace(); + } + return bytes; + } + + /** + * 数组转对象 + * + * @param bytes + * @return + */ + public static Object toObject(byte[] bytes) { + Object obj = null; + try { + ByteArrayInputStream bis = new ByteArrayInputStream(bytes); + ObjectInputStream ois = new ObjectInputStream(bis); + obj = ois.readObject(); + ois.close(); + bis.close(); + } catch (IOException | ClassNotFoundException ex) { + ex.printStackTrace(); + } + return obj; + } + + public static MultipartFile convertToMultipartFile(File file) { + FileInputStream inputStream = null; + try { + inputStream = new FileInputStream(file); + return new SimpleMultipartFile(file.getName(), inputStream); + } catch (FileNotFoundException e) { + e.printStackTrace(); + if (inputStream != null) { + try { + inputStream.close(); + } catch (IOException ex) { + ex.printStackTrace(); + } + } + return null; + } + } + + // 简单的MultipartFile实现,用于模拟Spring中的MultipartFile对象 + static class SimpleMultipartFile implements MultipartFile { + + private String filename; + private InputStream inputStream; + + public SimpleMultipartFile(String filename, InputStream inputStream) { + this.filename = filename; + this.inputStream = inputStream; + } + + @Override + public String getName() { + return null; + } + + @Override + public String getOriginalFilename() { + return filename; + } + + @Override + public String getContentType() { + return "application/octet-stream"; + } + + @Override + public boolean isEmpty() { + return false; + } + + @Override + public long getSize() { + try { + return inputStream.available(); + } catch (IOException e) { + e.printStackTrace(); + return 0; + } + } + + @Override + public byte[] getBytes() throws IOException { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + byte[] buffer = new byte[1024]; + int len; + while ((len = inputStream.read(buffer)) != -1) { + output.write(buffer, 0, len); + } + return output.toByteArray(); + } + + @Override + public InputStream getInputStream() throws IOException { + return inputStream; + } + + @Override + public void transferTo(File dest) throws IOException, IllegalStateException { + try (FileOutputStream outputStream = new FileOutputStream(dest)) { + byte[] buffer = new byte[1024]; + int len; + while ((len = inputStream.read(buffer)) != -1) { + outputStream.write(buffer, 0, len); + } + } finally { + if (inputStream != null) { + inputStream.close(); + } + } + } + } + + + + /** + * /admin/goods 转 AdminGoods + */ + public static String pathToClassName(String path) { + // 按斜杠分割字符串 + String[] parts = path.split("/"); + StringBuilder className = new StringBuilder(); + for (String part : parts) { + // 将每个部分的首字母大写,并追加到 StringBuilder 中 + className.append(StrUtil.upperFirst(part)); + } + return className.toString(); + } + + public static String extractController2Path(String prefix, String className) { + Pattern pattern = Pattern.compile("([A-Za-z0-9]+)Controller$"); + Matcher matcher = pattern.matcher(className); + + if (matcher.find()) { + String extracted = matcher.group(1); + + // 将前缀拆分为单词数组 + String[] prefixWords = splitCamelCase(prefix); + String[] classWords = splitCamelCase(extracted); + + // 从前缀和类名中逐个匹配并去除匹配的部分 + int i = 0; + for (int j = 0; i < prefixWords.length; j++) { + if (j >= classWords.length) { + break; + } + for (String prefixWord : prefixWords) { + if (prefixWord.equalsIgnoreCase(classWords[i])) { + i++; + break; + } + } + } + // 从当前位置开始,拼接剩余部分 + return String.join("/", java.util.Arrays.copyOfRange(classWords, i, classWords.length)).toLowerCase(); + } + return ""; + } + + // 拆分驼峰命名的字符串为单词数组 + private static String[] splitCamelCase(String input) { + return input.split("(?<=.)(?=[A-Z])"); + } + + /** + * 将给定的字段值转换为可序列化的形式 + * 此方法旨在将一个对象的特定字段值转换为其相应的可序列化类型 + * 它在序列化和反序列化过程中特别有用,确保字段值可以被正确处理 + * + * @param fieldName 字段名称,用于查找字段类型 + * @param fieldValue 待转换的字段值 + * @param clazz 包含该字段的类 + * @return 转换后的可序列化字段值,如果无法确定字段类型,则返回原始值 + */ + public static Object convertByClass(String fieldName, Object fieldValue, Class clazz) { + // 检查输入参数是否为空,如果字段名或字段值为空,则直接返回字段值 + if (fieldName == null || fieldValue == null) { + return fieldValue; + } + + // 获取字段类型 + Class fieldType = getFieldType(clazz, fieldName); + // 如果字段类型为空,则直接返回字段值 + if (fieldType == null) { + return fieldValue; + } + + // 使用Convert类的convert方法将字段值转换为字段类型 + return Convert.convert(fieldType, fieldValue); + } + + public static List covertListByClass(String fieldName, List fieldValue, Class clazz) { + // 检查输入参数是否为空,如果字段名或字段值为空,则直接返回字段值 + if (fieldName == null || fieldValue == null) { + return fieldValue; + } + + // 获取字段类型 + Class fieldType = getFieldType(clazz, fieldName); + // 如果字段类型为空,则直接返回字段值 + if (fieldType == null) { + return fieldValue; + } + + return Collections.singletonList(Convert.toList(fieldType, fieldValue)); + } + /** + * 获取指定类中指定字段的类型 + * + * @param clazz 目标类 + * @param fieldName 字段名称 + * @return 字段的类型 Class,如果字段不存在则返回 null + */ + public static Class getFieldType(Class clazz, String fieldName) { + Field field = ReflectUtil.getField(clazz, fieldName); + return field != null ? field.getType() : null; + } +} \ No newline at end of file diff --git a/cool-admin-java/src/main/java/com/cool/core/util/CoolPluginInvokers.java b/cool-admin-java/src/main/java/com/cool/core/util/CoolPluginInvokers.java new file mode 100644 index 0000000..2a2fdf2 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/util/CoolPluginInvokers.java @@ -0,0 +1,165 @@ +package com.cool.core.util; + +import cn.hutool.json.JSONUtil; +import com.cool.core.exception.CoolPreconditions; +import com.cool.core.plugin.consts.PluginConsts; +import com.cool.core.plugin.service.DynamicJarLoaderService; +import com.cool.modules.plugin.entity.PluginInfoEntity; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Arrays; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.ApplicationContext; + +/** + * 插件调用封装 + */ +@Slf4j +public class CoolPluginInvokers { + + private static final DynamicJarLoaderService dynamicJarLoaderService = SpringContextUtils + .getBean(DynamicJarLoaderService.class); + + /** + * 插件默认调用入口 + */ + public static Object invokePlugin(String key, String... params) { + return invoke(key, PluginConsts.invokePluginMethodName, params); + } + + /** + * 设置插件配置信息 + */ + public static void setPluginJson(String key, PluginInfoEntity entity) { + invoke(key, PluginConsts.setPluginJson, JSONUtil.toJsonStr(entity.getPluginJson())); + setApplicationContext(key); + } + + /** + * 设置 ApplicationContext 到插件类中 + */ + public static void setApplicationContext(String key) { + ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader(); + try { + Thread.currentThread() + .setContextClassLoader(dynamicJarLoaderService.getDynamicJarClassLoader(key)); + Object beanInstance = dynamicJarLoaderService.getBeanInstance(key); + Method method = beanInstance.getClass().getSuperclass() + .getMethod(PluginConsts.setApplicationContext, + ApplicationContext.class); + method.invoke(beanInstance, SpringContextUtils.applicationContext); + } catch (Exception e) { + log.error("setApplicationContext err", e); + } finally { + Thread.currentThread().setContextClassLoader(originalClassLoader); + } + } + + /** + * 反射调用插件 + * + * @param key 插件key + * @param methodName 插件方法 + * @param params 参数 + */ + public static Object invoke(String key, String methodName, Object... params) { + Object beanInstance = dynamicJarLoaderService.getBeanInstance(key); + CoolPreconditions.checkEmpty(beanInstance, "未找到该插件:{}, 请前往插件市场进行安装",key); + ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader(); + try { + // 设置当前线程的上下文类加载器为插件的类加载器 + Thread.currentThread() + .setContextClassLoader(dynamicJarLoaderService.getDynamicJarClassLoader(key)); + log.info("调用插件类: {}, 方法: {} 参数: {}", key, methodName, params); + return invoke(beanInstance, methodName, params); + } catch (Exception e) { + log.error("调用插件{}.{}失败", key, methodName, e); + CoolPreconditions.alwaysThrow("调用插件{}.{}失败 {}", key, methodName, e.getMessage()); + } finally { + Thread.currentThread().setContextClassLoader(originalClassLoader); + } + return null; + } + + /** + * 反射调用插件 + * + * @param beanInstance 插件实例对象 + * @param methodName 插件方法 + * @param params 参数 + */ + private static Object invoke(Object beanInstance, String methodName, Object[] params) + throws InvocationTargetException, IllegalAccessException { + Class[] paramTypes = Arrays.stream(params).map(Object::getClass) + .toArray(Class[]::new); + Method method = findMethod(beanInstance.getClass(), methodName, paramTypes); + CoolPreconditions.check(method == null, "No such method: {} with parameters {}", methodName, + Arrays.toString(paramTypes)); + if (method.isVarArgs()) { + // 处理可变参数调用 + int varArgIndex = method.getParameterTypes().length - 1; + Object[] varArgs = (Object[]) java.lang.reflect.Array.newInstance( + method.getParameterTypes()[varArgIndex].getComponentType(), + params.length - varArgIndex); + System.arraycopy(params, varArgIndex, varArgs, 0, varArgs.length); + Object[] methodArgs = new Object[varArgIndex + 1]; + System.arraycopy(params, 0, methodArgs, 0, varArgIndex); + methodArgs[varArgIndex] = varArgs; + return method.invoke(beanInstance, methodArgs); + } else { + // 正常调用 + return method.invoke(beanInstance, params); + } + } + + // 查找方法,包括处理可变参数 + private static Method findMethod(Class clazz, String methodName, Class... paramTypes) { + try { + return clazz.getMethod(methodName, paramTypes); + } catch (NoSuchMethodException e) { + // Try to find a varargs method + for (Method method : clazz.getMethods()) { + if (method.getName().equals(methodName) && isAssignable(paramTypes, + method.getParameterTypes(), method.isVarArgs())) { + return method; + } + } + // If not found, try to find in superclass + if (clazz.getSuperclass() != null) { + return findMethod(clazz.getSuperclass(), methodName, paramTypes); + } + } + return null; + } + + private static boolean isAssignable(Class[] paramTypes, Class[] methodParamTypes, + boolean isVarArgs) { + if (isVarArgs) { + if (paramTypes.length < methodParamTypes.length - 1) { + return false; + } + for (int i = 0; i < methodParamTypes.length - 1; i++) { + if (!methodParamTypes[i].isAssignableFrom(paramTypes[i])) { + return false; + } + } + Class varArgType = methodParamTypes[methodParamTypes.length - 1].getComponentType(); + for (int i = methodParamTypes.length - 1; i < paramTypes.length; i++) { + if (!varArgType.isAssignableFrom(paramTypes[i])) { + return false; + } + } + return true; + } else { + if (paramTypes.length != methodParamTypes.length) { + return false; + } + for (int i = 0; i < paramTypes.length; i++) { + if (!methodParamTypes[i].isAssignableFrom(paramTypes[i])) { + return false; + } + } + return true; + } + } +} diff --git a/cool-admin-java/src/main/java/com/cool/core/util/CoolSecurityUtil.java b/cool-admin-java/src/main/java/com/cool/core/util/CoolSecurityUtil.java new file mode 100644 index 0000000..5173cca --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/util/CoolSecurityUtil.java @@ -0,0 +1,110 @@ +package com.cool.core.util; + +import cn.hutool.extra.spring.SpringUtil; +import cn.hutool.json.JSONObject; +import com.cool.core.cache.CoolCache; +import com.cool.core.enums.UserTypeEnum; +import com.cool.core.exception.CoolPreconditions; +import com.cool.core.security.jwt.JwtUser; +import com.cool.modules.base.entity.sys.BaseSysUserEntity; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UserDetails; + +/** + * Security 工具类 + */ +public class CoolSecurityUtil { + + private static final CoolCache coolCache = SpringUtil.getBean(CoolCache.class); + + /***************后台********************/ + /** + * 获取后台登录的用户名 + */ + public static String getAdminUsername() { + return SecurityContextHolder.getContext().getAuthentication().getName(); + } + + /** + * 获得jwt中的信息 + * + * @param requestParams 请求参数 + * @return jwt + */ + public static JSONObject getAdminUserInfo(JSONObject requestParams) { + JSONObject tokenInfo = requestParams.getJSONObject("tokenInfo"); + if (tokenInfo != null) { + tokenInfo.set("department", + coolCache.get("admin:department:" + tokenInfo.get("userId"))); + tokenInfo.set("roleIds", coolCache.get("admin:roleIds:" + tokenInfo.get("userId"))); + } + return tokenInfo; + } + + public static Long getTenantId(JSONObject requestParams) { + JSONObject tokenInfo = requestParams.getJSONObject("tokenInfo"); + if (tokenInfo != null) { + return tokenInfo.getLong("tenantId"); + } + return null; + } + + /** + * 后台账号退出登录 + * + * @param adminUserId 用户ID + * @param username 用户名 + */ + public static void adminLogout(Long adminUserId, String username) { + coolCache.del("admin:department:" + adminUserId, "admin:passwordVersion:" + adminUserId, + "admin:userInfo:" + adminUserId, "admin:userDetails:" + username); + } + + /** + * 后台账号退出登录 + * + * @param userEntity 用户 + */ + public static void adminLogout(BaseSysUserEntity userEntity) { + adminLogout(userEntity.getId(), userEntity.getUsername()); + } + + + /** + * 获取当前用户id + */ + public static Long getCurrentUserId() { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + if (authentication != null) { + Object principal = authentication.getPrincipal(); + if (principal instanceof UserDetails) { + return ((JwtUser) principal).getUserId(); + } + } + CoolPreconditions.check(true, 401, "未登录"); + return null; + } + + /** + * 获取当前用户类型 + */ + public static UserTypeEnum getCurrentUserType() { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + if (authentication != null) { + Object principal = authentication.getPrincipal(); + if (principal instanceof UserDetails) { + return ((JwtUser) principal).getUserTypeEnum(); + } + } + // 还未登录,未知类型 + return UserTypeEnum.UNKNOWN; + } + + /** + * app退出登录,移除缓存信息 + */ + public static void appLogout() { + coolCache.del("app:userDetails"+ getCurrentUserId()); + } +} diff --git a/cool-admin-java/src/main/java/com/cool/core/util/DatabaseDialectUtils.java b/cool-admin-java/src/main/java/com/cool/core/util/DatabaseDialectUtils.java new file mode 100644 index 0000000..f4f2554 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/util/DatabaseDialectUtils.java @@ -0,0 +1,56 @@ +package com.cool.core.util; +import com.cool.core.exception.CoolPreconditions; +import org.dromara.autotable.core.constants.DatabaseDialect; +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.SQLException; +import javax.sql.DataSource; + +/** + * 获取数据库方言 + */ +public class DatabaseDialectUtils { + private static String dialect; + + public static String getDatabaseDialect(DataSource dataSource) { + if (dialect == null) { + dialect = determineDatabaseType(dataSource); + } + return dialect; + } + + public static boolean isPostgresql() { + DataSource dataSource = SpringContextUtils.getBean(DataSource.class); + return DatabaseDialect.PostgreSQL.equals(getDatabaseDialect(dataSource)); + } + + public static boolean isPostgresql(DataSource dataSource) { + return DatabaseDialect.PostgreSQL.equals(getDatabaseDialect(dataSource)); + } + + + private static String determineDatabaseType(DataSource dataSource) { + // 从 DataSource 获取连接 + try (Connection connection = dataSource.getConnection()) { + // 获取元数据 + DatabaseMetaData metaData = connection.getMetaData(); + String productName = metaData.getDatabaseProductName(); + + return inferDatabaseTypeFromProductName(productName); + } catch (SQLException e) { + throw new RuntimeException("Failed to determine database dialect", e); + } + } + + private static String inferDatabaseTypeFromProductName(String productName) { + if (productName.startsWith(DatabaseDialect.MySQL)) { + return DatabaseDialect.MySQL; + } else if (productName.startsWith(DatabaseDialect.PostgreSQL)) { + return DatabaseDialect.PostgreSQL; + } else if (productName.startsWith(DatabaseDialect.SQLite)) { + return DatabaseDialect.SQLite; + } + CoolPreconditions.alwaysThrow("暂不支持!"); + return "unknown"; + } +} diff --git a/cool-admin-java/src/main/java/com/cool/core/util/EntityUtils.java b/cool-admin-java/src/main/java/com/cool/core/util/EntityUtils.java new file mode 100644 index 0000000..b564a0c --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/util/EntityUtils.java @@ -0,0 +1,121 @@ +package com.cool.core.util; + +import cn.hutool.core.annotation.AnnotationUtil; +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.lang.Editor; +import cn.hutool.core.util.ObjUtil; +import com.mybatisflex.annotation.Table; +import com.mybatisflex.core.query.QueryColumn; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import org.springframework.core.io.Resource; +import org.springframework.core.io.support.PathMatchingResourcePatternResolver; + +public class EntityUtils { + + private static Map> TABLE_MAP; + + public static Set findEntityClassName() { + Set entitySet = new HashSet<>(); + PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); + Resource[] resources = null; + try { + resources = resolver.getResources("classpath*:com/cool/**/entity/**/*Entity.class"); + for (Resource r : resources) { + String path = r.getURL().getPath(); + String className = path.substring(path.indexOf("com/cool"), + path.lastIndexOf('.')).replace('/', '.'); + entitySet.add(className); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + return entitySet; + } + + public static Map> findTableMap() { + if (ObjUtil.isEmpty(TABLE_MAP)) { + init(); + } + return TABLE_MAP; + } + + private static void init() { + Set classNames = EntityUtils.findEntityClassName(); + TABLE_MAP = new HashMap<>(); + classNames.forEach(className -> { + Class entityClass; + try { + entityClass = Class.forName(className); + Table tableAnnotation = AnnotationUtil.getAnnotation(entityClass, Table.class); + // key表名,value 实体对象 + TABLE_MAP.put(tableAnnotation.value(), entityClass); + } catch (Exception e) { + // do nothing + } + }); + } + + /** + * 获取实体类及其父类的字段名数组(排除指定字段) + * + * @return 字段名数组 + */ + public static QueryColumn[] getFieldNamesWithSuperClass(QueryColumn[] queryColumns, + String... excludeNames) { + return getFieldNamesListWithSuperClass(queryColumns, excludeNames).toArray( + new QueryColumn[0]); + } + + public static List getFieldNamesListWithSuperClass(QueryColumn[] queryColumns, + String... excludeNames) { + ArrayList excludeList = new ArrayList<>(List.of(excludeNames)); + return Arrays.stream(queryColumns).toList().stream() + .filter(o -> !excludeList.contains(o.getName())).toList(); + } + + /** + * 将bean的部分属性转换成map
+ * 可选拷贝哪些属性值,默认是不忽略值为{@code null}的值的。 + * + * @param bean bean + * @param ignoreProperties 需要忽略拷贝的属性值,{@code null}或空表示拷贝所有值 + * @return Map + * @since 5.8.0 + */ + public static Map toMap(Object bean, String... ignoreProperties) { + int mapSize = 16; + Editor keyEditor = null; + final Set propertiesSet = CollUtil.set(false, ignoreProperties); + propertiesSet.add("queryWrapper"); + mapSize = ignoreProperties.length; + keyEditor = property -> !propertiesSet.contains(property) ? property : null; + // 指明了要复制的属性 所以不忽略null值 + return BeanUtil.beanToMap(bean, new LinkedHashMap<>(mapSize, 1), false, keyEditor); + } + + /** + * 检查字段名是否在排除列表中 + * + * @param fieldName 要检查的字段名 + * @param excludeNames 排除的字段名数组 + * @return 是否在排除列表中 + */ + private static boolean isExcluded(String fieldName, String[] excludeNames) { + for (String excludeName : excludeNames) { + if (fieldName.equals(excludeName)) { + return true; + } + } + return false; + } + +} \ No newline at end of file diff --git a/cool-admin-java/src/main/java/com/cool/core/util/I18nUtil.java b/cool-admin-java/src/main/java/com/cool/core/util/I18nUtil.java new file mode 100644 index 0000000..13d28d5 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/util/I18nUtil.java @@ -0,0 +1,125 @@ +package com.cool.core.util; + +import cn.hutool.core.io.FileUtil; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import java.io.File; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicReference; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.context.request.RequestContextHolder; + +@Slf4j +@Component +public class I18nUtil { + + public static final String MSG_PREFIX = "msg_"; + public static final String MENU_PREFIX = "menu_"; + public static final String DICT_INFO_PREFIX = "dictInfo_"; + public static final String DICT_TYPE_PREFIX = "dictType_"; + + public static boolean enable = false; + + public static String path; + public static String getLanguage() { + RequestAttributes attributes = RequestContextHolder.getRequestAttributes(); + if (attributes == null) { + return null; + } + return (String) attributes.getAttribute("cool-language", RequestAttributes.SCOPE_REQUEST); + } + + private static final Map data = new ConcurrentHashMap<>(); + + private void load(String key, File file) { + try { + String content = FileUtil.readUtf8String(file); + data.put(key, JSONUtil.parseObj(content)); + } catch (Exception e) { + log.error("读取国际化文件失败", e); + } + } + + public boolean exist(String name) { + // 获取该目录下所有的 .json 文件 + List jsonFiles = FileUtil.loopFiles(getPath(), file -> + file.isFile() && file.getName().endsWith(".json") + ); + AtomicReference flag = new AtomicReference<>(false); + jsonFiles.forEach(file -> { + String parentName = file.getParentFile().getName(); + String key = parentName + "_" + file.getName().replace(".json", ""); + if (key.equals(name)) { + flag.set(true); + // 加载 + load(key, file); + } + }); + return flag.get(); + } + + public static String getI18nMenu(String name) { + return getI18n(name, MENU_PREFIX); + } + + public static String getI18nMsg(String name) { + return getI18n(name, MSG_PREFIX); + } + + public static String getI18nDictInfo(String name) { + return getI18n(name, DICT_INFO_PREFIX); + } + public static String getI18nDictType(String name) { + return getI18n(name, DICT_TYPE_PREFIX); + } + private static String getI18n(String name, String prefix) { + if (!enable) { + return name; + } + String language = I18nUtil.getLanguage(); + if (language == null) { + return name; + } + JSONObject jsonObject = data.get(prefix + language); + if (jsonObject == null) { + return name; + } + String str = jsonObject.getStr(name); + if (str == null) { + return name; + } + return str; + } + + public void update(String key, JSONObject object) { + data.put(key, object); + String[] split = key.split("_"); + String absolutePath = getPath(); + File file = FileUtil.file(absolutePath, split[0], split[1] + ".json"); + // 确保父目录存在 + FileUtil.mkParentDirs(file); + // 写入内容 + FileUtil.writeUtf8String(JSONUtil.toJsonStr(object), file); + } + + private String getPath() { + String absolutePath = path; + if (!PathUtils.isAbsolutePath(absolutePath)) { + absolutePath = PathUtils.getUserDir() + File.separator + absolutePath; + } + return absolutePath; + } + + public void clear() { + data.clear(); + List jsonFiles = FileUtil.loopFiles(getPath(), file -> + file.isFile() && file.getName().endsWith(".json") + ); + jsonFiles.forEach(File::delete); + enable = false; + } +} \ No newline at end of file diff --git a/cool-admin-java/src/main/java/com/cool/core/util/IPUtils.java b/cool-admin-java/src/main/java/com/cool/core/util/IPUtils.java new file mode 100644 index 0000000..ed33d80 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/util/IPUtils.java @@ -0,0 +1,46 @@ +package com.cool.core.util; + +import cn.hutool.core.util.StrUtil; +import jakarta.servlet.http.HttpServletRequest; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + + +/** + * IP地址 + */ +@Slf4j +@Component +public class IPUtils { + + /** + * 获取IP地址 + *

+ * 使用Nginx等反向代理软件, 则不能通过request.getRemoteAddr()获取IP地址 + * 如果使用了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP地址,X-Forwarded-For中第一个非unknown的有效IP字符串,则为真实IP地址 + */ + public String getIpAddr(HttpServletRequest request) { + String ip = null; + try { + ip = request.getHeader("x-forwarded-for"); + if (StrUtil.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("Proxy-Client-IP"); + } + if (StrUtil.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("WL-Proxy-Client-IP"); + } + if (StrUtil.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("HTTP_CLIENT_IP"); + } + if (StrUtil.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("HTTP_X_FORWARDED_FOR"); + } + if (StrUtil.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) { + ip = request.getRemoteAddr(); + } + } catch (Exception e) { + log.error("IP extraction error", e); + } + return ip; + } +} diff --git a/cool-admin-java/src/main/java/com/cool/core/util/MapExtUtil.java b/cool-admin-java/src/main/java/com/cool/core/util/MapExtUtil.java new file mode 100644 index 0000000..3179ea2 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/util/MapExtUtil.java @@ -0,0 +1,30 @@ +package com.cool.core.util; + +import cn.hutool.core.map.MapUtil; +import cn.hutool.core.util.ObjectUtil; + +import java.util.Map; + +public class MapExtUtil extends MapUtil { + + /** + * 比较两个map key 和 value 是否一致 + */ + public static boolean compareMaps(Map map1, Map map2) { + if (ObjectUtil.isEmpty(map1) || ObjectUtil.isEmpty(map2)) { + return true; + } + if (map1.size() != map2.size()) { + return false; + } + for (Map.Entry entry : map1.entrySet()) { + if (!map2.containsKey(entry.getKey())) { + return false; + } + if (!ObjectUtil.equal(entry.getValue(), map2.get(entry.getKey()))) { + return false; + } + } + return true; + } +} diff --git a/cool-admin-java/src/main/java/com/cool/core/util/MappingAlgorithm.java b/cool-admin-java/src/main/java/com/cool/core/util/MappingAlgorithm.java new file mode 100644 index 0000000..783aa77 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/util/MappingAlgorithm.java @@ -0,0 +1,21 @@ +package com.cool.core.util; + +/** + * 自定义映射算法 + * 将 ID 转换为一个混淆形式的数字,然后能够逆向转换回原始 ID。 + * 场景:混淆订单id + */ +public class MappingAlgorithm { + + private static final long ENCRYPTION_KEY = 123456789L; // 任意密钥 + + // 将 ID 转换为混淆的数字 + public static long encrypt(long id) { + return id ^ ENCRYPTION_KEY; // 使用异或操作进行混淆 + } + + // 将混淆的数字恢复为原始的 ID + public static long decrypt(long encryptedId) { + return encryptedId ^ ENCRYPTION_KEY; // 逆操作恢复原始 ID + } +} diff --git a/cool-admin-java/src/main/java/com/cool/core/util/PathUtils.java b/cool-admin-java/src/main/java/com/cool/core/util/PathUtils.java new file mode 100644 index 0000000..0f61184 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/util/PathUtils.java @@ -0,0 +1,70 @@ +package com.cool.core.util; + +import cn.hutool.core.io.file.PathUtil; +import cn.hutool.core.text.AntPathMatcher; +import com.cool.CoolApplication; +import java.io.File; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; + +public class PathUtils { + private static final AntPathMatcher antPathMatcher = new AntPathMatcher(); + + public static boolean isAbsolutePath(String pathStr) { + Path path = Paths.get(pathStr); + return path.isAbsolute(); + } + + public static String getUserDir() { + return System.getProperty("user.dir"); + } + + public static String getModulesPath() { + return getUserDir() + getSrcMainJava() + File.separator + CoolApplication.class.getPackageName() + .replace(".", File.separator) + File.separator + "modules"; + } + + public static String getSrcMainJava() { + return File.separator + "src" + File.separator + "main" + File.separator + "java"; + } + public static String getTargetGeneratedAnnotations() { + return "target" + File.separator + "generated-sources" + File.separator + "annotations"; + } + + public static String getClassName(String filePath) { + // 定位 "/src/main/java" 在路径中的位置 + int srcMainJavaIndex = filePath.indexOf(getSrcMainJava()); + if (srcMainJavaIndex == -1) { + throw new IllegalArgumentException("File path does not contain 'src/main/java'"); + } + + // 提取 "src/main/java" 之后的路径 + // 将文件分隔符替换为包分隔符 + return filePath.substring(srcMainJavaIndex + ("src" + File.separator + "main" + File.separator + "java").length() + 2) + .replace(File.separator, ".").replace(".java", ""); + } + + /** + * 路径不存在创建 + */ + public static void noExistsMk(String pathStr) { + Path path = Paths.get(pathStr); + if (PathUtil.exists(path, false)) { + PathUtil.mkParentDirs(path); + } + } + + /** + * 判断给定的请求URI是否匹配列表中的任意一个URL模式 + * 使用Ant风格的路径匹配来处理URL模式,提供了一种通配符匹配的方法 + * + * @param urls 待匹配的URL模式列表 + * @param requestURI 请求的URI + * @return 如果请求URI匹配列表中的任意一个URL模式,则返回true;否则返回false + */ + public static boolean isMatch(List urls, String requestURI) { + return urls.stream() + .anyMatch(url -> antPathMatcher.match(url, requestURI)); + } +} diff --git a/cool-admin-java/src/main/java/com/cool/core/util/SpringContextUtils.java b/cool-admin-java/src/main/java/com/cool/core/util/SpringContextUtils.java new file mode 100644 index 0000000..f026531 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/util/SpringContextUtils.java @@ -0,0 +1,45 @@ +package com.cool.core.util; + +import java.util.Map; +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * Spring Context 工具类 + */ +@Component +public class SpringContextUtils implements ApplicationContextAware { + + public static ApplicationContext applicationContext; + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + SpringContextUtils.applicationContext = applicationContext; + } + + public static Object getBean(String name) { + return applicationContext.getBean(name); + } + + public static T getBean(Class requiredType) { + return applicationContext.getBean(requiredType); + } + + public static boolean containsBean(String name) { + return applicationContext.containsBean(name); + } + + public static boolean isSingleton(String name) { + return applicationContext.isSingleton(name); + } + + public static Class getType(String name) { + return applicationContext.getType(name); + } + + public static Map getBeansOfType(Class requiredType) { + return applicationContext.getBeansOfType(requiredType); + } +} \ No newline at end of file diff --git a/cool-admin-java/src/main/java/com/cool/core/util/TenantUtil.java b/cool-admin-java/src/main/java/com/cool/core/util/TenantUtil.java new file mode 100644 index 0000000..66d20e4 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/core/util/TenantUtil.java @@ -0,0 +1,14 @@ +package com.cool.core.util; + +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.context.request.RequestContextHolder; + +public class TenantUtil { + public static Long getTenantId() { + RequestAttributes attributes = RequestContextHolder.getRequestAttributes(); + if (attributes == null) { + return null; + } + return (Long) attributes.getAttribute("tenantId", RequestAttributes.SCOPE_REQUEST); + } +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/controller/admin/AdminBaseCodingController.java b/cool-admin-java/src/main/java/com/cool/modules/base/controller/admin/AdminBaseCodingController.java new file mode 100644 index 0000000..c1cce5c --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/controller/admin/AdminBaseCodingController.java @@ -0,0 +1,43 @@ +package com.cool.modules.base.controller.admin; + + +import cn.hutool.json.JSONArray; +import cn.hutool.json.JSONObject; +import com.cool.core.annotation.CoolRestController; +import com.cool.core.annotation.TokenIgnore; +import com.cool.core.exception.CoolPreconditions; +import com.cool.core.request.R; +import com.cool.modules.base.dto.sys.CodeContentDto; +import com.cool.modules.base.service.sys.BaseCodingService; +import io.swagger.v3.oas.annotations.Operation; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestAttribute; + +/** + * ai 编码 + */ +@CoolRestController +@RequiredArgsConstructor +public class AdminBaseCodingController { + + private final BaseCodingService baseCodingService; + + @TokenIgnore + @Operation(summary = "获取模块目录结构", description = "获取模块目录结构") + @GetMapping("/getModuleTree") + public R getModuleTree() { + return R.ok(baseCodingService.getModuleTree()); + } + + @TokenIgnore + @Operation(summary = "创建代码", description = "创建代码") + @PostMapping("/createCode") + public R createCode(@RequestAttribute JSONObject requestParams) { + JSONArray codes = requestParams.get("codes", JSONArray.class); + CoolPreconditions.checkEmpty(codes); + this.baseCodingService.createCode(codes.toList(CodeContentDto.class)); + return R.ok(); + } +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/controller/admin/AdminBaseCommController.java b/cool-admin-java/src/main/java/com/cool/modules/base/controller/admin/AdminBaseCommController.java new file mode 100644 index 0000000..451ab3c --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/controller/admin/AdminBaseCommController.java @@ -0,0 +1,107 @@ +package com.cool.modules.base.controller.admin; + +import cn.hutool.core.lang.Dict; +import com.cool.core.annotation.CoolRestController; +import com.cool.core.annotation.TokenIgnore; +import com.cool.core.eps.CoolEps; +import com.cool.core.file.FileUploadStrategyFactory; +import com.cool.core.request.R; +import com.cool.core.util.I18nUtil; +import com.cool.modules.base.entity.sys.BaseSysMenuEntity; +import com.cool.modules.base.entity.sys.BaseSysUserEntity; +import com.cool.modules.base.service.sys.BaseSysLoginService; +import com.cool.modules.base.service.sys.BaseSysPermsService; +import com.cool.modules.base.service.sys.BaseSysUserService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletRequest; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestAttribute; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestPart; +import org.springframework.web.multipart.MultipartFile; + +/** + * 系统通用接口, 每个人都有权限操作 + */ +@RequiredArgsConstructor +@Tag(name = "系统通用", description = "系统通用") +@CoolRestController() +public class AdminBaseCommController { + + final private BaseSysPermsService baseSysPermsService; + + final private BaseSysUserService baseSysUserService; + + final private BaseSysLoginService baseSysLoginService; + + final private CoolEps coolEps; + + final private FileUploadStrategyFactory fileUploadStrategyFactory; + + @TokenIgnore + @Operation(summary = "实体信息与路径", description = "系统所有的实体信息与路径,供前端自动生成代码与服务") + @GetMapping("/eps") + public R eps() { + return R.ok(coolEps.getAdmin()); + } + + @Operation(summary = "个人信息") + @GetMapping("/person") + public R person(@RequestAttribute() Long adminUserId) { + BaseSysUserEntity baseSysUserEntity = baseSysUserService.getById(adminUserId); + baseSysUserEntity.setPassword(null); + baseSysUserEntity.setPasswordV(null); + return R.ok(baseSysUserEntity); + } + + @Operation(summary = "修改个人信息") + @PostMapping("/personUpdate") + public R personUpdate(@RequestAttribute Long adminUserId, @RequestBody Dict body) { + baseSysUserService.personUpdate(adminUserId, body); + return R.ok(); + } + + @Operation(summary = "权限与菜单") + @GetMapping("/permmenu") + public R permmenu(@RequestAttribute() Long adminUserId) { + Dict permmenu = baseSysPermsService.permmenu(adminUserId); + List list = (List) permmenu.getObj("menus"); + list.forEach(o -> o.setName(I18nUtil.getI18nMenu(o.getName()))); + return R.ok(permmenu); + } + + @Operation(summary = "文件上传") + @PostMapping(value = "/upload", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE, + MediaType.ALL_VALUE}) + public R upload( + @RequestPart(value = "file", required = false) @Parameter(description = "文件") MultipartFile[] files, + HttpServletRequest request) { + return R.ok(fileUploadStrategyFactory.upload(files, request)); + } + + @Operation(summary = "文件上传模式") + @GetMapping("/uploadMode") + public R uploadMode() { + return R.ok(fileUploadStrategyFactory.getMode()); + } + + @Operation(summary = "退出") + @PostMapping("/logout") + public R logout(@RequestAttribute Long adminUserId, @RequestAttribute String adminUsername) { + baseSysLoginService.logout(adminUserId, adminUsername); + return R.ok(); + } + + @TokenIgnore + @Operation(summary = "编程") + @GetMapping("/program") + public R program() { + return R.ok("Java"); + } +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/controller/admin/AdminBaseOpenController.java b/cool-admin-java/src/main/java/com/cool/modules/base/controller/admin/AdminBaseOpenController.java new file mode 100644 index 0000000..ed87680 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/controller/admin/AdminBaseOpenController.java @@ -0,0 +1,121 @@ +package com.cool.modules.base.controller.admin; + +import static com.cool.core.plugin.consts.PluginConsts.captchaHook; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.ObjUtil; +import cn.hutool.json.JSONObject; +import com.cool.core.annotation.CoolRestController; +import com.cool.core.cache.CoolCache; +import com.cool.core.enums.UserTypeEnum; +import com.cool.core.eps.CoolEps; +import com.cool.core.plugin.service.CoolPluginService; +import com.cool.core.request.R; +import com.cool.core.util.CoolPluginInvokers; +import com.cool.modules.base.dto.sys.BaseSysLoginDto; +import com.cool.modules.base.service.sys.BaseSysLoginService; +import com.cool.modules.plugin.entity.PluginInfoEntity; +import io.micrometer.common.util.StringUtils; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import java.util.Map; +import java.util.concurrent.ThreadLocalRandom; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; + +/** + * 系统开放接口,无需权限校验 + */ +@RequiredArgsConstructor +@Tag(name = "系统开放", description = "系统开放") +@CoolRestController() +public class AdminBaseOpenController { + + final private BaseSysLoginService baseSysLoginService; + final private CoolPluginService coolPluginService; + final private CoolEps coolEps; + final private CoolCache coolCache; + + @Operation(summary = "实体信息与路径", description = "系统所有的实体信息与路径,供前端自动生成代码与服务") + @GetMapping("/eps") + public R eps() { + return R.ok(coolEps.getAdmin()); + } + + @Operation(summary = "获得网页内容的参数值") + @GetMapping("/html") + public R html() { + return R.ok(); + } + + @Operation(summary = "登录") + @PostMapping("/login") + public R login(@RequestBody BaseSysLoginDto baseSysLoginDto) { + return R.ok(baseSysLoginService.login(baseSysLoginDto)); + } + + @Operation(summary = "验证码") + @GetMapping("/captcha") + public R captcha(@Parameter(description = "类型:svg|base64") @RequestParam(defaultValue = "base64") String type, + @Parameter(description = "宽度") @RequestParam(defaultValue = "150") Integer width, + @Parameter(description = "高度") @RequestParam(defaultValue = "50") Integer height) { + return R.ok(baseSysLoginService.captcha(UserTypeEnum.ADMIN, type, width, height)); + } + + @Operation(summary = "刷新token") + @GetMapping("/refreshToken") + public R refreshToken(String refreshToken) { + return R.ok(baseSysLoginService.refreshToken(refreshToken)); + } + + @RequestMapping("/gen") + @ResponseBody + public Object genCaptcha(@RequestParam(value = "type", required = false)String type) { + if (StringUtils.isBlank(type)) { + type = "SLIDER"; + } + if ("RANDOM".equals(type)) { + int i = ThreadLocalRandom.current().nextInt(0, 4); + if (i == 0) { + type = "SLIDER"; + } else if (i == 1) { + type = "CONCAT"; + } else if (i == 2) { + type = "ROTATE"; + } else{ + type = "WORD_IMAGE_CLICK"; + } + + } + return CoolPluginInvokers.invoke("tianai", "generateCaptcha", type); + } + + @PostMapping("/check") + @ResponseBody + public Object checkCaptcha(@RequestAttribute() JSONObject requestParams) { + Object result = CoolPluginInvokers.invoke("tianai", "matching", requestParams); + Map map = BeanUtil.beanToMap(result); + if (ObjUtil.equals(map.get("code"), 200)) { + String code = ThreadLocalRandom.current().nextInt(100000, 999999) + ""; + coolCache.set("verify:img:" + requestParams.getStr("id"), code, 1800); + R r = new R(); + r.put("data", Map.of("id", requestParams.getStr("id"), + "code", code)); + r.put("code", map.get("code")); + return r; + } + return result; + } + + @Operation(summary = "验证码类型") + @GetMapping("/captchaMode") + public R captchaMode() { + PluginInfoEntity pluginInfoEntity = coolPluginService.getPluginInfoEntityByHook( + captchaHook); + if (pluginInfoEntity != null) { + return R.ok(CoolPluginInvokers.invoke(pluginInfoEntity.getKey(), "getMode")); + } + return R.ok(Map.of("mode", "common")); + } +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/controller/admin/sys/AdminBaseSysDepartmentController.java b/cool-admin-java/src/main/java/com/cool/modules/base/controller/admin/sys/AdminBaseSysDepartmentController.java new file mode 100644 index 0000000..b969055 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/controller/admin/sys/AdminBaseSysDepartmentController.java @@ -0,0 +1,35 @@ +package com.cool.modules.base.controller.admin.sys; + +import cn.hutool.json.JSONObject; +import com.cool.core.annotation.CoolRestController; +import com.cool.core.base.BaseController; +import com.cool.core.request.R; +import com.cool.modules.base.entity.sys.BaseSysDepartmentEntity; +import com.cool.modules.base.service.sys.BaseSysDepartmentService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; + +import jakarta.servlet.http.HttpServletRequest; +import java.util.List; + +/** + * 系统部门 + */ +@Tag(name = "系统部门", description = "系统部门") +@CoolRestController(api = { "add", "delete", "update", "list" }) +public class AdminBaseSysDepartmentController + extends BaseController { + + @Override + protected void init(HttpServletRequest request, JSONObject requestParams) { + } + + @Operation(summary = "排序") + @PostMapping("/order") + public R order(@RequestBody List list) { + this.service.order(list); + return R.ok(); + } +} \ No newline at end of file diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/controller/admin/sys/AdminBaseSysLogController.java b/cool-admin-java/src/main/java/com/cool/modules/base/controller/admin/sys/AdminBaseSysLogController.java new file mode 100644 index 0000000..7b1ff35 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/controller/admin/sys/AdminBaseSysLogController.java @@ -0,0 +1,57 @@ +package com.cool.modules.base.controller.admin.sys; + +import cn.hutool.json.JSONObject; +import com.cool.core.annotation.CoolRestController; +import com.cool.core.base.BaseController; +import com.cool.core.request.R; +import com.cool.modules.base.entity.sys.BaseSysLogEntity; +import com.cool.modules.base.entity.sys.table.BaseSysLogEntityTableDef; +import com.cool.modules.base.entity.sys.table.BaseSysUserEntityTableDef; +import com.cool.modules.base.service.sys.BaseSysConfService; +import com.cool.modules.base.service.sys.BaseSysLogService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletRequest; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestAttribute; + +/** + * 系统日志 + */ +@RequiredArgsConstructor +@Tag(name = "系统日志", description = "系统日志") +@CoolRestController(api = {"page"}) +public class AdminBaseSysLogController extends BaseController { + + private final BaseSysConfService baseSysConfService; + + @Override + protected void init(HttpServletRequest request, JSONObject requestParams) { + setPageOption( + createOp() + .keyWordLikeFields( + BaseSysUserEntityTableDef.BASE_SYS_USER_ENTITY.NAME, + BaseSysLogEntityTableDef.BASE_SYS_LOG_ENTITY.PARAMS)); + } + + @Operation(summary = "清理日志") + @PostMapping("/clear") + public R clear() { + service.clear(true); + return R.ok(); + } + + @Operation(summary = "设置日志保存时间") + @PostMapping("/setKeep") + public R setKeep(@RequestAttribute JSONObject requestParams) { + baseSysConfService.updateValue("logKeep", requestParams.getStr("value")); + return R.ok(); + } + + @Operation(summary = "获得日志报错时间") + @PostMapping("/getKeep") + public R getKeep() { + return R.ok(baseSysConfService.getValue("logKeep")); + } +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/controller/admin/sys/AdminBaseSysMenuController.java b/cool-admin-java/src/main/java/com/cool/modules/base/controller/admin/sys/AdminBaseSysMenuController.java new file mode 100644 index 0000000..fbe96e2 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/controller/admin/sys/AdminBaseSysMenuController.java @@ -0,0 +1,66 @@ +package com.cool.modules.base.controller.admin.sys; + +import cn.hutool.json.JSONObject; +import com.cool.core.annotation.CoolRestController; +import com.cool.core.base.BaseController; +import com.cool.core.exception.CoolPreconditions; +import com.cool.core.request.CrudOption; +import com.cool.core.request.R; +import com.cool.core.util.I18nUtil; +import com.cool.modules.base.entity.sys.BaseSysMenuEntity; +import com.cool.modules.base.service.sys.BaseSysMenuService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletRequest; +import java.util.List; +import java.util.Map; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; + +/** + * 系统菜单 + */ +@Tag(name = "系统菜单", description = "系统菜单") +@CoolRestController(api = {"add", "delete", "update", "page", "list", "info"}) +public class AdminBaseSysMenuController extends + BaseController { + + @Override + protected void init(HttpServletRequest request, JSONObject requestParams) { + CrudOption transform = createOp() + .transform(o -> { + BaseSysMenuEntity entity = (BaseSysMenuEntity) o; + entity.setName(I18nUtil.getI18nMenu(entity.getName())); + }); + setPageOption(transform); + setListOption(transform); + setInfoOption(transform); + } + + @Operation(summary = "创建代码", description = "创建代码") + @PostMapping("/create") + public R create(@RequestBody() Map params) { + CoolPreconditions.checkEmpty(params.get("module"), "module参数不能为空"); + CoolPreconditions.checkEmpty(params.get("entity"), "entity参数不能为空"); + CoolPreconditions.checkEmpty(params.get("controller"), "controller参数不能为空"); + CoolPreconditions.checkEmpty(params.get("service"), "service参数不能为空"); + CoolPreconditions.checkEmpty(params.get("service-impl"), "service-impl参数不能为空"); + CoolPreconditions.checkEmpty(params.get("mapper"), "mapper参数不能为空"); + CoolPreconditions.checkEmpty(params.get("fileName"), "fileName参数不能为空"); + this.service.create(params); + return R.ok(); + } + + @Operation(summary = "导出", description = "导出") + @PostMapping("/export") + public R export(@RequestBody Map params) { + return R.ok(this.service.export(getIds(params))); + } + + @Operation(summary = "导入", description = "导入") + @PostMapping("/import") + public R importMenu(@RequestBody Map> params) { + CoolPreconditions.checkEmpty(params.get("menus"), "参数不能为空"); + return R.ok(this.service.importMenu(params.get("menus"))); + } +} \ No newline at end of file diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/controller/admin/sys/AdminBaseSysParamController.java b/cool-admin-java/src/main/java/com/cool/modules/base/controller/admin/sys/AdminBaseSysParamController.java new file mode 100644 index 0000000..56f7291 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/controller/admin/sys/AdminBaseSysParamController.java @@ -0,0 +1,33 @@ +package com.cool.modules.base.controller.admin.sys; + +import static com.cool.modules.base.entity.sys.table.BaseSysParamEntityTableDef.BASE_SYS_PARAM_ENTITY; + +import cn.hutool.json.JSONObject; +import com.cool.core.annotation.CoolRestController; +import com.cool.core.base.BaseController; +import com.cool.modules.base.entity.sys.BaseSysParamEntity; +import com.cool.modules.base.service.sys.BaseSysParamService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.web.bind.annotation.GetMapping; + +/** + * 系统参数配置 + */ +@Tag(name = "系统参数配置", description = "系统参数配置") +@CoolRestController(api = { "add", "delete", "update", "page", "info" }) +public class AdminBaseSysParamController extends BaseController { + + @Override + protected void init(HttpServletRequest request, JSONObject requestParams) { + setPageOption(createOp().fieldEq(BASE_SYS_PARAM_ENTITY.DATA_TYPE) + .keyWordLikeFields(BASE_SYS_PARAM_ENTITY.NAME, BASE_SYS_PARAM_ENTITY.KEY_NAME)); + } + + @Operation(summary = "根据键返回网页的参数值") + @GetMapping("/html") + public String html(String key) { + return service.htmlByKey(key); + } +} \ No newline at end of file diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/controller/admin/sys/AdminBaseSysRoleController.java b/cool-admin-java/src/main/java/com/cool/modules/base/controller/admin/sys/AdminBaseSysRoleController.java new file mode 100644 index 0000000..51f0993 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/controller/admin/sys/AdminBaseSysRoleController.java @@ -0,0 +1,37 @@ +package com.cool.modules.base.controller.admin.sys; + +import static com.cool.modules.base.entity.sys.table.BaseSysRoleEntityTableDef.BASE_SYS_ROLE_ENTITY; + +import cn.hutool.json.JSONArray; +import cn.hutool.json.JSONObject; +import com.cool.core.annotation.CoolRestController; +import com.cool.core.base.BaseController; +import com.cool.modules.base.entity.sys.BaseSysRoleEntity; +import com.cool.modules.base.service.sys.BaseSysRoleService; +import com.mybatisflex.core.query.QueryWrapper; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletRequest; + +/** + * 系统角色 + */ +@Tag(name = "系统角色", description = "系统角色") +@CoolRestController(api = { "add", "delete", "update", "page", "list", "info" }) +public class AdminBaseSysRoleController extends BaseController { + + @Override + protected void init(HttpServletRequest request, JSONObject requestParams) { + JSONObject tokenInfo = requestParams.getJSONObject("tokenInfo"); + boolean isAdmin = tokenInfo.getStr("username").equals("admin"); + + setPageOption(createOp().keyWordLikeFields(BASE_SYS_ROLE_ENTITY.NAME, BASE_SYS_ROLE_ENTITY.LABEL).queryWrapper(QueryWrapper.create().and(qw -> { + qw.eq(BASE_SYS_ROLE_ENTITY.USER_ID.getName(), tokenInfo.getLong("userId")).or(w -> { + Object o = tokenInfo.get("roleIds"); + if (o != null) { + w.in(BASE_SYS_ROLE_ENTITY.ID.getName(), new JSONArray(o).toList(Long.class)); + } + }); + }, !isAdmin).and(BASE_SYS_ROLE_ENTITY.LABEL.ne("admin")))); + } + +} \ No newline at end of file diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/controller/admin/sys/AdminBaseSysUserController.java b/cool-admin-java/src/main/java/com/cool/modules/base/controller/admin/sys/AdminBaseSysUserController.java new file mode 100644 index 0000000..aa15e18 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/controller/admin/sys/AdminBaseSysUserController.java @@ -0,0 +1,34 @@ +package com.cool.modules.base.controller.admin.sys; + +import cn.hutool.json.JSONObject; +import com.cool.core.annotation.CoolRestController; +import com.cool.core.base.BaseController; +import com.cool.core.request.R; +import com.cool.modules.base.entity.sys.BaseSysUserEntity; +import com.cool.modules.base.service.sys.BaseSysUserService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestAttribute; + +import jakarta.servlet.http.HttpServletRequest; + +/** + * 系统用户 + */ +@Tag(name = "系统用户", description = "系统用户") +@CoolRestController(api = { "add", "delete", "update", "page", "info" }) +public class AdminBaseSysUserController extends BaseController { + + @Override + protected void init(HttpServletRequest request, JSONObject requestParams) { + } + + @Operation(summary = "移动部门") + @PostMapping("/move") + public R move(@RequestAttribute JSONObject requestParams) { + service.move(requestParams.getLong("departmentId"), requestParams.get("userIds", Long[].class)); + return R.ok(); + } + +} \ No newline at end of file diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/controller/app/AppBaseCommController.java b/cool-admin-java/src/main/java/com/cool/modules/base/controller/app/AppBaseCommController.java new file mode 100644 index 0000000..d326b0a --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/controller/app/AppBaseCommController.java @@ -0,0 +1,71 @@ +package com.cool.modules.base.controller.app; + +import cn.hutool.json.JSONObject; +import com.cool.core.annotation.CoolRestController; +import com.cool.core.annotation.TokenIgnore; +import com.cool.core.eps.CoolEps; +import com.cool.core.exception.CoolPreconditions; +import com.cool.core.file.FileUploadStrategyFactory; +import com.cool.core.request.R; +import com.cool.modules.base.service.sys.BaseSysParamService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletRequest; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestAttribute; +import org.springframework.web.bind.annotation.RequestPart; +import org.springframework.web.multipart.MultipartFile; + +/** + * app通用接口 + */ +@RequiredArgsConstructor +@Tag(name = "应用通用", description = "应用通用") +@CoolRestController +public class AppBaseCommController { + + private final CoolEps coolEps; + + private final BaseSysParamService baseSysParamService; + + @Value("${cool.sysParam.allowKeys:[]}") + private List allowKeys; + + final private FileUploadStrategyFactory fileUploadStrategyFactory; + + @TokenIgnore + @Operation(summary = "参数配置") + @GetMapping("/param") + public R param(@RequestAttribute() JSONObject requestParams) { + String key = requestParams.get("key", String.class); + CoolPreconditions.check(!allowKeys.contains(key), "非法操作"); + return R.ok(baseSysParamService.dataByKey(key)); + } + + @TokenIgnore + @Operation(summary = "实体信息与路径", description = "系统所有的实体信息与路径,供前端自动生成代码与服务") + @GetMapping("/eps") + public R eps() { + return R.ok(coolEps.getApp()); + } + + + @Operation(summary = "文件上传") + @PostMapping(value = "/upload", consumes = { MediaType.MULTIPART_FORM_DATA_VALUE, MediaType.ALL_VALUE }) + public R upload(@RequestPart(value = "file", required = false) @Parameter(description = "文件") MultipartFile[] files, + HttpServletRequest request) { + return R.ok(fileUploadStrategyFactory.upload(files, request)); + } + + @Operation(summary = "文件上传模式") + @GetMapping("/uploadMode") + public R uploadMode() { + return R.ok(fileUploadStrategyFactory.getMode()); + } +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/dto/sys/BaseSysLoginDto.java b/cool-admin-java/src/main/java/com/cool/modules/base/dto/sys/BaseSysLoginDto.java new file mode 100644 index 0000000..20f3149 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/dto/sys/BaseSysLoginDto.java @@ -0,0 +1,30 @@ +package com.cool.modules.base.dto.sys; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import jakarta.validation.constraints.NotBlank; + +/** + * 登录 + */ +@Data +@Schema(description = "登录参数") +public class BaseSysLoginDto { + + @Schema(description = "用户名") + @NotBlank + private String username; + + @Schema(description = "密码") + @NotBlank + private String password; + + @Schema(description = "验证码ID") + @NotBlank + private String captchaId; + + @Schema(description = "验证码") + @NotBlank + private String verifyCode; +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/dto/sys/CodeContentDto.java b/cool-admin-java/src/main/java/com/cool/modules/base/dto/sys/CodeContentDto.java new file mode 100644 index 0000000..bcff941 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/dto/sys/CodeContentDto.java @@ -0,0 +1,9 @@ +package com.cool.modules.base.dto.sys; + +import lombok.Data; + +@Data +public class CodeContentDto { + private String path; + private String content; +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/entity/sys/BaseSysConfEntity.java b/cool-admin-java/src/main/java/com/cool/modules/base/entity/sys/BaseSysConfEntity.java new file mode 100644 index 0000000..73ffbb1 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/entity/sys/BaseSysConfEntity.java @@ -0,0 +1,24 @@ +package com.cool.modules.base.entity.sys; + +import com.cool.core.base.BaseEntity; +import com.mybatisflex.annotation.Table; +import com.tangzc.mybatisflex.autotable.annotation.ColumnDefine; +import lombok.Getter; +import lombok.Setter; +import org.dromara.autotable.annotation.Index; +import org.dromara.autotable.annotation.enums.IndexTypeEnum; + +/** + * 系统配置 + */ +@Getter +@Setter +@Table(value = "base_sys_conf", comment = "系统配置表") +public class BaseSysConfEntity extends BaseEntity { + @Index(type = IndexTypeEnum.UNIQUE) + @ColumnDefine(comment = "配置键", notNull = true) + private String cKey; + + @ColumnDefine(comment = "值", notNull = true, type = "text") + private String cValue; +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/entity/sys/BaseSysDepartmentEntity.java b/cool-admin-java/src/main/java/com/cool/modules/base/entity/sys/BaseSysDepartmentEntity.java new file mode 100644 index 0000000..200a126 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/entity/sys/BaseSysDepartmentEntity.java @@ -0,0 +1,30 @@ +package com.cool.modules.base.entity.sys; + +import com.cool.core.base.BaseEntity; +import com.mybatisflex.annotation.Column; + +import com.tangzc.mybatisflex.autotable.annotation.ColumnDefine; +import com.mybatisflex.annotation.Table; +import lombok.Getter; +import lombok.Setter; + +/** + * 系统部门 + */ +@Getter +@Setter +@Table(value = "base_sys_department", comment = "系统部门") +public class BaseSysDepartmentEntity extends BaseEntity { + @ColumnDefine(comment = "部门名称", notNull = true) + private String name; + + @ColumnDefine(comment = "上级部门ID", type = "bigint") + private Long parentId; + + @ColumnDefine(comment = "排序", defaultValue = "0") + private Integer orderNum; + + // 父菜单名称 + @Column(ignore = true) + private String parentName; +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/entity/sys/BaseSysLogEntity.java b/cool-admin-java/src/main/java/com/cool/modules/base/entity/sys/BaseSysLogEntity.java new file mode 100644 index 0000000..450960c --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/entity/sys/BaseSysLogEntity.java @@ -0,0 +1,34 @@ +package com.cool.modules.base.entity.sys; + +import com.cool.core.base.BaseEntity; +import com.mybatisflex.annotation.Column; +import com.mybatisflex.annotation.Table; +import com.cool.core.mybatis.handler.Fastjson2TypeHandler; +import com.tangzc.mybatisflex.autotable.annotation.ColumnDefine; +import lombok.Getter; +import lombok.Setter; +import org.dromara.autotable.annotation.Index; + +@Getter +@Setter +@Table(value = "base_sys_log", comment = "系统日志表") +public class BaseSysLogEntity extends BaseEntity { + + @Index + @ColumnDefine(comment = "用户ID", type = "bigint") + private Long userId; + + @ColumnDefine(comment = "行为", length = 1000) + private String action; + + @ColumnDefine(comment = "IP", length = 50) + private String ip; + + @ColumnDefine(comment = "参数", type = "json") + @Column(typeHandler = Fastjson2TypeHandler.class) + private Object params; + + // 用户名称 + @Column(ignore = true) + private String name; +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/entity/sys/BaseSysMenuEntity.java b/cool-admin-java/src/main/java/com/cool/modules/base/entity/sys/BaseSysMenuEntity.java new file mode 100644 index 0000000..96c4ca4 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/entity/sys/BaseSysMenuEntity.java @@ -0,0 +1,52 @@ +package com.cool.modules.base.entity.sys; + +import com.cool.core.base.BaseEntity; +import com.mybatisflex.annotation.Column; +import com.mybatisflex.annotation.Table; +import com.tangzc.mybatisflex.autotable.annotation.ColumnDefine; +import java.util.List; +import lombok.Getter; +import lombok.Setter; +import org.dromara.autotable.annotation.Index; + +@Getter +@Setter +@Table(value = "base_sys_menu", comment = "系统菜单表") +public class BaseSysMenuEntity extends BaseEntity { + @Index + @ColumnDefine(comment = "父菜单ID", type = "bigint") + private Long parentId; + + @ColumnDefine(comment = "菜单名称") + private String name; + + @ColumnDefine(comment = "权限", type = "text") + private String perms; + + @ColumnDefine(comment = "类型 0:目录 1:菜单 2:按钮", defaultValue = "0") + private Integer type; + + @ColumnDefine(comment = "图标") + private String icon; + + @ColumnDefine(comment = "排序", defaultValue = "0") + private Integer orderNum; + + @ColumnDefine(comment = "菜单地址") + private String router; + + @ColumnDefine(comment = "视图地址") + private String viewPath; + + @ColumnDefine(comment = "路由缓存", defaultValue = "true") + private Boolean keepAlive; + + @ColumnDefine(comment = "是否显示", defaultValue = "true") + private Boolean isShow; + + @Column(ignore = true) + private String parentName; + + @Column(ignore = true) + private List childMenus; +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/entity/sys/BaseSysParamEntity.java b/cool-admin-java/src/main/java/com/cool/modules/base/entity/sys/BaseSysParamEntity.java new file mode 100644 index 0000000..d5f1001 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/entity/sys/BaseSysParamEntity.java @@ -0,0 +1,29 @@ +package com.cool.modules.base.entity.sys; + +import com.cool.core.base.BaseEntity; +import com.mybatisflex.annotation.Table; +import com.tangzc.mybatisflex.autotable.annotation.ColumnDefine; +import lombok.Getter; +import lombok.Setter; +import org.dromara.autotable.annotation.Index; + +@Getter +@Setter +@Table(value = "base_sys_param", comment = "系统参数配置") +public class BaseSysParamEntity extends BaseEntity { + @Index + @ColumnDefine(comment = "键", notNull = true) + private String keyName; + + @ColumnDefine(comment = "名称") + private String name; + + @ColumnDefine(comment = "数据", type = "text") + private String data; + + @ColumnDefine(comment = "数据类型 0:字符串 1:数组 2:键值对", defaultValue = "0") + private Integer dataType; + + @ColumnDefine(comment = "备注") + private String remark; +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/entity/sys/BaseSysRoleDepartmentEntity.java b/cool-admin-java/src/main/java/com/cool/modules/base/entity/sys/BaseSysRoleDepartmentEntity.java new file mode 100644 index 0000000..f7a48ff --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/entity/sys/BaseSysRoleDepartmentEntity.java @@ -0,0 +1,20 @@ +package com.cool.modules.base.entity.sys; + +import com.cool.core.base.BaseEntity; + +import com.tangzc.mybatisflex.autotable.annotation.ColumnDefine; +import com.mybatisflex.annotation.Table; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@Table(value = "base_sys_role_department", comment = "系统角色部门") +public class BaseSysRoleDepartmentEntity extends BaseEntity { + + @ColumnDefine(comment = "角色ID", type = "bigint") + private Long roleId; + + @ColumnDefine(comment = "部门ID", type = "bigint") + private Long departmentId; +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/entity/sys/BaseSysRoleEntity.java b/cool-admin-java/src/main/java/com/cool/modules/base/entity/sys/BaseSysRoleEntity.java new file mode 100644 index 0000000..8102e2d --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/entity/sys/BaseSysRoleEntity.java @@ -0,0 +1,43 @@ +package com.cool.modules.base.entity.sys; + +import com.cool.core.base.BaseEntity; +import com.mybatisflex.annotation.Column; +import com.mybatisflex.annotation.Table; +import com.cool.core.mybatis.handler.Fastjson2TypeHandler; +import com.tangzc.mybatisflex.autotable.annotation.ColumnDefine; +import java.util.List; +import lombok.Getter; +import lombok.Setter; +import org.dromara.autotable.annotation.Index; +import org.dromara.autotable.annotation.enums.IndexTypeEnum; + +@Getter +@Setter +@Table(value = "base_sys_role", comment = "系统角色表") +public class BaseSysRoleEntity extends BaseEntity { + + @Index + @ColumnDefine(comment = "用户ID", notNull = true, type = "bigint") + private Long userId; + + @ColumnDefine(comment = "名称", notNull = true) + private String name; + + @Index(type = IndexTypeEnum.UNIQUE) + @ColumnDefine(comment = "角色标签", notNull = true) + private String label; + + @ColumnDefine(comment = "备注") + private String remark; + + @ColumnDefine(comment = "数据权限是否关联上下级", defaultValue = "1") + private Integer relevance; + + @ColumnDefine(comment = "菜单权限", type = "json") + @Column(typeHandler = Fastjson2TypeHandler.class) + private List menuIdList; + + @ColumnDefine(comment = "部门权限", type = "json") + @Column(typeHandler = Fastjson2TypeHandler.class) + private List departmentIdList; +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/entity/sys/BaseSysRoleMenuEntity.java b/cool-admin-java/src/main/java/com/cool/modules/base/entity/sys/BaseSysRoleMenuEntity.java new file mode 100644 index 0000000..0886904 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/entity/sys/BaseSysRoleMenuEntity.java @@ -0,0 +1,19 @@ +package com.cool.modules.base.entity.sys; + +import com.cool.core.base.BaseEntity; + +import com.tangzc.mybatisflex.autotable.annotation.ColumnDefine; +import com.mybatisflex.annotation.Table; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@Table(value = "base_sys_role_menu", comment = "系统角色菜单表") +public class BaseSysRoleMenuEntity extends BaseEntity { + @ColumnDefine(comment = "菜单", type = "bigint") + private Long menuId; + + @ColumnDefine(comment = "角色ID", type = "bigint") + private Long roleId; +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/entity/sys/BaseSysUserEntity.java b/cool-admin-java/src/main/java/com/cool/modules/base/entity/sys/BaseSysUserEntity.java new file mode 100644 index 0000000..fa5b5c0 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/entity/sys/BaseSysUserEntity.java @@ -0,0 +1,72 @@ +package com.cool.modules.base.entity.sys; + +import com.cool.core.base.TenantEntity; +import com.mybatisflex.annotation.Column; +import com.mybatisflex.annotation.Table; +import com.tangzc.mybatisflex.autotable.annotation.ColumnDefine; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; +import org.dromara.autotable.annotation.Ignore; +import org.dromara.autotable.annotation.Index; +import org.dromara.autotable.annotation.enums.IndexTypeEnum; + +import java.util.List; + +@Getter +@Setter +@Table(value = "base_sys_user", comment = "系统用户表") +public class BaseSysUserEntity extends TenantEntity { + @Index + @ColumnDefine(comment = "部门ID", type = "bigint") + private Long departmentId; + + @ColumnDefine(comment = "姓名") + private String name; + + @Index(type = IndexTypeEnum.UNIQUE) + @ColumnDefine(comment = "用户名", length = 100, notNull = true) + private String username; + + @ColumnDefine(comment = "密码", notNull = true) + private String password; + + @ColumnDefine(comment = "密码版本", defaultValue = "1") + private Integer passwordV; + + @ColumnDefine(comment = "昵称", notNull = true) + private String nickName; + + @ColumnDefine(comment = "头像") + private String headImg; + + @ColumnDefine(comment = "手机号") + private String phone; + + @ColumnDefine(comment = "邮箱") + private String email; + + @ColumnDefine(comment = "备注") + private String remark; + + @ColumnDefine(comment = "状态 0:禁用 1:启用", defaultValue = "1") + private Integer status; + + // 部门名称 + @Column(ignore = true) + private String departmentName; + + // 角色名称 + @Column(ignore = true) + private String roleName; + + @ColumnDefine(comment = "socketId") + private String socketId; + + + @Ignore + @Schema( description = "角色列表" ) + private List roleIdList; + + +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/entity/sys/BaseSysUserRoleEntity.java b/cool-admin-java/src/main/java/com/cool/modules/base/entity/sys/BaseSysUserRoleEntity.java new file mode 100644 index 0000000..c8ffc67 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/entity/sys/BaseSysUserRoleEntity.java @@ -0,0 +1,21 @@ +package com.cool.modules.base.entity.sys; + +import com.cool.core.base.BaseEntity; +import com.mybatisflex.annotation.Table; +import com.tangzc.mybatisflex.autotable.annotation.ColumnDefine; +import lombok.Getter; +import lombok.Setter; +import org.dromara.autotable.annotation.Index; + +@Getter +@Setter +@Table(value = "base_sys_user_role", comment = "系统用户角色表") +public class BaseSysUserRoleEntity extends BaseEntity { + @Index + @ColumnDefine(comment = "用户ID", type = "bigint") + private Long userId; + + @Index + @ColumnDefine(comment = "角色ID", type = "bigint") + private Long roleId; +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/filter/BaseLogFilter.java b/cool-admin-java/src/main/java/com/cool/modules/base/filter/BaseLogFilter.java new file mode 100644 index 0000000..9e10474 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/filter/BaseLogFilter.java @@ -0,0 +1,33 @@ +package com.cool.modules.base.filter; + +import cn.hutool.json.JSONObject; +import com.cool.modules.base.service.sys.BaseSysLogService; +import jakarta.servlet.Filter; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import java.io.IOException; +import lombok.RequiredArgsConstructor; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +@Component +@Order(10) +@RequiredArgsConstructor +public class BaseLogFilter implements Filter { + + final private BaseSysLogService baseSysLogService; + + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, + FilterChain filterChain) + throws IOException, ServletException { + // 记录日志 + HttpServletRequest request = (HttpServletRequest) servletRequest; + baseSysLogService.record(request, (JSONObject) request.getAttribute("requestParams")); + filterChain.doFilter(servletRequest, servletResponse); + } + +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/mapper/sys/BaseSysConfMapper.java b/cool-admin-java/src/main/java/com/cool/modules/base/mapper/sys/BaseSysConfMapper.java new file mode 100644 index 0000000..298448c --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/mapper/sys/BaseSysConfMapper.java @@ -0,0 +1,11 @@ +package com.cool.modules.base.mapper.sys; + +import com.cool.modules.base.entity.sys.BaseSysConfEntity; +import com.mybatisflex.core.BaseMapper; + +/** + * 系统配置 + */ +public interface BaseSysConfMapper extends BaseMapper { + +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/mapper/sys/BaseSysDepartmentMapper.java b/cool-admin-java/src/main/java/com/cool/modules/base/mapper/sys/BaseSysDepartmentMapper.java new file mode 100644 index 0000000..cc3148e --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/mapper/sys/BaseSysDepartmentMapper.java @@ -0,0 +1,10 @@ +package com.cool.modules.base.mapper.sys; + +import com.mybatisflex.core.BaseMapper; +import com.cool.modules.base.entity.sys.BaseSysDepartmentEntity; + +/** + * 系统部门 + */ +public interface BaseSysDepartmentMapper extends BaseMapper { +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/mapper/sys/BaseSysLogMapper.java b/cool-admin-java/src/main/java/com/cool/modules/base/mapper/sys/BaseSysLogMapper.java new file mode 100644 index 0000000..5bd6f09 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/mapper/sys/BaseSysLogMapper.java @@ -0,0 +1,10 @@ +package com.cool.modules.base.mapper.sys; + +import com.mybatisflex.core.BaseMapper; +import com.cool.modules.base.entity.sys.BaseSysLogEntity; + +/** + * 系统日志 + */ +public interface BaseSysLogMapper extends BaseMapper { +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/mapper/sys/BaseSysMenuMapper.java b/cool-admin-java/src/main/java/com/cool/modules/base/mapper/sys/BaseSysMenuMapper.java new file mode 100644 index 0000000..ab39f68 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/mapper/sys/BaseSysMenuMapper.java @@ -0,0 +1,20 @@ +package com.cool.modules.base.mapper.sys; + +import com.mybatisflex.core.BaseMapper; +import com.cool.modules.base.entity.sys.BaseSysMenuEntity; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 系统菜单 + */ +public interface BaseSysMenuMapper extends BaseMapper { + /** + * 根据角色ID获得所有菜单 + * + * @param roleIds 角色ID集合 + * @return SysMenuEntity + */ + List getMenus(@Param("roleIds") Long[] roleIds); +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/mapper/sys/BaseSysParamMapper.java b/cool-admin-java/src/main/java/com/cool/modules/base/mapper/sys/BaseSysParamMapper.java new file mode 100644 index 0000000..49ce1bd --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/mapper/sys/BaseSysParamMapper.java @@ -0,0 +1,10 @@ +package com.cool.modules.base.mapper.sys; + +import com.mybatisflex.core.BaseMapper; +import com.cool.modules.base.entity.sys.BaseSysParamEntity; + +/** + * 系统参数配置 + */ +public interface BaseSysParamMapper extends BaseMapper { +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/mapper/sys/BaseSysRoleDepartmentMapper.java b/cool-admin-java/src/main/java/com/cool/modules/base/mapper/sys/BaseSysRoleDepartmentMapper.java new file mode 100644 index 0000000..9f3f027 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/mapper/sys/BaseSysRoleDepartmentMapper.java @@ -0,0 +1,10 @@ +package com.cool.modules.base.mapper.sys; + +import com.mybatisflex.core.BaseMapper; +import com.cool.modules.base.entity.sys.BaseSysRoleDepartmentEntity; + +/** + * 系统角色部门 + */ +public interface BaseSysRoleDepartmentMapper extends BaseMapper { +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/mapper/sys/BaseSysRoleMapper.java b/cool-admin-java/src/main/java/com/cool/modules/base/mapper/sys/BaseSysRoleMapper.java new file mode 100644 index 0000000..6264504 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/mapper/sys/BaseSysRoleMapper.java @@ -0,0 +1,10 @@ +package com.cool.modules.base.mapper.sys; + +import com.mybatisflex.core.BaseMapper; +import com.cool.modules.base.entity.sys.BaseSysRoleEntity; + +/** + * 系统角色 + */ +public interface BaseSysRoleMapper extends BaseMapper { +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/mapper/sys/BaseSysRoleMenuMapper.java b/cool-admin-java/src/main/java/com/cool/modules/base/mapper/sys/BaseSysRoleMenuMapper.java new file mode 100644 index 0000000..4d488f0 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/mapper/sys/BaseSysRoleMenuMapper.java @@ -0,0 +1,18 @@ +package com.cool.modules.base.mapper.sys; + +import com.mybatisflex.core.BaseMapper; +import com.cool.modules.base.entity.sys.BaseSysRoleMenuEntity; +import org.apache.ibatis.annotations.Param; + +/** + * 系统角色菜单 + */ +public interface BaseSysRoleMenuMapper extends BaseMapper { + /** + * 跟菜单关联的所有用户 + * + * @param menuId 菜单 + * @return 所有用户ID + */ + Long[] userIds(@Param("menuId") Long menuId); +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/mapper/sys/BaseSysUserMapper.java b/cool-admin-java/src/main/java/com/cool/modules/base/mapper/sys/BaseSysUserMapper.java new file mode 100644 index 0000000..37f4c90 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/mapper/sys/BaseSysUserMapper.java @@ -0,0 +1,11 @@ +package com.cool.modules.base.mapper.sys; + +import com.mybatisflex.core.BaseMapper; +import com.cool.modules.base.entity.sys.BaseSysUserEntity; + +/** + * 系统用户 + */ +public interface BaseSysUserMapper extends BaseMapper { + +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/mapper/sys/BaseSysUserRoleMapper.java b/cool-admin-java/src/main/java/com/cool/modules/base/mapper/sys/BaseSysUserRoleMapper.java new file mode 100644 index 0000000..51b8105 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/mapper/sys/BaseSysUserRoleMapper.java @@ -0,0 +1,10 @@ +package com.cool.modules.base.mapper.sys; + +import com.mybatisflex.core.BaseMapper; +import com.cool.modules.base.entity.sys.BaseSysUserRoleEntity; + +/** + * 系统用户角色 + */ +public interface BaseSysUserRoleMapper extends BaseMapper { +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/security/JwtUserDetailsServiceImpl.java b/cool-admin-java/src/main/java/com/cool/modules/base/security/JwtUserDetailsServiceImpl.java new file mode 100644 index 0000000..574dce7 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/security/JwtUserDetailsServiceImpl.java @@ -0,0 +1,57 @@ +package com.cool.modules.base.security; + +import cn.hutool.core.util.ObjectUtil; +import com.cool.core.cache.CoolCache; +import com.cool.core.security.jwt.JwtUser; +import com.cool.modules.base.entity.sys.BaseSysUserEntity; +import com.cool.modules.base.service.sys.BaseSysPermsService; +import com.cool.modules.base.service.sys.BaseSysUserService; +import com.mybatisflex.core.query.QueryWrapper; +import java.util.ArrayList; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Component; + +/** + * 获得用户信息 + */ +@Component +@RequiredArgsConstructor +public class JwtUserDetailsServiceImpl implements UserDetailsService { + + final private BaseSysUserService baseSysUserService; + final private BaseSysPermsService baseSysPermsService; + final private CoolCache coolCache; + + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + BaseSysUserEntity sysUserEntity = baseSysUserService.getMapper().selectOneByQuery( + QueryWrapper.create().eq(BaseSysUserEntity::getUsername, username) + .eq(BaseSysUserEntity::getStatus, 1)); + if (ObjectUtil.isEmpty(sysUserEntity)) { + throw new UsernameNotFoundException("用户名不存在"); + } + List authority = new ArrayList<>(); + String[] perms = baseSysPermsService.getPerms(sysUserEntity.getId()); + for (String perm : perms) { + authority.add(new SimpleGrantedAuthority(perm)); + } + Long[] departmentIds = baseSysPermsService.getDepartmentIdsByRoleIds(sysUserEntity.getId()); + JwtUser jwtUser = new JwtUser(sysUserEntity.getId(), sysUserEntity.getUsername(), sysUserEntity.getPassword(), + authority, + sysUserEntity.getStatus() == 1); + Long[] roleIds = baseSysPermsService.getRoles(sysUserEntity); + coolCache.set("admin:userDetails:" + jwtUser.getUsername(), jwtUser); + coolCache.set("admin:passwordVersion:" + sysUserEntity.getId(), + sysUserEntity.getPasswordV()); + coolCache.set("admin:userInfo:" + sysUserEntity.getId(), sysUserEntity); + coolCache.set("admin:department:" + sysUserEntity.getId(), departmentIds); + coolCache.set("admin:roleIds:" + sysUserEntity.getId(), roleIds); + return jwtUser; + } +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/security/MySecurityMetadataSource.java b/cool-admin-java/src/main/java/com/cool/modules/base/security/MySecurityMetadataSource.java new file mode 100644 index 0000000..2f97be4 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/security/MySecurityMetadataSource.java @@ -0,0 +1,81 @@ +package com.cool.modules.base.security; + +import cn.hutool.core.util.ObjectUtil; +import com.cool.core.enums.UserTypeEnum; +import com.cool.core.util.CoolSecurityUtil; +import com.cool.modules.base.service.sys.BaseSysPermsService; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.ConfigAttribute; +import org.springframework.security.access.SecurityConfig; +import org.springframework.security.web.FilterInvocation; +import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource; +import org.springframework.stereotype.Component; + +/** + * 权限资源管理器 为权限决断器提供支持 + */ +@Slf4j +@Component +@RequiredArgsConstructor +public class MySecurityMetadataSource implements FilterInvocationSecurityMetadataSource { + + final private BaseSysPermsService baseSysPermsService; + + private Map> map = null; + + /** + * 加载权限表中所有操作请求权限 + */ + public void loadResourceDefine() { + map = new HashMap<>(); + Collection configAttributes; + ConfigAttribute cfg; + String[] perms = baseSysPermsService.getAllPerms(); + // 获取启用的权限操作请求 + for (String perm : perms) { + configAttributes = new ArrayList<>(); + cfg = new SecurityConfig(perm); + // 作为MyAccessDecisionManager类的decide的第三个参数 + configAttributes.add(cfg); + // 用权限的path作为map的key,用ConfigAttribute的集合作为value + map.put(perm.replaceAll(":", "/"), configAttributes); + } + } + + /** + * 判定用户请求的url是否在权限表中 如果在权限表中,则返回给decide方法,用来判定用户是否有此权限 如果不在权限表中则放行 + * + * @param o + * @return + * @throws IllegalArgumentException + */ + @Override + public Collection getAttributes(Object o) throws IllegalArgumentException { + UserTypeEnum userTypeEnum = CoolSecurityUtil.getCurrentUserType(); + if (ObjectUtil.equal(userTypeEnum, UserTypeEnum.APP)) { + // app用户不需要权限拦截 + return null; + } + if (map == null) { + loadResourceDefine(); + } + // Object中包含用户请求request + String url = ((FilterInvocation) o).getRequestUrl(); + return map.get(url.replace("/admin/", "").split("[?]")[0]); + } + + @Override + public Collection getAllConfigAttributes() { + return new ArrayList<>(); + } + + @Override + public boolean supports(Class aClass) { + return true; + } +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/BaseCodingService.java b/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/BaseCodingService.java new file mode 100644 index 0000000..303fb62 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/BaseCodingService.java @@ -0,0 +1,11 @@ +package com.cool.modules.base.service.sys; + +import com.cool.modules.base.dto.sys.CodeContentDto; + +import java.util.List; + +public interface BaseCodingService { + List getModuleTree(); + + void createCode(List codes); +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/BaseSysConfService.java b/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/BaseSysConfService.java new file mode 100644 index 0000000..3117a6f --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/BaseSysConfService.java @@ -0,0 +1,41 @@ +package com.cool.modules.base.service.sys; + +import com.cool.core.base.BaseService; +import com.cool.modules.base.entity.sys.BaseSysConfEntity; + +/** + * 系统配置 + */ +public interface BaseSysConfService extends BaseService { + /** + * 更新配置 + * + * @param key 键 + * @param value 值 + */ + void updateValue(String key, String value); + + /** + * 获得值 + * + * @param key 键 + * @return 值 + */ + String getValue(String key); + + /** + * 获得值(带缓存) + * + * @param key 键 + * @return 值 + */ + String getValueWithCache(String key); + + /** + * 设置值 + * + * @param key 键 + * @param value 值 + */ + void setValue(String key, String value); +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/BaseSysDepartmentService.java b/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/BaseSysDepartmentService.java new file mode 100644 index 0000000..502862d --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/BaseSysDepartmentService.java @@ -0,0 +1,18 @@ +package com.cool.modules.base.service.sys; + +import com.cool.core.base.BaseService; +import com.cool.modules.base.entity.sys.BaseSysDepartmentEntity; + +import java.util.List; + +/** + * 系统部门 + */ +public interface BaseSysDepartmentService extends BaseService { + /** + * 排序 + * + * @param list 新的排序 + */ + void order(List list); +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/BaseSysLogService.java b/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/BaseSysLogService.java new file mode 100644 index 0000000..4ca596d --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/BaseSysLogService.java @@ -0,0 +1,27 @@ +package com.cool.modules.base.service.sys; + +import cn.hutool.json.JSONObject; +import com.cool.core.base.BaseService; +import com.cool.modules.base.entity.sys.BaseSysLogEntity; + +import jakarta.servlet.http.HttpServletRequest; + +/** + * 系统日志 + */ +public interface BaseSysLogService extends BaseService { + /** + * 清理日志 + * + * @param isAll 是否全部清除 + */ + void clear(boolean isAll); + + /** + * 日志记录 + * + * @param requestParams 请求参数 + * @param request 请求 + */ + void record(HttpServletRequest request, JSONObject requestParams); +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/BaseSysLoginService.java b/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/BaseSysLoginService.java new file mode 100644 index 0000000..242d8f2 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/BaseSysLoginService.java @@ -0,0 +1,48 @@ +package com.cool.modules.base.service.sys; + +import com.cool.core.enums.UserTypeEnum; +import com.cool.modules.base.dto.sys.BaseSysLoginDto; + +/** + * 系统登录 + */ +public interface BaseSysLoginService { + /** + * 验证码 + * + * @param type 类型 svg base64 svg是node版本的, java版本用base64, svg未实现 + * @param width 宽度 + * @param height 高度 + * @return base64 验证码与ID + */ + Object captcha(UserTypeEnum userTypeEnum, String type, Integer width, Integer height); + + /** + * 校验验证码 + */ + void captchaCheck(String captchaId, String code); + + /** + * 登录 + * + * @param baseSysLoginDto 登录必要信息 + * @return token与相关的过期信息 + */ + Object login(BaseSysLoginDto baseSysLoginDto); + + /** + * 退出登录 + * + * @param adminUserId 用户ID + * @param username 用户名称 + */ + void logout(Long adminUserId, String username); + + /** + * 刷新token + * + * @param refreshToken 刷新token + * @return 新的token + */ + Object refreshToken(String refreshToken); +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/BaseSysMenuService.java b/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/BaseSysMenuService.java new file mode 100644 index 0000000..e7753d9 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/BaseSysMenuService.java @@ -0,0 +1,18 @@ +package com.cool.modules.base.service.sys; + +import com.cool.core.base.BaseService; +import com.cool.modules.base.entity.sys.BaseSysMenuEntity; +import java.util.List; +import java.util.Map; + +/** + * 系统菜单 + */ +public interface BaseSysMenuService extends BaseService { + + Object export(List ids); + + boolean importMenu(List menus); + + void create(Map params); +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/BaseSysParamService.java b/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/BaseSysParamService.java new file mode 100644 index 0000000..7926140 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/BaseSysParamService.java @@ -0,0 +1,25 @@ +package com.cool.modules.base.service.sys; + +import com.cool.core.base.BaseService; +import com.cool.modules.base.entity.sys.BaseSysParamEntity; + +/** + * 系统参数配置 + */ +public interface BaseSysParamService extends BaseService { + /** + * 根据key获得网页内容 + * + * @param key 键 + * @return 网页内容 + */ + String htmlByKey(String key); + + /** + * 根据key获得数据 + * + * @param key 键 + * @return 数据 + */ + String dataByKey(String key); +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/BaseSysPermsService.java b/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/BaseSysPermsService.java new file mode 100644 index 0000000..0e364db --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/BaseSysPermsService.java @@ -0,0 +1,160 @@ +package com.cool.modules.base.service.sys; + +import cn.hutool.core.lang.Dict; +import com.cool.modules.base.entity.sys.BaseSysMenuEntity; +import com.cool.modules.base.entity.sys.BaseSysUserEntity; +import java.util.List; + +/** + * 权限菜单 + */ +public interface BaseSysPermsService { + /** + * 获得权限缓存 + * + * @param userId 用户ID + * @return 返回用户相关的权限信息 + */ + String[] getPermsCache(Long userId); + + /** + * 获得权限 + * + * @param userId 用户ID + * @return 返回用户相关的权限信息 + */ + String[] getPerms(Long userId); + + /** + * 获得权限 + * + * @param roleIds 用户角色数组 + * @return 返回用户相关的权限信息 + */ + String[] getPerms(Long[] roleIds); + + /** + * 获得菜单 + * + * @param roleIds 角色 + * @return 返回菜单 + */ + List getMenus(Long[] roleIds); + + /** + * 获得菜单 + * + * @param userId 用户ID + * @return 返回菜单 + */ + List getMenus(Long userId); + + /** + * 获得菜单 + * + * @param username 用户名 + * @return 返回菜单 + */ + List getMenus(String username); + + /** + * 获得角色数组 + * + * @param userId 用户ID + * @return 返回角色数组 + */ + Long[] getRoles(Long userId); + + /** + * 获得角色数组 + * + * @param username 用户名 + * @return 返回角色数组 + */ + Long[] getRoles(String username); + + /** + * 获得登录用户的部门权限 + * + * @return 部门ID集合 + */ + Long[] loginDepartmentIds(); + + /** + * 根据角色获得部门ID + * + * @param roleIds 角色ID数组 + * @return 部门ID数组 + */ + Long[] getDepartmentIdsByRoleIds(Long[] roleIds); + + /** + * 根据用户ID获得部门ID + * + * @param userId 角色ID数组 + * @return 部门ID数组 + */ + Long[] getDepartmentIdsByRoleIds(Long userId); + + /** + * 获得角色数组 + * + * @param userEntity 用户 + * @return 返回角色数组 + */ + Long[] getRoles(BaseSysUserEntity userEntity); + + /** + * 所有的操作权限 + * + * @return 返回所有的操作权限 + */ + String[] getAllPerms(); + + /** + * 用户的权限菜单 + * + * @param adminUserId 登录的用户 + * @return 权限菜单 + */ + Dict permmenu(Long adminUserId); + + /** + * 更新角色权限 + * + * @param roleId 角色ID + * @param menuIdList 菜单ID + * @param departmentIds 部门ID + */ + void updatePerms(Long roleId, Long[] menuIdList, Long[] departmentIds); + + /** + * 更新用户角色 + * + * @param userId 用户ID + * @param roleIdList 角色集合 + */ + void updateUserRole(Long userId, Long[] roleIdList); + + /** + * 刷新权限 + * + * @param userId 用户ID + */ + void refreshPerms(Long userId); + + /** + * 刷新权限 + * + * @param menuId 用户ID + */ + void refreshPermsByMenuId(Long menuId); + + /** + * 刷新权限 + * + * @param roleId 角色ID + */ + void refreshPermsByRoleId(Long roleId); + +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/BaseSysRoleService.java b/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/BaseSysRoleService.java new file mode 100644 index 0000000..f9e4546 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/BaseSysRoleService.java @@ -0,0 +1,10 @@ +package com.cool.modules.base.service.sys; + +import com.cool.core.base.BaseService; +import com.cool.modules.base.entity.sys.BaseSysRoleEntity; + +/** + * 系统角色 + */ +public interface BaseSysRoleService extends BaseService { +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/BaseSysUserService.java b/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/BaseSysUserService.java new file mode 100644 index 0000000..0a6197a --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/BaseSysUserService.java @@ -0,0 +1,25 @@ +package com.cool.modules.base.service.sys; + +import cn.hutool.core.lang.Dict; +import com.cool.core.base.BaseService; +import com.cool.modules.base.entity.sys.BaseSysUserEntity; + +/** + * 系统用户 + */ +public interface BaseSysUserService extends BaseService { + /** + * 修改用户信息 + * + * @param body 用户信息 + */ + void personUpdate(Long userId, Dict body); + + /** + * 移动部门 + * + * @param departmentId 部门ID + * @param userIds 用户ID集合 + */ + void move(Long departmentId, Long[] userIds); +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/impl/BaseCodingServiceImpl.java b/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/impl/BaseCodingServiceImpl.java new file mode 100644 index 0000000..627b35f --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/impl/BaseCodingServiceImpl.java @@ -0,0 +1,83 @@ +package com.cool.modules.base.service.sys.impl; + +import com.cool.core.exception.CoolPreconditions; +import com.cool.modules.base.dto.sys.CodeContentDto; +import com.cool.modules.base.service.sys.BaseCodingService; +import com.google.common.collect.Lists; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; +import java.util.stream.Collectors; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +@Slf4j +@Service +public class BaseCodingServiceImpl implements BaseCodingService { + + @Value("${spring.profiles.active}") + private String env; + + // 获取模块目录结构 + public List getModuleTree() { + if (!"local".equals(env)) { + return List.of(); // 返回空列表 + } + + // 获取基础目录 + Path modulesPath = getModulesPath(); + // 获取模块文件夹 + try { + return Files.list(modulesPath) + .filter(path -> !path.getFileName().toString().equals(".DS_Store")) + .map(path -> path.getFileName().toString()) + .collect(Collectors.toList()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private static Path getModulesPath() { + String moduleDir = System.getProperty("user.dir"); // 可通过其他方式获取应用目录 + String packageName = BaseCodingServiceImpl.class.getPackageName(); + String modulesParentPath = packageName.split("modules")[0].replace(".", File.separator); + return Paths.get(moduleDir, "src", "main", "java", modulesParentPath, "modules"); + } + + // 创建代码文件 + public void createCode(List codes) { + if (!"local".equals(env)) { + throw new IllegalArgumentException("只能在开发环境下创建代码"); + } + Path modulesPath = getModulesPath(); + String absolutePathStr = modulesPath.toAbsolutePath().toString(); + List list = Lists.newArrayList(); + try { + for (CodeContentDto code : codes) { + // 格式化代码内容 + String formattedContent = code.getContent(); + Path filePath = Paths.get(absolutePathStr, code.getPath().replace("java/", "/")); + Path dirPath = filePath.getParent(); + // 确保目录存在 + if (!Files.exists(dirPath)) { + Files.createDirectories(dirPath); + } + // 写入文件 + try (FileWriter writer = new FileWriter(filePath.toFile())) { + formattedContent = formattedContent.replace("com.tangzc.mybatisflex.autotable.annotation.Index;", + "org.dromara.autotable.annotation.Index;"); + writer.write(formattedContent); + } + list.add(filePath.toString()); + } + } catch (Exception e) { + CoolPreconditions.alwaysThrow("生成代码失败", e); + } + log.info("代码已生成,请先编译后,手动重启服务"); + } +} \ No newline at end of file diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysConfServiceImpl.java b/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysConfServiceImpl.java new file mode 100644 index 0000000..db130a9 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysConfServiceImpl.java @@ -0,0 +1,58 @@ +package com.cool.modules.base.service.sys.impl; + +import com.cool.core.base.BaseServiceImpl; +import com.cool.core.cache.CoolCache; +import com.cool.modules.base.entity.sys.BaseSysConfEntity; +import com.cool.modules.base.mapper.sys.BaseSysConfMapper; +import com.cool.modules.base.service.sys.BaseSysConfService; +import com.mybatisflex.core.query.QueryWrapper; +import com.mybatisflex.core.update.UpdateChain; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +/** + * 系统配置 + */ +@Service +@RequiredArgsConstructor +public class BaseSysConfServiceImpl extends BaseServiceImpl + implements BaseSysConfService { + + private final CoolCache coolCache; + + @Override + public void updateValue(String key, String value) { + UpdateChain.of(BaseSysConfEntity.class).set(BaseSysConfEntity::getCValue, value) + .eq(BaseSysConfEntity::getCKey, key).update(); + } + + @Override + public String getValue(String key) { + BaseSysConfEntity baseSysConfEntity = getOne(QueryWrapper.create().eq(BaseSysConfEntity::getCKey, key)); + if (baseSysConfEntity != null) { + return baseSysConfEntity.getCValue(); + } + return null; + } + + @Override + public String getValueWithCache(String key) { + String value = coolCache.get(key, String.class); + if (value != null) { + return value; + } + value = getValue(key); + if (value != null) { + coolCache.set(key, value); + } + return value; + } + + @Override + public void setValue(String key, String value) { + BaseSysConfEntity baseSysConfEntity = new BaseSysConfEntity(); + baseSysConfEntity.setCKey(key); + baseSysConfEntity.setCValue(value); + save(baseSysConfEntity); + } +} \ No newline at end of file diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysDepartmentServiceImpl.java b/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysDepartmentServiceImpl.java new file mode 100644 index 0000000..2c284cd --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysDepartmentServiceImpl.java @@ -0,0 +1,84 @@ +package com.cool.modules.base.service.sys.impl; + +import cn.hutool.json.JSONObject; +import com.cool.core.base.BaseServiceImpl; +import com.cool.core.util.CoolSecurityUtil; +import com.cool.modules.base.entity.sys.BaseSysDepartmentEntity; +import com.cool.modules.base.entity.sys.BaseSysUserEntity; +import com.cool.modules.base.mapper.sys.BaseSysDepartmentMapper; +import com.cool.modules.base.mapper.sys.BaseSysUserMapper; +import com.cool.modules.base.service.sys.BaseSysDepartmentService; +import com.cool.modules.base.service.sys.BaseSysPermsService; +import com.mybatisflex.core.query.QueryWrapper; +import com.mybatisflex.core.update.UpdateChain; +import java.util.ArrayList; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +/** + * 系统部门 + */ +@RequiredArgsConstructor +@Service +public class BaseSysDepartmentServiceImpl extends + BaseServiceImpl + implements BaseSysDepartmentService { + + final private BaseSysUserMapper baseSysUserMapper; + + final private BaseSysPermsService baseSysPermsService; + + @Override + public void order(List list) { + list.forEach(baseSysDepartmentEntity -> { + UpdateChain.of(BaseSysDepartmentEntity.class) + .set(BaseSysDepartmentEntity::getOrderNum, baseSysDepartmentEntity.getOrderNum()) + .set(BaseSysDepartmentEntity::getParentId, baseSysDepartmentEntity.getParentId()) + .eq(BaseSysDepartmentEntity::getId, baseSysDepartmentEntity.getId()).update(); + }); + } + + @Override + public List list(JSONObject requestParams, QueryWrapper queryWrapper) { + String username = CoolSecurityUtil.getAdminUsername(); + Long[] loginDepartmentIds = baseSysPermsService.loginDepartmentIds(); + if (loginDepartmentIds != null && loginDepartmentIds.length == 0) { + return new ArrayList<>(); + } + List list = this.list( + QueryWrapper.create() + .in(BaseSysDepartmentEntity::getId, loginDepartmentIds, !username.equals("admin")) + .orderBy(BaseSysDepartmentEntity::getOrderNum, false)); + list.forEach(e -> { + List parentDepartment = list.stream() + .filter(sysDepartmentEntity -> e.getParentId() != null + && e.getParentId().equals(sysDepartmentEntity.getId())) + .toList(); + if (!parentDepartment.isEmpty()) { + e.setParentName(parentDepartment.get(0).getName()); + } + }); + return list; + } + + @Override + public boolean delete(JSONObject requestParams, Long... ids) { + super.delete(ids); + // 是否删除对应用户 否则移动到顶层部门 + if (requestParams.getBool("deleteUser")) { + return baseSysUserMapper + .deleteByQuery( + QueryWrapper.create().in(BaseSysUserEntity::getDepartmentId, (Object) ids)) > 0; + } else { + BaseSysDepartmentEntity topDepartment = getOne( + QueryWrapper.create().isNull(BaseSysDepartmentEntity::getParentId)); + if (topDepartment != null) { + UpdateChain.of(BaseSysUserEntity.class) + .set(BaseSysUserEntity::getDepartmentId, topDepartment.getId()) + .in(BaseSysUserEntity::getDepartmentId, (Object) ids).update(); + } + } + return false; + } +} \ No newline at end of file diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysLogServiceImpl.java b/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysLogServiceImpl.java new file mode 100644 index 0000000..fd4886c --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysLogServiceImpl.java @@ -0,0 +1,115 @@ +package com.cool.modules.base.service.sys.impl; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import com.cool.core.base.BaseServiceImpl; +import com.cool.core.config.LogProperties; +import com.cool.core.security.IgnoredUrlsProperties; +import com.cool.core.util.CoolSecurityUtil; +import com.cool.core.util.IPUtils; +import com.cool.core.util.PathUtils; +import com.cool.modules.base.entity.sys.BaseSysLogEntity; +import com.cool.modules.base.entity.sys.BaseSysUserEntity; +import com.cool.modules.base.entity.sys.table.BaseSysLogEntityTableDef; +import com.cool.modules.base.entity.sys.table.BaseSysUserEntityTableDef; +import com.cool.modules.base.mapper.sys.BaseSysLogMapper; +import com.cool.modules.base.service.sys.BaseSysConfService; +import com.cool.modules.base.service.sys.BaseSysLogService; +import com.mybatisflex.core.paginate.Page; +import com.mybatisflex.core.query.QueryWrapper; +import jakarta.servlet.http.HttpServletRequest; +import java.util.Date; +import java.util.concurrent.Executor; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +/** + * 系统日志 + */ +@RequiredArgsConstructor +@Service +public class BaseSysLogServiceImpl extends BaseServiceImpl + implements BaseSysLogService { + + private final BaseSysConfService baseSysConfService; + + private final IgnoredUrlsProperties ignoredUrlsProperties; + + private final IPUtils ipUtils; + + private final LogProperties logProperties; + + private final Executor logTaskExecutor; + + @Override + public Object page( + JSONObject requestParams, Page page, QueryWrapper queryWrapper) { + queryWrapper + .select( + BaseSysLogEntityTableDef.BASE_SYS_LOG_ENTITY.ALL_COLUMNS, + BaseSysUserEntityTableDef.BASE_SYS_USER_ENTITY.NAME) + .from(BaseSysLogEntityTableDef.BASE_SYS_LOG_ENTITY) + .leftJoin(BaseSysUserEntityTableDef.BASE_SYS_USER_ENTITY) + .on(BaseSysLogEntity::getUserId, BaseSysUserEntity::getId); + return mapper.paginate(page, queryWrapper); + } + + @Override + public void clear(boolean isAll) { + if (isAll) { + this.remove(QueryWrapper.create().ge(BaseSysLogEntity::getId, 0)); + } else { + String keepDay = baseSysConfService.getValue("logKeep"); + int keepDays = Integer.parseInt(StrUtil.isNotEmpty(keepDay) ? keepDay : "30"); + Date beforeDate = DateUtil.offsetDay(new Date(), -keepDays); + this.remove(QueryWrapper.create().lt(BaseSysLogEntity::getCreateTime, beforeDate)); + } + } + + @Override + public void record(HttpServletRequest request, JSONObject requestParams) { + String requestURI = request.getRequestURI(); + if (isIgnoreUrl(requestURI)) { + // 配置了忽略记录请求日志 + return; + } + String ipAddr = ipUtils.getIpAddr(request); + // 异步记录日志 + recordAsync(ipAddr, requestURI, requestParams); + } + + private boolean isIgnoreUrl(String requestURI) { + return PathUtils.isMatch(ignoredUrlsProperties.getLogUrls(), requestURI); + } + + public void recordAsync(String ipAddr, String requestURI, JSONObject requestParams) { + logTaskExecutor.execute(() -> { + JSONObject userInfo = CoolSecurityUtil.getAdminUserInfo(requestParams); + + Long userId = null; + if (userInfo != null) { + userId = userInfo.getLong("userId"); + } + + JSONObject newJSONObject = JSONUtil.parseObj(JSONUtil.toJsonStr(requestParams)); + newJSONObject.remove("tokenInfo"); + newJSONObject.remove("refreshToken"); + newJSONObject.remove("body"); + if (newJSONObject.toString().getBytes().length > logProperties.getMaxByteLength()) { + // 超过指定 + newJSONObject.clear(); + } + BaseSysLogEntity logEntity = new BaseSysLogEntity(); + logEntity.setAction(requestURI); + logEntity.setIp(ipAddr); + if (userId != null) { + logEntity.setUserId(userId); + } + logEntity.setParams(newJSONObject); + save(logEntity); + + }); + } +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysLoginServiceImpl.java b/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysLoginServiceImpl.java new file mode 100644 index 0000000..635f268 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysLoginServiceImpl.java @@ -0,0 +1,137 @@ +package com.cool.modules.base.service.sys.impl; + +import cn.hutool.captcha.CaptchaUtil; +import cn.hutool.captcha.GifCaptcha; +import cn.hutool.captcha.generator.RandomGenerator; +import cn.hutool.core.convert.Convert; +import cn.hutool.core.lang.Dict; +import cn.hutool.core.util.ObjUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.jwt.JWT; +import com.cool.core.cache.CoolCache; +import com.cool.core.enums.UserTypeEnum; +import com.cool.core.exception.CoolPreconditions; +import com.cool.core.security.jwt.JwtTokenUtil; +import com.cool.core.util.CoolSecurityUtil; +import com.cool.modules.base.dto.sys.BaseSysLoginDto; +import com.cool.modules.base.entity.sys.BaseSysUserEntity; +import com.cool.modules.base.mapper.sys.BaseSysUserMapper; +import com.cool.modules.base.service.sys.BaseSysLoginService; +import com.cool.modules.base.service.sys.BaseSysPermsService; +import com.mybatisflex.core.query.QueryWrapper; +import java.awt.Color; +import java.util.HashMap; +import java.util.Map; +import lombok.RequiredArgsConstructor; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class BaseSysLoginServiceImpl implements BaseSysLoginService { + + private final CoolCache coolCache; + + private final AuthenticationManager authenticationManager; + + private final JwtTokenUtil jwtTokenUtil; + + private final BaseSysUserMapper baseSysUserMapper; + + private final BaseSysPermsService baseSysPermsService; + + @Override + public Object captcha(UserTypeEnum userTypeEnum, String type, Integer width, Integer height) { + // 1、生成验证码 2、生成对应的ID并设置在缓存中,验证码过期时间30分钟; + Map result = new HashMap<>(); + String captchaId = StrUtil.uuid(); + result.put("captchaId", captchaId); + GifCaptcha gifCaptcha = CaptchaUtil.createGifCaptcha(width, height); + if (ObjUtil.equals(userTypeEnum, UserTypeEnum.APP)) { + gifCaptcha.setGenerator(new RandomGenerator("0123456789", 4)); + } else { + gifCaptcha.setGenerator(new RandomGenerator(4)); + } + gifCaptcha.setBackground(new Color(248, 248, 248)); + gifCaptcha.setMaxColor(60); + gifCaptcha.setMinColor(55); + result.put("data", "data:image/png;base64," + gifCaptcha.getImageBase64()); + coolCache.set("verify:img:" + captchaId, gifCaptcha.getCode(), 1800); + return result; + } + + @Override + public void captchaCheck(String captchaId, String code) { + String key = "verify:img:" + captchaId; + String verifyCode = coolCache.get(key, + String.class); + boolean flag = StrUtil.isNotEmpty(verifyCode) + && verifyCode.equalsIgnoreCase(code); + if (!flag) { + coolCache.del(key); + CoolPreconditions.alwaysThrow("验证码不正确"); + } + } + + @Override + public Object login(BaseSysLoginDto baseSysLoginDto) { + // 1、检查验证码是否正确 2、执行登录操作 + captchaCheck(baseSysLoginDto.getCaptchaId(), baseSysLoginDto.getVerifyCode()); + UsernamePasswordAuthenticationToken upToken = + new UsernamePasswordAuthenticationToken( + baseSysLoginDto.getUsername(), baseSysLoginDto.getPassword()); + Authentication authentication = authenticationManager.authenticate(upToken); + SecurityContextHolder.getContext().setAuthentication(authentication); + // 查询用户信息并生成token + BaseSysUserEntity baseSysUserEntity = + baseSysUserMapper.selectOneByQuery( + QueryWrapper.create() + .eq(BaseSysUserEntity::getUsername, baseSysLoginDto.getUsername())); + CoolPreconditions.check( + ObjectUtil.isEmpty(baseSysUserEntity) || baseSysUserEntity.getStatus() == 0, "用户已禁用"); + Long[] roleIds = baseSysPermsService.getRoles(baseSysUserEntity); + coolCache.del("verify:img:" + baseSysLoginDto.getCaptchaId()); + return generateToken(roleIds, baseSysUserEntity, null); + } + + @Override + public void logout(Long adminUserId, String username) { + CoolSecurityUtil.adminLogout(adminUserId, username); + } + + @Override + public Object refreshToken(String refreshToken) { + CoolPreconditions.check(!jwtTokenUtil.validateRefreshToken(refreshToken), "错误的refreshToken"); + JWT jwt = jwtTokenUtil.getTokenInfo(refreshToken); + CoolPreconditions.check(jwt == null || !(Boolean) jwt.getPayload("isRefresh"), + "错误的refreshToken"); + BaseSysUserEntity baseSysUserEntity = + baseSysUserMapper.selectOneById(Convert.toLong(jwt.getPayload("userId"))); + Long[] roleIds = baseSysPermsService.getRoles(baseSysUserEntity); + return generateToken(roleIds, baseSysUserEntity, refreshToken); + } + + private Dict generateToken(Long[] roleIds, BaseSysUserEntity baseSysUserEntity, String refreshToken) { + Dict tokenInfo = + Dict.create() + .set("userType", UserTypeEnum.ADMIN.name()) + .set("roleIds", roleIds) + .set("username", baseSysUserEntity.getUsername()) + .set("userId", baseSysUserEntity.getId()) + .set("tenantId", baseSysUserEntity.getTenantId()) + .set("passwordVersion", baseSysUserEntity.getPasswordV()); + String token = jwtTokenUtil.generateToken(tokenInfo); + if (StrUtil.isEmpty(refreshToken)) { + refreshToken = jwtTokenUtil.generateRefreshToken(tokenInfo); + } + return Dict.create() + .set("token", token) + .set("expire", jwtTokenUtil.getExpire()) + .set("refreshToken", refreshToken) + .set("refreshExpire", jwtTokenUtil.getRefreshExpire()); + } +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysMenuServiceImpl.java b/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysMenuServiceImpl.java new file mode 100644 index 0000000..0e3d930 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysMenuServiceImpl.java @@ -0,0 +1,180 @@ +package com.cool.modules.base.service.sys.impl; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.ObjUtil; +import cn.hutool.extra.spring.SpringUtil; +import cn.hutool.json.JSONObject; +import com.cool.CoolApplication; +import com.cool.core.base.BaseServiceImpl; +import com.cool.core.base.ModifyEnum; +import com.cool.core.eps.CoolEps; +import com.cool.core.i18n.I18nGenerator; +import com.cool.core.util.CompilerUtils; +import com.cool.core.util.CoolSecurityUtil; +import com.cool.core.util.PathUtils; +import com.cool.modules.base.entity.sys.BaseSysMenuEntity; +import com.cool.modules.base.mapper.sys.BaseSysMenuMapper; +import com.cool.modules.base.service.sys.BaseSysMenuService; +import com.cool.modules.base.service.sys.BaseSysPermsService; +import com.mybatisflex.core.query.QueryWrapper; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +/** + * 系统菜单 + */ +@Service +@RequiredArgsConstructor +public class BaseSysMenuServiceImpl extends BaseServiceImpl + implements BaseSysMenuService { + + final private BaseSysPermsService baseSysPermsService; + + final private CoolEps coolEps; + + @Override + public Object list(JSONObject requestParams, QueryWrapper queryWrapper) { + List list = baseSysPermsService.getMenus(CoolSecurityUtil.getAdminUsername()); + list.forEach(e -> { + List parent = list.stream() + .filter(sysMenuEntity -> e.getParentId() != null && e.getParentId() + .equals(sysMenuEntity.getId())) + .toList(); + if (!parent.isEmpty()) { + e.setParentName(parent.get(0).getName()); + } + }); + return list; + } + + @Override + public void modifyAfter(JSONObject requestParams, BaseSysMenuEntity sysMenuEntity, + ModifyEnum type) { + if (sysMenuEntity != null && sysMenuEntity.getId() != null) { + baseSysPermsService.refreshPermsByMenuId(requestParams.getLong("id")); + } + if (requestParams.get("ids") != null) { + Long[] ids = requestParams.get("ids", Long[].class); + for (Long id : ids) { + baseSysPermsService.refreshPermsByMenuId(id); + } + } + if (ModifyEnum.ADD.equals(type) || ModifyEnum.UPDATE.equals(type)) { + SpringUtil.getBean(I18nGenerator.class).asyncGenBaseMenu(); + } + } + + @Override + public boolean delete(Long... ids) { + super.delete(ids); + for (Long id : ids) { + this.delChildMenu(id); + } + return true; + } + + /** + * 删除子菜单 + * + * @param id 删除的菜单ID + */ + private void delChildMenu(Long id) { + List delMenu = list( + QueryWrapper.create().eq(BaseSysMenuEntity::getParentId, id)); + if (CollectionUtil.isEmpty(delMenu)) { + return; + } + Long[] ids = delMenu.stream().map(BaseSysMenuEntity::getId).toArray(Long[]::new); + if (ArrayUtil.isNotEmpty(ids)) { + delete(ids); + for (Long delId : ids) { + this.delChildMenu(delId); + } + } + } + + @Override + public Object export(List ids) { + List list = list( + QueryWrapper.create().in(BaseSysMenuEntity::getId, ids)); + List parentList = list.stream() + .filter(o -> ObjUtil.isEmpty(o.getParentId())).toList(); + Map> map = list.stream() + .filter(o -> ObjUtil.isNotEmpty(o.getParentId())) + .collect(Collectors.groupingBy(BaseSysMenuEntity::getParentId)); + parentList.forEach(o -> handler(o, map)); + return parentList; + } + + private void handler(BaseSysMenuEntity parentBaseSysMenuEntity, + Map> map) { + parentBaseSysMenuEntity.setChildMenus( + map.getOrDefault(parentBaseSysMenuEntity.getId(), new ArrayList<>())); + parentBaseSysMenuEntity.getChildMenus().forEach(o -> { + handler(o, map); + o.setId(null); + o.setParentId(null); + o.setCreateTime(null); + o.setUpdateTime(null); + }); + parentBaseSysMenuEntity.setId(null); + parentBaseSysMenuEntity.setParentId(null); + parentBaseSysMenuEntity.setCreateTime(null); + parentBaseSysMenuEntity.setUpdateTime(null); + } + + @Override + public boolean importMenu(List menus) { + menus.forEach(this::importMenu); + SpringUtil.getBean(I18nGenerator.class).asyncGenBaseMenu(); + return true; + } + + private void importMenu(BaseSysMenuEntity sysMenuEntity) { + sysMenuEntity.save(); + if (ObjUtil.isNotEmpty(sysMenuEntity.getChildMenus())) { + sysMenuEntity.getChildMenus().forEach(o -> { + o.setParentId(sysMenuEntity.getId()); + importMenu(o); + }); + } + } + + @Override + public void create(Map params) { + coolEps.clear(); + String module = (String) params.get("module"); + String controller = (String) params.get("controller"); + String entity = (String) params.get("entity"); + String service = (String) params.get("service"); + String serviceImpl = (String) params.get("service-impl"); + String mapper = (String) params.get("mapper"); + + String fileName = (String) params.get("fileName"); + List javaPathList = new ArrayList<>(); + String modulesPath = PathUtils.getModulesPath(); + // 创建的模块地址 + String actModulePath = CompilerUtils.createModule(modulesPath, module); + // 创建顺序不能调整,类加载的时候需按这个顺序加载,否则类找不到 + // 创建 entity + String entityPath = CompilerUtils.createEntity(actModulePath, fileName, entity); + javaPathList.add(entityPath); + // 创建 mapper + javaPathList.add(CompilerUtils.createMapper(actModulePath, fileName, mapper)); + // 创建 service + javaPathList.add(CompilerUtils.createService(actModulePath, fileName, service)); + // 创建 serviceImpl + javaPathList.add(CompilerUtils.createServiceImpl(actModulePath, fileName, serviceImpl)); + // 创建 controller + javaPathList.add(CompilerUtils.createController(actModulePath, fileName, controller)); + // 构建TableDef + CompilerUtils.compilerEntityTableDef(actModulePath, fileName, entityPath, javaPathList); + // 重启 + CoolApplication.restart(javaPathList); + } +} \ No newline at end of file diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysParamServiceImpl.java b/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysParamServiceImpl.java new file mode 100644 index 0000000..30607c6 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysParamServiceImpl.java @@ -0,0 +1,53 @@ +package com.cool.modules.base.service.sys.impl; + +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONObject; +import com.cool.core.base.BaseServiceImpl; +import com.cool.core.cache.CoolCache; +import com.cool.modules.base.entity.sys.BaseSysParamEntity; +import com.cool.modules.base.mapper.sys.BaseSysParamMapper; +import com.cool.modules.base.service.sys.BaseSysParamService; +import com.mybatisflex.core.query.QueryWrapper; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +/** + * 系统参数配置 + */ +@Service +@RequiredArgsConstructor +public class BaseSysParamServiceImpl extends BaseServiceImpl + implements BaseSysParamService { + + final private CoolCache coolCache; + + @Override + public String htmlByKey(String key) { + String data = dataByKey(key); + return "" + (StrUtil.isNotEmpty(data) ? data : "key notfound") + + ""; + } + + @Override + public String dataByKey(String key) { + BaseSysParamEntity baseSysParamEntity = coolCache.get(key, BaseSysParamEntity.class); + if (baseSysParamEntity == null) { + baseSysParamEntity = getOne( + QueryWrapper.create().eq(BaseSysParamEntity::getKeyName, key)); + } + if (baseSysParamEntity != null) { + coolCache.set("param:" + baseSysParamEntity.getKeyName(), baseSysParamEntity); + return baseSysParamEntity.getData(); + } + return null; + } + + @Override + public void modifyAfter(JSONObject requestParams, BaseSysParamEntity baseSysParamEntity) { + List list = this.list(); + list.forEach(e -> { + coolCache.set("param:" + e.getKeyName(), e); + }); + } +} \ No newline at end of file diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysPermsServiceImpl.java b/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysPermsServiceImpl.java new file mode 100644 index 0000000..42919a5 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysPermsServiceImpl.java @@ -0,0 +1,262 @@ +package com.cool.modules.base.service.sys.impl; + +import static com.cool.modules.base.entity.sys.table.BaseSysMenuEntityTableDef.BASE_SYS_MENU_ENTITY; +import static com.cool.modules.base.entity.sys.table.BaseSysRoleMenuEntityTableDef.BASE_SYS_ROLE_MENU_ENTITY; +import static com.cool.modules.base.entity.sys.table.BaseSysUserRoleEntityTableDef.BASE_SYS_USER_ROLE_ENTITY; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.convert.Convert; +import cn.hutool.core.lang.Dict; +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.cool.core.cache.CoolCache; +import com.cool.core.util.CoolSecurityUtil; +import com.cool.core.util.SpringContextUtils; +import com.cool.modules.base.entity.sys.*; +import com.cool.modules.base.mapper.sys.*; +import com.cool.modules.base.service.sys.BaseSysPermsService; +import com.mybatisflex.core.query.QueryWrapper; +import com.mybatisflex.core.row.Row; +import java.util.*; +import java.util.concurrent.ExecutorService; +import lombok.RequiredArgsConstructor; +import org.springframework.scheduling.annotation.Async; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class BaseSysPermsServiceImpl implements BaseSysPermsService { + final private CoolCache coolCache; + + final private BaseSysUserMapper baseSysUserMapper; + + final private BaseSysUserRoleMapper baseSysUserRoleMapper; + + final private BaseSysMenuMapper baseSysMenuMapper; + + final private BaseSysRoleMenuMapper baseSysRoleMenuMapper; + + final private BaseSysRoleDepartmentMapper baseSysRoleDepartmentMapper; + + final private BaseSysDepartmentMapper baseSysDepartmentMapper; + + final private ExecutorService cachedThreadPool; + + @Override + public Long[] loginDepartmentIds() { + String username = CoolSecurityUtil.getAdminUsername(); + if (username.equals("admin")) { + return baseSysDepartmentMapper.selectAll().stream().map(BaseSysDepartmentEntity::getId) + .toArray(Long[]::new); + } else { + Long[] roleIds = getRoles(username); + return baseSysRoleDepartmentMapper + .selectListByQuery( + QueryWrapper.create().in(BaseSysRoleDepartmentEntity::getRoleId, (Object) roleIds)) + .stream().map(BaseSysRoleDepartmentEntity::getDepartmentId).toArray(Long[]::new); + } + } + + @Override + public Long[] getDepartmentIdsByRoleIds(Long[] roleIds) { + return getLongs(roleIds); + } + + private Long[] getLongs(Long[] roleIds) { + if (ObjectUtil.isEmpty(roleIds)) { + return new Long[]{}; + } + QueryWrapper queryWrapper = QueryWrapper.create(); + if (!CollUtil.toList(roleIds).contains(1L)) { + queryWrapper.in(BaseSysRoleDepartmentEntity::getRoleId, (Object) roleIds); + } + return baseSysRoleDepartmentMapper + .selectListByQuery(queryWrapper) + .stream().map(BaseSysRoleDepartmentEntity::getDepartmentId).toArray(Long[]::new); + } + + @Override + public Long[] getDepartmentIdsByRoleIds(Long userId) { + Long[] roleIds = getRoles(userId); + return getLongs(roleIds); + } + + @Override + public String[] getPermsCache(Long userId) { + Object result = coolCache.get("admin:perms:" + userId); + if (ObjectUtil.isNotEmpty(result)) { + return Convert.toStrArray(result); + } + return getPerms(userId); + } + + @Override + public Long[] getRoles(Long userId) { + return getRoles(baseSysUserMapper.selectOneById(userId)); + } + + @Override + public Long[] getRoles(String username) { + return getRoles( + baseSysUserMapper.selectOneByQuery(QueryWrapper.create().eq(BaseSysUserEntity::getUsername, username))); + } + + @Override + public Long[] getRoles(BaseSysUserEntity userEntity) { + Long[] roleIds = null; + if (!userEntity.getUsername().equals("admin")) { + List list = baseSysUserRoleMapper + .selectListByQuery(QueryWrapper.create().eq(BaseSysUserRoleEntity::getUserId, userEntity.getId())); + roleIds = list.stream().map(BaseSysUserRoleEntity::getRoleId).toArray(Long[]::new); + if (Arrays.asList(roleIds).contains(1L)) { + roleIds = null; + } + } + return roleIds; + } + + @Override + public String[] getPerms(Long userId) { + return getPerms(getRoles(userId)); + } + + @Override + public String[] getPerms(Long[] roleIds) { + List menus = getMenus(roleIds); + Set perms = new HashSet<>(); + String[] permsData = menus.stream().map(BaseSysMenuEntity::getPerms) + .filter(itemPerms -> !StrUtil.isEmpty(itemPerms)).toArray(String[]::new); + for (String permData : permsData) { + perms.addAll(Arrays.asList(permData.split(","))); + } + return ArrayUtil.toArray(perms, String.class); + } + + @Override + public List getMenus(Long[] roleIds) { + if (CollUtil.toList(roleIds).contains(1L)) { + roleIds = null; + } + if (roleIds != null && roleIds.length == 0) { + return new ArrayList<>(); + } + + QueryWrapper queryWrapper = QueryWrapper.create().select(BASE_SYS_MENU_ENTITY.ALL_COLUMNS).from(BASE_SYS_MENU_ENTITY); + if (ObjectUtil.isNotEmpty(roleIds)) { + queryWrapper.leftJoin(BASE_SYS_ROLE_MENU_ENTITY).on(BASE_SYS_MENU_ENTITY.ID.eq(BASE_SYS_ROLE_MENU_ENTITY.MENU_ID)).and(BASE_SYS_ROLE_MENU_ENTITY.ROLE_ID.in((Object) roleIds)); + } + return baseSysMenuMapper.selectListByQuery(queryWrapper.groupBy(BASE_SYS_MENU_ENTITY.ID).orderBy(BASE_SYS_MENU_ENTITY.ORDER_NUM, false)); + } + + @Override + public List getMenus(Long userId) { + return getMenus(getRoles(userId)); + } + + @Override + public List getMenus(String username) { + BaseSysUserEntity sysUserEntity = baseSysUserMapper + .selectOneByQuery(QueryWrapper.create().eq(BaseSysUserEntity::getUsername, username)); + return getMenus(sysUserEntity.getId()); + } + + @Override + public String[] getAllPerms() { + return getPerms((Long[]) null); + } + + @Override + public Dict permmenu(Long adminUserId) { + return Dict.create().set("menus", getMenus(adminUserId)).set("perms", getPerms(adminUserId)); + } + + @Override + public void updatePerms(Long roleId, Long[] menuIdList, Long[] departmentIds) { + // 更新菜单权限 + baseSysRoleMenuMapper.deleteByQuery(QueryWrapper.create().eq(BaseSysRoleMenuEntity::getRoleId, roleId)); + List batchRoleMenuList = new ArrayList<>(); + for (Long menuId : menuIdList) { + BaseSysRoleMenuEntity roleMenuEntity = new BaseSysRoleMenuEntity(); + roleMenuEntity.setRoleId(roleId); + roleMenuEntity.setMenuId(menuId); + batchRoleMenuList.add(roleMenuEntity); + } + if (ObjectUtil.isNotEmpty(batchRoleMenuList)) { + baseSysRoleMenuMapper.insertBatch(batchRoleMenuList); + } + // 更新部门权限 + baseSysRoleDepartmentMapper + .deleteByQuery(QueryWrapper.create().eq(BaseSysRoleDepartmentEntity::getRoleId, roleId)); + List batchRoleDepartmentList = new ArrayList<>(); + for (Long departmentId : departmentIds) { + BaseSysRoleDepartmentEntity roleDepartmentEntity = new BaseSysRoleDepartmentEntity(); + roleDepartmentEntity.setRoleId(roleId); + roleDepartmentEntity.setDepartmentId(departmentId); + batchRoleDepartmentList.add(roleDepartmentEntity); + } + if (ObjectUtil.isNotEmpty(batchRoleDepartmentList)) { + baseSysRoleDepartmentMapper.insertBatch(batchRoleDepartmentList); + } + cachedThreadPool.submit(() -> { + // 刷新对应角色用户的权限 + List userRoles = baseSysUserRoleMapper + .selectListByQuery(QueryWrapper.create().eq(BaseSysUserRoleEntity::getRoleId, roleId)); + for (BaseSysUserRoleEntity userRole : userRoles) { + refreshPerms(userRole.getUserId()); + } + }); + } + + @Override + public void updateUserRole(Long userId, Long[] roleIdList) { + baseSysUserRoleMapper.deleteByQuery(QueryWrapper.create().eq(BaseSysUserRoleEntity::getUserId, userId)); + if (roleIdList == null) { + roleIdList = new Long[0]; + } + for (Long roleId : roleIdList) { + BaseSysUserRoleEntity sysUserRoleEntity = new BaseSysUserRoleEntity(); + sysUserRoleEntity.setRoleId(roleId); + sysUserRoleEntity.setUserId(userId); + baseSysUserRoleMapper.insert(sysUserRoleEntity); + } + refreshPerms(userId); + } + + @Override + public void refreshPerms(Long userId) { + BaseSysUserEntity baseSysUserEntity = baseSysUserMapper.selectOneById(userId); + if (baseSysUserEntity != null && baseSysUserEntity.getStatus() != 0) { + SpringContextUtils.getBean(UserDetailsService.class).loadUserByUsername(baseSysUserEntity.getUsername()); + } + if (baseSysUserEntity != null && baseSysUserEntity.getStatus() == 0) { + CoolSecurityUtil.adminLogout(baseSysUserEntity.getId(), baseSysUserEntity.getUsername()); + } + } + + @Async + @Override + public void refreshPermsByMenuId(Long menuId) { + // 刷新超管权限、 找出这个菜单的所有用户、 刷新用户权限 + BaseSysUserEntity admin = baseSysUserMapper + .selectOneByQuery(QueryWrapper.create().eq(BaseSysUserEntity::getUsername, "admin")); + refreshPerms(admin.getId()); + List list = baseSysRoleMenuMapper.selectRowsByQuery(QueryWrapper.create().select(BASE_SYS_USER_ROLE_ENTITY.USER_ID) + .from(BASE_SYS_ROLE_MENU_ENTITY).leftJoin(BASE_SYS_USER_ROLE_ENTITY) + .on(BASE_SYS_ROLE_MENU_ENTITY.ROLE_ID.eq(BASE_SYS_USER_ROLE_ENTITY.ROLE_ID)).and(BASE_SYS_ROLE_MENU_ENTITY.MENU_ID.eq(menuId, ObjectUtil.isNotEmpty(menuId))).groupBy(BASE_SYS_USER_ROLE_ENTITY.USER_ID)); + for (Row row : list) { + refreshPerms(row.getLong("userId")); + } + } + + @Override + public void refreshPermsByRoleId(Long roleId) { + // 找出角色对应的所有用户 + List list = baseSysUserRoleMapper + .selectListByQuery(QueryWrapper.create().eq(BaseSysUserRoleEntity::getRoleId, roleId)); + list.forEach(e -> { + refreshPerms(e.getUserId()); + }); + } +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysRoleServiceImpl.java b/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysRoleServiceImpl.java new file mode 100644 index 0000000..159ae97 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysRoleServiceImpl.java @@ -0,0 +1,98 @@ +package com.cool.modules.base.service.sys.impl; + +import cn.hutool.core.lang.Dict; +import cn.hutool.json.JSONObject; +import com.cool.core.base.BaseServiceImpl; +import com.cool.core.base.ModifyEnum; +import com.cool.core.exception.CoolException; +import com.cool.core.util.CoolSecurityUtil; +import com.cool.modules.base.entity.sys.BaseSysRoleDepartmentEntity; +import com.cool.modules.base.entity.sys.BaseSysRoleEntity; +import com.cool.modules.base.entity.sys.BaseSysRoleMenuEntity; +import com.cool.modules.base.mapper.sys.BaseSysRoleDepartmentMapper; +import com.cool.modules.base.mapper.sys.BaseSysRoleMapper; +import com.cool.modules.base.mapper.sys.BaseSysRoleMenuMapper; +import com.cool.modules.base.service.sys.BaseSysPermsService; +import com.cool.modules.base.service.sys.BaseSysRoleService; +import com.mybatisflex.core.query.QueryWrapper; + +import java.util.Arrays; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +/** + * 系统角色 + */ +@RequiredArgsConstructor +@Service +public class BaseSysRoleServiceImpl extends BaseServiceImpl + implements BaseSysRoleService { + + final private BaseSysRoleMapper baseSysRoleMapper; + + final private BaseSysRoleMenuMapper baseSysRoleMenuMapper; + + final private BaseSysRoleDepartmentMapper baseSysRoleDepartmentMapper; + + final private BaseSysPermsService baseSysPermsService; + + @Override + public Object add(JSONObject requestParams, BaseSysRoleEntity entity) { + BaseSysRoleEntity checkLabel = getOne(QueryWrapper.create().eq(BaseSysRoleEntity::getLabel, entity.getLabel())); + if (checkLabel != null) { + throw new CoolException("标识已存在"); + } + entity.setUserId((CoolSecurityUtil.getAdminUserInfo(requestParams).getLong("userId"))); + return super.add(requestParams, entity); + } + + @Override + public BaseSysRoleEntity info(Long id) { + BaseSysRoleEntity roleEntity = getById(id); + Long[] menuIdList = new Long[0]; + Long[] departmentIdList = new Long[0]; + if (roleEntity != null) { + List list = baseSysRoleMenuMapper + .selectListByQuery(QueryWrapper.create().eq(BaseSysRoleMenuEntity::getRoleId, id, !id.equals(1L))); + menuIdList = list.stream().map(BaseSysRoleMenuEntity::getMenuId).toArray(Long[]::new); + + List departmentEntities = baseSysRoleDepartmentMapper.selectListByQuery( + QueryWrapper.create().eq(BaseSysRoleDepartmentEntity::getRoleId, id, !id.equals(1L))); + + departmentIdList = departmentEntities.stream().map(BaseSysRoleDepartmentEntity::getDepartmentId) + .toArray(Long[]::new); + + + roleEntity.setMenuIdList(Arrays.asList( menuIdList )); + roleEntity.setDepartmentIdList(Arrays.asList(departmentIdList )); + + } + + return roleEntity; + } + + @Override + public void modifyAfter(JSONObject requestParams, BaseSysRoleEntity baseSysRoleEntity, ModifyEnum type) { + if (type == ModifyEnum.DELETE) { + Long[] ids = requestParams.get("ids", Long[].class); + for (Long id : ids) { + baseSysPermsService.refreshPermsByRoleId(id); + } + } else { + baseSysPermsService.updatePerms(baseSysRoleEntity.getId(), requestParams.get("menuIdList", Long[].class), + requestParams.get("departmentIdList", Long[].class)); + } + } + + @Override + public Object list(JSONObject requestParams, QueryWrapper queryWrapper) { + return baseSysRoleMapper.selectListByQuery(queryWrapper.ne(BaseSysRoleEntity::getId, 1L).and(qw -> { + JSONObject object = CoolSecurityUtil.getAdminUserInfo(requestParams); + qw.eq(BaseSysRoleEntity::getUserId, object.get("userId")).or(w -> { + w.in(BaseSysRoleEntity::getId, + (Object) object.get("roleIds", Long[].class)); + }); + }, !CoolSecurityUtil.getAdminUsername().equals("admin"))); + } +} \ No newline at end of file diff --git a/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysUserServiceImpl.java b/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysUserServiceImpl.java new file mode 100644 index 0000000..7ba615c --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/base/service/sys/impl/BaseSysUserServiceImpl.java @@ -0,0 +1,187 @@ +package com.cool.modules.base.service.sys.impl; + +import static com.cool.modules.base.entity.sys.table.BaseSysDepartmentEntityTableDef.BASE_SYS_DEPARTMENT_ENTITY; +import static com.cool.modules.base.entity.sys.table.BaseSysRoleEntityTableDef.BASE_SYS_ROLE_ENTITY; +import static com.cool.modules.base.entity.sys.table.BaseSysUserEntityTableDef.BASE_SYS_USER_ENTITY; +import static com.cool.modules.base.entity.sys.table.BaseSysUserRoleEntityTableDef.BASE_SYS_USER_ROLE_ENTITY; +import static com.mybatisflex.core.query.QueryMethods.groupConcat; + +import cn.hutool.core.lang.Dict; +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.crypto.digest.MD5; +import cn.hutool.json.JSONObject; +import com.cool.core.base.BaseServiceImpl; +import com.cool.core.base.ModifyEnum; +import com.cool.core.cache.CoolCache; +import com.cool.core.exception.CoolPreconditions; +import com.cool.core.util.CoolSecurityUtil; +import com.cool.core.util.DatabaseDialectUtils; +import com.cool.modules.base.entity.sys.BaseSysDepartmentEntity; +import com.cool.modules.base.entity.sys.BaseSysUserEntity; +import com.cool.modules.base.mapper.sys.BaseSysDepartmentMapper; +import com.cool.modules.base.mapper.sys.BaseSysUserMapper; +import com.cool.modules.base.service.sys.BaseSysPermsService; +import com.cool.modules.base.service.sys.BaseSysUserService; +import com.mybatisflex.core.paginate.Page; +import com.mybatisflex.core.query.QueryWrapper; +import com.mybatisflex.core.update.UpdateChain; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 系统用户 + */ +@Service +@RequiredArgsConstructor +public class BaseSysUserServiceImpl extends BaseServiceImpl + implements BaseSysUserService { + + final private CoolCache coolCache; + + final private BaseSysPermsService baseSysPermsService; + + final private BaseSysDepartmentMapper baseSysDepartmentMapper; + + @Override + public Object page(JSONObject requestParams, Page page, QueryWrapper qw) { + String keyWord = requestParams.getStr("keyWord"); + Integer status = requestParams.getInt("status"); + Long[] departmentIds = requestParams.get("departmentIds", Long[].class); + JSONObject tokenInfo = CoolSecurityUtil.getAdminUserInfo(requestParams); + // 用户的部门权限 + Long[] permsDepartmentArr = coolCache.get("admin:department:" + tokenInfo.get("userId"), + Long[].class); + if (DatabaseDialectUtils.isPostgresql()) { + // 兼容postgresql + qw.select("base_sys_user.id","base_sys_user.create_time","base_sys_user.department_id", + "base_sys_user.email","base_sys_user.head_img","base_sys_user.name","base_sys_user.nick_name", + "base_sys_user.phone","base_sys_user.remark","base_sys_user.status", + "base_sys_user.update_time","base_sys_user.username", + "string_agg(base_sys_role.name, ', ') AS roleName", + "base_sys_department.name AS departmentName" + ); + } else { + qw.select(BASE_SYS_USER_ENTITY.ALL_COLUMNS, + groupConcat(BASE_SYS_ROLE_ENTITY.NAME).as("roleName"), + BASE_SYS_DEPARTMENT_ENTITY.NAME.as("departmentName") + ); + } + + qw.from(BASE_SYS_USER_ENTITY).leftJoin(BASE_SYS_USER_ROLE_ENTITY) + .on(BASE_SYS_USER_ENTITY.ID.eq(BASE_SYS_USER_ROLE_ENTITY.USER_ID)) + .leftJoin(BASE_SYS_ROLE_ENTITY) + .on(BASE_SYS_USER_ROLE_ENTITY.ROLE_ID.eq(BASE_SYS_ROLE_ENTITY.ID)) + .leftJoin(BASE_SYS_DEPARTMENT_ENTITY) + .on(BASE_SYS_USER_ENTITY.DEPARTMENT_ID.eq(BASE_SYS_DEPARTMENT_ENTITY.ID)); + + // 不显示admin用户 + qw.and(BASE_SYS_USER_ENTITY.USERNAME.ne("admin")); + // 筛选部门 + qw.and(BASE_SYS_USER_ENTITY.DEPARTMENT_ID.in(departmentIds, + ArrayUtil.isNotEmpty(departmentIds))); + // 筛选状态 + qw.and(BASE_SYS_USER_ENTITY.STATUS.eq(status, status != null)); + // 搜索关键字 + if (StrUtil.isNotEmpty(keyWord)) { + qw.and(BASE_SYS_USER_ENTITY.NAME.like(keyWord) + .or(BASE_SYS_USER_ENTITY.USERNAME.like(keyWord))); + } + // 过滤部门权限 + qw.and(BASE_SYS_USER_ENTITY.DEPARTMENT_ID.in( + permsDepartmentArr == null || permsDepartmentArr.length == 0 ? new Long[]{null} + : permsDepartmentArr, + !CoolSecurityUtil.getAdminUsername().equals("admin"))); + if (DatabaseDialectUtils.isPostgresql()) { + // 兼容postgresql + qw.groupBy("base_sys_user.id","base_sys_user.create_time","base_sys_user.department_id", + "base_sys_user.email","base_sys_user.head_img","base_sys_user.name","base_sys_user.nick_name", + "base_sys_user.phone","base_sys_user.remark","base_sys_user.status", + "base_sys_user.update_time","base_sys_user.username", + "base_sys_department.name"); + } else { + qw.groupBy(BASE_SYS_USER_ENTITY.ID); + } + return mapper.paginate(page, qw); + } + + @Override + public void personUpdate(Long userId, Dict body) { + BaseSysUserEntity userEntity = getById(userId); + CoolPreconditions.checkEmpty(userEntity, "用户不存在"); + userEntity.setNickName(body.getStr("nickName")); + userEntity.setHeadImg(body.getStr("headImg")); + // 修改密码 + if (StrUtil.isNotEmpty(body.getStr("password"))) { + userEntity.setPassword(MD5.create().digestHex(body.getStr("password"))); + userEntity.setPasswordV(userEntity.getPasswordV() + 1); + coolCache.set("admin:passwordVersion:" + userId, userEntity.getPasswordV()); + } + updateById(userEntity); + } + + @Override + public void move(Long departmentId, Long[] userIds) { + UpdateChain.of(BaseSysUserEntity.class) + .set(BaseSysUserEntity::getDepartmentId, departmentId) + .in(BaseSysUserEntity::getId, (Object) userIds).update(); + } + + @Override + public Long add(JSONObject requestParams, BaseSysUserEntity entity) { + BaseSysUserEntity check = getOne( + QueryWrapper.create().eq(BaseSysUserEntity::getUsername, entity.getUsername())); + CoolPreconditions.check(check != null, "用户名已存在"); + entity.setPassword(MD5.create().digestHex(entity.getPassword())); + super.add(requestParams, entity); + return entity.getId(); + } + + @Override + public boolean update(JSONObject requestParams, BaseSysUserEntity entity) { + CoolPreconditions.check( + StrUtil.isNotEmpty(entity.getUsername()) && entity.getUsername().equals("admin"), + "非法操作"); + BaseSysUserEntity userEntity = getById(entity.getId()); + if (StrUtil.isNotEmpty(entity.getPassword())) { + entity.setPasswordV(entity.getPasswordV() + 1); + entity.setPassword(MD5.create().digestHex(entity.getPassword())); + coolCache.set("admin:passwordVersion:" + entity.getId(), entity.getPasswordV()); + } else { + entity.setPassword(userEntity.getPassword()); + entity.setPasswordV(userEntity.getPasswordV()); + } + // 被禁用 + if (entity.getStatus() == 0) { + CoolSecurityUtil.adminLogout(entity); + } + return super.update(requestParams, entity); + } + + @Override + public void modifyAfter(JSONObject requestParams, BaseSysUserEntity baseSysUserEntity, + ModifyEnum type) { + if (type != ModifyEnum.DELETE && requestParams.get("roleIdList", Long[].class) != null) { + // 刷新权限 + baseSysPermsService.updateUserRole(baseSysUserEntity.getId(), + requestParams.get("roleIdList", Long[].class)); + } + } + + @Override + public BaseSysUserEntity info(Long id) { + BaseSysUserEntity userEntity = getById(id); + Long[] roleIdList = baseSysPermsService.getRoles(id); + BaseSysDepartmentEntity departmentEntity = baseSysDepartmentMapper.selectOneById( + userEntity.getDepartmentId()); + userEntity.setPassword(null); + + + userEntity.setRoleIdList(List.of(roleIdList)); + userEntity.setDepartmentName(departmentEntity != null ? departmentEntity.getName() : userEntity.getDepartmentName() ); + + return userEntity; + } +} \ No newline at end of file diff --git a/cool-admin-java/src/main/java/com/cool/modules/dict/controller/admin/AdminDictInfoController.java b/cool-admin-java/src/main/java/com/cool/modules/dict/controller/admin/AdminDictInfoController.java new file mode 100644 index 0000000..a9288d0 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/dict/controller/admin/AdminDictInfoController.java @@ -0,0 +1,57 @@ +package com.cool.modules.dict.controller.admin; + +import cn.hutool.core.lang.Dict; +import cn.hutool.json.JSONObject; +import com.cool.core.annotation.CoolRestController; +import com.cool.core.annotation.TokenIgnore; +import com.cool.core.base.BaseController; +import com.cool.core.request.CrudOption; +import com.cool.core.request.R; +import com.cool.core.util.I18nUtil; +import com.cool.modules.dict.entity.DictInfoEntity; +import com.cool.modules.dict.entity.table.DictInfoEntityTableDef; +import com.cool.modules.dict.service.DictInfoService; +import com.mybatisflex.core.query.QueryWrapper; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; + +/** + * 字典信息 + */ +@Tag(name = "字典信息", description = "字典信息") +@CoolRestController(api = {"add", "delete", "update", "page", "list", "info"}) +public class AdminDictInfoController extends BaseController { + @Override + protected void init(HttpServletRequest request, JSONObject requestParams) { + setListOption(createOp().fieldEq(DictInfoEntityTableDef.DICT_INFO_ENTITY.TYPE_ID) + .keyWordLikeFields(DictInfoEntityTableDef.DICT_INFO_ENTITY.NAME) + .queryWrapper(QueryWrapper.create().orderBy(DictInfoEntityTableDef.DICT_INFO_ENTITY.CREATE_TIME, false)) + .transform(o -> { + DictInfoEntity entity = (DictInfoEntity) o; + entity.setName(I18nUtil.getI18nDictInfo(entity.getName())); + })); + CrudOption transform = createOp().transform(o -> { + DictInfoEntity entity = (DictInfoEntity) o; + entity.setName(I18nUtil.getI18nDictInfo(entity.getName())); + }); + setPageOption(transform); + setInfoOption(transform); + } + + @Operation(summary = "获得字典数据", description = "获得字典数据信息") + @PostMapping("/data") + public R data(@RequestBody Dict body) { + return R.ok(this.service.data(body.get("types", null))); + } + + @TokenIgnore + @GetMapping("/types") + @Operation(summary = "获得字典数据", description = "获得字典数据信息") + public R types() { + return R.ok(this.service.types()); + } +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/dict/controller/admin/AdminDictTypeController.java b/cool-admin-java/src/main/java/com/cool/modules/dict/controller/admin/AdminDictTypeController.java new file mode 100644 index 0000000..fb0ff5f --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/dict/controller/admin/AdminDictTypeController.java @@ -0,0 +1,36 @@ +package com.cool.modules.dict.controller.admin; + +import static com.cool.modules.dict.entity.table.DictTypeEntityTableDef.DICT_TYPE_ENTITY; + +import cn.hutool.json.JSONObject; +import com.cool.core.annotation.CoolRestController; +import com.cool.core.base.BaseController; +import com.cool.core.request.CrudOption; +import com.cool.core.util.I18nUtil; +import com.cool.modules.dict.entity.DictTypeEntity; +import com.cool.modules.dict.service.DictTypeService; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletRequest; + +/** + * 字典类型 + */ +@Tag(name = "字典类型", description = "字典类型") +@CoolRestController(api = {"add", "delete", "update", "page", "list", "info"}) +public class AdminDictTypeController extends BaseController { + + @Override + protected void init(HttpServletRequest request, JSONObject requestParams) { + setPageOption( + createOp().select(DICT_TYPE_ENTITY.ID, DICT_TYPE_ENTITY.KEY, DICT_TYPE_ENTITY.NAME).transform(o -> { + DictTypeEntity entity = (DictTypeEntity) o; + entity.setName(I18nUtil.getI18nDictType(entity.getName())); + })); + CrudOption transform = createOp().transform(o -> { + DictTypeEntity entity = (DictTypeEntity) o; + entity.setName(I18nUtil.getI18nDictType(entity.getName())); + }); + setPageOption(transform); + setInfoOption(transform); + } +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/dict/controller/app/AppDictInfoController.java b/cool-admin-java/src/main/java/com/cool/modules/dict/controller/app/AppDictInfoController.java new file mode 100644 index 0000000..bad4ba8 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/dict/controller/app/AppDictInfoController.java @@ -0,0 +1,34 @@ +package com.cool.modules.dict.controller.app; + +import cn.hutool.core.convert.Convert; +import cn.hutool.core.lang.Dict; +import cn.hutool.json.JSONObject; +import com.cool.core.annotation.CoolRestController; +import com.cool.core.base.BaseController; +import com.cool.core.request.R; +import com.cool.modules.dict.entity.DictInfoEntity; +import com.cool.modules.dict.service.DictInfoService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; + +import jakarta.servlet.http.HttpServletRequest; + +/** + * 字典信息 + */ +@Tag(name = "字典信息", description = "字典信息") +@CoolRestController(api = {}) +public class AppDictInfoController extends BaseController { + @Override + protected void init(HttpServletRequest request, JSONObject requestParams) { + + } + + @Operation(summary = "获得字典数据", description = "获得字典数据信息") + @PostMapping("/data") + public R data(@RequestBody Dict body) { + return R.ok(this.service.data(Convert.toList(String.class, body.get("types")))); + } +} \ No newline at end of file diff --git a/cool-admin-java/src/main/java/com/cool/modules/dict/entity/DictInfoEntity.java b/cool-admin-java/src/main/java/com/cool/modules/dict/entity/DictInfoEntity.java new file mode 100644 index 0000000..ff0c944 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/dict/entity/DictInfoEntity.java @@ -0,0 +1,32 @@ +package com.cool.modules.dict.entity; + +import com.cool.core.base.BaseEntity; +import com.tangzc.mybatisflex.autotable.annotation.ColumnDefine; +import com.mybatisflex.annotation.Table; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@Table(value = "dict_info", comment = "字典信息") +public class DictInfoEntity extends BaseEntity { + + @ColumnDefine(comment = "类型ID", notNull = true) + private Long typeId; + + @ColumnDefine(comment = "父ID") + private Long parentId; + + @ColumnDefine(comment = "名称", notNull = true) + private String name; + + @ColumnDefine(comment = "值") + private String value; + + @ColumnDefine(comment = "排序", defaultValue = "0") + private Integer orderNum; + + @ColumnDefine(comment = "备注") + private String remark; + +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/dict/entity/DictTypeEntity.java b/cool-admin-java/src/main/java/com/cool/modules/dict/entity/DictTypeEntity.java new file mode 100644 index 0000000..35a2fd2 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/dict/entity/DictTypeEntity.java @@ -0,0 +1,21 @@ +package com.cool.modules.dict.entity; + +import com.cool.core.base.BaseEntity; +import com.mybatisflex.annotation.Table; +import com.tangzc.mybatisflex.autotable.annotation.ColumnDefine; +import com.tangzc.mybatisflex.autotable.annotation.UniIndex; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@Table(value = "dict_type", comment = "字典类型") +public class DictTypeEntity extends BaseEntity { + + @ColumnDefine(comment = "名称", notNull = true) + private String name; + + @ColumnDefine(comment = "标识", notNull = true) + @UniIndex + private String key; +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/dict/mapper/DictInfoMapper.java b/cool-admin-java/src/main/java/com/cool/modules/dict/mapper/DictInfoMapper.java new file mode 100644 index 0000000..6c79be5 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/dict/mapper/DictInfoMapper.java @@ -0,0 +1,10 @@ +package com.cool.modules.dict.mapper; + +import com.mybatisflex.core.BaseMapper; +import com.cool.modules.dict.entity.DictInfoEntity; + +/** + * 字典信息 + */ +public interface DictInfoMapper extends BaseMapper { +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/dict/mapper/DictTypeMapper.java b/cool-admin-java/src/main/java/com/cool/modules/dict/mapper/DictTypeMapper.java new file mode 100644 index 0000000..1c01714 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/dict/mapper/DictTypeMapper.java @@ -0,0 +1,10 @@ +package com.cool.modules.dict.mapper; + +import com.mybatisflex.core.BaseMapper; +import com.cool.modules.dict.entity.DictTypeEntity; + +/** + * 字典类型 + */ +public interface DictTypeMapper extends BaseMapper { +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/dict/service/DictInfoService.java b/cool-admin-java/src/main/java/com/cool/modules/dict/service/DictInfoService.java new file mode 100644 index 0000000..2dfec7e --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/dict/service/DictInfoService.java @@ -0,0 +1,21 @@ +package com.cool.modules.dict.service; + +import com.cool.core.base.BaseService; +import com.cool.modules.dict.entity.DictInfoEntity; + +import java.util.List; + +/** + * 字典信息 + */ +public interface DictInfoService extends BaseService { + /** + * 字典数据 + * + * @param types 字典类型 + * @return + */ + Object data(List types); + + Object types(); +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/dict/service/DictTypeService.java b/cool-admin-java/src/main/java/com/cool/modules/dict/service/DictTypeService.java new file mode 100644 index 0000000..0c17f82 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/dict/service/DictTypeService.java @@ -0,0 +1,10 @@ +package com.cool.modules.dict.service; + +import com.cool.core.base.BaseService; +import com.cool.modules.dict.entity.DictTypeEntity; + +/** + * 字典类型 + */ +public interface DictTypeService extends BaseService { +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/dict/service/impl/DictInfoServiceImpl.java b/cool-admin-java/src/main/java/com/cool/modules/dict/service/impl/DictInfoServiceImpl.java new file mode 100644 index 0000000..51e6506 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/dict/service/impl/DictInfoServiceImpl.java @@ -0,0 +1,134 @@ +package com.cool.modules.dict.service.impl; + +import static com.cool.modules.dict.entity.table.DictInfoEntityTableDef.DICT_INFO_ENTITY; +import static com.cool.modules.dict.entity.table.DictTypeEntityTableDef.DICT_TYPE_ENTITY; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.lang.Dict; +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.ObjUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.extra.spring.SpringUtil; +import cn.hutool.json.JSONObject; +import com.cool.core.base.BaseServiceImpl; +import com.cool.core.base.ModifyEnum; +import com.cool.core.i18n.I18nGenerator; +import com.cool.modules.dict.entity.DictInfoEntity; +import com.cool.modules.dict.entity.DictTypeEntity; +import com.cool.modules.dict.mapper.DictInfoMapper; +import com.cool.modules.dict.mapper.DictTypeMapper; +import com.cool.modules.dict.service.DictInfoService; +import com.mybatisflex.core.query.QueryWrapper; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +/** + * 字典信息 + */ +@Service +@RequiredArgsConstructor +public class DictInfoServiceImpl extends BaseServiceImpl implements + DictInfoService { + + final private DictTypeMapper dictTypeMapper; + + @Override + public Object data(List types) { + Dict result = Dict.create(); + QueryWrapper find = QueryWrapper.create(); + find.select(DICT_TYPE_ENTITY.ID, DICT_TYPE_ENTITY.KEY, + DICT_TYPE_ENTITY.NAME); + if (CollectionUtil.isNotEmpty(types)) { + find.and(DICT_TYPE_ENTITY.KEY.in(types)); + } + List typeData = dictTypeMapper.selectListByQuery(find); + if (typeData.isEmpty()) { + return result; + } + List infos = this.list(QueryWrapper.create() + .select(DictInfoEntity::getId, DictInfoEntity::getName, DictInfoEntity::getTypeId, + DictInfoEntity::getParentId, DictInfoEntity::getValue) + .in(DictInfoEntity::getTypeId, + typeData.stream().map(DictTypeEntity::getId).collect(Collectors.toList())) + .orderBy(DICT_INFO_ENTITY.ORDER_NUM.getName(), DICT_INFO_ENTITY.CREATE_TIME.getName())); + typeData.forEach(item -> { + List datas = new ArrayList<>(); + infos.stream().filter(d -> d.getTypeId().equals(item.getId())).toList().forEach(d -> { + Dict data = Dict.create(); + data.set("typeId", d.getTypeId()); + data.set("parentId", d.getParentId()); + data.set("name", d.getName()); + data.set("id", d.getId()); + data.set("value", StrUtil.isEmpty(d.getValue()) ? null : d.getValue()); + try { + data.set("value", Integer.parseInt(d.getValue())); + } catch (Exception ignored) { + } + datas.add(data); + }); + result.set(item.getKey(), datas); + }); + return result; + } + + @Override + public Object types() { + List infos = this.list(); + if (ObjUtil.isEmpty(infos)) { + return infos; + } + List datas = new ArrayList<>(); + infos.stream().forEach(d -> { + Dict data = Dict.create(); + data.set("typeId", d.getTypeId()); + data.set("parentId", d.getParentId()); + data.set("name", d.getName()); + data.set("id", d.getId()); + data.set("value", StrUtil.isEmpty(d.getValue()) ? null : d.getValue()); + try { + data.set("value", Integer.parseInt(d.getValue())); + } catch (Exception ignored) { + } + datas.add(data); + }); + return datas; + } + + @Override + public boolean delete(Long... ids) { + super.delete(ids); + for (Long id : ids) { + this.delDictChild(id); + } + return true; + } + + /** + * 删除子菜单 + * + * @param id 删除的菜单ID + */ + private void delDictChild(Long id) { + List delDict = list( + QueryWrapper.create().eq(DictInfoEntity::getParentId, id)); + if (CollectionUtil.isEmpty(delDict)) { + return; + } + Long[] ids = delDict.stream().map(DictInfoEntity::getId).toArray(Long[]::new); + if (ArrayUtil.isNotEmpty(ids)) { + delete(ids); + for (Long delId : ids) { + this.delDictChild(delId); + } + } + } + @Override + public void modifyAfter(JSONObject requestParams, DictInfoEntity entity, ModifyEnum type) { + if (ModifyEnum.ADD.equals(type) || ModifyEnum.UPDATE.equals(type)) { + SpringUtil.getBean(I18nGenerator.class).asyncGenBaseDictInfo(); + } + } +} \ No newline at end of file diff --git a/cool-admin-java/src/main/java/com/cool/modules/dict/service/impl/DictTypeServiceImpl.java b/cool-admin-java/src/main/java/com/cool/modules/dict/service/impl/DictTypeServiceImpl.java new file mode 100644 index 0000000..6373cbb --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/dict/service/impl/DictTypeServiceImpl.java @@ -0,0 +1,50 @@ +package com.cool.modules.dict.service.impl; + +import static com.cool.modules.dict.entity.table.DictInfoEntityTableDef.DICT_INFO_ENTITY; +import static com.cool.modules.dict.entity.table.DictTypeEntityTableDef.DICT_TYPE_ENTITY; + +import cn.hutool.extra.spring.SpringUtil; +import cn.hutool.json.JSONObject; +import com.cool.core.base.BaseServiceImpl; +import com.cool.core.base.ModifyEnum; +import com.cool.core.i18n.I18nGenerator; +import com.cool.modules.dict.entity.DictTypeEntity; +import com.cool.modules.dict.mapper.DictInfoMapper; +import com.cool.modules.dict.mapper.DictTypeMapper; +import com.cool.modules.dict.service.DictTypeService; +import com.mybatisflex.core.query.QueryWrapper; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +/** + * 字典类型 + */ +@Service +@RequiredArgsConstructor +public class DictTypeServiceImpl extends BaseServiceImpl implements + DictTypeService { + + final private DictInfoMapper dictInfoMapper; + + @Override + public List list(QueryWrapper queryWrapper) { + return super.list( + queryWrapper.select(DICT_TYPE_ENTITY.ID, DICT_TYPE_ENTITY.KEY, + DICT_TYPE_ENTITY.NAME)); + } + + @Override + public boolean delete(Long... ids) { + super.delete(ids); + return dictInfoMapper.deleteByQuery( + QueryWrapper.create().and(DICT_INFO_ENTITY.TYPE_ID.in((Object) ids))) > 0; + } + + @Override + public void modifyBefore(JSONObject requestParams, DictTypeEntity t, ModifyEnum type) { + if (ModifyEnum.ADD.equals(type) || ModifyEnum.UPDATE.equals(type)) { + SpringUtil.getBean(I18nGenerator.class).asyncGenBaseDictType(); + } + } +} \ No newline at end of file diff --git a/cool-admin-java/src/main/java/com/cool/modules/recycle/aop/DeleteAspect.java b/cool-admin-java/src/main/java/com/cool/modules/recycle/aop/DeleteAspect.java new file mode 100644 index 0000000..45003ba --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/recycle/aop/DeleteAspect.java @@ -0,0 +1,112 @@ +package com.cool.modules.recycle.aop; + +import cn.hutool.core.convert.Convert; +import cn.hutool.core.util.ObjUtil; +import cn.hutool.json.JSONObject; +import com.cool.core.annotation.IgnoreRecycleData; +import com.cool.core.base.BaseController; +import com.cool.core.base.BaseService; +import com.cool.core.util.CoolSecurityUtil; +import com.cool.modules.recycle.entity.RecycleDataEntity; +import com.cool.modules.recycle.service.RecycleDataService; +import com.mybatisflex.core.query.QueryWrapper; +import jakarta.servlet.http.HttpServletRequest; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.springframework.stereotype.Component; + +/** + * 数据删除前拦截 + */ +@Aspect +@Component +@Slf4j +@RequiredArgsConstructor +public class DeleteAspect { + + final private RecycleDataService recycleDataService; + + @Around(value = "execution(* com.cool.core.base.BaseController.delete*(..)) && args(request, params, requestParams)", argNames = "joinPoint,request,params,requestParams") + public Object aroundAdvice(ProceedingJoinPoint joinPoint, HttpServletRequest request, + Map params, + JSONObject requestParams) throws Throwable { + Method currentMethod = getCurrentMethod(joinPoint); + if (Objects.nonNull(currentMethod) && currentMethod.isAnnotationPresent( + IgnoreRecycleData.class)) { + // 忽略回收站记录 + return joinPoint.proceed(); + } + List list = null; + String className = null; + try { + log.info("数据删除前拦截"); + // 可以在目标方法执行前进行一些操作 + BaseController baseController = (BaseController) joinPoint.getTarget(); + BaseService service = baseController.getService(); + className = (baseController.currentEntityClass()).getName(); + QueryWrapper queryWrapper = new QueryWrapper(); + Object ids = params.get("ids"); + if (!(ids instanceof ArrayList)) { + ids = ids.toString().split(","); + } + List idList = Convert.toList(Long.class, ids); + queryWrapper.in("id", (Object) Convert.toLongArray(idList)); + list = service.list(queryWrapper); + } catch (Exception e) { + log.error("数据删除前拦截获取数据详情信息失败", e); + } + + Object result = joinPoint.proceed(); + if (ObjUtil.isNotEmpty(list)) { + RecycleDataEntity recycleDataEntity = new RecycleDataEntity(); + recycleDataEntity.setUrl(request.getRequestURI()); + recycleDataEntity.setUserName(CoolSecurityUtil.getAdminUsername()); + recycleDataEntity + .setUserId(Long.parseLong( + String.valueOf(CoolSecurityUtil.getAdminUserInfo(requestParams).get("userId")))); + recycleDataEntity.setParams(params); + recycleDataEntity.setData(list); + recycleDataEntity.setParams(params); + RecycleDataEntity.EntityInfo entityInfo = new RecycleDataEntity.EntityInfo(); + entityInfo.setEntityClassName(className); + recycleDataEntity.setEntityInfo(entityInfo); + recycleDataEntity.setCount(recycleDataEntity.getData().size()); + + log.info("数据进入回收站 {}", recycleDataService.add(recycleDataEntity)); + } + return result; + } + + private Method getCurrentMethod(JoinPoint joinPoint) { + String methodName = joinPoint.getSignature().getName(); + Object[] args = joinPoint.getArgs(); + Method[] methods = joinPoint.getTarget().getClass().getMethods(); + + for (Method method : methods) { + if (method.getName().equals(methodName) && method.getParameterCount() == args.length) { + boolean isSameMethod = true; + Class[] parameterTypes = method.getParameterTypes(); + for (int i = 0; i < parameterTypes.length; i++) { + if (!parameterTypes[i].isAssignableFrom(args[i].getClass())) { + isSameMethod = false; + break; + } + } + if (isSameMethod) { + return method; + } + } + } + return null; + } + +} \ No newline at end of file diff --git a/cool-admin-java/src/main/java/com/cool/modules/recycle/controller/admin/AdminRecycleDataController.java b/cool-admin-java/src/main/java/com/cool/modules/recycle/controller/admin/AdminRecycleDataController.java new file mode 100644 index 0000000..9e428e5 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/recycle/controller/admin/AdminRecycleDataController.java @@ -0,0 +1,40 @@ +package com.cool.modules.recycle.controller.admin; + +import cn.hutool.json.JSONObject; +import com.cool.core.annotation.CoolRestController; +import com.cool.core.base.BaseController; +import com.cool.core.request.R; +import com.cool.modules.recycle.entity.RecycleDataEntity; +import com.cool.modules.recycle.entity.table.RecycleDataEntityTableDef; +import com.cool.modules.recycle.service.RecycleDataService; +import com.mybatisflex.core.query.QueryWrapper; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletRequest; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; + +import java.util.Map; + + +/** + * 数据回收站 + */ +@Tag(name = "数据回收站", description = "数据回收站") +@CoolRestController(api = { "add", "delete", "update", "page", "list", "info" }) +@RequiredArgsConstructor +public class AdminRecycleDataController extends BaseController { + final private RecycleDataService recycleDataService; + + @Override + protected void init(HttpServletRequest request, JSONObject requestParams) { + setListOption(createOp().queryWrapper(QueryWrapper.create().orderBy(RecycleDataEntityTableDef.RECYCLE_DATA_ENTITY.CREATE_TIME, false))); + } + + @Operation(summary = "恢复数据", description = "恢复数据") + @PostMapping("/restore") + public R restore(@RequestBody Map params) { + return R.ok(this.service.restore(getIds(params))); + } +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/recycle/entity/RecycleDataEntity.java b/cool-admin-java/src/main/java/com/cool/modules/recycle/entity/RecycleDataEntity.java new file mode 100644 index 0000000..3906b9b --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/recycle/entity/RecycleDataEntity.java @@ -0,0 +1,56 @@ +package com.cool.modules.recycle.entity; + +import com.cool.core.base.BaseEntity; +import com.mybatisflex.annotation.Column; +import com.mybatisflex.annotation.Table; +import com.cool.core.mybatis.handler.Fastjson2TypeHandler; +import com.tangzc.mybatisflex.autotable.annotation.ColumnDefine; +import java.util.List; +import java.util.Map; +import lombok.Getter; +import lombok.Setter; +import org.dromara.autotable.annotation.Ignore; +import org.dromara.autotable.annotation.Index; + +/** + * 数据回收站 软删除的时候数据会回收到该表 + */ +@Getter +@Setter +@Table(value = "recycle_data", comment = "数据回收站表") +public class RecycleDataEntity extends BaseEntity { + + @ColumnDefine(comment = "表信息", type = "json") + @Column(typeHandler = Fastjson2TypeHandler.class) + private EntityInfo entityInfo; + + @Index() + @ColumnDefine(comment = "操作人", notNull = true) + private Long userId; + + @ColumnDefine(comment = "被删除的数据", type = "json") + @Column(typeHandler = Fastjson2TypeHandler.class) + private List data; + + @ColumnDefine(comment = "请求的接口", notNull = true) + private String url; + + @ColumnDefine(comment = "请求参数", type = "json", notNull = true) + @Column(typeHandler = Fastjson2TypeHandler.class) + private Map params; + + @ColumnDefine(comment = "删除数据条数", defaultValue = "1") + private Integer count; + + @Setter + @Getter + public static class EntityInfo { + + // entityClassName + public String entityClassName; + } + + @Ignore + @Column(ignore = true) // 操作人名称 + public String userName; +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/recycle/mapper/RecycleDataMapper.java b/cool-admin-java/src/main/java/com/cool/modules/recycle/mapper/RecycleDataMapper.java new file mode 100644 index 0000000..7fef289 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/recycle/mapper/RecycleDataMapper.java @@ -0,0 +1,7 @@ +package com.cool.modules.recycle.mapper; + +import com.mybatisflex.core.BaseMapper; +import com.cool.modules.recycle.entity.RecycleDataEntity; + +public interface RecycleDataMapper extends BaseMapper { +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/recycle/service/RecycleDataService.java b/cool-admin-java/src/main/java/com/cool/modules/recycle/service/RecycleDataService.java new file mode 100644 index 0000000..612584e --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/recycle/service/RecycleDataService.java @@ -0,0 +1,21 @@ +package com.cool.modules.recycle.service; + +import cn.hutool.json.JSONObject; +import com.cool.core.base.BaseService; +import com.cool.modules.recycle.entity.RecycleDataEntity; +import com.mybatisflex.core.paginate.Page; +import com.mybatisflex.core.query.QueryWrapper; + +import java.util.List; + +public interface RecycleDataService extends BaseService { + Object page(JSONObject requestParams, Page page, QueryWrapper queryWrapper); + + /** + * 恢复数据 + * + * @param ids + * @return + */ + Boolean restore(List ids); +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/recycle/service/impl/RecycleDataServiceImpl.java b/cool-admin-java/src/main/java/com/cool/modules/recycle/service/impl/RecycleDataServiceImpl.java new file mode 100644 index 0000000..bc13286 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/recycle/service/impl/RecycleDataServiceImpl.java @@ -0,0 +1,118 @@ +package com.cool.modules.recycle.service.impl; + +import cn.hutool.core.util.ClassUtil; +import cn.hutool.core.util.ObjUtil; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import com.cool.core.base.BaseServiceImpl; +import com.cool.core.base.service.MapperProviderService; +import com.cool.modules.base.entity.sys.BaseSysUserEntity; +import com.cool.modules.base.service.sys.BaseSysUserService; +import com.cool.modules.recycle.entity.RecycleDataEntity; +import com.cool.modules.recycle.mapper.RecycleDataMapper; +import com.cool.modules.recycle.service.RecycleDataService; +import com.mybatisflex.core.BaseMapper; +import com.mybatisflex.core.paginate.Page; +import com.mybatisflex.core.query.QueryWrapper; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * 数据回收站 + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class RecycleDataServiceImpl extends BaseServiceImpl + implements RecycleDataService { + + final private BaseSysUserService baseSysUserService; + + final private MapperProviderService mapperProviderService; + + @Override + public Object page(JSONObject requestParams, Page page, + QueryWrapper queryWrapper) { + String keyWord = requestParams.getStr("keyWord"); + if (ObjUtil.isNotEmpty(keyWord)) { + List list = baseSysUserService + .list(QueryWrapper.create().select(BaseSysUserEntity::getId) + .like(BaseSysUserEntity::getName, keyWord)) + .stream().map(BaseSysUserEntity::getId).toList(); + queryWrapper.like(RecycleDataEntity::getUrl, keyWord).or(w -> { + w.in(RecycleDataEntity::getUserId, list, ObjUtil.isNotEmpty(list)); + }); + } + Page iPage = page(page, queryWrapper); + List records = iPage.getRecords(); + List list = records.stream().map(RecycleDataEntity::getUserId) + .filter(ObjUtil::isNotEmpty).toList(); + + if (ObjUtil.isNotEmpty(list)) { + Map map = baseSysUserService + .list(QueryWrapper.create() + .select(BaseSysUserEntity::getId, BaseSysUserEntity::getName) + .in(BaseSysUserEntity::getId, list)) + .stream() + .collect(Collectors.toMap(BaseSysUserEntity::getId, BaseSysUserEntity::getName)); + records.forEach(o -> { + if (map.containsKey(o.getUserId())) { + o.setUserName(map.get(o.getUserId())); + } + }); + } + return iPage; + } + + @Override + public Boolean restore(List ids) { + if (ObjUtil.isEmpty(ids)) { + return false; + } + List list = list( + QueryWrapper.create().in(RecycleDataEntity::getId, ids)); + list.forEach(o -> { + // 处理恢复数据 + boolean flag = handlerRestore(o); + if (flag) { + // 删除回收站记录 + o.removeById(); + } + }); + return true; + } + + /** + * 处理数据恢复 + */ + private boolean handlerRestore(RecycleDataEntity recycleDataEntity) { + RecycleDataEntity.EntityInfo entityInfo = recycleDataEntity.getEntityInfo(); + try { + Class entityClass = ClassUtil.loadClass(entityInfo.getEntityClassName()); + List records = recycleDataEntity.getData(); + BaseMapper baseMapper = mapperProviderService.getMapperByEntityClass( + entityClass); + // 插入数据 + List insertList = new ArrayList<>(); + for (Object record : records) { + Object entity = JSONUtil.toBean(JSONUtil.parseObj(record), entityClass); + Method getIdMethod = entityClass.getMethod("getId"); + Object id = getIdMethod.invoke(entity); + if (baseMapper.selectOneById((Long) id) == null) { + insertList.add(entity); + } + } + baseMapper.insertBatch(insertList); + return true; + } catch (Exception e) { + log.error("恢复数据失败", e); + } + return false; + } +} \ No newline at end of file diff --git a/cool-admin-java/src/main/java/com/cool/modules/space/controller/admin/AdminSpaceInfoController.java b/cool-admin-java/src/main/java/com/cool/modules/space/controller/admin/AdminSpaceInfoController.java new file mode 100644 index 0000000..af1ab9e --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/space/controller/admin/AdminSpaceInfoController.java @@ -0,0 +1,24 @@ +package com.cool.modules.space.controller.admin; + +import cn.hutool.json.JSONObject; +import com.cool.core.annotation.CoolRestController; +import com.cool.core.base.BaseController; +import com.cool.modules.space.entity.SpaceInfoEntity; +import com.cool.modules.space.service.SpaceInfoService; +import io.swagger.v3.oas.annotations.tags.Tag; + +import jakarta.servlet.http.HttpServletRequest; + +import static com.cool.modules.space.entity.table.SpaceInfoEntityTableDef.SPACE_INFO_ENTITY; + +/** + * 文件空间信息 + */ +@Tag(name = "文件空间信息", description = "文件空间信息") +@CoolRestController(api = { "add", "delete", "update", "page", "list", "info" }) +public class AdminSpaceInfoController extends BaseController { + @Override + protected void init(HttpServletRequest request, JSONObject requestParams) { + setPageOption(createOp().fieldEq(SPACE_INFO_ENTITY.TYPE, SPACE_INFO_ENTITY.CLASSIFY_ID)); + } +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/space/controller/admin/AdminSpaceTypeController.java b/cool-admin-java/src/main/java/com/cool/modules/space/controller/admin/AdminSpaceTypeController.java new file mode 100644 index 0000000..d5c0ace --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/space/controller/admin/AdminSpaceTypeController.java @@ -0,0 +1,23 @@ +package com.cool.modules.space.controller.admin; + +import cn.hutool.json.JSONObject; +import com.cool.core.annotation.CoolRestController; +import com.cool.core.base.BaseController; +import com.cool.modules.space.entity.SpaceTypeEntity; +import com.cool.modules.space.service.SpaceTypeService; +import io.swagger.v3.oas.annotations.tags.Tag; + +import jakarta.servlet.http.HttpServletRequest; + +/** + * 文件空间信息 + */ +@Tag(name = "文件空间信息", description = "文件空间信息") +@CoolRestController(api = { "add", "delete", "update", "page", "list", "info" }) +public class AdminSpaceTypeController extends BaseController { + + @Override + protected void init(HttpServletRequest request, JSONObject requestParams) { + + } +} \ No newline at end of file diff --git a/cool-admin-java/src/main/java/com/cool/modules/space/entity/SpaceInfoEntity.java b/cool-admin-java/src/main/java/com/cool/modules/space/entity/SpaceInfoEntity.java new file mode 100644 index 0000000..c2de212 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/space/entity/SpaceInfoEntity.java @@ -0,0 +1,57 @@ +package com.cool.modules.space.entity; + +import com.cool.core.base.BaseEntity; +import com.mybatisflex.annotation.Column; +import com.mybatisflex.annotation.Table; +import com.tangzc.mybatisflex.autotable.annotation.ColumnDefine; +import lombok.Getter; +import lombok.Setter; +import org.dromara.autotable.annotation.Ignore; +import org.dromara.autotable.annotation.Index; + +/** + * 文件空间信息 + */ +@Getter +@Setter +@Table(value = "space_info", comment = "文件空间信息") +public class SpaceInfoEntity extends BaseEntity { + @ColumnDefine(comment = "地址", notNull = true) + private String url; + + @ColumnDefine(comment = "类型", notNull = true) + private String type; + + @ColumnDefine(comment = "分类ID") + private Integer classifyId; + + @Index() + @ColumnDefine(comment = "文件id") + private String fileId; + + @ColumnDefine(comment = "文件名") + private String name; + + @ColumnDefine(comment = "文件大小") + private Integer size; + + @ColumnDefine(comment = "文档版本", defaultValue = "1") + private Long version; + + @ColumnDefine(comment = "文件位置") + private String filePath; + + @Ignore + @Column(ignore = true) + private String key; + + public void setFilePath(String filePath) { + this.filePath = filePath; + this.key = filePath; + } + + public void setKey(String key) { + this.key = key; + this.filePath = key; + } +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/space/entity/SpaceTypeEntity.java b/cool-admin-java/src/main/java/com/cool/modules/space/entity/SpaceTypeEntity.java new file mode 100644 index 0000000..f50f61f --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/space/entity/SpaceTypeEntity.java @@ -0,0 +1,21 @@ +package com.cool.modules.space.entity; + +import com.cool.core.base.BaseEntity; +import com.mybatisflex.annotation.Table; +import com.tangzc.mybatisflex.autotable.annotation.ColumnDefine; +import lombok.Getter; +import lombok.Setter; + +/** + * 图片空间信息分类 + */ +@Getter +@Setter +@Table(value = "space_type", comment = "图片空间信息分类") +public class SpaceTypeEntity extends BaseEntity { + @ColumnDefine(comment = "类别名称", notNull = true) + private String name; + + @ColumnDefine(comment = "父分类ID") + private Integer parentId; +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/space/mapper/SpaceInfoMapper.java b/cool-admin-java/src/main/java/com/cool/modules/space/mapper/SpaceInfoMapper.java new file mode 100644 index 0000000..3f41f26 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/space/mapper/SpaceInfoMapper.java @@ -0,0 +1,10 @@ +package com.cool.modules.space.mapper; + +import com.mybatisflex.core.BaseMapper; +import com.cool.modules.space.entity.SpaceInfoEntity; + +/** + * 文件空间信息 + */ +public interface SpaceInfoMapper extends BaseMapper { +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/space/mapper/SpaceTypeMapper.java b/cool-admin-java/src/main/java/com/cool/modules/space/mapper/SpaceTypeMapper.java new file mode 100644 index 0000000..8858289 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/space/mapper/SpaceTypeMapper.java @@ -0,0 +1,10 @@ +package com.cool.modules.space.mapper; + +import com.mybatisflex.core.BaseMapper; +import com.cool.modules.space.entity.SpaceTypeEntity; + +/** + * 文件空间信息 + */ +public interface SpaceTypeMapper extends BaseMapper { +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/space/service/SpaceInfoService.java b/cool-admin-java/src/main/java/com/cool/modules/space/service/SpaceInfoService.java new file mode 100644 index 0000000..bbf358e --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/space/service/SpaceInfoService.java @@ -0,0 +1,10 @@ +package com.cool.modules.space.service; + +import com.cool.core.base.BaseService; +import com.cool.modules.space.entity.SpaceInfoEntity; + +/** + * 文件空间信息 + */ +public interface SpaceInfoService extends BaseService { +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/space/service/SpaceTypeService.java b/cool-admin-java/src/main/java/com/cool/modules/space/service/SpaceTypeService.java new file mode 100644 index 0000000..5f4aa5e --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/space/service/SpaceTypeService.java @@ -0,0 +1,10 @@ +package com.cool.modules.space.service; + +import com.cool.core.base.BaseService; +import com.cool.modules.space.entity.SpaceTypeEntity; + +/** + * 文件空间信息 + */ +public interface SpaceTypeService extends BaseService { +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/space/service/impl/SpaceInfoServiceImpl.java b/cool-admin-java/src/main/java/com/cool/modules/space/service/impl/SpaceInfoServiceImpl.java new file mode 100644 index 0000000..de9ce6b --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/space/service/impl/SpaceInfoServiceImpl.java @@ -0,0 +1,15 @@ +package com.cool.modules.space.service.impl; + +import com.cool.core.base.BaseServiceImpl; +import com.cool.modules.space.entity.SpaceInfoEntity; +import com.cool.modules.space.mapper.SpaceInfoMapper; +import com.cool.modules.space.service.SpaceInfoService; +import org.springframework.stereotype.Service; + +/** + * 文件空间信息 + */ +@Service +public class SpaceInfoServiceImpl extends BaseServiceImpl + implements SpaceInfoService { +} \ No newline at end of file diff --git a/cool-admin-java/src/main/java/com/cool/modules/space/service/impl/SpaceTypeServiceImpl.java b/cool-admin-java/src/main/java/com/cool/modules/space/service/impl/SpaceTypeServiceImpl.java new file mode 100644 index 0000000..3b5894f --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/space/service/impl/SpaceTypeServiceImpl.java @@ -0,0 +1,15 @@ +package com.cool.modules.space.service.impl; + +import com.cool.core.base.BaseServiceImpl; +import com.cool.modules.space.entity.SpaceTypeEntity; +import com.cool.modules.space.mapper.SpaceTypeMapper; +import com.cool.modules.space.service.SpaceTypeService; +import org.springframework.stereotype.Service; + +/** + * 文件空间信息 + */ +@Service +public class SpaceTypeServiceImpl extends BaseServiceImpl + implements SpaceTypeService { +} \ No newline at end of file diff --git a/cool-admin-java/src/main/java/com/cool/modules/task/config/ScheduleConfig.java b/cool-admin-java/src/main/java/com/cool/modules/task/config/ScheduleConfig.java new file mode 100644 index 0000000..020ab47 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/task/config/ScheduleConfig.java @@ -0,0 +1,21 @@ +package com.cool.modules.task.config; + +import org.springframework.boot.autoconfigure.quartz.SchedulerFactoryBeanCustomizer; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.quartz.SchedulerFactoryBean; + + +/** + * 定时任务配置 + */ +@Configuration +@EnableScheduling +public class ScheduleConfig implements SchedulerFactoryBeanCustomizer { + @Override + public void customize(SchedulerFactoryBean schedulerFactoryBean) { + schedulerFactoryBean.setStartupDelay(2); + schedulerFactoryBean.setAutoStartup(true); + schedulerFactoryBean.setOverwriteExistingJobs(true); + } +} \ No newline at end of file diff --git a/cool-admin-java/src/main/java/com/cool/modules/task/controller/admin/AdminTaskInfoController.java b/cool-admin-java/src/main/java/com/cool/modules/task/controller/admin/AdminTaskInfoController.java new file mode 100644 index 0000000..5d3eca4 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/task/controller/admin/AdminTaskInfoController.java @@ -0,0 +1,60 @@ +package com.cool.modules.task.controller.admin; + +import static com.cool.modules.task.entity.table.TaskInfoEntityTableDef.TASK_INFO_ENTITY; + +import cn.hutool.json.JSONObject; +import com.cool.core.annotation.CoolRestController; +import com.cool.core.base.BaseController; +import com.cool.core.request.R; +import com.cool.modules.task.entity.TaskInfoEntity; +import com.cool.modules.task.service.TaskInfoService; +import com.mybatisflex.core.paginate.Page; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestAttribute; + +/** + * 任务 + */ +@Tag(name = "任务管理", description = "统一管理任务") +@CoolRestController(api = { "add", "delete", "update", "info", "page" }) +public class AdminTaskInfoController extends BaseController { + + @Override + protected void init(HttpServletRequest request, JSONObject requestParams) { + setPageOption(createOp().fieldEq(TASK_INFO_ENTITY.STATUS, TASK_INFO_ENTITY.TYPE)); + } + + @Operation(summary = "执行一次") + @PostMapping("/once") + public R once(@RequestAttribute JSONObject requestParams) { + service.once(requestParams.getLong("id")); + return R.ok(); + } + + @Operation(summary = "开始任务") + @PostMapping("/start") + public R start(@RequestAttribute JSONObject requestParams) { + service.start(requestParams.getLong("id"), requestParams.getInt("type")); + return R.ok(); + } + + @Operation(summary = "停止任务") + @PostMapping("/stop") + public R stop(@RequestAttribute JSONObject requestParams) { + service.stop(requestParams.getLong("id")); + return R.ok(); + } + + @Operation(summary = "任务日志") + @GetMapping("/log") + public R log(@RequestAttribute JSONObject requestParams) { + Integer page = requestParams.getInt("page", 0); + Integer size = requestParams.getInt("size", 20); + return R.ok(pageResult((Page) service.log(new Page<>(page, size), requestParams.getLong("id"), + requestParams.getInt("status")))); + } +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/task/entity/TaskInfoEntity.java b/cool-admin-java/src/main/java/com/cool/modules/task/entity/TaskInfoEntity.java new file mode 100644 index 0000000..79e815c --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/task/entity/TaskInfoEntity.java @@ -0,0 +1,62 @@ +package com.cool.modules.task.entity; + +import com.cool.core.base.BaseEntity; +import com.mybatisflex.annotation.Column; +import com.mybatisflex.annotation.Table; +import com.tangzc.mybatisflex.autotable.annotation.ColumnDefine; +import java.util.Date; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@Table(value = "task_info", comment = "任务信息") +public class TaskInfoEntity extends BaseEntity { + /** + * 任务调度参数key + */ + @Column(ignore = true) + public static final String JOB_PARAM_KEY = "JOB_PARAM_KEY"; + + @ColumnDefine(comment = "名称", notNull = true) + private String name; + + @ColumnDefine(comment = "任务ID") + private String jobId; + + @ColumnDefine(comment = "最大执行次数 不传为无限次") + private Integer repeatCount; + + @ColumnDefine(comment = "每间隔多少毫秒执行一次 如果cron设置了 这项设置就无效") + private Integer every; + + @ColumnDefine(comment = "状态 0:停止 1:运行", defaultValue = "1", notNull = true) + private Integer status; + + @ColumnDefine(comment = "服务实例名称") + private String service; + + @ColumnDefine(comment = "状态 0:cron 1:时间间隔", defaultValue = "0") + private Integer taskType; + + @ColumnDefine(comment = "状态 0:系统 1:用户", defaultValue = "0") + private Integer type; + + @ColumnDefine(comment = "任务数据") + private String data; + + @ColumnDefine(comment = "备注") + private String remark; + + @ColumnDefine(comment = "cron") + private String cron; + + @ColumnDefine(comment = "下一次执行时间") + private Date nextRunTime; + + @ColumnDefine(comment = "开始时间") + private Date startDate; + + @ColumnDefine(comment = "结束时间") + private Date endDate; +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/task/entity/TaskLogEntity.java b/cool-admin-java/src/main/java/com/cool/modules/task/entity/TaskLogEntity.java new file mode 100644 index 0000000..6dd0dd2 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/task/entity/TaskLogEntity.java @@ -0,0 +1,29 @@ +package com.cool.modules.task.entity; + +import com.cool.core.base.BaseEntity; +import com.mybatisflex.annotation.Column; +import com.mybatisflex.annotation.Table; +import com.tangzc.mybatisflex.autotable.annotation.ColumnDefine; +import lombok.Getter; +import lombok.Setter; +import org.dromara.autotable.annotation.Index; + +@Getter +@Setter +@Table(value = "task_log", comment = "任务日志") +public class TaskLogEntity extends BaseEntity { + + @Index + @ColumnDefine(comment = "任务ID", notNull = true, type = "bigint") + private Long taskId; + + @ColumnDefine(comment = "状态 0:失败 1:成功", defaultValue = "0") + private Integer status; + + @ColumnDefine(comment = "详情", type = "text") + private String detail; + + // 任务名称 + @Column(ignore = true) + private String taskName; +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/task/event/TaskEvent.java b/cool-admin-java/src/main/java/com/cool/modules/task/event/TaskEvent.java new file mode 100644 index 0000000..1ec2012 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/task/event/TaskEvent.java @@ -0,0 +1,25 @@ +package com.cool.modules.task.event; + +import com.cool.modules.task.service.TaskInfoService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Component; + +/** + * 事件监听 + */ +@Slf4j +@Component +@RequiredArgsConstructor +public class TaskEvent { + + final private TaskInfoService taskInfoService; + + @EventListener(ApplicationReadyEvent.class) + public void run() throws Exception { + taskInfoService.init(); + log.info("初始化任务"); + } +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/task/mapper/TaskInfoMapper.java b/cool-admin-java/src/main/java/com/cool/modules/task/mapper/TaskInfoMapper.java new file mode 100644 index 0000000..770f7ea --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/task/mapper/TaskInfoMapper.java @@ -0,0 +1,8 @@ +package com.cool.modules.task.mapper; + +import com.mybatisflex.core.BaseMapper; +import com.cool.modules.task.entity.TaskInfoEntity; + +public interface TaskInfoMapper extends BaseMapper { + +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/task/mapper/TaskLogMapper.java b/cool-admin-java/src/main/java/com/cool/modules/task/mapper/TaskLogMapper.java new file mode 100644 index 0000000..10a0bce --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/task/mapper/TaskLogMapper.java @@ -0,0 +1,8 @@ +package com.cool.modules.task.mapper; + +import com.mybatisflex.core.BaseMapper; +import com.cool.modules.task.entity.TaskLogEntity; + +public interface TaskLogMapper extends BaseMapper { + +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/task/run/ScheduleJob.java b/cool-admin-java/src/main/java/com/cool/modules/task/run/ScheduleJob.java new file mode 100644 index 0000000..f4fd06e --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/task/run/ScheduleJob.java @@ -0,0 +1,107 @@ +package com.cool.modules.task.run; + +import cn.hutool.core.thread.ThreadUtil; +import cn.hutool.core.util.ObjUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.extra.spring.SpringUtil; +import com.cool.core.util.AutoTypeConverter; +import com.cool.modules.task.entity.TaskInfoEntity; +import com.cool.modules.task.entity.TaskLogEntity; +import com.cool.modules.task.service.TaskInfoLogService; +import com.cool.modules.task.service.TaskInfoService; +import com.mybatisflex.core.util.StringUtil; +import lombok.extern.slf4j.Slf4j; +import org.quartz.JobExecutionContext; +import org.quartz.Scheduler; +import org.quartz.SchedulerException; +import org.springframework.scheduling.quartz.QuartzJobBean; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +/** + * 定时任务 + */ +@Slf4j +public class ScheduleJob extends QuartzJobBean { + private final ExecutorService executorService = Executors.newSingleThreadExecutor(); + + @Override + protected void executeInternal(JobExecutionContext context) { + // 获取spring bean + TaskInfoLogService taskInfoLogService = SpringUtil.getBean(TaskInfoLogService.class); + // 获取spring bean + TaskInfoService taskInfoService = SpringUtil.getBean(TaskInfoService.class); + + Scheduler scheduler = SpringUtil.getBean(Scheduler.class); + + TaskInfoEntity taskInfoEntity = taskInfoService + .getById(AutoTypeConverter.autoConvert(context.getJobDetail().getKey().getName().split("_")[1])); + if (ObjUtil.isEmpty(taskInfoEntity)) { + log.warn("taskInfoEntity is null"); + return; + } + + // 数据库保存执行记录 + TaskLogEntity taskLogEntity = new TaskLogEntity(); + + // 任务开始时间 + long startTime = System.currentTimeMillis(); + + try { + // 执行任务 + log.info("任务准备执行,任务ID:" + taskInfoEntity.getJobId()); + taskLogEntity.setTaskId(taskInfoEntity.getId()); + // 解析执行 + String service = taskInfoEntity.getService(); + if (StrUtil.isNotEmpty(service)) { + String[] arr = service.split("\\."); + String methodName = arr[1].substring(0, arr[1].indexOf("(")); + String params = service.substring(service.indexOf("(") + 1, service.indexOf(")")); + + ScheduleRunnable task = new ScheduleRunnable(StringUtil.firstCharToLowerCase(arr[0]).replaceAll(" ", ""), methodName, params); + Future future = executorService.submit(task); + + future.get(); + } + // 任务执行总时长 + long times = System.currentTimeMillis() - startTime; + // 状态 0:失败 1:成功 + taskLogEntity.setStatus(1); + taskLogEntity.setDetail("任务执行完毕,任务ID:" + taskInfoEntity.getJobId() + " 总共耗时:" + times + "毫秒"); + log.info(taskLogEntity.getDetail()); + } catch (Exception e) { + // 任务执行总时长 + long times = System.currentTimeMillis() - startTime; + + taskLogEntity.setDetail( + "任务执行失败,任务ID:" + taskInfoEntity.getJobId() + " 总共耗时:" + times + "毫秒" + "失败原因:" + e.getMessage()); + log.error("任务执行失败,任务ID:" + taskInfoEntity.getJobId(), e); + + // 状态 0:失败 1:成功 + taskLogEntity.setStatus(0); + } finally { + taskInfoLogService.add(taskLogEntity); + } + ThreadUtil.execAsync(() -> { + ThreadUtil.sleep(2000); + TaskInfoEntity next = new TaskInfoEntity(); + next.setId(taskInfoEntity.getId()); + try { + if (!scheduler.checkExists(context.getTrigger().getJobKey())) { + if (context.getTrigger().getNextFireTime() == null) { + next.setStatus(0); + } + } else { + if (context.getTrigger().getNextFireTime() == null) { + next.setNextRunTime(context.getTrigger().getNextFireTime()); + } + } + } catch (SchedulerException e) { + log.error("err", e); + } + taskInfoService.updateById(next); + }); + } +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/task/run/ScheduleRunnable.java b/cool-admin-java/src/main/java/com/cool/modules/task/run/ScheduleRunnable.java new file mode 100644 index 0000000..dbae43c --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/task/run/ScheduleRunnable.java @@ -0,0 +1,101 @@ +package com.cool.modules.task.run; + +import cn.hutool.core.util.StrUtil; +import cn.hutool.extra.spring.SpringUtil; +import com.cool.core.exception.CoolException; +import org.springframework.util.ReflectionUtils; + +import java.lang.reflect.Method; + +/** + * 执行定时任务 + */ +public class ScheduleRunnable implements Runnable { + private final Object target; + private final Method method; + private final Object[] params; + + public ScheduleRunnable(String beanName, String methodName, String params) + throws NoSuchMethodException, SecurityException { + this.target = SpringUtil.getBean(beanName); + + if (StrUtil.isNotBlank(params)) { + String[] paramArray = params.split(","); + this.params = new Object[paramArray.length]; + Class[] paramTypes = new Class[paramArray.length]; + + for (int i = 0; i < paramArray.length; i++) { + String param = paramArray[i].trim(); + if (param.matches("-?\\d+")) { + this.params[i] = Integer.parseInt(param); + paramTypes[i] = int.class; + } else if (param.matches("-?\\d+L")) { + this.params[i] = Long.parseLong(param.substring(0, param.length() - 1)); + paramTypes[i] = long.class; + } else if (param.matches("-?\\d+\\.\\d+")) { + this.params[i] = Double.parseDouble(param); + paramTypes[i] = double.class; + } else if (param.matches("-?\\d+\\.\\d+f")) { + this.params[i] = Float.parseFloat(param.substring(0, param.length() - 1)); + paramTypes[i] = float.class; + } else if (param.equalsIgnoreCase("true") || param.equalsIgnoreCase("false")) { + this.params[i] = Boolean.parseBoolean(param); + paramTypes[i] = boolean.class; + } else if (param.length() == 1) { + this.params[i] = param.charAt(0); + paramTypes[i] = char.class; + } else { + // Remove leading and trailing quotation marks for string parameters + if (param.startsWith("\"") && param.endsWith("\"")) { + param = param.substring(1, param.length() - 1); + } + this.params[i] = param; + paramTypes[i] = String.class; + } + } + + this.method = findMethod(target.getClass(), methodName, paramTypes); + } else { + this.params = new Object[0]; + this.method = target.getClass().getDeclaredMethod(methodName); + } + } + + private Method findMethod(Class targetClass, String methodName, Class[] paramTypes) throws NoSuchMethodException { + try { + return targetClass.getDeclaredMethod(methodName, paramTypes); + } catch (NoSuchMethodException e) { + // Try with wrapper classes + for (int i = 0; i < paramTypes.length; i++) { + if (paramTypes[i] == int.class) { + paramTypes[i] = Integer.class; + } else if (paramTypes[i] == long.class) { + paramTypes[i] = Long.class; + } else if (paramTypes[i] == double.class) { + paramTypes[i] = Double.class; + } else if (paramTypes[i] == float.class) { + paramTypes[i] = Float.class; + } else if (paramTypes[i] == boolean.class) { + paramTypes[i] = Boolean.class; + } else if (paramTypes[i] == char.class) { + paramTypes[i] = Character.class; + } + } + return targetClass.getDeclaredMethod(methodName, paramTypes); + } + } + + @Override + public void run() { + try { + ReflectionUtils.makeAccessible(method); + if (params.length > 0) { + method.invoke(target, params); + } else { + method.invoke(target); + } + } catch (Exception e) { + throw new CoolException("执行定时任务失败", e); + } + } +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/task/service/TaskInfoLogService.java b/cool-admin-java/src/main/java/com/cool/modules/task/service/TaskInfoLogService.java new file mode 100644 index 0000000..435c0a4 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/task/service/TaskInfoLogService.java @@ -0,0 +1,10 @@ +package com.cool.modules.task.service; + +import com.cool.core.base.BaseService; +import com.cool.modules.task.entity.TaskLogEntity; + +/** + * 任务日志 + */ +public interface TaskInfoLogService extends BaseService { +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/task/service/TaskInfoService.java b/cool-admin-java/src/main/java/com/cool/modules/task/service/TaskInfoService.java new file mode 100644 index 0000000..6f9657c --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/task/service/TaskInfoService.java @@ -0,0 +1,48 @@ +package com.cool.modules.task.service; + +import com.cool.core.base.BaseService; +import com.cool.modules.task.entity.TaskInfoEntity; +import com.cool.modules.task.entity.TaskLogEntity; +import com.mybatisflex.core.paginate.Page; + +/** + * 任务信息 + */ +public interface TaskInfoService extends BaseService { + + /** + * 初始化任务 + */ + void init(); + + /** + * 执行一次 + * + * @param taskId 任务ID + */ + void once(Long taskId); + + /** + * 停止任务 + * + * @param taskId 任务ID + */ + void stop(Long taskId); + + /** + * 任务日志 + * + * @param taskId 任务ID + * @param status 任务状态 + * @return 日志列表 + */ + Object log(Page page, Long taskId, Integer status); + + /** + * 开始任务 + * + * @param taskId 任务ID + * @param type 任务类型 + */ + void start(Long taskId, Integer type); +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/task/service/impl/TaskInfoLogServiceImpl.java b/cool-admin-java/src/main/java/com/cool/modules/task/service/impl/TaskInfoLogServiceImpl.java new file mode 100644 index 0000000..d1f6ccd --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/task/service/impl/TaskInfoLogServiceImpl.java @@ -0,0 +1,12 @@ +package com.cool.modules.task.service.impl; + +import com.cool.core.base.BaseServiceImpl; +import com.cool.modules.task.entity.TaskLogEntity; +import com.cool.modules.task.mapper.TaskLogMapper; +import com.cool.modules.task.service.TaskInfoLogService; +import org.springframework.stereotype.Service; + +@Service +public class TaskInfoLogServiceImpl extends BaseServiceImpl + implements TaskInfoLogService { +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/task/service/impl/TaskInfoServiceImpl.java b/cool-admin-java/src/main/java/com/cool/modules/task/service/impl/TaskInfoServiceImpl.java new file mode 100644 index 0000000..2d603d9 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/task/service/impl/TaskInfoServiceImpl.java @@ -0,0 +1,139 @@ +package com.cool.modules.task.service.impl; + +import static com.cool.modules.task.entity.table.TaskInfoEntityTableDef.TASK_INFO_ENTITY; +import static com.cool.modules.task.entity.table.TaskLogEntityTableDef.TASK_LOG_ENTITY; + +import cn.hutool.core.convert.Convert; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import com.cool.core.base.BaseServiceImpl; +import com.cool.modules.task.entity.TaskInfoEntity; +import com.cool.modules.task.entity.TaskLogEntity; +import com.cool.modules.task.mapper.TaskInfoMapper; +import com.cool.modules.task.service.TaskInfoService; +import com.cool.modules.task.utils.ScheduleUtils; +import com.mybatisflex.core.paginate.Page; +import com.mybatisflex.core.query.QueryWrapper; +import java.util.List; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.quartz.CronTrigger; +import org.quartz.Scheduler; +import org.quartz.SchedulerException; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Slf4j +@Service +@RequiredArgsConstructor +public class TaskInfoServiceImpl extends BaseServiceImpl implements + TaskInfoService { + + final private Scheduler scheduler; + + @Override + public void init() { + try { + List list = list(); + list.forEach(scheduleJob -> { + CronTrigger cronTrigger = ScheduleUtils.getCronTrigger(scheduler, + scheduleJob.getJobId()); + if (cronTrigger == null) { + ScheduleUtils.createScheduleJob(scheduler, scheduleJob); + } else { + ScheduleUtils.updateScheduleJob(scheduler, scheduleJob); + } + updateById(scheduleJob); + }); + } catch (Exception ignored) { + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void once(Long taskId) { + ScheduleUtils.run(scheduler, getById(taskId)); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void stop(Long taskId) { + ScheduleUtils.pauseJob(scheduler, taskId + ""); + TaskInfoEntity taskInfoEntity = getById(taskId); + taskInfoEntity.setStatus(0); + updateById(taskInfoEntity); + modifyAfter(JSONUtil.parseObj(taskInfoEntity), taskInfoEntity); + } + + @Override + public Object log(Page page, Long taskId, Integer status) { + + QueryWrapper queryWrapper = QueryWrapper.create().select(TASK_LOG_ENTITY.DETAIL, + TASK_LOG_ENTITY.STATUS, TASK_LOG_ENTITY.CREATE_TIME, + TASK_INFO_ENTITY.NAME).from(TASK_LOG_ENTITY) + .leftJoin(TASK_INFO_ENTITY).on(TASK_LOG_ENTITY.TASK_ID.eq(TASK_INFO_ENTITY.ID)) + .eq(TaskLogEntity::getTaskId, taskId, taskId != null) + .eq(TaskLogEntity::getStatus, status, status != null) + .orderBy(TaskLogEntity::getCreateTime, false); + return mapper.paginateAs(page, queryWrapper, TaskLogEntity.class); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void start(Long taskId, Integer type) { + TaskInfoEntity taskInfoEntity = getById(taskId); + taskInfoEntity.setStatus(1); + if (type != null) { + taskInfoEntity.setType(type); + } + boolean isExists = false; + try { + isExists = scheduler.checkExists(ScheduleUtils.getJobKey(taskId + "")); + } catch (SchedulerException e) { + log.error("err", e); + } + if (isExists) { + ScheduleUtils.updateScheduleJob(scheduler, taskInfoEntity); + ScheduleUtils.resumeJob(scheduler, taskId + ""); + } else { + ScheduleUtils.createScheduleJob(scheduler, taskInfoEntity); + } + updateById(taskInfoEntity); + modifyAfter(JSONUtil.parseObj(taskInfoEntity), taskInfoEntity); + + } + + @Override + @Transactional(rollbackFor = Exception.class) + public Long add(JSONObject requestParams, TaskInfoEntity scheduleJob) { + scheduleJob.setStatus(1); + super.add(scheduleJob); + scheduleJob.setJobId(scheduleJob.getId() + ""); + + ScheduleUtils.createScheduleJob(scheduler, scheduleJob); + updateById(scheduleJob); + super.modifyAfter(requestParams, scheduleJob); + return scheduleJob.getId(); + } + + @Override + public boolean update(JSONObject requestParams, TaskInfoEntity entity) { + updateById(entity); + ScheduleUtils.deleteScheduleJob(scheduler, entity.getId().toString()); + if (entity.getStatus() == 1) { + start(entity.getId(), entity.getType()); + } else { + stop(entity.getId()); + } + return true; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean delete(JSONObject requestParams, Long... ids) { + Convert.toList(String.class, ids).forEach(jobId -> { + ScheduleUtils.deleteScheduleJob(scheduler, jobId); + }); + return super.delete(requestParams, ids); + } +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/task/utils/ScheduleUtils.java b/cool-admin-java/src/main/java/com/cool/modules/task/utils/ScheduleUtils.java new file mode 100644 index 0000000..7e82df5 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/task/utils/ScheduleUtils.java @@ -0,0 +1,251 @@ +package com.cool.modules.task.utils; + +import com.cool.core.exception.CoolException; +import com.cool.modules.task.entity.TaskInfoEntity; +import com.cool.modules.task.run.ScheduleJob; +import org.quartz.*; + +/** + * 定时任务工具类 + * + * @author Mark sunlightcs@gmail.com + * @since 1.2.0 2016-11-28 + */ +public class ScheduleUtils { + private final static String JOB_NAME = "TASK_"; + + public enum ScheduleStatus { + /** + * 暂停 + */ + PAUSE(0), + /** + * 正常 + */ + NORMAL(1); + + private int value; + + ScheduleStatus(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + } + + /** + * 获取触发器key + */ + public static TriggerKey getTriggerKey(String jobId) { + return TriggerKey.triggerKey(JOB_NAME + jobId); + } + + /** + * 获取jobKey + */ + public static JobKey getJobKey(String jobId) { + return JobKey.jobKey(JOB_NAME + jobId); + } + + /** + * 获取表达式触发器 + */ + public static CronTrigger getCronTrigger(Scheduler scheduler, String jobId) { + try { + return (CronTrigger) scheduler.getTrigger(getTriggerKey(jobId)); + } catch (SchedulerException e) { + throw new CoolException("获取定时任务CronTrigger出现异常", e); + } + } + + /** + * 获取表达式触发器 + */ + public static SimpleTrigger getSimpleTrigger(Scheduler scheduler, String jobId) { + try { + return (SimpleTrigger) scheduler.getTrigger(getTriggerKey(jobId)); + } catch (SchedulerException e) { + throw new CoolException("获取定时任务CronTrigger出现异常", e); + } + } + + /** + * 创建定时任务 + */ + public static void createScheduleJob(Scheduler scheduler, TaskInfoEntity scheduleJob) { + try { + // 构建job信息 + JobDetail jobDetail = JobBuilder.newJob(ScheduleJob.class).withIdentity(getJobKey(scheduleJob.getJobId())) + .build(); + + if (scheduleJob.getTaskType() == 0) { + // 表达式调度构建器 + CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCron()) + .withMisfireHandlingInstructionDoNothing(); + + TriggerBuilder triggerBuilder = TriggerBuilder.newTrigger() + .withIdentity(getTriggerKey(scheduleJob.getJobId())).withSchedule(scheduleBuilder); + + if (scheduleJob.getStartDate() != null) { + triggerBuilder.startAt(scheduleJob.getStartDate()); + } + + if (scheduleJob.getEndDate() != null) { + triggerBuilder.endAt(scheduleJob.getEndDate()); + } + + // 按新的cronExpression表达式构建一个新的trigger + CronTrigger trigger = triggerBuilder.build(); + + scheduler.scheduleJob(jobDetail, trigger); + scheduleJob.setNextRunTime(trigger.getNextFireTime()); + } + + if (scheduleJob.getTaskType() == 1) { + SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule() + .withIntervalInSeconds(scheduleJob.getEvery() / 1000); + if (scheduleJob.getRepeatCount() != null) { + scheduleBuilder.withRepeatCount(scheduleJob.getRepeatCount()); + } else { + scheduleBuilder.repeatForever(); + } + TriggerBuilder triggerBuilder = TriggerBuilder.newTrigger() + .withIdentity(getTriggerKey(scheduleJob.getJobId())).withSchedule(scheduleBuilder); + if (scheduleJob.getStartDate() != null) { + triggerBuilder.startAt(scheduleJob.getStartDate()); + } + + if (scheduleJob.getEndDate() != null) { + triggerBuilder.endAt(scheduleJob.getEndDate()); + } + Trigger trigger = triggerBuilder.build(); + + scheduler.scheduleJob(jobDetail, trigger); + scheduleJob.setNextRunTime(trigger.getNextFireTime()); + } + + // 暂停任务 + if (scheduleJob.getStatus() != null && scheduleJob.getStatus() == ScheduleStatus.PAUSE.getValue()) { + pauseJob(scheduler, scheduleJob.getJobId()); + } + } catch (SchedulerException e) { + throw new CoolException("创建定时任务失败", e); + } + } + + /** + * 更新定时任务 + */ + public static void updateScheduleJob(Scheduler scheduler, TaskInfoEntity scheduleJob) { + try { + TriggerKey triggerKey = getTriggerKey(scheduleJob.getJobId()); + + if (scheduleJob.getTaskType() == 0) { + // 表达式调度构建器 + CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCron()) + .withMisfireHandlingInstructionDoNothing(); + + CronTrigger trigger = getCronTrigger(scheduler, scheduleJob.getJobId()); + + TriggerBuilder triggerBuilder = trigger.getTriggerBuilder(); + + if (scheduleJob.getStartDate() != null) { + triggerBuilder.startAt(scheduleJob.getStartDate()); + } + + if (scheduleJob.getEndDate() != null) { + triggerBuilder.endAt(scheduleJob.getEndDate()); + } + + // 按新的cronExpression表达式重新构建trigger + trigger = triggerBuilder.withIdentity(triggerKey).withSchedule(scheduleBuilder).build(); + + scheduler.rescheduleJob(triggerKey, trigger); + scheduleJob.setNextRunTime(trigger.getNextFireTime()); + + } + + if (scheduleJob.getTaskType() == 1) { + SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule() + .withIntervalInSeconds(scheduleJob.getEvery() / 1000); + + SimpleTrigger trigger = getSimpleTrigger(scheduler, scheduleJob.getJobId()); + + if (scheduleJob.getRepeatCount() != null) { + scheduleBuilder.withRepeatCount(scheduleJob.getRepeatCount()); + } else { + scheduleBuilder.repeatForever(); + } + TriggerBuilder triggerBuilder = trigger.getTriggerBuilder(); + if (scheduleJob.getStartDate() != null) { + triggerBuilder.startAt(scheduleJob.getStartDate()); + } + + if (scheduleJob.getEndDate() != null) { + triggerBuilder.endAt(scheduleJob.getEndDate()); + } + trigger = triggerBuilder.withIdentity(triggerKey).withSchedule(scheduleBuilder).build(); + + scheduler.rescheduleJob(triggerKey, trigger); + scheduleJob.setNextRunTime(trigger.getNextFireTime()); + } + + // 暂停任务 + if (scheduleJob.getStatus() == ScheduleStatus.PAUSE.getValue()) { + pauseJob(scheduler, scheduleJob.getJobId()); + } + + } catch (SchedulerException e) { + throw new CoolException("更新定时任务失败", e); + } + } + + /** + * 立即执行任务 + */ + public static void run(Scheduler scheduler, TaskInfoEntity scheduleJob) { + try { + // 参数 + JobDataMap dataMap = new JobDataMap(); + + scheduler.triggerJob(getJobKey(scheduleJob.getJobId()), dataMap); + } catch (SchedulerException e) { + throw new CoolException("立即执行定时任务失败", e); + } + } + + /** + * 暂停任务 + */ + public static void pauseJob(Scheduler scheduler, String jobId) { + try { + scheduler.pauseJob(getJobKey(jobId)); + } catch (SchedulerException e) { + throw new CoolException("暂停定时任务失败", e); + } + } + + /** + * 恢复任务 + */ + public static void resumeJob(Scheduler scheduler, String jobId) { + try { + scheduler.resumeJob(getJobKey(jobId)); + } catch (SchedulerException e) { + throw new CoolException("恢复定时任务失败", e); + } + } + + /** + * 删除定时任务 + */ + public static void deleteScheduleJob(Scheduler scheduler, String jobId) { + try { + scheduler.deleteJob(getJobKey(jobId)); + } catch (SchedulerException e) { + throw new CoolException("删除定时任务失败", e); + } + } +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/user/controller/admin/AdminUserInfoController.java b/cool-admin-java/src/main/java/com/cool/modules/user/controller/admin/AdminUserInfoController.java new file mode 100644 index 0000000..833762d --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/user/controller/admin/AdminUserInfoController.java @@ -0,0 +1,24 @@ +package com.cool.modules.user.controller.admin; + +import static com.cool.modules.user.entity.table.UserInfoEntityTableDef.USER_INFO_ENTITY; + +import cn.hutool.json.JSONObject; +import com.cool.core.annotation.CoolRestController; +import com.cool.core.base.BaseController; +import com.cool.modules.user.entity.UserInfoEntity; +import com.cool.modules.user.service.UserInfoService; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletRequest; + +@Tag(name = "用户信息", description = "用户信息") +@CoolRestController(api = {"add", "delete", "update", "page", "list", "info"}) +public class AdminUserInfoController extends BaseController { + + @Override + protected void init(HttpServletRequest request, JSONObject requestParams) { + + setPageOption(createOp().fieldEq(USER_INFO_ENTITY.STATUS, USER_INFO_ENTITY.GENDER, + USER_INFO_ENTITY.LOGIN_TYPE) + .keyWordLikeFields(USER_INFO_ENTITY.NICK_NAME, USER_INFO_ENTITY.PHONE)); + } +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/user/controller/app/AppUserAddressController.java b/cool-admin-java/src/main/java/com/cool/modules/user/controller/app/AppUserAddressController.java new file mode 100644 index 0000000..78aacc3 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/user/controller/app/AppUserAddressController.java @@ -0,0 +1,49 @@ +package com.cool.modules.user.controller.app; + +import static com.cool.modules.user.entity.table.UserAddressEntityTableDef.USER_ADDRESS_ENTITY; + +import cn.hutool.json.JSONObject; +import com.cool.core.annotation.CoolRestController; +import com.cool.core.base.BaseController; +import com.cool.core.request.R; +import com.cool.core.util.CoolSecurityUtil; +import com.cool.modules.user.entity.UserAddressEntity; +import com.cool.modules.user.service.UserAddressService; +import com.mybatisflex.core.query.QueryWrapper; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.web.bind.annotation.GetMapping; + +/** + * 用户模块-收货地址 + */ +@Tag(name = "用户模块-收货地址", description = "用户模块-收货地址") +@CoolRestController(api = {"add", "delete", "update", "page", "list", "info"}) +public class AppUserAddressController extends BaseController { + @Override + protected void init(HttpServletRequest request, JSONObject requestParams) { + setPageOption( + createOp() + .queryWrapper( + QueryWrapper.create() + .and(USER_ADDRESS_ENTITY.USER_ID.eq(CoolSecurityUtil.getCurrentUserId())) + .orderBy( + USER_ADDRESS_ENTITY.IS_DEFAULT.getName(), false))); + + setListOption( + createOp() + .queryWrapper( + QueryWrapper.create() + .and(USER_ADDRESS_ENTITY.USER_ID.eq(CoolSecurityUtil.getCurrentUserId())) + .orderBy( + USER_ADDRESS_ENTITY.IS_DEFAULT.getName(), false))); + } + + @Operation(summary = "默认地址", description = "默认地址") + @GetMapping("/default") + public R getDefault() { + Long userId = CoolSecurityUtil.getCurrentUserId(); + return R.ok(this.service.getDefault(userId)); + } +} \ No newline at end of file diff --git a/cool-admin-java/src/main/java/com/cool/modules/user/controller/app/AppUserInfoController.java b/cool-admin-java/src/main/java/com/cool/modules/user/controller/app/AppUserInfoController.java new file mode 100644 index 0000000..0f09313 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/user/controller/app/AppUserInfoController.java @@ -0,0 +1,70 @@ +package com.cool.modules.user.controller.app; + +import cn.hutool.json.JSONObject; +import com.cool.core.annotation.CoolRestController; +import com.cool.core.request.R; +import com.cool.core.util.CoolSecurityUtil; +import com.cool.core.util.EntityUtils; +import com.cool.modules.user.entity.UserInfoEntity; +import com.cool.modules.user.service.UserInfoService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestAttribute; + +@RequiredArgsConstructor +@Tag(name = "用户信息", description = "用户信息") +@CoolRestController +public class AppUserInfoController { + + private final UserInfoService userInfoService; + + @Operation(summary = "用户个人信息", description = "获得App、小程序或者其他应用的用户个人信息") + @GetMapping("/person") + public R person() { + Long userId = CoolSecurityUtil.getCurrentUserId(); + UserInfoEntity userInfoEntity = userInfoService.person(userId); + return R.ok(EntityUtils.toMap(userInfoEntity, + "password")); + } + + @Operation(summary = "更新用户信息") + @PostMapping("/updatePerson") + public R updatePerson(@RequestAttribute JSONObject requestParams) { + UserInfoEntity infoEntity = requestParams.toBean(UserInfoEntity.class); + infoEntity.setId(CoolSecurityUtil.getCurrentUserId()); + return R.ok( + userInfoService.updateById(infoEntity) + ); + } + + @Operation(summary = "更新用户密码") + @PostMapping("/updatePassword") + public R updatePassword( + @RequestAttribute JSONObject requestParams + ) { + String password = requestParams.get("password", String.class); + String code = requestParams.get("code", String.class); + userInfoService.updatePassword(CoolSecurityUtil.getCurrentUserId(), password, code); + return R.ok(); + } + + @Operation(summary = "注销") + @PostMapping("/logoff") + public R logoff() { + userInfoService.logoff(CoolSecurityUtil.getCurrentUserId()); + return R.ok(); + } + + @Operation(summary = "绑定手机号") + @PostMapping("/bindPhone") + public R bindPhone( + @RequestAttribute JSONObject requestParams) { + String phone = requestParams.get("phone", String.class); + String code = requestParams.get("code", String.class); + userInfoService.bindPhone(CoolSecurityUtil.getCurrentUserId(), phone, code); + return R.ok(); + } +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/user/controller/app/AppUserLoginController.java b/cool-admin-java/src/main/java/com/cool/modules/user/controller/app/AppUserLoginController.java new file mode 100644 index 0000000..53fe9d8 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/user/controller/app/AppUserLoginController.java @@ -0,0 +1,182 @@ +package com.cool.modules.user.controller.app; + +import com.cool.core.annotation.CoolRestController; +import com.cool.core.annotation.TokenIgnore; +import com.cool.core.enums.UserTypeEnum; +import com.cool.core.exception.CoolPreconditions; +import com.cool.core.request.R; +import com.cool.modules.base.service.sys.BaseSysLoginService; +import com.cool.modules.user.controller.app.params.CaptchaParam; +import com.cool.modules.user.controller.app.params.LoginParam; +import com.cool.modules.user.controller.app.params.RefreshTokenParam; +import com.cool.modules.user.controller.app.params.SmsCodeParam; +import com.cool.modules.user.service.UserLoginService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; + +@RequiredArgsConstructor +@Tag(name = "用户登录", description = "用户登录") +@CoolRestController +public class AppUserLoginController { + + private final UserLoginService userLoginService; + + private final BaseSysLoginService baseSysLoginService; + + /** + * 小程序登录 + */ + @TokenIgnore + @Operation(summary = "小程序登录") + @PostMapping("/mini") + public R mini(@RequestBody LoginParam param) { + String code = param.getCode(); + String encryptedData = param.getEncryptedData(); + String iv = param.getIv(); + CoolPreconditions.checkEmpty(code); + CoolPreconditions.checkEmpty(encryptedData); + CoolPreconditions.checkEmpty(iv); + return R.ok(userLoginService.mini(code, encryptedData, iv)); + } + + /** + * 公众号登录 + */ + @TokenIgnore + @Operation(summary = "公众号登录") + @PostMapping("/mp") + public R mp(@RequestBody LoginParam param) { + String code = param.getCode(); + CoolPreconditions.checkEmpty(code); + return R.ok(userLoginService.mp(code)); + } + + /** + * 微信APP授权登录 + */ + @TokenIgnore + @Operation(summary = "微信APP授权登录") + @PostMapping("/wxApp") + public R wxApp(@RequestBody LoginParam param) { + String code = param.getCode(); + CoolPreconditions.checkEmpty(code); + return R.ok(userLoginService.wxApp(code)); + } + + /** + * 手机号登录 + */ + @TokenIgnore + @Operation(summary = "手机号登录") + @PostMapping("/phone") + public R phone( + @RequestBody LoginParam param) { + String phone = param.getPhone(); + String smsCode = param.getSmsCode(); + CoolPreconditions.checkEmpty(phone); + CoolPreconditions.checkEmpty(smsCode); + return R.ok(userLoginService.phoneVerifyCode(phone, smsCode)); + } + + /** + * 一键手机号登录 + */ + @TokenIgnore + @Operation(summary = "一键手机号登录") + @PostMapping("/uniPhone") + public R uniPhone( + @RequestBody LoginParam param) { + String accessToken = param.getAccess_token(); + String openid = param.getOpenid(); + String appId = param.getAppId(); + CoolPreconditions.checkEmpty(accessToken); + CoolPreconditions.checkEmpty(openid); + CoolPreconditions.checkEmpty(appId); + return R.ok(userLoginService.uniPhone(accessToken, openid, appId)); + } + + /** + * 绑定小程序手机号 + */ + @TokenIgnore + @Operation(summary = "绑定小程序手机号") + @PostMapping("/miniPhone") + public R miniPhone(@RequestBody LoginParam param) { + String code = param.getCode(); + String encryptedData = param.getEncryptedData(); + String iv = param.getIv(); + CoolPreconditions.checkEmpty(code); + CoolPreconditions.checkEmpty(encryptedData); + CoolPreconditions.checkEmpty(iv); + return R.ok(userLoginService.miniPhone(code, encryptedData, iv)); + } + + /** + * 图片验证码 + */ + @TokenIgnore + @Operation(summary = "图片验证码") + @GetMapping("/captcha") + public R captcha( + @ModelAttribute CaptchaParam param) { + String type = param.getType(); + Integer width = param.getWidth(); + Integer height = param.getHeight(); + + CoolPreconditions.checkEmpty(type); + CoolPreconditions.checkEmpty(width); + CoolPreconditions.checkEmpty(height); + + return R.ok(baseSysLoginService.captcha(UserTypeEnum.APP, type, width, height)); + } + + /** + * 验证码 + */ + @TokenIgnore + @Operation(summary = "验证码") + @PostMapping("/smsCode") + public R smsCode( + @RequestBody SmsCodeParam param) { + String phone = param.getPhone(); + String captchaId = param.getCaptchaId(); + String code = param.getCode(); + + CoolPreconditions.checkEmpty(phone); + CoolPreconditions.checkEmpty(captchaId); + CoolPreconditions.checkEmpty(code); + userLoginService.smsCode(phone, captchaId, code); + return R.ok(); + } + + /** + * 刷新token + */ + @TokenIgnore + @Operation(summary = "刷新token") + @PostMapping("/refreshToken") + public R refreshToken(@RequestBody RefreshTokenParam param) { + return R.ok(userLoginService.refreshToken(param.getRefreshToken())); + } + + /** + * 密码登录 + */ + @TokenIgnore + @Operation(summary = "密码登录") + @PostMapping("/password") + public R password( + @RequestBody LoginParam param) { + String phone = param.getPhone(); + String password = param.getPassword(); + + CoolPreconditions.checkEmpty(phone); + CoolPreconditions.checkEmpty(password); + return R.ok(userLoginService.password(phone, password)); + } +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/user/controller/app/params/CaptchaParam.java b/cool-admin-java/src/main/java/com/cool/modules/user/controller/app/params/CaptchaParam.java new file mode 100644 index 0000000..b01495c --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/user/controller/app/params/CaptchaParam.java @@ -0,0 +1,12 @@ +package com.cool.modules.user.controller.app.params; + +import lombok.Getter; +import lombok.Setter; + +@Setter +@Getter +public class CaptchaParam { + private String type; + private Integer width = 150; + private Integer height = 50; +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/user/controller/app/params/LoginParam.java b/cool-admin-java/src/main/java/com/cool/modules/user/controller/app/params/LoginParam.java new file mode 100644 index 0000000..bb4df32 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/user/controller/app/params/LoginParam.java @@ -0,0 +1,34 @@ +package com.cool.modules.user.controller.app.params; + +import lombok.Getter; +import lombok.Setter; + +@Setter +@Getter +public class LoginParam { + + /*******小程序/公众号/微信APP授权 登录*******/ + private String code; + + private String encryptedData; + + private String iv; + + + /*******手机号登录*******/ + private String phone; + + private String smsCode; + + + /*******一键手机号登录*******/ + private String access_token; + + private String openid; + + private String appId; + + + /*******密码登录*******/ + private String password; +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/user/controller/app/params/RefreshTokenParam.java b/cool-admin-java/src/main/java/com/cool/modules/user/controller/app/params/RefreshTokenParam.java new file mode 100644 index 0000000..c06065a --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/user/controller/app/params/RefreshTokenParam.java @@ -0,0 +1,13 @@ +package com.cool.modules.user.controller.app.params; + +import lombok.Getter; +import lombok.Setter; + +/** + * 刷新token + */ +@Setter +@Getter +public class RefreshTokenParam { + private String refreshToken; +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/user/controller/app/params/SmsCodeParam.java b/cool-admin-java/src/main/java/com/cool/modules/user/controller/app/params/SmsCodeParam.java new file mode 100644 index 0000000..c5c8c75 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/user/controller/app/params/SmsCodeParam.java @@ -0,0 +1,12 @@ +package com.cool.modules.user.controller.app.params; + +import lombok.Getter; +import lombok.Setter; + +@Setter +@Getter +public class SmsCodeParam { + private String phone; + private String captchaId; + private String code; +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/user/entity/UserAddressEntity.java b/cool-admin-java/src/main/java/com/cool/modules/user/entity/UserAddressEntity.java new file mode 100644 index 0000000..2297a4f --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/user/entity/UserAddressEntity.java @@ -0,0 +1,43 @@ +package com.cool.modules.user.entity; + +import com.cool.core.base.BaseEntity; +import com.mybatisflex.annotation.Table; +import com.tangzc.mybatisflex.autotable.annotation.ColumnDefine; +import lombok.Getter; +import lombok.Setter; +import org.dromara.autotable.annotation.Index; + +/** + * 用户模块-收货地址 + */ +@Getter +@Setter +@Table(value = "user_address", comment = "用户模块-收货地址") +public class UserAddressEntity extends BaseEntity { + + @Index + @ColumnDefine(comment = "用户ID", notNull = true) + private Long userId; + + @ColumnDefine(comment = "联系人", notNull = true) + private String contact; + + @Index + @ColumnDefine(comment = "手机号", length = 11, notNull = true) + private String phone; + + @ColumnDefine(comment = "省", notNull = true) + private String province; + + @ColumnDefine(comment = "市", notNull = true) + private String city; + + @ColumnDefine(comment = "区", notNull = true) + private String district; + + @ColumnDefine(comment = "地址", notNull = true) + private String address; + + @ColumnDefine(comment = "是否默认", defaultValue = "false") + private Boolean isDefault; +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/user/entity/UserInfoEntity.java b/cool-admin-java/src/main/java/com/cool/modules/user/entity/UserInfoEntity.java new file mode 100644 index 0000000..776177e --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/user/entity/UserInfoEntity.java @@ -0,0 +1,40 @@ +package com.cool.modules.user.entity; + +import com.cool.core.base.BaseEntity; +import com.mybatisflex.annotation.Table; +import com.tangzc.mybatisflex.autotable.annotation.ColumnDefine; +import com.tangzc.mybatisflex.autotable.annotation.UniIndex; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@Table(value = "user_info", comment = "用户信息") +public class UserInfoEntity extends BaseEntity { + + @UniIndex + @ColumnDefine(comment = "登录唯一ID") + private String unionid; + + @ColumnDefine(comment = "头像") + private String avatarUrl; + + @ColumnDefine(comment = "昵称") + private String nickName; + + @UniIndex + @ColumnDefine(comment = "手机号") + private String phone; + + @ColumnDefine(comment = "性别 0-未知 1-男 2-女", defaultValue = "0") + private Integer gender; + + @ColumnDefine(comment = "状态 0-禁用 1-正常 2-已注销", defaultValue = "1") + private Integer status; + + @ColumnDefine(comment = "登录方式 0-小程序 1-公众号 2-H5", defaultValue = "0") + private String loginType; + + @ColumnDefine(comment = "密码") + private String password; +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/user/entity/UserWxEntity.java b/cool-admin-java/src/main/java/com/cool/modules/user/entity/UserWxEntity.java new file mode 100644 index 0000000..4737c8c --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/user/entity/UserWxEntity.java @@ -0,0 +1,47 @@ +package com.cool.modules.user.entity; + +import com.cool.core.base.BaseEntity; +import com.mybatisflex.annotation.Table; +import com.tangzc.mybatisflex.autotable.annotation.ColumnDefine; +import com.tangzc.mybatisflex.autotable.annotation.UniIndex; +import lombok.Getter; +import lombok.Setter; +import org.dromara.autotable.annotation.Index; + +@Getter +@Setter +@Table(value = "user_wx", comment = "微信用户") +public class UserWxEntity extends BaseEntity { + + @Index + @ColumnDefine(comment = "微信unionid") + private String unionid; + + @UniIndex + @ColumnDefine(comment = "微信openid", notNull = true) + private String openid; + + @ColumnDefine(comment = "头像") + private String avatarUrl; + + @ColumnDefine(comment = "昵称") + private String nickName; + + @ColumnDefine(comment = "性别 0-未知 1-男 2-女", defaultValue = "0") + private Integer gender; + + @ColumnDefine(comment = "语言") + private String language; + + @ColumnDefine(comment = "城市") + private String city; + + @ColumnDefine(comment = "省份") + private String province; + + @ColumnDefine(comment = "国家") + private String country; + + @ColumnDefine(comment = "类型 0-小程序 1-公众号 2-H5 3-APP", defaultValue = "0") + private Integer type; +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/user/mapper/UserAddressMapper.java b/cool-admin-java/src/main/java/com/cool/modules/user/mapper/UserAddressMapper.java new file mode 100644 index 0000000..94ede5c --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/user/mapper/UserAddressMapper.java @@ -0,0 +1,10 @@ +package com.cool.modules.user.mapper; + +import com.cool.modules.user.entity.UserAddressEntity; +import com.mybatisflex.core.BaseMapper; + +/** + * 用户模块-收货地址 + */ +public interface UserAddressMapper extends BaseMapper { +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/user/mapper/UserInfoMapper.java b/cool-admin-java/src/main/java/com/cool/modules/user/mapper/UserInfoMapper.java new file mode 100644 index 0000000..5b9f71d --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/user/mapper/UserInfoMapper.java @@ -0,0 +1,7 @@ +package com.cool.modules.user.mapper; + +import com.mybatisflex.core.BaseMapper; +import com.cool.modules.user.entity.UserInfoEntity; + +public interface UserInfoMapper extends BaseMapper { +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/user/mapper/UserWxMapper.java b/cool-admin-java/src/main/java/com/cool/modules/user/mapper/UserWxMapper.java new file mode 100644 index 0000000..f23a071 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/user/mapper/UserWxMapper.java @@ -0,0 +1,10 @@ +package com.cool.modules.user.mapper; + +import com.mybatisflex.core.BaseMapper; +import com.cool.modules.user.entity.UserWxEntity; + +/** + * 微信用户 + */ +public interface UserWxMapper extends BaseMapper { +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/user/proxy/WxProxy.java b/cool-admin-java/src/main/java/com/cool/modules/user/proxy/WxProxy.java new file mode 100644 index 0000000..ffcba4c --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/user/proxy/WxProxy.java @@ -0,0 +1,36 @@ +package com.cool.modules.user.proxy; + +import cn.binarywang.wx.miniapp.api.WxMaService; +import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult; +import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo; +import cn.binarywang.wx.miniapp.bean.WxMaUserInfo; +import com.cool.core.util.CoolPluginInvokers; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.mp.api.WxMpService; +import org.springframework.stereotype.Service; + +@Service +public class WxProxy { + public WxMaService getWxMaService() { + return (WxMaService)CoolPluginInvokers.invoke("wx", "getWxMaService"); + } + public WxMpService getWxMpService() { + return (WxMpService)CoolPluginInvokers.invoke("wx", "getWxMpService"); + } + + public WxMaJscode2SessionResult getSessionInfo(String jsCode) throws WxErrorException { + return getWxMaService().getUserService() + .getSessionInfo(jsCode); + } + + public WxMaPhoneNumberInfo getPhoneNumber(String jsCode) throws WxErrorException { + return getWxMaService().getUserService() + .getPhoneNumber(jsCode); + } + + public WxMaUserInfo getUserInfo(String sessionKey, String encryptedData, String ivStr) throws WxErrorException { + return getWxMaService().getUserService() + .getUserInfo(sessionKey, encryptedData, ivStr); + } + +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/user/service/UserAddressService.java b/cool-admin-java/src/main/java/com/cool/modules/user/service/UserAddressService.java new file mode 100644 index 0000000..da73041 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/user/service/UserAddressService.java @@ -0,0 +1,15 @@ +package com.cool.modules.user.service; + +import com.cool.core.base.BaseService; +import com.cool.modules.user.entity.UserAddressEntity; + +/** + * 用户模块-收货地址 + */ +public interface UserAddressService extends BaseService { + + /** + * 获取默认地址 + */ + Object getDefault(Long userId); +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/user/service/UserInfoService.java b/cool-admin-java/src/main/java/com/cool/modules/user/service/UserInfoService.java new file mode 100644 index 0000000..a779e80 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/user/service/UserInfoService.java @@ -0,0 +1,28 @@ +package com.cool.modules.user.service; + +import com.cool.core.base.BaseService; +import com.cool.modules.user.entity.UserInfoEntity; + +public interface UserInfoService extends BaseService { + /** + * 用户个人信息 + * @param userId + * @return + */ + UserInfoEntity person(Long userId); + + /** + * 更新用户密码 + */ + void updatePassword(Long userId, String password, String code); + + /** + * 注销 + */ + void logoff(Long currentUserId); + + /** + * 绑定手机号 + */ + void bindPhone(Long currentUserId, String phone, String code); +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/user/service/UserLoginService.java b/cool-admin-java/src/main/java/com/cool/modules/user/service/UserLoginService.java new file mode 100644 index 0000000..9c8048f --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/user/service/UserLoginService.java @@ -0,0 +1,57 @@ +package com.cool.modules.user.service; + +/** + * 用户登录 + */ +public interface UserLoginService { + + /** + * 发送短信验证码 + * @param phone + * @param captchaId + * @param code + */ + void smsCode(String phone, String captchaId, String code); + + /** + * 手机号验证码登录 + * @param phone + * @param smsCode + */ + Object phoneVerifyCode(String phone, String smsCode); + + + /** + * 刷新token + * + * @param refreshToken 刷新token + * @return 新的token + */ + Object refreshToken(String refreshToken); + /** + * 小程序登录 + */ + Object mini(String code, String encryptedData, String iv); + /** + * 公众号登录 + */ + Object mp(String code); + /** + * 微信APP授权登录 + */ + Object wxApp(String code); + + /** + * 一键手机号登录 + */ + Object uniPhone(String accessToken, String openid, String appId); + /** + * 绑定小程序手机号 + */ + Object miniPhone(String code, String encryptedData, String iv); + + /** + * 密码登录 + */ + Object password(String phone, String password); +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/user/service/UserWxService.java b/cool-admin-java/src/main/java/com/cool/modules/user/service/UserWxService.java new file mode 100644 index 0000000..28e0d65 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/user/service/UserWxService.java @@ -0,0 +1,15 @@ +package com.cool.modules.user.service; + +import com.cool.core.base.BaseService; +import com.cool.modules.user.entity.UserWxEntity; + +/** + * 微信用户 + */ +public interface UserWxService extends BaseService { + + /** + * 获取小程序用户信息 + */ + UserWxEntity getMiniUserInfo(String code, String encryptedData, String iv); +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/user/service/impl/UserAddressServiceImpl.java b/cool-admin-java/src/main/java/com/cool/modules/user/service/impl/UserAddressServiceImpl.java new file mode 100644 index 0000000..8ba4cfe --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/user/service/impl/UserAddressServiceImpl.java @@ -0,0 +1,21 @@ +package com.cool.modules.user.service.impl; + +import com.cool.core.base.BaseServiceImpl; +import com.cool.modules.user.entity.UserAddressEntity; +import com.cool.modules.user.mapper.UserAddressMapper; +import com.cool.modules.user.service.UserAddressService; +import com.mybatisflex.core.query.QueryWrapper; +import org.springframework.stereotype.Service; + +/** + * 用户模块-收货地址 + */ +@Service +public class UserAddressServiceImpl extends BaseServiceImpl implements UserAddressService { + + @Override + public Object getDefault(Long userId) { + return this.getOne(QueryWrapper.create().eq(UserAddressEntity::getUserId, userId) + .eq(UserAddressEntity::getIsDefault, true).limit(1)); + } +} \ No newline at end of file diff --git a/cool-admin-java/src/main/java/com/cool/modules/user/service/impl/UserInfoServiceImpl.java b/cool-admin-java/src/main/java/com/cool/modules/user/service/impl/UserInfoServiceImpl.java new file mode 100644 index 0000000..e66e993 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/user/service/impl/UserInfoServiceImpl.java @@ -0,0 +1,52 @@ +package com.cool.modules.user.service.impl; + +import cn.hutool.crypto.digest.MD5; +import com.cool.core.base.BaseServiceImpl; +import com.cool.modules.user.entity.UserInfoEntity; +import com.cool.modules.user.mapper.UserInfoMapper; +import com.cool.modules.user.service.UserInfoService; +import com.cool.modules.user.util.UserSmsUtil; +import com.cool.modules.user.util.UserSmsUtil.SendSceneEnum; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class UserInfoServiceImpl extends BaseServiceImpl implements + UserInfoService { + + private final UserSmsUtil userSmsUtil; + + @Override + public UserInfoEntity person(Long userId) { + UserInfoEntity info = getById(userId); + info.setPassword(null); + return info; + } + + @Override + public void updatePassword(Long userId, String password, String code) { + UserInfoEntity info = getById(userId); + userSmsUtil.checkVerifyCode(info.getPhone(), code, SendSceneEnum.ALL); + info.setPassword(MD5.create().digestHex(password)); + info.updateById(); + } + + @Override + public void logoff(Long userId) { + UserInfoEntity info = new UserInfoEntity(); + info.setId(userId); + info.setStatus(2); + info.setNickName("已注销-00" + userId); + info.updateById(); + } + + @Override + public void bindPhone(Long userId, String phone, String code) { + userSmsUtil.checkVerifyCode(phone, code, SendSceneEnum.ALL); + UserInfoEntity info = new UserInfoEntity(); + info.setId(userId); + info.setPhone(phone); + info.updateById(); + } +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/user/service/impl/UserLoginServiceImpl.java b/cool-admin-java/src/main/java/com/cool/modules/user/service/impl/UserLoginServiceImpl.java new file mode 100644 index 0000000..d8202a6 --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/user/service/impl/UserLoginServiceImpl.java @@ -0,0 +1,192 @@ +package com.cool.modules.user.service.impl; + +import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo; +import cn.hutool.core.convert.Convert; +import cn.hutool.core.lang.Dict; +import cn.hutool.core.util.ObjUtil; +import cn.hutool.core.util.RandomUtil; +import cn.hutool.crypto.digest.MD5; +import cn.hutool.jwt.JWT; +import com.cool.core.cache.CoolCache; +import com.cool.core.enums.UserTypeEnum; +import com.cool.core.exception.CoolPreconditions; +import com.cool.core.security.jwt.JwtTokenUtil; +import com.cool.core.security.jwt.JwtUser; +import com.cool.modules.base.service.sys.BaseSysLoginService; +import com.cool.modules.user.entity.UserInfoEntity; +import com.cool.modules.user.entity.UserWxEntity; +import com.cool.modules.user.proxy.WxProxy; +import com.cool.modules.user.service.UserInfoService; +import com.cool.modules.user.service.UserLoginService; +import com.cool.modules.user.service.UserWxService; +import com.cool.modules.user.util.UserSmsUtil; +import com.cool.modules.user.util.UserSmsUtil.SendSceneEnum; +import com.mybatisflex.core.query.QueryWrapper; +import java.util.List; +import lombok.RequiredArgsConstructor; +import me.chanjar.weixin.common.error.WxErrorException; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.stereotype.Service; + +@RequiredArgsConstructor +@Service +public class UserLoginServiceImpl implements UserLoginService { + + private final CoolCache coolCache; + + private final JwtTokenUtil jwtTokenUtil; + + private final UserInfoService userInfoService; + + private final UserSmsUtil userSmsUtil; + + private final BaseSysLoginService baseSysLoginService; + + private final UserWxService userWxService; + + private final WxProxy wxProxy; + private final static List authority = + List.of(new SimpleGrantedAuthority("ROLE_" + UserTypeEnum.APP.name())); + + @Override + public void smsCode(String phone, String captchaId, String code) { + // 校验图片验证码,不通过直接抛异常 + baseSysLoginService.captchaCheck(captchaId, code); + userSmsUtil.sendVerifyCode(phone, SendSceneEnum.ALL); + coolCache.del("verify:img:" + captchaId); + } + + @Override + public Object phoneVerifyCode(String phone, String smsCode) { + // 校验短信验证码,不通过直接抛异常 + userSmsUtil.checkVerifyCode(phone, smsCode, SendSceneEnum.ALL); + return generateTokenByPhone(phone); + } + + + @Override + public Object refreshToken(String refreshToken) { + CoolPreconditions.check(!jwtTokenUtil.validateRefreshToken(refreshToken), "错误的refreshToken"); + JWT jwt = jwtTokenUtil.getTokenInfo(refreshToken); + CoolPreconditions.check(jwt == null || !(Boolean) jwt.getPayload("isRefresh"), + "错误的refreshToken"); + Long userId = Convert.toLong(jwt.getPayload("userId")); + return generateToken(userId, refreshToken); + } + + @Override + public Object mini(String code, String encryptedData, String iv) { + UserWxEntity userWxEntity = userWxService.getMiniUserInfo(code, encryptedData, iv); + return wxLoginToken(userWxEntity); + } + + private Object wxLoginToken(UserWxEntity userWxEntity) { + String unionId = ObjUtil.isNotEmpty(userWxEntity.getUnionid()) ? userWxEntity.getUnionid() + : userWxEntity.getOpenid(); + UserInfoEntity userInfoEntity = userInfoService.getOne( + QueryWrapper.create().eq(UserInfoEntity::getUnionid, unionId)); + if (ObjUtil.isEmpty(userInfoEntity)) { + userInfoEntity = new UserInfoEntity(); + userInfoEntity.setNickName(ObjUtil.isNotEmpty(userWxEntity.getNickName()) ? userWxEntity.getNickName() : generateRandomNickname()); + userInfoEntity.setGender(userWxEntity.getGender()); + userInfoEntity.setAvatarUrl(userWxEntity.getAvatarUrl()); + userInfoEntity.setUnionid(unionId); + userInfoEntity.save(); + } + return generateToken(userInfoEntity, null); + } + + @Override + public Object mp(String code) { + return null; + } + + @Override + public Object wxApp(String code) { + return null; + } + + @Override + public Object uniPhone(String accessToken, String openid, String appId) { + return null; + } + + @Override + public Object miniPhone(String code, String encryptedData, String iv) { + try { + WxMaPhoneNumberInfo phoneNumber = wxProxy.getPhoneNumber(code); + CoolPreconditions.checkEmpty(phoneNumber, "微信登录失败"); + return generateTokenByPhone(phoneNumber.getPhoneNumber()); + } catch (WxErrorException e) { + CoolPreconditions.alwaysThrow(e.getMessage(), e); + } + CoolPreconditions.alwaysThrow("微信登录失败"); + return null; + } + + @Override + public Object password(String phone, String password) { + UserInfoEntity userInfoEntity = userInfoService.getOne( + QueryWrapper.create().eq(UserInfoEntity::getPhone, phone)); + CoolPreconditions.checkEmpty(userInfoEntity, "账号或密码错误"); + if (userInfoEntity.getPassword().equals(MD5.create().digestHex(password))) { + return generateToken(userInfoEntity, null); + } + CoolPreconditions.checkEmpty(userInfoEntity, "账号或密码错误"); + return null; + } + + /** + * 前置已校验用户的手机号, + * 根据手机号找到用户生成token + */ + private Object generateTokenByPhone(String phone) { + UserInfoEntity userInfoEntity = userInfoService.getOne( + QueryWrapper.create().eq(UserInfoEntity::getPhone, phone)); + if (ObjUtil.isEmpty(userInfoEntity)) { + userInfoEntity = new UserInfoEntity(); + userInfoEntity.setPhone(phone); + // 生成随机昵称 + userInfoEntity.setNickName(generateRandomNickname()); + userInfoEntity.save(); + } + return generateToken(userInfoEntity, null); + } + + /** + * + * @return 生成的昵称 + */ + private String generateRandomNickname() { + // 定义昵称的长度 + int length = 8; + // 生成随机字符串 + return RandomUtil.randomString(length); + } + /** + * 生成token + */ + private Dict generateToken(Long userId, String refreshToken) { + UserInfoEntity userInfoEntity = userInfoService.getById(userId); + return generateToken(userInfoEntity, refreshToken); + } + private Dict generateToken(UserInfoEntity userInfoEntity, String refreshToken) { + Dict tokenInfo = Dict.create() + .set("userType", UserTypeEnum.APP.name()) + .set("userId", userInfoEntity.getId()); + String token = jwtTokenUtil.generateToken(tokenInfo); + if (ObjUtil.isEmpty(refreshToken)) { + refreshToken = jwtTokenUtil.generateRefreshToken(tokenInfo); + } + JwtUser jwtUser = new JwtUser(userInfoEntity.getId(), + authority, + ObjUtil.equals(userInfoEntity.getStatus(), 1)); + coolCache.set("app:userDetails:" + jwtUser.getUserId(), jwtUser); + return Dict.create() + .set("token", token) + .set("expire", jwtTokenUtil.getExpire()) + .set("refreshToken", refreshToken) + .set("refreshExpire", jwtTokenUtil.getRefreshExpire()); + } +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/user/service/impl/UserWxServiceImpl.java b/cool-admin-java/src/main/java/com/cool/modules/user/service/impl/UserWxServiceImpl.java new file mode 100644 index 0000000..6b8286c --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/user/service/impl/UserWxServiceImpl.java @@ -0,0 +1,60 @@ +package com.cool.modules.user.service.impl; + +import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult; +import cn.binarywang.wx.miniapp.bean.WxMaUserInfo; +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.ObjUtil; +import com.cool.core.base.BaseServiceImpl; +import com.cool.core.exception.CoolPreconditions; +import com.cool.modules.user.entity.UserWxEntity; +import com.cool.modules.user.mapper.UserWxMapper; +import com.cool.modules.user.proxy.WxProxy; +import com.cool.modules.user.service.UserWxService; +import com.mybatisflex.core.query.QueryWrapper; +import lombok.RequiredArgsConstructor; +import me.chanjar.weixin.common.error.WxErrorException; +import org.springframework.stereotype.Service; + +/** + * 微信用户 + */ +@Service +@RequiredArgsConstructor +public class UserWxServiceImpl extends BaseServiceImpl implements UserWxService { + + private final WxProxy wxProxy; + + /** + * 获得小程序用户信息 + */ + public UserWxEntity getMiniUserInfo(String code, String encryptedData, String iv) { + // 获取 session + WxMaJscode2SessionResult result = null; + try { + result = wxProxy.getSessionInfo(code); + // 解密数据 + WxMaUserInfo wxMaUserInfo = wxProxy.getUserInfo(result.getSessionKey(), encryptedData, iv); + if (ObjUtil.isNotEmpty(wxMaUserInfo)) { + UserWxEntity userWxEntity = BeanUtil.copyProperties(wxMaUserInfo, UserWxEntity.class); + userWxEntity.setOpenid(result.getOpenid()); + userWxEntity.setUnionid(wxMaUserInfo.getUnionId()); + return getBySave(userWxEntity, 0); + } + } catch (WxErrorException e) { + CoolPreconditions.alwaysThrow(e.getMessage(), e); + } + CoolPreconditions.alwaysThrow("获得小程序用户信息"); + return null; + } + + public UserWxEntity getBySave(UserWxEntity entity, int type) { + UserWxEntity one = this.getOne( + QueryWrapper.create().eq(UserWxEntity::getOpenid, entity.getOpenid())); + if (ObjUtil.isEmpty(one)) { + entity.setType(type); + super.save(entity); + return entity; + } + return one; + } +} \ No newline at end of file diff --git a/cool-admin-java/src/main/java/com/cool/modules/user/util/UserSmsUtil.java b/cool-admin-java/src/main/java/com/cool/modules/user/util/UserSmsUtil.java new file mode 100644 index 0000000..43c5aff --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/user/util/UserSmsUtil.java @@ -0,0 +1,90 @@ +package com.cool.modules.user.util; + +import cn.hutool.core.util.RandomUtil; +import cn.hutool.core.util.StrUtil; +import com.cool.core.cache.CoolCache; +import com.cool.core.exception.CoolPreconditions; +import com.cool.core.plugin.service.CoolPluginService; +import com.cool.core.util.CoolPluginInvokers; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +/** + * UserSmsUtil - 用户短信工具类 + * 该类用于发送短信验证码。 + */ +@RequiredArgsConstructor +@Slf4j +@Component +public class UserSmsUtil { + + /** + * 短信发送场景枚举 + */ + public enum SendSceneEnum { + ALL, + } + + private final CoolPluginService coolPluginService; + + private final CoolCache coolCache; + + /** + * 发送短信验证码 + * + * @param phone + */ + public void sendVerifyCode(String phone, SendSceneEnum sendSceneEnum) { + // 随机生成4位验证码 + String verifyCode = RandomUtil.randomNumbers(4); + send(phone, verifyCode); + coolCache.set(sendSceneEnum.name() + "_sms:" + phone, verifyCode, 60 * 10); + } + + /** + * 检查验证码 + * @param phone + * @param code + * @return + */ + public void checkVerifyCode(String phone, String code, SendSceneEnum sendSceneEnum) { + String key = sendSceneEnum.name() + "_sms:" + phone; + String cacheCode = coolCache.get(key, String.class); + boolean flag = StrUtil.isNotEmpty(code) && code.equals(cacheCode); + if (flag) { + // 删除验证码 + coolCache.del(key); + } + CoolPreconditions.check(!flag, "验证码错误"); + } + + /** + * 发送短信 + * + * @param phone + * @param code + */ + public void send(String phone, String code) { + List phones = new ArrayList<>(); + phones.add(phone); + + Map params = new HashMap<>(); + params.put("code", code); + // 插件key sms-tx、sms-ali,哪个实例存在就调用哪个 + if (coolPluginService.getInstanceWithoutCheck("sms-tx") != null) { + // 调用腾讯短信插件 + CoolPluginInvokers.invoke("sms-tx", "send", phones, params); + } else if (coolPluginService.getInstanceWithoutCheck("sms-ali") != null) { + // 调用阿里短信插件 + CoolPluginInvokers.invoke("sms-ali", "send", phones, params); + } else { + // 未找到短信插件 + log.error("未找到短信插件,请前往插件市场下载安装"); + } + } +} diff --git a/cool-admin-java/src/main/java/com/cool/modules/user/util/UserWxUtil.java b/cool-admin-java/src/main/java/com/cool/modules/user/util/UserWxUtil.java new file mode 100644 index 0000000..74b32eb --- /dev/null +++ b/cool-admin-java/src/main/java/com/cool/modules/user/util/UserWxUtil.java @@ -0,0 +1,12 @@ +package com.cool.modules.user.util; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +/** + * UserWxUtil - 用户微信工具类 + */ +@Component +@RequiredArgsConstructor +public class UserWxUtil { +} diff --git a/cool-admin-java/src/main/java/org/dromara/autotable/core/strategy/pgsql/builder/ColumnSqlBuilder.java b/cool-admin-java/src/main/java/org/dromara/autotable/core/strategy/pgsql/builder/ColumnSqlBuilder.java new file mode 100644 index 0000000..97f545c --- /dev/null +++ b/cool-admin-java/src/main/java/org/dromara/autotable/core/strategy/pgsql/builder/ColumnSqlBuilder.java @@ -0,0 +1,53 @@ +package org.dromara.autotable.core.strategy.pgsql.builder; + +import org.dromara.autotable.annotation.enums.DefaultValueEnum; +import org.dromara.autotable.core.strategy.ColumnMetadata; +import org.dromara.autotable.core.utils.StringConnectHelper; +import org.dromara.autotable.core.utils.StringUtils; + +/** + * 列相关的SQL生成器 + * 覆盖原始的ColumnSqlBuilder GENERATED ALWAYS AS IDENTITY 改为 GENERATED BY DEFAULT AS IDENTITY + * 已提issues https://gitee.com/dromara/auto-table/issues/IC6TR5 + */ +public class ColumnSqlBuilder { + + /** + * 生成字段相关的SQL片段 + * + * @param columnMetadata 列元数据 + * @return 列相关的sql + */ + public static String buildSql(ColumnMetadata columnMetadata) { + // 例子:"name" varchar(100) NULL DEFAULT '张三' COMMENT '名称' + // 例子:"id" int4(32) NOT NULL AUTO_INCREMENT COMMENT '主键' + StringConnectHelper sql = StringConnectHelper.newInstance("{columnName} {typeAndLength} {null} {default}") + .replace("{columnName}", columnMetadata.getName()) + .replace("{typeAndLength}", () -> columnMetadata.getType().getDefaultFullType()); + + // 如果是自增列,则使用GENERATED ALWAYS AS IDENTITY, 忽略not null和默认值的配置 + if (columnMetadata.isAutoIncrement()) { + return sql.replace("{null} {default}", "GENERATED BY DEFAULT AS IDENTITY").toString(); + } + + return sql.replace("{null}", columnMetadata.isNotNull() ? "NOT NULL" : "") + .replace("{default}", () -> { + // 指定NULL + DefaultValueEnum defaultValueType = columnMetadata.getDefaultValueType(); + if (defaultValueType == DefaultValueEnum.NULL) { + return "DEFAULT NULL"; + } + // 指定空字符串 + if (defaultValueType == DefaultValueEnum.EMPTY_STRING) { + return "DEFAULT ''"; + } + // 自定义 + String defaultValue = columnMetadata.getDefaultValue(); + if (DefaultValueEnum.isCustom(defaultValueType) && StringUtils.hasText(defaultValue)) { + return "DEFAULT " + defaultValue; + } + return ""; + }) + .toString(); + } +} diff --git a/cool-admin-java/src/main/java/org/springframework/boot/autoconfigure/quartz/QuartzAutoConfiguration.java b/cool-admin-java/src/main/java/org/springframework/boot/autoconfigure/quartz/QuartzAutoConfiguration.java new file mode 100644 index 0000000..2d01e23 --- /dev/null +++ b/cool-admin-java/src/main/java/org/springframework/boot/autoconfigure/quartz/QuartzAutoConfiguration.java @@ -0,0 +1,159 @@ +/* + * Copyright 2012-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.autoconfigure.quartz; + +import java.util.Map; +import java.util.Properties; + +import javax.sql.DataSource; + +import com.cool.core.util.DatabaseDialectUtils; +import org.quartz.Calendar; +import org.quartz.JobDetail; +import org.quartz.Scheduler; +import org.quartz.Trigger; + +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate; +import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; +import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration; +import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration; +import org.springframework.boot.autoconfigure.sql.init.OnDatabaseInitializationCondition; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.sql.init.dependency.DatabaseInitializationDependencyConfigurer; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Conditional; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.core.annotation.Order; +import org.springframework.scheduling.quartz.SchedulerFactoryBean; +import org.springframework.scheduling.quartz.SpringBeanJobFactory; +import org.springframework.transaction.PlatformTransactionManager; + +/** + * {@link EnableAutoConfiguration Auto-configuration} for Quartz Scheduler. + * 覆盖原始的QuartzAutoConfiguration,兼容postgres数据库 + * properties.getProperties().put("org.quartz.jobStore.driverDelegateClass", "org.quartz.impl.jdbcjobstore.PostgreSQLDelegate"); + * @author Vedran Pavic + * @author Stephane Nicoll + * @since 2.0.0 + */ +@AutoConfiguration(after = { DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class, + LiquibaseAutoConfiguration.class, FlywayAutoConfiguration.class }) +@ConditionalOnClass({ Scheduler.class, SchedulerFactoryBean.class, PlatformTransactionManager.class }) +@EnableConfigurationProperties(QuartzProperties.class) +public class QuartzAutoConfiguration { + + @Bean + @ConditionalOnMissingBean + public SchedulerFactoryBean quartzScheduler(QuartzProperties properties, + ObjectProvider customizers, ObjectProvider jobDetails, + Map calendars, ObjectProvider triggers, ApplicationContext applicationContext) { + SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean(); + SpringBeanJobFactory jobFactory = new SpringBeanJobFactory(); + jobFactory.setApplicationContext(applicationContext); + schedulerFactoryBean.setJobFactory(jobFactory); + if (properties.getSchedulerName() != null) { + schedulerFactoryBean.setSchedulerName(properties.getSchedulerName()); + } + schedulerFactoryBean.setAutoStartup(properties.isAutoStartup()); + schedulerFactoryBean.setStartupDelay((int) properties.getStartupDelay().getSeconds()); + schedulerFactoryBean.setWaitForJobsToCompleteOnShutdown(properties.isWaitForJobsToCompleteOnShutdown()); + schedulerFactoryBean.setOverwriteExistingJobs(properties.isOverwriteExistingJobs()); + if (!properties.getProperties().isEmpty()) { + schedulerFactoryBean.setQuartzProperties(asProperties(properties.getProperties())); + } + schedulerFactoryBean.setJobDetails(jobDetails.orderedStream().toArray(JobDetail[]::new)); + schedulerFactoryBean.setCalendars(calendars); + schedulerFactoryBean.setTriggers(triggers.orderedStream().toArray(Trigger[]::new)); + customizers.orderedStream().forEach((customizer) -> customizer.customize(schedulerFactoryBean)); + return schedulerFactoryBean; + } + + private Properties asProperties(Map source) { + Properties properties = new Properties(); + properties.putAll(source); + return properties; + } + + @Configuration(proxyBeanMethods = false) + @ConditionalOnSingleCandidate(DataSource.class) + @ConditionalOnProperty(prefix = "spring.quartz", name = "job-store-type", havingValue = "jdbc") + @Import(DatabaseInitializationDependencyConfigurer.class) + protected static class JdbcStoreTypeConfiguration { + + @Bean + @Order(0) + public SchedulerFactoryBeanCustomizer dataSourceCustomizer(QuartzProperties properties, DataSource dataSource, + @QuartzDataSource ObjectProvider quartzDataSource, + ObjectProvider transactionManager, + @QuartzTransactionManager ObjectProvider quartzTransactionManager) { + return (schedulerFactoryBean) -> { + DataSource dataSourceToUse = getDataSource(dataSource, quartzDataSource); + schedulerFactoryBean.setDataSource(dataSourceToUse); + PlatformTransactionManager txManager = getTransactionManager(transactionManager, + quartzTransactionManager); + if (txManager != null) { + schedulerFactoryBean.setTransactionManager(txManager); + } + }; + } + + private DataSource getDataSource(DataSource dataSource, ObjectProvider quartzDataSource) { + DataSource dataSourceIfAvailable = quartzDataSource.getIfAvailable(); + return (dataSourceIfAvailable != null) ? dataSourceIfAvailable : dataSource; + } + + private PlatformTransactionManager getTransactionManager( + ObjectProvider transactionManager, + ObjectProvider quartzTransactionManager) { + PlatformTransactionManager transactionManagerIfAvailable = quartzTransactionManager.getIfAvailable(); + return (transactionManagerIfAvailable != null) ? transactionManagerIfAvailable + : transactionManager.getIfUnique(); + } + + @Bean + @ConditionalOnMissingBean(QuartzDataSourceScriptDatabaseInitializer.class) + @Conditional(OnQuartzDatasourceInitializationCondition.class) + public QuartzDataSourceScriptDatabaseInitializer quartzDataSourceScriptDatabaseInitializer( + DataSource dataSource, @QuartzDataSource ObjectProvider quartzDataSource, + QuartzProperties properties) { + DataSource dataSourceToUse = getDataSource(dataSource, quartzDataSource); + if (DatabaseDialectUtils.isPostgresql(dataSource)) { + properties.getProperties().put("org.quartz.jobStore.driverDelegateClass", "org.quartz.impl.jdbcjobstore.PostgreSQLDelegate"); + } + return new QuartzDataSourceScriptDatabaseInitializer(dataSourceToUse, properties); + } + + static class OnQuartzDatasourceInitializationCondition extends OnDatabaseInitializationCondition { + + OnQuartzDatasourceInitializationCondition() { + super("Quartz", "spring.quartz.jdbc.initialize-schema"); + } + + } + + } + +} diff --git a/cool-admin-java/src/main/resources/application-local.yml b/cool-admin-java/src/main/resources/application-local.yml new file mode 100644 index 0000000..049731f --- /dev/null +++ b/cool-admin-java/src/main/resources/application-local.yml @@ -0,0 +1,42 @@ +spring: + datasource: + url: jdbc:mysql://107.172.82.181:63301/cool?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2b8 + username: root + password: W4%qmVpow + driver-class-name: com.mysql.cj.jdbc.Driver + +# url: jdbc:postgresql://127.0.0.1:5432/cool +# username: postgres +# password: 123456 +# driver-class-name: org.postgresql.Driver +# AutoTable配置,根据实体类自动生成表 +auto-table: + # 启用自动维护表功能 + enable: true + # 自动删除名称不匹配的索引 + autoDropIndex: true + # 建表的时候,父类的字段排序是在子类后面还是前面 + superInsertPosition: before + # 模型包路径 + model-package: com.cool.**.entity.* + +# Cool相关配置 +cool: + # 初始化数据 + initData: false + +# 文档 +springdoc: + api-docs: + #是否开启文档功能 本地为了配合eps功能不可关闭 + enabled: true + group-configs: + - group: app + paths-to-match: /app/** + - group: admin + paths-to-match: /admin/** + +# 设置日志级别 +logging: + level: + com.cool: debug \ No newline at end of file diff --git a/cool-admin-java/src/main/resources/application-prod.yml b/cool-admin-java/src/main/resources/application-prod.yml new file mode 100644 index 0000000..7d4b34d --- /dev/null +++ b/cool-admin-java/src/main/resources/application-prod.yml @@ -0,0 +1,27 @@ +spring: + datasource: + url: jdbc:mysql://127.0.0.1:3306/cool?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2b8 + username: root + password: 123456 + driver-class-name: com.mysql.cj.jdbc.Driver + +# AutoTable配置,根据实体类自动生成表 +auto-table: + # 启用自动维护表功能 + enable: false + +# Cool相关配置 +cool: + # 初始化数据 + initData: false + +# 文档 +springdoc: + api-docs: + #是否开启文档功能 本地为了配合eps功能不可关闭 + enabled: true + +# 设置日志级别 +logging: + level: + com.cool: error \ No newline at end of file diff --git a/cool-admin-java/src/main/resources/application.yml b/cool-admin-java/src/main/resources/application.yml new file mode 100644 index 0000000..2ca78b3 --- /dev/null +++ b/cool-admin-java/src/main/resources/application.yml @@ -0,0 +1,162 @@ +server: + port: 8001 + servlet: + context-path: / + compression: + enabled: true + mime-types: application/json,application/xml,text/html,text/plain + +spring: + application: + name: cool-admin-java + profiles: + active: @spring.active@ + thymeleaf: + cache: false + prefix: classpath:/templates/ + suffix: .html + mode: HTML + #返回时间格式化 + jackson: + time-zone: GMT+8 + date-format: yyyy-MM-dd HH:mm:ss + + servlet: + multipart: + enabled: true + max-file-size: 2GB + max-request-size: 2GB + # Web设置 + web: + resources: + add-mappings: true + static-locations: classpath:/static/,file:./assets/public/ + + # caffeine 缓存 + cache: + type: caffeine + file: assets/cache + + #redis 缓存 + cache: + type: redis + data: + redis: + host: 107.172.82.181 + port: 63179 + database: 8 + password: 'R30#B5nTT' + quartz: + job-store-type: jdbc + jdbc: + initialize-schema: always + autoStartup: true + #相关属性配置 + properties: + org: + quartz: + scheduler: + instanceName: CoolScheduler + instanceId: AUTO + jobStore: + class: org.springframework.scheduling.quartz.LocalDataSourceJobStore + driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate + tablePrefix: QRTZ_ + isClustered: true + clusterCheckinInterval: 10000 + useProperties: false + threadPool: + class: org.quartz.simpl.SimpleThreadPool + threadCount: 5 + threadPriority: 9 + threadsInheritContextClassLoaderOfInitializingThread: true + +# 忽略url +ignored: + # 忽略后台鉴权url + adminAuthUrls: + - / + - /upload/** + - /actuator/** + - /download/** + - /static/** + - /favicon.ico + - /v3/api-docs/** + - /swagger + - /swagger-ui/** + - /css/* + - /js/* + - /druid/** + - /admin/base/open/** + # 忽略记录请求日志url + logUrls: + - / + - /**/eps + - /app/** + - /css/* + - /js/* + - /favicon.ico +# 文档 +springdoc: + api-docs: + #swagger后端请求地址 + path: /v3/api-docs + swagger-ui: + #自定义swagger前端请求路径,输入http://127.0.0.1:端口号/swagger会自动重定向到swagger页面 + path: /swagger + +mybatis-flex: + #多数据源 + # datasource: + #MyBatis 配置文件位置,如果有单独的 MyBatis 配置,需要将其路径配置到 configLocation 中 + # configuration: + #MyBatis Mapper 所对应的 XML 文件位置,如果在 Mapper 中有自定义的方法(XML 中有自定义的实现),需要进行该配置,指定 Mapper 所对应的 XML 文件位置 + mapper-locations: [ "classpath*:/mapper/**/*.xml" ] + type-aliases-package: com.cool.**.entity.* + global-config: + print-banner: false + + +# Cool相关配置 +cool: + # 缓存名称 + cacheName: comm + plugin: + # 插件安装位置 + path: assets/plugin + # token 相关配置 + token: + # 过期时间 单位:秒 半小时 + expire: 1800 + # 刷新token过期时间 单位:秒 7天 + refreshExpire: 604800 + # 文件上传相关 + file: + #上传模式 + mode: local + # 本地上传配置 + local: + # 文件访问地址 + base-url: http://127.0.0.1:${server.port}/upload + # 系统日志请求参数超过1024字节 就不记录,避免日志过大 + log: + # 请求参数最大字节,超过请求参数不记录 + max-byte-length: 1024 + # 核心线程数的倍数 + core-pool-size-multiplier: 2 + # 最大线程数的倍数 + max-pool-size-multiplier: 3 + # 队列容量的倍数 + queue-capacity-multiplier: 3 + multi-tenant: + # 是否开启多租户,默认关闭 + enable: false +# AutoTable配置,根据实体类自动生成表 +auto-table: + show-banner: false + +# 分布式唯一ID组件 +leaf: + segment: + # 默认禁用 + enable: false \ No newline at end of file diff --git a/cool-admin-java/src/main/resources/banner.txt b/cool-admin-java/src/main/resources/banner.txt new file mode 100644 index 0000000..0fce0d9 --- /dev/null +++ b/cool-admin-java/src/main/resources/banner.txt @@ -0,0 +1,8 @@ +✨🌈✨[cool-admin-java-plus](https://gitee.com/hlc4417/cool-admin-java-plus)✨🌈✨ + ______ ___ ___ _____ _ ______ ____ ____ _____ ____ _____ + .' ___ | .' `. .' `.|_ _| V8.x / \ |_ _ `.|_ \ / _||_ _||_ \|_ _| +/ .' \_|/ .-. \/ .-. \ | | ______ / _ \ | | `. \ | \/ | | | | \ | | +| | | | | || | | | | | _|______|/ ___ \ | | | | | |\ /| | | | | |\ \| | +\ `.___.'\\ `-' /\ `-' /_| |__/ | _/ / \ \_ _| |_.' /_| |_\/_| |_ _| |_ _| |_\ |_ + `.____ .' `.___.' `.___.'|________| |____| |____||______.'|_____||_____||_____||_____|\____| +:: https://java.cool-admin.com :: \ No newline at end of file diff --git a/cool-admin-java/src/main/resources/cool/captcha/bgimages/48.jpg b/cool-admin-java/src/main/resources/cool/captcha/bgimages/48.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ae731e4ee24c2a9f1ec2774ff8b07cb5b7890406 GIT binary patch literal 126519 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®kGj$k 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 literal 0 HcmV?d00001 diff --git a/cool-admin-java/src/main/resources/cool/captcha/bgimages/a.jpg b/cool-admin-java/src/main/resources/cool/captcha/bgimages/a.jpg new file mode 100644 index 0000000000000000000000000000000000000000..cef38ec0d19a2b323ee45a7e7b3e8eb957df3874 GIT binary patch literal 39380 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 literal 0 HcmV?d00001 diff --git a/cool-admin-java/src/main/resources/cool/captcha/bgimages/b.jpg b/cool-admin-java/src/main/resources/cool/captcha/bgimages/b.jpg new file mode 100644 index 0000000000000000000000000000000000000000..72fdb5639006e3c94a378abd4483b150f9d84c1e GIT binary patch literal 50207 zcmb4qWl&vD@a5x&26wk0!QDN$ySoMV_izschljhnLvWYiPH=a3c{l`?|5okRe%*7w z+^W7cJ<~Nc)A#i0kL8bT0J@x%tP}tW3JPHI`2arF0O9~R7+5%17&tgsICywC1VnU1 z#4leEu~E^G(ebeH@$s;6aS2JN$q0!kiE(ks8ObTX(a_P;5s)#lGSRY9)6&uY&md6n z@bHKTh**e-ShR$=gtY(P_~->-AV69FrvnW|0r(FC3K|3IV*o$`06@V&f6n&*0u~wu z4j%9y0@RmJvm83$KPc$`U|^tOKbP-Anf6xFJ4A`%5m~5h0s-`aR6hE=q#p3gE zDAnrzAaIz?>|9fc1A}gGIjPkX`tT$)5)0}ZW_LfwB7y>ZI{Kf;{2%-W4Fd)E49cgG z4FmAsC!k#_KojrO(w~ftPATB2G)F*>-q$|IIh{#?ACR%{AAm-vf3#6Wc-M`1^ffMlG8=x9 zJljvH57M;9)QJSA{y_RU20lu3&hTou^FkXoj@<^0b0;GljQf~_+pWH-UhG4i?P1$8DxHy@{U&&mbwNGhyD?8drEDa|3x zcf+%SlT13T5%;7z#qvSyyj$)y)J8n*R*{$Y1EwL^PEWF(|B4^o(T{;^TLclBX$%l| zb(L)N@d}sF&c$BK?;2wplnR%A)3$V@+=0Xiq;!XFy$Ije~7<;;t3Gf*wK@PNnQ!1@h5&1XaKJcvJA~{+w?T zi?Ej+K|`;mjSPkkQ-q!BP1p(4(wUV`WuGju8A=fm99|sg#efOKgo9~9J`ttX6SqM8JZlqD79SkyXzt1 z>aJkctj+Hl!j1e>!qtTE3%THo9Vs=nm_Y_T`A54LF=4a%->y~poOhUL#f)KTYB-%V zhZIftgOvhWT3Ttbus*uF1}@3jm1yF6ZGBi-+Qi=6wFH4M39R&3gT8JS1%JLu$?|bC zgT`~ef=h34rr(Tj@CQW&H{xQguBK+2nU(N8CDk2I#LmF?x^*D%5qjQ>P`>dbMzzVh?u@QD zW?kDE(mPD>2fiYgf^Nea?lT(N#1@}$8Tx-;OPZ^x1?%c=VU|d=^OG+NQ7VCL)SZDR z`uYkj7>wbvT4hZWB{ut@`P|v4>(@g*yx)9P7KwXheSO<|*gGDoiZ@3_LB5k_)aH?6 zlElHmvne>`=~AB_w9-Uta0(K$eJ<$?2@x*rgXjiKmk%;065l4dcXfXRt$wv58hKk8 zA%Jns!)^cd=$(Zwo~&&`%6+%~0ie%kSfxucs4Eqr&2EfmU=$5ZPfZ81etBcj`HW-|Gp%~pUVzUcAjYrESp$6k47n{ekNSC zKs0=5{sCa8ESQMk{5=_rT&D3H{WpEr$0s$Wo$yGzH@8#z6b1rISrW0@*SQ@=d$K^Whup=vhD_C z=gu3(dRh{1(pN8y$fFDwKcNfbG@!l1AhuJEMxt$5&H@$Dpgx<^%eK! zp;{fhBeUg;oB%Ozd39i2s8bN)mHZ+4jP(z`9VCeJ{Y4t6+V0q! zRik;w*4!$4#5N>r|07F1FUrNbZXz&LR&Md)e!M7a;6s(GJb zyIYkgqZ3v8uz2R$O-WCPWz_9`iN~yPp_$e9FUH-4E!C)*=>?dHaRcvR|Ez}*aBv@& z&>H1$kJhRkcnVJbm zqEMGz=kdLEAZy*|ijxYf$z1v@AfgYp2?YGS+1|TYV~OoO^+K+i2*5ZjzKe)y+U;RO z+@jme{IL&U(}52dE4rwg4H@iBm8E3AT)`IJ_1xukht4#Wvz}R3c6!|(u;m7AorpGR z>3%yfd{+8$qBr6q$;X>laf+cI4TPX`{4UvQL5nO+M9PL7s8&`hF?gx1We&uH`J`>V zF!6kmvvSAkIJH{qwDy%KlLT$YfCwYiRG{TO>@DSAgO241E=F5HOj*&1F=eq_lJ0pa z$u2na>?TKte}o&mI<2$bev!N&hFdp`qVx^aNH}`HPsMg#APUqd(`ScyBjTk(|0?&( zS+lKIu2Qzz&e0em@kZ&GX$4Ed?Tjv7&eX_Jj8o<~cLzKbBHcDCx_tXl6W3Z*i@on) zv>3tVl3a2?w_w{((MokJ%Rk#+Y>nr=VHa(Gryb2+(p6Q%hEmC}h;J^=;)eF$C2i>I z+h!89IUW;CrS<#0bt&b2b?O!3KK#!?3zMqC@9Da_vWAl+U5yD7JCvd+=F3_f(QV0J zLyD67C@yufpj5zYyB4w1IWqXvZSc&)FtNuX*-RA%vOdJ1^>Q$eNbAoI7B8|T62Xe} zr}Dwb*%Rb%F)9*B=()-$tre3 zSZ~q2jh)#WFT66>bkmc|(E zGdh$(b^%z5cDMM!9@T~+X3v5saapZsn^5AO>(}^X{Bon$K2-ywxe(kDw%*XB{Y zo#SElqL$8zWm4nBW7Wll4ujM>&J>5iPnivUq3*_7{!pX|zF5&C1^XIIEmy5^Dd+iv z9q9yazh~jAE?X&CRB5@fKeP3Xx;mp}xkxpqAaPGI_qN^CkX|F{6xFlI@z{Nvkm7+B zcl6C^XfbAuI;qo`nWR_ZNU<+J>K5}mqLZne6*UU2>jp>hkljzofACUW<+2!0<-K%u zz6e*fr1T=Uh&g|`>>jR`Yh+S%a?sp5aOT0eY_V){pPa1co(TB$!1c}E;lfMwrsVfj z@y;{G+&zNRg|BBU9W-i{hx!&p0U5f}dBTuDBk;;`Oa|Jl?Zharb*{!j(_jRiVTfO* zt7kUoMzOVX=WOrGq3l3bL2lOsi5RwD3LhaVz} zo90Nd&t8#M;PNEzkXtMvOt#sySnA0Fw2%;ceiw|h*?=_i`!$vLo4yX+ng7*p7wW2x z@S-$n*dVomm(!2cNk3UGV7h(A`O^x<>G6PLYIY3ZRu& zDt!PHqO^nXl0p%Sb*!qtds@kXXAK?nIEd|Nf-$YmG8B^M=z9y6#_f|%^xj(VRK;#6 zD$iwvPUVT-e#x%p6N{j7$vh7$%m=GnFFW6;;W6 zPQE9&?Ii`$ZFf-cX=JaP)Sc6k)N_{yMEUEIN{tAdGnfy?POL0_C{4ywcFD%E$c;8g1&p^K^+0 z;~$1YbY{+m_&lQVO@y=d6t8mss&J-Ge_d#5{k(}>_}f3=&gA$3cv}ld4|q}9J62S_ z>t>#DYyEGzlE*Q)0K__+nQuQIs4CY_ufU8N#Fe z0g&7BXjxfjw1WmFE{A3p4VsHYd#y^Xb7s4oNZ;L|c;NG%srplQ&hz?8ZSs%XeI=JB zKSJ~k3m6MRi&!;E>uibJXwECVlz@Wu;a1vAo*5@ASg*^f>&%thfl>p_t7(777QUAW zcv>l;&wVE=L-PuIj$H8PJOP>rWxoV3%awir+Usr!KL7)eufq--DUGIT$L&F0ibUz@ z)x^EnV=A{t(@km*TX>$x8ei1*2qwr9V|$8YN}zY6|dqk>3B=e!odpg_!hx`EA_a&u3eJGU2fY0 ziTeP|CB9WEuP%nYo06VNdRV_Jp0M;vbz#pEt$D>>9*Un#Dka@lD~iCW8!6i{Ffb@! zCOI`BbY?m1l$aYIp4^T_q{zmkGmNdkLHm1X zkUlDH%B}JvfQ^je)=l}z>v6|d)yv}A12fUHE0af@s z{0ca9UjkMSa!kLeyLB=kQ8w?Ogk-)sG*&b&G{Lkp-9iCmXp0t~%D?pOgjZEJ609a~ zV)8g;{kH+5Vj}p!_vqvU5O2ts#LQbogwD1mfYvEXNh+3MAh^j-uV07w>mZY0Yi+i; zSSs#nY+IUr|$uy||tNzjo8GC70&0Z|Cze6pxA(o5*EX%7)goDXg-`2Zks4Q>CkWEiy6 z=S~}Dosy;#Ak%Xq+0GavVP4OzmxjQ?+wZy4y!^e5VoY^E<-j)*Jv+3c>G`@FS=g8^ zRcf2~{eXp1l?oG_hmqwS{5N(g;`q_*ebSPgF)%4UAmnF1+JpxDPEHjwFP2<;YueLd zBvY~Fa$GCX^SS8Dd}+v!!+E!Z?=Uu=Y_S}KDgP8<$Yz9P)a&IwcMM%nEIr$RVrG-- zimj5;0`XFwWk)y#1d~;Wfh;J8LH^s2x8OJZ1%Q1=qS}svYbJGLAarL;2VuZ!9k~~u z-^way+(S{NB_9oEx*N%j4m0g){clp!7P*@=+V#c4?n#1oM-^J`mZ~TMT!d$Z$)4G8 zSx)OiDPGaKZ+QlGEW!Rui0)eO!l7XLVJQL9_jw;f%}eq>QtLJDT%5B`i7E}cdun-E z=o=L*@MugMSsaosV}{Vc_$JxAO3k|ZNB|J8{GQV>I-51fZ*}Z1R(zKQqauz}>;P_X zZ_^@Elzu}HGxiUujVSXxVLyJ$xLs$;`Ae^*WP-N12a9t_>OLDHJzMsviV+HW&35yD zKUJ!wBbu1F@tV`s9+jzX8OL)J9;RF5nzIaR;X6*=(-SjsZ@OxyKLB3eI@x?gE*M;! zlXk#tS zKfGT&s_pO9QR~ayD1n=`jKJJ}+I4@|ms{mkjIP1f!S#SGv1}c*q3-VF10WmcYcDXW z_h0!Fxgad^gH~$FWzj0*glU{Pj1`Q=c$n*oBNxg;WB5}7FXU7t8A*TSBKtt}1Au(Q zUh$6gX7T|L{`ab0>7aUd*TF{W<5PBx=+tBW_5t88jY|F@3zZtWW+=$>9=sv1re8T~ zC=vy|+6X?&B%AX)WpM(|jApM1U`P}sMWZ7?|31??3XaNu+ho`q<$e01Z^y(HvoKgx z6AkS#%zzxkCg<#4;u##aFY*rjg2w+CpsMNz;`eOp4EzA}tq-Ybl3?64#QKMZ`Eo9V zR2s0-u#MFIoPUnYB_>`Arr*1vNsSeZ*Vn9Hp0&?l81$0*V(@caJ4+f$t)X;7fQwkS zunl9Zb)1~{b`o`$4p)fVd_KO3uKM_PCjm5;$?*QI!_yv_`&?p<^!rvXn)UXh?v5sgGoXS*oP?$RN^|P>whraN z^Vih&d7h=0>@+F^Js!%TO`YXe(nic#9x?gc)UlMOg5~QsvK;`zRfF=Kd(hE zR`#!2*_3N}YcZ zeO+MkpE|nSBkmDnC~S3-qO&0b?T;j5wLnbP(?w_fo&Udi<~)nq#i-_=p1lidw`#6=eGB28j5b${^lLd$?4bYFY$ z;hb{9=;)}A4I=b;Ddh)XPnF>V5TeCeZta%tFxRrGDnq6s$t5c5fc4|bo6 zJQTc)J|+?+5YuJ7(1Aio2^EMQBSG9Q0(Y zSRejxEi+1Idp!hS5u%1)M(TVoM521WkQ}iFc ztoXSmWK*vv$ffEan^TgNM}`sm7jf-eB@p;UxTGmmKQkT11!F?G1ipM)^h`Ol6fW}v z(6Zmw4()ZMqN@Caeg7!nt=8U*=Sd|v!)d610V9TU0BA|-ys-@t9)_{| z^+YzV{W7p1PAB#T0XSY3*nFzjH%F&E{HP}Xf`0rw=SM51N>yWh)*grhEMexh zn0@2EcpyP>J1eWSqSa4k5-_6rZMQ?$BYkCm$V>L{A3LCiC(^@4Q)WGPcTnEp^0KH! zXJV?ZW<774@XHSHm7Bn%xxkGyaj>0wAd0wFfJY1?KJbO^ThZ@RJ%t&NPCxOsy>shu zx5qyQaAAs!fjm|{`&BX(*;EO!$dHt;j@_)xUpYS5c_9A2@@tr?A*~#elm<{}WoFKx zFgvd~+zWX1HppUC#wqM5gaY)yyq+p9Iio`|QgpEqnT8z&ikCw+!8ZKvQAI-ywuJWs zz?c#Jgf!uC8Ao~ZoggN4y?;|>!P>t*&)SKclH5TT;;1C&&4np+UxmN+xT^Aw&sc2*g#>`E`Z)}piSsi->7_v2b+xmm1cI`O|V zcr??2ssmYB~v zYkis|*E|(te1dA%!?!u2yWIYl{D=ZJJi#DAwXBpj`>UfSm@wR>r8-vXB#6UPn4GUa zEy4PJnw3(6eiUYNe2V8j`~gX9ZVJNLnN}&XuR!PglPyEJuoIz?_0Gu%{FqnQTNgcS zuK|q*NMK!&Abf_I>8Au zkAmO%?Agv#I&-4k4>;IPxu}-$+r(~x=sL=i15uW4Qkxh5d@S7)4?L6dn^I+D5E;{m zh`~dp4!YF+UWg{+L^JfxY8@-Bv$T-VWqgM zJ7w3*Fg=RHjXE~KmeD;sWOVYfQV4vJVsXSkj8L3LOHRg^ph(x3kh$S610L8Te@b42zijdI})gCVkhG$jPJ{E{XRTeVD`x za%(jSZ;&PA#=b120{P2vTxivPMvT$Z_Dce=sPKM;odkT^N%>(1n*+|!`{e?T8Lw1zsBavXm|-A)s+lj z_Qd$0BhF%;_&}JPByM}(41u7c@{%yd)6z3Ng%y^d?{{1k+)Bg6E*hqCeaLdszo%^_ z1}6!uMr=XjlSmlzk+MncP&r1=HJE95;qm!%Q4o6_%fc_k(*tbEM66(8CG~IoUM5~M zIV^2vFlfIIVbIw0Y?iK9^dv0}7$!hp$wHLxO9uJ>4s9S=gT|fmR^^_rcS#8XzRQfh zRj3kGg;x`WY7yXwV|-aGti6qKHymVDR6zd zR1uxZKtC7r+a-aw*1AaTx}pBssjA{AC^yTEcmr~v&SWL6Yb0Mx6h9^@aTKOF<2aRR zXNQI9tHmfIaKBFY<>pl+Ji67GS$5|(rH}BO-B`D~x+otHfv@J`^Y{0bCGD=PCVhZn zB^+UHwQXFiFnvyF-u1=DdttEeMG~A}D(+{2-0pj-gg83!<>iQco?#acanriotNOY- z8`EgNvCyOMF@gG+=;V`LqSrB?UWLz%O}ZJ~d-E696G187s9yM!#TbPb{u?FBUgn6T zW8QBou0}?{ic}NtiEao94R_ojK-g?PwLbu-=MXu*4KhmlRFZK4ZtExPnpZVQuWDN^ zWn=tre{WtBedMs21C=WiS`6-&0?ZG^VO$Ep2YPN8ddg&6St1tXAe`QI;GXTB%aK1QLqb_ojQqX?l zoAu*9{&M_*T-HLfBqPT8emvdIKVm%0b=1#tkg^zuBkd#$GM6_ka5c;%vSZ#|nFP%0_IZ@Q>)#jR)ia;-LNg2*Kg##FLBJfvCeKb{$)fSYk|O$~JoriGi1gw^IUI27F6OnkH_hjAb&>)Hzm0Crrr; zj~gVhmL??Osz)aLeJJz>zF`#rG-(H7Z8y2gKX8w!6KqM=jUrO2d{|=ga4GF)q8_5R zG8*84Qr*LrVTBOr@h#JiUvV(`ezK~jK;DZ0Rf-Sny?_x^xcBUfyzX1RW1IRC#`F}W z?}O!JQDs<=eN8R!0a*9=XN_C1^c}L5ZV~?oCySJLFEFRbS5wXGGO|gqS*%*!^{@3v z<(P*kr|S`CT*|5+)xd9%wEh*|xfFH%24#t!lBviFbq%iMw6s?HgD ztu8vmtk--bdy>5==V54(myvlDfkNv*LUQ!*RQ4=aPiyw1l!fZ@c5ID02!C|v@1Y`KYMh(s^6Nu6a}Tpy<KSO zqPe}#V<+)ifp(_2y36!z{?D$1(Vy7aA#!&uv@!nY!bN}XWWDviAVI$oVQ~K{-_Qr( zmG=Yi0nnq#v#`PHr0R8e7)kJ>64(aga>5T~UOEW1tr@C2&%7EVpI$eVz94Xt0+FP(gvCR?etrJ&Vq zMaw0lnW?bKU&-5>q(Es_l4kOEsp2JL=+=P9yP>X~*Rx6HE5TZr>OBhH(^3(hrA(J# zgXdDCNgK}8l&f*3ZepkC=smJ(SM9zU7Q98aX_#W_Ud%E+WWj%fN>@ld`7_Fb-kW3Q zG4D7x((s^BKl6tufbyGR8M_pGro%+{zMm~3fcNYq7gC$&p3yEBXjqVJ`WSi^tEyQ$ z5F4b&gC+efzu%HXK-Ip59$B339{Ms@Rr%K*%YS6n{OMzCGNcz$o>$8H;DK|K2O{VE-0jLLjVe{{Z;yifyXV!6iDluZUtq zSPHA=b9Mb?#x!x{oTW(AtXs%T9f+i99=$dDq#+v@m~Kjq8#`mgaTA}Ss2a*$*NII7 z7?0qJMbMw#9mF*ap{1i`X{BxCvKOAcG(neZ3v@S_BPXl=F?Kk!2J%+K;|!%6m=MhG zLf0Uj76#gAy;#ltNZTpJOKr<|ubxYz#yM?auCAI|1Q-ZV22D&l+p@vgyraJL47)YJ zKAMop$uboekGt@acPtrlN|)#wI8>cYay_&svztRSSEE3j$}LBcu->f2eM&S>S}1@r ztoPfrS+f-jJ|5Ugi#Fy9W=MJ`c1bc2s99Sdxgu%&A?^buWKKieKMfC~t=V|R6z_u< zvMF&Gv78W-{b$YBCqOU0_9wd8Zg$gLj`v0 zx}flN_1+B4Jq9qVCtnN|T8-g|!!M+-quqqv@Mi9iqE@t1-$|jtHpIRaMSJPt7jLJA zwbu)&uqV>0OZWJeUFNSH&e5kjk2Ge>_xN{QI7_XISMoc14n?-;6K?`1^el#Ztp##gCneoN{F+m8XEiwNU(1@cICH~k zbmbYu&BQU|J3uA`%BdxQ;kKH<9ocUZ2M5c`8LVDh;i4$p>74V#BFNE44~PpJ6t z5w2-q2s?iO=%#a>&ZMdjrg_4~bd|OpL84FP{?nX1GS2QJ!sgz{QRfwyZM>M3#wlbO zorf@1lxK?Fv-LKlf(~&r5UUeayMKDSo7{qLWjDczYi%OQB%7l*J0QpCJ$PLfhi5~b zf~>u|NuK$;*3ftd0k&89W^t<$Yt4MwQo&nPT^>{=(5ZFIzkWH>aIyp{M4{J=61e>^ zL*z!(Z#^hJ7Tz~c*Q^*cw9j$i!qo^H+=OX%rNBnp4*=VA&OP3)5VL$)VOu>2Hy`RS zRCH@n|L+V6>g}H9_F!iMv=az+T%6P7B0f5IF|wJ7VyM|V!{fj{`9fC}6{Vf5Q31$C zV4OJrtfjVJp0R)f+*~Wk`dd#x#jFG`deDU$DkTey8FPt_Wua&2_vI+Jx<`WlArv1y0(3l|niIYr1&M>$_XO z1gOsFY5G8kdOK=p(Yyovz()K7XaSVD%E%qYED{CaL*ox^C5w6XL~Y6S=riC*B|A?~ zW|@zuv9(PF%+YTv$J4!f3O4-?!_?!%jhD2Ip=_{%u7NkK$myzU?OtF#o-t(1T5*X+ zeZCvA9iMqRTs^&{p3i#~fThXJOowlSyr^vQ?Gh0kOL*ItQ*zI;8r~etRt;WCzJiPo zeT=f1wTWozcaF|~ylDz*<(kg9pmf@eBtSuU((m%!-;^swoyjhMGElDxE$qLqavxU< zdAx%psZ@hhMx5ISw#L9GZ$g!Zlm>p;Nvy>A%m4X>h?G#3=k)Kmu=c-{GrT=hX4&*L z`--}|#lZLlYoJUERV3irqkF|YIE1~P;r^@jZ2?9-Qzu9{ZAS1XUTATq;AvfFMquRY zY^A1$uas%!m!5PgQmzd<$DP$71NxH`n_Y6UmdilfDtZknC|i zyQMR?`T+=bgKhRoO&g>e+4^nTzLZTPm`kCoGZ+<{Y@r|g`a+pyTzgVh=`{L~Ij|f8 ztSB4}KNX@C&K&TtoM0?X*py}WMW^J&U!yEF_KrDw!L96Xxv;C&6U2PS%8C$*-7V*i zDlNFiIt7_jY5x(0=7s%!aw$onnz*$>DtHaNxEnRftvt(;Q0&g6(sHl7ZOje#Q#v{k zce67TP)y%zh;KrgH<)Djx9|Wd`@3{$7AhgziJ$H~sKhEbNwA}Y*S>TZd3uA=oU+0G z9?nOUXms@+uDyM8lM{1nw7hMMV}(CbKueH_-$jJoEKLr_=EUe zgHSn@BEzOm7JHJZ?!>y7k1J&by+^x$!w0RXx3X>67S<9OMA1d6Yu23R6nPH(h-Wz7AH&^dVB`debRXrecpx3 zG}ohAiqw4=FT@i1UEdO~0L|2rT&o-P$VS?xN-$@`Tw{4sYrLZbeW4H<#YHURVIHv* z6O%$zzzyyPKsz^I9y>#m=Do$uc$^D&o|%RMMOa8oJ_-<|8I|_rGU8!^eUXzbSl;uC z#|-XYZ*NiSOhtN8MowP+Vc(;w&agPu1koL*y7C?={cjU>opy#d76wAx2_8g#kCMc( zvZ9fBAthiyTxfB%E#Xwf(o6Kv?mi%7l&QruK~XUDBJxUgoZwA90)P)INzhC{kZ*nP zZO~C(raEU2JL~(feOUnN{5cD2kt2GUnE>K|TlCC?dqxyg?gs4Jvg%cspg40xr4$kt z7BR+Jd7k@CgUt(g11BI&WHtdo1w#90N)kFU!3B*}sb(s5!Lwg=XHDNhX%?qvCiit@ z^dN!b*jBwS0Nu6An!zTuZ}T|1t8p2A$pLc5rSZnL#METSu1KWWzc$fLHo3O6S&7Or zSIes%Uc;!HiP6KUeApFU{x!z^IA>a%TXLyE&&uG2dKmS_J!jRiJLQ)D&iX)|is?`w z@`zbz=L@gWanEXg#~hWtB(R3#n7}*ug)n+}uzsVr`DGr%c%b8J7KlG!_5CLXCtDqVia(y+8G;^~>E}{#+PqqlGicf3`~;8KKQ1iQL9_D#z}COP z4YBYbILTPA9IK@sK*X6RMbhA{lOe;V%A`?86gg>i#E5coR9t zf56^9wB6ax8cA1}#>7C8*d+y+=lxg_wVO(0SX7zkJg=r)xgHG@0-On6f0*tOU24MF zt+u^VnkBrP9oo|p!s|=LCw2H#T&~i`G<7WTraT-n6YhjH<*4}Trwt6(y^RdySovDkPTNH;{3)D>UJX5y zO3m#nzSNnEb=*jQ4vjFD>+&63uJvla&D`{rob!||6QskYf~Y)>8K&ZS|+XD&hyakP0tP5uGzE z=567A+h|wl&+PZ`C#wa5c0>HyfR(XF7z5iS1w)fq570_%!ppNJR;l&sVysX}SN|N6 z^%a$!HIqY)?vde7zGciV$eEaDl){ojQKo)d>tU;uw%5R5(UeP8{Fyo<{aA`_>*^O@ zi6wn?=GEj|#qyDn3v8EG1cYh&W@o_kyDeScB2t-)WK90|QO-Pm@GpOHTY@rMy!NK; zl=p*6YKHM$HrVEZPL_)1u&R>0vTq4of`RAI7=gB}!xb}(^_}(2a;_-sLM&h_CKnhC zX^uZ%(k?Il0%PS?r++y$fxor|xif*7{v2fz6`5QPc;zghx3{-6^sTo2Oc=WoFL#;`sH4>>rrQqY|_hZ;iR23k!6Y+yMc&sA8gUCSL!;Re=qm zRjuIc08gPd9?_WBCfU^L(>x5qD}WYuPl#z3za$gv+C3zpnl zbcz-A0tv{RHUa%CM~z2)!B6PV$cy^jGuTIkGwr+9?SE8FNpNOi0_K*aX+wTI1*7zh zrUfP%SCOuB~72Y*0S9G|KJ0L3-)w-mQq(msWU-#x7K zU&*GtkVEGBpeTi( zQ`LZ?YK(o`@k{A9X7zLFyEYX_QDkSSJ@;C68O;Dxg^eC(O9oUlj^HCJ5W*Mr8D(6Q12?mL!Qj~GfxZ-rY$fcnB z5*Ov$r{8slQ=;lY3^Oph)Ja2q+|vwRyNUI`qK+4-;rNJ9v%3bpzjB{9d&)=mACEr- z>FyEdaz6{jd~Z!v&-ehS;xT8n5D)4qy?U$rbc8n|xldVS@ArzW0r$-4XleXaef+=2 zq<)3`GQO|r+ly(VoV&|0;MFBQB69iwls)(a*cLj1`G?B>9s z3r2Cg)Mo4*W*|$D6be6?6Ji)&k*taU^28`p<=*9d%C;tzMPv0_T4cZdIG`$5O)>27 zcN1tBo*WrXez0%mofr)0SJ_%)Wd&6x2!gi`G#*lkdAuDqCdYw{bDTlnomHSele;Da zBbtTQ0ENz-*W20EW(6yO;2;rtvf9&vCGok&Gb^d1a9K93WtP+J|19f{H9mqPSG30f%! zE2CCS6J9a8f(!#@4%`firh11fGAbVcFgriG9~}vH@k{v!0CXaR2|O?x9mqJ(IeSN% z-djvZc|;KB`=Ohk?S+3ap|niegs~liy3$vG=t5@|XDzPtWTlgOgFO~TX z>&b;AueRh&uB<%mDn1M4v#(C?e||4H1396UA`zX^OtG;=x^lQu?qFH$dqCFDlQl?< zN~vU2JPvNLU+QNadgh4CWuZ8UsnA9NcSf3eVkY`O84-$q-Wlpa?*!Q%QsC2r@F0sr z=n29it_LqBH5utk$}u*G)0&wE=>%E}63*%o;k+(kK7K`R#IaBMn@bMm&(A`p!-|g?(xKIL=>asiW zY2t|Y1nYu3_QnAV{R3NAjm>ixt#-k82u_YBst$I}XA?6I#GM@}FF$jd%KwqNJBlaG z*E5yge*j?ZBWF;HN^eLD!j~t;h!Evy$I0k{u9;CkxF6#>dFsHjJC6BbdKO^~y5D2c zNxbBaU_H(xe5U+&6+^mbVB&AhDmY)7oeVqPA|GL9Yb3GBv&1X2->C;YWdWL-&~0?8ZnvDOcE+H<_SN%)d6 zrQSCT2}ahFhJ)^|UbHR`Aknb5Txn=dbQT*45M0(8BCA)w4WqRdr1QGxu+enqLPlG*8VGUx4V7S&>lddh+mFOS&ptflTRB# z!*H**iaHRUKjd8PO7blU?j2%nj!ISPi1CLU1blsO9EBH@>n{gnxHH25+eyP*t`w_( zQ)MvUG;a>O{Ie7MuUX`i;#266HRmN5trUs63xC=Rakxj)c{5a-bpFoE+?{(hRpGAi z@G`%(lZ(-u>)i}tyIwmWf5fh;tIc>}_`|s*i&OkBW5qxabKR5U>mO+gdol$=hh16R zGfu1bQ0SNWy*)C7;eu27N}IaiqAgMrYzOQxVE1s7R#;qiv(Ra{a(lf&M4tv0VPjc9 zr;+I#Ez!#&(?mw}Ta~=b#(xs>So?qyt(00f{z1f!x-G=EUJ_+hX_LiE*CIQA(soaZ z55TCDgst8X1X}0y@7H zc_H6bfOHpKC+Qz9ryLRLxa&qniR&W@Q@*1@^U=WM^yo!QRt%FS77g1|flnvL(>1R_ zS^H%CaRE=U1L&avt85!$=gPq#%<(bdjyONtL6}&+=?3(rt2?3^{1iV9=|tJC9LW|6 zhC)WiLU&$=c~|`VGKZR3X85_<+qbe(jI$O4aS+brMpM)87(QG9&o{0ipg!Q9lL;T5 zxRA8b8rPU?Wp~}yK$fZ=Y-(z6$k)Mv&iw+dQXA`izi!}EdHk?gx3UI-jYCTtZ}}vU zm$w517k>Urp5{8joO&zARu#)n+lES^5lPnk0FZILDpBp7tyQuB)_N-)h-U((kQSC- zKW{QQ?Klq){8@%I&kg;oXaJomD|^L55l#Y^3Ht=R(ZWTACj@MQct6CyfFZFLrGJ*@ zSm?QxBcr5l`g7kunSKYAVTn^9thJ@Xf}Q8eEMB}axJPN_E+5I3DOnZ3(PH3FM!$Ih zqkvV8l;CF*OK4{~OsOona8oHd)5H?yt&DFozHRV+@kK**w=gFbynPhFRFT9uiLH%M zCr!pIZAO2*XMIWYKIu)rDlt2ZRX8QBp>hto$U-b?^uQcu>ToknhX0iBC-7^0>Rb4= zUqyUnz_(MvgbPJTE}w)+KL=T-NFbTgR;q1VfqXbsKz-bp$F*#)@W7pL?sE-l#E+Q0 z3_4OeGshnZ-2Id&5BD``PXad-XSxmGX`T4bwmek*q_r&9=eaVWwor{1!c^*E^MYzM zCOR%?;uW)p+ecJB<+HjEfY0onN_htU0`b)Ea~ zhB<>vKxUo+R~G%id%O8l@r5Zl*eaTg-#ct;1U)t^gxVLjY3sh~cdoSrgh_B}%Q?)} zZ%E2LL2vGOC2hlr_W&_kewSI^zLHiP!{!q(FJHsK-Hi|)70SuWipSdx2~n# zDes5VROEpN9>=z?3mxjG+B?becS}~V$~z~3x&D`gu)6W z56z3TLbzA~)NRuFIbG!DKf(54#5ua9%Vq&}e4dRdXQvYG8NzWFnnnT*rR=;b*ImaLvw_cG-1fjk3Ppd>TsE_LB7|JKf zq+(HgEAt^(Y5vc8Q6}BMLdTr!s^xjkpR|K}wQcs$L`;elS4i&YGS_xb`rDRHcSr ze6}L(a1ax4s{|nMT}VC^+;9mn$*X953K(T5@n0*00@OHE_`uT4pnrZgm=Lp9jjI0z zm_TR0pZr>rOqWrzTLTHYRX#gIzTbyFztWcAoece-?H5@H+oB%+rlULyqa9OFGfJe{ zz(I4_kMREhom&HyKnT351^^wXqYG+m`X5Mh$2G`{{enC@t~QbO*b?0?mf|KKW|MIy z266djndqE3WpSuQ#NQ9OhIy9fNtEG~5r*)|?Y?nBZ0-tiZGqgZa<4G#2Y=G7%YFd4 z({-CUv`G>zH^nnL1BYCkkUzt{4B(R6Q+y%&dxv<|!%n&r3kfdr z$ts>vgUm{k)2I4pdWZ2guO_K?eX6_jNpR)4af2RvW9$8EwROEYFSM(>bW~YniIrH6 zgn}|_k~o{;_M@jGtKJSpk@+`Bo)6yA!s1XQ{5@yNKCnQbS^(JXYmn9kLYT`BV$wFA3Q2w+xP1B9~RW z#Fs7zBoD&AU;+A*R#o)zTiQ)D?5i3sSe=F`{{VVCyuJO}p5KF$xN}Ikzu?|Fc2gzH zXU8)?QbTX`s=CTDw-(5_FC&6U8*+}d&>Rn~+d;?rmkp;YSZeJlELW%_Y*#;V#jVbX z#kz)-H$;*jlR1*es80}b02RKR)acTt$(X(_XkwClIKvklt?9$t7qlF{{VgJ zK_nxYmS~4E95T02=~cAGM!AOOCIO?A4qWbYvmpNfXY#38TpR+x`q#GM1>9e3RhHi;o0xRl zwQ>-fD$DyhW|~`wSV#+;=dCBF-J%Ayy2=7}EwH24(W+eDMHfzHsSIGO_D7dh0PJ2m&v2^9;+w!It*3K6s z5i0%`*pca6{1dBQMr|Vyaj>MhiLYc=Q_57S@-$C}czagjOVMefSX^IE)0QPT9;Eai zT2MfOM*h__(vD$IP%6pcuk7W2A|$+1tJ`VF!~2+icKWgTN7AdSI7PL@*6RH042>9L z)qo^smp=i)s|&=RD5m#&W}Zj)ew5PlsimRv@BqIAHbo^2qwO$B-Tp@YpUBg@wa97` z*#W@nK4J9Uh+o+tPzdWub2Yr8L?cZ)9BrI3ahnT6ZiGMDas7Ewy-lTsL^mzE2Lyudq0k3VB z_o@c&pXNW6Dh=YDFARMD0Iv)CML}RmbArQcY}lvjI{|^v3{y=mCU%g4(MhL@a&zle zXp8m_@UE+Q!~Q8+`^sRhm%hy%(1luOc8e zR~=~1opJL6E-GC*_6z6Z0vaDbnsUxP@8SPXB*)1bR85uz%nNC6W z?_DYI*M+V1e}r$O>Jv`_Uy$ZVn1Z-f1JI22st1oadAMJRZ*+y9?Lytu33&qNm}G1T z$6q>DH}Yt7;QHAfmL^sJ9ItvQr9`pG&IWPwW7n{z9Iqp@OSfzTMl|Hju#=-mc~p5- z5L8asLdG)A(@D7}0RI45ZFh#bkdd}AL|w!&6O3SE29Q{Jvd@lY-)c61I)6$wz+V$JZ9dNC*6UfAJP~tSMROOA9N7FB z$SQq7$E8m3PCudO*tp%u>YXa$&h9a6W`&3xuNiIe<&P?+zA}6rj3nB}3B`xOd92WE zeA++iKPn-q>w2}8lW(c)YW}-C1lyR9XYUf`qsuuPSAOA zq_%ffpM7nA1a}s*B(XjjWJ9wK)IW{1W!EiXSeT^oI+bD60(biN70X`=z9-&rt?Jue z2D#H)Jn(=41G!%!JiGq@KAbwuuAyrU#*uj(sd*nXWD)+s^r{q{Y>mU^pth%^L3gCB zt<>zXC|#xL!X$+&v+P(%@@hQkb#5rC)EcNFsDN4c{w zEb>IcLJ-N#g$KFbrFZx6SZU_vj$;EV6z+Yh5yx7fy#12a%^*R|Bck*_FGKA|8*JC2 zH^kP-s#;uG$tGbWZoY?OSxva2S!{TH?=77PZ~`zn#zEe)skkjOE+c*&x0*Ys0JHq6#?!29;DHU4fuQ_8bra)DD>(IoByvc%QiUY~ ze23IFe@ZyZwCKjarlc{KRE((t-8ugN!~q$mw)fM*>`}^dbr{(FE8SY(!I@opINRU7 zJQ`BGaUNrge8BBS(x4s4t@v{A-0^k%vJuYw*gT~}!PF?>15Nzl2+N18xB)qA+F#r!U+P9iuMBX2^l;&=Df*+VjId}5ULsfhn zX~eptEwz{iFnPHliVhU(JIJZM{$K;_BkeO9CzZysuz29CCN z_l&C=;e2TKT=l{Jo6%;1lvGxavh}}A$SH% zP}%%No$n;G)>SndSsU&)In}h+f4By$<5D= z@&55hn^2CAD-1Y%JZlUi-cQT?e+NOnk$b1z4QGZgUhN}1(%UKhJ2<_%h33ce=W>Dqic zPPWX7hn6XKAP*y19FF?W$w&Q1>Fb)8D}t@BDSilt6Z|{9;T;m)Ze)&ji)VO&<-zyf zt9?gGTT5%nq0cOsV!lLmuE65MXT%&eEVgq;aR?(V8w32Sp7^gyjtiNhWhN%Zz~l9* zUOvju??>e?P~&@9m-QiZ%3k5jarl|}!RB9Zb5m{_y1Kr!X1Y{IM!;m~!kS+2wY--^ zt;3{w-3aFVjT+NZD=5||M=CDCahk{;H27KYP0C(BxI`SU-TA9F@4uyQ&6VaP4EC=M z`J!G(W(L&s=;Z~BOCatD$rL;6k*Z=G$B*GZ%v6};JB-r{t59tVsKj}i;+UHmUC)1X#jfuqosW5CWB4sSk8nGY2Q| zlE0M`E6gYck0&kUtNtpHDEUPL4hUm$9@J}uwa2lT!8TeJ`B-_19V%r_4wVWvLBY*q zijoQv==&RSUYq+HS@GdeUtedG2DH+jzHwG%u1stM1gb5Gk%C}II0 zotK@9t_S_N+}E<&yI=)K#6T%1glE*`^{wn8gZ}^yxPytbZE7nn9gwWIj2GwpGs+QV?LvKCEfkZvRz0^Nh=)W_v=8fuo>)rP6QNs7+X; zcgStnmH;1G9V;VDkttASaEg6N#YWm^jrn3`D$TGNC+pA}m3%JIXX0)?)2-)1ZQ*|& zT#SH)Y*s$oPYq{l8x3mmC)_n1KPa@TGfBsF;!7GF^1A`o1aCtgP|KFid$%`gbEHINe;L8R-F<~~X=o)D_I0lV zT3bWI78aKA6k9lCrX7d zY>v*}X;aXyKc@cTptS^h&u=gvBYf(_dxjXrd9rnOdQLW#5l`(E z!ZGMPcRbLiC7!6J;V?E?3HgWTzt*c=ChAD!@Fx4qkPb7IHP!zB+FwNdtH4ld(57Xu zm0XZF!RkP!rl_AC_yu#K$s}7N2IVMz;||1mA6}ld?2t;JGKL6F zK__)S{pro!pqnyAd1S^3^Y^B@eA8LVVUc;Gf0dEX%6y2&Po-sk0{f@n>YwcY0P!X+ zDboJ{^v@BLI*bwcahAs|%s^w8AH)adD!=&G@ZESfQ*CQbj!85NhQUa-FiLtU{{R8) z`Bh)1UL7*}+g8(MlG@_lK*fgqtPa`q_u9K7ggA>y_>I88$=3;`XoDNRlqegjfc zR#p6a!Fsl{YiX%lS{1pL5Z7>ciULSK7UzFDjqsK9P+l#bp)c8^1Cm*#I8-Cw{hH|0 z2oRoDI3oi-)lU3f;K-oUhNGvU3C)@I+ne~kk9wmPPNF+BJutGb)LSZnw!3g#Lm+k?Ph6U}xRZ-)(?f#p*^4~O&WOVY+NhUot7oY`bh_TjBx;hoFhR<@ z^c5^$&=H$Ro_s;$DY%D6(cyA3iJ5WuoE!sC29PM*cIjC(ryRLEQ|=hj#;vSd+Q}kC z8@658<8LAF{OclZ#1oJ4`SkmM?lQ`6~I&j|2Nfu{zz)u8>N=({YL zR4xAiNbT=Zdrc#a+P^&K*C z7MJ#GX;+mGHY5Y;YkMT_hGUXXOThDswL4pOP|hF2Zg&WBe=*Z~gzGw`?xG>_txdg- zODD^_kPma#r5q_|YiTTI>cakBL^(kak;%_cqpc6)+xu(V+i0}-FI7-B7I+F1oOB+2 zXk6tdq4mo*S6X7imJHBhX*u%sQBSshv{v+T0=gN$0+&`x+gp(kS(o_Vi z1^_YgIqO4g^$k>~*{m%RC65SlyzB?^A6hr3XrgBm>gDIU&fX(sSN_qkrA;YngmHRC z6hkyS^s&5IB!EhCFas4J`GeegQ7wJEO?9VRl#odh$v8#j0G^67`qR!ou!`EsJG*Oj z4DJ+_>%UFByZtICH3;nOuFSIY+^S)Dw=C`4`w!088PWt-VY}>e3SO2)_?5R@L3-TIFa~!gf;CWSmzTf z_^7T3Y_=4P9-HEo;~3*28>tBy7{)u%n=Ma9;;sma`-!|gI{NZ&5A6`HGFNa-5cq?` za>Kz*a|UjsiDjw*LT?Rfb;FHi|fWj9h%l$vC+>e~-qQMqS@W9IOgC$E6`} ztj7zM5HlPRy(Or+q@YN-RvE|}kELWfO!sk_tUMXO+^AuZ^rS;PX3uk($BR#+vC3;+ zJe$PB1Ja!~qESOM5)NUJxZZ}tEVg+UHms#jblB9|Ypp)&4IU@8NiFSk{7A#)CChUi z{DwfHmQ{^e@*K3GF9cBQE85+&>f(``Sdg#D3WMt=X?ZMQnn!rp;F55sZ>4AK$b0kW z-k$;~MIa63^zxDt)?QCvrCCzvm7dZyVKu?7Hh@4R}P1$ zPaUG%t8z)<fRq+qs+^yW<(EO}EUR~8iNAHM~{g%;;ms1=NqilJa-s0d{ z+Q_k!%P#4U)KPvFvxiQ%`)$z%>TkLU-A9+bY5}UztU7Aw_C_J{T|OD+JW5c!~sm6eDq#-Mw)` z^&2!{%3Gfu)KO+KTu!#|f>`W8t!_sw%M1rA8092>ChlvDU{v9|xqJt-LvSaQLkccA zxz4~G?NV=s*LuE}#5X!jH&R&Kzcf<3X&cGRr*+E?#2P1}u({Ip4K{TR_J~U+dq|@z z`SkkG4iS<~Gl(?%U=>ojyP4e1|X4RvzT&wnWSq?yaVwom7Q zw)IQ=c!mD}^%c9fH!Hw7SdEX&)pc=C6KQ-gY+m+dmhFe`?P6eEy-)CtyPfy0c;jty z?}@MEyu2z8hD1>(-HZdA57hl@IM98qmU8kZ0xYqGQZh*IUOHt}26D&njp=nKkTBR0 zy(wofwvefhnpXRycl4{7emx0;MgIf^SZA*FD32sb|c zC|q`PTqrj?u5u$A53O%2xSe2(l|#INcE}yQsd9v68nMun;VWn*Hx^yP#^ z(z_#tQW$tX1+iZYeUKQC`2^eb0;1&Oq?MLn$lbaO>91+V{{RizC|zDV>o$b{0D0D(LZ*22hOuVwf}GTUEc)jt)gqCqPLP!4Z=us;LXrCvD>ED zAk;78E}S$^iQ42Tfei8snDBG7gP-!rB8h&Q60S1-NNk*_jQPeJ1ZN$3QybZiH;6Q2 z^B-Dv%j4PIsQcWU!|A;-fSIFL8%fKC9&~U=O|J)*w@LPp$POf4S4KU5&ZgfC^++_` zb~_DG&+Mz$5f@j%hEKxT=sdkeS2D!FvvQE2;NzgBZ0`(id{S94f-|}DqLe!-72oK- z{xtA5t#6?wszd6QcANO*w>m}KFdYc<#wwP#NMuxK+@pC(xFew4S6KWX;yZpQ;AFGZ z9cPYM&6NDdcH01-ak2HTSJiaJ(RGXcGFH3OZH+l+IoxcQ&U*Sm) z2-$1)YQJM6!?+B?_fi9leS1;QfP7abiLc3JaU%;Wfy`8$l#j$etw=ry8*OWcxR-{t zG0$%-LU0JqG6={AxF8?=)qgINCkb)f7V?nd8HPyMO%rX-zeAi>CD}N!uAn`h~P-e-#X|-|jBX+B(5&_~YO^c4+#hKDxLG>o_fixJ8Pb61BBaDJ7i@Lb=v)+D==mS>%aQyJe1 z8`HS+HBso7sit2?c3@fFAgyb`ysez!&LfZ49RU8hqE+;Q zQBqnAMZ}jnMahd#zBkru)5k(TE{FA`H7$2g)MQ1}F66VdZSfRj0zXXtW~KUH2H0tw zvR#pRasVegD(A=#>rzN9VY`p_@T0^wRb>o6D(;MQV%ZANpwO)qCbqeSoROJlC!0Q; z+X|e_jd5$rkCtJOM{z#}qLK~7{Xqi>HL{HQbdsf^-rRy9~uG?N-3s~(TaC|h$+ow~%^sVjq9vGTQ zVAStYNde0Y4E~fKT;UB$-4*of+slHdF0U>d=}BxQP4M}f?OJt8McKXz=`$*RYpDv+!4akmAWil}* zloOD1zi;V4v?vENJ8TKu*2VTA<>X75gQ_8NqIxMtP zKf=8}VY*vgIzIi*KhCAR6~}YwKMpyQmU$q#5EPTADc^6UQ5+q{S81nTXm_$9u(@TB zyLF9}^&W@6(xo={9vz?AqjBIn2IS9Eji}_)ib(nhX2)Qztva>d4U*>M_hWE8O2-?!#cLBWpTsPy@K3Kzi6|SGKw>~LUtco zJ;ppmWp$}Z_E#xkqrxJ!Wo+~qC(C?vsdMT|DDZP~GWM*WMRz5I&8g;voG9`+AC)N{ zqi}-~s>la$aDOT*cy%p5N3hhjcoB{CZ9GxHaODB&RBcvo!;TfOhfhu-*6jvlP}cCy zm?3)eFgsQL`cb#!-+DO~ieFvT@AS(QoN1RRlWiT$u(Cy;LO=$fcb8LMPSV`UWsvt{ z)6jW+E4B32^jf z4>SYYHKhBKUTMx6*>Q{k*1enSS|{jZarX^JH8#d-M{+(!sJ5)wNj<30se-MKF)lvv zZhxnL(={~H96U-v>N8O7FQ^@M$1lA}v^NTm7I#B|>bikb<^Tk+;FhpCenvaN`6qV#gcx%^@i3z9|)y$1*X_=YM}X z=BU)|5-l>_QboDDW<0$InWvLneZJs9CCqlJPQ;DAxS(=h;Dzy`E_T9(e0m(;NZ5TANC-p0iRNk%Rw%UnhnieY2 zjB=^;!T$h0w9BVnl-T19D%rG>Jg#J!+2n26nX*YePJL-GK%N};BoXL;@m`hy9&Lx6 zCV84RbQpZ)N0uq+CE(dxLwKU)x0)P$@RA3prj|2J1qEh8lI&lbxH!S{pvdh|oPQT#>wS6#jz*g+ARRx8+L5uiFD%zH^Ex(IXPMIbz?q+=i+huWbw@AiAB|`qV>>b&2&^G{n>t zo7+oYvzd?l=))dHC%a(a`QtTYd~UMQ+d$DZeKJKe%ln_*?i~Qm82PTl+N(=Z`+G;4 z(0tmBl9^y&cacZlPke9bOU3$hGe6CYG$0=7V{VQLpREN8C8gx>{{YN|%AZ^sF~j4< zy^R3@nYOLC`poJ4XLd1#aFYIFo}b8;QM`SDjJZB6eLtA*L*%n9B&!JBcMIH#du05t zBq#3mU+YT842JnUINisFOY)9@b#u6tKuR*qX~Zc_vkx2(Ee$;_3Zs6b|jG zEN_F_iL>K45edcRthU^%xg_9^uE+JF-x+O0o(ztU4d$CN+e#R3%6C#dI?^8n;d?GD z8mP5N(#Q~@_5q)5zMsye{{S2<2C<@B>rpbT%F3|aAUNg&C0o>X`cbIUu$z4-fbj1T zOQvy-pRC4DjT)ewXK7QT8tN_}(jel_8M?Gq%r{W@v7F}wjE~m1@>DTjBwvYQR>!|l zU1RX#{%81qr%Z&2Rt`>LI|E&o6x7hHQgXNz)|GcIyYQD&(k}jM%_WEc^#M=%8jbL8 z6@8aaeIHPd$AOPEo00QDCPBa_qMuHcCD5(kNBD=RSx)hYHDMx!3<(_Df=6xhP+fCC zxX^5^HA%xONj#CqACiuZ^}+V~)o_ebrXjg@&|l++5dEceT{8g9Z5vB3t2O}r7e89c zsknz!xzx1@t}a-+I)nuJ3|3ZkNHnj>(ssizgXfd_(5+%lYk;Goj8W@&{zU_@#YA}5 zQi8%3TX*NXe2+vQ=TuppdcBa&D%H$$O9Ur#^0D&tsFsOwrl!9GYQQz7{MlTL_Qk*o=TonTdIDX~9p&Pdg%9r2_}k3TMm?BpH}Ly`1?c;Jvmfq3%y2US&+2_W zD$KC6wzVx4jl5RqPU{*4&*ezk&EPS}18e{~Q5^vIm!~}yb4J%iqK-Tp(*^60O>1^! zQb&k@9M-xdxJitRPcAS!0aHCn&MWI<6q_;KTgsu|U}$ES#cvCf&%I=3q>3kr!P%G6 zLnQHomW;3AKD$=UBikyZFl^m2X&ZT=`%v*03+8<3d%Mn8Xw^e)=hC*pu%?GAG;=J< zJWxX5^u<4A1U7ma38kxBxGdb^hV*jXlHw+KpCdTWttNhK)j+HLKHlj$ZeWgB$>__P zir?^cgqHwXJhqHR+@ukjx8t;d?G_e~Dn?lP`P5@s(k8T;8;Jh^c?z~09Y8)~xTUEl z>xvt(6uCYN)h%{8U$J`Cu@vK(|hF^@{Lb+Eup6a#3@>cA*?WB!6nU zjt6Fp&PXgUa0Of65A;}n^xSey405&07sDtdsMu9)@kdQfGm9=EiY108Rh1P+1_nX zwod2PpYcQ@&s@5<<^AGFL2JB|~Lr=+P2bnH6&M(LNmR66fT2F6rZ5d34B)J$T zZNKgEuMNU1r3;Q=dK!c9owLOhw{Bb(!lpVLb8|40#Hau3Grg_rBrrXFP!Q5wK!}mhti|jQWLhdMp5Flmn zQZeKS89DkRM(`JI;1Bk?+djrz9Bof;^{M>otU(KT8)TXYe?2_4($MO%y2w14&DA@ew8lJxO++9dwFJt`b|dp z$!Pp`R&wpv7~E&{t@QcILYi&;z`E5hZq`{!bVcS2LGl1EF8-c%Jmi!3hlS6jNaXG_ z;n_HIS(eb2mIf!meqGpS7$dP5#W>MzQo$N~wm~$XC{F4<{OZ>DiNl(XtEg)F#q8E_ zY1X&zZD^7V842B+Jr3fbSDFRRoUqAxr^_15yy+vyvkx$8+!J4KWbwrtZ37!sh-{nv zDGBeqXkq7LC z;ZJcE{{SS1A6@9Qn~L-1szMXh3@)~e)JIs!4gkqJRJ!x~vr!#Ug2))1g93j#)Fxo< zIk_Kxs&IalBDFph%u;?CK1TQLQTb(z>Qfjq;W6eJ6n@+H_N7;58>#Xmr}%B9&O^6*2N+Bxz z)P#wYBAG(04IJ+q;IA_;dXV4i&2yn?79!n4StF}4J$aasLH^1N@&ZT8g~e(^Ld9RP z*w9c!n@qcx_ML_6TPT7DR&NSSoxI1LTAvTN$3nB=?+W_(!FFYqSrSBJmS)bxbu?e$ zPr`jOi1-!nwKFxoqjcQX)2m>_qo!1BL8`xsIA>GgONjx{V#ts+vkAuG}mjB?Dm z+c{IdYj(k9C$4ZR!L|4)$5&6zbhzT^b0xwI{Q=H?l@{Wz7u7gZRr?mNZt=2X=jCow zp1_@`6w`E#aFkWCrRj!EFiP?PaFT=wda@9IkpuIor@*^bo8lgq$(bL23D57dgU zWddRpk`;1!y=cz}@dl&ATC{qGlQ36N%ECdFku$oHj)w!*vTIER2`X-@v%JCUs$gjx*Ir*sj)l2Y3o`-s^zl#)dMm}ZSdw2e{*%`TO7 zCAZom<&ds7Dt696^YW?R!)xo${Xr$+X|AUcypF`>*Z@usko2Q*lu%17W$+=I^|Hms zSI|az)-q$ybBesUCjR!v;Y2qU&I3m?M#aW{Qfi3OZl=598@s#@7GmsqhH;bnc~?mA zm6BQfB)I!t7Bq~?#fRM;PH3m7q{U->q}nRJA(f9FCB>wmO2RpdC*i>Pzm;$Czg0%E z(xO>1{{S9^Cp?w2yog+duY>^prbwBpS{wF~K-w=${aQ&vtf>X;F@ z$&qQCyqli&m4j(UdS?l(on`Bz*GrnkK!x^LZag0!lqzVs8T!h68EbSip{wsLFCC>hXyI#6!K2z>r(q6$mEWr7&OR7sJ5nVgGmzlnl+>E?FAm_U{niAE84j2(TsV-$A`Gm9 zud(!}DL1x5l09^SI(nHoRPx0nw;-1GS zky$_){3FtaTLM3lOQzf<-HbEE&C1K2*9Yn;!yu7JZNck7bSuCZ+Q@lMa=yNlZ#$mf z(x+>yE`+;8hdYR`q=EiYjevZ`MgAv3_Z%;K;YK8mB=HCxQI~#i%8KzGqJv)5EtMEc z1VQ=#01oO8=Sf+SsA%|qnQkE{eR2pi_>oV`M1O&<0kyHVAag@(y$4Wt7_ELH@Qi## zWV6IMZy-Xde~EhF`%^e=Zgfp*(XFi>I70GC$a#>jnDRcAJ4Z)S$iSyu{{W?M30iSE zqv7?FfB1u?+1xG}ZiZC(jO=Ph@n?o4gNdM?J?*ZC-yKx1Z_5IUaUGxRUyAT*R`8xj zh} z5Rb|jWOY7W@$X7WAciuLj5}?f^o(&dqm>8E)aP<&8TA<_*)P~WAze1g)@d0?xK9uP z)C`eLpHWgsMF-a%D{*Mo5ykeIH;FkFai0CVR^PKN)w9ndliiyb`U(O!6ozkh-Q1kk z*4Gz9oLfB6^Ncr!#d1A-=!8~~M~pyn z+LbIZkhaNZ9`Qz(`xeiF^lNEuV5EK#DY zGZ4d(K2TRXhR<(9P$yJn#ELMzGthd9Mre%pX*|naoM3un{&c6s`6(yh zj#%Go8!e}b-XzRRozJCgZII*vk>^gNAR#2<`A|#!SQ5}!W=7~(YzMik)bwQPD`Pvg zOI>RSawLo&s5qzK<#SQ{&Uoj7X&;%n%A9PtKd;o$+hffT^c5`KvL4C34DWxtYKZFN zIUb|=)W-09tx*kMX#w&gvLdDmzC#qMrEx-X~d_k zG;`L80LIdew1FPqT5$A<>r7q*wlq#y%PhG`82#hi(G3eoI_D7S+Fv+Ex}9QXBRCz; z};c|ECE)w?Rsk+(>ZSzj#a%H#<>cINh@7SZ@| znH&s}ovI*tm9p3%9hpW5`cWgT+#6pFf*r8Z5x=I{t6?hg1SXe~O{Ci~4I};LIX?dY z@A*-I8x;zpncL-121)$4s8*Y*>SvI^&2u9H!Vw=fN3a>LhyKr3T0XmBE^QJ$ZqR{o z;%-Pi9ejq^!0(#bayl&_(~Ox4;eUaehY;#Q`(2dSSUwMcqxbGSj&@P{`d2}4hXd$* zDQDnl_7K~G2RxYOk^NbY=A_Z0Lh{?c46`*(vL z{?Kz?Y3Ic%I=XisPPJxSU-jjoSNBM^(!Jb~qyT*FBXX`k#Cl`if)1UbzTKy13kalm zh=w+Fi8PKNJH;Hzky+_M{*)Mh>VCVGy(gC?rWSwQ() zsqg1j!O5+WWP*o>VJ$;apHQ=~vW-M`_Moba=b4!0nEUPY0;c?VZ+9mYT4}O#$t*Uu z@Is{I08n&3M3QssRn5B*%^p5(Vh7fzT6Y%C+(V{nTE((l8wgh05gt<@T=J9TcgNDQ zQQnP&m29~9CxLDBdq`Q3J;?c*M(T6d>E%N{JX?tiC$)o8o_qA?ioeK7}S+GBfn|`rP*Fy%_LT+T%az*kQGKZWBz?AO~<@Iy7Z88 zTlh&3##rQ%Y9$rz#8$G~B&@JVL3JN5KfXHq9jU44JzmDr03;wVAT}~O8p=(!V~&}u zuCPn%Q5YCgQQP6UUfpU%sUN~S^`LV^NGy7Etg@Vl1927sC#Px_wvBgr6bLe1vFs?_ z=mVg|KH%Lv$$Kr+jiVf@eQ18gBo*)$2x5jc!X_0*r9IPseS9!>4MeVV=%TSQlg#pL zgFOv4()8P#ZRAi(9ON2v+6xqukt?)Nn8qpeZ&|JJQ-({jNyK$1gYp8WkN|I&-H&?oj-h4c|1$5JLGKF;bhI zIw=FRYD1ow=~271Dur8S6j5pT5t7!}v~i`-3i%w{0y>IfEhM*__m0_C>Uvf~da%S4 zZ$5t^=Sp8|mQhL)%FwWekTs@+j7osk*5bZdm}>_rUBZ9i^SU z;xxKV>;N6aC9D450I!DeS9V8j+zpr{Ddg=scVU_@Tnr$VDeYI||d_aaV>`rS={m9hZKdI|C zZFPTj3@%5@5K||HzWEg$)+}e!ZeA<77a?*A{nlSR{{WR*cH=z9JJdtsT;2_wN|+5P z<>trT1AO{dUXMc`s81Kwq7M()=5Aqg8|ScZ^QZA5Cef%->E5Bb)stOW`1a}qis~mB z+i|lWEcg0W+771raY(NjzRbs$Bj04p88NI%1qi z-!p(zu6Cg+l25^@85Gj&xr+)3i#w6r(&k2TQZ^_%xAd)Jj3~eu&0_=k8rs^E`_}^< z0-AfU>t3@F7(@7Joz23gMsePNOod)TPoSn(+KhIKgO+yts5fIwt}kvT1uZ~~caghO zc&+1vGi1Dtxpp~Y{*}#=W#p*oc{RBEP3O&ZCoFl|B%fYO%77}4-Kj#^^{ovB zkV(pJ*vC^`+Ohr;4HK|#Xo2$p(;Ln0r61umu8l7>y88;iFJqh0v8aZ!KKG{eF}fVc zYA>osl0^~*Vn2S}7umnsbr!dju2;&6+udbw+m7P0j7&6T$jIn>`O*?e)`!PGhQ>BODcw)>rA(Om zR~=^WAPPx11HCaaNg>LyMb6uAUKvfqoTF%z?tINF%Y*4$bsJei8c-x~d*z2VY3-a$b06Os+OS_1miZ+_!MiIvvbu4xR^R9jlS7%9T zy0*KKU$`nTsZK@A}m1C$^g{ls(Es2(NHXYZIHJZ|nZeO71v% z-b+T7CNM}3C{co}N2Le2(DfKYpR@R?qdd{DZN0Nqr25#IVw_*(mdAgqcp7XxGCs=$ z)@e6|X&T1N$?{2-05cwC&tJtyej4g+q5N>R5i+cItk6t|K_4=6d7h31SNdh%zBKRI z_Rn~h+{E}QIZ$V=bM4&Gei_r};oVx(REp^h%o&kEj1^p|8#a zAuS_wH&T45apO1Tm&GJZc%S2y(#s?|9+;2-apPT{X2+i>Abw`5E-K=kb6&XT)%7{< zl%JL|+^D|FK40rkb<1zG6D%NesKH<2Us{f`2VO_!#&+}esw0Lm(np<|bM3K{b31RA zCbdvNY=e%Or|A+$_dy5FmX1Dl$7(NallBO3MV+pp#5#OBqA{?NRf<*(%EOyrLG&aV zlzc5ozCe#EUxr z0Mrlp0Lnl$zf@lHMY`ecBfZlv(~{~Bk(l%&u2<0Pb5mc0Y2s>{tOs?L)zpt#8LN+A zvD%kbR5r=T+}H7ax(R)0VfMV5bFLm-Qm74MNd0 zuY>w(kl$(6uY`?}gW<*w0Q%EY(h!w4Bf)xU)U{nAzz$NcY=5w-XQZ8k=TXYm=3AO8S}Kb157&w4Sv;^^+2e(u5&K zEz9c7BN6`q^sbxvps?e46G*0b76Wl;_!;>K_R5-b#TJuEqVVOFoKj0A-Lgr^7|Gjg zd6Sx#d=}8Y)xo;Pry#<>l4PFzvFG~Ki%)`UZXV&Ah-48ob_g=5^PX++Tdp_gF;vQT zDnjvM>_&8c0=d(g&c^6Qw=M*;uU`xvice3aSsYn)Yo&ZYxzX%gTg4m%JfMIFnA^^y z(rXs>Qk8iLorYBx=5{&iX{MT5|=S;S6XOa5F(QDLa2f%N{sJuV+8%L{85% zaV%*20KSyhK(t$~AhLnCNhDru`|nmK74X%rlWHNiy0x9{!H()tz90BddU^TPduw`Z zH34xLUlt;82W_$bv~m2A*7gwN&3@NXyB5|~3u_ItxIDQ1<7e+20oYblQesSu%yLP| zK6RDN*`@VzIgi$c-yCO`&lsW?4i_iOY6*EJN#3}kY!`8sepDGOa0i(+Ink{a!%jrT zFg|AUsP7KjEV_`IKul14$JM)3uHC-S+=K1|lkZ&-XjadjUz%b2wEpgoSgbCfb(0*} zp(KQnQ@I@}mCUybCyTfUaHJYyR)w_Gv`7`iFY{*^=}wwhXNW4dD|XFBR`KK`#cpCd z;+;b}vYZ-Aj?3}R;ySjxHrIw3{{Xve^A6thPfLW`%I_4bBn0GR&Z5&RHR6>Z<9c&x zeIzf;uE9avbrs!pLfqZiXj;y*#u-S@dWdnGwZ5SOM!6FV`tn#*nyA_oi#0zWM3AL<51z-D~U|6Zwd@<)RcC?nx2r+SV})@O41?;KdVg=0 zgT_^1&UuVSwKKP4;{DK6oDfA6kC!2G7kmIIY;shAHoBd_)uyw1c36T3S3RmJ@i#s# zwC^D0RVowt)c*icK)F2?M$CEv>s4PG%^s<#_-QD6bWT<(axQZc*#7`JIYX*FUT>!3!^f$+ar_mYnQyJdXqNUcv`x><&i?=@9k59_ z$9kID#W&fb7cZFtj$$wYKA7$4N^zG8TH0~N+`(do7GTj^Td@kD4y}(qxTQujwtlph zgm7_GJ8r*rVt@t!$EGn`<2B&#OfPj288N|!kar_x{{T7`J0#-;b7PCySi zHzd$07|MC1`B(n{m!IZ))~@8Sc^JE#GOcgFOl&nGV_&r86wxLtvy`LopGkZCJJ zB?&OOVUvTJ)VEqd$yzj($636mDo38whJgP7yXEpEezmK~){xR4mg;5y03Lrj)B}4Y zvW{rYNAKc1#}y%8nJ9J4878$brLrGz3=$W|?%SxQvdNvO{;6y79jYwNhAZS~gtNv& z;(WbvUaX`IyHc@}vo7RrD^i)baHAoHeXFd>(7MPTA{^Gy_?HL+Wn&u_^Y*P46hIng z>Ck!m3Rf>TLCF~CD}qKm%NPj|$nA>W-C3VAlB?u8n!u`q%94_Pp+7pq2Up?%!Quij z(~~)GdfSJ!Tdf~gx70NERJnnI40NG3d{uF$>9(k`!04;X%E7bwgHN<;b8&*8l>?A^p7bkQv0Di* z?DCrxnls#k+PZktj>;To7TWZ#ttBsL^H#caF`jH5E*(BgK>Q1KiUC4b9`0l$IV%vX5a$ zVbYNRCAw3UvPI}xib}_HK&v}30M0Vs#n@7J^X=gw&z(HfXb5Z^kH>NltQ{j!Nn(XYx#SMmoR&mYo~hQaw2;g=(qIAQ&3eb33}%Z$@$1Z>Dw+)GjpJ*sknlcy3~Tban0idG0Db36eGoB9v~~=-*m=vjUhqFzP9v87-5wEN+=_ z>(_R_5;$}ArMxQ-66r~ch!Fn(?jiGEGCKZZkoYlb2C;oR50!1sezjb1-m^A|tlMAP zocL{qL($OnQ}oSUHhN=QXn1*AJd8;+;c@HGpH%R$}D0NkBg=W8b}YIVUgRT%gkaOMBq%jJ!L- z@JTS`zSPf(6pi_R4t|@|8;-S={{YsS_2d$_A|l%1ju+)p3H-^aVB**=F7;hTA_CeY zL1_r;&5UFY*y&Y+@a@K@6!U5_b6ri7%0B9!J-YSpq|+{T$Z@eBN$y}8v7ixs4v91DytbJPz(Qtl~vBG5GlhEWuPBZ)}+ zzPRs1)s0Q{wp09VaGG_kwwGy^Iq@9#W9EI$MQvtBv?-6ydu)J53%G7V`MagL5xq&FkKR+=SJl zpSsbnqtn*?ttJ*nWtgGl{Oc+g?Xb; zd5$?T(9qLicWLNl6~u+noRueFO)E9IS82&I$U2V3m|v2DHyxUvMJvchD9%M{f!^XA z$8xO$$qC&?Bj2^i10pfXL-;!cw_$Y2&$z+CT&5fy<;X)a!1 zysTAJej!9;fb)`|@7|J|Pcy;tmNE^(`PMU_sEljNbr6Z|4k3`^BdVV&-q%rv$Ca-o z<$-#!$=~VgPUL5SUO7j~P71eUQEn@N+fQR|ywQfs?b5oaYm%V+lf$p+%MH}hNepM? zXyqUg1v6%EJn$IX`xk(JvECv?rL3f0+LOh|v3~Wxu&;rfjj> zK0sF{*Xd(1b8_KMFq1(&D@V~|vxVVu(JSG%_;0Kx1t4f2|SN;VJ4U z+9&||ih{?x9sd9-RE8b%>?t3yu>rg(PyM9-03%*WZ^%AqW*_w{RtE6ReIC4Fv&?h# zr2II?UY_)u1m@Z^^;2H0yp8uDl;_D!U@8*uk+u+h+Fwq$mhS7rhhg}euoR`Hl{Ag} z(jiQCIX|ULG%X|dVPIZZ`?sID^P-B`MjkYqxeoNt4$9qDB^d(>f3LZvY_zLwQ;4ls zRe2(gWoXEa@Wc_eezfNLNOagfP&`sGk=BF2w-QR%2v3eabp!qNr%haF^d|)4L}het zZD_$|BL)){jIjjlPp73?FfLJ85J3Tk)d}G*-*F9_k&P37_h1ySlLBw7Dx@;(A`$( zGcrYvW41?OUS40jCix@y2jZdQm;%mnPnYtnVxBaH^TLmA(Z0w=Hva&9b4ls8(lv`Q z8^n2Bc>%Zk_orbwk1_f$l|0dyCG(*lB&&_a$NlXpJDVh1;xlu1THQ zxp`4WTYks3X#W7kJ#R&xD_tXowEIz~T4$c(ILAAlfU6&vjCVVezebY$>HBI*oO>TgAM);0OsC&F{dQa$vx^%!wnv*e%A4VRwOMe1U$It0AuIZ>010d*5~8>Fx+eU1X0Hx$#$=SA^!jl zeqs5Vo9Q|wj+Cw}qUC9Symn&j-sJ9jpH1n{E~sQN%1-`|bge4WOSTsFa779Z$~yYc zt|*q)6db{Pa0_G|@$2bQR{MuL4*vjJt@xTh+BdV@MoB#ve!{Z^J4)Eh%|bO2FuIYl zl38QrWF)rz4MlYgQ&i$fUdAbk+H+=B{653{srI;yH!Y>Sg-ajawm$0l1M5fOiq6A8 zi%zhG1hNp*PuvgT2iLi)WlhoMrz$kyt4mERP9jxN8fB(EPoDn((uv>P#d?BB`G5nI zXTE7&4#ozuZxSVN{{Sf-o>lIl0wbgmqVg`}fz+Or%9EjuH3GKym91Re$qtVnGFscJ zv*-S6e~|6#n#!DB@ZOuLxHqU{mBs|&vCEEw9s1T%C*&yOl$DjF^79V0D&Tt}@jc9o zvmASYP)l}eo0Nt>yzR;bTe@^hXJHMx4V6ZH=;E!D_UaKbs;_JTfGBDm)ub}TmCDS6Ywf^;)he6BK&|zsg zEi1_Jx$HcsZ9f51`w3cdtO|j)8++4s`6OYDfvnS@@aE=e9nL=y%`bl#@Phy{yH|d} zD{9b(haJ~6E^toZdeeyF7BC4WU~#ra^gU&cDU>hGF~DA4)J5iL6vn|wJ$>ttN}4@^ zVM+ec0^yu)F^tj|%`D)Hn{enmrskK6rqsHrE1Dz&PJx!UZ)g=_Dc0EwA=mdO9W>Xs3d1N@)WkAtH-6-3u{oa zT{z!Abu--go$0Qtsl@^`Hq5OrLd*9>Mj5l6$@id^O414|cVbAs7$ZE++q09BX*X?+ zZ0&(fC6z&?w%p=%*)0Qb{QUawbLqo>m8HC2gfkAq{fg8vg(ao&LU5 z`dA{4(p0yM0m?=|>-DbL=)==8sP~$r8q-c;UFrFuIvev_A@cyyP=fQ04;KVI-KfydmBwA`9?+Ms>n}~8ybY(zEH-4 z=aGVe=s(u2ZZEczOw;&xO_n}Kg25Q)xozp#)w1tOi<&BR2UbYIQpoZbaOjvHtr}ts6*H#FGrRI#y8@Sf}7? zqv-E52`&Z`s9!pe-A@gTuR)K(J!y7jh7!bpswyjeJ73(EZ6I6tve*Au59cjRN6%M1O{D3|wf|tI=JZ zf9d5Wn&{FMnpmy{irDv~C$ggjUo z=z4xaqHA(5VtLup%R#;mGL?O?18Oin=e@Yh2l_jD@B$E_r?PX}>MPM0r z$YF;15KTwqepLV+_haiv?VQJ_h9KdToa17Asx?0TDIE?#_N-eIIaFH)>TQcC*Sof9 z-Kt_09r3*|)s7^EM??elqVWu%_NyTsQS%da+Zo?m=aOXIkninNkA{32IJ;BixD2{% zAUy6nj?3N^WK zZ0%yTw25K2i9#YSKv9m=hNrD*np6!f{r$WMzsDfYupMiZul2op^6p>S8n&YF!GP3tG)*sn2jM z>=jPP4)Z5|T6&)&Ow7-zHpE2AW#BbTL<>yW4v9E}UPIFen zH(GIu>%+H&-Bj|8xw(&WPkMW4Wi{V3Mz}>dZq)Nry*3FXzk65bQ{nDsQ7%8x=2UKr8zXIo`^s81j{ZS(C}Qk%U?Pe`37yMZ#KZfhwjQ)5(d ztsJ@V=TB?hLR*JY$!;(Qn;-J4V%JP|iz_1s{{R-_+j?WbdMaCJ=`$xIPR3^#>&?IN z$LCUexr7$~04V^GfGg63DIYyK+`7Zb8+Euz9a=SDz16Xracy+5TW6H`hwz@?T2e9M zF&W7x8Kre=F9S(;jY~T99(1|2bXSiYqMKluE=2QToEGcWwssE_Coft@PSesWb~C8v zJDh-aq}t*YxIPGB7}zQjGeccKd2d3N?h-@H4*vj5j%4vK#>_Nda|yDTttwk!IS#EY`fZ<1^c!5( ziFUKFZSjf(7Q z1_!5?l_w#Tzuv#}|VH32khn0w~8} z(?8`+hAB_%#M0S7UT|IRnaJ9_i61{iLy~dpTU*;fY@D#51J9{7Vf;>s&GoF@n1Du6 zPm#_@s6hjKbgX##==%RA%|GUZr;<>LiX$)X|6mXJZVpMKZyN0 zQyNA~pPQ8??_Yuut8nekopBucn(2^FAi`SNjCg6jWSrJPA1eCNw`S&R$z;9~ zEz`F%i4~OZ(_`9@y_dkYJK*%sl?5K>9y0dVXJDOf<)weK$Fc*zsibVJc}QchAFVjF zwco^%erDVc;T}}s*-&77*z72f-n4nj%yM@$jF%{hQNL*)CEu-ZSMoaee#F4kWPctZ&nBPdAyDuCe`iE(Om)nJu%F2`hPlwUFu;0 zSX41PWcgFyg?C2RRlAuV6I#fp1F1rGKhyH4IgzOLBIQA^kW-H!Z3l_3^z}>xa>(D{ zZO8lcsLI?k5=&&&pYh(>E5^|^dteEkBOI6?RsDItDyvo;4fZs6C)x-+O}HW4Qs89P zvfURL9Vw#|&{u`IR+z@9inNSXij0sct2a{JhHDwIxj0%u!H|5}3D?xuAd)mJToz-? z8sz8s(23i{cXB@PqWATDB3r_ok(Iw$bkFzrS7#j-YI9o;I0(`&J9x-XkWVK?&w|^*768txP~(L+dKP; z%120^TbnV;n3Fik>F-%w;uLa3B_0(*r~nOs6hBmqNc_s!xQcc|{A zc#!iJY`OdZ?@o;DiD8y0cSDG0@a_=1VFPcyDXwuMMRu9N7D?h9_K2Da0h>S-p@^r z)q#98gV$k2A#a!;Jlao;`;>-G~B6{waE?|;daf#G#kHjb%MzElkL-$t|D!-j=t!0u!fCfK0 zhNm{6I0GwghksgDKFtl}^^4H%-I`!nj4AuHvs*EYxW_N4r4<6ND(n`#lI}4Nhq*bX z!8>+ODZ2Q9uC3&ERp<%EO%I+E1nn6h`ieO#ha8||e9*htxnION!0VqX=(Aji&b=U# zXyNR;nrzagm7~om*bD*uN61n)R|sd8;zq(}BR%~+eX2LC>MwOC&5#%FAnZMTX&EP8 z0gP{K8zl12bu{-6%`Am~6i5&R%y z^{tfD0gNRwv5h9VaF9mML~d>5l=&Hc!_xL&eL&>ulkI~PQhJ5AvD ze{`zg{V4|Kc`!F5;)unkL?a$CEdB6tRpZ2?v?0yNlW^sPdXuxO5V+=PPV9d=Pl;^f z(PoHvtkKFoQbyp4Bf#^+3%#n2Qa~doIjwl^RBM}9hBAst`u_mpx-*x#MPAfBtNSbd zCXy@t66zxqtW|l{g6tSoT)?mdoYlvB5W2LQ*_fh8r3)`nRgSG^XKOiz%4ugQvpZv# z*kiA~6yo25=|Aa=%_(8q`~86gWLJeYH0dH8YDdAkJXdqQ?x4KZkQ@a60OmKBu%PJD z+4TI}(c|KIG7yau@5$>Ue>y&+VL`Ok@h&bU00ntng5#hpcB7H~(Ni_E^EperQ&xJ>lt6)m{?rlOj#<$hz>gZkFT@G3>i@FPWt@E*9Vyv=)YBxnARxF4-4 z{hzt5bZutAzx=)PDE6g(09}UBwQDkeySP~geVKpGg8VAKxVHF(#Cm&MTpLNIc@_CS zRBZP(QdLC$Y`M#d^O)zZ)QcQ@`x?M^rlc+|s)&EYf`RnYkKX?9b9t}JwO4mi39fK{ z>h}JXE%=3cX4ewl5($P7q#lY%$v==47`B7MEV$g9mOV`^qwKvh4m^0-;-g9O?~-;^ zJNpd6V4xW|7_aCV5hS9h5uFiVHfwhB1?l-RRE(+#+#8D(Azz ziJ)RgIbpc38%?&32WzJ#K>3>(81|r0NhO?-T-%be!pkP(?_lHu^!~ItalDXdi{Ia%x4zcS#QsX*!Gt_ZQadIxrmx zJCFD2S$!Ce=0#C}-#Ysp{{XM)Qt=;Oiye+>#*rKSn{oKAz&?m8)UcK^#LQi}c}Fr0 zkDp31!joZD1fpmQD zs*khVD>-hbau@p4dyOu%Yt2$b;mbd>X{x>)Task|022~P{{Y1a)(bABI=?tLQ-VDy zCAXGO2ls9xo%vOYkPn>&nUb8SVqAD>DI}7)I}?I7qPFdrkdEW8ojVpH-p=H*4EUt3 zJFi@SIv;L4Gb}j4Q}U1SoyYYbN~#%c(dP0va>E|qmMJS?qxb&+U-#`u+YmfRk7JSS zYukf@jCR34sKqt8b8m@&*>*nP@A=TmRWmWizZ*s4{hRe@BGfgVGFg!&kR-9AFjCmq z;CHDP#w{K}e`Be|%wmxEZn@~gr{`SHr`$;%r5(g>(a5JN%G{+7q3c~C@b`*O8*u&J zgRDMvI8aFpj6b~#-`~!K#ln8#5S(WYjEzHL@-P4#p43{$LIm?%pOddB{5gDADwKE$4tM6s%|6s6!y0RAVD}BrE>bUEr~NBo0{rB*?CtX ze-jFq*jvYG0!0o2j=AqlAXSY*#yM1U#W{_LAn#65Jo(FG_h9jyfUG)KmgEI2*yZ)6 z65T}`5iF`Pz6qoxzFE8# z;+I2vSn&}V0Ljg1;w&o6$6?yC2FS%Xx*xts_9HyUKkv?#(D=>yL)%iKB@KYh^B;OA zWvInqvKxX#L}wmmfh^;gh<wV zF2|LzpGqjL0P{7VcPIH!z9X4!bg5a68ILOBi%!b|lILN!y;pp1u7x~-fskyg*+2gP zs+T;}6)z+3MpNI>7uGKdF&Pm*wPz(x++uJGZydwbG zk&p^oI26+6U5#o$$>?Exa18{Mmy{?YdVhZ|#)aF1HSBSz>eSB>Vm!JpKZD#oY|y2| z(W@M1aaSDkED?AXfmN})0iIfb{5y~AnnY(GgaPkTvI+t`_a>Fc#PZ7D(EdhGZ789g z$qE>jC(NFvqgRb3{N-Z=ApD2D8N4R#jB0rz9Z#Jl;jBx_gOq=B%YX= z-`=q>Ny++u6=pitEi!>#NTtUGt>x{_)cTCRB+t${B3ut4x$Us}P;Fm8Z4OxGy3O^2 z9#T-4*dNbh@3*B{NkMql_TJw^n%-VhEaR0Ezg*;>A?Hhy(duz|x#cyF$}62hD`vTL zvz|#U2n2JCH~lT`>9qjXtyC|M5@r$dOM!rVzsvHY5h0Wu0wU>>H*9|)No&KCMx3a} zFD`wuE29(WIau!lPv~K!-(7u;teWayvqaeuhQgfpAZ?#od@dk_sFqlivA_h>ec}## z@|~Ci)K{qrM!cwsqqqy&h2g!P6n#sq6l-B_Bq1Pz9D~kz&iUAXt|$={81g$rHl3|pX*z+#R{+FYw*4G>1A|^<{uBNWR}b{xP?H}mtIrQ3AmsaW zrTilk80Au~grjG%8&<5?&J9wQh6$L8q2_D>znwC7@tX_x7r&il#Kz(LB_J<)Ryg@r z1GN<#WN|Aib3Y&hZL`dLvHfUvpj0$S=jG=F(K0ru{-ZZFz#itgBU3e<<<##~ebLcJ zWM2OOS}Ud^65bfXFUr1xnc1(|^yzLGWtd)q-EpT*L6Nv@}c^D<=yb+j!QVxuv6kU*KjD0fjJm^fw;lMU+Y^ysSv$hR=Bwn z$n4WOJj}-=`_lR=Jl9L&yEJy|gi^$XB;&Vz3@4ocf;a|fMk{x9EM#M1x06)@~GDb1X!B1`X{Hw_W z$saUv%-p09+_)d_tx-O$U)kXC5|yTt45LrJ#Q z^yIm=3F7i|!66+~jDh;pZUq{2FKu;hTI??>sU!g3#p_l6gYgGe(Rh1Kp4vsZw~IE? z+sHBxbvYO-ws)znjqwLV;l5RME-eTZLu*5>7>XrltE#LLmi4;QYC% zEyQ9;4jQ(%i;+%x&^iew_9JgA$81coIFqL+13%8RTbDg8XD9qv6y`@#2tBJv0ds-U zg`n?rEd$-MWg(6{j;`51rE2?}pm|c!oQgwRDTvV{@Yj`4h4d8S z-cJl2wxz323=&RFXYwA`gC0*1?X^9R?hN@;XwV_gT3tfh9-ZhX(d`1oqM1G#W^oiwAU1BpHCz4&H>3?x9 zG2$h#NigcyCt#trK~+t~!`;r(%EXd$O|EaHzPM>8Vo5o#QIvG3oEzINc@y}>QXM7& z?O4x&P1;OSPcAcA)E?A@WSe75ZYJ2)vQO5B+|7~JwL}LYt?Y!B#W~>%HoVqi7{~^O zPQ|l>R!_oRBgDBAvh2J2(ByR;1%^GOU0gM5;MztG!58(XS28ujcrctP>U`@`{tddq zyPw5Qtzi+wOMUhm)qHq#$Duj0cavjDVhIitwGEk+6OsXZ2Ja z8}zD6F?M<&_|!t(B?0xqP1C@&lqV@^5s%b5xs|6>2?6_Jn8tn6HiXW2(MI9oVBnR8SpFzDQ{_>%R0lX-%k=$CSsI5A*y_@jyla^gJ4g10 z2oIP8rFfhdqw;{TPmY*b-2VVt9Ujl8a`?PolTFC3qg-vc^2Kd%VvZIwg)xzWt=@|9 zTsl^jas%O{2in=*5zdjNdK`5g!6P`kUQxsbDC1ETfwLwGY;Nf;20Lnp9HX^)oXOPB(h?noT^c1fs2&w=9b{OkMm7gE#SaD&>IDs3OkTcV!ez>WmGedJ2mI)R}n4B`5jy6B7LEI2_>(g$ck8s_+>~@bY zf<>*v_;53Hc?QP=`THL#UPxKI9Q|Kb6Vx>OnRJ()NO>%0V+3<4{{WaeoOT%)2h19Z z={IStD6-U_!PRY_l_ooL0nMi8%a=1=5Ly;8prxOQC&S%Oz^ z_P3z;6JwNy9Z`q2^&cmXakNz&`}q=nC$+t^7L&~n&2bpZXXR!cN}k}18UWvDm~xlE z@K={v#Ov zW~WvS<22DW;zS~$oI`BMJY3GDj4Ir!d9jjlzn`TXR>?VU`b~i2V;l1!D#LI_$KIzr z4X)2E$+NtXqzp3?F*ygw)KdP=7zMbuxfd+)D@%nSM#u1vJbBaY9tVPO#Nt2$De|Yd zS>$2QEOSlxEbH5-Y~V879#tIx+_CZ%t%c-Qw(BfMW7SUOPp_>(HGBC#zPpp2W3unC z^d3Tk+F#vUPGz*7NZ&i2p}ogSSGBDkjD10O{fkEP#UW#ZW_^kB6q;Gu+o$g_BV%$$ zT90YGUf5K;w#pnOq?)@ zmrAH&(Ur<4c76 zL+2hx&b-m=o>i0V(y)~}1vusv?WO+!gsmK@%@93*hdy+*%x|XL$8~8Uv@i23j)%=_ z5ngxl(Y#Y!TgpVTNW>ofMIE%gnpn>#EZ`0I<#GOXmXq3RHs_f@l}F5{sP+EQB

EQn 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 LXOyW@pv?c-zOAKq literal 0 HcmV?d00001 diff --git a/cool-admin-java/src/main/resources/cool/captcha/bgimages/d.jpg b/cool-admin-java/src/main/resources/cool/captcha/bgimages/d.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6057faa352b0671ef894fa622744a05762c28305 GIT binary patch literal 40185 zcmb4pRZtvU(BYx?fckO zr_am1x4X~zZ|%Q50EWDboD2X83JPHS?*RVW1V{qlVd3E6VBz86;1Lku5s@*Fk&%#) zanR6FG4OE+2=H<6@Q6rh$cc!7BzSlf%oIRcItE4tLUI;%7J7CXdItLc0f9n5KtM)B z#zscQrYFK9qW}Mn|M~%#h)~whIxtXF0BB4o7)+@Dh5;l105mkrKeqojVBuik0ni9g zi2t%O7yxJ}7#L_+7&rtNXgC-cI4Ecs04ydP7A1!`Jhqw%l}iW$4rg)^P(rKQJxPFuwKI`qj{z27apN z?qAc$QkcQ0W^B!B~?M6sl_Jvf;x zjYuAD+~(a+zLH_o3?ffz!cTe;a?!0AU0Ez0)fpWmhWZb{x*h1w_{`|yxKK`NV*?yC zcM9dX+1<=t+(y^pec|Z8d64-JfPT&1EzJ8=RKsQ#(X%@mbq5a!4REz(xVa`$KPSp2 zI2B2s<>&q*;PS?vYd}N(NPa*Z2CShGXDCQeQT2VKBdyl8$gb6J(F!E3u9~&JTkY^JiXum?=E< zr#l_pIlj)FvO&|tTK{%CvX(B?xZuE8uM>4+iBNDR0Ut8E8#wRo5vOBQiIDQp9p-g( z!Oq%ZV_%XU_#!v(QJvwa;_oXQM2?VvCeQzsMk=$d+3+g=0EtWnhEHJiI6)L zE|WmX4<4NM7!niw=jkO!RiKJ<@2Ay$?URnD+$oSFA`y^#EmFW};63fNuQu^4Vm0|D zq$}ihwc52p#^~Fk_7uS7%2{RHS*Sa0AkFaPFW@pAi8{sp1pzRLbYlD)}`v zK*g#i+{p$piX846cyTkua+^z@aDdZked%% zxmm^{f02EyEv3Xr-6-)(M*%;Q%q)=Pr%BkeLYb9S&)@$|H?x;-tu2U$$wduK2?nk#6<&>rg2pQXl^{{Vq#5C;_26-7zMK|y@)+~q-gh@SrL4tC{o+I?Yyb`$!RdLdU&;Av zHW<&w%+U;i{F9&JA%CetC0D8@R+ieV4u;ilv6}d7LB=vvNZ=Yue4HYXWvBN-S3|Bi ziS?_%)=@Oxyu%6w(2c74D?e;L!W1rVnHBOD%9*Z$0*1Ewz=p;+AL$r*8EbDoQ)%1l zNjfJNrK&{Z7{cbR&`F|_JYLIt-r$%$P=l&(&g%R1U^3F-HU#(Utgoon)lR7RR5>Nnyt9w_?LXA9I7` z>k($`*!4WbRz(s<=YTU5=Om^np_E7=f&)H;6PxF{B<9NKa6X~mpG0!r+EfDohYH9C z&uYTi58zTOPne<_bdMYVUO{x>b5&aNG&6@x{j4peB;aI?XM>R6ywt$;v2|7x zX8vKFO*lRZ#rmSqUjAd_p|ybrd_pUV+ig0uG$Bi_Wmvt5(j$S43iBF5V|ka2&UIeq z-A(_008vKS+wlqY5sIF$Kif^MS((M5Y!Jy7c5__g?gVpSb*eH>hv&!Ni8 zUWz4mnbS|W-Ldzru|2DV0#M=vQ_ESlc9GlBzd;Spsb6%^24-XCMpy>$p;5RU@a|@Xz{4FmZL;8#gtwM0E zn4?fTS#xuH^FiUyKMM7>r+p{h8YTl3*ej}MqXd$2KJeZQNNCx#ldVxuB;pt9ll3GN z87gCIk0|dTK;2rLW?cO}nQUZK%5k&(E~YGeF>O(Ho)HK9dk@d>Dw`gJ?^j?tLi+2#8>H>+U4$%k^FHZXazhpqVa@&x%wgTqB(Z^Ucbqm8S5bqmNJhkgLBc zmo{N88)nqgf?M|MItm5(Qmx!DP^r%CAE$#gcYR9*{7xMFzdB^U5|dK|k&YiFUDBy876#%0z^gXxeN_GD|8ybdU` z*RW@#e@x^nk%>tv;W*0mHLbzp%?fvRwHD@G{gsTryHG2!X-mdeoV0sYw>=ce-6yqC zx;Pcx&i}SBwX{i4WL(_qu?#U7{IOk!RCW`dZ>L*{s}cL+2(N?%Jc#P#Gi=d-fhu5K z=fTj+ty8kc&RIdGl7^@YEya=9x+@|xosbkV6EY=lR zV(ox$4JPe4Xi=MXNEpu9;J8y$Tv8x1cafHWHOnF8J6Eq$K%H+!pxEK7!Az0m;VE`h zlZx)-sTq83A3rI|m`mVIWNA(DM+3WuF#_WG1GOndeVX3K^zD*{& zSFwMbX5tjjNaWd4adgDQc6?^}kmM6`Wmw|cAjJTAR<5c+G{2-Bk}7khPK^h$At8U8{@8ye9DnzCDzu9LK%ZL2&AUXZBL=*QYkZjht=-y%6Q=ri^-2){< zndDQ7nQOd9ExyWX4kve`;&LsvyQ8ZBEy)Z`7mkZu-;wWy z9#`>jDJ5LJyCIPyC?~|2TTLE=UNp;h+5c2$V^-0a3b%X^%a2@)52LbPiPgEfxX?iI=u`ai&hu(FL-GnD&$4NV*g=`Z%agM8NHZpN;N&WG&& zAu9w@4zUc9cz?-G0&;<-o&NXlzW|t{;^XVKZ31{ek?>P$?w(;e)ow z_@}?RJ^<`?sSzLMnG6w#XqScKz0Z1-JW;-gG- zYz;+m5>4B*fQqtTlqIER)O^@#{M5|Dz~c}#+7(FQO<6reAUTA+wdT%F%URpmvlveT zV&?wqyIais6)<$3DM(O_=W-k`H-jhevnFL!AC?a39?0_ql2n`%ut#B?!36a{(k6kw zwuCHsePkY}nQW#Nv3x+97&E&5PIZZgX|zgpbugifH*2YepoL66%X|#65D*RNsh)>i zK!50@shN({t$ibdg+~d0g8v|WR2ElO@?8=vsHy1HKD;gP$27Vv5`5#EC|F{nt5I50xZ7>keT!M=HcW*rA0v_I@QzsEeAmhgK%PW)2EPzFXF;f=XjN~ih2 zDcEg*psAtD$=!vRI=9rZ=-t(-On;MilBU($yw~Z7vet$1L$tFv#uHa|) zopx4~09wY;)zzD9n?W65cJIs^mM@T+{I~M2Ry$RF=FHUxbu7^gX)|TE9^d%!kA-{> z0(I;`A6KilvW4ea4;kIs8Z*?`c^PqPG9TK^=wg`ckZ0APgV-f2{p|G&AyhacU#Jn} zDz{v>oi68*JGthmhb9oMjU1aL>-dc7R6+jkaZb{XLQ6=?>1#0m#|5Xbz_((d<$S)r z8J**_Ab5L6!zlVF7!va!#zj}p2o>_--JRYww-I?t8ea`{LllQ+sYs5{Ii^I##?RI( zOuWp9{%L$Th}qm?t*8RjVRzb{-b(dDW(9jPG$45z(<2fTN`s_5%tI#R&VVS$ys|O#;_e$L?@O4q%z4)BOTJ z@L0pitTx&aC*vRr)1s4P5kW$ZTDyoH9fz5lEkn34Ro+UnBXuXw;Dw-2Pw1pIgwk_k z8#s+|2k_NQmT_B*We80GCW6zXI2`Fn1vMe$1jPq&wvQ*Vmc`In1eKG<^A;|u9VM1< zE)zu-NAv1;IVAC^((Gzve6^kr>ZZLY|GpRD1n=Ua_VH;D^ff=u=w`e83QlOv!6wEu z=5Y=q0X#fNZKa*Vtd%Dxc+#}hqIjD_a=f($2c7CpT(Ps9O@eRAMemmwWLh3F;#d;9 z4&sToo)24TzS-}*l!AQ?V47Yd7{eh93B?g|MF4KZMLy+waHi|RFae9vhXt(eD>Fpo zHgj%AzlO?1JzZ8USBY+9ZlpjG7eLY=njbyyQ=cG2616)gUm>5*dHDxgafuC|yr45_u>k33d=1s8#quGnj? zo;qEFd{;kcL61MGPQVz#gLpGKyKWL=PXeKWnT|Bk#)EKyG}k1x5VZk*1JjhhTkTmI zF%TuC+CzOrf7QXk}%+2G(peGmLU{_s-5O&fUto3e*gi$ z<o#ki;GB(l%Scn@(hQmOmKl?n>BN|2V&N^rsKR(^DbT2SUL|?NV_?y6unDpjt zfR0pz3}oQ`meXca@c5EiJB(SayklDUn?;vZ9$)ASq@^IwuWW!>qjVNe(-p?|puTZax2d_5 z1Mdh+6^pSquyl(Ie))V>etx+0>U`o;k7INnjBDYgYKgTckB_i4w<(EvqPSpIIB`(k zhrEc{W9~9uiAs}+((sY>&EGT;?j%*ywl0~3?z_`(Jwbfr4%O=MS6dS&igQ9yO1-Or z0a(nnEIz6}?%$&o^D8(@{4)7>nX){T4nU;1ypvdvC&gv(qHKPVunL>T= zSS;9!Q#jNzQ=rN)E|zVeF-f6=GTQX<%ZMFpGCzcndH$`))mA)T4Gt<}+R!M*0NMun zDaBc1cm^x&g;WLUJaO6@PvOY%d{qHQ#@OG!d_UOMiYt4q&QYMZ(OyIQfAX^f?EfIeq8Asx)+z?n{fwn&>lXVu*oFB=z4v+JsFSn&^kBVP9=Fo_K zj-77NfP-!VyGbepe<7y06jyY0k(m}#M{Tuht6aHCsn!Nb2sDB2Jqa>*HHnV*RpWCMlx?T` zkJKNR+X6EO2Rm|D6my`+-5;fI(rW?_Cp zOTW!o@mNy$AD}Y4o?kSMG{KsAl;F7S{UL0lwT%Tff_Pt>`^Pk%Aab2*%TXjQ`o&0BvOnTU zazkPxWxoZ^Q<&-#07-@2K$}+^W(nbs8ww|a!Tl6`2#cv7=WGkyW}a(Rd>eAO66uzF z6o0(R-GX(^jBuHlS5z%JJGQv;%D_G)?o%qf@Es2Qzc&hOIQlCdLw84Vs^fRx zTjw0epk$780@_ zIJSy9AM3>=*l{&e&vP#Hq^L6sHRX35Z4I-=FZHXA9!thGvoYjz2;ORkJ-FpsPI2nQ z)o5bar3DrbQAISr^mYbRwCcF8K_3d+*xM4?G(v$na$3)w^U-Zp%p6_=7-x+;;-UGg z`r{``!noaC9K@Jdich&6f1#z%MRUT&p8B5voj*dO;L1h*(phZr8dG%a zeL$GLjK4g?L}zRpouz4xWlcQoISNl{Fgf%J4>}e58cT)hxzUa830+x4t29X;Sgl@V zSuOh3hs)>pZ|1ahDS3@j>aj?izBd=`rW?u;qV7hZZyaecxTjxRvckPGAz~jF*O)uy zsk^QdamP^L$+>PG^GlfWADI~Qb!oRPrhsq}6s%2I(R|^*LCWS0*}22>lC6v6WWS@r z^0UT_mI8JXUks(MYEzg(s6JTr>Ea8*?{;_Jv~pIJLuVD!Ke8$k#?pSBVTzA(_P7RI zVC5AhU-v$G3GgYb8R>cv3avz>!JHSUOh#e<-Bre745OSJ?YYZ8Xj!a1>F~ZG5(7$O z%ALp}_XS-GB`&nA94mO-4@a-TvhM2b{b-jq4QJOM;>zgqL8M zPB9GjM@_!UGUFIy2-^n8fL!+-wP`oxHpXbHzJ8fmv2-ZK>JWatJm2M+M|EoQA*5g0 z1KcQOlT5^)o(O8IpXVzz>Bo5wu!ONu9J!zVywo-Hw~k2HrA{a%Ug|#Dvno@u;d)Az zsAnqpUIt%Pvtu41vzXj+C@Rm1q}B9cRY>hz(JSb$ooINM))D-Mk2ygh*@Ar;Y^z3G z@S@9=SZn9uJSx!;>gr4k5#1=Zr01nz-g2~ef3B#YY0f+uiPXY3p&_>hrk)`}4%8>V zR?_X_A{h>>S;)ul`D)L}N1$Cbe6nU$zRaJEaRa%_u7irbH|zGy$b~F>p;*o62}Bz& z7=`0H{b#}0<2<}(UmCSE!Jt6~*1QtP=;4?qz+nX!Z2`mxPn?O6|2H707oS>*rY1f) zdS4?SiXz_^`@YgqqVs;s-;9r5FhB2Z^KIo}jH)Zi%@I44m;xaB5t#c;(Xiz7Bc2T> za&EdLfd%X8*PoE%EG9C!rx{LqKNE*j_>`+3uEUR0=I(sJKTGV?REVsmTb2OG*0(!9 zHh!`r%`WdmtN~6g1bzvX!HTy91^F3=y1~}3P(U!P<@b^CQLbyLH3|Q5Ndz#7NmKvP zpQpoIWTP329@Y*)XL$ZSt%{*L-U@o1c~>fW8N|*104|4bZt7u$THV4vvxCsYiXnV1&T$_uWg{Li#zD`g?qH2oNxHk}uV`74(8JE(-Aa___TOOwFF^C4^^RdskTu88JZWI3xc-&bdHqU4>Aiek22Guur&|S0DqiraHmV^4yr} zh6W2!YOcBG$JxL4_$u5V)e8pUp@_8%yyqD6(NAu7MX~oEAirh0P%FIBRMm_SGR&r6 zj79gC>v2y@`9`ROynx58lb|l3f8CAegUjV16fqNN;PVhw2#ZLvQ+y)=rxnloI2;Z>7USBv8?gAo3urCUte0+4kfjyhiOZCKLr4{q?@o_Uws)_r z_)d3ClwuffS*sTh<%PLY)fK(j)loWAX)o#h9{>}l&zL~Xtsth-Uh}F-?A_;5eYA5= zvzi=sDPwN$rZ`KtN9`K-gwv;3cD&Zp^hXjFyfH{T$1s3XoLG)2Li#9G(TQ5e)P`ga zt-N!kw^A;M33C|Px%%?A5||BGL`Q>TS$#m~I=>D>6omO9rDc0!Lu+d8X|_te2xWg{ zjHbeK=$1Smb*ZGcHd8g8 zO|6wmGb~BMG0smc_jJsHaWmX||z`;*$g>Y-w$tJKJ%lMv=W@k64@!NH8DM7Bx5 zaMZbwekf5x{mg6r{Dng~Vnucrtyhw*=<{zCKSgORZurL4#fGM0TOk%`2Fw(3P}tDZ z^0Qs{s+0xA_laz0G?s4+7xAp(*}AyL0-^;VwSzu}%#}hpGvU%V6QJY-Ckfkh- zLsUZ%smd;~mk#@IeywPdF@qyzT@m_+<8HDvtN%v+Fsy%~TB$W71eTNgZklvSQK*sZ zRF@FMZ*Ua9_wd)+P?@Jk)Hg|5cr#Z%nRadxACS7}sj`G_n`*b7+F;Wvh1IgZm9?)G zowOOlf95h)f38gaO<@yBX<@QS7M==_49?cbMFo3Tea4_Vc;0R4F}3kB{@U~m%NM)M zy%!c`cJe0U4=v_Id`N?#Fn<3JARnJ%fg@4TftXz5!mUPfocQgLMZO-jE@Bxej?WZ9 zK1G_^VjPfPcpK=BV(@od(MWo|15g^4_-SiL)cAu*uXO74K>d0ad3)gZeW@FW$`G;L z983HOrvACaBW6Rcj2V>9Mjl6P{45L!$RTuuX12d_37PUb=%#>>EO;t$AW_k7B@G{^ zf&HFqAgpCMJ93zj@GcE6z?7hL3%&@XgPkf;C<>1+u_@ajA!!LCI{AXJ^SY;L@s0od z7`VYuBJ=4ebI2^dRuz*xb|rI|+eiNt;b7AcgPQO*+1XR2@{QZ%7N5dHx`nW|i13ox z*K}X{Q@WjaE7`C+)&O;s=-f5{p~_^WzVk%Nn4O2($64(~om9aM`}w(q3ULVxhAHn+ z$gHm{-TZbwdztdWoTg(a48e@}-XHCS{{Y>@a1_@AFDJ!Ks8yT62*MnH?bzyYl8HEW zDs0Aj(O9M=ndc+fuD}S;J~Tmtor47$`WxLKoGZ6T1M`AFaU6C;8Jz}aUyo@=Z^l6h zjrw6_#tUvAel7*N<rUra6$UwBDgaR|@um5d{BshTa zXUSH;#uj}Ly?mK&T72%GMSa;5UbmQIID+5Oro*}ZpB{AcL1ai1Iu_-v&Rt|BR?O2~ zQd}}_v(7Sson-=Cjv3Tov1~ac>O*Jpl}x)*YRq3z#MDFn(X%fQZW%T&LiBcXmZup; zk80s;aS1Hhw(Ut4ZrCuse5ZJJ>JPeBBs=GS@)muJ*na@*y}dm&_@Ihjmd-x)w%1cz zxFK>$Wg&*LpxRxE4ptT@<~8#8#O>MDdx%EHq>0N&?7H=BxccU6fVq8TN2=%0*w99e zm)=N^tN!}PyRP}G^5WoM8@wV&4X?U>;s~+5891zs0hXu+W7>+dnPJtO~XZ_r6{ zTg1qL|MetDY)Kb~U@GKYcudHZu|4QNz-ERFu^*;f4?jy=O^OOczFGO+eiN7*F{UQ9 zE8LfAMexlbA+MovmYYAvh{P%MBX|ecv8Ro@i3Q-Fv0KwSPzd6b%?vUp4J0tn{k0oFZ|{1Y7`iXEudOFNACrrjMlF&Y5^A)3EYE4dz4 z>OH3#p-{e!80NlZdE}s?8)(F73aNKH4RfsItrsz*8fMM#W1H<)u3c+r;9g1?iY&h& zm$pzzVetuJt8!WuRT9~ELezS{NKa0xwyU<$(c!ADFu(Dg8$$cz@|S*nwqv>#zHp1R zlcr>(=RD`+Y?diK%rWZn?|x1P@+_*uttXV^5S=Q^b$zK=(hU5%u9Z43ra&mvG@?A` zJC8XCoiId}?i#?z6AjsNlXGIu(QPO|6puHnMSySn$|2b=5F663>IUL$aa0=vRu-L# z^@GD-AaZ}mXh6gFJs}RJ7d~_=NpfW^FL-V9MU=S=z)srQ=Rf|LmN%|AK8`?|nSVRk z!phn@<3*=K3D{JS8*w!lMEKcJcNSpkru+l1Jc4R;VLU`tG_Wu0FM}Eq+|@_(R0-*iy{v!=U|~Xn-f++xA78uf6pDY z(O<{Eskx^saHNLWywutj_Zp%it8&u@3C=0C&S)NeC@dc9D^PXCsO~NM z?wqHHr>@4bu!gI1rrz@4&}9AwT#9-wO_#T1+^dn( zxXqcvOyk=*`8YJ4EbGqI>1o9$lRH+#zb`znf9~j-Cmb|{D`0_Ico#DqyOj}yo<)V0 zRxJJahEsav>y8x}i*R+&Gq~AFNSM@j8hx5J1MDx%+oXCopkXRKh zc?=?no#pmb=yFM5)ZEq}s^tgTDKZvlBcrpSi{NrmbCN>fx@*60-Wq#PAwA>CrqYx1OY;Zs(O~-`y29z|GC{ z4)au76GMtL>O**`>D|!{l7C=D<1|d&aW1MWV{8OS=EPc%CAIapBeRy$_MByJ0t#Vtih5_=v~OkDtrIniJlVo{L-_~?%H8y?D}+F~#< zLOR7hKxK~K=By&5H<8{8e<;QG%VLa6W}2*S=0u7uj3?I*>wq~{bC#s33}qcr2s!eG zNyvS321@Y{tih=MPoqpZHtWR7aauzX4iP;W$<+y^0+`*v#>euES(2)Gk>5Lx>FTb0KnL9qIlPxD&<_~s;L5v<&g9*ng@d2UNfFIgwM79 zREy&a*JJNG1HV=LCCh8BnxwKFN=4r;jamK=fH;dI@`Eh>2%9`f1F|Dd)sx3k%PKUIVBX?x%KJ0ON&du|pfJ61gJ7au zI&bcTL6CE0h3jo{zRT1bOc1u@$<3QtDIr;zmW6|Wwk`Guc}z0cGT_`(TsHuFE-b^) z@>j|!tyvCrGxJ|Q)+2}YzkOVYan0R5)XRq-nQ`A){TR#`{Ul8AKaktpJpN{9gNWR* zHM}qF)+?|#!ub&Kd{9RuymCIoyHkKJ%v6EX4k9z~yvCcdZWvl@sJNvC;zW)fDGr!I zWx1rz`TtcCX@vz%;hjPV>Oth70_yobzOvP!FvVGULyz~R`!m^RT94Nb$bsk=c{2pQ z%EY0ZWIbLwurw04Nz6f$jpv;%_6=@=lsLQKYHapwnMynE8NvBNEIToTaBM`PwIR8a zK%`~5D<_WRL4n3Z+E05PwTf)(!>rD4Sx z$qQcUd?bXDb&lK@`44vp3zMNXA|+0@4r3Jr(VyJ+l7r>Q1r`)CBaYNvBEHPNU4vfb zr~M`Cl+4lS@?nm#*F&CO&Y$W!s<60s27jAj)Qo%6yNq9Nge`=&HCx`tk1CIm6^4q| z8n&XND^+=`ld2;N`Ju79MnN@Rg3%Ws&vztPSzD!KxhFY~S~5FvY+>#(?xHQk zI;HAgc^^%-RU{4duhln)+|JZN2gH|lbQZK(} z2-oHIuF0ptf{vo{|Mbp`%#HG&mD?9gEDhkj{v_F7Hym>uLaDpd^O_3OeM5p=w)flO z4$jS^Nah}YZ`Q}u3gjVnlJ@aauX0q~6%j(D0d(u-#eb$_K^{){JN6aSNXUu9H6^R7 zbE|mEa~Lw{e84TD8uGLF?X}aZpn(-5;L`6K9s}XpXz`=p8|I#LkVgQ?%eh)W)2r?5 zkneK$IplbKdsqjQdfPya!S(40=^K9{c%1fp@fmj2$5Qrnpg2hmfOt1}XX;6Z{ZLR< z=lTFqH;dM_Bf)={<|<0_ zy}ZYPVk7O)AA<2LtOtzWBWpWICV(^NrJFu$;HC9Q-`#)u1q)L*Ht z{;P~9dVPH_MQ;KBz(HJZrkw)`+UH}NN$(%9iumRyLnm=GFm>QGzvH)2R)~i?MZ8P; z$ESzDW=pJmsMrkxE+uCVEv)t{+5rxE9JnH}j3q&AUg~OW^20wDGB&#r9Z84p@^^bY z%ax!F4Rl}Lr3F6Q(Zv~@3+^vLkA5NbJt*vv&fC~Q@k#m4o)kt0?thtWvvt%j!E+E* zY{6@+y(yeVISlMaXBp@3A42!-(zD@R^(CE7&)fb*Kld9^zQvYn3tUkow92{gc$xk) zY$8@FnO&ZdbZ9kH=8HkT&SL`qu{9x$sy07WDuT=G!PwhFodH;($UCM1n6@bvcjAC} zptU0^lJ}59rHMh^IDXE=%Pu}naLRuX*rH*yK0%P1oxeY7VF{!@tnU*om`vR<=;3%v zrborE##}mmClgM<*+iM+8FI)fbWeiGJq`P#6{OzD=wr;^e|mt+GBUgX0t#Zq%(ew2 z(DZgN7p*ThZ|zOA0De@ILGI zQhbyzc=uaZXacTJK1tNs zy|&daE_xZYwo@7YZYj~%kmk69#yo0TH5?j>qRsmdNGi%$j2kw3ynej#i|Y=K-{kSJ zrtmm#XdFu>fy7_70#N7nrma!LtPQ_LRMOGKJWfap!NsA1VX zGj5vh;p9j{8%>g;-*chpGg+I4pcm-6S)7o2j@vqpg&aLSJPlXR=@a^hSjRO4x8z3% zx8*O_x=~tX*OFXh5=s1m!7}HZ14~iI_!e-jY_d*FBH}h`m*I8xJ5&WGi9XkD#bu=ncJ!@cS& z{oy4L@6e@h0pOi=Jo}w!_4W0Kk)2%VWdTl z7>(K>kj62s&)_CxJ8yv4^_Q#Ln3~bWH%tSaXp{NRv&u~)(~)+}(XW_0p>oOhMJasy z|2lw<#nWWRmejA=xk*4l;ep56j5q1)2?c}dQJEd*@ISt)N$2(O1GWSB#>qKfDL8{U zk^ckaRoUqtz4ydxtFX!l4og9UoXVt2!SS4v`=g2rgWp<{nEK=6LUDh*E&r5T(!NDp z#v}xR0zu+B5^4a%7%< zsxbx`_@60Zoo(y)`K)caT`KZAl76OP9$Ajj%V!twe`5?}(`$Zp-7;Xj@eeuQsoHa! z)_p`$>Z-i5U8|Z=oYiC7(4@lAQpNE_4s!V1rdgQ%ft(xbhH;2{aZojXbkw~LbmvB` zPO)C+lN4_}$&L+Kcm9HWm?|T;5Rv2oX`Jgjhu?|?)1l;gKxj#Axf6w}{F>s5-32c# z51QyF<6U&NZ5DA>TgBc8M=<>6YFw9VCJ4z#9*R7E1ohfvswSu0CI3;&KIm~uTqu9! ztQPUSvt<_e(c%x$+7jmbJP5t*YxqOf3|~ZqgbMpX+?f1O5oFt@ROVeOi}08GGS}?( zVevdw3r^!DFSab|K)rX=PpfcIqFwRlMS=B>a1U6pmvLcZVNq>MQqrzdd55>r{Z>zH?q~l0Xb#`UP;9vM@TyV8k4&HMp(3n)4}7rP z@QH+WB}9gN$?w~!Eo<%V+Am9!CR7);(ZiN&i*Hbf10Z?`-aDhZ(ao@Vj?JgJEss^KyOoh~^ z6}2`VUr|el#m4lGj0jd+Nr`Af34tkF_hv~}k#2W_8J0j_-SRo-T~ zM@8xBsqvGJ?vFn2!C8AQ1AkWL=&@ELx&Q6Bq+_y_xWtO|7YSMm^1#Z8UYq|*~m_1d6204b!c^U&~5}e&;9iHZf*w+Tk*?n%_N%O ziLjbC@xZ*{w&#|m@@qS)RNYi?Wl*is=vwot#QAKx3)LHc(g!1c!SPPY;PZ9u2wvSZ z2?~cUj5+5Yt2xbls?{PtKVltIYoav{Q#qP@w>z_q>h`AYY9XEUwcjk`Zyr_uR#f(3 z!$c+1evJOm8?;pPdw@}XVG;MX&znn4eQmr32@~nW=>*vajz!=~8-P>p6qh*K{~D*!;M{icrsV& z_7K-_NcPD3mL@{O^;&{QeH%srvk#@8dc}gxR1gx>m*t|sI=o!}_-K%_?Ol`Nc-;!IoLMZv$GVyIukaMlb~W%AxHXOW9`xeDkuL{;ihnPt zz)hEmfDU^8eq@V+W*F$flq=zKCJm}^y?iJyI2a|8zBB0d#ROgQ#MU)J6nW1$t@+ zh{IluDny|v!FzuS|q|qM^H1VOToK%j9A`BNR?E7&r)a54h!Vj6x#5f z6J1|9Ws!v3ap5*@SVEC}pxK^E*!WHCFef995+6QBl;le7`LL(>10(Q~KREg0uj!EY z+-t+7FdEx5@5XT!4yW3KW#F~GmD6JtQNxOe85}n7XeGCnBu?CY;;#u$JXlGo4eYu6 zR;h7loZx_vSS0elX?bq_?%j?LIb-+>@m{(ioaG;r$2mKR(-v%t336%Z9H4l4D$fXJ zzbH*~WDrS3F=S$=0Qg)gUFpupTZkLIcZV1(`U;fbueFb?_DMIy$jz#AfV_>?Hf$O} zW7$+b@o0X_W?D(M0!Qq*Z}xlbO<}X=-&TU6FTUb?I&pLcm?zuJx^dAzq~3y^ zMF-T*&>eqz$DW7E==+}5xo!L}0GU8$znp1SD|zAj1bHMy@>e?!3E)!;Ei%^DB8w8X zPbK*^86CKD#p1d5{S~{&p_<|}vNKLp=Kzui(9<>046#S%OyHiVI0Br-Z5&w7Ld&vC>;epwUocolvzi%4o6yJ2@%J|dKk2i zGGQ|{3f)aZJ=x}lYo;LW$4Yk5k_dJL;M7teAoEG?ZXY=;Ygx4>Sn$7y4l_vPhfuKN z23zr;%B4$e43|Ges{9)Jh9X4dahf!1(S`W7kEIS#8Nx$j3gh>`EL2Y!2acaQMK6hz zF#wW1K&foCrIKTo%AWOtd1Svh3!%Tk`l#%S|%I?$T$O~I*MX3bD@kJ zjwl-4PGb-31JYid?WG0s1BtM43+{$!2ucRsZ#>!PrY_Ex^vAWcHr z-r^fK5Npjx!nRth%Xe!d*lGjf4-voy zv~uxvAkPYMxSv=E)E&bgO4`0|)4Xf;k)XnsL#S)H5x*(sB!K++fOy=P~Xzv#?q%k~`I-(#YosIw>I{7EEbJ{h|$0kE(Q<%m*3#rXZ>$8taBx%R4%TFE3<`_>_WhdDXG z&VIS7V~uPQTvp0vus<00r3Nr$k9KpOl6%!81$@@#BSS8Oql zl^NOqBZ`*YOmU7fPbW1D!!CodY|$qm)LT0ukW5F^56YWpI=kuj1Iy0BaLP{@q*1mi zK;$qZ)|JN5(-ys*cTJi*)ddJD{m(m3Uti}^wd|JWMOhSv0e0*hjymH5+nS(gI=fli zfZr5v!>?j0_hPp4DVlQLRs$i3{70UH>FZqbjcAnN?GX()yq;W4HxrfIFaQIdd;U~a zh+BDN63$>TjjOXKc27Ky>M`w8ShFiI*}Z_z;oXqD{{Ztut-Zz5$sxkP@4ijEsp@<6 zJp8E~($gZ)IWfGFA$Kfr6`hXJ+#HVo06bK8M`j4-LOvopeJWdtz9|+6kTW(nd3Yn` z=}{zdXO;k{=O-nqeT5+1(1b}0PI?ArZ^iWOS$T5`L;(bxgMxA~n%79VTU+=ix{0nK zjO0d6GxMnRt!3}EH@lMERaD_pGyo|6v=l^=u}#&alUhq6AO(5I7z5`+CgzBVur>jM zkBPmg{Z~+y?&!(2A>Km-fMGH*l0K9cprv7HljD3~oDtWpS}2b|XA-R2LuD{YE8o(x zD3U21Sc0H>@K4LP&W2e5w+$RdM?5gjPhXu4cXud{Xxe06rx^ySq9bA7eU33CNhV#7 zImw~!u4G$w*xNDC;{?*HR+>gi!`4nOWS?w$VX4|7n= z-?YcQPp9!e=SL^v!W9eR<-IeCvBw#>(WXSk@VQ+2imR#HE_>#!nhS1(f_TsA=~IgO zq*4vXXsq1GE_CvnhUl9q&*mt2r2hb+gmzZVZK%Z7I;8NhA}!g+s5QQth2}`x;!wf9 znW@cjje0sI2{Nx<5#hdk=b^)?>0ui2(SUBRx-`{OMfs=IT=^#!2hxTFZ21 zjI4RW@${*vxpmQhAIpprZ?K@!UAwXt=Q!FjN&1@FX&AuF?ii7PK*tm{ykH|1!9WIj z4*9L`P9a4ccc*DbM;?5#%K0-ihmslENKPDZr>-+jVUXM|4hw^mjx$TNlwohV2n3uQ znl=?^x5@@b@}VZE7%{oNBaJgq7Pjtzkx3s2Y#w>eDV5}(bFqvbGOdnzIRoCR7Ldtu z>>p^2dC36eRQK;9pxpa{uG9z9{{V{Tlx>~)V6nnV_DP}GuAzNB%<`D+MvjQex# z{OROZ_I9yJ_c`tr<2)VPl=H?#Y2fQiY4qm%-c&~7Y=hN({lB#htz6knb|trgQ{pT! z!Ek@2B(`?=81$_dYkP?eoxSq@!dd?SV$8$=j?MEN)R8`rE`&E)ox^adWD*{^Ip{d5 zB)YZl-6M_P$+Ta7BS& z(Hbh(yEBvMGh1!o^{m^Bo(~nQtr3;?uQA9KD`%!_zzTwYTGv71!!#)W0PAu`02Noi+j00u>VM+8usb<3svSm$E}&y)L!9Qko%W~$p%omn z`F7Jvcm+WHIH9JHx{RFHXEcr#2iYCLI43j;Om`e~qhvp_RLFkJaB=w;#+l-;>)}=BQ9MF>-=7%Ap z02x~uJ?PyYQeDRZRAiA$?hR#>uWtL3q5M?5iad6xxmsPtu}er*RQ08vEb#=JzU^Ts z5n~011fQJ)f2ge1LMYd6e-$DKWO}d4`Xe76ov^(kbw+b3V&|##rWZHHMA`<`>?jzb z*u6QZF6A+)#V;YgJ7jlPrY8jsT~28~h%8p+oG0U4v}E@OoPVD6yB+LU=Zo+YtvoPhIi&Qqu4VveXK+UKK-e`*aZP0<5?S#0daCul)Jqa)6V7OzQqi8;qErMaU z9;ec*H}-93rbRC1-#&QT@a_KqKb<4C2hBY`m7?tfjXDZZn}~}NDV%h1LH!jgI#yLd-bjyV=9w<~V_NE!VqgTHJHNAS@) zZR0FRS3H~wSt~`MCHS+tTgYSL-8cM2krjR>1OQ1m&N_6jZZF;|i9YWfQK2|^##n+q z+n?!GpA2gyt^B6PoS+0_!Q-}igG?Mel9S2Yau+A_`PT!E$e3YEqV z3H-k*7;hLLjyN8|rMQY1z%lRKN5rf;A4(TOfH&bzkNA&{LxjUQiVX+zV%(dwL)1LL12n5{Gie zyYi%C1J#XQD3f+esmzL2NQfkyZXIX^pUjn7>D^QedJXjki287#Z!_vW*IA&ALKpy+8f$&X=k9sOtm!f6URz_%MZI zjo#*;_SM_@aQn=P zR~=FTcVjds@d3CRsA(W2%)9fITzzS0xUrhvk8ctg$a$PAuO7M0KrIu?X(G5;0v=Qi zq%W^N^upCdlbF^eW+(ABI3GT=ea@QTwAHsQY@`_9Z+rlAN zj4&m5-_A$MfYjSA$`4Eo`qOxoRs~(evM63@9N)FL1NfW0Dwj9^07o~IgX5aUG_;Mp zu$x%zQIL4XX{N}M)xdOSQ-Ox(2iAhTiQNVtCtw-&6dX~jq1@$I4w&mf&d&UPFU4Eg zthX{jKkUSaeKFRhk(r_ej^=D0l{>Hq0+t6D$?s7{LtH4_K^*75%97WiJfz&?21#pk zENeJ{*+Cl$=K;OH&st-pTKVfMU0la(Rd`UlnZCWgv?S2@)wx3Uk*hhIJX9UdAw&y)C z4hRF?Mt)Vsv^jq79M)fS6WLFnE;h#C-HM!NKPvBj0m$ zG_6<4u#!uiE)R+%X5cnE6WCSb!rI&G@IB(8iZSq#$J5fNvs*l@{{Z9XiYiZ`j-hm7 zSfWh%g#KQplw8e&jORS()|kqh*`z~|dKy=Bs-XV>Ixb9#f=fcn>B#{_Yi5Ls#*fXB zv6GG{_+Z+r#b~mxNYRw2#R)btXvx?q=763+*~J?)Vg}eQ9RWUvspr~^BP@)LOv?(tV|0NTCS;N@ zBIWYn5ne|Q>|o>(pYs*Uzt!Wpy}Fj}DN@;xl#ba50kg(&*ijxH@#Xe~6tdVz$uKG) z-N;k>#~$O1d)H6#TRB&qeWR{hSq5%E&v8Xq=}QdYz(U02d0OQw0log49qqQIJ*@L6aS}f0(>(wulgC;~VR6vQ$ct&S zn|-Ir_iqfz7&}Y0I5o&D4(&Q*$6mE<`&ho#G~3tEbJsQPuLKu{d?ZT7W)}SgOIeo`z$#K@Sm~6W&yl&}G-b&0c4-5ut zp+tjr>4j?-vFZXd7Vj=K*t@vt*Qd^s#&$?>#D2B3Er!P8R~aMckL_B^fY}t#RE|uY z*vi?9%%tu3LFT2Ky#r$*^L~{)^7ZDX*2~6ghQXvf*74MMB;?lXRIL)dp4>j$cJ~+HFa-sA*hLo)0}63kv;{x0anf%LQX>ZVmyulqM!y%)sw#z@c)%FX z_pVW=xdd)J)uT&Q-UTU{8_;e`&`*+PR}^M-<%&wJ4+vfpP{g+~<#40(Dq- z;qn0(C!UmUqYKBTi;c&4VxN<}z*n38EzZ!E-|{ErpW2#{=!{^X=B$y5AC zxT^fO4AO>R%MN}K!NW?Z@Hnf*9P(sx%*`tw zFr4wtMI&YfA()<+Tp!Z3bDSUD9AncpsgXH6d?av3UzRG#6E?U(6m1-_vRvom4lqFN zfl@}#$znK82s}_*q_@Etpg|fjq{@P^O=|BLVtmV)?XY_FLHBR zTQNyL^qwjU7uk5r>N8U}!!h^fmLG~946^ydFw4f)7&MCN#qG5#rA`A3ieY0Xn`rU$ zDl#aYLNjq5dC_%7Kyne@Z4>tEO_2M*Bd*zIu8S z^riAKj!B(D+@ zpT$Wb{{Zi!IT!~#if^l2G{YuXqXX$#D-xUHRSUbG=7?4Mwp7QxN8$jG!`xJWM(TF5x)ILa3jFGK=^sHDCcePe z!2}SL3>&>eqo!{B;~9`{!me?<9+e)UE=k7$SAkYN2Ek;og&BYggT?_QjP?4_=^jQp zenh7I3?kFpQklHS7S#YDVu%7+kMA)9wP~Q6`%Uj*7o8UJjJWP8rMHn_hsq;xQdx`V zwGH7bvlf>cxY#F=%DEj$JRY?fZ5=Sq`Ej86>@R#n3~=f&!)a`d<}`lsiLMZkR&*joe|%?;%9Lwb#O*xR+lJD>9lUyqbE50^mgsJ8k*2ta2%?YCM^ZDz zMqH@xggGF~yUU$#SkvCqO)*|6AqqcnKp!fT85tGgfWr;c^~X|bK#a#H81$}3E0YS1BTl0LP?z@7&JrjXLacdk zxg+IFHjpvevu**$Tz*ta;>p5El&x~YIPGp_ifLq$F}2v93wG(&s`A@jTH6V(V`7qF zm&;yGepS$|>;&3O*3Nd!T$7(%)pqAa)o!CU5nD*`m)x7%0T0j8tB!S})SS65tf`?4 zHz_We70hv@w@k+?xSgmtvuOTaS-w&5X5>kpAY0IRm;cmC~q;x zQa^OpmR7JfBpX@r)M1%zc98tD>xwW$iWmmVW9ve| zq+@nSqhXaJTz(#En90pCb<`(0Dt{_kVq*Ck+8(cBqI;1DR(L{!R*8XQM$qgz{jgMma#16)S%BC&T;08z-z4JF5xhu60_r#=$Z zEs$JV-djsI-gr=e7AL0K$|_o9XDLB)NaQ+}zPbjIo*lSIq?T7;E_W+!89P*S$GNU| zuf*`Doi)X%EOH@=K_SP?am83XUEqy#QSpAE7K@_lD{JNv63)8eQniEMxKRQ*@& zBgS`Eo=h6G&*H8O&@ekf^Y^)=F+d-B?p8bV#nJz=yJWPHTp%r^)ry2Zk;vTIQp=r3HtLNb> zN$z7QD2x!q^MPK#k}9&tIZ)k)S|%G;R3R6nUPL%_b$b}au@$kyZdgg_9C*l6J zVj~^-H3LNxAKFHQ=dLP>M=QYF>AJ6y>XK>} zOwnAhw44G78@#{mR8J{&4LV3qiv zd~+=q7flSZN4)N1f@J{Yk8|3PU0pewXPKAIPI1StG)|#%Zl#pMiV+5Ow_i>()c$m$ z?h^9TX8)w zO$w5+&IVZW4m#E1y^?J8fMU&sDx(-4rl5QhI3VXede(wW9Af|;gi$Bph)70Rv$$hF z^G+d-tAO7Y0p~sQLd=P^*RJlQw@ThSh4Tp`2>nh!2ox3M?I9xF3vD>b9Q`Px1z5-B z#UN%oe+c$J-m?6Fic}1am>lMWjV~2LO5X=isz>WbMtsEtss#1)YCRYR-ZTE(%ONHC z!0Vo$*0PwXkzD*h4oT#C5&Y{bSOoV2;%}XAr#J1;eJe|k_aEn4*&JM_{;FyIEW;*m zF7`9@qi5npZ(0iYVU>rk^{J+lbZC2y4JJLoAfc9>Czo=&ZDl72ElD2?)BLD85IY$9sWcs<^6u(6KU%bDQ!1V9z#M$(_$t}tW63#5@#&Tes9HT9?ni6^8yu+HlaJ1m zO0Nfo^s))bjh#=vO)%FrKmLU@N`vEEWVa)~^sFWej|kZyQnEuIQ_$dZ^{!U5cjAP( z{{W)De{>|(_veQt&2E=6T)?qFtn#@kiZV(03{pGkS#DJDF&`e(>%!J=cXJav7$Z~r zISUm9hhT7PIHempJY2k+RzB12F0Inq(HCR74VaLq&+#0bZu*L}-8O}(NeolVt4lIQ z%`-^ZF2H^f$pB}*K>E^sD@q!ksFA$$&pRUx<%{LJW7JW0vtOIbgwn09t?tqR6Gv!j!Q*Uo^3NM}p`Q{*~=O@!2ucao{lgri}JoKC)BhEwk z$4t{1;ELEpbt1O{NM&uR4pqS*D|gOnF9}*jed23tdDnWd8OKjk{HrxdiR5N)EMncO zIv<7QzE(E3fh12QB#u?!;PxZdta~xX6||mA0J4-^E;|E(QkIG+)ud$sh#5R&p4G(D zYUx)jYuLfHLG(4!h@kL@*G<=ywQWC=(#NUUH zVNtcenB};pQ$>X&8qp&-=~Ykylk5lXxLOuS$UiD@>N*oc$bpXor8O@lhU_Z9w~N1ZwBv*h;R^dM5+KWLESecYXyC@fF>p1J%OS$>E*Jy zig-v4ha){I7XJXWXBF=>3vjheuz#tW=$y2v4BN4_dxPoytBd%TPkSv^OPyIJx<$J( zY<&51#Mt;j{nu0Z=Y!h1b-ZQC#~AmfjRCk#mj$Fwn_rNBI(%7p?BUOWNm6Ie{ws&W z32fI|6w~?aKl?UE{hmSn{Bw^&O(yU@si)}LtLl2EnfHiC>;kDcW8aVdE4p}(!M+wY zlF59qSUZo#Bq{m|;2O1!qH0px*vKZ1HXukp4n1qW8F{Ka)rL5qCd+Q6_Rpxj!P#q@ za5_sVE>Ewg`PQIswN|)B+XT%i84Do+bMvZ{b`VFBR5A5E{*|KL4i(2_-r;O(a1EAktAF=fD_V7n+f@##xg zvXj7S#GQIEDrh*AhIQz6UOC2p3x7I+mDf8)Xa$!)g}AAsxpeQvEiyGr^&* z6z6hqMQ7f3b*~J8fz4!THAE#tu15#GYdh?PkF{bP5=BL*HW5JXa%ji0GSorse-$%? z{4}oI^GqQ$Sh$#UMvAqUoKSI^nlFWv)Y;hw_ANR*-w+g=#a7>R)jZ?}WaB?3qIBtY zzDe&)d`WHh-4UHYEfL;7twJw^?7nz>xL@=w()AXa-^c}g)#Vt0mL8d{!`xgm2=dPw zmm{wo#a3-5Xk8c*8>l{&Yf0^Af(wY^+FK%gu^_*p0C(eq>0J_qba;zsQRaoXM^p*0 zhQi=+p84bR6$RL1Je{zAcR$yfVRIS`$skoSl2nd|*n3bcsj*+V;GB$Bk3uv=BkoBH zo~$c;Z6!&_Za5kKR8;W!a$Bw(sZji!=RG^rtRe+ug*e7Gj0#~zkS^u|ATn3*oab-K zqSY;Yh?+qmZM@~18-7%G-9&N?k~S3n@y^lQRCg0Z#eqI*o_-9GwJ&;a!! zjzy+XJqCDWB$xM*zei6006JT)>E_TvB}dM;nkfuX=Z&aA9q~aqGDc+wY;cXDr6|5sk4G<&aN-MS*}0MX4)oUB z&)S7Sc+}8gr#v$u64=WH>6S&++x+u=yHY;>*~l(ql+LS5i&@z{jn0?+#68C5@~JZk~I@ zqjHSplmIJ}EL~{yJZ!Dym9Ix4@otAUo2%MdO27$_FhBNZzxmp({uiFwTN9@6=?|Rh z4{@|$`*WI_*4iHvc=J&E;Qs)pwt&P4JTLCA@+TCxQ?eQcx@}=n;Ks|p)mx)`e5!MQ zS~=p>6s6Y2+7;k}2{l(O6DtU<5rOmXGq#y$eG_FaAPha2_5DRn zL+qM88OAu;v!{3#?nSZH^=s!QGJ2lmdQ(3FYL`01x~{A86-6MY!9;Tj-EYgBauHQoijF!j)uUe`2 z)-iwL4FgGDR!RKH0Q4Ny?l{1YIM1z8blmDcYL}7@Qo`II_ANojqtD38y8urBb6T>n z;YAna1z(kG82I@-S4Rk6NjRgWP0VY>fS#1D$BI!_2?`pOATHbrHamQr zD5K!E*f0iI^`ettl+Zn;rqO^tF8=h7$KD|x8`Bg(17A(VYI(r^BUgJ{aI3wCL7&RF zH`*oR>U!nWta7M!AoL&Lt7C@GGd^F@M%J}E-A3i6zPOTEPdRqadfi;#)x52Frd&=Yom0zU*BANiXtaR z9}5HRnp*MWky>P@UMO))c;}VV8-YOIK4r(Cs7%t8$C%itfhD;#6m~n!dM1swwI2h6 z-j=By!J=Vw9-^~DV{|r*`c&$8=jlOPwntEYv|5ebdQ{pwVIhs9;MJnV)_X>Yx-#vm zg}KLiuxS%?2BDE!JFv^sD$v9r)fx#`faM6MdSq*DshcZ?XzebB(BHz@;fJ_5`cPgb zhsoCb#o$N-(@kXz!PMl+in4>8@qwSxs-I0cPo)%d zv;njzk8S~Dh73vP+P9h~j3c&7BLbm%v9AQk{$Ii6m2Ze*qAnz6P{$*o=}d$?o--Yw zaM)%!&#BKtL8MacmD~b$;YT2I>qb0|F-$N#HvvNR~Yo>gk+I-9D+CiXB_wXR*Kuy;fn!8!H&s;oEE?YR#5O^*p?$; z{9d({fGr0tTA#&U1Myd_>rP?x2h7t~{{T%ZCkBtwj{7DDwnZ*;jQep=!}&=V+syLh zQ_}~Ev)f9yHqptPGIgq)oToHqm2}Cu0pl2|O?_Bx7B3Io2(D%i%D)DgY6! zoMD7RkWM-0rFLx}N=+le%d1Z)CL1v#05O77x%!IZJ|vx|wiy#17b5ru zJuWEQCJ0fO9;0B$u1twOi{i;Rxgx2e>P8(N_IQ}3#ns>A2OKJleKO{(PpI4Kz9`e9 zyjAjN-H=7$kxwW5z<{ z0grRdb7Wg9j%sm?8ZP?wou)%BM zZ!t)TPvUXbr0}dWf92b|q(Z@&)IK^Ii(g~eoMVnkHgj(mUp3d4Z4)yy$+2=Wdf;Ze z6|aOQwzY=N2;_4NYK+d^IOiW)&74ogA7?Y_T5-C8HeaVy{{Z(?cK-m?+RUMJ#jMToqK? zk^#q0a7nMM-ab2UYmIA`3w`$ArNG?B5Hm9NEUCtRrjjwIM)Gq{E9BW^`#$jGkxaU_ zrx;1hOC7Db{{Z`V@yFJ$sE2+?%S1{ErQn&4v@!TL+EO{VXO#U-82z$Q9FB`C41?R+ zwOIPm;v9^M)uX^Q*T9!Cbdl6DrV|v!l7*Eyq~bhe1S8{`&n!_UJl2LPDN$6xnlLlK zp`IPbkw!Z96^j`I)`KY-R=^A+(uSTak^rYJp42qCiIX3!LN>WkZTPYhW+)XJXKJW=~oq)Jn?YRQXPcK-kg{#Elgi{|q68Ds8C z8v24k`xhRnYvmubhB0`8Tz?q`sgJXRJG54An{!YMcC{5NbMHb;$*$yaGtzPmVjRRh zxTt|R=CT*~nNNOc(5I6QhM)xIiI8zYIUt(GJeDv?BdrM`D%|z;qC*;vbP^%;qJTgp z^{;cEY7mmFSJJjw2&@E8S~AywhW4$neRK1yVir%&*0n3gH9HKBm7`*cuVx_`UJXi^ zKGmyYwNs9i8eWHttFXjZ11rr>4ALWGKb;8-hjug1r5hB3_rR&Nbz_zEF}9m4lloJw zI&3yU=xG!lS?R~6HnIS8sLfhC@V$h1tOt(DUq&cLwI6Y@^#L<(I8^D3ZQ23;R5qlZ zeUvJB0#!dDnu=FP4VG=7_8oboT~W#ADxHNg2hruVa@n@H{h8~4!=L0SZN&U+W^Iee z$>4EB+&c?dm>s3kGtVB>jrR~sFd*`9YLPgyFxl=_K)EL$y@omM)`WCrcL0Ko$nQfp zLOLM_131NOw<-!OgvpKo9dT4hndIkWWCOG?>O0gB$>gbGJ9F<+&hj}XA+-U|9cU}P z_$PK0{_Z-OV+1p-oR`XJz#(}!_Y^$OhhC5FMc8wLh3**o^1irvCr}i=h?w83T+1SK9|`Xi_Vs-)`tINaCm$ zr{ix?SG@}UJIh$0n*oA=GfRnT#e8jO4gkUatKPW<5Z zs6>%0AptFb8Jn>79`#?-W{f@Z+z&EOFNV*5T4i-=V4m&n&+Nhmg;er$gG|yZ2~=no zSF(5_nVMbSvtAEugGYFx7>)yU3Xsg;jQ8TU@sEiTe+^q&00f?J zK!D`n8lw1{Ulv{jyU`Fw!UpZ@?3Qd-;iQ||keTuUK#9<|rmahk7ZGEP1F0d?U1b;A^FwE!SQYwSxaxRhy6AFT}_$f?|}&`AQJEUY+XKU(fb7&$o2MyLNQzJ2D7bW5b`>8q9M2_ zM(|41L}s&ZKJ+vdCmx3u^!o`g$r z`>sY-Kl`wHnu132WqAU;LW^%^kRuN;Dx+tp!2bZ6uen!7$l&^ukyGAWnap5hst%;` z%uY$5g9cDQA&J|J=M_k;95QC0GVf;O9th7LN`^^7g)tBT?hb2dU2+y#M+YMV6%O1g ztETUZIqQ*BLX$20h9pTJX?@1+#4+8EgdWsr z1hPu478l@Q({6dKJk@QviyK!2j^?4-RD4*#^fik3;PRf7$iX0I9e#C{;<~U4k~r;I zSjUm@d9N7!RQBUVURv3TpW$PWe!Zz()rHI_FAHt{A;_#37HI>7WNh>xnmG-Qy-L>On4jrMFU61OL3^JuvF}W5E(~EZNXJTDdOvEzvEqxFab;_8ISv9JVkvO+ zPAt9XTC&W^4buXDb-idmB`5nqu|~s2U#GSzsb_n!#^NzfbSvav7ud}!Wfe~+zZJ3$ zt3{W@-Vv7C^xkR8WVM$*VuScS4FZvkLjHKA%LRroKOxiJx|W|hPZz>fkdM-n-*|G~ z4Mnf4@`g-rPhUa>bNrRr(ZcqQcd0=XbI)w0#E2w({{R*M08oA$e>+~%nbbPR2?2gU z)1^tquW=p3ER7?{3Wr=1xld26De!imHPy|`%ef0^e#nRF>|_CAW$bFo+JDjb-kYX8IM>P%w((LaavaxZ<7o zao{p)YK{PFG>uQVH5+edLX4w5ns|clJMR%`A`5j#W>;nGNj>YHc;Wo-6UXn{ENX+E zGg3}cdOdio9De=LXt22Z-X&Gqq-QnCzR!L?wcisTNT2@z`d47EwM#oyhCG!)j(%0h zzRrjL0IVJ;U;hBo-~RwQyH3@fRz|sNqpj@by(7?c2E2J zQ2zj^@n424^TSSr{{Zf;%8QX)W5%Dh`&#hS9dROY`PXYfkx%0;+0B)hsamk+r92AL zt#!0T5W4YE?V>_%t&DgToJUfiQlk~8mMV4?s9vS^6RRfb?tTv3A8c7H|(UWqd(%GK` zibgVKvOhVmnm*j&^1Nj+?JR1-zKgiH3)8P*UpfB(;yPDde#Th1^C1CpCq;3UEV#{g#V(FknGAOlsK(;M{`%Rc z-aaM4_N>|MUU_DSq-}%RwIM(?I82)KM0*O<6a};~?lazq)wJ7zkh=L|ayoO!Bg^3UWe^TCYto4nfIN=qo2>5*8!_=s2j1gp8=%K>Ab` z-IU8WCTlF9At>Jo9+|Ig$|+~t&&!G&leho~1JbA94y3nJlZtXc(~a!@T816R0-`c` zZmI?cWzKSHc_hPbLCF|29OKN0OOQr;_M;OLODU0uP zPVYi0cQK*?gOGFVX^ca&%u%=TdI8O7RFX0VGmnH+`E7)-RT$#28+JxOO}RMlSjI$v zWal7r!0B01d@=wOVY>lYSjD$@eEofE(D~{5hRQ z#IgJ4rH`Q_*$LCG5>{0qfcz&spJ7tz$t-$`86%SbWAKxMR=q1rT|+6nE`4~#Ol}`X zm&z}>LBRmgl#8fd+a=Omv*cOWgJP4ifXUz~fPK`8ePh^X_E~+tB zi)-yqP>_u*$dR|gKse-5%N_JO$o-PuY3*ZlZOaGQ*9SFI`$vv+vC>>de1^Cnx2t2N zS)w=TytqjRk#@%i`9O@uWyWJ@eGnx5J(wH_$MVTh3F* zILNMYs|435mf?db!;{*rV(!M)4=&#=F&veyJCs>^O$jxy@_nr7I=g^uZHN!B?qS9= zfnA=%QnkEH!7`skJRivOTs9*u)$1yiSu@=7DT3eKX;Ki^8DC8GtK#xykF-X36uLUc zi1oO%YgCq1+|I#OLBaQ-^sf_X`h?NL1Gt&gkgT}(#d4Xo!>B8*%*FO|7$>1Ue~_fd zQj*$0*3Qwoo*7OEHE-of%F+>d`ls34Z+usz>DLVn#n0_j;gwf*E5`9|mho>%9E0e; z-nc_vJg(A7A!jEfvB@Xaw_Dc(@funAc^^Z^#gA>Bq2wIs;f_HQQ8J?JT9E1K3@o^TEiYEyfuLmLH>Xw;s7wJfBNVw(<< z;E{?FX-3?df(xjn9}9**I$5n=yhwiTrJEz<1wvCuq+-u+oM#~MRlg8ux^BM$!KqrL z{{X;G1RmHlXunyIt0M_LF~`!hfn7^T%eAwB9R9R9q^`zMb|tm&SBG?)GjDCCK_Zt8 zB$6igVmfktJ-sTS_L<<@op~*#(w+h>)T+asyn7$;*G86RT;)OeF+b9Rl0f-qBRv2h zaZ-+XMpj$nO;PiM_(xVpA*>|?f7{Re)z?M)Dl+Jj&8XZM^$8=)Fn|KaPeT34$6?aC z9r7%S%^uJDwjML<&3UF?IdcT(Cm#!Xfn8GaB;#m;!jq+=7mu;ci)z&_Ws;dNnar~sx|50xVhrB4CL8#d%4KQHZEm80p8^WM7u0Q#5u?}u;n z+nB+<3%WMOL*u9Ps>g=>6R2EjkT$7nCB2~di$7M!Y<@z!JbbGhA1_B9Y)*60NAmjd zkLmAT#cd?)79}j%zyiL7zVOzOs-PEEQ8!@A@UR~-&+AC8e$1BA`U~A2=W+(zVVABw z0si#x^5G$6;>s-I(%MZA`?0$7jFJ9-I)@d}HH%3swR@X+RE@8|G_K;t*5w^p6&&VJ@5*F@q#5KVzN9j-;xCj66Q_7WFDi^iZNjUUY>wr zohlIV9B*UjAa=HHi{CR)&AMH)_Vk6^#Zy#+5Z5BZVZWWd2J&j`*yB-q}+Yd?m0G-wX#7K*!(y4#cii4 zOZ!$a0gSAD2jx-7tMNs#)BJ~P;iuCs8&ODhLY#nm)S8rD)5eBI$QbBj%yN z_pX89Zw_h?7@b{~1{oxFK9q-6(H`GhxRX$hI5x2;W9Vt8g?x22h2giEOWI^~81|-< zZZ{DU<0@wV0BD*W-kp0C_Rk|k#1m9>%gW5pvBrAwU9-ejRyxI-$@i=%U-rXdxY9uq zY7RFIfw;-z^`VV9FR=1;(*P0N&cv#-ob~?IaPT*b-@?f~t?i@Ck{qrW1_$fcr6zq# z$hs+RfF7MX{Hx2WcQA{I@EN%P^`fwd@?T@`5%~7{{r5w<)(zX05RiVSy(rVQ$u4zy zt|gXC+^VCywsDRFdmM4}r4vfdxHvx4t<{mYM(5;fKOA3@nbLKAR>w-WXzk_?ES!=% z8au#OB4v_h8T2k|j>$BLgsr3_b$8o{zDZTZ`ztL5sY(CyOsyvg+Y)Ft2xa=#MIE%TAI>^^0!9H`2FVL1qoOg}~`njwB<s2+oeY+IpO+wPN zXK6pJABM&GD6%E`q@*qg9R(3@;u)ck6(FuURXyZxr-tqCT6xWqLFYXye;q!<^8Wxu z%JW&4QJv&x)1?eAkCfP5!@ha?)pi+K)w3o5>`gJ#^?0qA7KlHw?@Ro39)?-JWt+nK z_2!v(y4FY7c`@}3^sb1$HMea(S>;Ddi1;wKRz8E)xW&G`96E=ZBLXmT06hn#HkVj! zYEkz<69aAyEzSmTgtj@?JVAe|$Yg&q7(v2Dt%VedOhiltt_Lm2&(5pf z4!BErrMJ4aRwUq-9D_yO7rbd=w{>`w^0~?SRHcpjVND0asWZx_%E)8YXzA|02F7wa zimt_SEg}&|@i6_@;EJC5?qL8j9h<*&VB(QLD26R+3x{pM?F5azvywUf)uq+zObARY zVDJCd%2eKOrtD?GUNVbAGJ#5RP|Twq{hJ!@St!)gJT zfC8Lny*B>G#qQ;zgC(|zPJxfsCd z+MNwPBPW=0>-;QoDlw$QW!xlUfahW9StUTaDYFue$oS7=oN-ETZG6Tc4CcC@-L1mo z?(pN(#t-wQy5)_GmaQZCP%{4h&@t`B4mGqgot*ywN7H<%jHiZLw8Y4~~=DETS7-N&pE2I6Tm9p^0fv2CucTB)`-~s%r znQ!>W9|-MTbxh=wvSi3{>*+>$ghWn8<@KNgvbN$5af4D?2W5V{N$*(*Yy&e6dGEzW z>QfozPeY2Bw$^_6HKgTNZhDpPSj18O1H9z?t5uU>7|8>gCSkhYc016L$FweckLy_& zbi-^Q@D3?V<8vuv*U)vVHjxdi_el-z{{SqgRoHNI`BN*e3~9`PP~0vKe;6nEQ!^!H z4S5aIcR`bi$asoO<27)P!!|KF+|$T2_*me6lx&)HfQZBQNI*TnAdjs8@ntJb20=2h z$i{0b$}~%BcWEu=b;!onIjp9%YGjh!1P2&DDuPK%`U(}5d$Fyp)VH#Z{7S}5a*?PLX4R!F7?N6Y7F&1 z%81{NwH3n+ht{I9gU9Q z@%-t>h&0VVT(d5$vE6`M%mbFkV_d%Bu5BmVASmc}bpHT7DI9q!V{+o{A5(ab#t>?D z_Ni}eZ01!vw}ZG4esm6r;f+FA67`~nB$zQ!Mle0=m}%Oii#C|c5SVWT#yKO3>RR`X zZml%v;z*Gr+78j!dVZA$j!|XfB{giL_>u0ktA~x*$6^8Ek;kf#LBssG=k)%xR=MI2 z^+5jscu?+6cT#w4-bmU-afRugwP=XaEEc+g`H3dLnTa!v++_SH}C2HI7_ zZaw*@5lbA*+(ZjV4qK`T^FnLhSUv!-i0P zbv2_~vXDSl>_MoO&St@IcAkLIap~nsw1AIcNZz(QY+(i6)UYkPG=@Ijl*-;qTia(d zNH?I`aC_9cbT;PA()^UPD01VfilE7KmY1@N7iPC7fZfNb_pV7(=;)2E%aQUepfUij z>`hm$ZdK)Sqk~>aDVEV?jFJx+Cz?xsx1|_BW7^-selN_^V~_0FB)tsZSGI`90h8h_ zgM*xV(nb=UvNsSajYrcYr2V4x ztNqR>6h|+`j)s=S8@d(%W7d;2^0@)d54obenT%ko5I^nXH8)6f?P!!r5>hfVTFEM| zIl&#MNs-}Jc2{orJZ6-(vl_YcAaDWf!vp%$t@JB@vdF5_;HsUy>DH3pcbYbjJHhyc z3*ilWO`2Rz#RpG~PAQ%3%r?4+o)a6P9ANboDSnw)e#;cP-Mo>kcNXZf58fh@YC4nH zv3qw0Cis*N*`+tPzj>EA;Pl6DYG|4xOQbx`%)|G6svHzul~c7yTmJx=H7)F5i3onD z98o$pxqD~kZ$$Q0AMZp>}v7N7o#)YZeWCnuZ3=(=b ztypxA6+x&mSwi4`@H|&E)YTp`tfzNXKJ=!>>PuO{f>ud0jH%$(_|+Sk-(OINYKYh{ zJ;ANoW#E|lMdWgs6SK&d>RqKYXLxwNyhHuC2j zZDEhrf+A~o32@AS^gThVk+pl7+aY22c-_uxM$l%vk7VK{jP)e+`C^(me`bHtN|NP+ z5fd{3)rsp{$8Z|P04c=tC*p7q_ zf6twEsC+4DYQOZhRv!-_`9L4k9%?t!n%x~z5elA2jy1vjxUP(IggPNON>16yzR}_T z095f4sGG~Tw2VTZ4tHa&IjYneEvE0t5yvS6aO{+)GY zbeT`W!wjcCtvI{8a!FOe@0u>+dlgc!UPUydei-?rvp(Q!Hph%r8p(Kh+)vO{LhTzM zoKVw>6~`2#bQo^aemNu7vVc%=Sz4GZ-J^sP`$j&+f9A0y5=awyRL5LUtiz^wt%R85 zam{s60JjMU_+$>s_yqTtk7Ed zjzS!oo9;e(zum^*J}w1$Whk>P=AVk5F43x(GeX{fmN_Kjig68_T0o`aY#N`#_ZCuL zd6z$c9G)u4;!SSCOG6Evumc~D6}da;WffhOt2l(Jz{pSx^FrR+1boVYkdyd^b5mKz zCEBQjV2tL3)aRB25lVM3=qo82KFx3qk!{J8w9%~M*NRF@2JI)R>*SC!qE zyJok7W>y3oW36c`*^?hVi>zxV&~x0^p_nO26$fF(2|lBCkOH584x~_aS5r?pc}ZdE zNUSY~O(bAo$BcS5GeqgI+(^J$p(>FTHYK;sxh1#b4F;oL^ns=*ML2Gm+h%?66 z>%pl@B9F177RuH9@<%iI4(gfXCZ@2yo%V-QA_LU$4Lp-gx4j_1GW~Gfsa5s7wo+na z$7+qmJaUsXTpEFk93iw_-=$-CnV}bZrkJf~nN}2}5 zskGIP!nZGHa3YX^q<5pmBU=<|o*S{SkTQm0-C46*>RO^&={{5tMz|mX7n-?hdVE@d zk&&`Tanh@Aqb=2y-K?YbilvplRJHDnv!7jFOLFcTsW{+bmbIjtiDcY8>74NSZW#&O zIme|*Hmw+pBSaPYXB}v%*c$zl=@Um1pDjY1eiOw7tm_KM0qg7qc?7_|;sGBz6H>MN z(cKCVX{j(?v`1~M%&mYoAnZ>y)I1%njY7eoPm2U@Q~R~Yq_Dh=NobpIs`E~~6|MgO zqiV6sHsKy{z>cD)n;$6Xd^tG1o!;gJz0+;rmu?3HpGvIwx*aas%*7Oer5tfc^^Y8J zEEc#C5_$Ecx?8rVGjBV|=nZn?@#P(}s(E6=G}tYCjrW)-*p8#?-o3oNiY_5g>N+v* zKfMjD+O@PBNHOEo)pRtn5UN;#&Pc9~9Eds4#`f+jfH1*d(*~84R${;~AI#Ie63RRH z+swxBa1VNQ7l*A326?1?nc)HYWYRgP=x9O9WiZb=WC>0I>DH{8O~kR@M%l(O+a{6CG*LmOJx0=B6df82xO{LKj@((cYMr1#{|c8)FY zJhmW)JW~xoGpZ_rN$p(HZuB~&5|M{R$jCLYwczr@*Wx_Ux^|x8rw#!^C! zjnuZ#%8zv7S-iOz7aa~UkxY^wZ_a?Vh&95u0aNiddQ*uciX`05tLc+Z7Rg8%pi|qQ zQNgP3i*!jf4Jp#rNfJf)!h^#fLsnM1fC6&I9*Su`v#%wEv(7Cgc*k;f`+5K?qxnlrW0jt|bHnn~;#Zmn3PksR(H=TGNTYWLQcI+yx|sFEj_0%%<4{{YEP z<@r#P>Xyumg;jLOdYfoE<_KBB?W6wj_{Eana1Y)?pn|(f&bhkQO zs<%}k@JKgbAgHu`J;~7N4VHx13$C?f$!3)p-Zx9??)Qe zw7vHw{Lqjd+2m3yy*GSJZDc-RAAx`%im>Z9JNFWx4CDdZ+L0{h%s9^-XvR*4lu<{y zmN7de!~s|w7DKdyL&*v;&ABcA0BaA3Q|}qsg6Vw_z?0#BpRHDxgOEr*wa}fd9L-bM z?@F~6@d=z}W(WTOZ5H5TiW5z_GeQxM?GR%=-nA@~s_~qfG}%i@8p|F=Xh%!~QcE`C zKs5t5T4fS$NYYI06_v6nkoVd;)>H6eau-N&DkgGQj?wBtaJQ11?SSy@6OvE{C{bsPo+a|hDm}auF zuZ|JyoTTW`*hb_lv$*O&I0l^9+O$DPj4WfIUV^f+t0HkN33CPIy2mHtRlvZ;D!=#f zrrxs#059^atf?}g(s+d56?ctxsN)^z7rpau12@3Ea4Rb-B#at0naqMKb|^Ykt4Uub z(b{KLk(8dbm6Wm?Cp);bN7iTEEO5ZiN`(cD3#)j1EP?H&j%djIObU_w>nkc=#zZmc zMmTpg@u>6_;#~_e!Gf~-;vbd(HoeQGC3c{GrDltP!$tn1hW7ntaSy@Vqc(X-phhnPk^*JVl zn^1-_S(O1l!@>OPD=P~iX?1A8&AcBMc5Ju&RexEQ<57x4n6j^6q;vjzR#sIaz?Fy} zM~!16_J%{w?YIJg8U_5y&XGTsKYwY*@~o_@sWD|0M^XDb&~%$iXV#)Cm6U42ofRwZ3~6ApUFv{21o5?Sen*<;-XO4DB21gxX_4D%6n;`fB+-G~Fy^U@r*;n+HIN< literal 0 HcmV?d00001 diff --git a/cool-admin-java/src/main/resources/cool/captcha/bgimages/e.jpg b/cool-admin-java/src/main/resources/cool/captcha/bgimages/e.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b5e22e369bd9b6c1218541a8a0ee2096beeaa3fa GIT binary patch literal 53838 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%0DH=(8NZ+oB|D!{>YPWu8ch&jOQX1dJ%KIw z^M`J#9Z+u9xz(_npPrqt?&XT&b0rES$laF4^NNF*9KFnXXx~TJ=Brwb92AnuDaOY0o5GKC`SN;q>t;j2SBKY06{i4HXXIF_jmjIdhc^Jg#{6G>!{xPfOgkw;j2wyZ8#Qx zL@j#(>-c=VZDY0uBQZoD0s(PYCDsCJpuLHcKhw=p{bkBd4czUJF5Qx^u7KVX@z6J6IQ@iFOH$|TtAyd;J7h&+c*Yw9~%;@$W4wia~h(Vl)wuBA$SDN31bCdyl2 zdC`0Qph>=iPsRXc%-1fIqM0f}974Y}QqPnffj1_=i-T>h4TpInl{2$X#%*uQiX7PV z$t$@Xy8s8_Yy8pYa*W1BT3wQ&1!yiW(Z0TKi@$|_D`mVvl|vJe#3_X&B`Yc(6_)Wa zH5LBYpS&QXpNzpDM|EGJ35=c0EdknUfT$_S*`T9*-&D*E2x2g{^6( z+`XNZN_*)jG7{^kX~e0O9Uo6BR3ex)fb#!r!I#O%IPFhN41>Ig|rr?Wb29ls;W zm{s_XF~Xn2q6wVZ9C?YTei$Hv>MTfMyKm&!vJNM4bJ`Euf{(?|W}ZKL8)T1adVdcp zP~+xm_YUfHtglp}RH`tHm^HksIt5~_Hj!Q@Sk-Dg9KRY1i0RcSD1jl^GHHX0p2J*A z_GXVj&Pd6*%A3Oc)+0Ack)AUA7Bf~)o7a-5luYjimue+GQj+vmV9(0sd1kbTuhe1~ zbye0V^siI?$r*Eo9?vx_`NFAHXJ6w5aoD-vIoC4{N_+nR+g7UTeq3C~l%&7;i*yI& zs#9|4u?aLPx?ZQK@}yx|?X#8Xng0NVRY<6Y#O|~NNRWplc#d|RN{2L4e;`jx^AWw$ zb{J;OfilRa^j)n)aY@~Ckr^VEg0P>`d zuq;5=UfSZefe^r4RWlN@0JRH0?B5@vGji~_hbWGy$R!b_;H4)`2_Y;};D7_%dhRiC zzmx0RQe}UKakxLkg10OAUIP)RlPW}YDw$cdmf*cGo#j#E1jc-R(k^Y@I{SZc>4(zh za->I&ww9;lDRFgWXmaXGk*3N?zs%T+;tJ%-q^!4@>2-Q+uLmhI`m%_b_Tw0*HE<8E0m+dtb&7a%0h`cZ`-x?&<(Lay_oodAbM zd1eew=Qf4uWWb8*X11Yff)64MK8Mjwf7m_sBQU!}JUPyCkSG5DX>uj0PE~6O z03_yIyhrv=Gy`kd;2Z>=Z#OnG5sTRK@`dn*sO%~RX|GA){b6A+g*v(bp;^IlQFIjn*pycfW)kqGW0eStPlz}bqqrr< zE=~0FSvT~uzxl}@{{XDxlC)+i^dz6ScgGk109ld$0M5Vv0MU<_wsGey7_nKO8Zujr z?uS%2*b!^%r^EMO1;}yUtBQP{q>G(42YdQ|*S0emjK*McYZGI{ascXdT`5)C(PNiU z@wT9w>HNgdnQmL!J2kbPR!)~sIMYuz&n06ILu}o zxzq-lgyguA-ww8rrvuwtVaxaa{{UPintkV447)1*V_*gMMenV()kD_%{4iHOvpMkJ zPF=wzD?907{CD|Z9cZpJi7He70Gz2!sPmujNE)ib+uVG)Y;@a5pCY`lM=F;SQ_vu) z%1}1BNe2h>s*F)7y;tRPAtRJG*s8+EeJ`LIcIK{x zwIZ_Oq{^nkjQM3{FDTw`QNh(D>7qfnL9sRiwi2>rO@`FS?MPRKOocF}N%KfcN-gr8 zcCgb!aCPs8PK%x>PEUhRVVb+Ep0u_VE+BQ7p=cl;d)R~nYj(A-=!?&par#uWvg2J? z^3>#rlakqOE`=eU%h@g?J!khY-U!#$CrJG|J-fNdg!Hp#Z z1x%^|Qui8I0>s|6Z_Hu3nFbX>N@XxQQZHtj*2y;9pNaEo02lab5|@;WiGq_*Q!tTH zC79I*!1^wqSHI?SBpp7opg^J!bmmp`8sTY`;yqd(8WWBG0BI@2%A|)hgI8&@`OFrM zzus|M9Yo&tB|71EE|POSJ!yv($o1%CyI7%2Ki=*-FX1W--+r|(EgA|0 z0Z?m0wYT;-qUNR}rY~s(GGfJ0iMNK2O8vk#eX$&Bv|7a?qbiY8i6RwVARLfnlh9ZM z52*hD%h&3xO@+G)V$QfdljHEmhm_^JAFWrO$(cHNz1(_2c~MU~T#9j5QvU$twi(Qe zKAoJS#iwSBzY=9@Dw{x^Qm2BnDK@$mqBS8x+{ErKZ+l`vRBB17w-J{j7_BnZ=CYA> zIO<0*LQ`-QR7HY7H}`#TB7Y{1ln9Ur1saNm=GVVbd+ca&V(?(dr6vr_^y;N16cAw& ztk)QbiFH}?lFMwg0k|N+TB@~l{!-&13!Z(Z=3UTtB8HrgT*t1D0~_Zw}e-`taJ1x3y7IQkOQ z0^-TAO^NxPejnEOWP>#l63~!KGEL3s#p&wcGYnT`e}@31>PlHe+$dhG?d!Lu6%@&J zXw%av#=6fn%<4z%D4TQG+}_5(d~iLY^ODyk>17h0bxy6Zryx3k>%D-z?SA+xrNhj1 zi7t3ZEwG~JIvjPLvPd`3CsLJa4=}dY!>K~ZH7N`v)~AIPI;A?qSltj3H38$g$EKQV z@WVWmb1<~RAk~Zd0aJfny5KOCF-El>l_HksYz2p>f&j$O~h54y(= z_F8DQ7G%VO$hgght*4PLSX$a{4g2ZoY$R&28>B)^cnq+F6VNMa#m70U0e8@gD#y1n zyIA2}m)l%AG{WZSVYH6gEqvPiH7D;o>TvOvLNH2D_8|L|e%tHGb2?9E3LbzE0H~`9 zF>1Tg#Nghh(U}%<1^&7lfDJ|Yn*i)Vy|z7wCkWaFE9eR{5kGBjI&W_&eZsv(t#f@X z+;_sZvpeXTQmQ@B>}IXp_>NF?xwr#s{I>%Hv)nEvwWiik1ZZt*ceVX?zw^Pf3`bXQ zKxM6Mo0SXRug<0_R{shXD)`FpxnzgF*X$J;pJYx=ZQXQDS~Kz5f8vTld=o%DK-m z@9X$~)8T@~)6y)uYzl}r?Q3bLZ%x0R4Aj1IRqJE>hw$6i5@l2(D_!*{8uc5v=YnWV zL?tLuPNaYdE-U*#vyYg}W&%i+;$Hv@06BEqOAGh(>`&c}rJT1i-cOC4M#U%J&+I|K z)+TsX);&^een9u_^R>P^U>j2Uk15~Sx~->g+&>?UuqtIVpcy~!0RZWymhaetHQ!-` z)6uzB6?@p<(`~ob+FxCJdf)~#1&|%N=>n`pAD;LFHeGinslWZU`e9njop+G4 zsK3mc+*hrs^D4l6IeXsP;n00t zk$NN&IX{QrYy5F0Z6R^c2y&&f`vG2Jo_pYgneY=pNTb@}>y9w$F&S-0++2S3dXZuO z04=a^m)S~C<64(O(0%}+M*55HpY^@Q5tCN7(;Z0nx@rfuma*5@VXh2ltCb)rqqU0F z@@(}D&v9h-x2`wt{e#6N^a7?O?RpdD_#q8tDh1L*Y+i+{<%svk8plQ&+C8HNEpPlv z`3d=p5vktyzTziS8Y+B{bzmW@o7+xfrrx688*h9*Tyd$IwRNZn)elQU(tSA)ppk72 z>{3V_^cL3*N*HaSF>QX0eMApSv=R@e?O0!3F-GSTKg6?0@y$EBmXBqd6)@|)jmX&FW= zu(5JfLiM+QFw)*{;(qI4)Xq7Ir^K9>#7yH@ixCs4)jWd)%z;njOPvO4)UPsy>=od( zUgL5vyeY2RTpr8)Pwty+_%kYC&&tJ)ve8$gvPiug9jG0NaniVKqeonG$b<(}sL{Yj zaukawYuKcdeRTQT4$liBH<=_?_-Q6zP2As?sw$*7ZTYTZ%Q4-pQ=8WM$)?Gh58_<{ z#@53t9nO3RdZlq)2mL$L(xg~yTw$t^ z!l2ER)3MbCLsAQGL^lP6whKlrkL>dGPt0k2ZrjRnMJQ21$UKVE-X3AKy$&DWX?(K| zm7N;Rv}Ox=Z;7;+S=xkqMKxBEr(&gSTv_%+rVy}p8YJtd zpu-Z{P>gP zZJ~V(-$Qe2dXl+h%A;jjoVil9LJ3+!mo)_F9H_*By|BGJzS}d(rx<}SR|QM}9uNbN zeD@8@o(-LnnFF1_BV|$?@ZhJma;1+cUyGM-+{Y66dQyO{_X|Tg_Q}K}`Np9e# zJB6S-**7BkcLZD3-y9}gnzvR~uz8J#ZH9w;;pneW;z?(gH@pB*ApNU%&}**x{IJ?d zrAiKwsO11@eSomo>$m#jRps;PQiL)z1L5A3=j;187YMosN_$~EXGma$p!s(ncKT_1 zUtgBk_=>c*A42bLVtqHi^V4y0e_LQf^tpXi{%jYh^B($dfv_^ZDr|Nyw&AzJ%~BLnpp)hx zgxh!XEC32r4UU%73;y%-({ZL0S$?t@lJiPfNaaWb`?nij+v}#Ez~NI@ z%2SsaPomuJqnS3iH@H2m+t7Le>xSXT@*^q5tbp?h2>edFZ`kezp9~^q2+QY5kf7|r zslC$Gp%mYnR@iJ_UBtNzti19{z=))<4v-0A96MQ>qk3Y%V6h8`wZ<|(lBE$(e? z2A>h3u(k!}EayKeLXBU7>61)~hVn_Z*@^o3XY`y$Rn7aQZxhOe@z5XxgPAP zGy$p*0Vi@nOZ2~=(BNdm-1Pip#GQz<7*qhF))oY|#=OOzg3vfu`9iAI9vtxVAyi#r zW@_PXcaNAjbHoTWg7$05w0eYvNUvpDWmte@Wemc%OsRBr5+Iehpbs`KA18iLsvc#_ z4p4JVQ|M(i5%`XpqAyMjC!P0D)5MOnP-O!c_EO!r7dG;1l(=^)m7S;)Bk50pRgW!u zkI)slYmWNg{+ON%&ghRznK;_aQlF@@G&;w5X zi4@7NE!gihaTVZQa_f(Ct7^8y3lME#Y%$Ex>h)yFa+u3Af)b|}6j(?|1I)Dgrq>{i z$k<{(Gwl%;d}g3k9*)yj0kk|t?5i7%h)*)@a(BJAIFMX7;`Ua{jXyr9^d}j045_1V zZGC|^*4tR$ea~?-vNK{N6A|=AN@5ZPL$Lyt2V&k$k5+J>#90WOI|5!7c7qcxgB2%P z8i<6#uTssv&eX$l<{9^e5GT%ih+R_b#F&2sQeFr?imJilRYn2|6TP6Jh~9zIz-LlaLyB1-Tmar>*N> zYPaIY#T=hAhnFEU{q8y;Xk0Xa$pA6bL)frpZ!Ap@YMv1{KEF1x7nLOrzTgPIC>-Q~ zpHM*D{OztF)>~n^9eBf>zN=3yaOJ=xj-xV^KqAL$ALE7gWA>w+nII{d?k-#5Hf;`S zph&R<+?`GIJ*);JUSQ7hr@kdHlL^GEsYVM(k?oRm-T=E`z7WDXE8HQM7Xiawg{l~rtL!2cE zASs(|O>s(kd$!{VNik&yr2c6#-ZDp^2g+@*y~)?{*7yvFvbodwoZb7Rum1qpx0~hP z8H~eT5%4L<@|$gI@RK~Cn}|WZFK^Ob>Am;+yW@mN65m6s@Uu0!8V{Kp{_k6DjK*Uz zm<-!*w57J>NxZit>9H2Iuc^Pw{#^@BIiqnVk~KFL({97m<1v`bW;4Rd{{X?w{r>>z zgBomEePd{kjR)y|{Zo5;C4rLCdeMjPdXY2N52=lFG;`T~Hh}X6=8G!K=L{x_?bq3j= z4l=+Ttpubv6fIFy*zJ9=n5tx|m2nNopOfWOW4#=P#LT;2TdKGg2~D*&y@B6*>M+$* zJ)QFF>V8@>g?^JI#3;DrM(Z@jnJ0BAnLkrx-oQ9{bsg=D#$%*#J1}&Lq?1m#0*{&} z{a=<4C)s$mfb1zbnrU&xEiL^ECT~vW<)0M}&)r_=<+vl>&|vDDz&eZvn^T!zGP0ED z2ljfu`NF#oUok$N^|si|W+P?E1x3I=jMW_mK1TTun8MOVO{h`ZX;P>)YD+Dsaw4Nk zsljba3BAzl;85bqK|F~eR=R+&IN7tJU+|AzvPaaL`g_;0*4Gvr_ul!8!<>)-K!5>Z zRvgoS5xGuzrvw?u6hws(#J7r^!bj$vbEhTz-wkdp zara~Fh_8l{mf}g|Lis+eu97^uD#+P7-uh~9>x{-=v8JY@-M9H~?}!rwgh@B~NB&p< zxYELp=BwCy_U0c0bAb%SmRw|rvhTN-R9kN?uc!02n&UB;`6wDG{{XE0la8}T@Zp{G zr2ViWR9SldXrsTpHQd_!YwPhow!v&;E;O6?OOL~1blb5bL9eB;n9OQ!e9zw+Ncrvm z0O~NlZbVs-)f@s;(h8CjqKN>TC(x1x{mt*T6A~#Q1iRs8{b!f9$I{#Dt|+i8WROv@3YvKVo@NpVF@ z`@@i2_PM`(K7h8H~hvrKrorALu;aZn!NcWLD)P(5WNs ziucT>Wmhv#mbTw?q1RY!HM&`8)pYI+t_i)b-?rlki9%U;HQ^@Ql0E^Kh8>6ES-aVn8al`d3TyzH7GPMZtps;jLsV=Fiw3RKx|~QQ1L1p}v`NroF_@a4oDN|?{V>Y}p6euByPCazVTm15 zLtI7nXOz=GNU!jBF}X4%b$+=~%ejPeEyN$$i!BOTuj_n6m!Y^4$z>B?=R*&;I(=@E zolzW|hf+b)Prqy9F_;kqmyAFAs{8){Z+hT29n?ybQ{5pFcO%_?-!wDp=fj7?hh`&X}@eZ*%oT56x`2~Bq8{*>rq~t3RBklx0zE##3$3J$50){ zo||Sf2eNPd!c=Ti5yr>F1xEh3L!1CYk}N3|4NEyqxqi5Qb4?O$S0ivki;C+mWaufpsZkeLf#NW-}7xznFjO$7yfpFaD)} zj@GM9rcpf;FXRP*ok>D!V<$J5vYC zWFkLB=-*n}JfpBYw$O|3{H^fA7n-u~D!Rfc`oimkYjI3g@vQohlOXTbIb2j3u~>z%1QMn(T@@G94>OLq)j7@DP<93We-%b8GEm z^J1$tY~z=pu9s1Arya&gWlgEBgncwBQU&|!NbCsTY{p_~v=9FP82HVwEc3dXhFbzP`HQ{o!{EAm^z}q1$+w4xyH; zEvksH+<{}?LJ0K6V==Y`OH4(YjIP~U{6vR(7Z$BCIP*uaHB&F-+E#0i4rNHmsMG1y zCh3rRjKYaglH7RGXRgF4Xj`O{u9n0^v&kLtB%3bHZEM>nupBXNYp*B+N`1;Yp{E0VyC9 oo>8be3yp@iy@AGKF_@8pyf&1azNtw);w?yj>PPDT0JD$(*)n0@TL1t6 literal 0 HcmV?d00001 diff --git a/cool-admin-java/src/main/resources/cool/captcha/bgimages/h.jpg b/cool-admin-java/src/main/resources/cool/captcha/bgimages/h.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2326c881fab1e63a3f8e88ed31b65ecf60886749 GIT binary patch literal 80101 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 Aod5s; literal 0 HcmV?d00001 diff --git a/cool-admin-java/src/main/resources/cool/captcha/bgimages/j.jpg b/cool-admin-java/src/main/resources/cool/captcha/bgimages/j.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8f9056f4b6d30347c72dc16bd6f357eaf06a2384 GIT binary patch literal 144883 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%0D!50 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�ZNKpeE@N7nEfHk0?5l zShlUZK0N``cdKb$G#bQuW3W7BLXT9BOr|bjO())}EYg{6OhS;&}dr}=P`k_au*Xb-=)vIn5EY=fTQbWQt&P z9u)vo^w*|Rr_>W3TH}b-c4RXBBB8+3lMGU~7Rm-N%GZ^)I&hq7dN-@47}v(}E_o7+ z+P%e5p}XUhe958Isg#PHY$)rmy`t0-an)J);?Iz$PSUB-5|9#vk`i6Kp_smx7u4UT zD@tV|LOoeiu}O#!y%**Qbq~U97+X)}jx|@($W%D-;lzU&Dmoz3^g~6#!^ESE@T4dc zj==3LKPSabVD_}#d(RLfyye*)t#nVlZIDx)0mdj~3~8o=Jt3t+M-!=Ui-0KLtmDcQ zpbE7Z^5{Uw=uWzl{d+ClADEl<-L2In?<`BIixx{ECo$mEU@DXE5wG}5t|3^{JpnqM zq|%Sxpt~OMIeYwQ{-@`O9i>TqqrkjLCYJ&nv~_?S4=gJ%^?UtBJ!29EPh5SPx8R5D!z=U57iwb<`XKsK-O7*BSZ! zy|cBmETEWK+!hSZHVNC1e^>U$##+iEDt2mEC16V_M5v(ODHd@4ob|UpP7f}C9314F z4G8FQkFb&WZ4&pXLX%V88_SK7vrl9zBsb909dtk^UYt7h8+e(ms)-U-W)Vkw z5p0qe>etlid;41!7iCnLdCK&7lW9H}%EK`nTHrOba$k0P7dV2=+bUIFs{wNwrz^!e zwM=w_%i%y*EOZ%jRFkHe*#}vq@zbkkiI#%^HA(j%YDS)&dTPqw+oyIM8R=!dU=6pOdJZi!+s)AY0La<)nc5Vp zrO+mb5mcnG^0T;pt>}4az2h~(9pq0HNgxpAE?U;>b{Bna`(h^3AQJ0p@R;Cf3DA9E z!aUgR*IwTo?6!!>T3mTaTy`1qyjlHwfS)Q7dW@YjjOSg2yKBp*I^uantne!xbmgFA zdUWmAUzXoPPPWsf<%ZilEIj6VCBuYk+fqNFotviXbn2WKKpe&-JfR_p1wdb)>!83T z)8ooaArl~osai>E7fV=NKA+PPKX!Z8b9J;@)Em|{jTP6Z$mbJ)46>xB z9kJJ@(ZAY@d3Rkl+=EJXT$vR3^l8yx7SEDW8zetX&X_JY%3ouR0mi#P)-H>M=|0NM zu;jH-srUOg4LrtjlLnyG!vd((=a%fJfqc{B)0&XmrF!t7fO=IN!t43Zz9sU;xSdW zE-QMxC&6Xaz@=5FHBkI%O(pW*237)+TvKiiFV-bNTIYmZwHk4}RUwQxg4 zUb8d?(>iP#YDGE}YLILtw7{fDGg@sZ9JC<;DdI*62g1F#3PlojhKibIJn9NINlNn% zF(E=_PMAy30@rW|2z?kx{5ra+ncT z@d0sS>7<2>p`qD)I5^j9P*t&SUt8mmeA21(`lZhb3<`9*tn!+r9?hW_iAavyZGgLi z>_IFsZ1EMi(i>Mg*(y_)BHHq(S)0CoJ*h>e(;!r8$u((D(ZQ#xodJK{WYi-xOOI7* z3&T;FMqFHlB?;8$YX%=~^%Zc`Dt#qJEZ_-BR6ONi*+iEvd6M97vBXMm1j1cyXk3Y! zh@e!95FwPau@=;g$kS{w4^!+7z(t|4Z8E}c>fAbgsS-nl2D;Q1>I#0Pbyl@gi4|b6 z0+@JG6qKMPXDUdZuhb)t%_MMHo z#pee8q}?^y@g_4}x+;&tZjlzY)L2%$Sy5f3itEpi({n_ix_MIkqupg*xS#gzYE-$* z*6KA1O%k;RlGQ>Rv!r;)Oi?F8Fx-PCI2m#~zUmSl2~t#+!qyH_HeKR4-X@brs4gm^ zPR_>fXMFj9h*SVbE?6WuZ5i|gVsa>J@w0|zj+DWbUPQYwPEniG<}B~11AIwp$)VFJ zPgJUpM5WVWHdi)m*AmP|7&$`J`i@5eiqZ(~a65yvU0a*B-o@)%qOQ`ms#I!CxiV6# zwKz^duDe%FN)qj=G#Q7sx`$oIIQMXI!F zSB-IDN0kxPL{&b7l_gwG_>>Xn8xE$TB-Gq!B&-yGq!+e;me`gA`jX7U3AI$yWYnmV zG*GyvDME-y_}#8H0FkNrUk**JOEjug%XL~7jS{0!i*eNGFfQoSk9o1Xs%16g$BA5{ zS|}nU2PLxO)mb+sIb64$W1Ue#s3j`fsmO(K)tHq8kdRbdc~~%Vd2BUu&unrejLP84 zt~}S-(9}YeDv$|CQx{Vg8L!I)cS84w)Wy@?gKqO&ExB+eyDi%L*5n$AJ`Sx>q*}D( z)tpV6s-aLtJ>yT9^Nk?5^mr9| zg%99pNdc5JORcl<@n$;EB{Q1;u z)@ssZ5X>l&V-*Hz5h<{i8$?!{L^s}l-7!n6M(gYkrdpKpp0q7M znJPb7YjKJ!#3(Pn8@$t?QbwB-M)rE#JUaY4jvnNyxOYr7YB1jL4H9HmY^BqB9q9df>>F{P-4c>bQ?*g;ByT90{+U=Ph(3_B}kW3gTtAG@WjV;E<4JMOvFgzvaL`r|KuB1ekl!0~QZ$$`8 z${a~}q=%dXL6DNAXaVW~ILA-r5q+Y!18e(5S?y6~R~)2W)}?BnbME%=g9WOUYRbIm z6GMzv5)>FNL?eN#p4$aTlL(}^Likj2GoZX7H)XL2t6FB7xG_O8{C&!--hTd{{V7tHD$_`({0is$c-0xZL5h-&hV@x zJx{vILe%0oiMbY226y)Ch8476_I%tGFMpP^JDR!W#k04EZo!%@o0e@g(RSQ5>r$6V zL|a>UG3qOBuU)5E(W{keG8zn{TgXbiH#CV6qp*o&IHW^9DM0|0zLxMj zz4?k61Jr@0Hl{yl8#1#;_JCIO_fwhhfa|9c^@$OvE^% zDM$ezbYYj@oCP5nh?k8#sqwdj*skkmN>Z5F9qM7a~$tk369 zt6FZcM<$Iawx-9Yw6|JnH9bhG!Ir9Tc-z|DOq5<*y1Xh-VpeK%q|&7}`>2OCapf#Y zq0OZ=OszDU^DQMAq_rK`?=%rnr@Gt)ls9{u{{YTD)z0z;X*3( z`N@SPnq&%t%p$`MzZQ77P08?gXb@1@A*SffyMF$kzQgQGM=Dc=avcKTnE@N|_!@HTq;@Pl0gJ8;a{R zd)=}_iD3}yH3)McR4uvuP=v-Dew?8xeUQH>E&XBFXgjpt6lsNTytZuTYIn66%m@?m&R!E-=DF#7JTojYwy< z-~rd=*A0{|GKvCdwS;AyV-6aWH6bo;ZE!7agyA3gRiZfy+Cl{O;RX1MeWf1UIVG^^ z8ht_u>7diOJ2#(`QXhr(nWm~@1I*2%RhaSTq@NO4P-i1S;kX8I)H-xMq+jJqgE{@{ zS&I?4nw1Th(qAo3Wh+Q^Xl2AAQbTSyriw%BYYJ)LSYCK_W4|Z6;xDyDiy6szh$GY~ zMV^`BM1>BY@{n`WBRg&VHh6#F^5uiLmx!~M;_@UZ-RxgSeq8ZfL{OgM-vaEIu@;=U zn0c-k8xVN`^K5!Qa+RuiEf)atpy)tI%0TE3Zlw44jk+~MnITC_v4AJaH5uU_S32iE zf2O-TQK@jbepGVP<>4Nw2>=t4ag1>F!3p^6F{*ngaH$|*9WXzyOnkZ>wN@VxMT;#A z!5(;PT1##LXJgBd7JgR4x_d8zBE#=;ug>?=6VeL92FzuAMY*_`a^I6U2OG|+dz=rQZ)Huy1(I&FqETA>jjFkp3X z+5kQ6duhHH&t_aIl_6}N^dx5Th9Ci}I0oBapG1T!T`Zwx-X0OtAQSeIGIh={Pfc;$ zzFo5JN|j$w<(UK6($w?8n>obACf9Xr!nUj-Zi`UcEs* zv(RmTPt;2hceRzzqXEow+tz%?2Jpa?DDL4Tzz*z$lFZ+Sb9Vm#d?p~!uz(aWKm>u) zAOWVQp$8ofG4|%iaixa=01`4rG$#im9}MY_yFIqex>VgkMeXWI4|LyaTj+7>MvFj1 zyfmQ&Ne;wm@d0DLy8Rr!8MYyUg#a^@ka9Dr{=GZ))NQ&cgsC`A4oBbVos?1xIE^5! zQ4*Y|iv%7Nl>(xiXIx~B4x>5Pd`N9Nq)2Vn|4k{HC0SziiQ#Zunx6nU7TVrP_@KOFSH*KSCwKHyPlqOb{15GSrN(~-$8iZZ-$bQvS+jAI%29{T;ea&DB% zV68|bj`=-1Y5*Gb`SjQ)ijgsjj=ez#ZOUz5xePR!F3KIVS!=(TK4Z{SnwpkTeHQz483? z8*kwFev`TDu6S|q)9>$-x1%0fGo~9jXMG7Ea|2Dc>$WAzOVr^+D$G@DyY5nTCzwAj zxE3Uim>T~8m%q&Yzi-EAJMF0;8Wo~CfpHEa*Q_;YGpN*@{Kv%YHNYp#0!Pe~kLCWK zX3%fjP#?|9YuEFpIQ7Tqgb|%Fj=9t0*JFG%gr>J7q_Ak4bsIAs2|C+cPMD1~3SJ?O z2?`!xkR`pfeq6A~dpt_;``NbojwDq&AKq;v?KsFEkH*(I!}pKgKm4P$N^U5B`dhPg z$LZoZXuIm}%&4G2DdIb<0CAQsvHP z4|@O|x(5yGjXA^jkKg|LXFWf>ufP5NKgZDRzlHdIAO8R@+O98=M;*V0J_8?k**te{ z06MVMJGb=tVrPh+{t@yWI(k35?~F^RDj6jF{{RmE0LQ0&q8GO(vvnWZr`gi`-8AWG zrPONi*{E9;-VSQ0H)SQy8$qg}kTU-Ohn(AC#&LzVwdW&gY}{Q30>GF1;LB$cN_r~_!C8_gf#(lRRLH__XE5(tX_yCjD;{2dK&G9#h zG8M|26BQ?IJEwd!M%!t17H$a6Q*YH(godTj0Jvf@hU;x%>KEyuL?rzIcW4{BdKGeg z!3NB)Zxzu?;Hg!hM&2bxi2WKPklJOR0V?LG{{Y@7#07*$_x5Ln3_FrEJz0^P{^``F z;VRMK!-kuT&Jq&fjU2tkHur=pJ~CRJ8hDJ5N>rei4iZuefHfT+`d=R-Qe`2w+H3o} zA%^3xIOC7tVXiUGhdvohNX~A!M zE>NSsKRY*>X;PR&uQJsh&yi2PYmT&*V@gVjpffNoJEBnVYIX?V0pOaIG=(YRo%GpT ziLm!&au3a`lBHd$(q`M1>mK^>_Z7iWsPW@I@`ZG5Dpxq9l-yKHhc`~XH!PXTqyc9&hB#wK*mX2|wx*eJO9(Bv? z{{Xz(gK|F7)D=^2E#FjN#kZcON0R-UantJTI_COTw&D+u9b%}{nz zZwm5VE}u}kE_#d@)k@(^T2QFX@G491G~%MOOq4%Z)E3LHAz1_ij=+j_TsWQ_m@Y$Xpu36vtXfY%=Q*pO) z*wAKs!W`MW;vc z$NvC`bLo$*rp8G6m7`H?^#cSQMmCAQ%hhe+Ul%nCa@&Q2ChECwtCF2hX1gvbV^FE} zX~JhBeR}qH6sF-Vwbbfqp;1S^>mKb&q>$p(wdDI(`yJDLkgU&UxU^@z?3&dkxnp1V zN4wSHE^Fb`et$Dos1<<;ZVsv6P})jOpl1y zW2z-V*fQI7hdDAMHr%!y)bP6zXq3{i@LNe5V2;}Dt$HzyA;E$&m5o9D+Bf6;w7r5Y|-T@=JUhM@Q7M5oRUa!%;%{YI&AH( z-h&|ksX7pNun9d5FgxSdu^QuOJNY@U72W>H_6nuRQJ-!KrL{RoSVH_w9&^k(0*-*G zh7z1>p*T1>+F(6+!-sNHZQ_Y<&8bCpWJSZLt#DvMYzzsrxPnr*Rgi!I3s!@n%S=i2 zrdATW#W5+dI%o^-#BMGxkDmNT!?c-7tzK3o6#+0Om);zSasu~zw=r$csoOT?Iv6Qv z6?u!C1dUQPQOve$SUAQo6mkZgd*tl@0Jyv| z1FPZVA6o;+k~73kzPRd(nt8V)78>JxXRkQ6gMcoJ*y^bRSs&0j4?+ zO@Z+oDT&E6#Dx(;A_7#4ok2;nF}QJX!ME1}p~}h8<<_YhdSs!-Po89D9nf%dn>b@( zv3J?=r7g1UMzD1HMMZp!=j%rpI-K|DMl=Jt*pBg+N2F5RmtC#Fpi|Q0L35`lDYsqb zp-sU{1cK?7l(?-k!^r~#sO-hwyYOnqwQqaPrs7I=lSh>*kxZEPgJPvuV4^%IvZoK! z!CS6=n9$FNNJ~JCNso8JF8iv-iFIAIW)XT;snpoRnzd6YHtDDaWtM3$Nx`Sl*mO#X zG?J->3t7lc%$yu#r{&!eWI~O|c!xqP9R3vd6B~7lZBf*zSiAHNE zqyhj9l%8kw!}CVGtSjzP)k>4hg)Xr=mu69BMzb23~>>a21#xkc}hxw0K*)W2Gk2-N(EFby%^+~Al^%`vnPq-=cN;71eB!ZHbdOUloi0!2QbE_xNcYdIOH)kY&ILY|wZp;WkOwCK^? zbtS0O6-GzCTVy)ooZ{j#w{;%e-o{ZEN4IE}6=QX;)Sx#y+NV@Ed2B*r|mwnHDk|2n|J%lkU|l>XJUGAzvMr zW@J-c;tA>6tlDKIBE;@Wj!;&WjHM|K?YICIYiw~;(A8d>saB?7P{@~)j8&U0vZR4! zF|pOOz4gU`NvrPrc$BEu6{jYbE+QloMY!lr&{nwfP=_5vXmwgT%=i)#?+~a`F(L}COt<*TDlBQb z)R%>dgft~BK`AQ$IRU_6&8xM60kGxTk6#w`20f{3+3+p1BB^}MuFn-Jve(60 zt0k*$)>5lg)>`HAYf5!SD`6}Wpo7O+`{Uj&`FB0Nm=bSzGFU*UimNr{RLq)g@ZqxP zfa?@Hfj}w9P}*^8T_H&dqbD*51*4ai+4lFmx5;rvw;^sS`j2cTsZD05bwRuwrqW?h z(J5b?GFznEmZ^3{cw3@Nj9V_=sZ^w`5(*kQLY{AEYi5~Q-Nj0mbS~e$DmI)S&TY?K z6Xx*8xzvP4irpGia_gd@ar?fZ2B$IB%9C}v#UgG%JR<$<*M+Oyo6W&j6v>(S1wxyZ zWw}xnA0Tm?OOQc(Xl!sAUyC5ehPs71brR5)pdu+Or71UJ2nRqM->W%%N6J*I$J!F3 zyXm&;>$CS*iBqZG3Z+5!n>1R?2a`5Supnvg2P#giCAz|n8_yn~Z78m^)19SIB1fo1 zh=~xR$gQ|4f?U|t`YG=DK|CH^|?*D zP$>1d@TI>^dRH>lgEo;T5vj?ZyNEeT};$&yF!@EDe)5J zhYE>yvp}dt;ZM3J)GBa@RYGzi@|$&4GH7aZ3uoyATUd}~*E=vNz7)zzh^mPwl@oYz zRhTPs08)q?fgMgGadk#QT7oKwt`fMg$%qnlQ-Po^$5$b&|Y1;c!qW z*Iw|DsDY}b(Ovo@6q*ht6?WEKxv}R+{D)8kB)AY+8krpJVbVN1d{9VOdxgbL^#3yPhedKXlHTiV3 z`xf&Gdzm!f6u1$m84X8})6~l2tX3**cv6@~Jc=}Wgo=tr9u28H+!M8C?jLnmrSV6t zKTDw7b`03EsWECcwY$8>CtNgo$2>@BTg8ztc5-H3Qshf&E0j1?8v1P&Lo;5a%d0fo z%ViPmDRFyR?%wB9ENgW%}>wF8OXB+ zAKsTNlb0xFV8hcECBM6dJ>k3BwU+W@PIBp!25Z!WOQp`P%%Ck4^;6YNrO&9LRaS0E z^pwM+(^#Wb!pn0Vbx^rT=hUwAy_UDb6^pv>t?uILg>TYnwQBO}SDi}NF_^dM6q&WE zjcTzrt$GR_Ey_%0XVl{rQ|WT(^!U^1Vj59cLyLNMLG3Lsb+hSL44uNnwa=uBYOag+^xY*s(uqly!;Pk%%{unCE$DI_@bV~d*^?Dc%ICL-yRT~+ zg`G;?WpcN>iz0(}(^WThRjIU@DBh*W&3@Wlr4sY1T8^rdBF}ENsFeuz4W~L}Yvt2Q zsa`IslM$vvw*mHpSK+11cp(WN*(9sQ9 zN0gk&Neye+?riM(J{)h!tGVmXc6*zu*SC)nO&+Vfs;|G`Th%!&NRe+*pM=~xdMd^> zMxhQZTCCAbx2f=C_*f`)sLh~o4l6l?>}J{J0_Ty%x4^u87YX6zBN-gDaPYT-puqLn zF-N98DXcb*0EV1XEg?Ln!)&syRCb(dI-HD`S!D=m-wLk{%u2a9Km%nWB1uX@e4lta z_s_5O*I{+qta|-gdapQB;%B3(JY0-`6hcxG0I&cg2IqcwcYy=g@Wa+qlA$op48Tf7hnO;VvWuD5R9+ckXlB=eK03K_kjf zT}E-&wwo`gBq-$ppIz}i6Get(D5!w!6a(8w1Oa}I;Ny&#;bmG3WS+-TeLEla&waSD z9prVu&OrLP89JVw`}EES*m96KMpc7>rVih5pWgof={si=04FYC?{n>=UHJ}}!QcT< zTaYtm02XH;+WMXJdti<4(a`G{D&T2q!0r-~uaV9>jY-bB?HDaON+EB?^{qJ>JQHWq zs0vX4f+AWJiOM)Q*Dio`$?9{opp@c5+K{7!@>Rw0PY)3XBmt&+oaa9squspciQZk) zC1ZuAw~~mht2&+=0*w%7{{U4nMCYMVQPdN%ZB}t9tWyr+9&3R4fE@JM%f9VngY=oM z;##W+fKw4h8GQm3kT|(_2IJq=#+@lLE-5H&VU}Yij}$3G2uXZOl$59el7+bYZMZR> z1s?lFKWgt~h`Zu$nRZ$a!?*XfW=)MzwJOfVQ}nu@y4`AeZR?aa-!?r4L+loqnmCLl zubrUD626X6GU=!~aCwzFkk4QELow;;9+~nIGx6+kvzV0Rg#OMo>HIO@KQD&GX+Xi6 zi#AL5;J&0>26uLEZg;@?tc0aTUJ4Qe%LJ_jv{FdANoKv9NB6`8_Kw_TLw}o}qDuEo zHZJxouXEfqCu#GdPN)0X4Y2K2itTb(D|*?izvCh}l`Sqd+i6(=BOc?{3nKYuu2gh9g&Kwdz$$kt9L5=r;`xb5$A@ zcHOBb2A@)2;#5#rkup?B0W3*#YXAdXuH~%ux4NBEg{hMXfi)c@ zOv6%2R0YX&gQJ%WZ+-o7}KrBZ?#VC3siPkN@_1fk{Lf%LgJol%E2J> zf|8{F0L!PLn%|V}oepe^B4nyMUyii8wLs^2T$bC&;taAv1I@yD4mIP@+i7*Qu!M{N zL_GFcX;8QS0J{3qjs?5OmUVh8w0U4fNU|#wq zi}DsYpsGF=o!U$R2%O1{1Oa{2mj`Qy>&o^XqgS33Wa>a9V;DLdecx!#+?{VI$Rrb{ zhZsNYkA|Z^F3qeugfFNmK_6>rP(S@&e{F)xah8y!y7w&Sr*a2F^2zU~rUtuetePC9 z04M<-DX=&5hPBIc8ff_0*@VGdIf&6zz(7Gus_s$_%)^$}H`fIcAAOaAg=8gI*HhOA zQZcSR2h&ZoROu^Ph)Lm4&V*nS^3eP+PuCj^s)9gQw*PoE{4Wy}BApn&tQ{@>arVp+M zU%O+O5~6U96^9f1D$aywu9?aEdVID_$|+Y8ql_$)aj$cqmOG6901bBa1p+0CGFS%z zo0H$mVeaPw>ae0gjT#zi3!6+-fKrlKBoNvi>^9^c_&$Rq#cUEuBn@@X%;fp8@)*$T z(`?wHJe4FJH3JG5*CRupj(u`ISOn(Xu2BUF!LB= zQkUiP)87pA86s4l(uvO!06v=Pez$JtJ-Zz?b10RF%<(ZQQh9BUp*h!000a_2$4=dQ z;|!FuEM&&|fD*4<4!<6qGvDpl=7}UI0Qllrz)D6kPtONK@%|*?s(wK;vS?mlogFq7 z3`ug|vC{_p64{`n2#@4qJ}Wle2g?!}n%zCrr3ig0DmVa~m5@Q<1m|A*{58(UZMI(E zaTw*0Pi&m@7$;13>8^HY;YOCXqdu77EH=I+D<>&W2>|@^MltvLJrJ|VWRZ`f1pVE9 z-44j}uu~{PP^78(5y%GAvA5^zg0d1bWGC$a9f4p2Kb5)sxecsw%fp{R_Yd{kJUR3q zaQ^^ZjChml{C3VX`u+#~HW{0$zxRJk7!oi>jz44he(c5G9QqHqf3DjGxHThFp!+`# z{{Yu<Y5e|pG25sKPy~%}j=r05Pk;H2KK+BO;+3g6 z8XR>W0y}Bx`0edMEC|qAz#pB*?Bfr3A%LX=a2zpvw%YQ*{uKItCulS6q%&&U-N(Ng z*XFPWzb!smZ8dyB^&fcu08OEvwq$o4vu)L53>xbN%@0y|jt^X%llTm0I~AbD67^X~ z;FpIG5Hx)a^?ePwKICE~)MUkl5G5+KD7PbWi#4BHKHTvZHz}s{?ILs@^1wYkarkun zHny1ZM-ziOB^^CDLHu$x!3WbLYKYx%@Vmyd_)nMKLj%+Ugr3>Z_9r;gpxV~PpdU~+ zW8&C?Zg0e^{{U4Dad5>Y_3LW`j~qY$0FyxH-^afCr2e>8$BHY&@TOplJ*e{N5oCN$<2l3bqL-CgZLeS z%F3B{gs5jgQPkyFBVK@lLC^Ya?im@=qq<9f+@E}7P_$FNRJY7&{W0cm+EPfO?`wKi z*;0qPce{2>jF2={I^eafJBpYUoj6R2eOn+5oE(GDS4REmQ>NL|FDe9zH72udJzG?k z-=d2IFjUbJhdrBI8K?fAIev6$+dl>9;!fy@TT07H&1mv z#&U^kOv>)>tBj{zR1L*LaE*MZ`*wm4(jZppw++2hQ?5a(wz%%4tn(Xf$gM|ZurLSc z>SV7N)aM6hxfMuG)6q|!D(>8p0e>o+QP*N!zD=-v9};d1jEs07su+TcT!27JySrRo z;OhIl35C9$+i~2i5%8xKsB(0n5 zmGxJ zschYiMpZ`lq(pW*%}8H1WoCfVONxrifSxI=V6NLa1W8F6V`{$L?&}`D>lFK9L(Wv; zQYJpLChmzvsKvCYtSLyEP7xnuM3;cu7lOM5Cjr zktVE5D+2^$$((i>&#u+k?GwKB*|xQ2ooyivRAxj)E)+tDJ~2&uuA!LZF&K#j}MxZDJg`dN)S*BhhzkX9&6=m zYTWsTwZF*~Xi@jO?Kg8>wv8LzTa)%fx4-P}%T!up5$HE=_;1!~-<>x^bfL8{ioLyR z)8$jmAy}7{p7{A;|H%REK_%%X*0`O)@r-Ac^5>Bd9a)m z8^VD}tlA4wf`UYdcyBtko zw>{9W@hS0UQ7r`ol$07d(}ZDGaXGkC+I9-SQeHyPvBRDutt2RXc(Qu+$@^C-DqTft z%mNgmLekBYmT(76n%1^8+lZ@~xSccQZXicWK?T^uhylx#^G(^@JLqxY{zJ^yDb!lb z7yL~wy$S^Qa}JzvDsat8Dlj$A7zsXvl=NsX>&gR_^ag+O24STf?A2GOIN>2Yx;#nhwgQGh_h}&Mvo96c zwIYWZ)xI?G6OuJh89(~9I{n%mltP50>f}`A2|-ee4}<{W$0yU?*T&<}>M}D_>Md44 zm4Ai>VN6b7l#=@st=t#Z*uJmH2Y4Y?#`ZUTCVOgCI^ltH(;}@rXkrDyM}(=tNhB2y ze4=guI4Z)9KsmAYcf9g<%AMWEhYUexFC2+eswERkoH8|AoP{6Q80)nKdjRil zleyjXi8b$e3N86XlWDwTFl5I}iYx8aDGs>E$t|}YZBf?mljKa zUs6krNc0%e-q&HSk;W0=BoMl^Q$Cl{?7X&qY{uT9-p0(ZfUOxkrxl_VgTh8~QhFa; zV4R;_pzpPm%8L)vD-^#G;$hRBaV;^NxY$?^rGMltl^^-BrZKeHEUjq5P+DyX0HF0c zjvaK!9fqGGdPR?DX^|*33wo(N_>iE)YM|uV6C6)n5Q`Jd?eFSDs9Sc9=B?G3r z8kdv4 zS&IM&fR&t1xO?$GDk`0^epk zbn8Nc02qz6Phud3v&1_4Uk5 z`ZadvktOElRq67`9{Xl1DV-i1ah^(@;~Jf;S*_&M?}^hXw!JP*HkVCdh1Tj7!Ox!s zZY2eZH8Pu@?CA!U+zGG={_xEA^!gK!G}yA#LR=RjDmv-!rA8YeMTW`}>wI2i zkU`=jL4@=G16}T}ilzlZQ*qg?Jdm1u%+LJ|h`RHnRZ4hAA!x`z!PIDRrp*&|x?EMa z5%o(^nGFv|_j??OFype4B)>coGaCq6l0YQXyhzumNY%H5x@6jVQen-s>g`BRyz9>x zu%pqEI2@={<*6l3R#|W^EGl9`ed32(Z$JpxgaNts6Ahy#I(5DfDl%_IL@$LZ!B#fOhGqKGU^rm~Rr&W<&rOJ7d z>kw(t;nOYCNVi)mMIwytCQ;`_kn*tPjGQ>5%s}B*%mm3Cgxlp;o8syj4t_oeL5Y^GR7r3IMPl7TN=@m)8uE zoHG`e!?jv`s7hy}OPs{AR6>X@#03{EYo1}O6Zc~cDl4v2rzV{+<}3<~W`ojc@)PuF zl?njSs+v@uChDXP3?pAIt<0J=xf&d^bJnNJH8!Dsbli81#<^E5rtt_ zPKdmbMWGJ|9ATKbWe6J>-CobW&|AWx#*4b@wD={ei;AUHP`i5CfjNfKA~LGHl!V<7 zsZru7a-+LWQFf;K+)jZ>*vg6Qv$@(mK8I*tvZYn-yFRf?fmyyS%ZBHu!mnPWiSwxw zB3zC+8H4V$LrR)SA)>AWg#wX$MB`o^qSVz;mXH&Zec*&bfH?wE2q{r=9D>YkrZqo} z`#9tNDV~?4!l?LKWVAl^aG_UJH5|EI63Pcrs05yvZDa3x(X=X(;X6};n{r)0-L{*}X`~CK1x1>{%A}sk9z<%0IPM9H2VzWeP zbm*?jioITDsTC!M81g0bJX<)(398>{TP?Xe-Exspi4xF-PoxR9g!&CZHF{lIn_ftu znib1#Bg^^3?ZZo9O{pURDkr86)@|(n08(>zyOOXe6_m$zvmV@N8Vw;zsXsEcK2*xH zl$tx7AWw-MbCQQDdWeV|@=pl@zU>RO2$dwjTBK7dsFN_n0O`!IN6b& zKH#U**=`IPe~+XzCA9E>!X9ozO%NViW=Zh;)d}PI?FF)i=TSWjG%C=uxv{3N_* zRb{^>Jeg12?!;;&=U!YVUlioBm~z&)SmEX417;N3+uW4IYjW`1WF73<5t)4uZi$iX z=5AV&Ww@83Os-qkC34Jui1b+|LRhIa6}73o3Yb#Ehy@dht1zRcW5D>Osu~pqV6ab> zESK0=X`lkz;%5?Y-0fzQ4qlB>5>p9GPW20Hsu`U{m8Roo_Xi9e7NL7@Ri~zIZtRFI zDDc%TUhk{$=v3RO5XM)*4yy>8a=8c`@?2O=N-B5@*>{U?o4(#%R*ic#VsEmObI_)l zF(exFdV7>xzJZrQd_`sVVNamkw&`D%ES^H#j@jdEgS2(Jt5z+UyqDxzm3ofouIpm3 zlsJ=8k#*Cl)mD~P`%>w2+lIecTsKlYJJjk8klWDNl)DN<`%UF2CZf12tOqG)0mAScB!stUHMr9-(LFQv zTH*l#FcRepOMnze+~{*(>xx!ahUm1otC)*5;wo}6Gfyo*6sRDAw4@Niz?T=bp4hW0 zzUudRU0pJwssj^i;sYp+a8f*F2B!KSN*;kCWzA{QDfO5|)g`$Nt%n0?l9s`1P_Wvn z*Sjdv>ifH`)?d4=s>5$JK(1G1c*@KuRT5)VDV0@(rTc)zkoPHdI*|9GSarDamdA@T zBf#1pQZpRw>D!cv70A-So-V6-t{qiR*Tf?0Q?m%}YK$bMo7P49J%i22$Ai zL!1V*$VMPUTv0Nql%$BsO9og4oB{wJ$;iWnE41#xgIBaFHk8FO{m*K~ z_nb+zy1hM8on@)hD6i719_V7NQEYeBx(&|MCDJY(-H7|EyJ1|`z1Y*P*q3FILXlsv z>gk_HM6}iI%O=vR%1h5W!lF`|qTVbDnUM}<-AP>gBH~v{_KLE1J-z#O+_>XUo~sXc za^Y927VS2HGLt6pyUmt^36Pq^>a#Uylx(hnl1o(2@dDOxb=8uG8hCPQj)`k57m* zqB;_yl{j@d%0h3caN6ijB+K@r*}CVU(I+dgg>F(Ohn7iN5UlXj5{CxoVBC(FlG~c7 z!nikoZ`?4$VVi=V60nssC&tHLjgH&IMw`IFlEY<1w$^TGF#{rqG3^Vid$hASp_Qq>@2qED0=Jf4)0ynEtYV zul4V?ZSy1451xnaJ9ICl{V%SVlVBdeTU&B%eZH6kzpStMkMTQqT2i11R}W0&jA^E) z2LSxNb=WG$EG=N2Rg>4LB%ibG#>pGLy2TEiB2((&!a>Q?wm|Qn!~yUpZ$Pjrb^}sH znV(;6I@?@(l9P!&I+++jN>psQ0zo%XNOuHi?bBz$5^Sv9dr0{|Jd9Ua@IE{TrDc!rn5(CU#PkqRJ5Ha`ocM3TbUOWp11iREIpx2kfc zEP0lKp;MP8a>yAZ1w>qMNc6^=JD^~zJ(7PMYyEoc)$Z*q8Zzg!Le(l*QZS%% z4l`w#h*0Q~nB^W`xW;?oe8iUta3U!LA5bzqK|QtUpN`H{#CK9~W2w)4q>QG_R7T9= zz(1pJifU~_6x_s-Y|w*PTEqq{3v<^%1+*roBx59wn92TIaCNrS5|t;27aGv?(Zn2_ z>8D+}bEN+O@{9if+&0lmb;5)=!kZk%&k-Q!3kR_I^ZINiTT-)s(2 zl9pPKNd+TAXCWh9udw#TOa4=8Gjr(nWcK2cS)D1etwxD;99j%%l26AcxB%B?<*BYU zz0KatXb8L)O(%;(^qI&S>-Bpb0UBdEZE8Q1MiO7Lt+}cRFs42&gA-$apR->Y zx5kL@ouon_f1fcbOMm$gYQ{q1E3m>KJAuC;XvWeF`mlr>!0hU+MW_g z`@Z9z-oGxpc!@neup0LV_C})G@;LMMB|LmXU0i^6eF*s-*!rcJp+^T!CG^yt6n$_z z9R@#!n-~gQZ~);N06M2*oF~@*_y--cdO>e)&ZsVha}x zS%@E>LNSsZ5}F+3az)EI`MI|z>B|Kk?2r4S?@#*en;UY+p#K2eKi6#A*_u(-BEDm0 z>(FB%qSDE{G?Udg)hA>7anX_{#h@o&3)5ez>8Z)${#||>Zwk(!!gRWrpsCZ0DLMHa zGDe?1$2c1+dBgGe^!~m-XKlWv-XaD%{hpscU+cfG8&D}IR8{3H?7an_PJrpD-=1{C zlL{F^a~28LTXfW(p|BmOG2@`O9e~{1#%}z;0o4pR>nfYqi zk1_{`jknz|m++tE^u$Qrgr^_bd84TVg(5Y@M zgds4T;>>8s#}mnOmKsR&7Yc&gBN!*^>8Zi#w*nI8DvM1H*XB``3dt$x4v9~!)-v03SM+NpEu+>J`-pv|CYGD9SqqA)$<)PKu$r*8r!ihrz zBw!UBWaDZjxacw{*UiC7n!t@Zp5o)ljM>Xkl&NwSBA|^A0)x+=K`TwJE81GGO}uIq z=#CN88FG@~6=IQFw0*FtI7iS%tA6#?o87hg;f-%h&iEUoR*?#A3;n}Vx8zceKt zAX6vQyc0`L7Lfb~KDi_>o7aIH7}sDG&D`2`!dbR0o9MW+mY)>~z8ohx0Y-Py58eSD zOdRS$wquy5#DxgMh_5+`^!i%`{{X!-^~|bSF^q5uPknF{>|Od3{JCN& zx5dMwX>5W)N$Z^aKd-x+euQ7AW=0Z^7rq^mVOb4bRQxb3#Bh(mTF$CbJ zQgzPO8N5$pD%I;>p(^VYdw$mvDhyO1(W>4ay;xO2JU$WXzy1mnp*$|Y>gq}T?VEpO z9n)^R+4J(Z?k=TawDqLz(`en)3HDpqZ^PB&&|XAwK;qMxU1k#GR8(+WEv?M?v9>8} z-VQEv_nu!@a0@pfw;|22<1t-C#R97%O*vx3rvjw_SQ3QYz}C;ZWAcTGUA=%Z(l$$%+r*`*DP$Qk;*s^Wwjew36)MioU&XYuQ3H{+Zdh?8{1L3uGOtT`<>y1vP zj!Y_w67%$ZFt^o%;&d6nIXLOBPMcWY9u?-QM{ux)m0t0S?E9L5(IA z$p)3CkX@fWZOOnGO*L8Tv>*V?fgWdGCSu71{{Z+>c)Il`9d*Y-bFd^OKWN0ybd-lA zIU$lr_ZGG`YqGlFn&Ec^!~~lKSY-mhZ1x)$eMP~gCN)Z%5xH=gQ&mcRL8|>VNL!7q z#X(7Z$f;XDN}m}Sx1wZe^!RfqD%$zIfOmN|O}Qg`m6)<(F6e9Cf!4xdo~sDcO8(CM|feoj5` z@@o}M&(&rmwIMR=_K8;s;|g<%vjHAbpj}aJa7ZZ_I6F;{q)A1M8e$)rP=Q)Piv|Q~ zeOsgHrV=}0p$dgUn^z^rg$gZpU>p%*I&X97i-~!Z21*t(lZ=e@=y9n1ubI<3QU~R? z-aqC~v(*;grp}(t+q|2;k8NAgAxkkr*4*Z2xe@;Ern1aM(b{hs$(+|<0k%E%ZyKSx zyB@E2Q*CM2lBjJaqcVj{s7I&No%Mkv*aqd0otvlOMyzMFY~d=vlX>e zO-|p8!GxAxd2N@KkgC+7P8xhNzX*a=ls&w+P}^qJ?lvu1()enpREY#iC0)T7*;r?Z73_kp@?+*niMq7B6gBB9VIVh0^I-hQhs>WhoIBqS5>S}I+6nNQ%U zQG;;$&EeX?Vqdmq?&vAA?b?i4b0fU$YOQLkQI9xywFc8VMa@x_`hC%Rza_W)buNSj zT9USzqQ*iQgz!~jQum!v{Nb(8?MaM^v()udDs}g3@?lXZ@Ek%Nsa0!Lmj}7hXEPy* z5^Ap>d%GFd<50g!c}HiW+qx|~E|XJomqwett>gxsW!klRZ5F`Y#Cb)Q7b#H$s-#Pr z6&Wzgb0X8Ka4Qumla%}}JaJxXbb9t2yv(ghW^I!&h`~w+%ampoDLQWM2AiC0oLCg( z(c~oQz_hFsCUpROQJEt$wqO90Ky1IO0NrflVt!c^mN%y1xP`$~Kb!Mmd!DaSr%i_% zk0mNmepEYhN9e9pq_RYIY0)y=XyJ;KplT1u1eV zMwbq!bkU+xsTVw!>U8K)Y7wT}Mtd}PGNPiPRGk_+-&>HpnPmWJgyM626_cHhkeqe-BsZDsd+ij`b=`FjP~mljU)g zYk#K9M~1jwYHpzhJi#JL8bnOC2n8j^Vs1$w+n3dKyLzNLP3;naJ~a|dTGTZ;3Xd)| zCbI&EE}WntOk$lc^r(+iAP;e=@}Pyi2}=V9CFI_Y@~wnbDN`7QPk~#Z(CTQU1k<9a zwq%}5PC5esvXMeZ>A@|Mp~b?I4t9(-HI+%Y?;3NIWYQe2P@H16Bcge!Hkc7!dPKRA zs$l;BW>yg6#-A0v1FgA^!(`t1D>Zdr)QGg`z77(lIW|+3HT$=m@$#nGb^ic28;bt? zr$UHXV5?l`V7y|O93dTE6)98#pCLd52I>I=TWj-XXN$vhI@b}#hOZ%kE161$upS{$ zND9iZe860E)M<%9QQtM|4xKd=Tb74yLWxM7CT&VhKCeD~c5~sxQ=(9zutP1+ep{rr z+eD9~N#P{tWQDC|@21(YDQ(@ijT(aW6-c}%(do96l}i0ZbvYg?G;QJB4%`-WI%L{~ zO+m)3+Ek_0<*jQ(nGQVD#5Y^1mq@a1Id@gus(nJHzEwgrx~Z+bN`lOH6x2ynbkmT! zHD+SnaJYx6MGoF{OOnB7 zBSZ;nKCA`FCG^S#)rLFS{@kJ17X@Cay!c2p`7>(~(|cPCTr?W38K>)QzgeMNOfK(~ zYc}FqC{eDd$2~IDF(53UqbNlQKIn;04c>RG6xLJxg+oYZbOq$O~JaNTQH|l{x28 z!C1*SSNkH|(QR9vp=ZjU6~=0n2_X(8MKtwRV?8-d+c3x}!|`d!aw|tnu9gpTjB-3H zOsh!5uGADvz$x&Fa&oAjG0Gb$cH4ed6#U&`apvaJ41o?ANQjWkprAt~?g3{lXLDyR zUu41Gm4Qxnr$V%?zcjfKs*){BLX~pVC8`^Tj$D=^ySwe+I^Km&@YJq3r5WWwn6MdJ zng0N8wcD{yP%bxUHhn$}RQuYmPOVO-(<&-a<+{fdifgsYG8&5cRTNzo%XOz*QlPa{ zrn35)lDfaI8M~#ZLAqi>MOGC~<)1^ZP?J(&sL~S>H;ZcUwx5vlq0lC*EWoJKAHx;0 z5P%Db4s2O^QulSf`(ah2!Kl#}SfogT&B-#|xFAT1)2iVO8>5t%Zy-txwk^u)%?;i& zC4tRmI+VpL!}CH+cdIExVDL{QzET~X-S^VK@&c&vRUDWSCTQd#Y6@(sCCXo(>bJW~w(*uL7`a%(BwoO-opgK|e|lYZ{f@~%5kq1R~-VU$g#RT7ucL9Nr0vnA@RwY3_m z5#gSa*l@YD^t2;W>lR(9P%3FMTcp5kb*4o##UaXjVk3{Q!xFIHDlz6MI7kOkrid#2 zZJ0I2o|IXpyvk&!I#1a5aiB+v@VRl=EsrAX(sFRdnkf%vz1wa9qmTbc8Nd@n-VgOD2nLD1pBUNEh zU9WEHvj(E{H6o2scCSTs3^x_nbLezCmFl}R)JcfrNShLaSwuFL*x`Z>y z(Xit;0bx@nMx~~z`eHLSyHb->R5{pCjS5M`1{+dvIgz3^&(#Uhj7yqap9yi>@Y{%7kxk}BnJ<^D*jiouIV?cXH%{l5f!Uebxu3e+n-PuGNn~y zE`-fy$*dFSp;-%{^;7F*#p zgtbS5Rkj|0gsBUcOl8t)7R^vLPo1!~B^0#EQOrjWzK0{BPqyMFa#DhD+ERSMN2fqC zHR^wm+v||yR8+PlzKKmbg3_Zo6g=5UI^}1|I^zRPdyTC+M`*QK7%^$lT4IqD5{Pje z5EMaHRb?b8C*gZo5Z5?F;~(tf!dy=?2Db(p_)Can%2x(*3W57tIuZae65+Fu9EKtB zQ8k^&RBu~SCi8uhFPir6r-*4=_FENdJy_YFwitu|^DrX|*-DPZYq~KmuHC6i7}K0&~+Rj`}wn zyN&x>QZ0+_hZ?UEOm`V>N}=-Q!+FH<8L+D92ibvoTq!mOYYQVh+fON}uNN`~rXMty|7%gwx(Q1fnr;$1_i@;Zfu1tn|lQh>p#S89Ai zNS#Ed8qrk-3cw1Ao2C-{poI|W0l{S#8ao@}{7}9iL(Fp!kN_iGjCn~v5t4ox*Bdgs z>uyB5dS`}CI3X;jQcea!bEyi`AC8#L(eH6y)-f)NzGmmQrELw{?{bY9E;mkcr2RtQ zzG<%#rmLH`x+L((uT$`#{J2X;iJ&y|abNmIi4!K|rpBz&9bu*CDMoz!dB_+%S``%> z`N~HS8R|&dy`QGkDWu9&E|`y!CV^nFu@)}c1FPyrHb1k@E~C_HG>V-zrkIf7NAtn* zsYw}u$f2*40(2(W^Q*mB^5a}`!|Ewfcn%=0g+~ErQb(I!m_KRQ-*xw#+Fi{^YDA;U zW~}Ls2dHJVjD-4e9@xshJ4!!jUC$NWGZ?2uGMsK2N<>VPRu+ys-gswkx%6Xyo4QFpyy|N zeR1KwAmOew;Tm-_G$9l0_^3I`2i_Pqa7*7?v%Z-0SGuaaDz&XoF{GtU#*WZhbB-sR z0ctrq5IO9GK7elY7O#P#3u(eRA*9Dy_7LN&3 ze0CqKrT6cjTz32I_uFor3GLUd)wEwMRO1ve+0vjv1n0IhfsWdeFe*Zm7Z2O7wAY4O zCDUALIOy72nCVsl*9Sq2k)}R7Y&QUyM}z8uASE6eFlH_eS7E8%$CD1Y)qc{VPr>8) zMSvT>lw$e}=+gVXpB6n4(kfxPL?H<8~U_Rczvy@$75gzi+A(vS}c z1Z$9cedF-iHEp!i>sE&InB#Vt2~HECDiPWpay0FaQ`ckow3w*E!hUBxap}`v!=^HG zwGS{P(r)e|tg$A*D2wRZ3;GjmY=pekLMeiTkbdd`xxLbX?YobzxG%2U(5cW~l$SZq zDM?Q&AbEy^AZP{vCnsH!k#E?~@S$x;X@9hY4=QpqkWW#rm>Pct?M5v<#PV0Eba3FO zI2h^Bf_h-*J+s$jQvlkW*y`Se{ zHR#nCG0>oFKm-E7a^?Cp?oJP4T&t1-BQUk#U=^P-y61~Q@%ZWS*h!UDQ6xr#g%Wa4 zn*{gI?P@dEQ?Xw<-CnGos&;yb^2*z{M)a#M7 zd6*JtS!M}#4*EDQbOOu^6V`!6$ZJR|uXM)5VHpBfrdLOSlOAu;NzVH^zT-=5v zkI=u*XTp~$_1y>=l@S}9YF zXI8r4>3~OFI_f)M{I=NDBL2z2>(M>B_xyI}h04kgYn$t%UD%J$+Za4#GS)Zs*3LBR zu9!L@2^x>HCtt_o{byn--8aWabr=IFB|7I&G3(ra9Am!Q3Z#7Jh<(Gqaz?+_yAMi` z;Nn0SI8H~QIrw)2Z)gR=tz)6zn9z%iWrH%6L`qvy9>+q?7=iiv;i#ubpGTI49m$55 z2~a0cGyE~z8iA4zU7c9(HtRv=&QRbx ze&0+RagSf){dOC1azhAK7U)68Op*5V*tNP>C@6T9YND@BpbuY$+xxT={q6LhM$~bR z+3T*+$s}Em$^L{K40Z3np!|q0(*rzIZ~kC^?my|bQ6Yi>4xo%^c!s+G6xPBO$0AY4 zAd=<}e#Ix@jdjPvVr5YyxT2-Ym|H(oYBW7SBRxJ_dO||Y>;TjUb8BwpwcnmP?~Fe) zJMtu-R&qua$@74ukf3@HLH>J0Uu&%Y0NMN!M!x%JC*#Dg^!zrFUgKX#Qsu`T66sgg z&wP+G@H``-81J-j_PIo~ZsL@Jr8uNjqM)q(WvL*ih~on)Agk>?_VX111`!I@DmoBz z2HoG-8)FpAZuV9<2~Z&$0$s~;)33KPh_7kN@Yfx#d@wOhN{mT3I`a;2Ph6jtGpEMY z%}Nsp#F=rDct!^v6P#zwsm`5n0o3RY)dO!unNzON;zo-$VHFBFP=S!7`PGt1>B2NU z{>=rHzd(l5Fxr(aTs1AeS(Q3}65b>LTM0T6tb~N?l19umm{Rek;RwrOnP^PJX1F)M zI~@u3!0J?C0t$f|n~tEJg}MI8!<;LWkU{aW4nK8gh?AzBG20z=C*gsJmmWe2*mIbj zKCTbPT?RT6+wB`7VA?dM4>B%2pM!awanp}?$^6o#jg0$Q7U0*ZA3Vr zkl6s96@oCMpG*>Sr^9BSdR6fbpAy}IwgqzQl_DiPGNmFbGNu*}_X6W-=2FHKKjDrtV|3Gm40kBy^96dB zEy$(F(IF~qXFq&$iJx;4b*=6omk+a=PJMf3vZJ@UM97j|EwaQYh;U%6vXNXh|js<&&l` zyf05oY#%v!cPB#k+sm!=*XxLpCrF4{EJzzM&_23*ZSRCjFWg9NF1aETZU6&~`@iZe zbsr6W-90g#lUTSKbh+Z2&|vcE#H4|aoknx@vEN;k^I)*qP>+y>WlBHhBu@N&*P@McJI_`*pwcClcYrh@>Gvk1|0QQ{VOU!5wuI z?utaHv)vD^NK&9AH_9lhG7FUD6anPrC>P1sL(pyKciV(lY#sL4-qExuvT4^wDjCkvcYZ$C)`s9~_hq|xLYEqIHics3w&nOmCXI5s znp4J!LqpA}-et!o;iaa75wehyUq>GSP$+~ykkfpx-G0ea_bXnSBwQZM_w9FfGW>dq zs!v(&#%|%=-ED-aDL{!bpDw3vMZr>wcFN8ZfyBQ2q}Kg1@2FZ7`duz`+lJerRW56` zZ9g0on?bsZB7$q65)jwtDqATS{q<)ZAWlz-RH0$M_$798n5Y8ReJ<_04RKWQB{piG zTCCHHTs}Yl2z9&+bYFT$Bex91OBHy&?ktBQM&MHd%=H;;TMMt1c zPYR+;sIZP9?lZM<`weeyoqpQVE!h(yuD@@;B8y*ykF63y$(;^zJq1IURFFFnj+;Q7 zlu{)jPk^lJDe?z<D}k6Z{4O7+CoCre zJWZ(_V9((%aSlkV+BN2@j5gb*GH13jisc>m z5_potnsS|Wcn2mjN5f!5GQUpwQ%Lul;k=ZjhejIHwBI&8_&F{l*O0nADq>I!oy-rW}&%Ic(>r`;{tUl_Q{U) zagGq_cTm~Gp$B~kwV+Wg3dJ%tr5=Xt*XSGJrpbWz@Y{o3VR31e6hkPA)u%>sqTrPp zWvUlJbqh3_$V^!)P(XmA+lQXggOT38zNf}~*$0#gAxpw#2u~2Z8ZVwF2 zR3#%`9HXT~s>A{V9d6`VpL`b5>`Qxh6?9EgEYs-K<`p5fWJwE)MVlB0UyVn5ATdjk z#m5eiN0v&Klh5=N|yG)GSSfrt7fl8_tYHlGZ za!S^Qf`J1nAOHg1uWsf&4Oe4tOtm+2YE5FZShy$_>f4WM(&9HR42j96!lAWVsMAc@ z&=WY*=v9rX`iU(#qGDD{?!fg=J;;l=ThnKmsYT2q$w&gf{#p+Q4YOCt5NHm$&ubfyKb2VzN(a0 zIQ&d#65&+pO)1%E!d#lC!qkunNXHi1+e$?2DD#kIViZ6z510}OVgL`RJj3g_IAWsl z?3~myDF$pxEHAmtq5vST&7t?T8h+Y!Oh7>KskX)Ac2|W59h& zBq|rV2<8bMVDgpCzzf+yW6g;-!^Ba%IZ?i2TYOPC&RiCBQ6*&}5ckvvlO$-78 zTvGkVh4$jE&8-Is%z~>(4i9KG~?o>fEzDx z5<_?(tCsBBCFN2dc@McEl>4)ozF~nEgc-4_E_GbCG0LPYePkg7;OB1iYmUF;e>iEi zTFgqkmsKKFRkbE_l9@||C~lz$j5S9nLQHgUcUM zcQ{n9@o(Dj)~dq=!wiBQ#6k*4a2qHZZ}d1$MUCN;h^1y+-2&J3>B+(RMgIVuLsBuG zERokGv)x>_Q@tx{9VwUHZku@#8TYiB^-Or*6FPZ5Ukt{sJ^ujRC18`N+0HM7F)`$m z;$-Edl6aK@j^B}P6OS=b1w@~%oP*zH5}gH5DwAZ?;LCoDy6m<&s$VXdH8F`=qsLIe zLyx2uf{t*dB^ zj(m%UY)CI?4dc^q3!V*?Y`Go!HH_1ueQpxIj=xuz3Y8LL1OtF6?o$??A*uEBoIcG- zYEI|r47i4zM>3$oks$%bNOC|)O3|QFR1`r^eBc&8^b)v0)y5+5t)Yz->79yhD%D>4p2H=Q-7m*B)wxZcg{2F7jDvGrO^-Bs zS_V{#Qj!ZREjmCaNf}~MVB55m#$hfk#`&Htay-)An&Boyx#Xm)n)v`j)gV9!>N;vM zi$B^I8byg0G2wa)RLlZOj(Nn8OKSE3fdpNyaP1U|M3clBXQQUWOt944hNRj3E?W!A zctRZwH^9H5S#ieoY%MM%1SdLz21m&{=NlYgdJnj40yB**#Dom1m7L=M42*%(zhmp4 znTFd50Vqrueb{JfLR65=Dz2eNE+~hbJrUBch28du#9KEe-E(j^$H6a9=QG=0qeG0aDa6HwvHW}O?hA|z;W~) z2Vwno+p8&00P>9qBTr4c?VEAWJaZ~vGYr~02X0TU5cd_oOs%mt4ONJ;Y4VT}P-%Z# zkPcCi>%;~RZpYR*Z`;}C#ou=CYP-C-ppgaU$$&itAY#MTw!*v!t_e)q$K#+50cLwjbF{V7`H@mBfe7cXa_Vp_6 z(f8T9)j3=CYTiUyZZ%(+MWD&KG8HP3RDL{FHB3s9+@>kUmiQ9s6kcVG`yzWx z4d+@H6|cO?Ogl?@o3jFwe$uK^1Q9pfY6=%E4fSy;`YWYjZ_P@OZRt)KE|6VD$G+Kn zk#l&q>`mcXucU8ZbCqVR);&TmEj3ALjGBy>HuL=GPT z9!0rxa@+7DVw_vYl9RM4nHZGB#IHsHd_Gc1SBoe>j#4hr)Ja}PWUAn?#Y@7SoL0C? zi48`UwIheo5kW{&?36fbJ30U<1%-^zB+bTG72^LafqUuytqXnZR|Fog{h#lkBtAEHnF zpW^DNJ@jBkRVLuApI17P$K|#*GMm~3Q8SB>q}Jj?5ReH>HK{D1kP9(SmnhoBhP$L~ zozL19%*Q0tVz7q_L0Lc?dBE2_fz9&F_&7!wb}6;V)vcp@7Px)!j(V#- zQ-~KoQ}Gc&2P%jvQ7k}mNxtuM>w(GvV2_W-sQb3(%LoLHq+{_P6Sq)v_Go^4b9j*2 zi2l0mnj*5HN*abE<}nmpfZCB`>NnfeVj=rs!fICPCMnlBVY-Ax1$5U60B1dpy*+WY zKcT46<5N_Zd8=tLRx{Bh6OMgzkU{UB-iGJ>sbP4{&{xMRnpg;x=m#NOLppWsr>||Q zMg=vQ5uwU)vm8h$lpi|s_z?C}sm2wNoMdUCJ?}ovrV8kD$ROoZIE*=hkzx*)2T}a7 zseQG=R30p$#Y=zAz;ssJi-Y%?TGEHfp(JM-tYzHN<(k$_;x!<8IO<1Jia zN4E*r;s%?)(rZhhvw_y%Vjz$4%fQ5i?2m?6BPyjgie74yQwv?qQ9#o70lhgga7~2^V1O7qf&X~@6jvaB^ zvFqu#wMI--EO}T5(7T^qU!d8s>YprN%|RzM)CKMfTyAvG9dLSMWEEgzKM!8n8)m}B zd1pOxGxO7I*dme?Njjcbd|E*u=t@Jj0r(|)kH6#d`#xVCcFzgJs=lb}t~C4q0Id3S z0?8pN(^3vR$F6(n)7S6#?bWj98gd3T&tFfF{#ujRZ6v?|lIim8lrhTMd7qbE@c}*o z!A4?SHl%(Q(@(>H>w!Fo>GKdY@0{(;#6?m{N&?9v$*4bOanNh8UArf!`Hi@}o+FHX zy*{z~ep`7<<^TX3v1ilEeSJUQ5;KGVwhWV?9J2NO-<|{erV5C4QIm}in>~AIF`a#K z2i>s$04#JRDQqDhv(p-aa5dEYb;dNU51-rTS;FSms$#e}5;B>ML3Pw@U50bOR80?&%aCmeVOxj4=-u7rKsjO~i^ zVJm4aC0ZPI9;ZIJ*Wfg=#U%%SrFThxTltv z0stEQW9o88$2~FArrh1#&8y;Bl$dR{>}2qSwlJI#gy?*_j`-`Z$71$vDs%^*F{!eb z&QbF>j$R4Sr`N8X3DDzBiXX982_gzsl9f7&j#o=)F7Czs8++kxQxd9(xtK+lm%1rB zYVWnQ*#4MUO1&XM?9%TJuSdIAM5VbBX=XibRRsxX z;cv%Bh*bmd z*(#YqF2tmJ{rY5ul+&7@!&-6-r4>z6DbJMSpdB<$0NS|XO3b7vb8@mOdE%%@l2f=b zGk{4v*m|CKY!8W4Oc+yHvW)0txi$o_3FrA(j3%I4bh;(MRjfdl3LQpvIH68HT6*vb zoK7*2;mJrHbEzQU$r=S7eQow8*Pl%G6yG`&IgmmY(=t*Lq80lkDNral%5*wlZC`gr z@o85inlc5a8k;ROIyyw!jX?Y6lmomVX`#YXkB`T$)|*QoqeZ~ZAx0xp+k>I`ABoy@ z3ROkr=BjHZZF2BTL71^{7Xh~W=7~%l*_-q{mF1R%4a1YD2K7S8P z>$hdJgs|eBNN^z`!ruoluYo~fDM9+nJRl%x=E3RI&}P2O507*m3MDD$q47mb`4mX2OiFx6f?VhgA@#T#OL>#T zN^q2{gM}9J_rYM<6&jZDuWQ0A3I&x76nHJhT>7^oU_zKo-A0KSz@j@-hZ)DpiyyInaw+XJ>tE;}$mq@XR{h zdYd6upYT$Pi=AamkV7TzPNWB71%WzS6Jp-qUhFSB!iz_+u4gVZUQ`*i`*Nh&rWPi# zW*|wgQf7!X%A10t;P|9@*lirPT+6&fAy0b{(%D07k>Sw9enK@onC`SBMrS=TmShi1 z0j3T%^Zx+s)okw`$=(1Pv$w8U^$p!nYi-PSeU(|GFH80m}vI_r^+ z`f2mogM)HCTZ1MuwO!}f_W?@XVxfClPDhT&Kqtb>ma0WsmcDnFg|S+Ql2pt~7AKxpw%`2wKSzsWy zbyd{*QWCdcq|hE==P|3k8}o9J%u0#+{`PB&xK1`OMLz3k?q|FxRS+?(x-{x5%D~ks zRU+rPV5BD;DO+@&H4Lf7_{keCFXBJFh9j*iLW%$xQ(*e&EL-y1*9VAVLymHh^>RST z?bqY>e@AMw_Wif%R`u^{UAKLD*|lhu3L94RdDZIW6^GSXdV6wUCB`2fA*N z`4B2@Ha|z0+9mafM%A|*acqwc#g~>^NmOu^D3DlY%YFI>ZBNSM>}Q02*sauSMy?@v zNlU{Z4}d4immm-r2O8+jivj$XyWgezI(vEVYR0*$3{tH9_3n~Q%-eMbS#qA6$964y z@u^T8Ni986k!wq;t;ILxam5nfVYi^2&kKIJLAv*;ycc50pT4IS^cp=v3aZF%$BL!K zqEZbH3Q_TNnyadCg%W-C3XoDrK0Q6BZBx4oLt5z5-IgYLx`!! zR+?m?C`at2DeHnj*wy*^q{RT!X#r?iN1PH}!bnlOb3DcGra9V23kmA%I)YSkR)S^J zpc>FXhnO|olnwS96N=;Zv;3VKjNfA-EwL)GxX883nmXoPl_-^|wzQ~EOKlbFedsb} zz+#T;FqI)TrFk;9D7O&XxACNz{V@_<8nRdvzrlfA!Yhi*OM zZWrCvxss@LC~sNU6L%d#-7#2<;0t(OuEC^JyN}lf&!dC zQ1bDGJD!CJ89DUr*Jyq0^Sx`Cr{F{0oYYH~yk)BHO-xX2`V=@fU1d+nsoGGjYFdpx z*l9T~!HaGl3UXR`6#`$9v$WKd%Vh=+Cmi8c0R}Wzs&4L>!!G+}PXQhZZy>s-n7b6zm9;=AKhQa-1)< z9rs&2ZNku9Z%tDG+L~p-!qQL0(Z7A{3xn#Iu9F@2le2ZA;#tZZSSRHe8qO zr|WT@g7qo5)0v{lgHuf+e5j8l4G9Vl#a+X0mwvbP#YUu3 z=#{Hx(5+j?cq~On@X=~hAgL4URMaj^6{S*CcDyTf z*Q++0m5b`zp+uEUVdjlWMHZVT9bTOhEOj+>QQWHLt8Y;1RQRe*3f8TaR_Sy^(`Qr< z_OlpV?JJDvl=#x}5>(XIAynbsNi3rA5*UyH$WlwWVsvtGX7IG#E?zO0k%D7)@<>%i z0*ME_?!mAu11nuQ0@#U^e`mjCYx;{zYW>_U;p$DujTLnIvoqzq>VWOLP^8k2JTJxb5&>mc*EA)k#8W zk}gWMB@t7QL?3lJ5(f@eF|?Q6GnUj<-SufS8Z2m%>hSzEF(QLL9C+5M)8d^lqvmrj zzcQ;LM>ULqg`f;@k+6F0#)>U|TIg<1TQvSvL4+!$I;7iB)jPt;W;m#2$V?>*0k}33edCE1hB5e*W!zl@5SnKvRWk$4K>BgT4t_8 z5yP?EtIRDm7%hAViB3oCCmJKC-P1G**M+4_)8T+-UgGL8Y31|VLe?}{EhTPiuM2|%zRGwmy3_UA zua!!p!kH2p)AdY;RHW2OPhJuYUk5!1?TwNs^ohyJifXk#`S`I4Vq7qU2q|lRXV3w2 zMOKt*67i522&z-Hn|?vG8e2_+;jfs0iBqA1oI}h3!gRv$uR*7Ld~$YeTUd?r?kRN3P6U<|KOkYA!(n zbbxihK2k<{1Dt(_TxqqK^Vm$VF zO}L^Gg)6q5`{az{8qYsxdTMHLIn@O%_>EQ(4w%%k0vm0%l~Ah7fO{Kx8#4jE;Wuy>FvgdcvhnNuL zd^WYQBDZO0IY}n5R98N&Rd1N3sgV%Di-1|BCNCKwF_HlVKpgeP&nj9KMpR1rhU?6GRVKYHBpxc#)%@F+XmQ;wuULl^+HNr(cCR%pQpRyazqpV`?qp~Ny03Wz1*eX&-|Qvy~Q zBtvo;4v@ejO>d^d6B8^{jLIYe0U(A0L1))otp5O&xL(&w@hS$}x8jPm!&q^~ki%z* zntT;4ZOyD*B!F9P8VZdp9Pzdik){YMg}M7Km1I}#D(f;UcJ;{BU{<47CN8H(G~0$b zMShynRD#_K-FSevaHI|;sPU+PlDxNVx=pbG%7Wc_>9bHJ)$6r4QksofZ6vAHROTxt zmkJYwNDzriW1%TzBo@?_Y|@^+iA&MMdvUcCn8 zM5fecY6#*AizP@5m@ZY^l`&v8%b{Qex3R=ou`S??fp&;gqEh#AA41&r{c%@Yw%k>< zbnf?iKF!y4QToJ-PIBeglk2dNOky1(oi9mTC~J8MU` zs^vvB#3eQj9+5?s_H6!dPs57!oQyL^VaS0~LTG9>6Tmr*$zULPQ zw#fR!?fwU1Ds4g~O}Nrws5-=erKRDadxf^t(uZ{gHs(jJ2d2lUNJ_e3;Et!Sf9JGi z7X_KNFRPGrVD@7Cx5JtXlq)E^dA)%*A@658eKFf$?)7g>eIf6h=ym&jHW9FC3eXX# z1n1|ce@th$Zo6Y_)^>Yx)br)f6B08JA5t#=0Ke;oAKEUSYFn_mBXDtp5i7v|04m8p zexUk|s$QE-GN`PlmCEF}^I84uH0puJ`FUeM0jAdhzNqd_-JRCMXbvfKiA0Sw-~nSp zp#TkflTt~G16xIN8!l@x>Jj|7Kz^DQGYKQeS17q#(cTbRtv+S$+NIiy8z)O`|pUp)Co zPe4w)JH`?Y30@9852@EcI_%GG5U@96ZnquYY8qi^QO^P^jAZHC)B5>nHWiqkyZ->yx88aaqCg292Aw|fv?3L|^t;~@ zifQ&Nf?uFJFdDNz^EU??raB5iMmTY%fNAmo?YD;mT|WN+_S0+ATRyBYW;>(u?Z{%0F@+c%*6uxG~uxa(nUHNW-J*RbzD z`F|a=&;DP>ZXxW96ejn|(2V@kfI62UsnEwDz^(Sv84|wADw@=^f+a6a? zLJ|~9vXg6bAMd^sb?Z_EP5ACk0JdHV#)RiNAH?G)9gke>q=gBXObGFS-O!>v&jxdmljJ6 z+@DYP!AZ)kLShss5lKv;NKg*mV9ZE2I=7(A z8BHOftBY21@k#U;(1WossxSOW9JO~xn@>-_Vk-5@?II_k#u<=;1~7k zQVBoljP1orq6jO9$q7n}wyc}mPk*4k2P?{#AO{vV1h5(%3)ndRSY)nh)z3$-RwB~j z>rkjBnZ!U*REdg87??6oMwIGt*rzzzzTYLeGj_I;?x^*1QgNrb2A?(ng4)yxNgg8w zP5@KoaYN}7h2(>x^6{_x(z#BnQ({hisLX_=4Cy9RnFj&4Mn)G1kh6_W0qAyU_u`9= zKI`j_*5*!=6;CtaX_K%5AM4_{v62>Y-~{6*KsxPI(jvf~jZudRMN_5?NhdJ{kUP); zNoE^{8eO`GRICZu-ON&=l15UK_?$c3U7M)h&xowMrd7dFr`2SkD3|XlH;n-CaHpDh z5*4O!4m0R9#@9_skOevi)xm=RoNLa0qgd(>+7F<3rQ7 zn&WGopj29!L#7E58*!CV;UU(XY`ljWFjdTLY>p*5m8Xj>q!O@7K*`$ns?+<}Qj0R4 z5JHuNPneRRLT*cv!MA27+?Nrc$jgW_z?I9Cq!I}Pt+YGbUsI;$&QzDuBfeCn1cufY zSzjs82*KsJPm#(`d- z>G!=_+5EzwT(f3WtlKU-Jo$}VRTq@(3x@2gr8uiycOXHl*Pl@a8}gfs1{0E+C*VSx z65kX>CE?#NH{6W?Hq_`^&xZL*ZB_*>6`6#26i0Sck}O!TeL*hf*3{xA?;F@o->2^` zg}d^<*h&8%pi`+wto5 zqRJAI>el>r!ul5-NeRcP;vMih4!c$Zb857frczm-ASo`cB*>D^X{!vCVG9_*1v(Gn zcF9bEQJegYUDpE%h)P)57 zpS-(1=u;*Qa+rykb*VJRYG#_Kl1r|MEw>k=g_qIb$_@bV*!Y-@?K8VKZ_UVWg4|*O zjV7sMR%Jm=9w&=wRSHu+_m1=camkv?krL@}4DwLm>UKc;Fp75l_glM*&MiU>I_SDA z=A=DPilZ(gmn{jV={0zjxT7XK%FK8)`+;X9l~hVbFhM;hCqF3=sUQ&zMIX z*Gw6SAuTZ=Q5q`DNGejvDssev#J$I@{Z1_@1h~@(U!9I8cmPN!coL9!92w^X;W;{B z5&PPAl}fgf$dNjkOl&7kWkl0MTwQXGW@&>lV^v|Y3}9e&1^(W&naO#+^_ zx#FE{M={n))Oo96;!h7WAsj^XIO&75mbWZQ9S@T0X!n&xBU+Vaq3;Ttpd1yb>&Zze z;^dupxRv``6q<~<(DTIrM6gzyW&Wp-7)hH%lr(scwN)>2JD^D^31O(%^}Yfwrdugu z+>c$9<}lJC8U6?ppiXKaxFUnolmj3iFHJ@;&hzIXreBjqw;L)v!3H6D=Nc*;A;$>w zJf!5fKV^Drvx>t>X<;ei)B>P!gsU2a{{WPB>U}ZLC$C$X`V|ut#WRiO{u6e3fnZ+FzS9!#k7WJU&!|S35<+NynzfZqDpFjVLR|`tQlcelIXw7owh&e3P_5+Z z6n2*T^R(@cY;R_L-)~}z2{hWn5m8Z!ke)Ac&4}|<%YxXOkVnzi!}BJ#q!QJz-DWpR z*#^HCxrEHMD-`Y0OIGS`So2(&dD!cN?|TAW;XsRh`WgC>M>SyE*j7 zl+ktfTpVOQBZ;_sfvXerjfO3`DzfWzIFy*)di@D% zi3peb)U1PHzOQeVmD4Yi520qBzj_>!ICx_R4;DPQ(`Jg+ zp}%}LC90J@B96-ynGqs6Qs5E|Zmf!g=|yKa0ddlDFn$N7(Sr58x1C_!h_|iz>RN!jW8z`#i?iWj?_>&h|py9YV0j zw1)F2yS};Ipv7X=wy$XQi&82p^;rv>CR94@!)?X1q_347iR8t3Etcxb1f&$KZd@KZ z;MiO@4!gq@SbRVu022rl6(A@iB^gEhp@qRV<%+JmJH#>wh?7QAV5lDSgpvp?nM^EL zT-wb0z8f2-cC?8$tXfpwYc&}j?s^ouLtZkYN2sz-yXUbmXxbsDB21Nx9|+sy1Rag6 zOR8ONEZS{x)Hie5&l*KhnB)~mTVNr&y7eE~^<)7lopf-k%bl%bcfQKex5HnnqO(qo z7RZeXsMWiB*!O)pbtd6)#{+b??RV%7A{&w8CzUdx6+|YY8FmH~B!FOdwLh^H!|Z8C zrtk8Tam>AKcJ5?TcY#r(K~*WJ)C-C7)JY!c;V4U#x!7`KvU0~Ch5!WZLiU5j96!bK z=!GLkR0_Pg3Y>_=ApkK_oG>JB(V4~q_CGmOpwwy<>cJ|KtIwuxo)k-=WniHp$z+09 zhdz(0dY3fF<^+a~SznTt`Y-o{-XH3~rH zxl_3+i)_FVV|&Jz;@yWQ!zE0YmP=IStCmRO6x#Tbtx24xNmJQS)fov;V68}EY;T}0 z-$%yE&u}Fstg&97ScM))cfv7p$v|^+sLNm-hb&Gl^4(ka_M_jeskrUc-?a;ObaSk9 zQFqT@r$eVxkw@MATDcMHgjMbum?()lp-hkCAke9Q+fyaEDxCv`xl#z4UeGGE{gF2l zx?Rm~HrA_eR`S2EcWvuicegd&SC_mB-LTvWoZHg&Vy#$Hf|`ZOg+Y%+g7qprQKlB;Wx8Q8OTJw3ah8aYr$b?M zX%!IYZZwBnPXb_{w}-Pv^f!5T!rnVKMddcszbDcWUUKHRE0QaA6~PJgRol0!Qf>zY z@o8C%NsC31ZpvmHNi;guP7G^&E;U-D5Z7C&N2brNr8dfs;o(Ia<@iZqux(g$wl$Zu z+4&9_RDLDk`OmahG^E0wlZGy#2!zBek>vma%sOJn?49q@lXtyquIQk{uT<4dYF(iw zr)|@&8Wqs|WXq`4BTy<|+R<5cibHVaE*==0HawZ%tbKWUs4UdmaW@4;gsO{hRB80~ zX13diG^eT6=+KuP(7c7Npr%x%t*@gX>D=u>+qu3kdtUFBxA##>-WKzbHVjys!l>1^ zif*b*=~5QdsMiAN)kn={ebGoWEx8pK*35{`_<$!=gyc$PtAh4$_JZH-t2&ov@2hl9 z%(PypIZvnG7G1e6zfGdgbt`&AJD#0PtW{hJisPz6s`WI}YBb1Oi^fyY*(>tlH8?a3H(84kXhQ^^VtVa1v+XvTh+H^?e zqb^IbC&@qJHB?fO%^3ajZ|7WnZrRurwYMGtD#?7jxzB^p$A$Vcc+vBd^1*pJ!pN8Hc09P03nd;|)I@!=B+V zN{`Q{QK9+l^f9882V$?gi2ne#%*{xM*QIbP0wj@6bv#-Dh{TNJpzD*@85=p%iqN^3 zvd{K{B<4IfA__)(o!!28j~+L35*)IUd&T836wV1#9rnJv`s1@GTNf1~B7iJ220(UN%<%+E&@sqoat0$Zt>&=zxnBq2?#5^;|rlr;YUZJ@hKNvP23 zO^BtY*>!~!=Zgjn894(@ep-*iY4hye9TF&aD^rrnqoSzW$q(@Iic~b?&zA!rjEz;p z+-*qHV@l7WtWZKYrX58{b+8@TE=bJVn|#<2cDcpIk(ZHS+;OXIwkx#=ZA+fC zra>R0HlVyEM0M-+Mlsi>&Tz#}QcWvdhl`Aq0~R7kV73H{KAQb~aLK@fP>Q6&T0qI( zGw)~C9c$J#Pp=mu= zYHSvS5QR0%r=9|}=zx%F^&E_i07?NJ6s~|;Yx65?(BZ&PB|Y9`5(pyt>RXZ5O|gk` z%39L^rAQs&K~jNBGPfen(iNzK8aEuz6m!~Ns#=|Koi47!- z%t0z(EImdE#o?Hg`AGATa+SbykolCQBn_U$ucDpx#K54%T&Bfts={MFoQUqteVNjE zN*PgfM**5z`z^E+$yP$hQcl1sd&Gf3sWna@n9jDYThU~ytukxmk{E=QsY*E~15uR% z5(YJG?R$#lxVL>=sY`Wgtd?desS+DYEH&=n98nGa&T>fW-0as>sW)5C6-b{$n%vkh z$eSWnYMU*QDWp7184>uIUkP&oO@yQnbSFC$qfx1xJr&A?WhIArp_xm{1E`aCKhVAK zj<_|d>F(*s$o4j3k!J^B@2@!KSQY2s?emu;SxM88hqau4nr+O_k(Ml2&eQ} zJOwFvjFQsw-k<^&(5o>$(+)(0rJ*7$canyN5P<6_SV}eeiQ?f-I{}}B8Q%rVdeN<` zZi7Ch5-lo9W)!H9idlJ{Vv+-k#)u#eVL!9Q zj@fqMnF@UDc*3S~0SQ1k${dDmoE}f5?D)+~pvc!HD-zTGSg=)|5hpL5B_wLjNo_9f z1|%=CHu|q!pJTB!JpMM?AN9?U7v|B z4xpq({80+BgvkbSI5&Mpgnu~^w8}LBKuT9n|VpLAW-ML+enbgs%iwmi0e(O zggj5|6#x&z*RIh%=JvwhbW6a}V6#FHS5#XN*rwCXK{8>b;DGa}7%ZziA#Q3jrVkdy z<#>9bISEk!3=&nCt0>SL2I%JCm$n#b{0GD}54@F9Lt{H# z?c~A&$+1p`WRhey-s1L>8*|)11YhU7D)Oqt#t2#p1I6ewO?v|KCGTmW0x(&H5`r} zSJSkt3~CCp2grTxoEhRFNz{_E;#d@@fF0N*5JSCy`5su+PTS>T!<(T`Or&>_XGEhg zZ@P#QO9yfF2h`$l?h%sS?&*!?KsLD}Q-W~v&V$ol;B4@=6_t=d%Dd;T2hUO8_-AG_ zangfUQ|gxJ;cBA$QCd;ZyxXgE5r7FK@PnLy21&@-$+c?L8qE9QuRT8S=|QEko)eUmjC99b?9sovd$J^&)!3MA!lXue zS$bT7iEcL`*9V7!2sugAfHA50(7F%Zd7$N~FEQ8eeV{fsHlOu*TWZS&~wc5qpgslVPA9)^l%sVv^vg z7(pu)l1e}!Hvq8(or`9$az%}?Aos1jd3H6w7PUo=-D8_lW)sZF$dJlhK5h+hl%$;G z9*1a~{{Y%byuJEHrJ3$IK@`?x$fh#UacNLWRO>+lLy}11?Tqv}+DQ9C*mdiwmdfaL zDohyBone}Lb5qQWB@&l7o^PU)gsX%D_4sttXe(0OV~D#U-j7~yCgypCQfqOL$Ak)L z2mlyQe#;31QJ*q&>(pB7Dig~LKnwuYECPC1>UO@`5dFgR9v_NkAt-EV*s$9!`>fO#Dm6x$ z{ECWRbrIfnKOwgmNF*eYfS{D?jd7iDPTbhu%4JQeQmFpys#mBkHmUS>R(bK7c)P>I zI&m+MvG6E8wu)0I^+|O*X0KsyK4raV)ZCdOM736+xcuH!q{(%~F*^xmm(th|a{R># z!m*~`D^|_LQM{SHcUf~(*j3eXGbZhy1$O-VdFotN7>4_>LQjltORH(aKafhCS0{*h zQg#PD#IOpKWfIUqU|8rIeSrrU;_y8%#VU%GcSr?bvG~#fMVp?wXv96SBrAKyy9!;I z9@vneVm|v2oX<5btqN$Ztbz1kryAp2>$4BI?`k-gE&kr?>kwzbu0(ohneRjN03}LN z8IPQK!Ov6afCkbA{kUz^*sG#SyI+A-eJs&^=>>_*)f!zyhRe-~g-TN;Df-Nkz*iVf z4;CTPDqhRBCC2UbT)HP4xE5(H)X}Ho(Rxr6seh6)z+oeH8hBEAk(0wEJBr)C|M2|Cd3jLw^j#|{h+s}QQlqQ zXi+WMQ)AI*9}L8(eAT}Z4umP>Inhle8nltG08f3L4eeidtr-^0B8x;d>DBsFX>~ec zq6t!1Lbz1(kfGVxg{d*&DkJ@9vK9xbB48v2OVbU=~$4I9?Ssl0x1~xWOq_ zG6}*)g9Hpq1;U2xL?R3tvr<<^N)vKaWtP<$kPC&CB$KEb5)cM4q3?z-6!?frf#Af- zqM>O-F|o<<77pxfd$?xDioG5bv8Bn>D5*?TAyE>o0-+SJ4(v#9A9Lx5)i&n5U{fjY zS+?y$by}iJ4#%lO6lQ7dveHYBRFqGZ#+Ftz>ex?R0cy9aP~KHu%bd+}RRNf-M?{CA zL~y%PacfT!{3C>pHj0Vmtm?Gj_d7|L6&UrmWF`#6)Do1)W5pqS#Jw^iI8_}h&=933 zB;#D;9kztk7I%v-_1;}Z@^)P&+m%a18&(w3MKOG%!7tqekNA#rcM-kn-zu%T1-GdBmhmc+usUwnHqe`s%RARD7kgVQdHrTSb!bJugT8Ar&L)| zX^;e5iG_525Tk_*EaQl4<{!1DLHTVYH?O?C?Cz?8L5&{mw`0zmMsBL?hbivXnxRpd zj}9Bv>w*%VX~x@!IQyzKHHVs&cih4}78cittQ5z(l*aAaWI3K5RZ>ie^txp_g%x2n zi;}TfDsF{u&=yDtxh{nvO%>>rwAos)06Q_h(6`-ArEsRys#N0CE0p01M)9Ufskrqv z1>F&&4U1x&RQu*l3e$$Q(;ZML_m$7%?hw;ysigwQ?GuX+3sI0%r;fUQM3Su*q$D6d zj!(Y!vB7@L=?JRSAd`Yd+1tv2JP-&Y7b~j4$`kC zT)G6yqD|RajZr9d&jR|zTIIYej5O4ARIiJgq}w$6inf**Zk7ZpLSsNXhG+H6v<&_AIxk8@IKqo8i1=(&=@Z zfd`*M+!eOP^0N`$Ou2*p@tir-RLqZK7|nhWV}css^(gcUS!=amlA#o4jVdx;^R9+YPIS^jXz&qSP64Dhp=nrd=&X z;YVykT2UxAwX)z?`q=sb2j0EXoM|9&bzTqau+K~8gqD)e% zu;*pr=J5(byu?_7EJoUOVXNzlq_?XvtF*`y<7Egjns1WqP{fwO36M+fkM99%ePyzK zrWJwa(Qygj)_`?ZeRROabFXac(;m1YD{gk+TIbj7x~y>u;J2J{H3({0<7F=)4@PmO zv-EViY2uwi)CEx`Q}xKk&aL;o3O4TPhDA-aRBIJPC7X8Mh<~*zl2CwFsQuF#G5~gA z{{YDfA03^dR4Frb_0K|30vsf*LBKucRF&_tpG$k3R})k@$P>wuNX-s3VvwfH&Y(j( zH_U!V4h`LU(5$*^wTqGV+ovr7h8SZ?gxZp{g-?gjnX;TA5e|N~d+dj{Wue-Uy)XIn zdOd0QC8}Kpr7n`vZOR+tEkKruXPzz!lO-}Ls!+j{rEp|mZ4d1zo59~D?JE4c;-;f+ zP+n712uiFf+q2$x{8{d z_Y7FE_pluB*BgW7Y0}W*$4N@cQeqY%Ifw+VB4WceGvR*<#YKwGpaqb>z|4A#Mj1PnA{%JwBzzq7tJD zVwj(zfchOy+dz*x?u<<`{I@D?hQo@FQQezv__QfJNhTe2n9sJ`i9TAL8KJ-a<>ybGU>NY{vo>7FucQHc>ti@Orc+WL|}*8`=g)X7?eI)sH_A~ZClDI(-9&Xa49ZK-z9TM%>d zeO$9`%ZGYi&Nr*a#-^iFtVD}H`_yXnI6X$V=@j5{lEre8h<8f>5IJ<=fOE8zyZxV^ zxMxebtw|9e?;e7mcU-ioP@D|y4)?U0uI;^{ zoV)C6X49iPA(~CjYc%`1j?F?e*(psDu}!2&s$DGFl^UFw(5dY`N1DTHWy-RdEg@*( z7ATv->#0zvyTGDUE$WpnY${aQH>=8ys(n7!3nEoU=C|T0ahrkGLA{Xegmnsa}RazGsV5y*6sY0&XfSyG4YT4HbR!{8dM#Y)quFq-S00A?*kaYB)nL`>>4zL8Z)m9?6%?$eIU%0lC_S$GVjJ!P z>4|8~GxsBW-FvdHjv19JZl79Wp6rC+sJSxSTN3Sio|L4hl-yMYRLR04wzeN}m)f=n zKGw8t=I)Z{+z+&kFu84CR`lz6{pV9DX_ZKARc03%nU^KC;w4CT7|g{^~^NtMMJ<`_I$!iuKsUJ={DJH6DCz3ivhGa zgOj1&#^1c^^cXhfQdJS_iet%*Mz5`Y?x9rj2$L$K6B(w>LJ&~$jJB2BIjk3mezUAdedtV+@;&rH(F#^3r`c((}7e5(6wP`5v{W5afs;%aYfDRm!pinG?$;cvxx#_N!y^4(K&mwJMg><27L?-&N@G=~W4_P@$^7DiIy zb|LnY-o>K5@5r?+dgA8Rt+=vjYLg0qI;luy>5G9br%ktr< z0Ty*yi%u#J_D&I8&x&qIwMf2GD^&~DJzT} z&QFDub{Zes75cqSQX)aimJ$?G2(vPZcF>1%Pg~fWB%}`+AR&Z=G=(jQi6-v z<^}23u65WH#j0GjhIC0~CP~53>;kX}>{d_kI%8vIp%hCB3E|{3&ned-NhBy|B{&H@#VybL#VLNd;sob78OX*CHohsa%{HGaF0j!%w5e8ml!yBDKP*vmCM@l4 zbx{gT7%57jXrc~aJ$Bu_G&tr45(l6I?$i4I8#I+T&;EDSi=`qNVT=`Mk<(L?f{-zt zMgThcJ7b{v58<<2T#+SrBI2qy3_(vp3MA;SQhMYN5A}_WNJp44yXZ&m(2|w@5<=Kp zowk2tv^n|Dyn==xfS;y~IAh@@5R)g<7g zEaV)N;b7!-)MGivZ%w2<4&}J0PfB)%nqvk++LWqbi1f}_$ZYAU?c?F`8&HAKZou^UWUi4-urOT<(y!W(fZBpF%bD*7;tEbQWMDy-qLmCLAC=TuVbEjr8c3)J}X6yZvvx&ZQ} z1YtNDjEs%E;BU9tuX$d}wZnaG{@|!NZ7Ja|^N!to#CnojURYgXIM6-L2yIEnRdmx^ zKlVEIow$9VECWxwFKAKkD{)Q0tFt}u^s0kx0GP9ac!vs#08t?%9AhII*R)A$DV~}Y z`B;?s*HDKqnM4_vx{~i@sfZ4%GZU^aF4cPxfk)xV9@O{)j3M#I2g#u;uhSBgrX?*A z05D=JC}M62A%%cvxPD{WH{3Wb&!0!BE(DU{j_z>~DeQ2r5Kg!_9Mh=L80oTR^|UK1 zfo?@=JII+S#Wf*s9Z>4YAOp~Vl_ymlHTVsmf~Qud9DjLS)F+85l#h3wg&?-TpU|>& zJe;30c>e%rVf70p%df_cE1S-)O;c|sR8pBRm~s=z00){xAEPM+BMNg1$Um|M)+H`N zptOXURLLZlO+`#|p~g!P>=UydxYno~V>c}nMui+kgAt-ZQ{6Dtl%g2}_yZ({Jo*Gp zvAJvU>N^op5+znbnM(;}>0&yahVdRDqMZgCO0o~frp~mD%vL8^)Y=OTI>lC*UW|u~ zc}1qZ!W0Y95jQ7`kdLEKA5@P(b}nk#v)N!Nd&9gRT3iS(`@*UuzrrvU--63rykI1& z&7sbNLx!VS5t7T#T$jyB4W(&3>V?2uUlBPP9B`zZ4*fdp%_mHrl!#U>hM z4AvaA7Xh@#i2P#`Vk+W9Qz{{K0BxYNSP*Ter%XPyibV#>ix$+ULos4hAyic<)k`x} zr{u6<9ytV(;Za_s=mEz}4WcE}ysAw)^`YBBZyzd@++PAZJtm(e*a*q$2~2d1jA%xC zY^+TKcWxO;2)-n_B`I47eanT|*;4WX9O_1Wa5L-QjOz<_3{;mkO^sWfQbBEjIKz3u z%GA;@c;Cy)I8fEiNzR}RvBjjx#H&myI>c2jOf5?v3YKz`cMjug>Og#Cr*UM2lnC?M zEegn_xw?U8XV5=g5-{M@E{kUJwd#=S5h5Y_MKB?OJBNibI3zmaQg8slrzj_;1~7Ed zt*%@b?csIGmq4%D^g2x%BMYI4lfr7X7na&fi9$gDHkBMCYoH$-89Te{SDf@%c6~_< zmm}nDkf%U#PDxHYt|>|-NjNDagN$vvHpQ(G#((`6OP4MjXH=QZlfaN%RuYVz z5IQ5a2ptB}=&*K}1#%WW5I2GBl^Ld#N~NkP#~^5PD1l(CQs4-Q67M$Bp{6A;llv-d?VnmEk z1C^+=q*>LY+TT6!5!90n3Kd1_gf7$(4g%)+YI-p~c^R?FD zQ?3HshqyA85K=s$M3OK-1RVAUkZWGd)QaG^+qeG!Ol@j;6$j|`C!7x{)SxXWmYx7| zNh(jDOmxWD3~F7<*jk*4ZpTiefvR{43L`^+dmUAi^XaH(srQqGX=A_qW z8Yu%ztPKYi4i29KD3O#5nQF4v1dOUeR8pl5K!6RN=avUe_Qk}|Vi{Q#l)zdP6w6Sv zIUg4w4>sz~f4#l!?(+4urP3&rTEwb~c`@TkMYf{ALL5Sf4yfe`$3+D6IQ7}9wCSo# zRcDgdCMcZ22r9zEjix#k%w%JhL0AB5lbw9I*;f*acP+wIqg{rx1qtlu~&h zcOZeF&|^{D;M!I3Epl48=AkaO-#s4g!)}qqj$iz|N+gd_>#-_oB`ENwA;D2pNrh@o zppaDdxo=-xu~~6FW^aq-DTZPEObL}N0{KBgfxf$rclqF&+uj7bF~w0P(WlgDiK$f| zeaL@Nwq+xNIuuVu7r|CB(Lj0R}+Z-oCN)(+( zU&CP0>>1A^F4iVAr_V6{kI3W5!B-BM)MGd~#+`N+o!L0bkn5Exl2liczZJ>h)Zsii z&Yqy-uA4xQDMO7A#h8~fF^Rk|NVy@)f(4%A*A4XA{{Ryv1iZ2b_*f8v6U#6Gi`m7V z!_x|tdqCD@CC){IRSPH>=gmlCrZwUGdY_+Nk@a2gT{FT0ESTtdqIi=cpaTgx(*R)O z*QR@C8!6FY$0$b}xtw^%{6iWJnq#m7xzihc{{XYtiabH7k7Rzc$LEXUe7|R2owKw^ zwEiB55(OX(stWTh_7}RezT5pw!LIQMh>*mRTG}%Xx_(4kY)5PNdfV5lK$lC8K%&Ei z$Wj<(H3AUZ`0~gHBOxUEX|AM=qWqileN;5I>x^5jNP#9Jh;n*@kg%L(K|>&=Lr`<5 z^Bs1wIh(Ygy&X)+hdFXx`j30V0yat0OlUKl^gj&f&RpA*r9RxWDl(QsWg%r;Wmw1x zD$^xcB&)u2jhSe%ICV1+<>FESgtVy&Qj`k@05QF`)t{prE%6xQIPq5##u;qmT|%@h z?EYJj+TRpQ?Zf$6J*anEQFhDSw5lZ;$c?2{N%Z<}y}&#pi->d>B!Sxp9k$J**SGHG z%`W1-0(kn-e6==%_jgk`N`^@B@i+DJ@qGS+jcuO?EAAB-WHRYnV~>bSc`~M zr6wAQx_48X2X9R_$8__=B32OlX_>-Dtb5)YPgK+KoO4c#a9o$%7{z1vgZyUV5C*8KSp zs_BTob2jSUOK|eqL|5;Y@}fZMPb3JMB#?baPS6;z|MYD2)j0 zoai*z$kwiyah8R|r!Cc|o8liimT`hmjSrnf@T8pQQgPE~Sxy44&Ouc2t4@i8fK8c| zmDqux>2c3oP#@kIDMk1c(tD_q#E}#60ssL-YOZ>}Tv&~ny(*J-ySB7hROpgv5K}Rb zxZHAU4?3Kr8M!$Fs(~kqQPXD5v%4D#{jEd0FU#CUdaTl$p8^=lsqUiQRny!(^{ezr=-%Rz{Ot$7poeAl68Fct4fiK51 zPG_ElP4KRUR8g-AIoKRsc(I)^w8U^tMm(%YMy|$LAQDB%1tHknlH*Mu+|S|q;^gNS zFadbZQVqs{jdZ?;LG;AbtM0FQi1*?Vc0zn{v04`)_ zB|Y|P&8H?0=A;!}bb6S#((~|YP^MfI*W|6o%2bCc0RD@`%R|Xe_@%XU;l|7q8ZFA~ z7Un%)CZWKm;kN3Wdha*xBPsFRKHtl)W7?kzE_;6%CmUX~9AskuPI0qg5 z0oyDd2Al3mV%Avz0$2gbi!(YvZ8bvaNwSu zN2h%Us@64!BTi)LuAqz+9Zybxefkse*gQ@HjT$mj2DZyef{Tk3hBq2|{%wHL+)W-< zELgCl47#EytS>c#u^!elInyq4Gex+53;+$%hzAjWX!aAU*Aq73i&VxG! zvmvU_p6r;i>akvQG={2hroRrS5hL}YD^ox2toBxO&tkj+`lc}Hv+kQF!Mz=ia@=&d zPPGk6moD<5xWqUUnt<3+DYtbJF)^algQty2U~*g|n9&GO1`Ov8O-N0V7PROPz;x`Z zS-`PvTWi?sJNx4`7Ghk?%6OoaoT*TJzEgKUKyB%U%GtgzxLd5aZaOU591E@$QJ2Ai zO5{`dG6F&sDV;fdNWzqzbWu3zvtLo(J@a)kqkq-yXPSp1T!$a0x9-K$%Au)ClpOy6 z6FRRW>m5!udFflVpJ__2(w5>XR^9lA-HBLf#ZIAcNXzl!y4r{KEc7($8*QY5I8ujl zO0XLGM(nKFH#HL2uFYZ`7pv{t)duI(Qnab5Pao10rKz;2ObZl3O40~9NgHCONWetQ zRY#u_MGJ(eNG>v~FmtH64j5`RHo$ob^l8|$aA8PzFsSj<5lUxTNFj!&({GbvJl5|w zcWJx&m$VI4C}Qocvs&G+vgIaT9;nmUtJ2+O@!w@$iJn`REn<+&ihY{q9C0@DRK`eY zyPn}*)!{bvqgnRlO7*;}%8N>+w>qa;txb99&NK|3bw;gHfgBkVDwAg<2+YKTe*rn-QLk5rlO?Lo~=--G1pX=z#LjqtCFrG+EPMD zPv-3&n4pkJ+PSy)yvcXg?rL)xl_nj&^}}yaE!D=9WX7ph>I!OX*ssUx`xf;eyGn7Q zK9vPYIVw9u;w}-Z@&5oANz&pKeTgLw6y({yQ{05A8bY*U0~`FtyAj#NCZ9~LrnLq~I^V6;rMVhqUG-D5noUxlPjrCzKSX$yt~UJz{f}rHu($Vm)vaMx zD3=`Ta-{tV^QllJ3al}C(c5X7>ZMm2Q^H7zM^O{fGUryFbpNRkw~47{3< z837Qag8&l>3PKH@-e7*Z;=AoK3@TPh$wZY!nL%4IH!IZHwdULITp+!eJ&)*nh>R;2 zZRdFJn|hPrGK;@_Th6Ifs}~hhg#p(YrA4hwtWzy3Nu`A)6q{N4CmH}G9tcsZ{ic&daASG)5necvQqx1s@XOK2@{{;vPj*CD#vmVh|a!iUo#BxgqwFntDo-xI#jd(Wuc+r_Ff`?6Yz21*js4*geDru@!) z!Sj0c!P!1NLK@=0F^j=;xndY*NIbRBxUfFBTj1UrmaNk%bxt589_2}tN(&W402Hgr zbp()faj_a+7We-EDvir3D0_D-w^D^Irkh-sm^3j3_nTA2j|53l%2JX`DgcGkJ6r9OGG zqvD^xJb7&;88|5eRTGi`86!9t`E+KxSM)EuKy-mBa;OvF6%=8-x(-=$o38?^Un6XRO-Jk~Aq zAyjwIyQ$Q?5!*I>-@NVTDOKy$7bE7KRCcgGHYUYPYD(7vG=2uDpj56Jq)8HCKTNh* z#5zqh)gGzlIibYP_HL;ch4>h^;%Uq%G8@?xlU6vX!W$w>DjoZ z!wGV2Hd?6VT(MDa#UC_rwTw*srhAIt6+!!3bWm=qqFYFnHlcsi={E(RM6zMj6sG1b z(|SSt?rQCj#voDISuqRfc%M3)J1H(oQXHxy#H$zzT0vB}Bme_jE}o^2w#}22%A`2! z`#zE;WkE`z%nmbv2Tf6#} z{P(RNlFd(j)v-gK^Yc^YlNQyTQWcci)YUpxhMKVK+I(l42~>)`O~K<86ZgmM0C+%$ zze8AZ#e=$=B6Nx+qR$%DNrL+^U#x4H{{TssQI_J?^;T5x(%hcpj%RGc*p-{$vnWw_Fx7JPsTs}8oqJsdt!UF= z%Ui9XnsO=hi(ay1vdL|>6D5{jN>Y@Yh$JOxs)SZkA~8d6@E|8d6Vs@`8f(`8kCt@V zD)h#Z>zvtKh5}!8_m4$#8{^6QJ|j`kt#}8 zn5Z+|LG*G>o!;(GK1{y$w5~V3UD#Rs*0HIOY|EE+HKPLfvgmaR-Co_S+gB32B^vml zR%gzsT&&B3aKUbaaM>=;sL6*it4pifbLF<%QXF6VDf@a`7Jaq(fpAeSSeE^96*_!M zox4$fte6#*HlKacE*o<1wTrg}xTg3nTSnwk)pyMx{q&@icYIaCNKg`%m|q zqw&+GHWTBF^zvtF2mql8NDKyIkN^xlhTA_|GM!AP0Ged*cxqyTKmY@kfYrk>E(?=# z#^Qap_w|0%_xS=MH_g1uw!x{zP_`%wy6%T*j8dN*RMf?dYTYg&>a%HD7^yN?a4o(j z`Aa0A$E$mN`_|oMP0Na#ygU8MT2xxD#;V^}1;b98#G&CDsv@vWN+nX9lfy^3;^p_T z?vOIcAxrI9N^Kme2JBMJwgoHc7XW!Yk^T9YBe&LsSIFsIp}sRx-HjYL8V;{ zG|#y%8f043X>Yt3W-PQIL7Kyle!^0;aTRt0J@wgc8l};A%Yq@wRA|ut=_IBh%3CP1 zgSNmD0rtmp632(?MKtj6{G^SW%VrweZhG^?thBwc_kmSuv-#&(OD?pR^5W=~Noi8G zZAo(N;abv%OKW`&5zS#PBkL<*HJhSs*)C;q)+w(`n1S!ssL<&2xV5=CNOGqRjSu@S zl{xf~mu1KOEU1|gK9RAs22vZURB1@1C%{9II8or$=}}|FRG9J-v0SS*B@Rt-O})ax zSR^?29}7QDTiQ-jtUdBsG}{uPS+(kQS|;)-EzGd%lqPC*nsr(_WxD~0?#E*_x;1se z+Jx#gbc#$QW=h9{ZQZE4w`M4#&dklx5TdA#5D=4M={h8A&DHOR>OU1y1QIGr2`Nq7 zfRI>ff2#yziX1g-bUamw!P6rtIFR+t5s_A-97t8pj~zJSFPGA5ly(aQE|w$ z5@J}2x2el^s*2hV=B>_K6*}6D%FAgrthp&md2MNRmy%ryVQo7d&M?_a>y;1~vtM`~ zBO%e^#uSy{aUH#$eor4_%L0SD%c9`kBqY~2yS&RHb-wKx_9{xIS=L=uhhsYui&U09 z#d1_7IPpzpxo+VMql%jZ`>8T^@)N#m4XxI1PkGz3LW7OiH{IE8N0XrORQR=r+or4y zFc^%-hr!S4v?pDPOUup5NWqt=d1Eq1n@~numutT^>f5VR_<~xuRG)=RFA4&Skf2}8 zA8>Dd+mHd7C23ssn_9a>xh?7b>#k60km}T#z=j-;P=fMbjOuCwSVSo#aUEBpdt+~5 zKF;5ij{Wx2_H|;<-Gh`h`$XBa=#B3RfqY!PcgkgNjJQZ_juGX`KHLOjoghO#q9C*ew1yYei} z)7UI=#|uf;REmH?lRGDpB3K_bQVN`a<-on)pki_8*K{-s?&G@aRl4;u4SsblzX6+; zHM?+8>q)qLB}K}G&gv=@+FdT}sL*E8os~{i(uQ2KB|SOrQ=TEYAu`77snzNAC+`ZC zDvtW9byQUCY7@dVswE}pL@`uExon|S*=VUy%!W|dgI=9gazSdB35U?KS`W#CyiM3| z0u@&Iw(l3DUNY(L(rR{HX)VH^ZqsDB&5>1g>X`SXK@;DC`cp0u@TC}Sye%plS;gl^ zVRSdC)_t`aT$-!zPWNG5HgsoXzY0W{5(^i$X&H$r)joV~Bl+iYfD1hf!rH;GF^^xoAt2$aj?JjK=3`W+>xk{N( zLLjaL7iz9>xi#2P@?!}t$}8rsm;IFEfU2MRIZnp!T@%$ZB}vMYkz`Ow?7?|Np->@$&J>u5Al%u&BTH#(94_&t zRKt@pQZlKUsYC>!0ghFao1GZBZkKn$&P+JzZd=a>khsfKH$;ZZZi3#9hY|ZK2n*9) z2=B5+L`GP&q>Y4K}G zB>A2NLx%&(2E`EO%ajlviWos`6uzIT;&GI?02sp4!hJ?Yd*fhI^D^+Ehbn+Gbv6t} z_5gl^V@gx1-V!j7tjTyvtayYjAvRPpe5rej6Vq>QKw}>*JLo%~yInSC?G=5 zwAi6E=7~fl6t=t_Qnmid2pCcQkV!bk&s>q>bp6qc{04yhj-NBwY{G96Y}i*-JHky6 zxM0mVC&`q`2U1T=<2^{h)EsS|N_Q;WI7AVW$_G=YPkla2_@5aw%9}Fq@~RQEH8!vQ ztqrywp|C0qtr1V~zf_v1P689}1Cp%g85q;9nZ|nOvy)G?=<-m@Z%LY^wVx@d9dMKB zr)=sor{5hBBE00}NnOD|4!V>P2|+F8Y6$Zys!_zQqfxGhQ?#z8ZUcGfqsOYtxZ_h> zl^H3FnY9pIl^#Mu+ZhK_s!2V_BRdw2J1gHPMmKU&G+-Hymf!ucmTs3Z1H12uWud@u z&B*LI-)~F}fosrAcO#U_SjtWusGbilzN1n0X`PKzZd-u~Y1qw#0tx2K4l3>G2e_OrN)a&QjnCK^3=Qr!=1SJdY!6u8?H~XKeaWNano2bcR#&4s%R@g zP?t`&s`YZQ9+f6HNXScrjAsQzl;k80rnzaR{-g7OUQ)Mx~|2#svo7qpBdyxg;J*E{{Y0Iy5AgSWMx^;VX!)t9-C7zrwe$< zD+*VaT%=`l`aAk!>Fmd}YL^B}R(M7{Q^Z^=#L{blTA(RJrkbRopiGR;#YfD*^0wHS zkRG(u+YX^rHK3!Iry5`}8BZ5oX~eUitWX(jxt&2N$k%5!6;{(kX4TH3v`_%SG_naD z59z;1erY@h9=uyYxUp#HQ-(u4#XlfQE;%JqCP-P08X~1t2>O*rQwaiJscEyO4$kck zH3P$^Fc^0vd7c;}%k@U5L8!>}_-tU!E(EMNiYCA$4ZN%@FQB(ua>Ye4P7tPMV?zW$ zRLoxC8$*}Q@Q}jZR9fM!ai%4O9!(yy+>=Z9Y{z1Nr8d`t;cX;+f6%^**E!1cIn$}? zVL?YE2jIN=f>x$ZFqJD_504MtI%(5p4%@9#=uOIQGa@7Mo8gQiL+35mKWPDHAQA}j z^~b0>n7ey8;pDMz*Antjl&q?ra;FlUEx<^}3ySjr@zY@QRSCGTgh?UiHX*HWEcyaA z0gi;<1D7`<7DPek1(jmY zHP=RZMA>j@s(~6yMpSg^Qbb2q5#r)>=z*tBgz11b=KaT2DdxRw)E6DGmt?IRrLd55 z#8H#Oj=0G0+hpy+^lGwc(jsvdYSG`0g1nW9EOBHJ@KDEGe0CWxIaZXOhZ3OWDoE5= z1`aKKnDWzHNrw`hI*|wrtiX^gSO>6fUsmKW;yJxbc4KH$MtMTel7%@3iOv-y6qT#? zoZ%pqcO;(rlS$rnFl8~J)@ER1{v4bU(BNZH_78?MJ2v!6vdtv4@9UvHsLRd)=CGpL zv7ItXN&f(Fb~5**p3;E$WNGl}vs{$$Dp3J~iBKRmpjq1g04DliJoKlGIYp5SfG*FJ zjc(fwJv73dThNOoDqrUPWlBI%N_+<&o(!eCz)qD+468ICR zs=s7$$)Q$uJZGkCbHvwho?MA9MVck8e7AZ!)GWSw*+_hn}H?0l=f?^amPsB;)0= zQ`^(H+e2$bu7J=|!RAyvxj6t5H9rB3Po^`m99gvV2bVKg=>)_lAo!AXAa)qyJ#(J8 z*r9H^^2@6Lv>i!n1fL)}9YO7n^*U@)LT|ieFfPMw2_F9d&#nN@$Ve~9a~BNvKf|H* z*ca0G!Rq&sc|P#vTTt6V&klXz*U1N%2|F(di+mk86r5mWj2_zd@A%_oB|ZUjJx&pvfI%K%_#FNC>y3@VFySpL zT0lS`k`e{1{{X+H1)_x@wIw-}=HG}GAXpRW?mbQqB3JHL99fLaHk9B`Em;~UpEssR z_-EHWws5G+xg>l&M}Xc#&BS=(@mw{t$;>4V<2Paq4{;~v7*_E%DI~K8jpu=+78|S00KZp znlU1flH1&~vt9oHChLbeYHdCY5dhkQo?BPAKsdSG|^&b_wr znj@sSBQRzvJi6%3^y!Sg7M}%+5d9qJIljPYwYSEJjT?nLWUW~9D~GAqWDQ*SC zn2X6x93_8S9X$U45Oe)?iF?Z5B`(gb z&T@5595@jiWyLOZ@Rsp3mok)Vgp{i(NYo4g(>pR!Y4bHns50{9MkZB|2RyC_Yq!&D zW3LM#F%l5&ikQ0)`vz-YdkYf$LNYLcw^uzH!BOtvMTiq~ zVVOM->~g}rPM;)+wSbkRTEQiS!QH>KbLJ>=FZxDQW>N{?Iz>rp(H! zQe{RAGb(R_Y!xOD9%gZs=6t+~Raxu*|a+1uyz?LRb}AeM5V0RrHXkOPO?^S$xCbCsFZ$-zRvDO$i-Z^Gaz z+UT!+G;CTegM8JhR0vRNbjh)+R5JA@tqd{l=`B=X$a*C7&X2-)h*WfWbs<0!qq3DZ zM5m+@X%k#SPNgoRni|VoUr2cRi~;tZqo&Yr+3xw8^-i-wllI2A4EtrHC8*M#H zs{n*xXnq?Uv3oLZ81kaq@?N92A+(xZQla#cSSkRS8UFynap3$_!ZvD>`Ef~3Gz#sK z2Vb*O_w0EM{{Rlmw@>UXynpX({{SzSuEd1&@^%|+&!amF*jf4SfJ#A#l7zj(48Nm( zn0@5erYgHRZd0R0g0&^)qrs>T0TG3^0vQ@-Dc6W}#!hjv(wS3vxbW8l-Eta~Zr>9KpE@E<^VuoTHK+M+FzIQu4?~D-SNL$^;uHgLkJx(6VT*{_dL1G$< zzoR8$!13+j5S9La5TDy9zo4dSFbMHsx7`47Zfh2&vkW-DIV5q{-rlTvoSfAb*ytfH?zlG|}AOrX+VTlm2r2pc2{2t}me2?})`V+La%5w5zXy0)OW;h;NGUhXp*Tl`%;?)sjax=nmTKdr?O@ol|KetRD`;+yss{S zBpeADcOz!DuUXUSDNO=$D936wgs-IB4Y`3=XV)ePp&duW}918r*lSq%5=8`mg7|e4L)SD3dCX z){9EMVO2MV*7Rs}OGeL;Du)iIMRFq&XGwnEa<@*tU2*5`ilmto=n`IO$6j`b;?&yQ zTF|AHEmml_J-rFqn}{u0`P9m91!9>C(O zeXTzyeT}~x)@A3ro579J-E(Ku?km;WggWhKcePmb3LSR4Ub!SuD2rzBpxq2KkhMv* zlx?XY1yW79Ief>dhk0~Zmg9S|-ONdIC)4OP!&ItHNFY?JNsyJwm4lTW1eIZaU=9ws z+Sm8bzI&qSwd;Q1l~JcluSccWLbnm**BoYuYw6wv!rje7PnG*|)!UYBrt`_s)~+js zK#b#R*uAX#;%(C9emySOewg+|dZOy)-$X|ah>lm$q`1Bmm7N<;pQ?1e_$H@MkdO(R z0a4~*r7%=3rDX=h>UA3z8a_5(g=y6_OQ6gx36+G1MJaFv^*dh7K;(DTpSkzEs%71E zyF#ee;$2i`-g?}fO`9g0P_$WY0%#M=Inh5!iuFQj>d6l=^r#BTb=v)Z{M=7!FwXGz zwd~1o)sS4d=#h7gX|Usrl}oErR%y31XD3wE?^>lsR6zo!`rG1JQ>$JAc((Ip?FDIE z+q}Qty6cqInt^=MrKy*wMAR6gO`R@1L^7(j54_V*3=_)0;s;C>X#u@k(h%GAjU;KWh!qdSWzq$qo4G*KDhl*H>F_Hw~f2n^`|Ka zVN+>x*h9)AEV|=M4LCI(VDASA8sPi^+rY23&6if(w)}32EzK5HG1&5#8boOtK{F8Y zxGHBk^Ua0B!LL)-Z)dl!w|?dKTkP?=Uuiq}>b(-w-lZzpol1jEf+|%w&e!QIR93{M zQgU0TEyp9YaG;d16^!+vf6B2p+1uM|bdvYk?E81nuDjyShV0t>8fOa^5?~=ENou_i z;X%|S5S}FECtW~0Da4$Xhcn@$2P(>2a0$>4u7}*>rR?%nxh95PIL=c-*9B1sIRhJw zGP^#z0AC({PV;S+*(hCUIZhPg5g9M9gCJ#T2LU<2;uzG7=O<)U=e&ruv`42?9(^#d z6zi`>429#T4!&%4?T?>W>fDJK;C0uO%K$dR4(K8&TFGDnGmz>*?l2C!Y-g5KoNLSq zYZ&XqG1CL*r^sNDw27HGONE*jz(6+|=>GsW>&uocICQuWqxgsryfPF*yRxeVILyP5 zHu-6MIu2DFsxv+^oes3N5UZ$7IK%$4a2uiT4B^hK~f!4&I~xR6ymyb6hO+(2kmDkI(PUH=%2`N zEJ)?(JieIp_?%}Qc4u9!a3GFJGN)`ICf$-i8qg%u<}!BoaU+x$XMl_kOv{1<@}6;OW%k7|1<8 zAC}D~^>1krEvMP1E?VYIQ%yRwXoDR`2ZI^YIq8gQa(g9YU8;R)ZOMN{k&Q8d*z40@ ziN?PzhSn+Su3I%3XnryogB91Fmp449@lpX%8sG$wPH~Z+O@~2}CVmK6Hvk8)C6aFA zuG;CV4i<0>}<2keNCxaD5UC+EQ6I0K~Xt5=uXac z(=WqY$TCL^vrwTZ0CSAi+B##tGn4j?n-f|w2gHf|9H7BOCDPld#SA@Pr>vXo@c4frv8N4}f(PJ={skEv> zPZc?~5m_26;{M>sQ6y<8lS%z0dm_0 z8tJ~o%4&D8*R<2{6?w05`^xu46^3NfrdRD+wT)!QgkEh;MUg)8okEc*+M(fP4%_q@ zOA%gLgGp#DX|&DS+|)`ps;R#7M520HxGzrmYv_UE5`o-YL`!;!I@u&K7gv^$8CA`rB0~DK`5OD z*p}^8_vw--FGWjbid@F)4K$Ul<58)rhB9tW2;u3u!816pf?}aTFO-07%r>^>`iB?Q z9x3fAEkZQ)8jy&Ba#DBvdXkj{_bDJOrEJI4Fy=AozjfQvqgzuX)GpO{N$9kp%b|E^ z>2f1Vc1t4R5hiz#xh4Z}fzedOAZwkx#(QJ#CVj!}S-y&uyJf+z(62`0?>;O#qx9CR zRM%=RuANn(F6_5y5~nWgp*c(BUG!U8WvOqb zlJs_CR8p57YDLRg0{OU15ZQhDWLjOfYEhDyZoy_!8wo0^M)Pfr>{NGiazwbP29a{P zacV!6^v6GL`C&`T$Or5GeKjFDCH#nKegiFK# zgsdnGgp}Qba&4Ge_84aDC$uOu`sCC(q@prJMqD+iijwzy#BY1_z1tLdac(N#qd)z* zXWW+2(bb7G`+|VBN$RA=V=){?qYGmpLkAc;9NK%Bwki^sMGlE@-11*q6%mmJ^sdHp zmPsv1hfD!ME~!c2T;uM+z`qs>LUy~Wf+Xe@RB5R1Q>GRrrZgGOhUB5*OKnmgNgqzG zTLK&gG4$;OCq8Th^`Cb^tTbZMWwy+!WOm_J>2ldkCg7)3P+Uu~Dpu*oyW^mwnsmKI zNGejZ`ZzmNQFu}$QQbnWG_-bwnb`f~1hbu7>hG&`-%-XixX@)L(ZdLx837P-pooBg z>Tuw&b8=m+h8x-1nRM=f1PG?pj{cRwdzPLa14&eyMcUL|Q}EQs1XUxEXm-2liC96PKHSmYGD! zmn~=X2=UrMV=GFtT|&sGUGbp5#WtC6(?gEZs??Zq<<+U_aU3r=+-k8jN`xsXDvvfB zxtGb}T70T+DCFAre(9wm@T4}vS#3&X1`x+leTM9D-=phnu4OLTO9SixDC`yB|77Z&xe^(`bx84 zjsaJP{hLwYFTfm*6R*Or*nsK4H7&!wUUpFkDFvPWTzjdPuP?F=_}?OPtL7Q(e^ z(52gV948Q~wYOtIpH8Y;oQKy+Tbs*Wm zEOqCxxyHCx(y2P#Mp1Hv1Vr*wNy;NNf)eL*=JMLZW*BoLmf}ZdD=HzV?V+@eBcVV6 zU$y((U3(v0i{(?F4nH~!nJvr>@gfu{{3>^g&BUbS@RAO2e801vn+uU4Y#}Z=jxseN zu0~QcZ|HHByqq~7Z+*GOs>CD{o+1WLo>h0$<4pC}9)Rs*$W4h92&4x}L1SWEyL0@( zy`8X^QsLF{1Q^MNg&43?nJY?3R&6e!uwlFUW9=4H$t)DhjWQhEk(z?DopF(;TxAS9az#aml;aKOQ6ZGJ{{RmcElP1I3*j250iYkW zeKi|cU0$)_S)|h@Tr~*~!KcJS$&U?9$BL&I4g$9|2uf5Ff;waZaiFZYGfF0*Vcu5* zfqczJ07(ieJx+igzwRuCi8`MxiX?>}9}=f-Q+QMd){>S>OHkD38P9y=%=(tBq;c8Uzo=B*B7>c~#LJcN$p9lL3c;B7cAh|!=^=<`sb`vGgFxTF67 zhi%YOP^NYUMVF?Kp?x1OE_`*?yM=@p4&hv#|v3k3Qk6NE)Fz{jTHWbk}Kxy3hX45-l{% zy=v7MRmQ{1eiMxskdhOR(b58fNy*96i>7+)RWe{^ato-c%Gis8!@wh>^2v}GZJ}hvGm2>Bsr-4oN#^FCtjGw26lDm6;IHb>N^g(Iwa?|y63UR zd+D?6Y@Nb6O^o~{+>XY1giVaJ!74(NCnt#~2{}ZrW#Hlv;(=U#B%U-%Yfc4m=RsbpHS% zQkPVe<2b<}Yuh;o8QE=ZQ!Pq#w4?uvd3z3zxk6YjZO)Tt6)mNC6nkq0O&!xBGhXy6hT{jF?<3 zpbYGMt^7A}%j@jHK}C}?pC#B;y01J)ZAorPM=UZ(AV=k%oM!;!Yn^s(Ze}D>s!zcR z;e{c#>Qv*xe?pVYP?C|2Jm^SS#!eNEy;qXf5Yz5>abOII&|-hY*T#2 zRO)p;dLrTG!%i#%f@8dtwm~CO1`c({+th77qY|Ml7)1{lDb`!@fB|o-S+>5o_ZnyH z`N&Ea1P1^zOR(hH9jyIM7}w@Sr(AUyvK-@!C8)Ist|aQW-wAn31N_BVA3Z&GHIr3| z*TrK!iRt`*>PS6vw)H5H6FPw3- z)Dxfc1o|HN#xsp`(13P1Pnr`_Nz&NUiw^Qpp!bA9Z29S^SB zlVVq{YEup+xf3BJZYd~2v>Yl?0Vk>GNIsbzblA1qrrnO?h?7)?N#X>RaBH5Nf3kJ@ z!0Fp(H+Hc1c&cqeop{^OzwSTsn|eEMDQm%V30hZ=Le=Rb|)n@O2IT8WWRjaxmrf)H&(Ru0jV1aO6nH zLM!14)F~q|2T)iKZ=3X!w$%D7X<;qOXCwlyS6peK>TrHo*Wr@mqP0kCDKgn9a3rgp z{!mYs1GaqHdK?b%o~>|No4Kc|b#7#M0y{(`)Fp`J2N+i+y$kCj>nETX;@6}(-bc1{ z2#q~WwCU{5bqjNqP?`D-JOyB+tY`H6T3Con}bGqR*xofTb!T)RuA&l;wRJPNVsY=l=lXRXU3=3N?DFntW)G!q+0A z9S15&4oJF7^&n_QFOKW{qZ_#kb{r(svv;W`tX_XEDsX5sv& z7S9{zn3*U{XB8RbwAYP7apm&K!RB`)gYeTB+LWpy`>MAgkrsD4PDCH=9Rks#zaOkJ z0M{7Q4z0u1rRu2CTb~7%9CgqZ^ooWZS{dP4vpkp6*)u)kBQX>o_!k`cmkbnYFjRu+8 zG*`Dtbh%K2DHRmSL#lKHpO`uE5bYC8z@IkB?SVM|Cvn2@uGOxjs#M~7jd9)Hs^NRtJ{OLTaFA`kI|wGd1;E=_`Lc%JlCPGiKT_Z z%jw}D9484qRntNQKHOG;ku8|2LbJr|u=-p$AR#FSLPk}^+yXo8Qw*bfb!StXg0}o; z97}IJy3EL}q^R)o9dagKET^j58A`^7O`QmvsNP)P1j|c_LSXn8J zCU4QXFlRVV(r^WxQ^mI;)u!Ylp)-)oc%a%4{AGo<=6PIOOL?R4gxvfvs&rot2=YZ& z;cys-x25^>#iY<`QDqiX4-rr)OR&e4WOe7AKu!l-eVaR!3cQk*n+>wB3C>y<69Q{t zTnJFq;H6q|1E!sh(1&)=?)yg4r(4r2RE7i~v@WkQoGR6W#G<3c3|1+H#Eg=G$e+S- z^eM)x)ccNh8n~<11fIiE6r1@RHqzmDs@#_M7qOpt{7=S<5WRJohl-Vo=d7q(%L2l?){`J zcvQqe-L*G;TjsZ$C`AHgySi$)rbcTd1joJZ$hM_Er3fq#nGh;Ur#3R%PM%t}q-eXu zws#A1ip{q|hd{ZmJ8}uDI?WBr``+oS$d2SQ8U@{0X4+Z_ryNLnjV@OhQhBAYmXjdt z{{U>s*PT;$_Ki}#SEABs)#EDUl~<`jw;`8m(kcmsHJFyAOLr3#xcu-_3fY%aeL2I4 zaU>m))x=ZtQ05@`fi7Z1VHt^MAvtyc9c~W5Fnk`G?9vpxpo=d~T=5#sJ)!{KY^p&d zux3hKsQVK)Pg z5u)M2SI`Jmyzgnf=q{m7jOFXN>t3NvtU#Gfn{11+@~Ot3J>Pe5a8>IxT654<1;?0> zrs>g}UkNHg*JW>0rLx5IG}H8&lPQr{sX0=sBAX4@AEiZ$PKyc^A`&Vk zwK-d2Gf96cM-E9P4t8#(D>fxXK+UCRI6!s|1m-cE0@WYfjZTIfjvQpS z$3Uu7DQK=BIb5%_@*8oBS+WXCOG*}iI244a5K5^ulv8(uMqNhGMZPphProZm6=EoQC{rYJd}j#5aCaO5tdTJI0**BFgEvLi-q>H z_CT9_`yD+x&Zo6oG%0S@>Fc3V11hVtNkW}V_Vr93?K*uqC?c%R0dRB!QMZ;4amuJw zS`pi2xe{iYMCN6@Vmk_Iq<9eMhJLwa<)vY09iOoX{(7(Aud2#_Q)EBXy z&3jqnP9~X?pRQ06wwN#GGWujEa=LTcsF&(GYRD?k}(kWV&Gdg?mhT)AjNVV60{LZw9xxZXKwU=@Y)j&%jjUk*mT zZ%w9UwS7gaTl=|}C2{4gG&U_NgobqFJwgscVYf5Yei5ka;?4&U_-z@j%0#8hZmUe7 z!LKz%b_|N_T9jIaMlzE+qY9BuVAG=hizQCZs5I(TH_FkEmc|z0GD3TH{X*ERQ=(Jf zwk`?`hOVky=i}3pN379WLvSt@V$ooLCMlL>QX(duBpDFH9ys7QovR)r6#-F{QKgvj zL0}>&B05sjtBWtJi0fKOLbc@+$;J>iE>pbaHnfL$QWAit{=2C`;SS(_%bFDD z85-GUBF3vbIF(18qhedl^m<2f!!1)tCmKA2lYexp*9(j&Cw^*)wZ zG2i~~lC|JTLDNKMi@5Y2vwBU54b92kln4?Vsa;H4ZyB>%$0?W8z?jS=fDe@{A;3?m zI0qX;D@jpVsK9bh>YASg`Ggx-R7c!WKyKq$yY#J2e~L-Syi?uf=B0 zeaEaju*{upI|dICq)X!!uFy7$v%u?dS}edTQ~9Q0JU zs8;}^xlya90lLk~KRXhh7Df^hP=w@Tfg>O>&dJm&RMoB$1CmNgN1TRmUgQTaW6uuU zEk~ZMaP&!;HN#BA6WuHOHw|QQ)$m~u#yr^!{`lfF3T$L#g3JbSAX8NGWxvCMAJThvLmloYu>lbXef*VR& z+4l7IpoL1N(Qp0AZd-d+%^{kM6;kib)zcoU*D3C-aw-yTt3p&|Qc55CPYp(p%`syl zwI!P3lImi%`gg&9Zz}4US*Y%=$latC*lDuoWLTY~EoNQ*C3qzVKz1*LpI zm4*1^CQE#zMxI5`}<0}yo!?+Pg{~3ZR)FOp;g(bHLJA7-E|G4V#+;wtvT1(Vhuh@<5QlfJk)x9 z2pWAICz9;CiNVNQ%R+DgJZcAAXJXp*WL-AXv*a{Rh8k?pLfFMaHJ46rs=n-Pi=LIYmwDpe7cDlQ4m3NEMpZsD6z62bZj&9(7S0g3F=CSNmd*zt z4=7N{^6R$ec~3y9RBDP#>9{3IYDD{nEn(UfdQ0q}p@*kSZz%CRvPf<0wtlvR3|7?+ z5#lP8iCa7Pi zrN7T9%49@5PVDvEcb@IHxoEjAhdP}@-g;rgdW37&S}ZHFkyLI|C9xXva^!&BX4Y;R zXLu+x?m6^@gt(d3^KQ8frNN#iH@jDbQK`~u_4kXuFc&eOv>52e#rjouQrG+xr-EFlVY+I7=jW(qQpqVtfJwJGJD|P9V_V|H?P_5S} zwAws4EpeeQp;Ky8>8V*v1u~}}FG_@(QXWDuCOj}hhUIHm3f7(K0&bg(6^7hi1Mm!(|3y3O) z7E{!*AxPu=;;c-5+KDHWfQZz|@TqcYa#931j?-j9l>D^aC$|kd#-iE2Xcfzyma1He z71eFgDeJqg7M@pyVTzXTeb(F=m1&b5NQUjZTxLV;a^yVIXjoR&-*VkHomCXdEkdf-*(VKXqn3=O1x9r;7s`W)cgf69CuE40FC`3fWOgQnMbVZfz14Z54 zVl3Mhmp+{QQ6t_rV-8D?a4s9{t|XTzlczlMlm--+0ZPJHN!JXZjhOgXg2_}>Rs7MT zD?GUXDd3xernZf9dwO8>r(|3?O`_E4Xq!z+r#MVVGwM(ztSQ1l+c7$iK=`)1+T+|b z+Pk*p!$G|5d)hh{sVKJSv+c{y->gWAms*x(*!Qf8600$rT2oo1*4CM@rExJ;X}8j` zw|hFNaa*?qGFIsBTD>Nms&pDPTA{o+a4Hqbs?tlfTZz~d=~H40(cC0uXFIS#KX$mz7pu=jxE zSxqF&0oama7RYqDm8hvI^BnPNdY_I?n|R_*&gG>ip-;<&2#E6*8jY+6$bV8$_?NKg zFk~ggR#_8uC{ocTC4v>@01qirfgqlQxqqFt*mv!6x4R~4_Y|Z~s(Z?-9#puDcxPn7 zg)~Eg`lD;%`KWmc5y$FMLs;@^fKKryM3fY%OG!Bj3;OBFIpWU=;vEh!bJGJ&hI>BK z=iJ+td2`Pjsk*L~nNS!j4!XmDj=3L6*8^WpyAxb?M7VNRJTDgt)RL@V94L&8XG4Nd zPTK8QR$x`(&UeZ`av2B@cN#eUf$T8@u~{z9#H~(=#Bvbi>agaQ4kDM8*9@qoAuneH zTn7v=?pu4$iS8SAk|^{a8J$e_rJBpD7o@*EziUQ(ff zok%Ag$QeGnGO?|Cw3!-3AOaFJIL2|4fzXY0?VW|zXqC!zdQ+1K33gkkQ8~y8$UQJV zsrYHvpdghdvshHb8FVF~2TVZ0t(Bd{tnK`*j~%CWDcOmG9}B zOhQ;+?#KYxe0VxS(;cOyYT-#v3cBEAYtv0}wCCMDSk16($x4(t^y#$-4*vlAy4U3d z4~{XPP<6&OgHh!~6oo^6A3mamke9GeE;bHTjdV!YT#sDfVo&Zepv1ch@PgOZqtAm| z2}#PiY&4{}Mx#`=RCMjruFMmNG34q}>iD8SQpZ&|3@i)pVYP-d+lu8{S#S`Hu;r9t z!io#`$k}1ZH@`6K_O>N$*oDrr<)t#e;nEW%^yn6na5c_^>z|*l&?9{Y3_H=|8P5>o zk>JZ)c^oH>I&!Rf4^#2)uG1dazik`Rn^L9IE3l_2biO|ZKoc60&>?9DKUD+}qH*%m zYVE)4&(!ZK>R!lAIVpnHhg7nnjAV2;0O`}FHXBBOsFISQL5wsAer-rW*QNJz`(a9h z3%Q#JI)o)eoj@h^v2u0jz~B?}gvArX;j)enEj7UhhvCycxEUL2?CxB4V|e}o)1ktV z{vZiZ#zwkh?as)57}^0_q~R+ZAZHoZKY;E(++dLVfv3Vp46Zn#THzeVlnLqSjD6kq zafK#I0S9edav!$oheZHoW7$86w?Bs0)VuT{>@jM4rJ3&y-rBN=$yFhS_{ribExPzR zopdLs$7c=4xG>&3hcx-)PfTNIm%07#SdTW#A($;mU>|l2LRUxu5{0-J+rWMlMd>*sgLBu zmhh-X?|=so&wWYL*B^Qov0Q^tp9R3=CA!lKeJbbkj|(ogKq@^jGC5jd~&r#oB=dg;mI(4^(htv33EwiqlK$SQSetG!x zIrS-V{sk0(aF7RWbQwDQc2UA_#8KT>PE^K;*R$=dI`+WEFh7q~eifZeIq8WqLGPBe z0`8VAzQ>l{n8`jJ4$ebgeRY11`eB7cxw7c-9d1F0`!ix8)oOC$KuXEiAQb{}lb=qz zI!?*BVz%6&;HM5+0QJF0*IfdS@%24fMZ9RS>k*`n2!<|3n@gUll_5(?y7vSehHEXN`Egxk?M zFy#LLc#|ARR%Eme4;TO+Ui#!?omTy|T9pE9c~d#e6gK!&0+gw>uZ3w+x&Tw0s~Q3h z#?CF77sbCdtn+5k)l5 zu=%zeC3p~)RMa$QID41@Pfyzz01V?F>ITM4LV~m<<5i4`PSQRq;+lW8&_{Oqe1n)V`Pojyl6I*C)FLHQl6H|m}yw>4X+ByB28TaCjx^3TO04nZ;DZuQo8|5R0F!qGBFE{zuWMuL zFZOc&$$ULLxn3aRXg($)B_T#!x`82fO^8*sA;yKs+Rn}W?Fn~X?!Q*5)@s$cZmWsu zvZ{r}Hv5XvC~r{(0Y^%B#~^jrW}VBTuRcOwsMH^FYvCMeeg1zfphqi*OeBz{aR5BU zBd|CjRA-jo(`S^mH_g=QI1+vu=T4;jc604}bHp;o3rxDoiaA{12~MYrhfH9cacibK z?5iVEnx2}45^$@%DjJe`68y*L*2eW!;BbFuRCPw2P+h z{{V^;FL+2;0Av%5al~_tP6tfj_C5ACn`kVt5+hL><~pJWE2a=Ll6_7!Jw}HhZM9vU zQQ=K4UNmBIWXx~50E6^>I&{a$-ru`%Gu0Y|2?ew`MQ9A77&#U$8s3lB5bk^gM({Ep zhUYEx9C%@e@CVOLJqJP1cTH3%5SH{xx|1SZG09P3)nm**r$mXwrJzL_!B-ZeO!fz9 zS6Qai8F@@S3M_`ic`!L{L+2@g;*ZjE2VNnS4!k`(Y|+&zke3EUF~vS)GT>8ugqGXN zI&h;Pqz;D|8P0Uub+}4qQk?=>5J1eOB@RGl8E#7kB=2vVW9PkBjA~UV(@M@%T}rx% zzHLLBl5NwS?!v9*)1)_6im7i$fi?HoW^_M!OG}N&a4?tS;P5Cmlmw?ASA_LeLN=_n zD-~JS0%6R7CGzB{5t7l4nGZg-IO5R8euOP*Dh-o_eO&@}c5C$6lM;%$&+o zQG*mHG)PL(P5{g14D2*>^l_vrba|ST1qkzA6S;>GK}20@%V2k4Hgo)zvu}-;E9>GRTQCER$J@;VHEV^zV1^Rv=Z7>XO|V z2P4YzaOQt#5uD>}*}{o9j|iv8<~&1ikp6M|^)I$8UJ0KN=y0K$z)?(i!PGz0k;vOm zQ0I}v4Mc=4K}5bOag;(^aR}xu3RZxnvyNhhMiG?-5E44Q=RVP&7T}R4 ze(CofhF;Z9N0BAyyT-fYpn08k*P-tED~%;-M0V7mpyo@PbJXdx?YNh4qtKX3D6H<= z*|vrGt8K<_1V@i@U!p};C0)|qQs})dT1`QCQk|a4$x!$uQ{!2Qr^iWRF+u2bkU6bV3P<-06K2_==z<|#2>eC>OKb(S0i!m{@_BY3rFGZhh= zi+=OwMx~)`44Jfz+S)Bcp!j9rEwo)1we1>6AW4dpsHbL5xm2K8k%LyPCWB(}JC^IU zRnu$NI+-8d-FB-w1i;J7UlJ7Mzq~t{Tq{sbDGe!ZHrYttRW3X?=JV=RMr6)X6Df@N zX-@vxD$W2=$sipy*q05=SEE)X=O>4nG@rsP<{%Q_b=|$jC)GG^MRJg86*#CVh{{p| z!5{|M9Z0sAkk<|0bKdm`^^1meHO_qV3M~$oM~7`uC=JI}j9a$#4h_FZ;2FYs*IRun^8|%D ziGTTp3r`lhaM27a}!I*mD%sf$6 z6gp3TG2vnuWicWKASAP-fOq^m;YD)q9tXTlyvLGtA|U#=Ch3wv9xz4t_$RmTs5>qCIvRqE%R*A#xg#CIs5FK4a)Yl1gVlSU6G&fjv5c zGm(v>{T88Ev#+=luKN3pQv3u8d>YKekxY4Xr{$VdYT^z!XE@EmhiQrIDJcgeXy~zA zaYa=4acT8APt(^4mfm{5aLI=iu1lUK1i#Ihe(OS1r4+Vgzrw7ZEpQH_+D}d)`n@8F zB0Pi3l?u5M;Hy(>QM2Vtw40I{OUp(I{{Tacg%kQaSmhwh^cB=&LrI~aK|lr=09+Of zZE|%F&AJg2@)9%kI8*4IGiF_3X@&s+C~iR9?r*KOz~o&rmc&+{;iv}*;8e&QNhnb& z9JP+ACsEMj8fmfnEK`>ys`W~r8L6Th5NX`Vz8Fe%i!Wx-WNG?V7wM;iHQ$JB3$WdjM~KU;28&C%SinFhaj z#$gpG5~EIO_;uFnX=#QQDfI=o<`B_}=L5-F@RSz#lsG}!4O)jPs1TDkASICsbXh znw3Si%p}uQ`L9aP{n3Y0;QrK>NA{T|UG!V-)wVYex&Hua%gQCx^Yt5#bg*|_NJO|i zx9QSvTahs3$V;8M(5aGH%6f-zb?RP+!gDVz9&#Ub!>~XS=|Vy-NK$N;H*u}KP9bq$ zYJ5303U`9wNyD9sGOq9x1m%^mhuxup0NAm+9gdi+9r14xP4~Pz%JY}TWnEWQcD*dL ze?|_~>QZK-u5d$dHWRPfakGB{Q9>Ml0|hEhx@w`1h}U2CI~C88+w$-cz%r7BoFv^y&R%bm_I54xWf|xgj@n?FHNXzr&i$<*lz= zSIUdt1SiAzQ3)a%VZNa{5Is43h7MU-bBTVW{h9v&r?1(LibyKq3p~zVT6Mpl8!I0? zjA@SN2d>EWWoVz4zYsg*=cmKAeFn-%4m9vvOAY1b+-1IZySZ*GwBv$4CjB=#?pF&Y zA>-rF=u!Z<@cXD`4WU0$o7uf_;u@m(fMS2kL1>KNKAF1n#Gu`q6X#K0qR`^ht5-Ga zcGIbpT16tCS*X=2k5Q>mQo3y-Egm%Yq}3#T=iH@+ALj7E(Oy=qBY=@ ziB!8Dxl3~8Y4+h&1eo#Th9%zYy@aPBX3gAJ?o>p#VH`Os zx4s?fqODD{cY8#NF*>(JrPUp{<3I?zLvuE zbG0dWGb@mT2_#E-5VDX|91OrIi(SU=`P5ob9=3?nX^sY&Q=T1(TurFB(vliOOG|G` zT3l%B_L8!x$Qv4nUnjr!~*NmiKAGbLkzjoF^?R^V(^Th=y zzbrcK{cMy|Y8H0nEz4qsxqaSS5frZjYtU{4QXoHm%wc7?v!&7MS40UiTXEFf^;gvE z#umRdrMJp`E}}spQX6>=Axyk+#>i>!J4k3?A*^trCxtmqHcqNj1tKi8GzE8a0XcIM zU|12%ja!$c@M?isr`KdxH3`!-2s+rf&0`-pS)yaKf^mDi^*b3;U|G0Ht=~2c=+TYVEB2Fv%NaU9qA|G^|irM>~LST#(E* zEYGUwcrA^;9NsdnlC_Iv#{!9lNX(@urAkXV1lTYvL+U*Z znjWiov*oT^@oCIb3ya|QdsQoknt-Fi6y6R4gCM6*t&DaX9*yx{bks2H3axrOtuPpA zrl;Ix#V-H=fP!2q^x@R>^x4O$dq2w#tyIf_FH(|{W5}INQHs*-wN`*sn&{2HCGm;L-i=jrZfNFe~LIVZl_F~8fn4hJRLmR$5Y%bduwg)Pq+BAIVY&l1DqUd+quC9vkD~CyhxK(#fZTrP{2|6 z>{DQF1KZ`$NQc_j7NKZbYU!~AC?$x}`GB`hjvt#1Cx2H%4JJ%`8+UBI!s28V+D=K5 zrx%_CiA`7PM+BTGDltOFi&_EB+)n=hw}uhNO{3ZrbiW*>Nv7KSzl$O~-XyF^4$r1k z>ONGZY1Nk1#6r2Cjul8x{>xTalJhcdJFYSd|94Q16lX|y(OA9T^e+@JpVl-NfN5zNZ zHnNoy2RTVWSzk99$CLJk)_#vf5#eHV%Wc;Ra!y1AC0(ChNER3Q zG_7h4mAe{^0@&AVeaaS$ zfyn@d4Rc~oyEWOKgs7j9TJCAqe1Ej<7_AB}tyKNk%PR#(iwIQ9xIRL2)RL3c8f_pg zzsW+H5koaEX#2Wq!;P)9(rhX{F(jaj@I5NAb3c!Zl(yBJ;Rj8vy|y^r<2~>J`3!Ue zUjDl0q1eNRfCTBF1K@uD0J~_hxX!;&M|7ls17!x11zS8F*s!-PyWx`LK zl2ie)OOs$mpb-4D!*99G)WqEFkxQ}SToucWs&uI{Q(La3rt8kmn(GfqWi7{rO<^?B z)MSMOL5h*)1-$vzv6V!NFp~U4mdcb+QIL)ksNw$rE-}J2z#TKFP{)tNqOQbeQT7w- zpSR?8?nenAbOeF+9Bi>Ns8LnkO?+xDKrS3>=qxt&!cusWpo!s7`)((T&6+s`icS4yxNQdl5_Ao zNllpj_`{Vd-lsCcxDtxAbr%jkjUp%OJCIY?9re${%m}jZSNNHma673${52m9ibajzM1oquBo+mY!#%yfJQk@&@1>TaT_IUc`U_v3 z{(4~Ba<3-c-l`dr$1jF#m=cLS8(PRlJ8Q%=C#H5o?|zdegS@MmlcOn`YIN{F^5h(> zWO|_JFh1Rs7qrCL``xIvj}yZh=Poo{#|J4=g2?DcL#Ix_4D71*mthLJ=(jr{a_iJM zt~uCop|Ph>G&t-0_Lvv|0|B!zck}}P0I`MCku5g{U|&2mL);7KsLHMpeYWk2e%8;8tquZ`cp@{0j~cnXNm5drC*h~xoiVP=Tm&JN zrb}&ct>q=PE1+yEAS>4j*BW$A4gkS_tsoEsLGEt@82%E{o zeMhb|8f@p#Q6i_hORkLQJ|^F-E%<#%_@@fM{ zxNeu%Lgn`uSg1iv83L9|iNuFs4p&b0w>_KJ9Y*nOjtJ%2svxAH1x9bwON0X8`2}Yq zxYJX!i)L4-Ri|Y`gIlIgMAnPQ@DsUfJdJW&=#!xs)43X)Z5r5WpDGMwNMS%}Z6bXtuL>aL(&j2MG0-AH z^dnxF#xy;&#>jZ4GO(sTx{?aI{bDk#eZP;#8#hj>PD*VG^AMzhNzkcTNh~Zi{k`zf z=2PI~AfOc?YE8qN5Za4BOFIY0De%jYRTL$~N8nj#G6y+M07??s{{YP@IB!9&26M9N zC2jaL8+zzslRCZbmfwLYod^CXmeMe^$;Ox=CnG((?27T6*Ij!Ame5uQuPku^(>;L3 zxb3pnb`Q!X;H9?^!KN_#G8Ew&%#klRM@)IjwLQB0HtJ4wD@jggNi0b$$vIfF*@r9* z;u$BWp8iPVi>TyfZt8Ahnz`K;T^G(Na%WN*Iu5RXROc2%E-fnkBwt1*tsA!y+b}{)2rNF zhH&_w;(9?0uOue{xua3(XCqEWNS(YJnYoWFGcFK8QuOhB;enHcr>=9UBkG)!p#x~| zQc|2|O1bgeD^q+aXQ({n5~4e&KsCmtJvG@wc+_J%Izj?NJhiDIpiTkK2?Xb+FiyDc zNjTXT5(6{jLyFt3wq?l)C8ZLw8bX}_jZQLvdUg2YY9e-XH0*RGyv2)Y@e6^zpuUVW zY<__|KjG+98U(a>sml&6DGE~n00J6KoDIYML%GAVL7~o?+qrDGg)%q>1{35;br>fk z;B^@TgdK7v_U<=+>yhBR>|i)yv{9U6RV13|O$p3u0MB2fN*lyXZMADb|ymi1EZx%jE?t z8R`_Q=b#z`fx-?(aC4o2)TnWiw8lOj6KxVy>zXZU81ie_k&fE^n=P5M!qS(Wuhkq& zh$U?`Bao0rQ-uw3pawX#IMDRjIXc6p$Z^oA)t+7t8wQ|q;)yw5Z>^uZCmGvjcvgN+ zMjR**Pne@13~it#?X~U&@$v(Us*|-jnc1kyIU+4Uhr5%>{4w{3 zN>5yIDLD#rKju)+uDQ<50&V&-DuSzVM@-6FG8{yzeKKfjw)}FRqkbZAK!la!nS-bV zob4xn?E2oP*J&!Kw>8Q<#~gs;6Dl7>TzHZ)au1nUBzG9u;)%Ik-zN?|MTq%l`?D^& z&58ikAr1lNNgYYXxyU+Z&4b3DX2V3QixCtTd+DpTyAEA2k4&b;?$sU|ok~_x4Z|K! zU^dilHW;d#hAeeegHa?zK$`NzDsrN8+*Ec~#L66eez9Q$2Np4v@c;-I*}AU6W;H+| z=tf;l^(n~?Ap|BP3p`wupyPx!o&YhXI%h+6%x<>G4z(rAR*BANW;jd$;y@h$U+oPw zJxS#Epia0GPbLDp3--v z@RUKN#iLku^fqHN8l7#iIu|5xfRZKEsuiXgPyl@;uNKgxq>@obLU>R!Y}@A;rAW%s zb3uX zc6wBG37M#9g<;UKofC~gJ3ExiZWYa9)hbLOm{j)b4hW3BFgS?FR(Yu4(}?2%C$Sy& z&9i7UKtA7=3>Zol4PkU>FiyQ1DFr4X%3KC2EY`C-Ve|HIwOpax6&MMsQ)9%NNs~Sx ztW^EgO^}$Zmsb^+x<4`SI3mRV0K~b5`{QX=)5QT9c)7;Q3k@x?6><1d=nXd)7+X5| zWd7EJ9&NL1+17Ln!CKt<#jighAx4O(Qu0#q;GrrBgE)@<7_$SF(8OvOi{tB(Dx-;h{HZn*%4>!8 zxhov8jE2Rfkdu!o$kSYG!24Rh^w|5VkyMHK-qc!MNtPX~F*wF#+aQ4JXfQ_K1cN~X=q_!TScN*lhu1DJFF0IU5vXwibp ziw%{|md&FY8v#F~*RUmkKPIN^!@8C~)~v z(txi5`OgYc2Dc-x#ySjzHv6d{doTNpBA(TVHLD%=lV-y(BBh9BJKAk91 zQ|6SG?uwr5vR1bM=oo!YH1yqK^ zHPgP+cwRD z!v6p%AM}h|VMI+X{{W3c>w~zja~95jWklobR&(k1W7EFM8hoB=l#U`fG7#gK3PY?g z96)+hXYn-T?u7gi$ZEk;e)fBD9-nps` zPpVdAE_!JcdCR8FdK_`y7q*>lwQf({<*uY|<8(DCej)n`)RihM3#^qSrbhA?%#l{! zWQQC;dRuoS$7zC~9h8<~wtN#AwrzujNt>t<9F+v95FXAMtXysL#=KPE!$m@-u$!36 zeqRtDmAx??q;E=+!{xQxo(AA+&&$H&6W)q$Mq<3QDkOsqDya z#7A&A#DtgHUNCqa^QYnpLF@ds&9iBpq5vb)zyJW0fBIp3?-8lS87{uub@Y}+VISYPub7M9rf>lvZB+jifv{jp)2$yW}i~dzu61Qmw}&Cf^;Bf zzDC)$ZJKD5tqMw%m1Y-7AloU_Ul3>i0P^+vtMf)3p(QJMaajYwAv{1RWhxja3Ipo{ zrc=~|!gk3;sR?RRQ)R=cu)a%ET9?R(wh17@cAx(MiEUs6sjQ5GPf@0An_d*?tBWB< z&T~Aua(7{3T-@7Jd~33jA9%c~ zGRhAok+UK5|-A5tIY*wR$i(4>_!Iu!0=L(5#k>_H``nDjEeHM+m_>_Bg>CX4$p~rO>M))n;#PIfln(lBW9}@HhR^K~ej0(-zpmM~ZL4+9{-LdZ`N!rlQgIpo0FTvd3q?q{ zeLy%eDCO{{{HZ@IfPGJ|^{(C6V~t!{>#jBJ@%U@swgKBV&4+?UgpWel4V>~G!M|Jy zT6jrLx@oUopJ(#hw0PV~;?q-|bB%GJ>GB^fJ{h)c(Z09!zB(#$9?kQoaM2o+I~tpKhZz&A6ZQ5&r;p{{XHrgZ?5504_y?IOX&h zhv-pDP9EX#emM*O0DX2fqRe^?T9sE}#I)opj7O5<^g?j+X>h2d9XV=OVW|h>wr!g* zBo5_P=lXvkhPki&v|sVJ<@#F=pR{B)mwCjkM?_~?t5Rw68hxx4^U4rTJlPbrnk90-d9rCarlZ=GHOU25CT$1#9(*)HqEnWN+duRzkV;j;KT@@^00sH{{Z}A zEy{hzQ5`W^<+K_lN7U#s{7=g}ab;{bg*ddNa}b#*;ODMO3p_4GL`?pWT^bS5IL|}2 zZJQ8`T3rqN3I71~7$}c{KlG2tVMh{OAyA>x*r!fzx{8#SKR6{+x#%>f5`zwu#UN+h z0+tZ}02n#(UM&Ov01u<#Va7%Z8+5$dP_&0mp?F!z$?Js`e02M>Y}q=iXeEidN%=SO z#Ce+}HJ#tB)2}={5TX*m$Q^X)@EvjR{6+_(k-Ju;ijCJwc32TAw%>?mCPt1!bAf9A z0M?*SPhBy#ZJPt5sF=m?=1}%@H_6LkUa52dZVG=ve_psk(;!4#S@GYM;AKUY_-(Gw z{UISb_c{1_Oy}9AQ-h@$IwceT!ippTPS~_qAG?idr^-0q|k4>5i5_$Ca?_-2F324V$ zaGYZ})22TSvuxRpw%=z0z>=hgYv_|>`_$oXm;V5n)yCb*3vKvE>w^gKk_>iPM~!i| zRJkOpfjp$3mvXMdfGZ?)>Uw8o9iu*z7UrfIjm~|F^D-haQi(MyW)rP>5go*7!~(FA z5BhDJX3JEn3qw!j)KAe059LU#|`E({XXMq;`FXnW}337Yt;?T zq$`lzk~8~lIITe#;?rmsz4BN9OqBB*FF9_X4$mfCI0}HLFK3Z%v}Ef z*>?P22pf+T3dZ5P#M{#qtzT+ebvcdr0HC)NzIQ;b6P^y*FFZN*I&5`hTXLpU<5UZh zBb2Nqx^p=tOIm^gm!_yWAb>`=*BKjT*|j$+#-^}9KEL*VJbn4B&Bm7CGPo)TQfP=F zhV2Y&M%9Hf~|bVr}{UYS2zW!G&*kP)>=GaD%Jbm@)GY&O>+DF`Vpq&JNU zbp(us9da?VnM;<`*svwFAB_*N(zt>8%Hi{LKDqmP<4v<{*u2z5u38Z!*({v3HqEjk zJV+~-Ts37=F5{v{Ua#wXN^)W#lerwN%G%-vdsS|NVy461-Lxk7+6)zY#tl6597KEc z>UC^+Pfx3y>$Yv1X4^a2y;^x(F)CFQ5@JNTNGIb+-Twf6Erpr&EKNiSTGAgxsEtZS J$M#zv|JgE!HzEK4 literal 0 HcmV?d00001 diff --git a/cool-admin-java/src/main/resources/cool/code/controller.th b/cool-admin-java/src/main/resources/cool/code/controller.th new file mode 100644 index 0000000..27cf579 --- /dev/null +++ b/cool-admin-java/src/main/resources/cool/code/controller.th @@ -0,0 +1,22 @@ +package com.cool.modules.[(${module})].controller.[(${type})][(${subModule}?'.'+${subModule}:'')]; + +import cn.hutool.json.JSONObject; +import com.cool.core.annotation.CoolRestController; +import com.cool.core.base.BaseController; +import com.cool.core.enums.Apis; +import com.cool.modules.[(${module})].entity[(${subModule}?'.'+${subModule}:'')].[(${entity})]Entity; +import com.cool.modules.[(${module})].service[(${subModule}?'.'+${subModule}:'')].[(${entity})]Service; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletRequest; + +/** + * [(${name})] + */ +@Tag(name = "[(${name})]", description = "[(${name})]") +@CoolRestController(api = {Apis.ADD, Apis.DELETE, Apis.UPDATE, Apis.PAGE, Apis.LIST, Apis.INFO}) +public class [(${upperType})][(${entity})]Controller extends BaseController<[(${entity})]Service, [(${entity})]Entity> { + @Override + protected void init(HttpServletRequest request, JSONObject requestParams) { + + } +} \ No newline at end of file diff --git a/cool-admin-java/src/main/resources/cool/code/mapper/interface.th b/cool-admin-java/src/main/resources/cool/code/mapper/interface.th new file mode 100644 index 0000000..112e6ab --- /dev/null +++ b/cool-admin-java/src/main/resources/cool/code/mapper/interface.th @@ -0,0 +1,10 @@ +package com.cool.modules.[(${module})].mapper[(${subModule}?'.'+${subModule}:'')]; + +import com.mybatisflex.core.BaseMapper; +import com.cool.modules.[(${module})].entity[(${subModule}?'.'+${subModule}:'')].[(${entity})]Entity; + +/** + * [(${name})] + */ +public interface [(${entity})]Mapper extends BaseMapper<[(${entity})]Entity> { +} diff --git a/cool-admin-java/src/main/resources/cool/code/service/impl.th b/cool-admin-java/src/main/resources/cool/code/service/impl.th new file mode 100644 index 0000000..1c31ea7 --- /dev/null +++ b/cool-admin-java/src/main/resources/cool/code/service/impl.th @@ -0,0 +1,14 @@ +package com.cool.modules.[(${module})].service[(${subModule}?'.'+${subModule}:'')].impl; + +import com.cool.core.base.BaseServiceImpl; +import com.cool.modules.[(${module})].entity[(${subModule}?'.'+${subModule}:'')].[(${entity})]Entity; +import com.cool.modules.[(${module})].mapper[(${subModule}?'.'+${subModule}:'')].[(${entity})]Mapper; +import com.cool.modules.[(${module})].service[(${subModule}?'.'+${subModule}:'')].[(${entity})]Service; +import org.springframework.stereotype.Service; + +/** + * [(${name})] + */ +@Service +public class [(${entity})]ServiceImpl extends BaseServiceImpl<[(${entity})]Mapper, [(${entity})]Entity> implements [(${entity})]Service { +} \ No newline at end of file diff --git a/cool-admin-java/src/main/resources/cool/code/service/interface.th b/cool-admin-java/src/main/resources/cool/code/service/interface.th new file mode 100644 index 0000000..6b365b0 --- /dev/null +++ b/cool-admin-java/src/main/resources/cool/code/service/interface.th @@ -0,0 +1,10 @@ +package com.cool.modules.[(${module})].service[(${subModule}?'.'+${subModule}:'')]; + +import com.cool.core.base.BaseService; +import com.cool.modules.[(${module})].entity[(${subModule}?'.'+${subModule}:'')].[(${entity})]Entity; + +/** + * [(${name})] + */ +public interface [(${entity})]Service extends BaseService<[(${entity})]Entity> { +} diff --git a/cool-admin-java/src/main/resources/cool/data/db/base.json b/cool-admin-java/src/main/resources/cool/data/db/base.json new file mode 100644 index 0000000..5698188 --- /dev/null +++ b/cool-admin-java/src/main/resources/cool/data/db/base.json @@ -0,0 +1,121 @@ +{ + "base_sys_param": [ + { + "keyName": "rich", + "name": "富文本参数", + "data": "

这是一个富文本

xxx

xxxxxxxxxx


", + "dataType": 1, + "remark": null + }, + { + "keyName": "json", + "name": "JSON参数", + "data": "{\n \"code\": 111233\n}", + "dataType": 0, + "remark": null + }, + { + "keyName": "file", + "name": "文件", + "data": "", + "dataType": 2, + "remark": null + }, + { + "keyName": "text", + "name": "测试", + "data": "这是一段字符串", + "dataType": 0, + "remark": null + } + ], + "base_sys_conf": [ + { + "cKey": "logKeep", + "cValue": "31" + }, + { + "cKey": "recycleKeep", + "cValue": "31" + } + ], + "base_sys_department": [ + { + "id": 1, + "name": "COOL", + "parentId": null, + "orderNum": 0 + }, + { + "id": 11, + "name": "开发", + "parentId": 12, + "orderNum": 2 + }, + { + "id": 12, + "name": "测试", + "parentId": 1, + "orderNum": 1 + }, + { + "id": 13, + "name": "游客", + "parentId": 1, + "orderNum": 3 + } + ], + "base_sys_role": [ + { + "id": 1, + "userId": "1", + "name": "超管", + "label": "admin", + "remark": "最高权限的角色", + "relevance": 1, + "menuIdList": null, + "departmentIdList": null + } + ], + "base_sys_user": [ + { + "id": 1, + "departmentId": 1, + "name": "超级管理员", + "username": "admin", + "password": "e10adc3949ba59abbe56e057f20f883e", + "passwordV": 7, + "nickName": "管理员", + "headImg": "https://cool-js.com/admin/headimg.jpg", + "phone": "18000000000", + "email": "team@cool-js.com", + "status": 1, + "remark": "拥有最高权限的用户", + "socketId": null + } + ], + "base_sys_user_role": [ + { + "userId": 1, + "roleId": 1 + } + ], + "task_info": [ + { + "id": 1, + "name": "清理日志", + "job_id": "1", + "repeat_count": null, + "every": 5000, + "status": 1, + "service": "baseSysLogServiceImpl.clear(false)", + "task_type": 0, + "type": null, + "data": null, + "remark": null, + "cron": "0 0 1 * * ?", + "start_date": null, + "end_date": null + } + ] +} \ No newline at end of file diff --git a/cool-admin-java/src/main/resources/cool/data/menu/menu.json b/cool-admin-java/src/main/resources/cool/data/menu/menu.json new file mode 100644 index 0000000..5da8568 --- /dev/null +++ b/cool-admin-java/src/main/resources/cool/data/menu/menu.json @@ -0,0 +1,813 @@ +[ + { + "name": "系统管理", + "router": "/sys", + "perms": null, + "type": 0, + "icon": "icon-set", + "orderNum": 2, + "viewPath": null, + "keepAlive": true, + "isShow": true, + "childMenus": [ + { + "name": "权限管理", + "router": null, + "perms": null, + "type": 0, + "icon": "icon-auth", + "orderNum": 1, + "viewPath": null, + "keepAlive": false, + "isShow": true, + "childMenus": [ + { + "name": "菜单列表", + "router": "/sys/menu", + "perms": null, + "type": 1, + "icon": "icon-menu", + "orderNum": 2, + "viewPath": "modules/base/views/menu/index.vue", + "keepAlive": true, + "isShow": true, + "childMenus": [ + { + "name": "新增", + "router": null, + "perms": "base:sys:menu:add", + "type": 2, + "icon": null, + "orderNum": 1, + "viewPath": null, + "keepAlive": false, + "isShow": true, + "childMenus": [] + }, + { + "name": "删除", + "router": null, + "perms": "base:sys:menu:delete", + "type": 2, + "icon": null, + "orderNum": 2, + "viewPath": null, + "keepAlive": false, + "isShow": true, + "childMenus": [] + }, + { + "name": "查询", + "router": null, + "perms": "base:sys:menu:page,base:sys:menu:list,base:sys:menu:info", + "type": 2, + "icon": null, + "orderNum": 4, + "viewPath": null, + "keepAlive": false, + "isShow": true, + "childMenus": [] + }, + { + "name": "参数", + "router": "/test/aa", + "perms": null, + "type": 1, + "icon": "icon-goods", + "orderNum": 0, + "viewPath": "modules/base/views/info.vue", + "keepAlive": true, + "isShow": true, + "childMenus": [] + }, + { + "name": "编辑", + "router": null, + "perms": "base:sys:menu:info,base:sys:menu:update", + "type": 2, + "icon": null, + "orderNum": 0, + "viewPath": null, + "keepAlive": true, + "isShow": true, + "childMenus": [] + } + ] + }, + { + "name": "角色列表", + "router": "/sys/role", + "perms": null, + "type": 1, + "icon": "icon-dept", + "orderNum": 3, + "viewPath": "cool/modules/base/views/role.vue", + "keepAlive": true, + "isShow": true, + "childMenus": [ + { + "name": "新增", + "router": null, + "perms": "base:sys:role:add", + "type": 2, + "icon": null, + "orderNum": 1, + "viewPath": null, + "keepAlive": false, + "isShow": true, + "childMenus": [] + }, + { + "name": "删除", + "router": null, + "perms": "base:sys:role:delete", + "type": 2, + "icon": null, + "orderNum": 2, + "viewPath": null, + "keepAlive": false, + "isShow": true, + "childMenus": [] + }, + { + "name": "修改", + "router": null, + "perms": "base:sys:role:update", + "type": 2, + "icon": null, + "orderNum": 3, + "viewPath": null, + "keepAlive": false, + "isShow": true, + "childMenus": [] + }, + { + "name": "查询", + "router": null, + "perms": "base:sys:role:page,base:sys:role:list,base:sys:role:info", + "type": 2, + "icon": null, + "orderNum": 4, + "viewPath": null, + "keepAlive": false, + "isShow": true, + "childMenus": [] + } + ] + }, + { + "name": "用户列表", + "router": "/sys/user", + "perms": null, + "type": 1, + "icon": "icon-user", + "orderNum": 0, + "viewPath": "modules/base/views/user/index.vue", + "keepAlive": true, + "isShow": true, + "childMenus": [ + { + "name": "部门列表", + "router": null, + "perms": "base:sys:department:list", + "type": 2, + "icon": null, + "orderNum": 0, + "viewPath": null, + "keepAlive": true, + "isShow": true, + "childMenus": [] + }, + { + "name": "新增部门", + "router": null, + "perms": "base:sys:department:add", + "type": 2, + "icon": null, + "orderNum": 0, + "viewPath": null, + "keepAlive": true, + "isShow": true, + "childMenus": [] + }, + { + "name": "更新部门", + "router": null, + "perms": "base:sys:department:update", + "type": 2, + "icon": null, + "orderNum": 0, + "viewPath": null, + "keepAlive": true, + "isShow": true, + "childMenus": [] + }, + { + "name": "删除部门", + "router": null, + "perms": "base:sys:department:delete", + "type": 2, + "icon": null, + "orderNum": 0, + "viewPath": null, + "keepAlive": true, + "isShow": true, + "childMenus": [] + }, + { + "name": "部门排序", + "router": null, + "perms": "base:sys:department:order", + "type": 2, + "icon": null, + "orderNum": 0, + "viewPath": null, + "keepAlive": true, + "isShow": true, + "childMenus": [] + }, + { + "name": "用户转移", + "router": null, + "perms": "base:sys:user:move", + "type": 2, + "icon": null, + "orderNum": 0, + "viewPath": null, + "keepAlive": true, + "isShow": true, + "childMenus": [] + }, + { + "name": "新增", + "router": null, + "perms": "base:sys:user:add", + "type": 2, + "icon": null, + "orderNum": 0, + "viewPath": null, + "keepAlive": true, + "isShow": true, + "childMenus": [] + }, + { + "name": "删除", + "router": null, + "perms": "base:sys:user:delete", + "type": 2, + "icon": null, + "orderNum": 0, + "viewPath": null, + "keepAlive": true, + "isShow": true, + "childMenus": [] + }, + { + "name": "修改", + "router": null, + "perms": "base:sys:user:delete,base:sys:user:update", + "type": 2, + "icon": null, + "orderNum": 0, + "viewPath": null, + "keepAlive": true, + "isShow": true, + "childMenus": [] + }, + { + "name": "查询", + "router": null, + "perms": "base:sys:user:page,base:sys:user:list,base:sys:user:info", + "type": 2, + "icon": null, + "orderNum": 0, + "viewPath": null, + "keepAlive": true, + "isShow": true, + "childMenus": [] + } + ] + } + ] + }, + { + "name": "参数配置", + "router": null, + "perms": null, + "type": 0, + "icon": "icon-params", + "orderNum": 3, + "viewPath": null, + "keepAlive": true, + "isShow": true, + "childMenus": [ + { + "name": "参数列表", + "router": "/sys/param", + "perms": null, + "type": 1, + "icon": "icon-menu", + "orderNum": 0, + "viewPath": "cool/modules/base/views/param.vue", + "keepAlive": true, + "isShow": true, + "childMenus": [ + { + "name": "新增", + "router": null, + "perms": "base:sys:param:add", + "type": 2, + "icon": null, + "orderNum": 0, + "viewPath": null, + "keepAlive": true, + "isShow": true, + "childMenus": [] + }, + { + "name": "修改", + "router": null, + "perms": "base:sys:param:info,base:sys:param:update", + "type": 2, + "icon": null, + "orderNum": 0, + "viewPath": null, + "keepAlive": true, + "isShow": true, + "childMenus": [] + }, + { + "name": "删除", + "router": null, + "perms": "base:sys:param:delete", + "type": 2, + "icon": null, + "orderNum": 0, + "viewPath": null, + "keepAlive": true, + "isShow": true, + "childMenus": [] + }, + { + "name": "查看", + "router": null, + "perms": "base:sys:param:page,base:sys:param:list,base:sys:param:info", + "type": 2, + "icon": null, + "orderNum": 0, + "viewPath": null, + "keepAlive": true, + "isShow": true, + "childMenus": [] + } + ] + } + ] + }, + { + "name": "监控管理", + "router": null, + "perms": null, + "type": 0, + "icon": "icon-monitor", + "orderNum": 9, + "viewPath": null, + "keepAlive": true, + "isShow": true, + "childMenus": [ + { + "name": "请求日志", + "router": "/sys/log", + "perms": null, + "type": 1, + "icon": "icon-log", + "orderNum": 1, + "viewPath": "cool/modules/base/views/log.vue", + "keepAlive": true, + "isShow": true, + "childMenus": [ + { + "name": "权限", + "router": null, + "perms": "base:sys:log:page,base:sys:log:clear,base:sys:log:getKeep,base:sys:log:setKeep", + "type": 2, + "icon": null, + "orderNum": 1, + "viewPath": null, + "keepAlive": false, + "isShow": true, + "childMenus": [] + } + ] + } + ] + }, + { + "name": "任务管理", + "router": null, + "perms": null, + "type": 0, + "icon": "icon-activity", + "orderNum": 9, + "viewPath": null, + "keepAlive": true, + "isShow": true, + "childMenus": [ + { + "name": "任务列表", + "router": "/task/list", + "perms": null, + "type": 1, + "icon": "icon-menu", + "orderNum": 0, + "viewPath": "modules/task/views/list.vue", + "keepAlive": true, + "isShow": true, + "childMenus": [ + { + "name": "权限", + "router": null, + "perms": "task:info:page,task:info:list,task:info:info,task:info:add,task:info:delete,task:info:update,task:info:stop,task:info:start,task:info:once,task:info:log", + "type": 2, + "icon": null, + "orderNum": 0, + "viewPath": null, + "keepAlive": true, + "isShow": true, + "childMenus": [] + } + ] + } + ] + } + ] + }, + { + "name": "框架教程", + "router": "/tutorial", + "perms": null, + "type": 0, + "icon": "icon-task", + "orderNum": 98, + "viewPath": null, + "keepAlive": true, + "isShow": true, + "childMenus": [ + { + "name": "文档官网", + "router": "/tutorial/doc", + "perms": null, + "type": 1, + "icon": "icon-log", + "orderNum": 0, + "viewPath": "https://admin.cool-js.com", + "keepAlive": true, + "isShow": true, + "childMenus": [] + }, + { + "name": "crud 示例", + "router": "/demo/crud", + "perms": null, + "type": 1, + "icon": "icon-favor", + "orderNum": 1, + "viewPath": "modules/demo/views/crud/index.vue", + "keepAlive": true, + "isShow": true, + "childMenus": [] + } + ] + }, + { + "name": "通用", + "router": null, + "perms": null, + "type": 0, + "icon": "icon-radioboxfill", + "orderNum": 99, + "viewPath": null, + "keepAlive": true, + "isShow": false, + "childMenus": [ + { + "name": "图片上传", + "router": null, + "perms": "space:info:page,space:info:list,space:info:info,space:info:add,space:info:delete,space:info:update,space:type:page,space:type:list,space:type:info,space:type:add,space:type:delete,space:type:update", + "type": 2, + "icon": null, + "orderNum": 1, + "viewPath": null, + "keepAlive": true, + "isShow": true, + "childMenus": [] + } + ] + }, + { + "name": "首页", + "router": "/", + "perms": null, + "type": 1, + "icon": null, + "orderNum": 0, + "viewPath": "modules/demo/views/home/index.vue", + "keepAlive": true, + "isShow": false, + "childMenus": [] + }, + { + "name": "数据管理", + "router": null, + "perms": null, + "type": 0, + "icon": "icon-data", + "orderNum": 7, + "viewPath": null, + "keepAlive": true, + "isShow": true, + "childMenus": [ + { + "name": "字典管理", + "router": "/dict/list", + "perms": null, + "type": 1, + "icon": "icon-dict", + "orderNum": 3, + "viewPath": "modules/dict/views/list.vue", + "keepAlive": true, + "isShow": true, + "childMenus": [ + { + "name": "删除", + "router": null, + "perms": "dict:info:delete", + "type": 2, + "icon": null, + "orderNum": 0, + "viewPath": null, + "keepAlive": true, + "isShow": true, + "childMenus": [] + }, + { + "name": "修改", + "router": null, + "perms": "dict:info:update,dict:info:info", + "type": 2, + "icon": null, + "orderNum": 0, + "viewPath": null, + "keepAlive": true, + "isShow": true, + "childMenus": [] + }, + { + "name": "获得字典数据", + "router": null, + "perms": "dict:info:data", + "type": 2, + "icon": null, + "orderNum": 0, + "viewPath": null, + "keepAlive": true, + "isShow": true, + "childMenus": [] + }, + { + "name": "单个信息", + "router": null, + "perms": "dict:info:info", + "type": 2, + "icon": null, + "orderNum": 0, + "viewPath": null, + "keepAlive": true, + "isShow": true, + "childMenus": [] + }, + { + "name": "列表查询", + "router": null, + "perms": "dict:info:list", + "type": 2, + "icon": null, + "orderNum": 0, + "viewPath": null, + "keepAlive": true, + "isShow": true, + "childMenus": [] + }, + { + "name": "分页查询", + "router": null, + "perms": "dict:info:page", + "type": 2, + "icon": null, + "orderNum": 0, + "viewPath": null, + "keepAlive": true, + "isShow": true, + "childMenus": [] + }, + { + "name": "新增", + "router": null, + "perms": "dict:info:add", + "type": 2, + "icon": null, + "orderNum": 0, + "viewPath": null, + "keepAlive": true, + "isShow": true, + "childMenus": [] + }, + { + "name": "组权限", + "router": null, + "perms": "dict:type:list,dict:type:update,dict:type:delete,dict:type:add", + "type": 2, + "icon": null, + "orderNum": 0, + "viewPath": null, + "keepAlive": true, + "isShow": true, + "childMenus": [] + } + ] + }, + { + "name": "数据回收站", + "router": "/recycle/data", + "perms": null, + "type": 1, + "icon": "icon-delete", + "orderNum": 6, + "viewPath": "modules/recycle/views/data.vue", + "keepAlive": true, + "isShow": true, + "childMenus": [ + { + "name": "恢复数据", + "router": null, + "perms": "recycle:data:restore", + "type": 2, + "icon": null, + "orderNum": 0, + "viewPath": null, + "keepAlive": true, + "isShow": true, + "childMenus": [] + }, + { + "name": "单个信息", + "router": null, + "perms": "recycle:data:info", + "type": 2, + "icon": null, + "orderNum": 0, + "viewPath": null, + "keepAlive": true, + "isShow": true, + "childMenus": [] + }, + { + "name": "分页查询", + "router": null, + "perms": "recycle:data:page", + "type": 2, + "icon": null, + "orderNum": 0, + "viewPath": null, + "keepAlive": true, + "isShow": true, + "childMenus": [] + } + ] + }, + { + "name": "文件管理", + "router": "/upload/list", + "perms": null, + "type": 1, + "icon": "icon-log", + "orderNum": 5, + "viewPath": "modules/space/views/list.vue", + "keepAlive": true, + "isShow": true, + "childMenus": [ + { + "name": "权限", + "router": null, + "perms": "space:type:delete,space:type:update,space:type:info,space:type:list,space:type:page,space:type:add,space:info:getConfig,space:info:delete,space:info:update,space:info:info,space:info:list,space:info:page,space:info:add", + "type": 2, + "icon": null, + "orderNum": 0, + "viewPath": null, + "keepAlive": true, + "isShow": true, + "childMenus": [] + } + ] + } + ] + }, + { + "name": "用户管理", + "router": null, + "perms": null, + "type": 0, + "icon": "icon-user", + "orderNum": 11, + "viewPath": null, + "keepAlive": true, + "isShow": true, + "childMenus": [ + { + "name": "用户列表", + "router": "/user/list", + "perms": null, + "type": 1, + "icon": "icon-menu", + "orderNum": 1, + "viewPath": "modules/user/views/list.vue", + "keepAlive": true, + "isShow": true, + "childMenus": [ + { + "name": "删除", + "router": null, + "perms": "user:info:delete", + "type": 2, + "icon": null, + "orderNum": 0, + "viewPath": null, + "keepAlive": true, + "isShow": true, + "childMenus": [] + }, + { + "name": "修改", + "router": null, + "perms": "user:info:update,user:info:info", + "type": 2, + "icon": null, + "orderNum": 0, + "viewPath": null, + "keepAlive": true, + "isShow": true, + "childMenus": [] + }, + { + "name": "单个信息", + "router": null, + "perms": "user:info:info", + "type": 2, + "icon": null, + "orderNum": 0, + "viewPath": null, + "keepAlive": true, + "isShow": true, + "childMenus": [] + }, + { + "name": "列表查询", + "router": null, + "perms": "user:info:list", + "type": 2, + "icon": null, + "orderNum": 0, + "viewPath": null, + "keepAlive": true, + "isShow": true, + "childMenus": [] + }, + { + "name": "分页查询", + "router": null, + "perms": "user:info:page", + "type": 2, + "icon": null, + "orderNum": 0, + "viewPath": null, + "keepAlive": true, + "isShow": true, + "childMenus": [] + }, + { + "name": "新增", + "router": null, + "perms": "user:info:add", + "type": 2, + "icon": null, + "orderNum": 0, + "viewPath": null, + "keepAlive": true, + "isShow": true, + "childMenus": [] + } + ] + } + ] + } +] \ No newline at end of file diff --git a/cool-admin-java/src/main/resources/cool/data/menu/menu_8.0.json b/cool-admin-java/src/main/resources/cool/data/menu/menu_8.0.json new file mode 100644 index 0000000..4ad1c60 --- /dev/null +++ b/cool-admin-java/src/main/resources/cool/data/menu/menu_8.0.json @@ -0,0 +1,158 @@ +[ + { + "name": "数据管理", + "router": null, + "perms": null, + "type": 0, + "icon": "icon-data", + "orderNum": 7, + "viewPath": null, + "keepAlive": true, + "isShow": true, + "childMenus": [ + { + "name": "字典管理", + "router": "/dict/list", + "perms": null, + "type": 1, + "icon": "icon-dict", + "orderNum": 3, + "viewPath": "modules/dict/views/list.vue", + "keepAlive": true, + "isShow": true, + "childMenus": [ + { + "name": "字典类型", + "router": null, + "perms": "dict:type:delete,dict:type:update,dict:type:info,dict:type:list,dict:type:page,dict:type:add", + "type": 2, + "icon": null, + "orderNum": 0, + "viewPath": null, + "keepAlive": true, + "isShow": true, + "childMenus": [ + ] + } + ] + }] + }, + { + "name": "扩展管理", + "router": null, + "perms": null, + "type": 0, + "icon": "icon-favor", + "orderNum": 8, + "viewPath": null, + "keepAlive": true, + "isShow": true, + "childMenus": [ + { + "tenantId": null, + "name": "插件列表", + "router": "/helper/plugins", + "perms": null, + "type": 1, + "icon": "icon-list", + "orderNum": 1, + "viewPath": "modules/helper/views/plugins.vue", + "keepAlive": true, + "isShow": true, + "childMenus": [ + { + "tenantId": null, + "name": "删除", + "router": null, + "perms": "plugin:info:delete", + "type": 2, + "icon": null, + "orderNum": 0, + "viewPath": null, + "keepAlive": true, + "isShow": true, + "childMenus": [] + }, + { + "tenantId": null, + "name": "分页查询", + "router": null, + "perms": "plugin:info:page", + "type": 2, + "icon": null, + "orderNum": 0, + "viewPath": null, + "keepAlive": true, + "isShow": true, + "childMenus": [] + }, + { + "tenantId": null, + "name": "单个信息", + "router": null, + "perms": "plugin:info:info", + "type": 2, + "icon": null, + "orderNum": 0, + "viewPath": null, + "keepAlive": true, + "isShow": true, + "childMenus": [] + }, + { + "tenantId": null, + "name": "安装插件", + "router": null, + "perms": "plugin:info:install", + "type": 2, + "icon": null, + "orderNum": 0, + "viewPath": null, + "keepAlive": true, + "isShow": true, + "childMenus": [] + }, + { + "tenantId": null, + "name": "修改", + "router": null, + "perms": "plugin:info:update", + "type": 2, + "icon": null, + "orderNum": 0, + "viewPath": null, + "keepAlive": true, + "isShow": true, + "childMenus": [] + }, + { + "tenantId": null, + "name": "列表查询", + "router": null, + "perms": "plugin:info:list", + "type": 2, + "icon": null, + "orderNum": 0, + "viewPath": null, + "keepAlive": true, + "isShow": true, + "childMenus": [] + }, + { + "tenantId": null, + "name": "新增", + "router": null, + "perms": "plugin:info:add", + "type": 2, + "icon": null, + "orderNum": 0, + "viewPath": null, + "keepAlive": true, + "isShow": true, + "childMenus": [] + } + ] + } + ] + } +] \ No newline at end of file diff --git a/cool-admin-java/src/main/resources/static/css/welcome.css b/cool-admin-java/src/main/resources/static/css/welcome.css new file mode 100644 index 0000000..c838986 --- /dev/null +++ b/cool-admin-java/src/main/resources/static/css/welcome.css @@ -0,0 +1,89 @@ +body { + display: flex; + height: 100vh; + justify-content: center; + align-items: center; + text-align: center; + background: #222; +} + +@keyframes fadeIn { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +.footer-bar { + position: fixed; + bottom: 0; + left: 0; + right: 0; + color: #6ee1f5; + padding: 10px 0 20px 0; + text-align: center; + opacity: 0; /* 开始时隐藏 */ + animation: fadeIn 5s forwards; /* 应用动画 */ +} + +.link { + color: #6ee1f5; +} + +.reveal { + position: relative; + display: flex; + color: #6ee1f5; + font-size: 2em; + font-family: Raleway, sans-serif; + letter-spacing: 3px; + text-transform: uppercase; + white-space: pre; +} +.reveal span { + opacity: 0; + transform: scale(0); + animation: fadeIn 2.4s forwards; +} +.reveal::before, .reveal::after { + position: absolute; + content: ""; + top: 0; + bottom: 0; + width: 2px; + height: 100%; + background: white; + opacity: 0; + transform: scale(0); +} +.reveal::before { + left: 50%; + animation: slideLeft 1.5s cubic-bezier(0.7, -0.6, 0.3, 1.5) forwards; +} +.reveal::after { + right: 50%; + animation: slideRight 1.5s cubic-bezier(0.7, -0.6, 0.3, 1.5) forwards; +} + +@keyframes fadeIn { + to { + opacity: 1; + transform: scale(1); + } +} +@keyframes slideLeft { + to { + left: -6%; + opacity: 1; + transform: scale(0.9); + } +} +@keyframes slideRight { + to { + right: -6%; + opacity: 1; + transform: scale(0.9); + } +} diff --git a/cool-admin-java/src/main/resources/static/favicon.ico b/cool-admin-java/src/main/resources/static/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..c4d673d648d53e845927fde538a703f8e4be7c9d GIT binary patch literal 67646 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 literal 0 HcmV?d00001 diff --git a/cool-admin-java/src/main/resources/static/js/welcome.js b/cool-admin-java/src/main/resources/static/js/welcome.js new file mode 100644 index 0000000..eb9b697 --- /dev/null +++ b/cool-admin-java/src/main/resources/static/js/welcome.js @@ -0,0 +1,14 @@ +const duration = 0.8; +const delay = 0.3; +// eslint-disable-next-line no-undef +const revealText = document.querySelector('.reveal'); +const letters = revealText.textContent.split(''); +revealText.textContent = ''; +const middle = letters.filter(e => e !== ' ').length / 2; +letters.forEach((letter, i) => { + // eslint-disable-next-line no-undef + const span = document.createElement('span'); + span.textContent = letter; + span.style.animationDelay = `${delay + Math.abs(i - middle) * 0.1}s`; + revealText.append(span); +}); diff --git a/cool-admin-java/src/main/resources/templates/welcome.html b/cool-admin-java/src/main/resources/templates/welcome.html new file mode 100644 index 0000000..2bd2140 --- /dev/null +++ b/cool-admin-java/src/main/resources/templates/welcome.html @@ -0,0 +1,25 @@ + + + + + + + + COOL-ADMIN 一个很酷的后台管理系统开发框架 + + + + + +
HELLO COOL-ADMIN V8.x
+ +
+ + + + diff --git a/cool-admin-java/src/test/java/com/cool/CoolAdminJavaApplicationTests.java b/cool-admin-java/src/test/java/com/cool/CoolAdminJavaApplicationTests.java new file mode 100644 index 0000000..1d280e5 --- /dev/null +++ b/cool-admin-java/src/test/java/com/cool/CoolAdminJavaApplicationTests.java @@ -0,0 +1,13 @@ +package com.cool; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class CoolAdminJavaApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/cool-admin-java/src/test/java/com/cool/CoolCodeGeneratorTest.java b/cool-admin-java/src/test/java/com/cool/CoolCodeGeneratorTest.java new file mode 100644 index 0000000..acf8caf --- /dev/null +++ b/cool-admin-java/src/test/java/com/cool/CoolCodeGeneratorTest.java @@ -0,0 +1,56 @@ +package com.cool; + +import com.cool.core.code.CodeGenerator; +import com.cool.core.code.CodeModel; +import com.cool.core.code.CodeTypeEnum; +import com.cool.modules.user.entity.*; +import com.mybatisflex.annotation.Table; +import java.util.List; + +public class CoolCodeGeneratorTest { + public static void main(String[] args) { + CodeGenerator codeGenerator = new CodeGenerator(); + codeGenerator.init(); + List list = List.of(UserWxEntity.class); + + list.forEach(o -> { + Table annotation = (Table) o.getAnnotation(Table.class); + CodeModel codeModel = new CodeModel(); + codeModel.setType(CodeTypeEnum.APP); + codeModel.setName(annotation.comment()); + codeModel.setModule(getFirstWord(o.getSimpleName())); + codeModel.setEntity(o); + // 生成 controller +// codeGenerator.controller(codeModel); + // 生成 mapper + codeGenerator.mapper(codeModel); + // 生成 service + codeGenerator.service(codeModel); + }); + } + + public static String getFirstWord(String className) { + if (className == null || className.isEmpty()) { + return ""; + } + + StringBuilder firstWord = new StringBuilder(); + boolean foundFirstWord = false; + + for (char c : className.toCharArray()) { + if (Character.isUpperCase(c)) { + if (foundFirstWord) { + break; + } + firstWord.append(c); + foundFirstWord = true; + } else { + if (foundFirstWord) { + firstWord.append(c); + } + } + } + + return firstWord.toString().toLowerCase(); + } +} diff --git a/cool-admin-vue/.cursorrules b/cool-admin-vue/.cursorrules new file mode 100644 index 0000000..c0df244 --- /dev/null +++ b/cool-admin-vue/.cursorrules @@ -0,0 +1,74 @@ +# 项目背景 + +- 库:typescript、javaScript、scss、vue、tailwind +- 框架:cool-admin-vue +- 项目版本:8.x + +# 项目目录 + +├── .vscode(代码片段,根据关键字可以快速地生成代码) +├── public(静态资源文件) +├── packages(源码包:@cool-vue/crud、@cool-vue/vite-plugin) +├── build +│ └── cool() +│ │ └── eps.json(Eps 配置文件) +│ │ └── eps.d.ts(Eps 描述文件) +├── src +│ └── cool(核心文件) +│ └── modules(项目模块) +│ │ └── base(基础模块) +│ │ └── demo(示例模块) +│ │ └── dict(字典模块) +│ │ └── helper(辅助模块) +│ │ └── recycle(回收站模块) +│ │ └── space(cl-upload-space 文件空间模块) +│ │ └── task(任务模块) +│ │ └── user(用户模块) +│ └── plugins(项目插件) +│ │ └── crud(cl-crud、@cool-vue/crud) +│ │ └── distpicker(cl-distpicker、省市区选择器) +│ │ └── echarts(图标) +│ │ └── editor-preview(编辑器预览组件) +│ │ └── editor-wange(wang富文本编辑器) +│ │ └── element-ui(element-plus 组件) +│ │ └── excel(excel导入、导出组件) +│ │ └── i18n(多语言) +│ │ └── iconfont(iconfont 图标) +│ │ └── theme(cl-theme 主题组件) +│ │ └── upload(cl-upload 文件上传组件) +│ │ └── view(cl-view-group、cl-view-head 视图组件) +│ └── config +│ │ └── index.ts(默认配置) +│ │ └── dev.ts(开发环境) +│ │ └── prod.ts(生产环境) +│ │ └── proxy.ts(代理配置) +│ └── App.vue(入口文件) +│ └── main.ts(入口文件) +├── package.json(依赖管理,项目信息) +└── ... + +模块、插件目录 +├── modules/plugins +│ └── base(模块名) +│ │ └── components(全局组件) +│ │ └── directives(全局指令) +│ │ └── locales(国际化) +│ │ └── router(路由) +│ │ └── store(状态管理) +│ │ └── utils(工具函数) +│ │ └── views(视图) +│ │ └── config.ts(必须,模块的配置) +│ │ └── index.ts(模块导出) + +# 其它 + +- 文件、组件命名用 - 连接,如:student-info.vue +- service 的描述类型,查看 build/cool/eps.d.ts 描述文件 +- 创建模块、插件代码需要读取.cursor/rules的module.mdc,其它的rules根据需要进行参考 + +# import 引用别名 + +- "/@" 对应 "./src" +- "/$" 对应 "./src/modules" +- "/#" 对应 "./src/plugins" +- "/~" 对应 "./packages" diff --git a/cool-admin-vue/.dockerignore b/cool-admin-vue/.dockerignore new file mode 100644 index 0000000..d451ff1 --- /dev/null +++ b/cool-admin-vue/.dockerignore @@ -0,0 +1,5 @@ +node_modules +.DS_Store +dist +dist-ssr +*.local diff --git a/cool-admin-vue/.editorconfig b/cool-admin-vue/.editorconfig new file mode 100644 index 0000000..284364f --- /dev/null +++ b/cool-admin-vue/.editorconfig @@ -0,0 +1,7 @@ +[*.{js,jsx,mjs,cjs,ts,tsx,mts,cts,vue}] +charset = utf-8 +end_of_line = lf +indent_style = tab +indent_size = 4 +trim_trailing_whitespace = true +insert_final_newline = true diff --git a/cool-admin-vue/.env b/cool-admin-vue/.env new file mode 100644 index 0000000..028356d --- /dev/null +++ b/cool-admin-vue/.env @@ -0,0 +1,5 @@ +# 应用名称 +VITE_NAME = "COOL-ADMIN" + +# 网络超时请求时间 +VITE_TIMEOUT = 30000 \ No newline at end of file diff --git a/cool-admin-vue/.gitattributes b/cool-admin-vue/.gitattributes new file mode 100644 index 0000000..e41187f --- /dev/null +++ b/cool-admin-vue/.gitattributes @@ -0,0 +1,4 @@ +*.js text eol=lf +*.json text eol=lf +*.ts text eol=lf +*.vue text eol=lf \ No newline at end of file diff --git a/cool-admin-vue/.gitignore b/cool-admin-vue/.gitignore new file mode 100644 index 0000000..615a016 --- /dev/null +++ b/cool-admin-vue/.gitignore @@ -0,0 +1,20 @@ +.DS_Store +node_modules/ +/dist/ +dist-ssr/ + +# Log files +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Editor directories and files +.project +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw* + +vite.config.ts.timestamp* diff --git a/cool-admin-vue/.hintrc b/cool-admin-vue/.hintrc new file mode 100644 index 0000000..de024c3 --- /dev/null +++ b/cool-admin-vue/.hintrc @@ -0,0 +1,16 @@ +{ + "extends": [ + "development" + ], + "hints": { + "meta-viewport": "off", + "axe/text-alternatives": [ + "default", + { + "document-title": "off" + } + ], + "disown-opener": "off", + "css-prefix-order": "off" + } +} \ No newline at end of file diff --git a/cool-admin-vue/.prettierrc.json b/cool-admin-vue/.prettierrc.json new file mode 100644 index 0000000..29d7d66 --- /dev/null +++ b/cool-admin-vue/.prettierrc.json @@ -0,0 +1,10 @@ +{ + "$schema": "https://json.schemastore.org/prettierrc", + "semi": true, + "useTabs": true, + "tabWidth": 4, + "printWidth": 100, + "singleQuote": true, + "arrowParens": "avoid", + "trailingComma": "none" +} diff --git a/cool-admin-vue/Dockerfile b/cool-admin-vue/Dockerfile new file mode 100644 index 0000000..811db32 --- /dev/null +++ b/cool-admin-vue/Dockerfile @@ -0,0 +1,14 @@ +FROM node:lts-alpine +WORKDIR /build +# 设置npm镜像 +RUN npm config set registry https://registry.npmmirror.com +COPY package.json /build/package.json +RUN npm install +COPY ./ /build +RUN npm run build + +FROM nginx +RUN mkdir /app +COPY --from=0 /build/dist /app +COPY --from=0 /build/nginx.conf /etc/nginx/nginx.conf +EXPOSE 80 diff --git a/cool-admin-vue/LICENSE b/cool-admin-vue/LICENSE new file mode 100644 index 0000000..b6722d4 --- /dev/null +++ b/cool-admin-vue/LICENSE @@ -0,0 +1,33 @@ +MIT License + +Copyright (c) [2025] [厦门闪酷科技开发有限公司] + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +--- + +MIT 许可证 + +版权所有 (c) [2025] [厦门闪酷科技开发有限公司] + +特此免费授予获得本软件及相关文档文件(“软件”)副本的任何人无限制地处理本软件的权限,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或销售软件的副本,并允许软件提供给其的人员这样做,但须符合以下条件: + +上述版权声明和本许可声明应包含在软件的所有副本或主要部分中。 + +本软件按“原样”提供,不提供任何明示或暗示的担保,包括但不限于对适销性、特定用途适用性和非侵权的担保。在任何情况下,作者或版权持有人均不对因软件或软件使用或其他交易而产生的任何索赔、损害或其他责任负责,无论是在合同诉讼、侵权诉讼或其他诉讼中。 \ No newline at end of file diff --git a/cool-admin-vue/README.md b/cool-admin-vue/README.md new file mode 100644 index 0000000..7a03692 --- /dev/null +++ b/cool-admin-vue/README.md @@ -0,0 +1,78 @@ +# cool-admin [vue3 - ts - vite] + +

+ cool-admin Logo +

+ +

cool-admin 一个很酷的后台权限管理系统,开源免费,模块化、插件化、极速开发 CRUD,方便快速构建迭代后台管理系统, 到文档 进一步了解

+ +

+ GitHub license + GitHub tag + GitHub tag +

+ +## 特性 + +Ai时代,很多老旧的框架已经无法满足现代化的开发需求,Cool-Admin开发了一系列的功能,让开发变得更简单、更快速、更高效。 + +- **Ai编码**:通过微调大模型学习框架特有写法,实现简单功能从Api接口到前端页面的一键生成 +- **流程编排**:通过拖拽编排方式,即可实现类似像智能客服这样的功能 +- **模块化**:代码是模块化的,清晰明了,方便维护 +- **插件化**:插件化的设计,可以通过安装插件的方式扩展如:支付、短信、邮件等功能 + +![](https://cool-show.oss-cn-shanghai.aliyuncs.com/admin/flow.png) + +## 地址 + +- [📌 v7 版本](https://github.com/cool-team-official/cool-admin-vue/tree/7.x) + +- [🌐 码云仓库](https://gitee.com/cool-team-official/cool-admin-vue) + +## 视频教程 + +[官方 B 站视频教程](https://www.bilibili.com/video/BV1j1421R7aB) + +## 演示 + +[https://show.cool-admin.com](https://show.cool-admin.com) + +账户:admin,密码:123456 + +Admin Home + +## 项目后端 + +[https://github.com/cool-team-official/cool-admin-midway](https://github.com/cool-team-official/cool-admin-midway) + +或 + +[https://gitee.com/cool-team-official/cool-admin-midway](https://gitee.com/cool-team-official/cool-admin-midway) + +或 + +[https://gitcode.com/cool_team/cool-admin-midway](https://gitcode.com/cool_team/cool-admin-midway) + +## 微信群 + +Admin Wechat + +## 安装项目依赖 + +推荐使用 `pnpm`: + +```shell +pnpm i +``` + +## 运行应用程序 + +安装过程完成后,运行以下命令启动服务。您可以在浏览器中预览网站 [http://localhost:9000](http://localhost:9000) + +```shell +pnpm dev +``` + +### 低价服务器 + +[阿里云、腾讯云、华为云低价云服务器,不限新老](https://cool-js.com/service/cloud) diff --git a/cool-admin-vue/env.d.ts b/cool-admin-vue/env.d.ts new file mode 100644 index 0000000..b5a1827 --- /dev/null +++ b/cool-admin-vue/env.d.ts @@ -0,0 +1,10 @@ +/// + +interface ImportMetaEnv { + readonly VITE_NAME: string; + readonly VITE_TIMEOUT: number; +} + +interface ImportMeta { + readonly env: ImportMetaEnv; +} diff --git a/cool-admin-vue/eslint.config.js b/cool-admin-vue/eslint.config.js new file mode 100644 index 0000000..a361065 --- /dev/null +++ b/cool-admin-vue/eslint.config.js @@ -0,0 +1,73 @@ +import pluginVue from 'eslint-plugin-vue'; +import vueTsEslintConfig from '@vue/eslint-config-typescript'; +import prettier from 'eslint-plugin-prettier'; +import skipFormatting from '@vue/eslint-config-prettier/skip-formatting'; + +export default [ + { + name: 'app/files-to-lint', + files: ['**/*.{ts,mts,tsx,vue}'], + }, + + { + name: 'app/files-to-ignore', + ignores: [ + '**/dist/**', + '**/dist-ssr/**', + '**/coverage/**', + '**/packages/**', + '**/build/**', + ], + }, + + ...pluginVue.configs['flat/recommended'], + ...vueTsEslintConfig(), + skipFormatting, + + { + languageOptions: { + parserOptions: { + ecmaVersion: 2020, + ecmaFeatures: { + jsx: true, + }, + }, + }, + rules: { + '@typescript-eslint/ban-ts-ignore': 'off', + '@typescript-eslint/explicit-function-return-type': 'off', + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-var-requires': 'off', + '@typescript-eslint/no-empty-function': 'off', + '@typescript-eslint/no-use-before-define': 'off', + '@typescript-eslint/ban-ts-comment': 'off', + '@typescript-eslint/ban-types': 'off', + '@typescript-eslint/no-non-null-assertion': 'off', + '@typescript-eslint/explicit-module-boundary-types': 'off', + '@typescript-eslint/no-namespace': 'off', + '@typescript-eslint/no-unused-vars': 'off', + '@typescript-eslint/no-empty-object-type': 'off', + 'space-before-function-paren': 'off', + 'no-unused-vars': 'off', + 'no-use-before-define': 'off', + 'no-self-assign': 'off', + 'vue/no-mutating-props': 'off', + 'vue/no-template-shadow': 'off', + 'vue/no-v-html': 'off', + 'vue/component-name-in-template-casing': ['error', 'kebab-case'], + 'vue/component-definition-name-casing': ['error', 'kebab-case'], + 'vue/attributes-order': 'off', + 'vue/one-component-per-file': 'off', + 'vue/html-closing-bracket-newline': 'off', + 'vue/max-attributes-per-line': 'off', + 'vue/multiline-html-element-content-newline': 'off', + 'vue/multi-word-component-names': 'off', + 'vue/singleline-html-element-content-newline': 'off', + 'vue/attribute-hyphenation': 'off', + 'vue/html-self-closing': 'off', + 'vue/require-default-prop': 'off', + 'vue/v-on-event-hyphenation': 'off', + 'vue/block-lang': 'off', + }, + }, +]; diff --git a/cool-admin-vue/index.html b/cool-admin-vue/index.html new file mode 100644 index 0000000..1148b64 --- /dev/null +++ b/cool-admin-vue/index.html @@ -0,0 +1,178 @@ + + + + + + + + + + + + + + +
+
+
+
+
+
+
+
+ +
+ + + diff --git a/cool-admin-vue/nginx.conf b/cool-admin-vue/nginx.conf new file mode 100644 index 0000000..2a02b0a --- /dev/null +++ b/cool-admin-vue/nginx.conf @@ -0,0 +1,72 @@ +user nginx; +worker_processes 1; +error_log /var/log/nginx/error.log warn; +pid /var/run/nginx.pid; +events { + worker_connections 1024; +} +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + access_log /var/log/nginx/access.log main; + sendfile on; + keepalive_timeout 65; + upstream cool { + server midway:8001; + } + + server { + listen 80; + server_name localhost; + location / { + root /app; + index index.html; + try_files $uri $uri/ /index.html; + } + location /api/ { + proxy_pass http://cool/; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header REMOTE-HOST $remote_addr; + + #缓存相关配置 + #proxy_cache cache_one; + #proxy_cache_key $host$request_uri$is_args$args; + #proxy_cache_valid 200 304 301 302 1h; + + #持久化连接相关配置 + proxy_connect_timeout 3000s; + proxy_read_timeout 86400s; + proxy_send_timeout 3000s; + #proxy_http_version 1.1; + #proxy_set_header Upgrade $http_upgrade; + #proxy_set_header Connection "upgrade"; + + add_header X-Cache $upstream_cache_status; + + #expires 12h; + } + + # socket需额外配置 + location /socket { + proxy_pass http://cool/socket; + proxy_connect_timeout 3600s; #配置点1 + proxy_read_timeout 3600s; #配置点2,如果没效,可以考虑这个时间配置长一点 + proxy_send_timeout 3600s; #配置点3 + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header REMOTE-HOST $remote_addr; + #proxy_bind $remote_addr transparent; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + rewrite /socket/(.*) /$1 break; + proxy_redirect off; + } + } +} \ No newline at end of file diff --git a/cool-admin-vue/package-lock.json b/cool-admin-vue/package-lock.json new file mode 100644 index 0000000..80ea03c --- /dev/null +++ b/cool-admin-vue/package-lock.json @@ -0,0 +1,8907 @@ +{ + "name": "cool-admin-vue", + "version": "8.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "cool-admin-vue", + "version": "8.0.0", + "dependencies": { + "@cool-vue/crud": "^8.0.6", + "@element-plus/icons-vue": "^2.3.1", + "@vueuse/core": "^12.5.0", + "@wangeditor/editor": "^5.1.23", + "@wangeditor/editor-for-vue": "^5.1.12", + "axios": "^1.7.9", + "chardet": "^2.0.0", + "core-js": "^3.40.0", + "dayjs": "^1.11.13", + "echarts": "^5.6.0", + "element-plus": "2.10.2", + "file-saver": "^2.0.5", + "lodash-es": "^4.17.21", + "marked": "^14.1.3", + "mitt": "^3.0.1", + "nprogress": "^0.2.0", + "pinia": "^2.3.1", + "store": "^2.0.12", + "vue": "^3.5.13", + "vue-echarts": "^7.0.3", + "vue-i18n": "^11.0.1", + "vue-router": "^4.5.0", + "vuedraggable": "^4.1.0", + "xlsx": "^0.18.5" + }, + "devDependencies": { + "@cool-vue/vite-plugin": "^8.2.2", + "@intlify/unplugin-vue-i18n": "^6.0.3", + "@rushstack/eslint-patch": "^1.10.5", + "@tsconfig/node20": "^20.1.4", + "@types/file-saver": "^2.0.7", + "@types/lodash-es": "^4.17.12", + "@types/mockjs": "^1.0.10", + "@types/node": "^20.17.17", + "@types/nprogress": "^0.2.3", + "@types/store": "^2.0.5", + "@vitejs/plugin-vue": "^5.2.1", + "@vitejs/plugin-vue-jsx": "^4.1.1", + "@vue/compiler-sfc": "^3.5.13", + "@vue/eslint-config-prettier": "^10.2.0", + "@vue/eslint-config-typescript": "^14.3.0", + "@vue/test-utils": "^2.4.6", + "@vue/tsconfig": "^0.5.1", + "autoprefixer": "^10.4.20", + "eslint": "^9.19.0", + "eslint-plugin-prettier": "^5.2.3", + "eslint-plugin-vue": "^9.32.0", + "postcss": "^8.5.1", + "prettier": "^3.4.2", + "rollup-plugin-visualizer": "^5.14.0", + "sass": "1.81.0", + "tailwindcss": "^3.4.17", + "terser": "^5.36.0", + "typescript": "~5.5.4", + "vite": "^5.4.14", + "vite-plugin-compression": "^0.5.1", + "vite-plugin-vue-devtools": "^7.7.1", + "vue-tsc": "^2.2.0" + } + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmmirror.com/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@antfu/utils": { + "version": "0.7.10", + "resolved": "https://registry.npmmirror.com/@antfu/utils/-/utils-0.7.10.tgz", + "integrity": "sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.27.1", + "resolved": "https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.28.0", + "resolved": "https://registry.npmmirror.com/@babel/compat-data/-/compat-data-7.28.0.tgz", + "integrity": "sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.28.3", + "resolved": "https://registry.npmmirror.com/@babel/core/-/core-7.28.3.tgz", + "integrity": "sha512-yDBHV9kQNcr2/sUr9jghVyz9C3Y5G2zUM2H2lo+9mKv4sFgbA8s8Z9t8D1jiTkGoO/NoIfKMyKWr4s6CN23ZwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.3", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-module-transforms": "^7.28.3", + "@babel/helpers": "^7.28.3", + "@babel/parser": "^7.28.3", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.3", + "@babel/types": "^7.28.2", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.28.3", + "resolved": "https://registry.npmmirror.com/@babel/generator/-/generator-7.28.3.tgz", + "integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.3", + "@babel/types": "^7.28.2", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.27.3", + "resolved": "https://registry.npmmirror.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz", + "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.27.3" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.27.2", + "resolved": "https://registry.npmmirror.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.28.3", + "resolved": "https://registry.npmmirror.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.3.tgz", + "integrity": "sha512-V9f6ZFIYSLNEbuGA/92uOvYsGCJNsuA8ESZ4ldc09bWk/j8H8TKiPw8Mk1eG6olpnO0ALHJmYfZvF4MEE4gajg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-member-expression-to-functions": "^7.27.1", + "@babel/helper-optimise-call-expression": "^7.27.1", + "@babel/helper-replace-supers": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/traverse": "^7.28.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmmirror.com/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.27.1", + "resolved": "https://registry.npmmirror.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.27.1.tgz", + "integrity": "sha512-E5chM8eWjTp/aNoVpcbfM7mLxu9XGLWYise2eBKGQomAk/Mb4XoxyqXTZbuTohbsl8EKqdlMhnDI2CCLfcs9wA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.27.1", + "resolved": "https://registry.npmmirror.com/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.3", + "resolved": "https://registry.npmmirror.com/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", + "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.28.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.27.1", + "resolved": "https://registry.npmmirror.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz", + "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.27.1", + "resolved": "https://registry.npmmirror.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", + "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.27.1", + "resolved": "https://registry.npmmirror.com/@babel/helper-replace-supers/-/helper-replace-supers-7.27.1.tgz", + "integrity": "sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-member-expression-to-functions": "^7.27.1", + "@babel/helper-optimise-call-expression": "^7.27.1", + "@babel/traverse": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.27.1", + "resolved": "https://registry.npmmirror.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz", + "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.27.1", + "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmmirror.com/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.28.3", + "resolved": "https://registry.npmmirror.com/@babel/helpers/-/helpers-7.28.3.tgz", + "integrity": "sha512-PTNtvUQihsAsDHMOP5pfobP8C6CM4JWXmP8DrEIt46c3r2bf87Ua1zoqevsMo9g+tWDwgWrFP5EIxuBx5RudAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.28.3", + "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.28.3.tgz", + "integrity": "sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.2" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-proposal-decorators": { + "version": "7.28.0", + "resolved": "https://registry.npmmirror.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.28.0.tgz", + "integrity": "sha512-zOiZqvANjWDUaUS9xMxbMcK/Zccztbe/6ikvUXaG9nsPH3w6qh5UaPGAnirI/WhIbZ8m3OHU0ReyPrknG+ZKeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/plugin-syntax-decorators": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-decorators": { + "version": "7.27.1", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.27.1.tgz", + "integrity": "sha512-YMq8Z87Lhl8EGkmb0MwYkt36QnxC+fzCgrl66ereamPlYToRpIk5nUjKUY3QKLWq8mwUB1BgbeXcTJhZOCDg5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.27.1", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz", + "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.27.1", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz", + "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.27.1", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz", + "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.28.0", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.28.0.tgz", + "integrity": "sha512-4AEiDEBPIZvLQaWlc9liCavE0xRM0dNca41WtBeM3jgFptfUOSG9z0uteLhq6+3rq+WB6jIvUwKDTpXEHPJ2Vg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-create-class-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/plugin-syntax-typescript": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.28.3", + "resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.28.3.tgz", + "integrity": "sha512-9uIQ10o0WGdpP6GDhXcdOJPJuDgFtIDtN/9+ArJQ2NAfAmiuhTQdzkaTGR33v43GYS2UrSA0eX2pPPHoFVvpxA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.27.2", + "resolved": "https://registry.npmmirror.com/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.28.3", + "resolved": "https://registry.npmmirror.com/@babel/traverse/-/traverse-7.28.3.tgz", + "integrity": "sha512-7w4kZYHneL3A6NP2nxzHvT3HCZ7puDZZjFMqDpBPECub79sTtSO5CGXDkKrTQq8ksAwfD/XI2MRFX23njdDaIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.3", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.3", + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.2", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.28.2", + "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.28.2.tgz", + "integrity": "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@cool-vue/crud": { + "version": "8.0.6", + "resolved": "https://registry.npmmirror.com/@cool-vue/crud/-/crud-8.0.6.tgz", + "integrity": "sha512-be6nKaUhdRmr2OQD6kJS6C+d1QTf6ibkp5fRSqs3x+lDuZOnyCh4/f/xg6ShKh2vtf+Bidwc2ftuxyEWx3A8SA==", + "dependencies": { + "@vue/runtime-core": "^3.5.13", + "element-plus": "^2.10.4", + "lodash-es": "^4.17.21", + "vue": "^3.5.13" + } + }, + "node_modules/@cool-vue/crud/node_modules/@types/web-bluetooth": { + "version": "0.0.16", + "resolved": "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz", + "integrity": "sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==", + "license": "MIT" + }, + "node_modules/@cool-vue/crud/node_modules/@vueuse/core": { + "version": "9.13.0", + "resolved": "https://registry.npmmirror.com/@vueuse/core/-/core-9.13.0.tgz", + "integrity": "sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==", + "license": "MIT", + "dependencies": { + "@types/web-bluetooth": "^0.0.16", + "@vueuse/metadata": "9.13.0", + "@vueuse/shared": "9.13.0", + "vue-demi": "*" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@cool-vue/crud/node_modules/@vueuse/metadata": { + "version": "9.13.0", + "resolved": "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-9.13.0.tgz", + "integrity": "sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@cool-vue/crud/node_modules/@vueuse/shared": { + "version": "9.13.0", + "resolved": "https://registry.npmmirror.com/@vueuse/shared/-/shared-9.13.0.tgz", + "integrity": "sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==", + "license": "MIT", + "dependencies": { + "vue-demi": "*" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@cool-vue/crud/node_modules/element-plus": { + "version": "2.10.7", + "resolved": "https://registry.npmmirror.com/element-plus/-/element-plus-2.10.7.tgz", + "integrity": "sha512-bL4yhepL8/0NEQA5+N2Q6ZVKLipIDkiQjK2mqtSmGh6CxJk1yaBMdG5HXfYkbk1htNcT3ULk9g23lzT323JGcA==", + "license": "MIT", + "dependencies": { + "@ctrl/tinycolor": "^3.4.1", + "@element-plus/icons-vue": "^2.3.1", + "@floating-ui/dom": "^1.0.1", + "@popperjs/core": "npm:@sxzz/popperjs-es@^2.11.7", + "@types/lodash": "^4.14.182", + "@types/lodash-es": "^4.17.6", + "@vueuse/core": "^9.1.0", + "async-validator": "^4.2.5", + "dayjs": "^1.11.13", + "escape-html": "^1.0.3", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", + "lodash-unified": "^1.0.2", + "memoize-one": "^6.0.0", + "normalize-wheel-es": "^1.2.0" + }, + "peerDependencies": { + "vue": "^3.2.0" + } + }, + "node_modules/@cool-vue/vite-plugin": { + "version": "8.2.6", + "resolved": "https://registry.npmmirror.com/@cool-vue/vite-plugin/-/vite-plugin-8.2.6.tgz", + "integrity": "sha512-Ey1qIMoHZOZdl/PxZ7qSa5A8hah0IlMVoyxPH7PQk6tAB1PNJiUfTkrPFi9vohFEeuj3WMZ5NhlRh+UIC3ZRXw==", + "dev": true, + "license": "ISC", + "dependencies": { + "@vue/compiler-sfc": "^3.5.13", + "axios": "^1.6.8", + "glob": "^10.3.12", + "lodash": "^4.17.21", + "magic-string": "^0.30.17", + "prettier": "^3.4.2", + "svgo": "^3.3.2" + } + }, + "node_modules/@ctrl/tinycolor": { + "version": "3.6.1", + "resolved": "https://registry.npmmirror.com/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz", + "integrity": "sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/@element-plus/icons-vue": { + "version": "2.3.2", + "resolved": "https://registry.npmmirror.com/@element-plus/icons-vue/-/icons-vue-2.3.2.tgz", + "integrity": "sha512-OzIuTaIfC8QXEPmJvB4Y4kw34rSXdCJzxcD1kFStBvr8bK6X1zQAYDo0CNMjojnfTqRQCJ0I7prlErcoRiET2A==", + "license": "MIT", + "peerDependencies": { + "vue": "^3.2.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.7.0", + "resolved": "https://registry.npmmirror.com/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", + "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmmirror.com/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.0", + "resolved": "https://registry.npmmirror.com/@eslint/config-array/-/config-array-0.21.0.tgz", + "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.6", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-array/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.3.1", + "resolved": "https://registry.npmmirror.com/@eslint/config-helpers/-/config-helpers-0.3.1.tgz", + "integrity": "sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.15.2", + "resolved": "https://registry.npmmirror.com/@eslint/core/-/core-0.15.2.tgz", + "integrity": "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.1", + "resolved": "https://registry.npmmirror.com/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", + "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/js": { + "version": "9.33.0", + "resolved": "https://registry.npmmirror.com/@eslint/js/-/js-9.33.0.tgz", + "integrity": "sha512-5K1/mKhWaMfreBGJTwval43JJmkip0RmM+3+IuqupeSKNC/Th2Kc7ucaq5ovTSra/OOKB9c58CGSz3QMVbWt0A==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.6", + "resolved": "https://registry.npmmirror.com/@eslint/object-schema/-/object-schema-2.1.6.tgz", + "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.3.5", + "resolved": "https://registry.npmmirror.com/@eslint/plugin-kit/-/plugin-kit-0.3.5.tgz", + "integrity": "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.15.2", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@floating-ui/core": { + "version": "1.7.3", + "resolved": "https://registry.npmmirror.com/@floating-ui/core/-/core-1.7.3.tgz", + "integrity": "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==", + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.10" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.7.3", + "resolved": "https://registry.npmmirror.com/@floating-ui/dom/-/dom-1.7.3.tgz", + "integrity": "sha512-uZA413QEpNuhtb3/iIKoYMSK07keHPYeXF02Zhd6e213j+d1NamLix/mCLxBUDW/Gx52sPH2m+chlUsyaBs/Ag==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.7.3", + "@floating-ui/utils": "^0.2.10" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.10", + "resolved": "https://registry.npmmirror.com/@floating-ui/utils/-/utils-0.2.10.tgz", + "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==", + "license": "MIT" + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmmirror.com/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.6", + "resolved": "https://registry.npmmirror.com/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.3.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmmirror.com/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmmirror.com/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@intlify/bundle-utils": { + "version": "10.0.1", + "resolved": "https://registry.npmmirror.com/@intlify/bundle-utils/-/bundle-utils-10.0.1.tgz", + "integrity": "sha512-WkaXfSevtpgtUR4t8K2M6lbR7g03mtOxFeh+vXp5KExvPqS12ppaRj1QxzwRuRI5VUto54A22BjKoBMLyHILWQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@intlify/message-compiler": "^11.1.2", + "@intlify/shared": "^11.1.2", + "acorn": "^8.8.2", + "escodegen": "^2.1.0", + "estree-walker": "^2.0.2", + "jsonc-eslint-parser": "^2.3.0", + "mlly": "^1.2.0", + "source-map-js": "^1.0.1", + "yaml-eslint-parser": "^1.2.2" + }, + "engines": { + "node": ">= 18" + }, + "peerDependenciesMeta": { + "petite-vue-i18n": { + "optional": true + }, + "vue-i18n": { + "optional": true + } + } + }, + "node_modules/@intlify/core-base": { + "version": "11.1.11", + "resolved": "https://registry.npmmirror.com/@intlify/core-base/-/core-base-11.1.11.tgz", + "integrity": "sha512-1Z0N8jTfkcD2Luq9HNZt+GmjpFe4/4PpZF3AOzoO1u5PTtSuXZcfhwBatywbfE2ieB/B5QHIoOFmCXY2jqVKEQ==", + "license": "MIT", + "dependencies": { + "@intlify/message-compiler": "11.1.11", + "@intlify/shared": "11.1.11" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + } + }, + "node_modules/@intlify/message-compiler": { + "version": "11.1.11", + "resolved": "https://registry.npmmirror.com/@intlify/message-compiler/-/message-compiler-11.1.11.tgz", + "integrity": "sha512-7PC6neomoc/z7a8JRjPBbu0T2TzR2MQuY5kn2e049MP7+o32Ve7O8husylkA7K9fQRe4iNXZWTPnDJ6vZdtS1Q==", + "license": "MIT", + "dependencies": { + "@intlify/shared": "11.1.11", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + } + }, + "node_modules/@intlify/shared": { + "version": "11.1.11", + "resolved": "https://registry.npmmirror.com/@intlify/shared/-/shared-11.1.11.tgz", + "integrity": "sha512-RIBFTIqxZSsxUqlcyoR7iiC632bq7kkOwYvZlvcVObHfrF4NhuKc4FKvu8iPCrEO+e3XsY7/UVpfgzg+M7ETzA==", + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + } + }, + "node_modules/@intlify/unplugin-vue-i18n": { + "version": "6.0.8", + "resolved": "https://registry.npmmirror.com/@intlify/unplugin-vue-i18n/-/unplugin-vue-i18n-6.0.8.tgz", + "integrity": "sha512-Vvm3KhjE6TIBVUQAk37rBiaYy2M5OcWH0ZcI1XKEsOTeN1o0bErk+zeuXmcrcMc/73YggfI8RoxOUz9EB/69JQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@intlify/bundle-utils": "^10.0.1", + "@intlify/shared": "^11.1.2", + "@intlify/vue-i18n-extensions": "^8.0.0", + "@rollup/pluginutils": "^5.1.0", + "@typescript-eslint/scope-manager": "^8.13.0", + "@typescript-eslint/typescript-estree": "^8.13.0", + "debug": "^4.3.3", + "fast-glob": "^3.2.12", + "js-yaml": "^4.1.0", + "json5": "^2.2.3", + "pathe": "^1.0.0", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2", + "unplugin": "^1.1.0", + "vue": "^3.4" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "petite-vue-i18n": "*", + "vue": "^3.2.25", + "vue-i18n": "*" + }, + "peerDependenciesMeta": { + "petite-vue-i18n": { + "optional": true + }, + "vue-i18n": { + "optional": true + } + } + }, + "node_modules/@intlify/vue-i18n-extensions": { + "version": "8.0.0", + "resolved": "https://registry.npmmirror.com/@intlify/vue-i18n-extensions/-/vue-i18n-extensions-8.0.0.tgz", + "integrity": "sha512-w0+70CvTmuqbskWfzeYhn0IXxllr6mU+IeM2MU0M+j9OW64jkrvqY+pYFWrUnIIC9bEdij3NICruicwd5EgUuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.24.6", + "@intlify/shared": "^10.0.0", + "@vue/compiler-dom": "^3.2.45", + "vue-i18n": "^10.0.0" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@intlify/shared": "^9.0.0 || ^10.0.0 || ^11.0.0", + "@vue/compiler-dom": "^3.0.0", + "vue": "^3.0.0", + "vue-i18n": "^9.0.0 || ^10.0.0 || ^11.0.0" + }, + "peerDependenciesMeta": { + "@intlify/shared": { + "optional": true + }, + "@vue/compiler-dom": { + "optional": true + }, + "vue": { + "optional": true + }, + "vue-i18n": { + "optional": true + } + } + }, + "node_modules/@intlify/vue-i18n-extensions/node_modules/@intlify/core-base": { + "version": "10.0.8", + "resolved": "https://registry.npmmirror.com/@intlify/core-base/-/core-base-10.0.8.tgz", + "integrity": "sha512-FoHslNWSoHjdUBLy35bpm9PV/0LVI/DSv9L6Km6J2ad8r/mm0VaGg06C40FqlE8u2ADcGUM60lyoU7Myo4WNZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@intlify/message-compiler": "10.0.8", + "@intlify/shared": "10.0.8" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + } + }, + "node_modules/@intlify/vue-i18n-extensions/node_modules/@intlify/message-compiler": { + "version": "10.0.8", + "resolved": "https://registry.npmmirror.com/@intlify/message-compiler/-/message-compiler-10.0.8.tgz", + "integrity": "sha512-DV+sYXIkHVd5yVb2mL7br/NEUwzUoLBsMkV3H0InefWgmYa34NLZUvMCGi5oWX+Hqr2Y2qUxnVrnOWF4aBlgWg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@intlify/shared": "10.0.8", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + } + }, + "node_modules/@intlify/vue-i18n-extensions/node_modules/@intlify/shared": { + "version": "10.0.8", + "resolved": "https://registry.npmmirror.com/@intlify/shared/-/shared-10.0.8.tgz", + "integrity": "sha512-BcmHpb5bQyeVNrptC3UhzpBZB/YHHDoEREOUERrmF2BRxsyOEuRrq+Z96C/D4+2KJb8kuHiouzAei7BXlG0YYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + } + }, + "node_modules/@intlify/vue-i18n-extensions/node_modules/vue-i18n": { + "version": "10.0.8", + "resolved": "https://registry.npmmirror.com/vue-i18n/-/vue-i18n-10.0.8.tgz", + "integrity": "sha512-mIjy4utxMz9lMMo6G9vYePv7gUFt4ztOMhY9/4czDJxZ26xPeJ49MAGa9wBAE3XuXbYCrtVPmPxNjej7JJJkZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@intlify/core-base": "10.0.8", + "@intlify/shared": "10.0.8", + "@vue/devtools-api": "^6.5.0" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + }, + "peerDependencies": { + "vue": "^3.0.0" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmmirror.com/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmmirror.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmmirror.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.11", + "resolved": "https://registry.npmmirror.com/@jridgewell/source-map/-/source-map-0.3.11.tgz", + "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.30", + "resolved": "https://registry.npmmirror.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.30.tgz", + "integrity": "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmmirror.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmmirror.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmmirror.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@one-ini/wasm": { + "version": "0.1.1", + "resolved": "https://registry.npmmirror.com/@one-ini/wasm/-/wasm-0.1.1.tgz", + "integrity": "sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@parcel/watcher": { + "version": "2.5.1", + "resolved": "https://registry.npmmirror.com/@parcel/watcher/-/watcher-2.5.1.tgz", + "integrity": "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "detect-libc": "^1.0.3", + "is-glob": "^4.0.3", + "micromatch": "^4.0.5", + "node-addon-api": "^7.0.0" + }, + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "@parcel/watcher-android-arm64": "2.5.1", + "@parcel/watcher-darwin-arm64": "2.5.1", + "@parcel/watcher-darwin-x64": "2.5.1", + "@parcel/watcher-freebsd-x64": "2.5.1", + "@parcel/watcher-linux-arm-glibc": "2.5.1", + "@parcel/watcher-linux-arm-musl": "2.5.1", + "@parcel/watcher-linux-arm64-glibc": "2.5.1", + "@parcel/watcher-linux-arm64-musl": "2.5.1", + "@parcel/watcher-linux-x64-glibc": "2.5.1", + "@parcel/watcher-linux-x64-musl": "2.5.1", + "@parcel/watcher-win32-arm64": "2.5.1", + "@parcel/watcher-win32-ia32": "2.5.1", + "@parcel/watcher-win32-x64": "2.5.1" + } + }, + "node_modules/@parcel/watcher-android-arm64": { + "version": "2.5.1", + "resolved": "https://registry.npmmirror.com/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.1.tgz", + "integrity": "sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-arm64": { + "version": "2.5.1", + "resolved": "https://registry.npmmirror.com/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.1.tgz", + "integrity": "sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-x64": { + "version": "2.5.1", + "resolved": "https://registry.npmmirror.com/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.1.tgz", + "integrity": "sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-freebsd-x64": { + "version": "2.5.1", + "resolved": "https://registry.npmmirror.com/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.1.tgz", + "integrity": "sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-glibc": { + "version": "2.5.1", + "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.1.tgz", + "integrity": "sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-musl": { + "version": "2.5.1", + "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.1.tgz", + "integrity": "sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-glibc": { + "version": "2.5.1", + "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.1.tgz", + "integrity": "sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-musl": { + "version": "2.5.1", + "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.1.tgz", + "integrity": "sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-glibc": { + "version": "2.5.1", + "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.1.tgz", + "integrity": "sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-musl": { + "version": "2.5.1", + "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.1.tgz", + "integrity": "sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-arm64": { + "version": "2.5.1", + "resolved": "https://registry.npmmirror.com/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.1.tgz", + "integrity": "sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-ia32": { + "version": "2.5.1", + "resolved": "https://registry.npmmirror.com/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.1.tgz", + "integrity": "sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-x64": { + "version": "2.5.1", + "resolved": "https://registry.npmmirror.com/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.1.tgz", + "integrity": "sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmmirror.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@pkgr/core": { + "version": "0.2.9", + "resolved": "https://registry.npmmirror.com/@pkgr/core/-/core-0.2.9.tgz", + "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/pkgr" + } + }, + "node_modules/@polka/url": { + "version": "1.0.0-next.29", + "resolved": "https://registry.npmmirror.com/@polka/url/-/url-1.0.0-next.29.tgz", + "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==", + "dev": true, + "license": "MIT" + }, + "node_modules/@popperjs/core": { + "name": "@sxzz/popperjs-es", + "version": "2.11.7", + "resolved": "https://registry.npmmirror.com/@sxzz/popperjs-es/-/popperjs-es-2.11.7.tgz", + "integrity": "sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-beta.32", + "resolved": "https://registry.npmmirror.com/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.32.tgz", + "integrity": "sha512-QReCdvxiUZAPkvp1xpAg62IeNzykOFA6syH2CnClif4YmALN1XKpB39XneL80008UbtMShthSVDKmrx05N1q/g==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/pluginutils": { + "version": "5.2.0", + "resolved": "https://registry.npmmirror.com/@rollup/pluginutils/-/pluginutils-5.2.0.tgz", + "integrity": "sha512-qWJ2ZTbmumwiLFomfzTyt5Kng4hwPi9rwCYN4SHb6eaRU1KNO4ccxINHr/VhH4GgPlt1XfSTLX2LBTme8ne4Zw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.46.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.46.2.tgz", + "integrity": "sha512-Zj3Hl6sN34xJtMv7Anwb5Gu01yujyE/cLBDB2gnHTAHaWS1Z38L7kuSG+oAh0giZMqG060f/YBStXtMH6FvPMA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.46.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.46.2.tgz", + "integrity": "sha512-nTeCWY83kN64oQ5MGz3CgtPx8NSOhC5lWtsjTs+8JAJNLcP3QbLCtDDgUKQc/Ro/frpMq4SHUaHN6AMltcEoLQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.46.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.46.2.tgz", + "integrity": "sha512-HV7bW2Fb/F5KPdM/9bApunQh68YVDU8sO8BvcW9OngQVN3HHHkw99wFupuUJfGR9pYLLAjcAOA6iO+evsbBaPQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.46.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.46.2.tgz", + "integrity": "sha512-SSj8TlYV5nJixSsm/y3QXfhspSiLYP11zpfwp6G/YDXctf3Xkdnk4woJIF5VQe0of2OjzTt8EsxnJDCdHd2xMA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.46.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.46.2.tgz", + "integrity": "sha512-ZyrsG4TIT9xnOlLsSSi9w/X29tCbK1yegE49RYm3tu3wF1L/B6LVMqnEWyDB26d9Ecx9zrmXCiPmIabVuLmNSg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.46.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.46.2.tgz", + "integrity": "sha512-pCgHFoOECwVCJ5GFq8+gR8SBKnMO+xe5UEqbemxBpCKYQddRQMgomv1104RnLSg7nNvgKy05sLsY51+OVRyiVw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.46.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.46.2.tgz", + "integrity": "sha512-EtP8aquZ0xQg0ETFcxUbU71MZlHaw9MChwrQzatiE8U/bvi5uv/oChExXC4mWhjiqK7azGJBqU0tt5H123SzVA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.46.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.46.2.tgz", + "integrity": "sha512-qO7F7U3u1nfxYRPM8HqFtLd+raev2K137dsV08q/LRKRLEc7RsiDWihUnrINdsWQxPR9jqZ8DIIZ1zJJAm5PjQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.46.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.46.2.tgz", + "integrity": "sha512-3dRaqLfcOXYsfvw5xMrxAk9Lb1f395gkoBYzSFcc/scgRFptRXL9DOaDpMiehf9CO8ZDRJW2z45b6fpU5nwjng==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.46.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.46.2.tgz", + "integrity": "sha512-fhHFTutA7SM+IrR6lIfiHskxmpmPTJUXpWIsBXpeEwNgZzZZSg/q4i6FU4J8qOGyJ0TR+wXBwx/L7Ho9z0+uDg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "version": "4.46.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.46.2.tgz", + "integrity": "sha512-i7wfGFXu8x4+FRqPymzjD+Hyav8l95UIZ773j7J7zRYc3Xsxy2wIn4x+llpunexXe6laaO72iEjeeGyUFmjKeA==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.46.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.46.2.tgz", + "integrity": "sha512-B/l0dFcHVUnqcGZWKcWBSV2PF01YUt0Rvlurci5P+neqY/yMKchGU8ullZvIv5e8Y1C6wOn+U03mrDylP5q9Yw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.46.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.46.2.tgz", + "integrity": "sha512-32k4ENb5ygtkMwPMucAb8MtV8olkPT03oiTxJbgkJa7lJ7dZMr0GCFJlyvy+K8iq7F/iuOr41ZdUHaOiqyR3iQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.46.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.46.2.tgz", + "integrity": "sha512-t5B2loThlFEauloaQkZg9gxV05BYeITLvLkWOkRXogP4qHXLkWSbSHKM9S6H1schf/0YGP/qNKtiISlxvfmmZw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.46.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.46.2.tgz", + "integrity": "sha512-YKjekwTEKgbB7n17gmODSmJVUIvj8CX7q5442/CK80L8nqOUbMtf8b01QkG3jOqyr1rotrAnW6B/qiHwfcuWQA==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.46.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.46.2.tgz", + "integrity": "sha512-Jj5a9RUoe5ra+MEyERkDKLwTXVu6s3aACP51nkfnK9wJTraCC8IMe3snOfALkrjTYd2G1ViE1hICj0fZ7ALBPA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.46.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.46.2.tgz", + "integrity": "sha512-7kX69DIrBeD7yNp4A5b81izs8BqoZkCIaxQaOpumcJ1S/kmqNFjPhDu1LHeVXv0SexfHQv5cqHsxLOjETuqDuA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.46.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.46.2.tgz", + "integrity": "sha512-wiJWMIpeaak/jsbaq2HMh/rzZxHVW1rU6coyeNNpMwk5isiPjSTx0a4YLSlYDwBH/WBvLz+EtsNqQScZTLJy3g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.46.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.46.2.tgz", + "integrity": "sha512-gBgaUDESVzMgWZhcyjfs9QFK16D8K6QZpwAaVNJxYDLHWayOta4ZMjGm/vsAEy3hvlS2GosVFlBlP9/Wb85DqQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.46.2", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.46.2.tgz", + "integrity": "sha512-CvUo2ixeIQGtF6WvuB87XWqPQkoFAFqW+HUo/WzHwuHDvIwZCtjdWXoYCcr06iKGydiqTclC4jU/TNObC/xKZg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rushstack/eslint-patch": { + "version": "1.12.0", + "resolved": "https://registry.npmmirror.com/@rushstack/eslint-patch/-/eslint-patch-1.12.0.tgz", + "integrity": "sha512-5EwMtOqvJMMa3HbmxLlF74e+3/HhwBTMcvt3nqVJgGCozO6hzIPOBlwm8mGVNR9SN2IJpxSnlxczyDjcn7qIyw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@sec-ant/readable-stream": { + "version": "0.4.1", + "resolved": "https://registry.npmmirror.com/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz", + "integrity": "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@sindresorhus/merge-streams": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz", + "integrity": "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@transloadit/prettier-bytes": { + "version": "0.0.7", + "resolved": "https://registry.npmmirror.com/@transloadit/prettier-bytes/-/prettier-bytes-0.0.7.tgz", + "integrity": "sha512-VeJbUb0wEKbcwaSlj5n+LscBl9IPgLPkHVGBkh00cztv6X4L/TJXK58LzFuBKX7/GAfiGhIwH67YTLTlzvIzBA==", + "license": "MIT" + }, + "node_modules/@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmmirror.com/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/@tsconfig/node20": { + "version": "20.1.6", + "resolved": "https://registry.npmmirror.com/@tsconfig/node20/-/node20-20.1.6.tgz", + "integrity": "sha512-sz+Hqx9zwZDpZIV871WSbUzSqNIsXzghZydypnfgzPKLltVJfkINfUeTct31n/tTSa9ZE1ZOfKdRre1uHHquYQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmmirror.com/@types/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha512-zx2/Gg0Eg7gwEiOIIh5w9TrhKKTeQh7CPCOPNc0el4pLSwzebA8SmnHwZs2dWlLONvyulykSwGSQxQHLhjGLvQ==", + "license": "MIT" + }, + "node_modules/@types/file-saver": { + "version": "2.0.7", + "resolved": "https://registry.npmmirror.com/@types/file-saver/-/file-saver-2.0.7.tgz", + "integrity": "sha512-dNKVfHd/jk0SkR/exKGj2ggkB45MAkzvWCaqLUUgkyjITkGNzH8H+yUwr+BLJUBjZOe9w8X3wgmXhZDRg1ED6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmmirror.com/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmmirror.com/@types/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-H3MHACvFUEiujabxhaI/ImO6gUrd8oOurg7LQtS7mbwIXA/cUqWrvBsaeJ23aZEPk1TAYkurjfMbSELfoCXlGA==", + "license": "MIT" + }, + "node_modules/@types/lodash-es": { + "version": "4.17.12", + "resolved": "https://registry.npmmirror.com/@types/lodash-es/-/lodash-es-4.17.12.tgz", + "integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==", + "license": "MIT", + "dependencies": { + "@types/lodash": "*" + } + }, + "node_modules/@types/mockjs": { + "version": "1.0.10", + "resolved": "https://registry.npmmirror.com/@types/mockjs/-/mockjs-1.0.10.tgz", + "integrity": "sha512-SXgrhajHG7boLv6oU93CcmdDm0HYRiceuz6b+7z+/2lCJPTWDv0V5YiwFHT2ejE4bQqgSXQiVPQYPWv7LGsK1g==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "20.19.11", + "resolved": "https://registry.npmmirror.com/@types/node/-/node-20.19.11.tgz", + "integrity": "sha512-uug3FEEGv0r+jrecvUUpbY8lLisvIjg6AAic6a2bSP5OEOLeJsDSnvhCDov7ipFFMXS3orMpzlmi0ZcuGkBbow==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/nprogress": { + "version": "0.2.3", + "resolved": "https://registry.npmmirror.com/@types/nprogress/-/nprogress-0.2.3.tgz", + "integrity": "sha512-k7kRA033QNtC+gLc4VPlfnue58CM1iQLgn1IMAU8VPHGOj7oIHPp9UlhedEnD/Gl8evoCjwkZjlBORtZ3JByUA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/store": { + "version": "2.0.5", + "resolved": "https://registry.npmmirror.com/@types/store/-/store-2.0.5.tgz", + "integrity": "sha512-5NmTKe3GWdOaykzq7no+Ahf6mafJu0oLc9JNhJ3E26+0oFvd6GnksnZQpMXcH526mfG4xDYjFiKzyDL51PzeWQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/web-bluetooth": { + "version": "0.0.21", + "resolved": "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz", + "integrity": "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==", + "license": "MIT" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.39.1", + "resolved": "https://registry.npmmirror.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.39.1.tgz", + "integrity": "sha512-yYegZ5n3Yr6eOcqgj2nJH8cH/ZZgF+l0YIdKILSDjYFRjgYQMgv/lRjV5Z7Up04b9VYUondt8EPMqg7kTWgJ2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.39.1", + "@typescript-eslint/type-utils": "8.39.1", + "@typescript-eslint/utils": "8.39.1", + "@typescript-eslint/visitor-keys": "8.39.1", + "graphemer": "^1.4.0", + "ignore": "^7.0.0", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.39.1", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmmirror.com/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.39.1", + "resolved": "https://registry.npmmirror.com/@typescript-eslint/parser/-/parser-8.39.1.tgz", + "integrity": "sha512-pUXGCuHnnKw6PyYq93lLRiZm3vjuslIy7tus1lIQTYVK9bL8XBgJnCWm8a0KcTtHC84Yya1Q6rtll+duSMj0dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.39.1", + "@typescript-eslint/types": "8.39.1", + "@typescript-eslint/typescript-estree": "8.39.1", + "@typescript-eslint/visitor-keys": "8.39.1", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.39.1", + "resolved": "https://registry.npmmirror.com/@typescript-eslint/project-service/-/project-service-8.39.1.tgz", + "integrity": "sha512-8fZxek3ONTwBu9ptw5nCKqZOSkXshZB7uAxuFF0J/wTMkKydjXCzqqga7MlFMpHi9DoG4BadhmTkITBcg8Aybw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.39.1", + "@typescript-eslint/types": "^8.39.1", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.39.1", + "resolved": "https://registry.npmmirror.com/@typescript-eslint/scope-manager/-/scope-manager-8.39.1.tgz", + "integrity": "sha512-RkBKGBrjgskFGWuyUGz/EtD8AF/GW49S21J8dvMzpJitOF1slLEbbHnNEtAHtnDAnx8qDEdRrULRnWVx27wGBw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.39.1", + "@typescript-eslint/visitor-keys": "8.39.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.39.1", + "resolved": "https://registry.npmmirror.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.39.1.tgz", + "integrity": "sha512-ePUPGVtTMR8XMU2Hee8kD0Pu4NDE1CN9Q1sxGSGd/mbOtGZDM7pnhXNJnzW63zk/q+Z54zVzj44HtwXln5CvHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.39.1", + "resolved": "https://registry.npmmirror.com/@typescript-eslint/type-utils/-/type-utils-8.39.1.tgz", + "integrity": "sha512-gu9/ahyatyAdQbKeHnhT4R+y3YLtqqHyvkfDxaBYk97EcbfChSJXyaJnIL3ygUv7OuZatePHmQvuH5ru0lnVeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.39.1", + "@typescript-eslint/typescript-estree": "8.39.1", + "@typescript-eslint/utils": "8.39.1", + "debug": "^4.3.4", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.39.1", + "resolved": "https://registry.npmmirror.com/@typescript-eslint/types/-/types-8.39.1.tgz", + "integrity": "sha512-7sPDKQQp+S11laqTrhHqeAbsCfMkwJMrV7oTDvtDds4mEofJYir414bYKUEb8YPUm9QL3U+8f6L6YExSoAGdQw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.39.1", + "resolved": "https://registry.npmmirror.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.39.1.tgz", + "integrity": "sha512-EKkpcPuIux48dddVDXyQBlKdeTPMmALqBUbEk38McWv0qVEZwOpVJBi7ugK5qVNgeuYjGNQxrrnoM/5+TI/BPw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.39.1", + "@typescript-eslint/tsconfig-utils": "8.39.1", + "@typescript-eslint/types": "8.39.1", + "@typescript-eslint/visitor-keys": "8.39.1", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.39.1", + "resolved": "https://registry.npmmirror.com/@typescript-eslint/utils/-/utils-8.39.1.tgz", + "integrity": "sha512-VF5tZ2XnUSTuiqZFXCZfZs1cgkdd3O/sSYmdo2EpSyDlC86UM/8YytTmKnehOW3TGAlivqTDT6bS87B/GQ/jyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.39.1", + "@typescript-eslint/types": "8.39.1", + "@typescript-eslint/typescript-estree": "8.39.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.39.1", + "resolved": "https://registry.npmmirror.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.39.1.tgz", + "integrity": "sha512-W8FQi6kEh2e8zVhQ0eeRnxdvIoOkAp/CPAahcNio6nO9dsIwb9b34z90KOlheoyuVf6LSOEdjlkxSkapNEc+4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.39.1", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@uppy/companion-client": { + "version": "2.2.2", + "resolved": "https://registry.npmmirror.com/@uppy/companion-client/-/companion-client-2.2.2.tgz", + "integrity": "sha512-5mTp2iq97/mYSisMaBtFRry6PTgZA6SIL7LePteOV5x0/DxKfrZW3DEiQERJmYpHzy7k8johpm2gHnEKto56Og==", + "license": "MIT", + "dependencies": { + "@uppy/utils": "^4.1.2", + "namespace-emitter": "^2.0.1" + } + }, + "node_modules/@uppy/core": { + "version": "2.3.4", + "resolved": "https://registry.npmmirror.com/@uppy/core/-/core-2.3.4.tgz", + "integrity": "sha512-iWAqppC8FD8mMVqewavCz+TNaet6HPXitmGXpGGREGrakZ4FeuWytVdrelydzTdXx6vVKkOmI2FLztGg73sENQ==", + "license": "MIT", + "dependencies": { + "@transloadit/prettier-bytes": "0.0.7", + "@uppy/store-default": "^2.1.1", + "@uppy/utils": "^4.1.3", + "lodash.throttle": "^4.1.1", + "mime-match": "^1.0.2", + "namespace-emitter": "^2.0.1", + "nanoid": "^3.1.25", + "preact": "^10.5.13" + } + }, + "node_modules/@uppy/store-default": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/@uppy/store-default/-/store-default-2.1.1.tgz", + "integrity": "sha512-xnpTxvot2SeAwGwbvmJ899ASk5tYXhmZzD/aCFsXePh/v8rNvR2pKlcQUH7cF/y4baUGq3FHO/daKCok/mpKqQ==", + "license": "MIT" + }, + "node_modules/@uppy/utils": { + "version": "4.1.3", + "resolved": "https://registry.npmmirror.com/@uppy/utils/-/utils-4.1.3.tgz", + "integrity": "sha512-nTuMvwWYobnJcytDO3t+D6IkVq/Qs4Xv3vyoEZ+Iaf8gegZP+rEyoaFT2CK5XLRMienPyqRqNbIfRuFaOWSIFw==", + "license": "MIT", + "dependencies": { + "lodash.throttle": "^4.1.1" + } + }, + "node_modules/@uppy/xhr-upload": { + "version": "2.1.3", + "resolved": "https://registry.npmmirror.com/@uppy/xhr-upload/-/xhr-upload-2.1.3.tgz", + "integrity": "sha512-YWOQ6myBVPs+mhNjfdWsQyMRWUlrDLMoaG7nvf/G6Y3GKZf8AyjFDjvvJ49XWQ+DaZOftGkHmF1uh/DBeGivJQ==", + "license": "MIT", + "dependencies": { + "@uppy/companion-client": "^2.2.2", + "@uppy/utils": "^4.1.2", + "nanoid": "^3.1.25" + }, + "peerDependencies": { + "@uppy/core": "^2.3.3" + } + }, + "node_modules/@vitejs/plugin-vue": { + "version": "5.2.4", + "resolved": "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz", + "integrity": "sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "vite": "^5.0.0 || ^6.0.0", + "vue": "^3.2.25" + } + }, + "node_modules/@vitejs/plugin-vue-jsx": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/@vitejs/plugin-vue-jsx/-/plugin-vue-jsx-4.2.0.tgz", + "integrity": "sha512-DSTrmrdLp+0LDNF77fqrKfx7X0ErRbOcUAgJL/HbSesqQwoUvUQ4uYQqaex+rovqgGcoPqVk+AwUh3v9CuiYIw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.27.1", + "@babel/plugin-transform-typescript": "^7.27.1", + "@rolldown/pluginutils": "^1.0.0-beta.9", + "@vue/babel-plugin-jsx": "^1.4.0" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "vite": "^5.0.0 || ^6.0.0", + "vue": "^3.0.0" + } + }, + "node_modules/@volar/language-core": { + "version": "2.4.15", + "resolved": "https://registry.npmmirror.com/@volar/language-core/-/language-core-2.4.15.tgz", + "integrity": "sha512-3VHw+QZU0ZG9IuQmzT68IyN4hZNd9GchGPhbD9+pa8CVv7rnoOZwo7T8weIbrRmihqy3ATpdfXFnqRrfPVK6CA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/source-map": "2.4.15" + } + }, + "node_modules/@volar/source-map": { + "version": "2.4.15", + "resolved": "https://registry.npmmirror.com/@volar/source-map/-/source-map-2.4.15.tgz", + "integrity": "sha512-CPbMWlUN6hVZJYGcU/GSoHu4EnCHiLaXI9n8c9la6RaI9W5JHX+NqG+GSQcB0JdC2FIBLdZJwGsfKyBB71VlTg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@volar/typescript": { + "version": "2.4.15", + "resolved": "https://registry.npmmirror.com/@volar/typescript/-/typescript-2.4.15.tgz", + "integrity": "sha512-2aZ8i0cqPGjXb4BhkMsPYDkkuc2ZQ6yOpqwAuNwUoncELqoy5fRgOQtLR9gB0g902iS0NAkvpIzs27geVyVdPg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/language-core": "2.4.15", + "path-browserify": "^1.0.1", + "vscode-uri": "^3.0.8" + } + }, + "node_modules/@vue/babel-helper-vue-transform-on": { + "version": "1.5.0", + "resolved": "https://registry.npmmirror.com/@vue/babel-helper-vue-transform-on/-/babel-helper-vue-transform-on-1.5.0.tgz", + "integrity": "sha512-0dAYkerNhhHutHZ34JtTl2czVQHUNWv6xEbkdF5W+Yrv5pCWsqjeORdOgbtW2I9gWlt+wBmVn+ttqN9ZxR5tzA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@vue/babel-plugin-jsx": { + "version": "1.5.0", + "resolved": "https://registry.npmmirror.com/@vue/babel-plugin-jsx/-/babel-plugin-jsx-1.5.0.tgz", + "integrity": "sha512-mneBhw1oOqCd2247O0Yw/mRwC9jIGACAJUlawkmMBiNmL4dGA2eMzuNZVNqOUfYTa6vqmND4CtOPzmEEEqLKFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/plugin-syntax-jsx": "^7.27.1", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.0", + "@babel/types": "^7.28.2", + "@vue/babel-helper-vue-transform-on": "1.5.0", + "@vue/babel-plugin-resolve-type": "1.5.0", + "@vue/shared": "^3.5.18" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + } + } + }, + "node_modules/@vue/babel-plugin-resolve-type": { + "version": "1.5.0", + "resolved": "https://registry.npmmirror.com/@vue/babel-plugin-resolve-type/-/babel-plugin-resolve-type-1.5.0.tgz", + "integrity": "sha512-Wm/60o+53JwJODm4Knz47dxJnLDJ9FnKnGZJbUUf8nQRAtt6P+undLUAVU3Ha33LxOJe6IPoifRQ6F/0RrU31w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/parser": "^7.28.0", + "@vue/compiler-sfc": "^3.5.18" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.5.18", + "resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.5.18.tgz", + "integrity": "sha512-3slwjQrrV1TO8MoXgy3aynDQ7lslj5UqDxuHnrzHtpON5CBinhWjJETciPngpin/T3OuW3tXUf86tEurusnztw==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.0", + "@vue/shared": "3.5.18", + "entities": "^4.5.0", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.5.18", + "resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.5.18.tgz", + "integrity": "sha512-RMbU6NTU70++B1JyVJbNbeFkK+A+Q7y9XKE2EM4NLGm2WFR8x9MbAtWxPPLdm0wUkuZv9trpwfSlL6tjdIa1+A==", + "license": "MIT", + "dependencies": { + "@vue/compiler-core": "3.5.18", + "@vue/shared": "3.5.18" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.5.18", + "resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.5.18.tgz", + "integrity": "sha512-5aBjvGqsWs+MoxswZPoTB9nSDb3dhd1x30xrrltKujlCxo48j8HGDNj3QPhF4VIS0VQDUrA1xUfp2hEa+FNyXA==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.0", + "@vue/compiler-core": "3.5.18", + "@vue/compiler-dom": "3.5.18", + "@vue/compiler-ssr": "3.5.18", + "@vue/shared": "3.5.18", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.17", + "postcss": "^8.5.6", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.5.18", + "resolved": "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.5.18.tgz", + "integrity": "sha512-xM16Ak7rSWHkM3m22NlmcdIM+K4BMyFARAfV9hYFl+SFuRzrZ3uGMNW05kA5pmeMa0X9X963Kgou7ufdbpOP9g==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.18", + "@vue/shared": "3.5.18" + } + }, + "node_modules/@vue/compiler-vue2": { + "version": "2.7.16", + "resolved": "https://registry.npmmirror.com/@vue/compiler-vue2/-/compiler-vue2-2.7.16.tgz", + "integrity": "sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==", + "dev": true, + "license": "MIT", + "dependencies": { + "de-indent": "^1.0.2", + "he": "^1.2.0" + } + }, + "node_modules/@vue/devtools-api": { + "version": "6.6.4", + "resolved": "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-6.6.4.tgz", + "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==", + "license": "MIT" + }, + "node_modules/@vue/devtools-core": { + "version": "7.7.7", + "resolved": "https://registry.npmmirror.com/@vue/devtools-core/-/devtools-core-7.7.7.tgz", + "integrity": "sha512-9z9TLbfC+AjAi1PQyWX+OErjIaJmdFlbDHcD+cAMYKY6Bh5VlsAtCeGyRMrXwIlMEQPukvnWt3gZBLwTAIMKzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/devtools-kit": "^7.7.7", + "@vue/devtools-shared": "^7.7.7", + "mitt": "^3.0.1", + "nanoid": "^5.1.0", + "pathe": "^2.0.3", + "vite-hot-client": "^2.0.4" + }, + "peerDependencies": { + "vue": "^3.0.0" + } + }, + "node_modules/@vue/devtools-core/node_modules/nanoid": { + "version": "5.1.5", + "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-5.1.5.tgz", + "integrity": "sha512-Ir/+ZpE9fDsNH0hQ3C68uyThDXzYcim2EqcZ8zn8Chtt1iylPT9xXJB0kPCnqzgcEGikO9RxSrh63MsmVCU7Fw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.js" + }, + "engines": { + "node": "^18 || >=20" + } + }, + "node_modules/@vue/devtools-core/node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmmirror.com/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@vue/devtools-kit": { + "version": "7.7.7", + "resolved": "https://registry.npmmirror.com/@vue/devtools-kit/-/devtools-kit-7.7.7.tgz", + "integrity": "sha512-wgoZtxcTta65cnZ1Q6MbAfePVFxfM+gq0saaeytoph7nEa7yMXoi6sCPy4ufO111B9msnw0VOWjPEFCXuAKRHA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/devtools-shared": "^7.7.7", + "birpc": "^2.3.0", + "hookable": "^5.5.3", + "mitt": "^3.0.1", + "perfect-debounce": "^1.0.0", + "speakingurl": "^14.0.1", + "superjson": "^2.2.2" + } + }, + "node_modules/@vue/devtools-shared": { + "version": "7.7.7", + "resolved": "https://registry.npmmirror.com/@vue/devtools-shared/-/devtools-shared-7.7.7.tgz", + "integrity": "sha512-+udSj47aRl5aKb0memBvcUG9koarqnxNM5yjuREvqwK6T3ap4mn3Zqqc17QrBFTqSMjr3HK1cvStEZpMDpfdyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "rfdc": "^1.4.1" + } + }, + "node_modules/@vue/eslint-config-prettier": { + "version": "10.2.0", + "resolved": "https://registry.npmmirror.com/@vue/eslint-config-prettier/-/eslint-config-prettier-10.2.0.tgz", + "integrity": "sha512-GL3YBLwv/+b86yHcNNfPJxOTtVFJ4Mbc9UU3zR+KVoG7SwGTjPT+32fXamscNumElhcpXW3mT0DgzS9w32S7Bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-config-prettier": "^10.0.1", + "eslint-plugin-prettier": "^5.2.2" + }, + "peerDependencies": { + "eslint": ">= 8.21.0", + "prettier": ">= 3.0.0" + } + }, + "node_modules/@vue/eslint-config-typescript": { + "version": "14.6.0", + "resolved": "https://registry.npmmirror.com/@vue/eslint-config-typescript/-/eslint-config-typescript-14.6.0.tgz", + "integrity": "sha512-UpiRY/7go4Yps4mYCjkvlIbVWmn9YvPGQDxTAlcKLphyaD77LjIu3plH4Y9zNT0GB4f3K5tMmhhtRhPOgrQ/bQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/utils": "^8.35.1", + "fast-glob": "^3.3.3", + "typescript-eslint": "^8.35.1", + "vue-eslint-parser": "^10.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "peerDependencies": { + "eslint": "^9.10.0", + "eslint-plugin-vue": "^9.28.0 || ^10.0.0", + "typescript": ">=4.8.4" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@vue/language-core": { + "version": "2.2.12", + "resolved": "https://registry.npmmirror.com/@vue/language-core/-/language-core-2.2.12.tgz", + "integrity": "sha512-IsGljWbKGU1MZpBPN+BvPAdr55YPkj2nB/TBNGNC32Vy2qLG25DYu/NBN2vNtZqdRbTRjaoYrahLrToim2NanA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/language-core": "2.4.15", + "@vue/compiler-dom": "^3.5.0", + "@vue/compiler-vue2": "^2.7.16", + "@vue/shared": "^3.5.0", + "alien-signals": "^1.0.3", + "minimatch": "^9.0.3", + "muggle-string": "^0.4.1", + "path-browserify": "^1.0.1" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@vue/reactivity": { + "version": "3.5.18", + "resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.5.18.tgz", + "integrity": "sha512-x0vPO5Imw+3sChLM5Y+B6G1zPjwdOri9e8V21NnTnlEvkxatHEH5B5KEAJcjuzQ7BsjGrKtfzuQ5eQwXh8HXBg==", + "license": "MIT", + "dependencies": { + "@vue/shared": "3.5.18" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.5.18", + "resolved": "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.5.18.tgz", + "integrity": "sha512-DUpHa1HpeOQEt6+3nheUfqVXRog2kivkXHUhoqJiKR33SO4x+a5uNOMkV487WPerQkL0vUuRvq/7JhRgLW3S+w==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.18", + "@vue/shared": "3.5.18" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.5.18", + "resolved": "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.5.18.tgz", + "integrity": "sha512-YwDj71iV05j4RnzZnZtGaXwPoUWeRsqinblgVJwR8XTXYZ9D5PbahHQgsbmzUvCWNF6x7siQ89HgnX5eWkr3mw==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.18", + "@vue/runtime-core": "3.5.18", + "@vue/shared": "3.5.18", + "csstype": "^3.1.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.5.18", + "resolved": "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.5.18.tgz", + "integrity": "sha512-PvIHLUoWgSbDG7zLHqSqaCoZvHi6NNmfVFOqO+OnwvqMz/tqQr3FuGWS8ufluNddk7ZLBJYMrjcw1c6XzR12mA==", + "license": "MIT", + "dependencies": { + "@vue/compiler-ssr": "3.5.18", + "@vue/shared": "3.5.18" + }, + "peerDependencies": { + "vue": "3.5.18" + } + }, + "node_modules/@vue/shared": { + "version": "3.5.18", + "resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.5.18.tgz", + "integrity": "sha512-cZy8Dq+uuIXbxCZpuLd2GJdeSO/lIzIspC2WtkqIpje5QyFbvLaI5wZtdUjLHjGZrlVX6GilejatWwVYYRc8tA==", + "license": "MIT" + }, + "node_modules/@vue/test-utils": { + "version": "2.4.6", + "resolved": "https://registry.npmmirror.com/@vue/test-utils/-/test-utils-2.4.6.tgz", + "integrity": "sha512-FMxEjOpYNYiFe0GkaHsnJPXFHxQ6m4t8vI/ElPGpMWxZKpmRvQ33OIrvRXemy6yha03RxhOlQuy+gZMC3CQSow==", + "dev": true, + "license": "MIT", + "dependencies": { + "js-beautify": "^1.14.9", + "vue-component-type-helpers": "^2.0.0" + } + }, + "node_modules/@vue/tsconfig": { + "version": "0.5.1", + "resolved": "https://registry.npmmirror.com/@vue/tsconfig/-/tsconfig-0.5.1.tgz", + "integrity": "sha512-VcZK7MvpjuTPx2w6blwnwZAu5/LgBUtejFOi3pPGQFXQN5Ela03FUtd2Qtg4yWGGissVL0dr6Ro1LfOFh+PCuQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@vueuse/core": { + "version": "12.8.2", + "resolved": "https://registry.npmmirror.com/@vueuse/core/-/core-12.8.2.tgz", + "integrity": "sha512-HbvCmZdzAu3VGi/pWYm5Ut+Kd9mn1ZHnn4L5G8kOQTPs/IwIAmJoBrmYk2ckLArgMXZj0AW3n5CAejLUO+PhdQ==", + "license": "MIT", + "dependencies": { + "@types/web-bluetooth": "^0.0.21", + "@vueuse/metadata": "12.8.2", + "@vueuse/shared": "12.8.2", + "vue": "^3.5.13" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/metadata": { + "version": "12.8.2", + "resolved": "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-12.8.2.tgz", + "integrity": "sha512-rAyLGEuoBJ/Il5AmFHiziCPdQzRt88VxR+Y/A/QhJ1EWtWqPBBAxTAFaSkviwEuOEZNtW8pvkPgoCZQ+HxqW1A==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/shared": { + "version": "12.8.2", + "resolved": "https://registry.npmmirror.com/@vueuse/shared/-/shared-12.8.2.tgz", + "integrity": "sha512-dznP38YzxZoNloI0qpEfpkms8knDtaoQ6Y/sfS0L7Yki4zh40LFHEhur0odJC6xTHG5dxWVPiUWBXn+wCG2s5w==", + "license": "MIT", + "dependencies": { + "vue": "^3.5.13" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@wangeditor/basic-modules": { + "version": "1.1.7", + "resolved": "https://registry.npmmirror.com/@wangeditor/basic-modules/-/basic-modules-1.1.7.tgz", + "integrity": "sha512-cY9CPkLJaqF05STqfpZKWG4LpxTMeGSIIF1fHvfm/mz+JXatCagjdkbxdikOuKYlxDdeqvOeBmsUBItufDLXZg==", + "license": "MIT", + "dependencies": { + "is-url": "^1.2.4" + }, + "peerDependencies": { + "@wangeditor/core": "1.x", + "dom7": "^3.0.0", + "lodash.throttle": "^4.1.1", + "nanoid": "^3.2.0", + "slate": "^0.72.0", + "snabbdom": "^3.1.0" + } + }, + "node_modules/@wangeditor/code-highlight": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/@wangeditor/code-highlight/-/code-highlight-1.0.3.tgz", + "integrity": "sha512-iazHwO14XpCuIWJNTQTikqUhGKyqj+dUNWJ9288Oym9M2xMVHvnsOmDU2sgUDWVy+pOLojReMPgXCsvvNlOOhw==", + "license": "MIT", + "dependencies": { + "prismjs": "^1.23.0" + }, + "peerDependencies": { + "@wangeditor/core": "1.x", + "dom7": "^3.0.0", + "slate": "^0.72.0", + "snabbdom": "^3.1.0" + } + }, + "node_modules/@wangeditor/core": { + "version": "1.1.19", + "resolved": "https://registry.npmmirror.com/@wangeditor/core/-/core-1.1.19.tgz", + "integrity": "sha512-KevkB47+7GhVszyYF2pKGKtCSj/YzmClsD03C3zTt+9SR2XWT5T0e3yQqg8baZpcMvkjs1D8Dv4fk8ok/UaS2Q==", + "license": "MIT", + "dependencies": { + "@types/event-emitter": "^0.3.3", + "event-emitter": "^0.3.5", + "html-void-elements": "^2.0.0", + "i18next": "^20.4.0", + "scroll-into-view-if-needed": "^2.2.28", + "slate-history": "^0.66.0" + }, + "peerDependencies": { + "@uppy/core": "^2.1.1", + "@uppy/xhr-upload": "^2.0.3", + "dom7": "^3.0.0", + "is-hotkey": "^0.2.0", + "lodash.camelcase": "^4.3.0", + "lodash.clonedeep": "^4.5.0", + "lodash.debounce": "^4.0.8", + "lodash.foreach": "^4.5.0", + "lodash.isequal": "^4.5.0", + "lodash.throttle": "^4.1.1", + "lodash.toarray": "^4.4.0", + "nanoid": "^3.2.0", + "slate": "^0.72.0", + "snabbdom": "^3.1.0" + } + }, + "node_modules/@wangeditor/editor": { + "version": "5.1.23", + "resolved": "https://registry.npmmirror.com/@wangeditor/editor/-/editor-5.1.23.tgz", + "integrity": "sha512-0RxfeVTuK1tktUaPROnCoFfaHVJpRAIE2zdS0mpP+vq1axVQpLjM8+fCvKzqYIkH0Pg+C+44hJpe3VVroSkEuQ==", + "license": "MIT", + "dependencies": { + "@uppy/core": "^2.1.1", + "@uppy/xhr-upload": "^2.0.3", + "@wangeditor/basic-modules": "^1.1.7", + "@wangeditor/code-highlight": "^1.0.3", + "@wangeditor/core": "^1.1.19", + "@wangeditor/list-module": "^1.0.5", + "@wangeditor/table-module": "^1.1.4", + "@wangeditor/upload-image-module": "^1.0.2", + "@wangeditor/video-module": "^1.1.4", + "dom7": "^3.0.0", + "is-hotkey": "^0.2.0", + "lodash.camelcase": "^4.3.0", + "lodash.clonedeep": "^4.5.0", + "lodash.debounce": "^4.0.8", + "lodash.foreach": "^4.5.0", + "lodash.isequal": "^4.5.0", + "lodash.throttle": "^4.1.1", + "lodash.toarray": "^4.4.0", + "nanoid": "^3.2.0", + "slate": "^0.72.0", + "snabbdom": "^3.1.0" + } + }, + "node_modules/@wangeditor/editor-for-vue": { + "version": "5.1.12", + "resolved": "https://registry.npmmirror.com/@wangeditor/editor-for-vue/-/editor-for-vue-5.1.12.tgz", + "integrity": "sha512-0Ds3D8I+xnpNWezAeO7HmPRgTfUxHLMd9JKcIw+QzvSmhC5xUHbpCcLU+KLmeBKTR/zffnS5GQo6qi3GhTMJWQ==", + "license": "MIT", + "peerDependencies": { + "@wangeditor/editor": ">=5.1.0", + "vue": "^3.0.5" + } + }, + "node_modules/@wangeditor/list-module": { + "version": "1.0.5", + "resolved": "https://registry.npmmirror.com/@wangeditor/list-module/-/list-module-1.0.5.tgz", + "integrity": "sha512-uDuYTP6DVhcYf7mF1pTlmNn5jOb4QtcVhYwSSAkyg09zqxI1qBqsfUnveeDeDqIuptSJhkh81cyxi+MF8sEPOQ==", + "license": "MIT", + "peerDependencies": { + "@wangeditor/core": "1.x", + "dom7": "^3.0.0", + "slate": "^0.72.0", + "snabbdom": "^3.1.0" + } + }, + "node_modules/@wangeditor/table-module": { + "version": "1.1.4", + "resolved": "https://registry.npmmirror.com/@wangeditor/table-module/-/table-module-1.1.4.tgz", + "integrity": "sha512-5saanU9xuEocxaemGdNi9t8MCDSucnykEC6jtuiT72kt+/Hhh4nERYx1J20OPsTCCdVr7hIyQenFD1iSRkIQ6w==", + "license": "MIT", + "peerDependencies": { + "@wangeditor/core": "1.x", + "dom7": "^3.0.0", + "lodash.isequal": "^4.5.0", + "lodash.throttle": "^4.1.1", + "nanoid": "^3.2.0", + "slate": "^0.72.0", + "snabbdom": "^3.1.0" + } + }, + "node_modules/@wangeditor/upload-image-module": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/@wangeditor/upload-image-module/-/upload-image-module-1.0.2.tgz", + "integrity": "sha512-z81lk/v71OwPDYeQDxj6cVr81aDP90aFuywb8nPD6eQeECtOymrqRODjpO6VGvCVxVck8nUxBHtbxKtjgcwyiA==", + "license": "MIT", + "peerDependencies": { + "@uppy/core": "^2.0.3", + "@uppy/xhr-upload": "^2.0.3", + "@wangeditor/basic-modules": "1.x", + "@wangeditor/core": "1.x", + "dom7": "^3.0.0", + "lodash.foreach": "^4.5.0", + "slate": "^0.72.0", + "snabbdom": "^3.1.0" + } + }, + "node_modules/@wangeditor/video-module": { + "version": "1.1.4", + "resolved": "https://registry.npmmirror.com/@wangeditor/video-module/-/video-module-1.1.4.tgz", + "integrity": "sha512-ZdodDPqKQrgx3IwWu4ZiQmXI8EXZ3hm2/fM6E3t5dB8tCaIGWQZhmqd6P5knfkRAd3z2+YRSRbxOGfoRSp/rLg==", + "license": "MIT", + "peerDependencies": { + "@uppy/core": "^2.1.4", + "@uppy/xhr-upload": "^2.0.7", + "@wangeditor/core": "1.x", + "dom7": "^3.0.0", + "nanoid": "^3.2.0", + "slate": "^0.72.0", + "snabbdom": "^3.1.0" + } + }, + "node_modules/abbrev": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/abbrev/-/abbrev-2.0.0.tgz", + "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmmirror.com/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmmirror.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/adler-32": { + "version": "1.3.1", + "resolved": "https://registry.npmmirror.com/adler-32/-/adler-32-1.3.1.tgz", + "integrity": "sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmmirror.com/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/alien-signals": { + "version": "1.0.13", + "resolved": "https://registry.npmmirror.com/alien-signals/-/alien-signals-1.0.13.tgz", + "integrity": "sha512-OGj9yyTnJEttvzhTUWuscOvtqxq5vrhF7vL9oS0xJ2mK0ItPYP1/y+vCFebfxoEyAz0++1AIwJ5CMr+Fk3nDmg==", + "dev": true, + "license": "MIT" + }, + "node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmmirror.com/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true, + "license": "MIT" + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmmirror.com/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/anymatch/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmmirror.com/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true, + "license": "MIT" + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/async-validator": { + "version": "4.2.5", + "resolved": "https://registry.npmmirror.com/async-validator/-/async-validator-4.2.5.tgz", + "integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==", + "license": "MIT" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/autoprefixer": { + "version": "10.4.21", + "resolved": "https://registry.npmmirror.com/autoprefixer/-/autoprefixer-10.4.21.tgz", + "integrity": "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "browserslist": "^4.24.4", + "caniuse-lite": "^1.0.30001702", + "fraction.js": "^4.3.7", + "normalize-range": "^0.1.2", + "picocolors": "^1.1.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/axios": { + "version": "1.11.0", + "resolved": "https://registry.npmmirror.com/axios/-/axios-1.11.0.tgz", + "integrity": "sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.4", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/birpc": { + "version": "2.5.0", + "resolved": "https://registry.npmmirror.com/birpc/-/birpc-2.5.0.tgz", + "integrity": "sha512-VSWO/W6nNQdyP520F1mhf+Lc2f8pjGQOtoHHm7Ze8Go1kX7akpVIrtTa0fn+HB0QJEDVacl6aO08YE0PgXfdnQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true, + "license": "ISC" + }, + "node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.25.2", + "resolved": "https://registry.npmmirror.com/browserslist/-/browserslist-4.25.2.tgz", + "integrity": "sha512-0si2SJK3ooGzIawRu61ZdPCO1IncZwS8IzuX73sPZsXW6EQ/w/DAfPyKI8l1ETTCr2MnvqWitmlCUxgdul45jA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "caniuse-lite": "^1.0.30001733", + "electron-to-chromium": "^1.5.199", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/bundle-name": { + "version": "4.1.0", + "resolved": "https://registry.npmmirror.com/bundle-name/-/bundle-name-4.1.0.tgz", + "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "run-applescript": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001735", + "resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001735.tgz", + "integrity": "sha512-EV/laoX7Wq2J9TQlyIXRxTJqIw4sxfXS4OYgudGxBYRuTv0q7AM6yMEpU/Vo1I94thg9U6EZ2NfZx9GJq83u7w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/cfb": { + "version": "1.2.2", + "resolved": "https://registry.npmmirror.com/cfb/-/cfb-1.2.2.tgz", + "integrity": "sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==", + "license": "Apache-2.0", + "dependencies": { + "adler-32": "~1.3.0", + "crc-32": "~1.2.0" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chardet": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/chardet/-/chardet-2.1.0.tgz", + "integrity": "sha512-bNFETTG/pM5ryzQ9Ad0lJOTa6HWD/YsScAR3EnCPZRPlQh77JocYktSHOUHelyhm8IARL+o4c4F1bP5KVOjiRA==", + "license": "MIT" + }, + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmmirror.com/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/codepage": { + "version": "1.15.0", + "resolved": "https://registry.npmmirror.com/codepage/-/codepage-1.15.0.tgz", + "integrity": "sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmmirror.com/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/compute-scroll-into-view": { + "version": "1.0.20", + "resolved": "https://registry.npmmirror.com/compute-scroll-into-view/-/compute-scroll-into-view-1.0.20.tgz", + "integrity": "sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg==", + "license": "MIT" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmmirror.com/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/confbox": { + "version": "0.1.8", + "resolved": "https://registry.npmmirror.com/confbox/-/confbox-0.1.8.tgz", + "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/config-chain": { + "version": "1.1.13", + "resolved": "https://registry.npmmirror.com/config-chain/-/config-chain-1.1.13.tgz", + "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/copy-anything": { + "version": "3.0.5", + "resolved": "https://registry.npmmirror.com/copy-anything/-/copy-anything-3.0.5.tgz", + "integrity": "sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-what": "^4.1.8" + }, + "engines": { + "node": ">=12.13" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/core-js": { + "version": "3.45.0", + "resolved": "https://registry.npmmirror.com/core-js/-/core-js-3.45.0.tgz", + "integrity": "sha512-c2KZL9lP4DjkN3hk/an4pWn5b5ZefhRJnAc42n6LJ19kSnbeRbdQZE5dSeE2LBol1OwJD3X1BQvFTAsa8ReeDA==", + "hasInstallScript": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/crc-32": { + "version": "1.2.2", + "resolved": "https://registry.npmmirror.com/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "license": "Apache-2.0", + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-select": { + "version": "5.2.2", + "resolved": "https://registry.npmmirror.com/css-select/-/css-select-5.2.2.tgz", + "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-tree": { + "version": "2.3.1", + "resolved": "https://registry.npmmirror.com/css-tree/-/css-tree-2.3.1.tgz", + "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mdn-data": "2.0.30", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/css-what": { + "version": "6.2.2", + "resolved": "https://registry.npmmirror.com/css-what/-/css-what-6.2.2.tgz", + "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csso": { + "version": "5.0.5", + "resolved": "https://registry.npmmirror.com/csso/-/csso-5.0.5.tgz", + "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "css-tree": "~2.2.0" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/css-tree": { + "version": "2.2.1", + "resolved": "https://registry.npmmirror.com/css-tree/-/css-tree-2.2.1.tgz", + "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", + "dev": true, + "license": "MIT", + "dependencies": { + "mdn-data": "2.0.28", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/mdn-data": { + "version": "2.0.28", + "resolved": "https://registry.npmmirror.com/mdn-data/-/mdn-data-2.0.28.tgz", + "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmmirror.com/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "license": "MIT" + }, + "node_modules/d": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/d/-/d-1.0.2.tgz", + "integrity": "sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==", + "license": "ISC", + "dependencies": { + "es5-ext": "^0.10.64", + "type": "^2.7.2" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/dayjs": { + "version": "1.11.13", + "resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.13.tgz", + "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==", + "license": "MIT" + }, + "node_modules/de-indent": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/de-indent/-/de-indent-1.0.2.tgz", + "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==", + "dev": true, + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmmirror.com/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmmirror.com/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/default-browser": { + "version": "5.2.1", + "resolved": "https://registry.npmmirror.com/default-browser/-/default-browser-5.2.1.tgz", + "integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==", + "dev": true, + "license": "MIT", + "dependencies": { + "bundle-name": "^4.1.0", + "default-browser-id": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser-id": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/default-browser-id/-/default-browser-id-5.0.0.tgz", + "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", + "dev": true, + "license": "Apache-2.0", + "optional": true, + "bin": { + "detect-libc": "bin/detect-libc.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmmirror.com/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmmirror.com/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true, + "license": "MIT" + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dev": true, + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/dom7": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/dom7/-/dom7-3.0.0.tgz", + "integrity": "sha512-oNlcUdHsC4zb7Msx7JN3K0Nro1dzJ48knvBOnDPKJ2GV9wl1i5vydJZUSyOfrkKFDZEud/jBsTk92S/VGSAe/g==", + "license": "MIT", + "dependencies": { + "ssr-window": "^3.0.0-alpha.1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmmirror.com/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.2.2", + "resolved": "https://registry.npmmirror.com/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmmirror.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" + }, + "node_modules/echarts": { + "version": "5.6.0", + "resolved": "https://registry.npmmirror.com/echarts/-/echarts-5.6.0.tgz", + "integrity": "sha512-oTbVTsXfKuEhxftHqL5xprgLoc0k7uScAwtryCgWF6hPYFLRwOUHiFmHGCBKP5NPFNkDVopOieyUqYGH8Fa3kA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "2.3.0", + "zrender": "5.6.1" + } + }, + "node_modules/editorconfig": { + "version": "1.0.4", + "resolved": "https://registry.npmmirror.com/editorconfig/-/editorconfig-1.0.4.tgz", + "integrity": "sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@one-ini/wasm": "0.1.1", + "commander": "^10.0.0", + "minimatch": "9.0.1", + "semver": "^7.5.3" + }, + "bin": { + "editorconfig": "bin/editorconfig" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/editorconfig/node_modules/minimatch": { + "version": "9.0.1", + "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-9.0.1.tgz", + "integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.202", + "resolved": "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.5.202.tgz", + "integrity": "sha512-NxbYjRmiHcHXV1Ws3fWUW+SLb62isauajk45LUJ/HgIOkUA7jLZu/X2Iif+X9FBNK8QkF9Zb4Q2mcwXCcY30mg==", + "dev": true, + "license": "ISC" + }, + "node_modules/element-plus": { + "version": "2.10.2", + "resolved": "https://registry.npmmirror.com/element-plus/-/element-plus-2.10.2.tgz", + "integrity": "sha512-p2KiAa0jEGXrzdlTAfpiS7HQFAhla4gvx6H7RuDf+OO0uC3DGpolxvdHjFR8gt7+vaWyxQNcHa1sAdBkmjqlgA==", + "license": "MIT", + "dependencies": { + "@ctrl/tinycolor": "^3.4.1", + "@element-plus/icons-vue": "^2.3.1", + "@floating-ui/dom": "^1.0.1", + "@popperjs/core": "npm:@sxzz/popperjs-es@^2.11.7", + "@types/lodash": "^4.14.182", + "@types/lodash-es": "^4.17.6", + "@vueuse/core": "^9.1.0", + "async-validator": "^4.2.5", + "dayjs": "^1.11.13", + "escape-html": "^1.0.3", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", + "lodash-unified": "^1.0.2", + "memoize-one": "^6.0.0", + "normalize-wheel-es": "^1.2.0" + }, + "peerDependencies": { + "vue": "^3.2.0" + } + }, + "node_modules/element-plus/node_modules/@types/web-bluetooth": { + "version": "0.0.16", + "resolved": "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz", + "integrity": "sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==", + "license": "MIT" + }, + "node_modules/element-plus/node_modules/@vueuse/core": { + "version": "9.13.0", + "resolved": "https://registry.npmmirror.com/@vueuse/core/-/core-9.13.0.tgz", + "integrity": "sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==", + "license": "MIT", + "dependencies": { + "@types/web-bluetooth": "^0.0.16", + "@vueuse/metadata": "9.13.0", + "@vueuse/shared": "9.13.0", + "vue-demi": "*" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/element-plus/node_modules/@vueuse/metadata": { + "version": "9.13.0", + "resolved": "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-9.13.0.tgz", + "integrity": "sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/element-plus/node_modules/@vueuse/shared": { + "version": "9.13.0", + "resolved": "https://registry.npmmirror.com/@vueuse/shared/-/shared-9.13.0.tgz", + "integrity": "sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==", + "license": "MIT", + "dependencies": { + "vue-demi": "*" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmmirror.com/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/error-stack-parser-es": { + "version": "0.1.5", + "resolved": "https://registry.npmmirror.com/error-stack-parser-es/-/error-stack-parser-es-0.1.5.tgz", + "integrity": "sha512-xHku1X40RO+fO8yJ8Wh2f2rZWVjqyhb1zgq1yZ8aZRQkv6OOKhKWRUaht3eSCUbAOBaKIgM+ykwFLE+QUxgGeg==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmmirror.com/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es5-ext": { + "version": "0.10.64", + "resolved": "https://registry.npmmirror.com/es5-ext/-/es5-ext-0.10.64.tgz", + "integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==", + "hasInstallScript": true, + "license": "ISC", + "dependencies": { + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.3", + "esniff": "^2.0.1", + "next-tick": "^1.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmmirror.com/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", + "license": "MIT", + "dependencies": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/es6-symbol": { + "version": "3.1.4", + "resolved": "https://registry.npmmirror.com/es6-symbol/-/es6-symbol-3.1.4.tgz", + "integrity": "sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==", + "license": "ISC", + "dependencies": { + "d": "^1.0.2", + "ext": "^1.7.0" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmmirror.com/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/eslint": { + "version": "9.33.0", + "resolved": "https://registry.npmmirror.com/eslint/-/eslint-9.33.0.tgz", + "integrity": "sha512-TS9bTNIryDzStCpJN93aC5VRSW3uTx9sClUn4B87pwiCaJh220otoI0X8mJKr+VcPtniMdN8GKjlwgWGUv5ZKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.0", + "@eslint/config-helpers": "^0.3.1", + "@eslint/core": "^0.15.2", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.33.0", + "@eslint/plugin-kit": "^0.3.5", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-config-prettier": { + "version": "10.1.8", + "resolved": "https://registry.npmmirror.com/eslint-config-prettier/-/eslint-config-prettier-10.1.8.tgz", + "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", + "dev": true, + "license": "MIT", + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "funding": { + "url": "https://opencollective.com/eslint-config-prettier" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "5.5.4", + "resolved": "https://registry.npmmirror.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.4.tgz", + "integrity": "sha512-swNtI95SToIz05YINMA6Ox5R057IMAmWZ26GqPxusAp1TZzj+IdY9tXNWWD3vkF/wEqydCONcwjTFpxybBqZsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.11.7" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-plugin-prettier" + }, + "peerDependencies": { + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-vue": { + "version": "9.33.0", + "resolved": "https://registry.npmmirror.com/eslint-plugin-vue/-/eslint-plugin-vue-9.33.0.tgz", + "integrity": "sha512-174lJKuNsuDIlLpjeXc5E2Tss8P44uIimAfGD0b90k0NoirJqpG7stLuU9Vp/9ioTOrQdWVREc4mRd1BD+CvGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "globals": "^13.24.0", + "natural-compare": "^1.4.0", + "nth-check": "^2.1.1", + "postcss-selector-parser": "^6.0.15", + "semver": "^7.6.3", + "vue-eslint-parser": "^9.4.3", + "xml-name-validator": "^4.0.0" + }, + "engines": { + "node": "^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0 || ^9.0.0" + } + }, + "node_modules/eslint-plugin-vue/node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmmirror.com/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-plugin-vue/node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmmirror.com/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-plugin-vue/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmmirror.com/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-plugin-vue/node_modules/vue-eslint-parser": { + "version": "9.4.3", + "resolved": "https://registry.npmmirror.com/vue-eslint-parser/-/vue-eslint-parser-9.4.3.tgz", + "integrity": "sha512-2rYRLWlIpaiN8xbPiDyXZXRgLGOtWxERV7ND5fFAv5qo1D2N9Fu9MNajBNc6o13lZ+24DAWCkQCvj4klgmcITg==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.4", + "eslint-scope": "^7.1.1", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.3.1", + "esquery": "^1.4.0", + "lodash": "^4.17.21", + "semver": "^7.3.6" + }, + "engines": { + "node": "^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=6.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmmirror.com/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/esniff": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/esniff/-/esniff-2.0.1.tgz", + "integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==", + "license": "ISC", + "dependencies": { + "d": "^1.0.1", + "es5-ext": "^0.10.62", + "event-emitter": "^0.3.5", + "type": "^2.7.2" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmmirror.com/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmmirror.com/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmmirror.com/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "license": "MIT" + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmmirror.com/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmmirror.com/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", + "license": "MIT", + "dependencies": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, + "node_modules/execa": { + "version": "9.6.0", + "resolved": "https://registry.npmmirror.com/execa/-/execa-9.6.0.tgz", + "integrity": "sha512-jpWzZ1ZhwUmeWRhS7Qv3mhpOhLfwI+uAX4e5fOcXqwMR7EcJ0pj2kV1CVzHVMX/LphnKWD3LObjZCoJ71lKpHw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/merge-streams": "^4.0.0", + "cross-spawn": "^7.0.6", + "figures": "^6.1.0", + "get-stream": "^9.0.0", + "human-signals": "^8.0.1", + "is-plain-obj": "^4.1.0", + "is-stream": "^4.0.1", + "npm-run-path": "^6.0.0", + "pretty-ms": "^9.2.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^4.0.0", + "yoctocolors": "^2.1.1" + }, + "engines": { + "node": "^18.19.0 || >=20.5.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/ext": { + "version": "1.7.0", + "resolved": "https://registry.npmmirror.com/ext/-/ext-1.7.0.tgz", + "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", + "license": "ISC", + "dependencies": { + "type": "^2.7.2" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmmirror.com/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmmirror.com/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmmirror.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmmirror.com/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/figures": { + "version": "6.1.0", + "resolved": "https://registry.npmmirror.com/figures/-/figures-6.1.0.tgz", + "integrity": "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-unicode-supported": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmmirror.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/file-saver": { + "version": "2.0.5", + "resolved": "https://registry.npmmirror.com/file-saver/-/file-saver-2.0.5.tgz", + "integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==", + "license": "MIT" + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmmirror.com/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmmirror.com/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" + }, + "node_modules/follow-redirects": { + "version": "1.15.11", + "resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmmirror.com/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/form-data": { + "version": "4.0.4", + "resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/frac": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/frac/-/frac-1.1.2.tgz", + "integrity": "sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/fraction.js": { + "version": "4.3.7", + "resolved": "https://registry.npmmirror.com/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmmirror.com/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmmirror.com/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmmirror.com/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stream": { + "version": "9.0.1", + "resolved": "https://registry.npmmirror.com/get-stream/-/get-stream-9.0.1.tgz", + "integrity": "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sec-ant/readable-stream": "^0.4.1", + "is-stream": "^4.0.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmmirror.com/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmmirror.com/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmmirror.com/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "license": "MIT", + "bin": { + "he": "bin/he" + } + }, + "node_modules/hookable": { + "version": "5.5.3", + "resolved": "https://registry.npmmirror.com/hookable/-/hookable-5.5.3.tgz", + "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/html-void-elements": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/html-void-elements/-/html-void-elements-2.0.1.tgz", + "integrity": "sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/human-signals": { + "version": "8.0.1", + "resolved": "https://registry.npmmirror.com/human-signals/-/human-signals-8.0.1.tgz", + "integrity": "sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/i18next": { + "version": "20.6.1", + "resolved": "https://registry.npmmirror.com/i18next/-/i18next-20.6.1.tgz", + "integrity": "sha512-yCMYTMEJ9ihCwEQQ3phLo7I/Pwycf8uAx+sRHwwk5U9Aui/IZYgQRyMqXafQOw5QQ7DM1Z+WyEXWIqSuJHhG2A==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.0" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmmirror.com/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/immer": { + "version": "9.0.21", + "resolved": "https://registry.npmmirror.com/immer/-/immer-9.0.21.tgz", + "integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, + "node_modules/immutable": { + "version": "5.1.3", + "resolved": "https://registry.npmmirror.com/immutable/-/immutable-5.1.3.tgz", + "integrity": "sha512-+chQdDfvscSF1SJqv2gn4SRO2ZyS3xL3r7IW/wWEEzrzLisnOlKiQu5ytC/BVNcS15C39WT2Hg/bjKjDMcu+zg==", + "dev": true, + "license": "MIT" + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmmirror.com/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmmirror.com/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmmirror.com/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true, + "license": "ISC" + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmmirror.com/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmmirror.com/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true, + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-hotkey": { + "version": "0.2.0", + "resolved": "https://registry.npmmirror.com/is-hotkey/-/is-hotkey-0.2.0.tgz", + "integrity": "sha512-UknnZK4RakDmTgz4PI1wIph5yxSs/mvChWs9ifnlXsKuXgWmOkY/hAE0H/k2MIqH0RlRye0i1oC07MCRSD28Mw==", + "license": "MIT" + }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-inside-container/node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "dev": true, + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmmirror.com/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmmirror.com/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-stream": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/is-stream/-/is-stream-4.0.1.tgz", + "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-unicode-supported": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", + "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-url": { + "version": "1.2.4", + "resolved": "https://registry.npmmirror.com/is-url/-/is-url-1.2.4.tgz", + "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==", + "license": "MIT" + }, + "node_modules/is-what": { + "version": "4.1.16", + "resolved": "https://registry.npmmirror.com/is-what/-/is-what-4.1.16.tgz", + "integrity": "sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.13" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmmirror.com/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jiti": { + "version": "1.21.7", + "resolved": "https://registry.npmmirror.com/jiti/-/jiti-1.21.7.tgz", + "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/js-beautify": { + "version": "1.15.4", + "resolved": "https://registry.npmmirror.com/js-beautify/-/js-beautify-1.15.4.tgz", + "integrity": "sha512-9/KXeZUKKJwqCXUdBxFJ3vPh467OCckSBmYDwSK/EtV090K+iMJ7zx2S3HLVDIWFQdqMIsZWbnaGiba18aWhaA==", + "dev": true, + "license": "MIT", + "dependencies": { + "config-chain": "^1.1.13", + "editorconfig": "^1.0.4", + "glob": "^10.4.2", + "js-cookie": "^3.0.5", + "nopt": "^7.2.1" + }, + "bin": { + "css-beautify": "js/bin/css-beautify.js", + "html-beautify": "js/bin/html-beautify.js", + "js-beautify": "js/bin/js-beautify.js" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/js-cookie": { + "version": "3.0.5", + "resolved": "https://registry.npmmirror.com/js-cookie/-/js-cookie-3.0.5.tgz", + "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmmirror.com/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmmirror.com/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonc-eslint-parser": { + "version": "2.4.0", + "resolved": "https://registry.npmmirror.com/jsonc-eslint-parser/-/jsonc-eslint-parser-2.4.0.tgz", + "integrity": "sha512-WYDyuc/uFcGp6YtM2H0uKmUwieOuzeE/5YocFJLnLfclZ4inf3mRn8ZVy1s7Hxji7Jxm6Ss8gqpexD/GlKoGgg==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.5.0", + "eslint-visitor-keys": "^3.0.0", + "espree": "^9.0.0", + "semver": "^7.3.5" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ota-meshi" + } + }, + "node_modules/jsonc-eslint-parser/node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmmirror.com/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmmirror.com/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmmirror.com/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kolorist": { + "version": "1.8.0", + "resolved": "https://registry.npmmirror.com/kolorist/-/kolorist-1.8.0.tgz", + "integrity": "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmmirror.com/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmmirror.com/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmmirror.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" + }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmmirror.com/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", + "license": "MIT" + }, + "node_modules/lodash-unified": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/lodash-unified/-/lodash-unified-1.0.3.tgz", + "integrity": "sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ==", + "license": "MIT", + "peerDependencies": { + "@types/lodash-es": "*", + "lodash": "*", + "lodash-es": "*" + } + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "license": "MIT" + }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmmirror.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==", + "license": "MIT" + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmmirror.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "license": "MIT" + }, + "node_modules/lodash.foreach": { + "version": "4.5.0", + "resolved": "https://registry.npmmirror.com/lodash.foreach/-/lodash.foreach-4.5.0.tgz", + "integrity": "sha512-aEXTF4d+m05rVOAUG3z4vZZ4xVexLKZGF0lIxuHZ1Hplpk/3B6Z1+/ICICYRLm7c41Z2xiejbkCkJoTlypoXhQ==", + "license": "MIT" + }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmmirror.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", + "deprecated": "This package is deprecated. Use require('node:util').isDeepStrictEqual instead.", + "license": "MIT" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmmirror.com/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.throttle": { + "version": "4.1.1", + "resolved": "https://registry.npmmirror.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz", + "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==", + "license": "MIT" + }, + "node_modules/lodash.toarray": { + "version": "4.4.0", + "resolved": "https://registry.npmmirror.com/lodash.toarray/-/lodash.toarray-4.4.0.tgz", + "integrity": "sha512-QyffEA3i5dma5q2490+SgCvDN0pXLmRGSyAANuVi0HQ01Pkfr9fuoKQW8wm1wGBnJITs/mS7wQvS6VshUEBFCw==", + "license": "MIT" + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/magic-string": { + "version": "0.30.17", + "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "node_modules/marked": { + "version": "14.1.4", + "resolved": "https://registry.npmmirror.com/marked/-/marked-14.1.4.tgz", + "integrity": "sha512-vkVZ8ONmUdPnjCKc5uTRvmkRbx4EAi2OkTOXmfTDhZz3OFqMNBM1oTTWwTr4HY4uAEojhzPf+Fy8F1DWa3Sndg==", + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mdn-data": { + "version": "2.0.30", + "resolved": "https://registry.npmmirror.com/mdn-data/-/mdn-data-2.0.30.tgz", + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/memoize-one": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/memoize-one/-/memoize-one-6.0.0.tgz", + "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==", + "license": "MIT" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmmirror.com/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmmirror.com/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/micromatch/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-match": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/mime-match/-/mime-match-1.0.2.tgz", + "integrity": "sha512-VXp/ugGDVh3eCLOBCiHZMYWQaTNUHv2IJrut+yXA6+JbLPXHglHwfS/5A5L0ll+jkCY7fIzRJcH6OIunF+c6Cg==", + "license": "ISC", + "dependencies": { + "wildcard": "^1.1.0" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmmirror.com/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/mitt": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", + "license": "MIT" + }, + "node_modules/mlly": { + "version": "1.7.4", + "resolved": "https://registry.npmmirror.com/mlly/-/mlly-1.7.4.tgz", + "integrity": "sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.14.0", + "pathe": "^2.0.1", + "pkg-types": "^1.3.0", + "ufo": "^1.5.4" + } + }, + "node_modules/mlly/node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmmirror.com/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, + "node_modules/mrmime": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/mrmime/-/mrmime-2.0.1.tgz", + "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/muggle-string": { + "version": "0.4.1", + "resolved": "https://registry.npmmirror.com/muggle-string/-/muggle-string-0.4.1.tgz", + "integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmmirror.com/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/namespace-emitter": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/namespace-emitter/-/namespace-emitter-2.0.1.tgz", + "integrity": "sha512-N/sMKHniSDJBjfrkbS/tpkPj4RAbvW3mr8UAzvlMHyun93XEm83IAvhWtJVHo+RHn/oO8Job5YN4b+wRjSVp5g==", + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmmirror.com/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/next-tick": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/next-tick/-/next-tick-1.1.0.tgz", + "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", + "license": "ISC" + }, + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmmirror.com/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/node-releases": { + "version": "2.0.19", + "resolved": "https://registry.npmmirror.com/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "dev": true, + "license": "MIT" + }, + "node_modules/nopt": { + "version": "7.2.1", + "resolved": "https://registry.npmmirror.com/nopt/-/nopt-7.2.1.tgz", + "integrity": "sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==", + "dev": true, + "license": "ISC", + "dependencies": { + "abbrev": "^2.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmmirror.com/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-wheel-es": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/normalize-wheel-es/-/normalize-wheel-es-1.2.0.tgz", + "integrity": "sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw==", + "license": "BSD-3-Clause" + }, + "node_modules/npm-run-path": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/npm-run-path/-/npm-run-path-6.0.0.tgz", + "integrity": "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^4.0.0", + "unicorn-magic": "^0.3.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nprogress": { + "version": "0.2.0", + "resolved": "https://registry.npmmirror.com/nprogress/-/nprogress-0.2.0.tgz", + "integrity": "sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA==", + "license": "MIT" + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmmirror.com/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/open": { + "version": "8.4.2", + "resolved": "https://registry.npmmirror.com/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmmirror.com/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-ms": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/parse-ms/-/parse-ms-4.0.0.tgz", + "integrity": "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmmirror.com/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmmirror.com/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/pathe": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/perfect-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/perfect-debounce/-/perfect-debounce-1.0.0.tgz", + "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinia": { + "version": "2.3.1", + "resolved": "https://registry.npmmirror.com/pinia/-/pinia-2.3.1.tgz", + "integrity": "sha512-khUlZSwt9xXCaTbbxFYBKDc/bWAGWJjOgvxETwkTN7KRm66EeT1ZdZj6i2ceh9sP2Pzqsbc704r2yngBrxBVug==", + "license": "MIT", + "dependencies": { + "@vue/devtools-api": "^6.6.3", + "vue-demi": "^0.14.10" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "typescript": ">=4.4.4", + "vue": "^2.7.0 || ^3.5.11" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmmirror.com/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-types": { + "version": "1.3.1", + "resolved": "https://registry.npmmirror.com/pkg-types/-/pkg-types-1.3.1.tgz", + "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "confbox": "^0.1.8", + "mlly": "^1.7.4", + "pathe": "^2.0.1" + } + }, + "node_modules/pkg-types/node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmmirror.com/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmmirror.com/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "dev": true, + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-js": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/postcss-js/-/postcss-js-4.0.1.tgz", + "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", + "dev": true, + "license": "MIT", + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-load-config": { + "version": "4.0.2", + "resolved": "https://registry.npmmirror.com/postcss-load-config/-/postcss-load-config-4.0.2.tgz", + "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "lilconfig": "^3.0.0", + "yaml": "^2.3.4" + }, + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/postcss-nested": { + "version": "6.2.0", + "resolved": "https://registry.npmmirror.com/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.1.1" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmmirror.com/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/preact": { + "version": "10.27.0", + "resolved": "https://registry.npmmirror.com/preact/-/preact-10.27.0.tgz", + "integrity": "sha512-/DTYoB6mwwgPytiqQTh/7SFRL98ZdiD8Sk8zIUVOxtwq4oWcwrcd1uno9fE/zZmUaUrFNYzbH14CPebOz9tZQw==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.6.2", + "resolved": "https://registry.npmmirror.com/prettier/-/prettier-3.6.2.tgz", + "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/pretty-ms": { + "version": "9.2.0", + "resolved": "https://registry.npmmirror.com/pretty-ms/-/pretty-ms-9.2.0.tgz", + "integrity": "sha512-4yf0QO/sllf/1zbZWYnvWw3NxCQwLXKzIj0G849LSufP15BXKM0rbD2Z3wVnkMfjdn/CB0Dpp444gYAACdsplg==", + "dev": true, + "license": "MIT", + "dependencies": { + "parse-ms": "^4.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/prismjs": { + "version": "1.30.0", + "resolved": "https://registry.npmmirror.com/prismjs/-/prismjs-1.30.0.tgz", + "integrity": "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmmirror.com/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", + "dev": true, + "license": "ISC" + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmmirror.com/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmmirror.com/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmmirror.com/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.10", + "resolved": "https://registry.npmmirror.com/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmmirror.com/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "dev": true, + "license": "MIT" + }, + "node_modules/rollup": { + "version": "4.46.2", + "resolved": "https://registry.npmmirror.com/rollup/-/rollup-4.46.2.tgz", + "integrity": "sha512-WMmLFI+Boh6xbop+OAGo9cQ3OgX9MIg7xOQjn+pTCwOkk+FNDAeAemXkJ3HzDJrVXleLOFVa1ipuc1AmEx1Dwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.46.2", + "@rollup/rollup-android-arm64": "4.46.2", + "@rollup/rollup-darwin-arm64": "4.46.2", + "@rollup/rollup-darwin-x64": "4.46.2", + "@rollup/rollup-freebsd-arm64": "4.46.2", + "@rollup/rollup-freebsd-x64": "4.46.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.46.2", + "@rollup/rollup-linux-arm-musleabihf": "4.46.2", + "@rollup/rollup-linux-arm64-gnu": "4.46.2", + "@rollup/rollup-linux-arm64-musl": "4.46.2", + "@rollup/rollup-linux-loongarch64-gnu": "4.46.2", + "@rollup/rollup-linux-ppc64-gnu": "4.46.2", + "@rollup/rollup-linux-riscv64-gnu": "4.46.2", + "@rollup/rollup-linux-riscv64-musl": "4.46.2", + "@rollup/rollup-linux-s390x-gnu": "4.46.2", + "@rollup/rollup-linux-x64-gnu": "4.46.2", + "@rollup/rollup-linux-x64-musl": "4.46.2", + "@rollup/rollup-win32-arm64-msvc": "4.46.2", + "@rollup/rollup-win32-ia32-msvc": "4.46.2", + "@rollup/rollup-win32-x64-msvc": "4.46.2", + "fsevents": "~2.3.2" + } + }, + "node_modules/rollup-plugin-visualizer": { + "version": "5.14.0", + "resolved": "https://registry.npmmirror.com/rollup-plugin-visualizer/-/rollup-plugin-visualizer-5.14.0.tgz", + "integrity": "sha512-VlDXneTDaKsHIw8yzJAFWtrzguoJ/LnQ+lMpoVfYJ3jJF4Ihe5oYLAqLklIK/35lgUY+1yEzCkHyZ1j4A5w5fA==", + "dev": true, + "license": "MIT", + "dependencies": { + "open": "^8.4.0", + "picomatch": "^4.0.2", + "source-map": "^0.7.4", + "yargs": "^17.5.1" + }, + "bin": { + "rollup-plugin-visualizer": "dist/bin/cli.js" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "rolldown": "1.x", + "rollup": "2.x || 3.x || 4.x" + }, + "peerDependenciesMeta": { + "rolldown": { + "optional": true + }, + "rollup": { + "optional": true + } + } + }, + "node_modules/rollup-plugin-visualizer/node_modules/source-map": { + "version": "0.7.6", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.7.6.tgz", + "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">= 12" + } + }, + "node_modules/run-applescript": { + "version": "7.0.0", + "resolved": "https://registry.npmmirror.com/run-applescript/-/run-applescript-7.0.0.tgz", + "integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/sass": { + "version": "1.81.0", + "resolved": "https://registry.npmmirror.com/sass/-/sass-1.81.0.tgz", + "integrity": "sha512-Q4fOxRfhmv3sqCLoGfvrC9pRV8btc0UtqL9mN6Yrv6Qi9ScL55CVH1vlPP863ISLEEMNLLuu9P+enCeGHlnzhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "chokidar": "^4.0.0", + "immutable": "^5.0.2", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=14.0.0" + }, + "optionalDependencies": { + "@parcel/watcher": "^2.4.1" + } + }, + "node_modules/scroll-into-view-if-needed": { + "version": "2.2.31", + "resolved": "https://registry.npmmirror.com/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.31.tgz", + "integrity": "sha512-dGCXy99wZQivjmjIqihaBQNjryrz5rueJY7eHfTdyWEiR4ttYpsajb14rn9s5d4DY4EcY6+4+U/maARBXJedkA==", + "license": "MIT", + "dependencies": { + "compute-scroll-into-view": "^1.0.20" + } + }, + "node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmmirror.com/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmmirror.com/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/sirv": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/sirv/-/sirv-3.0.1.tgz", + "integrity": "sha512-FoqMu0NCGBLCcAkS1qA+XJIQTR6/JHfQXl+uGteNCQ76T91DMUjPa9xfmeqMY3z80nLSg9yQmNjK0Px6RWsH/A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@polka/url": "^1.0.0-next.24", + "mrmime": "^2.0.0", + "totalist": "^3.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/slate": { + "version": "0.72.8", + "resolved": "https://registry.npmmirror.com/slate/-/slate-0.72.8.tgz", + "integrity": "sha512-/nJwTswQgnRurpK+bGJFH1oM7naD5qDmHd89JyiKNT2oOKD8marW0QSBtuFnwEbL5aGCS8AmrhXQgNOsn4osAw==", + "license": "MIT", + "dependencies": { + "immer": "^9.0.6", + "is-plain-object": "^5.0.0", + "tiny-warning": "^1.0.3" + } + }, + "node_modules/slate-history": { + "version": "0.66.0", + "resolved": "https://registry.npmmirror.com/slate-history/-/slate-history-0.66.0.tgz", + "integrity": "sha512-6MWpxGQZiMvSINlCbMW43E2YBSVMCMCIwQfBzGssjWw4kb0qfvj0pIdblWNRQZD0hR6WHP+dHHgGSeVdMWzfng==", + "license": "MIT", + "dependencies": { + "is-plain-object": "^5.0.0" + }, + "peerDependencies": { + "slate": ">=0.65.3" + } + }, + "node_modules/snabbdom": { + "version": "3.6.2", + "resolved": "https://registry.npmmirror.com/snabbdom/-/snabbdom-3.6.2.tgz", + "integrity": "sha512-ig5qOnCDbugFntKi6c7Xlib8bA6xiJVk8O+WdFrV3wxbMqeHO0hXFQC4nAhPVWfZfi8255lcZkNhtIBINCc4+Q==", + "license": "MIT", + "engines": { + "node": ">=12.17.0" + } + }, + "node_modules/sortablejs": { + "version": "1.14.0", + "resolved": "https://registry.npmmirror.com/sortablejs/-/sortablejs-1.14.0.tgz", + "integrity": "sha512-pBXvQCs5/33fdN1/39pPL0NZF20LeRbLQ5jtnheIPN9JQAaufGjKdWduZn4U7wCtVuzKhmRkI0DFYHYRbB2H1w==", + "license": "MIT" + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmmirror.com/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/speakingurl": { + "version": "14.0.1", + "resolved": "https://registry.npmmirror.com/speakingurl/-/speakingurl-14.0.1.tgz", + "integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ssf": { + "version": "0.11.2", + "resolved": "https://registry.npmmirror.com/ssf/-/ssf-0.11.2.tgz", + "integrity": "sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==", + "license": "Apache-2.0", + "dependencies": { + "frac": "~1.1.2" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/ssr-window": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/ssr-window/-/ssr-window-3.0.0.tgz", + "integrity": "sha512-q+8UfWDg9Itrg0yWK7oe5p/XRCJpJF9OBtXfOPgSJl+u3Xd5KI328RUEvUqSMVM9CiQUEf1QdBzJMkYGErj9QA==", + "license": "MIT" + }, + "node_modules/store": { + "version": "2.0.12", + "resolved": "https://registry.npmmirror.com/store/-/store-2.0.12.tgz", + "integrity": "sha512-eO9xlzDpXLiMr9W1nQ3Nfp9EzZieIQc10zPPMP5jsVV7bLOziSFFBP0XoDXACEIFtdI+rIz0NwWVA/QVJ8zJtw==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/strip-final-newline/-/strip-final-newline-4.0.0.tgz", + "integrity": "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/sucrase": { + "version": "3.35.0", + "resolved": "https://registry.npmmirror.com/sucrase/-/sucrase-3.35.0.tgz", + "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "^10.3.10", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/sucrase/node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmmirror.com/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/superjson": { + "version": "2.2.2", + "resolved": "https://registry.npmmirror.com/superjson/-/superjson-2.2.2.tgz", + "integrity": "sha512-5JRxVqC8I8NuOUjzBbvVJAKNM8qoVuH0O77h4WInc/qC2q5IreqKxYwgkga3PfA22OayK2ikceb/B26dztPl+Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "copy-anything": "^3.0.2" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/svgo": { + "version": "3.3.2", + "resolved": "https://registry.npmmirror.com/svgo/-/svgo-3.3.2.tgz", + "integrity": "sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^5.1.0", + "css-tree": "^2.3.1", + "css-what": "^6.1.0", + "csso": "^5.0.5", + "picocolors": "^1.0.0" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/svgo" + } + }, + "node_modules/svgo/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmmirror.com/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/synckit": { + "version": "0.11.11", + "resolved": "https://registry.npmmirror.com/synckit/-/synckit-0.11.11.tgz", + "integrity": "sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@pkgr/core": "^0.2.9" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/synckit" + } + }, + "node_modules/tailwindcss": { + "version": "3.4.17", + "resolved": "https://registry.npmmirror.com/tailwindcss/-/tailwindcss-3.4.17.tgz", + "integrity": "sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==", + "dev": true, + "license": "MIT", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.6.0", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.2", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.21.6", + "lilconfig": "^3.1.3", + "micromatch": "^4.0.8", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.1.1", + "postcss": "^8.4.47", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.2", + "postcss-nested": "^6.2.0", + "postcss-selector-parser": "^6.1.2", + "resolve": "^1.22.8", + "sucrase": "^3.35.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tailwindcss/node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/tailwindcss/node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/tailwindcss/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/tailwindcss/node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmmirror.com/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/terser": { + "version": "5.43.1", + "resolved": "https://registry.npmmirror.com/terser/-/terser-5.43.1.tgz", + "integrity": "sha512-+6erLbBm0+LROX2sPXlUYx/ux5PyE9K/a92Wrt6oA+WDAoFTdpHE5tCYCI5PNzq2y8df4rA+QgHLJuR4jNymsg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.14.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmmirror.com/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmmirror.com/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmmirror.com/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tiny-warning": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/tiny-warning/-/tiny-warning-1.0.3.tgz", + "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==", + "license": "MIT" + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/totalist": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/totalist/-/totalist-3.0.1.tgz", + "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/ts-api-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/ts-api-utils/-/ts-api-utils-2.1.0.tgz", + "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmmirror.com/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/tslib": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.3.0.tgz", + "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==", + "license": "0BSD" + }, + "node_modules/type": { + "version": "2.7.3", + "resolved": "https://registry.npmmirror.com/type/-/type-2.7.3.tgz", + "integrity": "sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==", + "license": "ISC" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmmirror.com/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmmirror.com/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "5.5.4", + "resolved": "https://registry.npmmirror.com/typescript/-/typescript-5.5.4.tgz", + "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", + "devOptional": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typescript-eslint": { + "version": "8.39.1", + "resolved": "https://registry.npmmirror.com/typescript-eslint/-/typescript-eslint-8.39.1.tgz", + "integrity": "sha512-GDUv6/NDYngUlNvwaHM1RamYftxf782IyEDbdj3SeaIHHv8fNQVRC++fITT7kUJV/5rIA/tkoRSSskt6osEfqg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.39.1", + "@typescript-eslint/parser": "8.39.1", + "@typescript-eslint/typescript-estree": "8.39.1", + "@typescript-eslint/utils": "8.39.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/ufo": { + "version": "1.6.1", + "resolved": "https://registry.npmmirror.com/ufo/-/ufo-1.6.1.tgz", + "integrity": "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==", + "dev": true, + "license": "MIT" + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/unicorn-magic": { + "version": "0.3.0", + "resolved": "https://registry.npmmirror.com/unicorn-magic/-/unicorn-magic-0.3.0.tgz", + "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unplugin": { + "version": "1.16.1", + "resolved": "https://registry.npmmirror.com/unplugin/-/unplugin-1.16.1.tgz", + "integrity": "sha512-4/u/j4FrCKdi17jaxuJA0jClGxB1AvU2hw/IuayPc4ay1XGaJs/rbb4v5WKwAjNifjmXK9PIFyuPiaK8azyR9w==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.14.0", + "webpack-virtual-modules": "^0.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.3", + "resolved": "https://registry.npmmirror.com/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmmirror.com/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/vite": { + "version": "5.4.19", + "resolved": "https://registry.npmmirror.com/vite/-/vite-5.4.19.tgz", + "integrity": "sha512-qO3aKv3HoQC8QKiNSTuUM1l9o/XX3+c+VTgLHbJWHZGeTPVAg2XwazI9UWzoxjIJCGCV2zU60uqMzjeLZuULqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vite-hot-client": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/vite-hot-client/-/vite-hot-client-2.1.0.tgz", + "integrity": "sha512-7SpgZmU7R+dDnSmvXE1mfDtnHLHQSisdySVR7lO8ceAXvM0otZeuQQ6C8LrS5d/aYyP/QZ0hI0L+dIPrm4YlFQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "vite": "^2.6.0 || ^3.0.0 || ^4.0.0 || ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0" + } + }, + "node_modules/vite-plugin-compression": { + "version": "0.5.1", + "resolved": "https://registry.npmmirror.com/vite-plugin-compression/-/vite-plugin-compression-0.5.1.tgz", + "integrity": "sha512-5QJKBDc+gNYVqL/skgFAP81Yuzo9R+EAf19d+EtsMF/i8kFUpNi3J/H01QD3Oo8zBQn+NzoCIFkpPLynoOzaJg==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "debug": "^4.3.3", + "fs-extra": "^10.0.0" + }, + "peerDependencies": { + "vite": ">=2.0.0" + } + }, + "node_modules/vite-plugin-inspect": { + "version": "0.8.9", + "resolved": "https://registry.npmmirror.com/vite-plugin-inspect/-/vite-plugin-inspect-0.8.9.tgz", + "integrity": "sha512-22/8qn+LYonzibb1VeFZmISdVao5kC22jmEKm24vfFE8siEn47EpVcCLYMv6iKOYMJfjSvSJfueOwcFCkUnV3A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@antfu/utils": "^0.7.10", + "@rollup/pluginutils": "^5.1.3", + "debug": "^4.3.7", + "error-stack-parser-es": "^0.1.5", + "fs-extra": "^11.2.0", + "open": "^10.1.0", + "perfect-debounce": "^1.0.0", + "picocolors": "^1.1.1", + "sirv": "^3.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "vite": "^3.1.0 || ^4.0.0 || ^5.0.0-0 || ^6.0.1" + }, + "peerDependenciesMeta": { + "@nuxt/kit": { + "optional": true + } + } + }, + "node_modules/vite-plugin-inspect/node_modules/define-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/vite-plugin-inspect/node_modules/fs-extra": { + "version": "11.3.1", + "resolved": "https://registry.npmmirror.com/fs-extra/-/fs-extra-11.3.1.tgz", + "integrity": "sha512-eXvGGwZ5CL17ZSwHWd3bbgk7UUpF6IFHtP57NYYakPvHOs8GDgDe5KJI36jIJzDkJ6eJjuzRA8eBQb6SkKue0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/vite-plugin-inspect/node_modules/open": { + "version": "10.2.0", + "resolved": "https://registry.npmmirror.com/open/-/open-10.2.0.tgz", + "integrity": "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "default-browser": "^5.2.1", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "wsl-utils": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/vite-plugin-vue-devtools": { + "version": "7.7.7", + "resolved": "https://registry.npmmirror.com/vite-plugin-vue-devtools/-/vite-plugin-vue-devtools-7.7.7.tgz", + "integrity": "sha512-d0fIh3wRcgSlr4Vz7bAk4va1MkdqhQgj9ANE/rBhsAjOnRfTLs2ocjFMvSUOsv6SRRXU9G+VM7yMgqDb6yI4iQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/devtools-core": "^7.7.7", + "@vue/devtools-kit": "^7.7.7", + "@vue/devtools-shared": "^7.7.7", + "execa": "^9.5.2", + "sirv": "^3.0.1", + "vite-plugin-inspect": "0.8.9", + "vite-plugin-vue-inspector": "^5.3.1" + }, + "engines": { + "node": ">=v14.21.3" + }, + "peerDependencies": { + "vite": "^3.1.0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0" + } + }, + "node_modules/vite-plugin-vue-inspector": { + "version": "5.3.2", + "resolved": "https://registry.npmmirror.com/vite-plugin-vue-inspector/-/vite-plugin-vue-inspector-5.3.2.tgz", + "integrity": "sha512-YvEKooQcSiBTAs0DoYLfefNja9bLgkFM7NI2b07bE2SruuvX0MEa9cMaxjKVMkeCp5Nz9FRIdcN1rOdFVBeL6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.23.0", + "@babel/plugin-proposal-decorators": "^7.23.0", + "@babel/plugin-syntax-import-attributes": "^7.22.5", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-transform-typescript": "^7.22.15", + "@vue/babel-plugin-jsx": "^1.1.5", + "@vue/compiler-dom": "^3.3.4", + "kolorist": "^1.8.0", + "magic-string": "^0.30.4" + }, + "peerDependencies": { + "vite": "^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0" + } + }, + "node_modules/vscode-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/vscode-uri/-/vscode-uri-3.1.0.tgz", + "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/vue": { + "version": "3.5.18", + "resolved": "https://registry.npmmirror.com/vue/-/vue-3.5.18.tgz", + "integrity": "sha512-7W4Y4ZbMiQ3SEo+m9lnoNpV9xG7QVMLa+/0RFwwiAVkeYoyGXqWE85jabU4pllJNUzqfLShJ5YLptewhCWUgNA==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.18", + "@vue/compiler-sfc": "3.5.18", + "@vue/runtime-dom": "3.5.18", + "@vue/server-renderer": "3.5.18", + "@vue/shared": "3.5.18" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/vue-component-type-helpers": { + "version": "2.2.12", + "resolved": "https://registry.npmmirror.com/vue-component-type-helpers/-/vue-component-type-helpers-2.2.12.tgz", + "integrity": "sha512-YbGqHZ5/eW4SnkPNR44mKVc6ZKQoRs/Rux1sxC6rdwXb4qpbOSYfDr9DsTHolOTGmIKgM9j141mZbBeg05R1pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/vue-demi": { + "version": "0.14.10", + "resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.10.tgz", + "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/vue-echarts": { + "version": "7.0.3", + "resolved": "https://registry.npmmirror.com/vue-echarts/-/vue-echarts-7.0.3.tgz", + "integrity": "sha512-/jSxNwOsw5+dYAUcwSfkLwKPuzTQ0Cepz1LxCOpj2QcHrrmUa/Ql0eQqMmc1rTPQVrh2JQ29n2dhq75ZcHvRDw==", + "license": "MIT", + "dependencies": { + "vue-demi": "^0.13.11" + }, + "peerDependencies": { + "@vue/runtime-core": "^3.0.0", + "echarts": "^5.5.1", + "vue": "^2.7.0 || ^3.1.1" + }, + "peerDependenciesMeta": { + "@vue/runtime-core": { + "optional": true + } + } + }, + "node_modules/vue-echarts/node_modules/vue-demi": { + "version": "0.13.11", + "resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.13.11.tgz", + "integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/vue-eslint-parser": { + "version": "10.2.0", + "resolved": "https://registry.npmmirror.com/vue-eslint-parser/-/vue-eslint-parser-10.2.0.tgz", + "integrity": "sha512-CydUvFOQKD928UzZhTp4pr2vWz1L+H99t7Pkln2QSPdvmURT0MoC4wUccfCnuEaihNsu9aYYyk+bep8rlfkUXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "eslint-scope": "^8.2.0", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", + "esquery": "^1.6.0", + "semver": "^7.6.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + } + }, + "node_modules/vue-eslint-parser/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/vue-i18n": { + "version": "11.1.11", + "resolved": "https://registry.npmmirror.com/vue-i18n/-/vue-i18n-11.1.11.tgz", + "integrity": "sha512-LvyteQoXeQiuILbzqv13LbyBna/TEv2Ha+4ZWK2AwGHUzZ8+IBaZS0TJkCgn5izSPLcgZwXy9yyTrewCb2u/MA==", + "license": "MIT", + "dependencies": { + "@intlify/core-base": "11.1.11", + "@intlify/shared": "11.1.11", + "@vue/devtools-api": "^6.5.0" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + }, + "peerDependencies": { + "vue": "^3.0.0" + } + }, + "node_modules/vue-router": { + "version": "4.5.1", + "resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-4.5.1.tgz", + "integrity": "sha512-ogAF3P97NPm8fJsE4by9dwSYtDwXIY1nFY9T6DyQnGHd1E2Da94w9JIolpe42LJGIl0DwOHBi8TcRPlPGwbTtw==", + "license": "MIT", + "dependencies": { + "@vue/devtools-api": "^6.6.4" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "vue": "^3.2.0" + } + }, + "node_modules/vue-tsc": { + "version": "2.2.12", + "resolved": "https://registry.npmmirror.com/vue-tsc/-/vue-tsc-2.2.12.tgz", + "integrity": "sha512-P7OP77b2h/Pmk+lZdJ0YWs+5tJ6J2+uOQPo7tlBnY44QqQSPYvS0qVT4wqDJgwrZaLe47etJLLQRFia71GYITw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/typescript": "2.4.15", + "@vue/language-core": "2.2.12" + }, + "bin": { + "vue-tsc": "bin/vue-tsc.js" + }, + "peerDependencies": { + "typescript": ">=5.0.0" + } + }, + "node_modules/vuedraggable": { + "version": "4.1.0", + "resolved": "https://registry.npmmirror.com/vuedraggable/-/vuedraggable-4.1.0.tgz", + "integrity": "sha512-FU5HCWBmsf20GpP3eudURW3WdWTKIbEIQxh9/8GE806hydR9qZqRRxRE3RjqX7PkuLuMQG/A7n3cfj9rCEchww==", + "license": "MIT", + "dependencies": { + "sortablejs": "1.14.0" + }, + "peerDependencies": { + "vue": "^3.0.1" + } + }, + "node_modules/webpack-virtual-modules": { + "version": "0.6.2", + "resolved": "https://registry.npmmirror.com/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz", + "integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wildcard": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/wildcard/-/wildcard-1.1.2.tgz", + "integrity": "sha512-DXukZJxpHA8LuotRwL0pP1+rS6CS7FF2qStDDE1C7DDg2rLud2PXRMuEDYIPhgEezwnlHNL4c+N6MfMTjCGTng==", + "license": "MIT" + }, + "node_modules/wmf": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/wmf/-/wmf-1.0.2.tgz", + "integrity": "sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/word": { + "version": "0.3.0", + "resolved": "https://registry.npmmirror.com/word/-/word-0.3.0.tgz", + "integrity": "sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmmirror.com/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wsl-utils": { + "version": "0.1.0", + "resolved": "https://registry.npmmirror.com/wsl-utils/-/wsl-utils-0.1.0.tgz", + "integrity": "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-wsl": "^3.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/wsl-utils/node_modules/is-wsl": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/is-wsl/-/is-wsl-3.1.0.tgz", + "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-inside-container": "^1.0.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/xlsx": { + "version": "0.18.5", + "resolved": "https://registry.npmmirror.com/xlsx/-/xlsx-0.18.5.tgz", + "integrity": "sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==", + "license": "Apache-2.0", + "dependencies": { + "adler-32": "~1.3.0", + "cfb": "~1.2.1", + "codepage": "~1.15.0", + "crc-32": "~1.2.1", + "ssf": "~0.11.2", + "wmf": "~1.0.1", + "word": "~0.3.0" + }, + "bin": { + "xlsx": "bin/xlsx.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/xml-name-validator": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/xml-name-validator/-/xml-name-validator-4.0.0.tgz", + "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmmirror.com/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/yaml": { + "version": "2.8.1", + "resolved": "https://registry.npmmirror.com/yaml/-/yaml-2.8.1.tgz", + "integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==", + "dev": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + } + }, + "node_modules/yaml-eslint-parser": { + "version": "1.3.0", + "resolved": "https://registry.npmmirror.com/yaml-eslint-parser/-/yaml-eslint-parser-1.3.0.tgz", + "integrity": "sha512-E/+VitOorXSLiAqtTd7Yqax0/pAS3xaYMP+AUUJGOK1OZG3rhcj9fcJOM5HJ2VrP1FrStVCWr1muTfQCdj4tAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.0.0", + "yaml": "^2.0.0" + }, + "engines": { + "node": "^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ota-meshi" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmmirror.com/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmmirror.com/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yoctocolors": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/yoctocolors/-/yoctocolors-2.1.1.tgz", + "integrity": "sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zrender": { + "version": "5.6.1", + "resolved": "https://registry.npmmirror.com/zrender/-/zrender-5.6.1.tgz", + "integrity": "sha512-OFXkDJKcrlx5su2XbzJvj/34Q3m6PvyCZkVPHGYpcCJ52ek4U/ymZyfuV1nKE23AyBJ51E/6Yr0mhZ7xGTO4ag==", + "license": "BSD-3-Clause", + "dependencies": { + "tslib": "2.3.0" + } + } + } +} diff --git a/cool-admin-vue/package.json b/cool-admin-vue/package.json new file mode 100644 index 0000000..d3d95ed --- /dev/null +++ b/cool-admin-vue/package.json @@ -0,0 +1,75 @@ +{ + "name": "cool-admin-vue", + "version": "8.0.0", + "type": "module", + "scripts": { + "dev": "vite --host", + "build": "vite build", + "build-static": "vite build --mode static", + "build-demo": "vite build --mode demo", + "preview": "vite preview", + "type-check": "vue-tsc --build --force", + "lint": "eslint . --fix", + "format": "prettier --write src/" + }, + "dependencies": { + "@cool-vue/crud": "^8.0.6", + "@element-plus/icons-vue": "^2.3.1", + "@vueuse/core": "^12.5.0", + "@wangeditor/editor": "^5.1.23", + "@wangeditor/editor-for-vue": "^5.1.12", + "axios": "^1.7.9", + "chardet": "^2.0.0", + "core-js": "^3.40.0", + "dayjs": "^1.11.13", + "echarts": "^5.6.0", + "element-plus": "2.10.2", + "file-saver": "^2.0.5", + "lodash-es": "^4.17.21", + "marked": "^14.1.3", + "mitt": "^3.0.1", + "nprogress": "^0.2.0", + "pinia": "^2.3.1", + "store": "^2.0.12", + "vue": "^3.5.13", + "vue-echarts": "^7.0.3", + "vue-i18n": "^11.0.1", + "vue-router": "^4.5.0", + "vuedraggable": "^4.1.0", + "xlsx": "^0.18.5" + }, + "devDependencies": { + "@cool-vue/vite-plugin": "^8.2.2", + "@intlify/unplugin-vue-i18n": "^6.0.3", + "@rushstack/eslint-patch": "^1.10.5", + "@tsconfig/node20": "^20.1.4", + "@types/file-saver": "^2.0.7", + "@types/lodash-es": "^4.17.12", + "@types/mockjs": "^1.0.10", + "@types/node": "^20.17.17", + "@types/nprogress": "^0.2.3", + "@types/store": "^2.0.5", + "@vitejs/plugin-vue": "^5.2.1", + "@vitejs/plugin-vue-jsx": "^4.1.1", + "@vue/compiler-sfc": "^3.5.13", + "@vue/eslint-config-prettier": "^10.2.0", + "@vue/eslint-config-typescript": "^14.3.0", + "@vue/test-utils": "^2.4.6", + "@vue/tsconfig": "^0.5.1", + "autoprefixer": "^10.4.20", + "eslint": "^9.19.0", + "eslint-plugin-prettier": "^5.2.3", + "eslint-plugin-vue": "^9.32.0", + "postcss": "^8.5.1", + "prettier": "^3.4.2", + "rollup-plugin-visualizer": "^5.14.0", + "sass": "1.81.0", + "tailwindcss": "^3.4.17", + "terser": "^5.36.0", + "typescript": "~5.5.4", + "vite": "^5.4.14", + "vite-plugin-compression": "^0.5.1", + "vite-plugin-vue-devtools": "^7.7.1", + "vue-tsc": "^2.2.0" + } +} diff --git a/cool-admin-vue/pnpm-lock.yaml b/cool-admin-vue/pnpm-lock.yaml new file mode 100644 index 0000000..6032cd0 --- /dev/null +++ b/cool-admin-vue/pnpm-lock.yaml @@ -0,0 +1,5655 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@cool-vue/crud': + specifier: ^8.0.6 + version: 8.0.6(typescript@5.5.4) + '@element-plus/icons-vue': + specifier: ^2.3.1 + version: 2.3.1(vue@3.5.18(typescript@5.5.4)) + '@vueuse/core': + specifier: ^12.5.0 + version: 12.8.2(typescript@5.5.4) + '@wangeditor/editor': + specifier: ^5.1.23 + version: 5.1.23 + '@wangeditor/editor-for-vue': + specifier: ^5.1.12 + version: 5.1.12(@wangeditor/editor@5.1.23)(vue@3.5.18(typescript@5.5.4)) + axios: + specifier: ^1.7.9 + version: 1.11.0 + chardet: + specifier: ^2.0.0 + version: 2.1.0 + core-js: + specifier: ^3.40.0 + version: 3.44.0 + dayjs: + specifier: ^1.11.13 + version: 1.11.13 + echarts: + specifier: ^5.6.0 + version: 5.6.0 + element-plus: + specifier: 2.10.2 + version: 2.10.2(vue@3.5.18(typescript@5.5.4)) + file-saver: + specifier: ^2.0.5 + version: 2.0.5 + lodash-es: + specifier: ^4.17.21 + version: 4.17.21 + marked: + specifier: ^14.1.3 + version: 14.1.4 + mitt: + specifier: ^3.0.1 + version: 3.0.1 + nprogress: + specifier: ^0.2.0 + version: 0.2.0 + pinia: + specifier: ^2.3.1 + version: 2.3.1(typescript@5.5.4)(vue@3.5.18(typescript@5.5.4)) + store: + specifier: ^2.0.12 + version: 2.0.12 + vue: + specifier: ^3.5.13 + version: 3.5.18(typescript@5.5.4) + vue-echarts: + specifier: ^7.0.3 + version: 7.0.3(@vue/runtime-core@3.5.18)(echarts@5.6.0)(vue@3.5.18(typescript@5.5.4)) + vue-i18n: + specifier: ^11.0.1 + version: 11.1.10(vue@3.5.18(typescript@5.5.4)) + vue-router: + specifier: ^4.5.0 + version: 4.5.1(vue@3.5.18(typescript@5.5.4)) + vuedraggable: + specifier: ^4.1.0 + version: 4.1.0(vue@3.5.18(typescript@5.5.4)) + xlsx: + specifier: ^0.18.5 + version: 0.18.5 + devDependencies: + '@cool-vue/vite-plugin': + specifier: ^8.2.2 + version: 8.2.2 + '@intlify/unplugin-vue-i18n': + specifier: ^6.0.3 + version: 6.0.8(@vue/compiler-dom@3.5.18)(eslint@9.31.0(jiti@1.21.7))(rollup@4.45.1)(typescript@5.5.4)(vue-i18n@11.1.10(vue@3.5.18(typescript@5.5.4)))(vue@3.5.18(typescript@5.5.4)) + '@rushstack/eslint-patch': + specifier: ^1.10.5 + version: 1.12.0 + '@tsconfig/node20': + specifier: ^20.1.4 + version: 20.1.6 + '@types/file-saver': + specifier: ^2.0.7 + version: 2.0.7 + '@types/lodash-es': + specifier: ^4.17.12 + version: 4.17.12 + '@types/mockjs': + specifier: ^1.0.10 + version: 1.0.10 + '@types/node': + specifier: ^20.17.17 + version: 20.19.9 + '@types/nprogress': + specifier: ^0.2.3 + version: 0.2.3 + '@types/store': + specifier: ^2.0.5 + version: 2.0.5 + '@vitejs/plugin-vue': + specifier: ^5.2.1 + version: 5.2.4(vite@5.4.19(@types/node@20.19.9)(sass@1.81.0)(terser@5.43.1))(vue@3.5.18(typescript@5.5.4)) + '@vitejs/plugin-vue-jsx': + specifier: ^4.1.1 + version: 4.2.0(vite@5.4.19(@types/node@20.19.9)(sass@1.81.0)(terser@5.43.1))(vue@3.5.18(typescript@5.5.4)) + '@vue/compiler-sfc': + specifier: ^3.5.13 + version: 3.5.18 + '@vue/eslint-config-prettier': + specifier: ^10.2.0 + version: 10.2.0(eslint@9.31.0(jiti@1.21.7))(prettier@3.6.2) + '@vue/eslint-config-typescript': + specifier: ^14.3.0 + version: 14.6.0(eslint-plugin-vue@9.33.0(eslint@9.31.0(jiti@1.21.7)))(eslint@9.31.0(jiti@1.21.7))(typescript@5.5.4) + '@vue/test-utils': + specifier: ^2.4.6 + version: 2.4.6 + '@vue/tsconfig': + specifier: ^0.5.1 + version: 0.5.1 + autoprefixer: + specifier: ^10.4.20 + version: 10.4.21(postcss@8.5.6) + eslint: + specifier: ^9.19.0 + version: 9.31.0(jiti@1.21.7) + eslint-plugin-prettier: + specifier: ^5.2.3 + version: 5.5.3(eslint-config-prettier@10.1.8(eslint@9.31.0(jiti@1.21.7)))(eslint@9.31.0(jiti@1.21.7))(prettier@3.6.2) + eslint-plugin-vue: + specifier: ^9.32.0 + version: 9.33.0(eslint@9.31.0(jiti@1.21.7)) + postcss: + specifier: ^8.5.1 + version: 8.5.6 + prettier: + specifier: ^3.4.2 + version: 3.6.2 + rollup-plugin-visualizer: + specifier: ^5.14.0 + version: 5.14.0(rollup@4.45.1) + sass: + specifier: 1.81.0 + version: 1.81.0 + tailwindcss: + specifier: ^3.4.17 + version: 3.4.17 + terser: + specifier: ^5.36.0 + version: 5.43.1 + typescript: + specifier: ~5.5.4 + version: 5.5.4 + vite: + specifier: ^5.4.14 + version: 5.4.19(@types/node@20.19.9)(sass@1.81.0)(terser@5.43.1) + vite-plugin-compression: + specifier: ^0.5.1 + version: 0.5.1(vite@5.4.19(@types/node@20.19.9)(sass@1.81.0)(terser@5.43.1)) + vite-plugin-vue-devtools: + specifier: ^7.7.1 + version: 7.7.7(rollup@4.45.1)(vite@5.4.19(@types/node@20.19.9)(sass@1.81.0)(terser@5.43.1))(vue@3.5.18(typescript@5.5.4)) + vue-tsc: + specifier: ^2.2.0 + version: 2.2.12(typescript@5.5.4) + +packages: + + '@alloc/quick-lru@5.2.0': + resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} + engines: {node: '>=10'} + + '@ampproject/remapping@2.3.0': + resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} + engines: {node: '>=6.0.0'} + + '@antfu/utils@0.7.10': + resolution: {integrity: sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww==} + + '@babel/code-frame@7.27.1': + resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} + engines: {node: '>=6.9.0'} + + '@babel/compat-data@7.28.0': + resolution: {integrity: sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.28.0': + resolution: {integrity: sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ==} + engines: {node: '>=6.9.0'} + + '@babel/generator@7.28.0': + resolution: {integrity: sha512-lJjzvrbEeWrhB4P3QBsH7tey117PjLZnDbLiQEKjQ/fNJTjuq4HSqgFA+UNSwZT8D7dxxbnuSBMsa1lrWzKlQg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-annotate-as-pure@7.27.3': + resolution: {integrity: sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-compilation-targets@7.27.2': + resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-create-class-features-plugin@7.27.1': + resolution: {integrity: sha512-QwGAmuvM17btKU5VqXfb+Giw4JcN0hjuufz3DYnpeVDvZLAObloM77bhMXiqry3Iio+Ai4phVRDwl6WU10+r5A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-globals@7.28.0': + resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-member-expression-to-functions@7.27.1': + resolution: {integrity: sha512-E5chM8eWjTp/aNoVpcbfM7mLxu9XGLWYise2eBKGQomAk/Mb4XoxyqXTZbuTohbsl8EKqdlMhnDI2CCLfcs9wA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.27.1': + resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-transforms@7.27.3': + resolution: {integrity: sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-optimise-call-expression@7.27.1': + resolution: {integrity: sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-plugin-utils@7.27.1': + resolution: {integrity: sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-replace-supers@7.27.1': + resolution: {integrity: sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-skip-transparent-expression-wrappers@7.27.1': + resolution: {integrity: sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-string-parser@7.27.1': + resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.27.1': + resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-option@7.27.1': + resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} + engines: {node: '>=6.9.0'} + + '@babel/helpers@7.27.6': + resolution: {integrity: sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.28.0': + resolution: {integrity: sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/plugin-proposal-decorators@7.28.0': + resolution: {integrity: sha512-zOiZqvANjWDUaUS9xMxbMcK/Zccztbe/6ikvUXaG9nsPH3w6qh5UaPGAnirI/WhIbZ8m3OHU0ReyPrknG+ZKeg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-decorators@7.27.1': + resolution: {integrity: sha512-YMq8Z87Lhl8EGkmb0MwYkt36QnxC+fzCgrl66ereamPlYToRpIk5nUjKUY3QKLWq8mwUB1BgbeXcTJhZOCDg5A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-attributes@7.27.1': + resolution: {integrity: sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-meta@7.10.4': + resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-jsx@7.27.1': + resolution: {integrity: sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-typescript@7.27.1': + resolution: {integrity: sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-typescript@7.28.0': + resolution: {integrity: sha512-4AEiDEBPIZvLQaWlc9liCavE0xRM0dNca41WtBeM3jgFptfUOSG9z0uteLhq6+3rq+WB6jIvUwKDTpXEHPJ2Vg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/runtime@7.27.6': + resolution: {integrity: sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q==} + engines: {node: '>=6.9.0'} + + '@babel/template@7.27.2': + resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.28.0': + resolution: {integrity: sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.28.1': + resolution: {integrity: sha512-x0LvFTekgSX+83TI28Y9wYPUfzrnl2aT5+5QLnO6v7mSJYtEEevuDRN0F0uSHRk1G1IWZC43o00Y0xDDrpBGPQ==} + engines: {node: '>=6.9.0'} + + '@cool-vue/crud@8.0.6': + resolution: {integrity: sha512-be6nKaUhdRmr2OQD6kJS6C+d1QTf6ibkp5fRSqs3x+lDuZOnyCh4/f/xg6ShKh2vtf+Bidwc2ftuxyEWx3A8SA==} + + '@cool-vue/vite-plugin@8.2.2': + resolution: {integrity: sha512-Fk3lKXXZJdP72Fnd9ndv95uN6kTQurvEHikU9AjD4Y6fLAgY4z+ljfGd3yRmMZWdN+bqD6OHVIiOm4ZOsAMAyQ==} + + '@ctrl/tinycolor@3.6.1': + resolution: {integrity: sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==} + engines: {node: '>=10'} + + '@element-plus/icons-vue@2.3.1': + resolution: {integrity: sha512-XxVUZv48RZAd87ucGS48jPf6pKu0yV5UCg9f4FFwtrYxXOwWuVJo6wOvSLKEoMQKjv8GsX/mhP6UsC1lRwbUWg==} + peerDependencies: + vue: ^3.2.0 + + '@esbuild/aix-ppc64@0.21.5': + resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.21.5': + resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.21.5': + resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.21.5': + resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.21.5': + resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.21.5': + resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.21.5': + resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.21.5': + resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.21.5': + resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.21.5': + resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.21.5': + resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.21.5': + resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.21.5': + resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.21.5': + resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.21.5': + resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.21.5': + resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.21.5': + resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-x64@0.21.5': + resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-x64@0.21.5': + resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + + '@esbuild/sunos-x64@0.21.5': + resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.21.5': + resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.21.5': + resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.21.5': + resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + + '@eslint-community/eslint-utils@4.7.0': + resolution: {integrity: sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + + '@eslint-community/regexpp@4.12.1': + resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + '@eslint/config-array@0.21.0': + resolution: {integrity: sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/config-helpers@0.3.0': + resolution: {integrity: sha512-ViuymvFmcJi04qdZeDc2whTHryouGcDlaxPqarTD0ZE10ISpxGUVZGZDx4w01upyIynL3iu6IXH2bS1NhclQMw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/core@0.15.1': + resolution: {integrity: sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/eslintrc@3.3.1': + resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/js@9.31.0': + resolution: {integrity: sha512-LOm5OVt7D4qiKCqoiPbA7LWmI+tbw1VbTUowBcUMgQSuM6poJufkFkYDcQpo5KfgD39TnNySV26QjOh7VFpSyw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/object-schema@2.1.6': + resolution: {integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/plugin-kit@0.3.4': + resolution: {integrity: sha512-Ul5l+lHEcw3L5+k8POx6r74mxEYKG5kOb6Xpy2gCRW6zweT6TEhAf8vhxGgjhqrd/VO/Dirhsb+1hNpD1ue9hw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@floating-ui/core@1.7.2': + resolution: {integrity: sha512-wNB5ooIKHQc+Kui96jE/n69rHFWAVoxn5CAzL1Xdd8FG03cgY3MLO+GF9U3W737fYDSgPWA6MReKhBQBop6Pcw==} + + '@floating-ui/dom@1.7.2': + resolution: {integrity: sha512-7cfaOQuCS27HD7DX+6ib2OrnW+b4ZBwDNnCcT0uTyidcmyWb03FnQqJybDBoCnpdxwBSfA94UAYlRCt7mV+TbA==} + + '@floating-ui/utils@0.2.10': + resolution: {integrity: sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==} + + '@humanfs/core@0.19.1': + resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} + engines: {node: '>=18.18.0'} + + '@humanfs/node@0.16.6': + resolution: {integrity: sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==} + engines: {node: '>=18.18.0'} + + '@humanwhocodes/module-importer@1.0.1': + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + + '@humanwhocodes/retry@0.3.1': + resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==} + engines: {node: '>=18.18'} + + '@humanwhocodes/retry@0.4.3': + resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} + engines: {node: '>=18.18'} + + '@intlify/bundle-utils@10.0.1': + resolution: {integrity: sha512-WkaXfSevtpgtUR4t8K2M6lbR7g03mtOxFeh+vXp5KExvPqS12ppaRj1QxzwRuRI5VUto54A22BjKoBMLyHILWQ==} + engines: {node: '>= 18'} + peerDependencies: + petite-vue-i18n: '*' + vue-i18n: '*' + peerDependenciesMeta: + petite-vue-i18n: + optional: true + vue-i18n: + optional: true + + '@intlify/core-base@11.1.10': + resolution: {integrity: sha512-JhRb40hD93Vk0BgMgDc/xMIFtdXPHoytzeK6VafBNOj6bb6oUZrGamXkBKecMsmGvDQQaPRGG2zpa25VCw8pyw==} + engines: {node: '>= 16'} + + '@intlify/message-compiler@11.1.10': + resolution: {integrity: sha512-TABl3c8tSLWbcD+jkQTyBhrnW251dzqW39MPgEUCsd69Ua3ceoimsbIzvkcPzzZvt1QDxNkenMht+5//V3JvLQ==} + engines: {node: '>= 16'} + + '@intlify/shared@11.1.10': + resolution: {integrity: sha512-6ZW/f3Zzjxfa1Wh0tYQI5pLKUtU+SY7l70pEG+0yd0zjcsYcK0EBt6Fz30Dy0tZhEqemziQQy2aNU3GJzyrMUA==} + engines: {node: '>= 16'} + + '@intlify/unplugin-vue-i18n@6.0.8': + resolution: {integrity: sha512-Vvm3KhjE6TIBVUQAk37rBiaYy2M5OcWH0ZcI1XKEsOTeN1o0bErk+zeuXmcrcMc/73YggfI8RoxOUz9EB/69JQ==} + engines: {node: '>= 18'} + peerDependencies: + petite-vue-i18n: '*' + vue: ^3.2.25 + vue-i18n: '*' + peerDependenciesMeta: + petite-vue-i18n: + optional: true + vue-i18n: + optional: true + + '@intlify/vue-i18n-extensions@8.0.0': + resolution: {integrity: sha512-w0+70CvTmuqbskWfzeYhn0IXxllr6mU+IeM2MU0M+j9OW64jkrvqY+pYFWrUnIIC9bEdij3NICruicwd5EgUuQ==} + engines: {node: '>= 18'} + peerDependencies: + '@intlify/shared': ^9.0.0 || ^10.0.0 || ^11.0.0 + '@vue/compiler-dom': ^3.0.0 + vue: ^3.0.0 + vue-i18n: ^9.0.0 || ^10.0.0 || ^11.0.0 + peerDependenciesMeta: + '@intlify/shared': + optional: true + '@vue/compiler-dom': + optional: true + vue: + optional: true + vue-i18n: + optional: true + + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + + '@jridgewell/gen-mapping@0.3.12': + resolution: {integrity: sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/source-map@0.3.10': + resolution: {integrity: sha512-0pPkgz9dY+bijgistcTTJ5mR+ocqRXLuhXHYdzoMmmoJ2C9S46RCm2GMUbatPEUK9Yjy26IrAy8D/M00lLkv+Q==} + + '@jridgewell/sourcemap-codec@1.5.4': + resolution: {integrity: sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==} + + '@jridgewell/trace-mapping@0.3.29': + resolution: {integrity: sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==} + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@one-ini/wasm@0.1.1': + resolution: {integrity: sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==} + + '@parcel/watcher-android-arm64@2.5.1': + resolution: {integrity: sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [android] + + '@parcel/watcher-darwin-arm64@2.5.1': + resolution: {integrity: sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [darwin] + + '@parcel/watcher-darwin-x64@2.5.1': + resolution: {integrity: sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [darwin] + + '@parcel/watcher-freebsd-x64@2.5.1': + resolution: {integrity: sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [freebsd] + + '@parcel/watcher-linux-arm-glibc@2.5.1': + resolution: {integrity: sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==} + engines: {node: '>= 10.0.0'} + cpu: [arm] + os: [linux] + libc: [glibc] + + '@parcel/watcher-linux-arm-musl@2.5.1': + resolution: {integrity: sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==} + engines: {node: '>= 10.0.0'} + cpu: [arm] + os: [linux] + libc: [musl] + + '@parcel/watcher-linux-arm64-glibc@2.5.1': + resolution: {integrity: sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@parcel/watcher-linux-arm64-musl@2.5.1': + resolution: {integrity: sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@parcel/watcher-linux-x64-glibc@2.5.1': + resolution: {integrity: sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@parcel/watcher-linux-x64-musl@2.5.1': + resolution: {integrity: sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [linux] + libc: [musl] + + '@parcel/watcher-win32-arm64@2.5.1': + resolution: {integrity: sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [win32] + + '@parcel/watcher-win32-ia32@2.5.1': + resolution: {integrity: sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==} + engines: {node: '>= 10.0.0'} + cpu: [ia32] + os: [win32] + + '@parcel/watcher-win32-x64@2.5.1': + resolution: {integrity: sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [win32] + + '@parcel/watcher@2.5.1': + resolution: {integrity: sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==} + engines: {node: '>= 10.0.0'} + + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + + '@pkgr/core@0.2.9': + resolution: {integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + + '@polka/url@1.0.0-next.29': + resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==} + + '@rolldown/pluginutils@1.0.0-beta.29': + resolution: {integrity: sha512-NIJgOsMjbxAXvoGq/X0gD7VPMQ8j9g0BiDaNjVNVjvl+iKXxL3Jre0v31RmBYeLEmkbj2s02v8vFTbUXi5XS2Q==} + + '@rollup/pluginutils@5.2.0': + resolution: {integrity: sha512-qWJ2ZTbmumwiLFomfzTyt5Kng4hwPi9rwCYN4SHb6eaRU1KNO4ccxINHr/VhH4GgPlt1XfSTLX2LBTme8ne4Zw==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/rollup-android-arm-eabi@4.45.1': + resolution: {integrity: sha512-NEySIFvMY0ZQO+utJkgoMiCAjMrGvnbDLHvcmlA33UXJpYBCvlBEbMMtV837uCkS+plG2umfhn0T5mMAxGrlRA==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.45.1': + resolution: {integrity: sha512-ujQ+sMXJkg4LRJaYreaVx7Z/VMgBBd89wGS4qMrdtfUFZ+TSY5Rs9asgjitLwzeIbhwdEhyj29zhst3L1lKsRQ==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.45.1': + resolution: {integrity: sha512-FSncqHvqTm3lC6Y13xncsdOYfxGSLnP+73k815EfNmpewPs+EyM49haPS105Rh4aF5mJKywk9X0ogzLXZzN9lA==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.45.1': + resolution: {integrity: sha512-2/vVn/husP5XI7Fsf/RlhDaQJ7x9zjvC81anIVbr4b/f0xtSmXQTFcGIQ/B1cXIYM6h2nAhJkdMHTnD7OtQ9Og==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.45.1': + resolution: {integrity: sha512-4g1kaDxQItZsrkVTdYQ0bxu4ZIQ32cotoQbmsAnW1jAE4XCMbcBPDirX5fyUzdhVCKgPcrwWuucI8yrVRBw2+g==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.45.1': + resolution: {integrity: sha512-L/6JsfiL74i3uK1Ti2ZFSNsp5NMiM4/kbbGEcOCps99aZx3g8SJMO1/9Y0n/qKlWZfn6sScf98lEOUe2mBvW9A==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.45.1': + resolution: {integrity: sha512-RkdOTu2jK7brlu+ZwjMIZfdV2sSYHK2qR08FUWcIoqJC2eywHbXr0L8T/pONFwkGukQqERDheaGTeedG+rra6Q==} + cpu: [arm] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-arm-musleabihf@4.45.1': + resolution: {integrity: sha512-3kJ8pgfBt6CIIr1o+HQA7OZ9mp/zDk3ctekGl9qn/pRBgrRgfwiffaUmqioUGN9hv0OHv2gxmvdKOkARCtRb8Q==} + cpu: [arm] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-arm64-gnu@4.45.1': + resolution: {integrity: sha512-k3dOKCfIVixWjG7OXTCOmDfJj3vbdhN0QYEqB+OuGArOChek22hn7Uy5A/gTDNAcCy5v2YcXRJ/Qcnm4/ma1xw==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-arm64-musl@4.45.1': + resolution: {integrity: sha512-PmI1vxQetnM58ZmDFl9/Uk2lpBBby6B6rF4muJc65uZbxCs0EA7hhKCk2PKlmZKuyVSHAyIw3+/SiuMLxKxWog==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-loongarch64-gnu@4.45.1': + resolution: {integrity: sha512-9UmI0VzGmNJ28ibHW2GpE2nF0PBQqsyiS4kcJ5vK+wuwGnV5RlqdczVocDSUfGX/Na7/XINRVoUgJyFIgipoRg==} + cpu: [loong64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-powerpc64le-gnu@4.45.1': + resolution: {integrity: sha512-7nR2KY8oEOUTD3pBAxIBBbZr0U7U+R9HDTPNy+5nVVHDXI4ikYniH1oxQz9VoB5PbBU1CZuDGHkLJkd3zLMWsg==} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-riscv64-gnu@4.45.1': + resolution: {integrity: sha512-nlcl3jgUultKROfZijKjRQLUu9Ma0PeNv/VFHkZiKbXTBQXhpytS8CIj5/NfBeECZtY2FJQubm6ltIxm/ftxpw==} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-riscv64-musl@4.45.1': + resolution: {integrity: sha512-HJV65KLS51rW0VY6rvZkiieiBnurSzpzore1bMKAhunQiECPuxsROvyeaot/tcK3A3aGnI+qTHqisrpSgQrpgA==} + cpu: [riscv64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-s390x-gnu@4.45.1': + resolution: {integrity: sha512-NITBOCv3Qqc6hhwFt7jLV78VEO/il4YcBzoMGGNxznLgRQf43VQDae0aAzKiBeEPIxnDrACiMgbqjuihx08OOw==} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-x64-gnu@4.45.1': + resolution: {integrity: sha512-+E/lYl6qu1zqgPEnTrs4WysQtvc/Sh4fC2nByfFExqgYrqkKWp1tWIbe+ELhixnenSpBbLXNi6vbEEJ8M7fiHw==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-x64-musl@4.45.1': + resolution: {integrity: sha512-a6WIAp89p3kpNoYStITT9RbTbTnqarU7D8N8F2CV+4Cl9fwCOZraLVuVFvlpsW0SbIiYtEnhCZBPLoNdRkjQFw==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@rollup/rollup-win32-arm64-msvc@4.45.1': + resolution: {integrity: sha512-T5Bi/NS3fQiJeYdGvRpTAP5P02kqSOpqiopwhj0uaXB6nzs5JVi2XMJb18JUSKhCOX8+UE1UKQufyD6Or48dJg==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.45.1': + resolution: {integrity: sha512-lxV2Pako3ujjuUe9jiU3/s7KSrDfH6IgTSQOnDWr9aJ92YsFd7EurmClK0ly/t8dzMkDtd04g60WX6yl0sGfdw==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.45.1': + resolution: {integrity: sha512-M/fKi4sasCdM8i0aWJjCSFm2qEnYRR8AMLG2kxp6wD13+tMGA4Z1tVAuHkNRjud5SW2EM3naLuK35w9twvf6aA==} + cpu: [x64] + os: [win32] + + '@rushstack/eslint-patch@1.12.0': + resolution: {integrity: sha512-5EwMtOqvJMMa3HbmxLlF74e+3/HhwBTMcvt3nqVJgGCozO6hzIPOBlwm8mGVNR9SN2IJpxSnlxczyDjcn7qIyw==} + + '@sec-ant/readable-stream@0.4.1': + resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==} + + '@sindresorhus/merge-streams@4.0.0': + resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==} + engines: {node: '>=18'} + + '@sxzz/popperjs-es@2.11.7': + resolution: {integrity: sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ==} + + '@transloadit/prettier-bytes@0.0.7': + resolution: {integrity: sha512-VeJbUb0wEKbcwaSlj5n+LscBl9IPgLPkHVGBkh00cztv6X4L/TJXK58LzFuBKX7/GAfiGhIwH67YTLTlzvIzBA==} + + '@trysound/sax@0.2.0': + resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} + engines: {node: '>=10.13.0'} + + '@tsconfig/node20@20.1.6': + resolution: {integrity: sha512-sz+Hqx9zwZDpZIV871WSbUzSqNIsXzghZydypnfgzPKLltVJfkINfUeTct31n/tTSa9ZE1ZOfKdRre1uHHquYQ==} + + '@types/estree@1.0.8': + resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + + '@types/event-emitter@0.3.5': + resolution: {integrity: sha512-zx2/Gg0Eg7gwEiOIIh5w9TrhKKTeQh7CPCOPNc0el4pLSwzebA8SmnHwZs2dWlLONvyulykSwGSQxQHLhjGLvQ==} + + '@types/file-saver@2.0.7': + resolution: {integrity: sha512-dNKVfHd/jk0SkR/exKGj2ggkB45MAkzvWCaqLUUgkyjITkGNzH8H+yUwr+BLJUBjZOe9w8X3wgmXhZDRg1ED6A==} + + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + + '@types/lodash-es@4.17.12': + resolution: {integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==} + + '@types/lodash@4.17.20': + resolution: {integrity: sha512-H3MHACvFUEiujabxhaI/ImO6gUrd8oOurg7LQtS7mbwIXA/cUqWrvBsaeJ23aZEPk1TAYkurjfMbSELfoCXlGA==} + + '@types/mockjs@1.0.10': + resolution: {integrity: sha512-SXgrhajHG7boLv6oU93CcmdDm0HYRiceuz6b+7z+/2lCJPTWDv0V5YiwFHT2ejE4bQqgSXQiVPQYPWv7LGsK1g==} + + '@types/node@20.19.9': + resolution: {integrity: sha512-cuVNgarYWZqxRJDQHEB58GEONhOK79QVR/qYx4S7kcUObQvUwvFnYxJuuHUKm2aieN9X3yZB4LZsuYNU1Qphsw==} + + '@types/nprogress@0.2.3': + resolution: {integrity: sha512-k7kRA033QNtC+gLc4VPlfnue58CM1iQLgn1IMAU8VPHGOj7oIHPp9UlhedEnD/Gl8evoCjwkZjlBORtZ3JByUA==} + + '@types/store@2.0.5': + resolution: {integrity: sha512-5NmTKe3GWdOaykzq7no+Ahf6mafJu0oLc9JNhJ3E26+0oFvd6GnksnZQpMXcH526mfG4xDYjFiKzyDL51PzeWQ==} + + '@types/web-bluetooth@0.0.16': + resolution: {integrity: sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==} + + '@types/web-bluetooth@0.0.21': + resolution: {integrity: sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==} + + '@typescript-eslint/eslint-plugin@8.38.0': + resolution: {integrity: sha512-CPoznzpuAnIOl4nhj4tRr4gIPj5AfKgkiJmGQDaq+fQnRJTYlcBjbX3wbciGmpoPf8DREufuPRe1tNMZnGdanA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + '@typescript-eslint/parser': ^8.38.0 + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' + + '@typescript-eslint/parser@8.38.0': + resolution: {integrity: sha512-Zhy8HCvBUEfBECzIl1PKqF4p11+d0aUJS1GeUiuqK9WmOug8YCmC4h4bjyBvMyAMI9sbRczmrYL5lKg/YMbrcQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' + + '@typescript-eslint/project-service@8.38.0': + resolution: {integrity: sha512-dbK7Jvqcb8c9QfH01YB6pORpqX1mn5gDZc9n63Ak/+jD67oWXn3Gs0M6vddAN+eDXBCS5EmNWzbSxsn9SzFWWg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <5.9.0' + + '@typescript-eslint/scope-manager@8.38.0': + resolution: {integrity: sha512-WJw3AVlFFcdT9Ri1xs/lg8LwDqgekWXWhH3iAF+1ZM+QPd7oxQ6jvtW/JPwzAScxitILUIFs0/AnQ/UWHzbATQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/tsconfig-utils@8.38.0': + resolution: {integrity: sha512-Lum9RtSE3EroKk/bYns+sPOodqb2Fv50XOl/gMviMKNvanETUuUcC9ObRbzrJ4VSd2JalPqgSAavwrPiPvnAiQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <5.9.0' + + '@typescript-eslint/type-utils@8.38.0': + resolution: {integrity: sha512-c7jAvGEZVf0ao2z+nnz8BUaHZD09Agbh+DY7qvBQqLiz8uJzRgVPj5YvOh8I8uEiH8oIUGIfHzMwUcGVco/SJg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' + + '@typescript-eslint/types@8.38.0': + resolution: {integrity: sha512-wzkUfX3plUqij4YwWaJyqhiPE5UCRVlFpKn1oCRn2O1bJ592XxWJj8ROQ3JD5MYXLORW84063z3tZTb/cs4Tyw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/typescript-estree@8.38.0': + resolution: {integrity: sha512-fooELKcAKzxux6fA6pxOflpNS0jc+nOQEEOipXFNjSlBS6fqrJOVY/whSn70SScHrcJ2LDsxWrneFoWYSVfqhQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <5.9.0' + + '@typescript-eslint/utils@8.38.0': + resolution: {integrity: sha512-hHcMA86Hgt+ijJlrD8fX0j1j8w4C92zue/8LOPAFioIno+W0+L7KqE8QZKCcPGc/92Vs9x36w/4MPTJhqXdyvg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' + + '@typescript-eslint/visitor-keys@8.38.0': + resolution: {integrity: sha512-pWrTcoFNWuwHlA9CvlfSsGWs14JxfN1TH25zM5L7o0pRLhsoZkDnTsXfQRJBEWJoV5DL0jf+Z+sxiud+K0mq1g==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@uppy/companion-client@2.2.2': + resolution: {integrity: sha512-5mTp2iq97/mYSisMaBtFRry6PTgZA6SIL7LePteOV5x0/DxKfrZW3DEiQERJmYpHzy7k8johpm2gHnEKto56Og==} + + '@uppy/core@2.3.4': + resolution: {integrity: sha512-iWAqppC8FD8mMVqewavCz+TNaet6HPXitmGXpGGREGrakZ4FeuWytVdrelydzTdXx6vVKkOmI2FLztGg73sENQ==} + + '@uppy/store-default@2.1.1': + resolution: {integrity: sha512-xnpTxvot2SeAwGwbvmJ899ASk5tYXhmZzD/aCFsXePh/v8rNvR2pKlcQUH7cF/y4baUGq3FHO/daKCok/mpKqQ==} + + '@uppy/utils@4.1.3': + resolution: {integrity: sha512-nTuMvwWYobnJcytDO3t+D6IkVq/Qs4Xv3vyoEZ+Iaf8gegZP+rEyoaFT2CK5XLRMienPyqRqNbIfRuFaOWSIFw==} + + '@uppy/xhr-upload@2.1.3': + resolution: {integrity: sha512-YWOQ6myBVPs+mhNjfdWsQyMRWUlrDLMoaG7nvf/G6Y3GKZf8AyjFDjvvJ49XWQ+DaZOftGkHmF1uh/DBeGivJQ==} + peerDependencies: + '@uppy/core': ^2.3.3 + + '@vitejs/plugin-vue-jsx@4.2.0': + resolution: {integrity: sha512-DSTrmrdLp+0LDNF77fqrKfx7X0ErRbOcUAgJL/HbSesqQwoUvUQ4uYQqaex+rovqgGcoPqVk+AwUh3v9CuiYIw==} + engines: {node: ^18.0.0 || >=20.0.0} + peerDependencies: + vite: ^5.0.0 || ^6.0.0 + vue: ^3.0.0 + + '@vitejs/plugin-vue@5.2.4': + resolution: {integrity: sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==} + engines: {node: ^18.0.0 || >=20.0.0} + peerDependencies: + vite: ^5.0.0 || ^6.0.0 + vue: ^3.2.25 + + '@volar/language-core@2.4.15': + resolution: {integrity: sha512-3VHw+QZU0ZG9IuQmzT68IyN4hZNd9GchGPhbD9+pa8CVv7rnoOZwo7T8weIbrRmihqy3ATpdfXFnqRrfPVK6CA==} + + '@volar/source-map@2.4.15': + resolution: {integrity: sha512-CPbMWlUN6hVZJYGcU/GSoHu4EnCHiLaXI9n8c9la6RaI9W5JHX+NqG+GSQcB0JdC2FIBLdZJwGsfKyBB71VlTg==} + + '@volar/typescript@2.4.15': + resolution: {integrity: sha512-2aZ8i0cqPGjXb4BhkMsPYDkkuc2ZQ6yOpqwAuNwUoncELqoy5fRgOQtLR9gB0g902iS0NAkvpIzs27geVyVdPg==} + + '@vue/babel-helper-vue-transform-on@1.4.0': + resolution: {integrity: sha512-mCokbouEQ/ocRce/FpKCRItGo+013tHg7tixg3DUNS+6bmIchPt66012kBMm476vyEIJPafrvOf4E5OYj3shSw==} + + '@vue/babel-plugin-jsx@1.4.0': + resolution: {integrity: sha512-9zAHmwgMWlaN6qRKdrg1uKsBKHvnUU+Py+MOCTuYZBoZsopa90Di10QRjB+YPnVss0BZbG/H5XFwJY1fTxJWhA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + peerDependenciesMeta: + '@babel/core': + optional: true + + '@vue/babel-plugin-resolve-type@1.4.0': + resolution: {integrity: sha512-4xqDRRbQQEWHQyjlYSgZsWj44KfiF6D+ktCuXyZ8EnVDYV3pztmXJDf1HveAjUAXxAnR8daCQT51RneWWxtTyQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@vue/compiler-core@3.5.18': + resolution: {integrity: sha512-3slwjQrrV1TO8MoXgy3aynDQ7lslj5UqDxuHnrzHtpON5CBinhWjJETciPngpin/T3OuW3tXUf86tEurusnztw==} + + '@vue/compiler-dom@3.5.18': + resolution: {integrity: sha512-RMbU6NTU70++B1JyVJbNbeFkK+A+Q7y9XKE2EM4NLGm2WFR8x9MbAtWxPPLdm0wUkuZv9trpwfSlL6tjdIa1+A==} + + '@vue/compiler-sfc@3.5.18': + resolution: {integrity: sha512-5aBjvGqsWs+MoxswZPoTB9nSDb3dhd1x30xrrltKujlCxo48j8HGDNj3QPhF4VIS0VQDUrA1xUfp2hEa+FNyXA==} + + '@vue/compiler-ssr@3.5.18': + resolution: {integrity: sha512-xM16Ak7rSWHkM3m22NlmcdIM+K4BMyFARAfV9hYFl+SFuRzrZ3uGMNW05kA5pmeMa0X9X963Kgou7ufdbpOP9g==} + + '@vue/compiler-vue2@2.7.16': + resolution: {integrity: sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==} + + '@vue/devtools-api@6.6.4': + resolution: {integrity: sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==} + + '@vue/devtools-core@7.7.7': + resolution: {integrity: sha512-9z9TLbfC+AjAi1PQyWX+OErjIaJmdFlbDHcD+cAMYKY6Bh5VlsAtCeGyRMrXwIlMEQPukvnWt3gZBLwTAIMKzQ==} + peerDependencies: + vue: ^3.0.0 + + '@vue/devtools-kit@7.7.7': + resolution: {integrity: sha512-wgoZtxcTta65cnZ1Q6MbAfePVFxfM+gq0saaeytoph7nEa7yMXoi6sCPy4ufO111B9msnw0VOWjPEFCXuAKRHA==} + + '@vue/devtools-shared@7.7.7': + resolution: {integrity: sha512-+udSj47aRl5aKb0memBvcUG9koarqnxNM5yjuREvqwK6T3ap4mn3Zqqc17QrBFTqSMjr3HK1cvStEZpMDpfdyw==} + + '@vue/eslint-config-prettier@10.2.0': + resolution: {integrity: sha512-GL3YBLwv/+b86yHcNNfPJxOTtVFJ4Mbc9UU3zR+KVoG7SwGTjPT+32fXamscNumElhcpXW3mT0DgzS9w32S7Bw==} + peerDependencies: + eslint: '>= 8.21.0' + prettier: '>= 3.0.0' + + '@vue/eslint-config-typescript@14.6.0': + resolution: {integrity: sha512-UpiRY/7go4Yps4mYCjkvlIbVWmn9YvPGQDxTAlcKLphyaD77LjIu3plH4Y9zNT0GB4f3K5tMmhhtRhPOgrQ/bQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^9.10.0 + eslint-plugin-vue: ^9.28.0 || ^10.0.0 + typescript: '>=4.8.4' + peerDependenciesMeta: + typescript: + optional: true + + '@vue/language-core@2.2.12': + resolution: {integrity: sha512-IsGljWbKGU1MZpBPN+BvPAdr55YPkj2nB/TBNGNC32Vy2qLG25DYu/NBN2vNtZqdRbTRjaoYrahLrToim2NanA==} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@vue/reactivity@3.5.18': + resolution: {integrity: sha512-x0vPO5Imw+3sChLM5Y+B6G1zPjwdOri9e8V21NnTnlEvkxatHEH5B5KEAJcjuzQ7BsjGrKtfzuQ5eQwXh8HXBg==} + + '@vue/runtime-core@3.5.18': + resolution: {integrity: sha512-DUpHa1HpeOQEt6+3nheUfqVXRog2kivkXHUhoqJiKR33SO4x+a5uNOMkV487WPerQkL0vUuRvq/7JhRgLW3S+w==} + + '@vue/runtime-dom@3.5.18': + resolution: {integrity: sha512-YwDj71iV05j4RnzZnZtGaXwPoUWeRsqinblgVJwR8XTXYZ9D5PbahHQgsbmzUvCWNF6x7siQ89HgnX5eWkr3mw==} + + '@vue/server-renderer@3.5.18': + resolution: {integrity: sha512-PvIHLUoWgSbDG7zLHqSqaCoZvHi6NNmfVFOqO+OnwvqMz/tqQr3FuGWS8ufluNddk7ZLBJYMrjcw1c6XzR12mA==} + peerDependencies: + vue: 3.5.18 + + '@vue/shared@3.5.18': + resolution: {integrity: sha512-cZy8Dq+uuIXbxCZpuLd2GJdeSO/lIzIspC2WtkqIpje5QyFbvLaI5wZtdUjLHjGZrlVX6GilejatWwVYYRc8tA==} + + '@vue/test-utils@2.4.6': + resolution: {integrity: sha512-FMxEjOpYNYiFe0GkaHsnJPXFHxQ6m4t8vI/ElPGpMWxZKpmRvQ33OIrvRXemy6yha03RxhOlQuy+gZMC3CQSow==} + + '@vue/tsconfig@0.5.1': + resolution: {integrity: sha512-VcZK7MvpjuTPx2w6blwnwZAu5/LgBUtejFOi3pPGQFXQN5Ela03FUtd2Qtg4yWGGissVL0dr6Ro1LfOFh+PCuQ==} + + '@vueuse/core@12.8.2': + resolution: {integrity: sha512-HbvCmZdzAu3VGi/pWYm5Ut+Kd9mn1ZHnn4L5G8kOQTPs/IwIAmJoBrmYk2ckLArgMXZj0AW3n5CAejLUO+PhdQ==} + + '@vueuse/core@9.13.0': + resolution: {integrity: sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==} + + '@vueuse/metadata@12.8.2': + resolution: {integrity: sha512-rAyLGEuoBJ/Il5AmFHiziCPdQzRt88VxR+Y/A/QhJ1EWtWqPBBAxTAFaSkviwEuOEZNtW8pvkPgoCZQ+HxqW1A==} + + '@vueuse/metadata@9.13.0': + resolution: {integrity: sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ==} + + '@vueuse/shared@12.8.2': + resolution: {integrity: sha512-dznP38YzxZoNloI0qpEfpkms8knDtaoQ6Y/sfS0L7Yki4zh40LFHEhur0odJC6xTHG5dxWVPiUWBXn+wCG2s5w==} + + '@vueuse/shared@9.13.0': + resolution: {integrity: sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==} + + '@wangeditor/basic-modules@1.1.7': + resolution: {integrity: sha512-cY9CPkLJaqF05STqfpZKWG4LpxTMeGSIIF1fHvfm/mz+JXatCagjdkbxdikOuKYlxDdeqvOeBmsUBItufDLXZg==} + peerDependencies: + '@wangeditor/core': 1.x + dom7: ^3.0.0 + lodash.throttle: ^4.1.1 + nanoid: ^3.2.0 + slate: ^0.72.0 + snabbdom: ^3.1.0 + + '@wangeditor/code-highlight@1.0.3': + resolution: {integrity: sha512-iazHwO14XpCuIWJNTQTikqUhGKyqj+dUNWJ9288Oym9M2xMVHvnsOmDU2sgUDWVy+pOLojReMPgXCsvvNlOOhw==} + peerDependencies: + '@wangeditor/core': 1.x + dom7: ^3.0.0 + slate: ^0.72.0 + snabbdom: ^3.1.0 + + '@wangeditor/core@1.1.19': + resolution: {integrity: sha512-KevkB47+7GhVszyYF2pKGKtCSj/YzmClsD03C3zTt+9SR2XWT5T0e3yQqg8baZpcMvkjs1D8Dv4fk8ok/UaS2Q==} + peerDependencies: + '@uppy/core': ^2.1.1 + '@uppy/xhr-upload': ^2.0.3 + dom7: ^3.0.0 + is-hotkey: ^0.2.0 + lodash.camelcase: ^4.3.0 + lodash.clonedeep: ^4.5.0 + lodash.debounce: ^4.0.8 + lodash.foreach: ^4.5.0 + lodash.isequal: ^4.5.0 + lodash.throttle: ^4.1.1 + lodash.toarray: ^4.4.0 + nanoid: ^3.2.0 + slate: ^0.72.0 + snabbdom: ^3.1.0 + + '@wangeditor/editor-for-vue@5.1.12': + resolution: {integrity: sha512-0Ds3D8I+xnpNWezAeO7HmPRgTfUxHLMd9JKcIw+QzvSmhC5xUHbpCcLU+KLmeBKTR/zffnS5GQo6qi3GhTMJWQ==} + peerDependencies: + '@wangeditor/editor': '>=5.1.0' + vue: ^3.0.5 + + '@wangeditor/editor@5.1.23': + resolution: {integrity: sha512-0RxfeVTuK1tktUaPROnCoFfaHVJpRAIE2zdS0mpP+vq1axVQpLjM8+fCvKzqYIkH0Pg+C+44hJpe3VVroSkEuQ==} + + '@wangeditor/list-module@1.0.5': + resolution: {integrity: sha512-uDuYTP6DVhcYf7mF1pTlmNn5jOb4QtcVhYwSSAkyg09zqxI1qBqsfUnveeDeDqIuptSJhkh81cyxi+MF8sEPOQ==} + peerDependencies: + '@wangeditor/core': 1.x + dom7: ^3.0.0 + slate: ^0.72.0 + snabbdom: ^3.1.0 + + '@wangeditor/table-module@1.1.4': + resolution: {integrity: sha512-5saanU9xuEocxaemGdNi9t8MCDSucnykEC6jtuiT72kt+/Hhh4nERYx1J20OPsTCCdVr7hIyQenFD1iSRkIQ6w==} + peerDependencies: + '@wangeditor/core': 1.x + dom7: ^3.0.0 + lodash.isequal: ^4.5.0 + lodash.throttle: ^4.1.1 + nanoid: ^3.2.0 + slate: ^0.72.0 + snabbdom: ^3.1.0 + + '@wangeditor/upload-image-module@1.0.2': + resolution: {integrity: sha512-z81lk/v71OwPDYeQDxj6cVr81aDP90aFuywb8nPD6eQeECtOymrqRODjpO6VGvCVxVck8nUxBHtbxKtjgcwyiA==} + peerDependencies: + '@uppy/core': ^2.0.3 + '@uppy/xhr-upload': ^2.0.3 + '@wangeditor/basic-modules': 1.x + '@wangeditor/core': 1.x + dom7: ^3.0.0 + lodash.foreach: ^4.5.0 + slate: ^0.72.0 + snabbdom: ^3.1.0 + + '@wangeditor/video-module@1.1.4': + resolution: {integrity: sha512-ZdodDPqKQrgx3IwWu4ZiQmXI8EXZ3hm2/fM6E3t5dB8tCaIGWQZhmqd6P5knfkRAd3z2+YRSRbxOGfoRSp/rLg==} + peerDependencies: + '@uppy/core': ^2.1.4 + '@uppy/xhr-upload': ^2.0.7 + '@wangeditor/core': 1.x + dom7: ^3.0.0 + nanoid: ^3.2.0 + slate: ^0.72.0 + snabbdom: ^3.1.0 + + abbrev@2.0.0: + resolution: {integrity: sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn@8.15.0: + resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} + engines: {node: '>=0.4.0'} + hasBin: true + + adler-32@1.3.1: + resolution: {integrity: sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==} + engines: {node: '>=0.8'} + + ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + + alien-signals@1.0.13: + resolution: {integrity: sha512-OGj9yyTnJEttvzhTUWuscOvtqxq5vrhF7vL9oS0xJ2mK0ItPYP1/y+vCFebfxoEyAz0++1AIwJ5CMr+Fk3nDmg==} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-regex@6.1.0: + resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} + engines: {node: '>=12'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + + any-promise@1.3.0: + resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} + + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + + arg@5.0.2: + resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + async-validator@4.2.5: + resolution: {integrity: sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==} + + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + + autoprefixer@10.4.21: + resolution: {integrity: sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==} + engines: {node: ^10 || ^12 || >=14} + hasBin: true + peerDependencies: + postcss: ^8.1.0 + + axios@1.11.0: + resolution: {integrity: sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + binary-extensions@2.3.0: + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} + engines: {node: '>=8'} + + birpc@2.5.0: + resolution: {integrity: sha512-VSWO/W6nNQdyP520F1mhf+Lc2f8pjGQOtoHHm7Ze8Go1kX7akpVIrtTa0fn+HB0QJEDVacl6aO08YE0PgXfdnQ==} + + boolbase@1.0.0: + resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} + + brace-expansion@1.1.12: + resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} + + brace-expansion@2.0.2: + resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + browserslist@4.25.1: + resolution: {integrity: sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + + bundle-name@4.1.0: + resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} + engines: {node: '>=18'} + + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + camelcase-css@2.0.1: + resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} + engines: {node: '>= 6'} + + caniuse-lite@1.0.30001727: + resolution: {integrity: sha512-pB68nIHmbN6L/4C6MH1DokyR3bYqFwjaSs/sWDHGj4CTcFtQUQMuJftVwWkXq7mNWOybD3KhUv3oWHoGxgP14Q==} + + cfb@1.2.2: + resolution: {integrity: sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==} + engines: {node: '>=0.8'} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + chardet@2.1.0: + resolution: {integrity: sha512-bNFETTG/pM5ryzQ9Ad0lJOTa6HWD/YsScAR3EnCPZRPlQh77JocYktSHOUHelyhm8IARL+o4c4F1bP5KVOjiRA==} + + chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} + engines: {node: '>= 8.10.0'} + + chokidar@4.0.3: + resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} + engines: {node: '>= 14.16.0'} + + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + + codepage@1.15.0: + resolution: {integrity: sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==} + engines: {node: '>=0.8'} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + + commander@10.0.1: + resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} + engines: {node: '>=14'} + + commander@2.20.3: + resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + + commander@4.1.1: + resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} + engines: {node: '>= 6'} + + commander@7.2.0: + resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} + engines: {node: '>= 10'} + + compute-scroll-into-view@1.0.20: + resolution: {integrity: sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg==} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + confbox@0.1.8: + resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} + + config-chain@1.1.13: + resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==} + + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + + copy-anything@3.0.5: + resolution: {integrity: sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==} + engines: {node: '>=12.13'} + + core-js@3.44.0: + resolution: {integrity: sha512-aFCtd4l6GvAXwVEh3XbbVqJGHDJt0OZRa+5ePGx3LLwi12WfexqQxcsohb2wgsa/92xtl19Hd66G/L+TaAxDMw==} + + crc-32@1.2.2: + resolution: {integrity: sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==} + engines: {node: '>=0.8'} + hasBin: true + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + css-select@5.2.2: + resolution: {integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==} + + css-tree@2.2.1: + resolution: {integrity: sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'} + + css-tree@2.3.1: + resolution: {integrity: sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} + + css-what@6.2.2: + resolution: {integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==} + engines: {node: '>= 6'} + + cssesc@3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + + csso@5.0.5: + resolution: {integrity: sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'} + + csstype@3.1.3: + resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + + d@1.0.2: + resolution: {integrity: sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==} + engines: {node: '>=0.12'} + + dayjs@1.11.13: + resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==} + + de-indent@1.0.2: + resolution: {integrity: sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==} + + debug@4.4.1: + resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + + default-browser-id@5.0.0: + resolution: {integrity: sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==} + engines: {node: '>=18'} + + default-browser@5.2.1: + resolution: {integrity: sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==} + engines: {node: '>=18'} + + define-lazy-prop@2.0.0: + resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} + engines: {node: '>=8'} + + define-lazy-prop@3.0.0: + resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==} + engines: {node: '>=12'} + + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + + detect-libc@1.0.3: + resolution: {integrity: sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==} + engines: {node: '>=0.10'} + hasBin: true + + didyoumean@1.2.2: + resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} + + dlv@1.1.3: + resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} + + dom-serializer@2.0.0: + resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} + + dom7@3.0.0: + resolution: {integrity: sha512-oNlcUdHsC4zb7Msx7JN3K0Nro1dzJ48knvBOnDPKJ2GV9wl1i5vydJZUSyOfrkKFDZEud/jBsTk92S/VGSAe/g==} + + domelementtype@2.3.0: + resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} + + domhandler@5.0.3: + resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} + engines: {node: '>= 4'} + + domutils@3.2.2: + resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + + echarts@5.6.0: + resolution: {integrity: sha512-oTbVTsXfKuEhxftHqL5xprgLoc0k7uScAwtryCgWF6hPYFLRwOUHiFmHGCBKP5NPFNkDVopOieyUqYGH8Fa3kA==} + + editorconfig@1.0.4: + resolution: {integrity: sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q==} + engines: {node: '>=14'} + hasBin: true + + electron-to-chromium@1.5.190: + resolution: {integrity: sha512-k4McmnB2091YIsdCgkS0fMVMPOJgxl93ltFzaryXqwip1AaxeDqKCGLxkXODDA5Ab/D+tV5EL5+aTx76RvLRxw==} + + element-plus@2.10.2: + resolution: {integrity: sha512-p2KiAa0jEGXrzdlTAfpiS7HQFAhla4gvx6H7RuDf+OO0uC3DGpolxvdHjFR8gt7+vaWyxQNcHa1sAdBkmjqlgA==} + peerDependencies: + vue: ^3.2.0 + + element-plus@2.10.4: + resolution: {integrity: sha512-UD4elWHrCnp1xlPhbXmVcaKFLCRaRAY6WWRwemGfGW3ceIjXm9fSYc9RNH3AiOEA6Ds1p9ZvhCs76CR9J8Vd+A==} + peerDependencies: + vue: ^3.2.0 + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + + entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + + error-stack-parser-es@0.1.5: + resolution: {integrity: sha512-xHku1X40RO+fO8yJ8Wh2f2rZWVjqyhb1zgq1yZ8aZRQkv6OOKhKWRUaht3eSCUbAOBaKIgM+ykwFLE+QUxgGeg==} + + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-object-atoms@1.1.1: + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + + es5-ext@0.10.64: + resolution: {integrity: sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==} + engines: {node: '>=0.10'} + + es6-iterator@2.0.3: + resolution: {integrity: sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==} + + es6-symbol@3.1.4: + resolution: {integrity: sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==} + engines: {node: '>=0.12'} + + esbuild@0.21.5: + resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} + engines: {node: '>=12'} + hasBin: true + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + escodegen@2.1.0: + resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==} + engines: {node: '>=6.0'} + hasBin: true + + eslint-config-prettier@10.1.8: + resolution: {integrity: sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==} + hasBin: true + peerDependencies: + eslint: '>=7.0.0' + + eslint-plugin-prettier@5.5.3: + resolution: {integrity: sha512-NAdMYww51ehKfDyDhv59/eIItUVzU0Io9H2E8nHNGKEeeqlnci+1gCvrHib6EmZdf6GxF+LCV5K7UC65Ezvw7w==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + '@types/eslint': '>=8.0.0' + eslint: '>=8.0.0' + eslint-config-prettier: '>= 7.0.0 <10.0.0 || >=10.1.0' + prettier: '>=3.0.0' + peerDependenciesMeta: + '@types/eslint': + optional: true + eslint-config-prettier: + optional: true + + eslint-plugin-vue@9.33.0: + resolution: {integrity: sha512-174lJKuNsuDIlLpjeXc5E2Tss8P44uIimAfGD0b90k0NoirJqpG7stLuU9Vp/9ioTOrQdWVREc4mRd1BD+CvGw==} + engines: {node: ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.2.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 + + eslint-scope@7.2.2: + resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-scope@8.4.0: + resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-visitor-keys@4.2.1: + resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint@9.31.0: + resolution: {integrity: sha512-QldCVh/ztyKJJZLr4jXNUByx3gR+TDYZCRXEktiZoUR3PGy4qCmSbkxcIle8GEwGpb5JBZazlaJ/CxLidXdEbQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + hasBin: true + peerDependencies: + jiti: '*' + peerDependenciesMeta: + jiti: + optional: true + + esniff@2.0.1: + resolution: {integrity: sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==} + engines: {node: '>=0.10'} + + espree@10.4.0: + resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + espree@9.6.1: + resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + + esquery@1.6.0: + resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} + engines: {node: '>=0.10'} + + esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + + estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + event-emitter@0.3.5: + resolution: {integrity: sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==} + + execa@9.6.0: + resolution: {integrity: sha512-jpWzZ1ZhwUmeWRhS7Qv3mhpOhLfwI+uAX4e5fOcXqwMR7EcJ0pj2kV1CVzHVMX/LphnKWD3LObjZCoJ71lKpHw==} + engines: {node: ^18.19.0 || >=20.5.0} + + ext@1.7.0: + resolution: {integrity: sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-diff@1.3.0: + resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} + + fast-glob@3.3.3: + resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} + engines: {node: '>=8.6.0'} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + + fastq@1.19.1: + resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} + + figures@6.1.0: + resolution: {integrity: sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==} + engines: {node: '>=18'} + + file-entry-cache@8.0.0: + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} + + file-saver@2.0.5: + resolution: {integrity: sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + flat-cache@4.0.1: + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} + + flatted@3.3.3: + resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} + + follow-redirects@1.15.9: + resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + + foreground-child@3.3.1: + resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} + engines: {node: '>=14'} + + form-data@4.0.4: + resolution: {integrity: sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==} + engines: {node: '>= 6'} + + frac@1.1.2: + resolution: {integrity: sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==} + engines: {node: '>=0.8'} + + fraction.js@4.3.7: + resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} + + fs-extra@10.1.0: + resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} + engines: {node: '>=12'} + + fs-extra@11.3.0: + resolution: {integrity: sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==} + engines: {node: '>=14.14'} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + + get-stream@9.0.1: + resolution: {integrity: sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==} + engines: {node: '>=18'} + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + glob@10.4.5: + resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} + hasBin: true + + globals@13.24.0: + resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} + engines: {node: '>=8'} + + globals@14.0.0: + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} + engines: {node: '>=18'} + + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + graphemer@1.4.0: + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + he@1.2.0: + resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} + hasBin: true + + hookable@5.5.3: + resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==} + + html-void-elements@2.0.1: + resolution: {integrity: sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A==} + + human-signals@8.0.1: + resolution: {integrity: sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==} + engines: {node: '>=18.18.0'} + + i18next@20.6.1: + resolution: {integrity: sha512-yCMYTMEJ9ihCwEQQ3phLo7I/Pwycf8uAx+sRHwwk5U9Aui/IZYgQRyMqXafQOw5QQ7DM1Z+WyEXWIqSuJHhG2A==} + + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + + ignore@7.0.5: + resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} + engines: {node: '>= 4'} + + immer@9.0.21: + resolution: {integrity: sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==} + + immutable@5.1.3: + resolution: {integrity: sha512-+chQdDfvscSF1SJqv2gn4SRO2ZyS3xL3r7IW/wWEEzrzLisnOlKiQu5ytC/BVNcS15C39WT2Hg/bjKjDMcu+zg==} + + import-fresh@3.3.1: + resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} + engines: {node: '>=6'} + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + ini@1.3.8: + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + + is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + + is-core-module@2.16.1: + resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} + engines: {node: '>= 0.4'} + + is-docker@2.2.1: + resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} + engines: {node: '>=8'} + hasBin: true + + is-docker@3.0.0: + resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + hasBin: true + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-hotkey@0.2.0: + resolution: {integrity: sha512-UknnZK4RakDmTgz4PI1wIph5yxSs/mvChWs9ifnlXsKuXgWmOkY/hAE0H/k2MIqH0RlRye0i1oC07MCRSD28Mw==} + + is-inside-container@1.0.0: + resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} + engines: {node: '>=14.16'} + hasBin: true + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-plain-obj@4.1.0: + resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} + engines: {node: '>=12'} + + is-plain-object@5.0.0: + resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==} + engines: {node: '>=0.10.0'} + + is-stream@4.0.1: + resolution: {integrity: sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==} + engines: {node: '>=18'} + + is-unicode-supported@2.1.0: + resolution: {integrity: sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==} + engines: {node: '>=18'} + + is-url@1.2.4: + resolution: {integrity: sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==} + + is-what@4.1.16: + resolution: {integrity: sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==} + engines: {node: '>=12.13'} + + is-wsl@2.2.0: + resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} + engines: {node: '>=8'} + + is-wsl@3.1.0: + resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==} + engines: {node: '>=16'} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + jackspeak@3.4.3: + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + + jiti@1.21.7: + resolution: {integrity: sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==} + hasBin: true + + js-beautify@1.15.4: + resolution: {integrity: sha512-9/KXeZUKKJwqCXUdBxFJ3vPh467OCckSBmYDwSK/EtV090K+iMJ7zx2S3HLVDIWFQdqMIsZWbnaGiba18aWhaA==} + engines: {node: '>=14'} + hasBin: true + + js-cookie@3.0.5: + resolution: {integrity: sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==} + engines: {node: '>=14'} + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + + json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + + jsonc-eslint-parser@2.4.0: + resolution: {integrity: sha512-WYDyuc/uFcGp6YtM2H0uKmUwieOuzeE/5YocFJLnLfclZ4inf3mRn8ZVy1s7Hxji7Jxm6Ss8gqpexD/GlKoGgg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + jsonfile@6.1.0: + resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + + kolorist@1.8.0: + resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==} + + levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + + lilconfig@3.1.3: + resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} + engines: {node: '>=14'} + + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + + lodash-es@4.17.21: + resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==} + + lodash-unified@1.0.3: + resolution: {integrity: sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ==} + peerDependencies: + '@types/lodash-es': '*' + lodash: '*' + lodash-es: '*' + + lodash.camelcase@4.3.0: + resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} + + lodash.clonedeep@4.5.0: + resolution: {integrity: sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==} + + lodash.debounce@4.0.8: + resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} + + lodash.foreach@4.5.0: + resolution: {integrity: sha512-aEXTF4d+m05rVOAUG3z4vZZ4xVexLKZGF0lIxuHZ1Hplpk/3B6Z1+/ICICYRLm7c41Z2xiejbkCkJoTlypoXhQ==} + + lodash.isequal@4.5.0: + resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} + deprecated: This package is deprecated. Use require('node:util').isDeepStrictEqual instead. + + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + lodash.throttle@4.1.1: + resolution: {integrity: sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==} + + lodash.toarray@4.4.0: + resolution: {integrity: sha512-QyffEA3i5dma5q2490+SgCvDN0pXLmRGSyAANuVi0HQ01Pkfr9fuoKQW8wm1wGBnJITs/mS7wQvS6VshUEBFCw==} + + lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + + lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + + magic-string@0.30.17: + resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} + + marked@14.1.4: + resolution: {integrity: sha512-vkVZ8ONmUdPnjCKc5uTRvmkRbx4EAi2OkTOXmfTDhZz3OFqMNBM1oTTWwTr4HY4uAEojhzPf+Fy8F1DWa3Sndg==} + engines: {node: '>= 18'} + hasBin: true + + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + mdn-data@2.0.28: + resolution: {integrity: sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==} + + mdn-data@2.0.30: + resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==} + + memoize-one@6.0.0: + resolution: {integrity: sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==} + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-match@1.0.2: + resolution: {integrity: sha512-VXp/ugGDVh3eCLOBCiHZMYWQaTNUHv2IJrut+yXA6+JbLPXHglHwfS/5A5L0ll+jkCY7fIzRJcH6OIunF+c6Cg==} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + + minimatch@9.0.1: + resolution: {integrity: sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==} + engines: {node: '>=16 || 14 >=14.17'} + + minimatch@9.0.5: + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} + engines: {node: '>=16 || 14 >=14.17'} + + minipass@7.1.2: + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + engines: {node: '>=16 || 14 >=14.17'} + + mitt@3.0.1: + resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==} + + mlly@1.7.4: + resolution: {integrity: sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==} + + mrmime@2.0.1: + resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==} + engines: {node: '>=10'} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + muggle-string@0.4.1: + resolution: {integrity: sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==} + + mz@2.7.0: + resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} + + namespace-emitter@2.0.1: + resolution: {integrity: sha512-N/sMKHniSDJBjfrkbS/tpkPj4RAbvW3mr8UAzvlMHyun93XEm83IAvhWtJVHo+RHn/oO8Job5YN4b+wRjSVp5g==} + + nanoid@3.3.11: + resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + nanoid@5.1.5: + resolution: {integrity: sha512-Ir/+ZpE9fDsNH0hQ3C68uyThDXzYcim2EqcZ8zn8Chtt1iylPT9xXJB0kPCnqzgcEGikO9RxSrh63MsmVCU7Fw==} + engines: {node: ^18 || >=20} + hasBin: true + + natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + + next-tick@1.1.0: + resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==} + + node-addon-api@7.1.1: + resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==} + + node-releases@2.0.19: + resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} + + nopt@7.2.1: + resolution: {integrity: sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + hasBin: true + + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + + normalize-range@0.1.2: + resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} + engines: {node: '>=0.10.0'} + + normalize-wheel-es@1.2.0: + resolution: {integrity: sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw==} + + npm-run-path@6.0.0: + resolution: {integrity: sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==} + engines: {node: '>=18'} + + nprogress@0.2.0: + resolution: {integrity: sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA==} + + nth-check@2.1.1: + resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + object-hash@3.0.0: + resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} + engines: {node: '>= 6'} + + open@10.2.0: + resolution: {integrity: sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==} + engines: {node: '>=18'} + + open@8.4.2: + resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} + engines: {node: '>=12'} + + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + + parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + + parse-ms@4.0.0: + resolution: {integrity: sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==} + engines: {node: '>=18'} + + path-browserify@1.0.1: + resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-key@4.0.0: + resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} + engines: {node: '>=12'} + + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} + + pathe@1.1.2: + resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} + + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + + perfect-debounce@1.0.0: + resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + picomatch@4.0.3: + resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} + engines: {node: '>=12'} + + pify@2.3.0: + resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} + engines: {node: '>=0.10.0'} + + pinia@2.3.1: + resolution: {integrity: sha512-khUlZSwt9xXCaTbbxFYBKDc/bWAGWJjOgvxETwkTN7KRm66EeT1ZdZj6i2ceh9sP2Pzqsbc704r2yngBrxBVug==} + peerDependencies: + typescript: '>=4.4.4' + vue: ^2.7.0 || ^3.5.11 + peerDependenciesMeta: + typescript: + optional: true + + pirates@4.0.7: + resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==} + engines: {node: '>= 6'} + + pkg-types@1.3.1: + resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} + + postcss-import@15.1.0: + resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} + engines: {node: '>=14.0.0'} + peerDependencies: + postcss: ^8.0.0 + + postcss-js@4.0.1: + resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==} + engines: {node: ^12 || ^14 || >= 16} + peerDependencies: + postcss: ^8.4.21 + + postcss-load-config@4.0.2: + resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==} + engines: {node: '>= 14'} + peerDependencies: + postcss: '>=8.0.9' + ts-node: '>=9.0.0' + peerDependenciesMeta: + postcss: + optional: true + ts-node: + optional: true + + postcss-nested@6.2.0: + resolution: {integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.2.14 + + postcss-selector-parser@6.1.2: + resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} + engines: {node: '>=4'} + + postcss-value-parser@4.2.0: + resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} + + postcss@8.5.6: + resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} + engines: {node: ^10 || ^12 || >=14} + + preact@10.26.9: + resolution: {integrity: sha512-SSjF9vcnF27mJK1XyFMNJzFd5u3pQiATFqoaDy03XuN00u4ziveVVEGt5RKJrDR8MHE/wJo9Nnad56RLzS2RMA==} + + prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + + prettier-linter-helpers@1.0.0: + resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} + engines: {node: '>=6.0.0'} + + prettier@3.6.2: + resolution: {integrity: sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==} + engines: {node: '>=14'} + hasBin: true + + pretty-ms@9.2.0: + resolution: {integrity: sha512-4yf0QO/sllf/1zbZWYnvWw3NxCQwLXKzIj0G849LSufP15BXKM0rbD2Z3wVnkMfjdn/CB0Dpp444gYAACdsplg==} + engines: {node: '>=18'} + + prismjs@1.30.0: + resolution: {integrity: sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==} + engines: {node: '>=6'} + + proto-list@1.2.4: + resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==} + + proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + read-cache@1.0.0: + resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} + + readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + + readdirp@4.1.2: + resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} + engines: {node: '>= 14.18.0'} + + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + resolve@1.22.10: + resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==} + engines: {node: '>= 0.4'} + hasBin: true + + reusify@1.1.0: + resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + rfdc@1.4.1: + resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} + + rollup-plugin-visualizer@5.14.0: + resolution: {integrity: sha512-VlDXneTDaKsHIw8yzJAFWtrzguoJ/LnQ+lMpoVfYJ3jJF4Ihe5oYLAqLklIK/35lgUY+1yEzCkHyZ1j4A5w5fA==} + engines: {node: '>=18'} + hasBin: true + peerDependencies: + rolldown: 1.x + rollup: 2.x || 3.x || 4.x + peerDependenciesMeta: + rolldown: + optional: true + rollup: + optional: true + + rollup@4.45.1: + resolution: {integrity: sha512-4iya7Jb76fVpQyLoiVpzUrsjQ12r3dM7fIVz+4NwoYvZOShknRmiv+iu9CClZml5ZLGb0XMcYLutK6w9tgxHDw==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + run-applescript@7.0.0: + resolution: {integrity: sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==} + engines: {node: '>=18'} + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + sass@1.81.0: + resolution: {integrity: sha512-Q4fOxRfhmv3sqCLoGfvrC9pRV8btc0UtqL9mN6Yrv6Qi9ScL55CVH1vlPP863ISLEEMNLLuu9P+enCeGHlnzhA==} + engines: {node: '>=14.0.0'} + hasBin: true + + scroll-into-view-if-needed@2.2.31: + resolution: {integrity: sha512-dGCXy99wZQivjmjIqihaBQNjryrz5rueJY7eHfTdyWEiR4ttYpsajb14rn9s5d4DY4EcY6+4+U/maARBXJedkA==} + + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + semver@7.7.2: + resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==} + engines: {node: '>=10'} + hasBin: true + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + sirv@3.0.1: + resolution: {integrity: sha512-FoqMu0NCGBLCcAkS1qA+XJIQTR6/JHfQXl+uGteNCQ76T91DMUjPa9xfmeqMY3z80nLSg9yQmNjK0Px6RWsH/A==} + engines: {node: '>=18'} + + slate-history@0.66.0: + resolution: {integrity: sha512-6MWpxGQZiMvSINlCbMW43E2YBSVMCMCIwQfBzGssjWw4kb0qfvj0pIdblWNRQZD0hR6WHP+dHHgGSeVdMWzfng==} + peerDependencies: + slate: '>=0.65.3' + + slate@0.72.8: + resolution: {integrity: sha512-/nJwTswQgnRurpK+bGJFH1oM7naD5qDmHd89JyiKNT2oOKD8marW0QSBtuFnwEbL5aGCS8AmrhXQgNOsn4osAw==} + + snabbdom@3.6.2: + resolution: {integrity: sha512-ig5qOnCDbugFntKi6c7Xlib8bA6xiJVk8O+WdFrV3wxbMqeHO0hXFQC4nAhPVWfZfi8255lcZkNhtIBINCc4+Q==} + engines: {node: '>=12.17.0'} + + sortablejs@1.14.0: + resolution: {integrity: sha512-pBXvQCs5/33fdN1/39pPL0NZF20LeRbLQ5jtnheIPN9JQAaufGjKdWduZn4U7wCtVuzKhmRkI0DFYHYRbB2H1w==} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + source-map-support@0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + source-map@0.7.4: + resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} + engines: {node: '>= 8'} + + speakingurl@14.0.1: + resolution: {integrity: sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==} + engines: {node: '>=0.10.0'} + + ssf@0.11.2: + resolution: {integrity: sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==} + engines: {node: '>=0.8'} + + ssr-window@3.0.0: + resolution: {integrity: sha512-q+8UfWDg9Itrg0yWK7oe5p/XRCJpJF9OBtXfOPgSJl+u3Xd5KI328RUEvUqSMVM9CiQUEf1QdBzJMkYGErj9QA==} + + store@2.0.12: + resolution: {integrity: sha512-eO9xlzDpXLiMr9W1nQ3Nfp9EzZieIQc10zPPMP5jsVV7bLOziSFFBP0XoDXACEIFtdI+rIz0NwWVA/QVJ8zJtw==} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + + strip-final-newline@4.0.0: + resolution: {integrity: sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==} + engines: {node: '>=18'} + + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + + sucrase@3.35.0: + resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} + engines: {node: '>=16 || 14 >=14.17'} + hasBin: true + + superjson@2.2.2: + resolution: {integrity: sha512-5JRxVqC8I8NuOUjzBbvVJAKNM8qoVuH0O77h4WInc/qC2q5IreqKxYwgkga3PfA22OayK2ikceb/B26dztPl+Q==} + engines: {node: '>=16'} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + svgo@3.3.2: + resolution: {integrity: sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==} + engines: {node: '>=14.0.0'} + hasBin: true + + synckit@0.11.11: + resolution: {integrity: sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==} + engines: {node: ^14.18.0 || >=16.0.0} + + tailwindcss@3.4.17: + resolution: {integrity: sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==} + engines: {node: '>=14.0.0'} + hasBin: true + + terser@5.43.1: + resolution: {integrity: sha512-+6erLbBm0+LROX2sPXlUYx/ux5PyE9K/a92Wrt6oA+WDAoFTdpHE5tCYCI5PNzq2y8df4rA+QgHLJuR4jNymsg==} + engines: {node: '>=10'} + hasBin: true + + thenify-all@1.6.0: + resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} + engines: {node: '>=0.8'} + + thenify@3.3.1: + resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + + tiny-warning@1.0.3: + resolution: {integrity: sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + totalist@3.0.1: + resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} + engines: {node: '>=6'} + + ts-api-utils@2.1.0: + resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==} + engines: {node: '>=18.12'} + peerDependencies: + typescript: '>=4.8.4' + + ts-interface-checker@0.1.13: + resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} + + tslib@2.3.0: + resolution: {integrity: sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==} + + type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + + type-fest@0.20.2: + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} + engines: {node: '>=10'} + + type@2.7.3: + resolution: {integrity: sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==} + + typescript-eslint@8.38.0: + resolution: {integrity: sha512-FsZlrYK6bPDGoLeZRuvx2v6qrM03I0U0SnfCLPs/XCCPCFD80xU9Pg09H/K+XFa68uJuZo7l/Xhs+eDRg2l3hg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' + + typescript@5.5.4: + resolution: {integrity: sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==} + engines: {node: '>=14.17'} + hasBin: true + + ufo@1.6.1: + resolution: {integrity: sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==} + + undici-types@6.21.0: + resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + + unicorn-magic@0.3.0: + resolution: {integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==} + engines: {node: '>=18'} + + universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + + unplugin@1.16.1: + resolution: {integrity: sha512-4/u/j4FrCKdi17jaxuJA0jClGxB1AvU2hw/IuayPc4ay1XGaJs/rbb4v5WKwAjNifjmXK9PIFyuPiaK8azyR9w==} + engines: {node: '>=14.0.0'} + + update-browserslist-db@1.1.3: + resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + vite-hot-client@2.1.0: + resolution: {integrity: sha512-7SpgZmU7R+dDnSmvXE1mfDtnHLHQSisdySVR7lO8ceAXvM0otZeuQQ6C8LrS5d/aYyP/QZ0hI0L+dIPrm4YlFQ==} + peerDependencies: + vite: ^2.6.0 || ^3.0.0 || ^4.0.0 || ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0 + + vite-plugin-compression@0.5.1: + resolution: {integrity: sha512-5QJKBDc+gNYVqL/skgFAP81Yuzo9R+EAf19d+EtsMF/i8kFUpNi3J/H01QD3Oo8zBQn+NzoCIFkpPLynoOzaJg==} + peerDependencies: + vite: '>=2.0.0' + + vite-plugin-inspect@0.8.9: + resolution: {integrity: sha512-22/8qn+LYonzibb1VeFZmISdVao5kC22jmEKm24vfFE8siEn47EpVcCLYMv6iKOYMJfjSvSJfueOwcFCkUnV3A==} + engines: {node: '>=14'} + peerDependencies: + '@nuxt/kit': '*' + vite: ^3.1.0 || ^4.0.0 || ^5.0.0-0 || ^6.0.1 + peerDependenciesMeta: + '@nuxt/kit': + optional: true + + vite-plugin-vue-devtools@7.7.7: + resolution: {integrity: sha512-d0fIh3wRcgSlr4Vz7bAk4va1MkdqhQgj9ANE/rBhsAjOnRfTLs2ocjFMvSUOsv6SRRXU9G+VM7yMgqDb6yI4iQ==} + engines: {node: '>=v14.21.3'} + peerDependencies: + vite: ^3.1.0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0 + + vite-plugin-vue-inspector@5.3.2: + resolution: {integrity: sha512-YvEKooQcSiBTAs0DoYLfefNja9bLgkFM7NI2b07bE2SruuvX0MEa9cMaxjKVMkeCp5Nz9FRIdcN1rOdFVBeL6Q==} + peerDependencies: + vite: ^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0 + + vite@5.4.19: + resolution: {integrity: sha512-qO3aKv3HoQC8QKiNSTuUM1l9o/XX3+c+VTgLHbJWHZGeTPVAg2XwazI9UWzoxjIJCGCV2zU60uqMzjeLZuULqA==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || >=20.0.0 + less: '*' + lightningcss: ^1.21.0 + sass: '*' + sass-embedded: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + + vscode-uri@3.1.0: + resolution: {integrity: sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==} + + vue-component-type-helpers@2.2.12: + resolution: {integrity: sha512-YbGqHZ5/eW4SnkPNR44mKVc6ZKQoRs/Rux1sxC6rdwXb4qpbOSYfDr9DsTHolOTGmIKgM9j141mZbBeg05R1pw==} + + vue-demi@0.13.11: + resolution: {integrity: sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==} + engines: {node: '>=12'} + hasBin: true + peerDependencies: + '@vue/composition-api': ^1.0.0-rc.1 + vue: ^3.0.0-0 || ^2.6.0 + peerDependenciesMeta: + '@vue/composition-api': + optional: true + + vue-demi@0.14.10: + resolution: {integrity: sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==} + engines: {node: '>=12'} + hasBin: true + peerDependencies: + '@vue/composition-api': ^1.0.0-rc.1 + vue: ^3.0.0-0 || ^2.6.0 + peerDependenciesMeta: + '@vue/composition-api': + optional: true + + vue-echarts@7.0.3: + resolution: {integrity: sha512-/jSxNwOsw5+dYAUcwSfkLwKPuzTQ0Cepz1LxCOpj2QcHrrmUa/Ql0eQqMmc1rTPQVrh2JQ29n2dhq75ZcHvRDw==} + peerDependencies: + '@vue/runtime-core': ^3.0.0 + echarts: ^5.5.1 + vue: ^2.7.0 || ^3.1.1 + peerDependenciesMeta: + '@vue/runtime-core': + optional: true + + vue-eslint-parser@10.2.0: + resolution: {integrity: sha512-CydUvFOQKD928UzZhTp4pr2vWz1L+H99t7Pkln2QSPdvmURT0MoC4wUccfCnuEaihNsu9aYYyk+bep8rlfkUXw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + + vue-eslint-parser@9.4.3: + resolution: {integrity: sha512-2rYRLWlIpaiN8xbPiDyXZXRgLGOtWxERV7ND5fFAv5qo1D2N9Fu9MNajBNc6o13lZ+24DAWCkQCvj4klgmcITg==} + engines: {node: ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: '>=6.0.0' + + vue-i18n@11.1.10: + resolution: {integrity: sha512-C+IwnSg8QDSOAox0gdFYP5tsKLx5jNWxiawNoiNB/Tw4CReXmM1VJMXbduhbrEzAFLhreqzfDocuSVjGbxQrag==} + engines: {node: '>= 16'} + peerDependencies: + vue: ^3.0.0 + + vue-router@4.5.1: + resolution: {integrity: sha512-ogAF3P97NPm8fJsE4by9dwSYtDwXIY1nFY9T6DyQnGHd1E2Da94w9JIolpe42LJGIl0DwOHBi8TcRPlPGwbTtw==} + peerDependencies: + vue: ^3.2.0 + + vue-tsc@2.2.12: + resolution: {integrity: sha512-P7OP77b2h/Pmk+lZdJ0YWs+5tJ6J2+uOQPo7tlBnY44QqQSPYvS0qVT4wqDJgwrZaLe47etJLLQRFia71GYITw==} + hasBin: true + peerDependencies: + typescript: '>=5.0.0' + + vue@3.5.18: + resolution: {integrity: sha512-7W4Y4ZbMiQ3SEo+m9lnoNpV9xG7QVMLa+/0RFwwiAVkeYoyGXqWE85jabU4pllJNUzqfLShJ5YLptewhCWUgNA==} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + vuedraggable@4.1.0: + resolution: {integrity: sha512-FU5HCWBmsf20GpP3eudURW3WdWTKIbEIQxh9/8GE806hydR9qZqRRxRE3RjqX7PkuLuMQG/A7n3cfj9rCEchww==} + peerDependencies: + vue: ^3.0.1 + + webpack-virtual-modules@0.6.2: + resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==} + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + wildcard@1.1.2: + resolution: {integrity: sha512-DXukZJxpHA8LuotRwL0pP1+rS6CS7FF2qStDDE1C7DDg2rLud2PXRMuEDYIPhgEezwnlHNL4c+N6MfMTjCGTng==} + + wmf@1.0.2: + resolution: {integrity: sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==} + engines: {node: '>=0.8'} + + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + + word@0.3.0: + resolution: {integrity: sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==} + engines: {node: '>=0.8'} + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + + wsl-utils@0.1.0: + resolution: {integrity: sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==} + engines: {node: '>=18'} + + xlsx@0.18.5: + resolution: {integrity: sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==} + engines: {node: '>=0.8'} + hasBin: true + + xml-name-validator@4.0.0: + resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==} + engines: {node: '>=12'} + + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + + yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + + yaml-eslint-parser@1.3.0: + resolution: {integrity: sha512-E/+VitOorXSLiAqtTd7Yqax0/pAS3xaYMP+AUUJGOK1OZG3rhcj9fcJOM5HJ2VrP1FrStVCWr1muTfQCdj4tAA==} + engines: {node: ^14.17.0 || >=16.0.0} + + yaml@2.8.0: + resolution: {integrity: sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==} + engines: {node: '>= 14.6'} + hasBin: true + + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + + yoctocolors@2.1.1: + resolution: {integrity: sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ==} + engines: {node: '>=18'} + + zrender@5.6.1: + resolution: {integrity: sha512-OFXkDJKcrlx5su2XbzJvj/34Q3m6PvyCZkVPHGYpcCJ52ek4U/ymZyfuV1nKE23AyBJ51E/6Yr0mhZ7xGTO4ag==} + +snapshots: + + '@alloc/quick-lru@5.2.0': {} + + '@ampproject/remapping@2.3.0': + dependencies: + '@jridgewell/gen-mapping': 0.3.12 + '@jridgewell/trace-mapping': 0.3.29 + + '@antfu/utils@0.7.10': {} + + '@babel/code-frame@7.27.1': + dependencies: + '@babel/helper-validator-identifier': 7.27.1 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/compat-data@7.28.0': {} + + '@babel/core@7.28.0': + dependencies: + '@ampproject/remapping': 2.3.0 + '@babel/code-frame': 7.27.1 + '@babel/generator': 7.28.0 + '@babel/helper-compilation-targets': 7.27.2 + '@babel/helper-module-transforms': 7.27.3(@babel/core@7.28.0) + '@babel/helpers': 7.27.6 + '@babel/parser': 7.28.0 + '@babel/template': 7.27.2 + '@babel/traverse': 7.28.0 + '@babel/types': 7.28.1 + convert-source-map: 2.0.0 + debug: 4.4.1 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/generator@7.28.0': + dependencies: + '@babel/parser': 7.28.0 + '@babel/types': 7.28.1 + '@jridgewell/gen-mapping': 0.3.12 + '@jridgewell/trace-mapping': 0.3.29 + jsesc: 3.1.0 + + '@babel/helper-annotate-as-pure@7.27.3': + dependencies: + '@babel/types': 7.28.1 + + '@babel/helper-compilation-targets@7.27.2': + dependencies: + '@babel/compat-data': 7.28.0 + '@babel/helper-validator-option': 7.27.1 + browserslist: 4.25.1 + lru-cache: 5.1.1 + semver: 6.3.1 + + '@babel/helper-create-class-features-plugin@7.27.1(@babel/core@7.28.0)': + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-member-expression-to-functions': 7.27.1 + '@babel/helper-optimise-call-expression': 7.27.1 + '@babel/helper-replace-supers': 7.27.1(@babel/core@7.28.0) + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + '@babel/traverse': 7.28.0 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/helper-globals@7.28.0': {} + + '@babel/helper-member-expression-to-functions@7.27.1': + dependencies: + '@babel/traverse': 7.28.0 + '@babel/types': 7.28.1 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-imports@7.27.1': + dependencies: + '@babel/traverse': 7.28.0 + '@babel/types': 7.28.1 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.27.3(@babel/core@7.28.0)': + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-module-imports': 7.27.1 + '@babel/helper-validator-identifier': 7.27.1 + '@babel/traverse': 7.28.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-optimise-call-expression@7.27.1': + dependencies: + '@babel/types': 7.28.1 + + '@babel/helper-plugin-utils@7.27.1': {} + + '@babel/helper-replace-supers@7.27.1(@babel/core@7.28.0)': + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-member-expression-to-functions': 7.27.1 + '@babel/helper-optimise-call-expression': 7.27.1 + '@babel/traverse': 7.28.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-skip-transparent-expression-wrappers@7.27.1': + dependencies: + '@babel/traverse': 7.28.0 + '@babel/types': 7.28.1 + transitivePeerDependencies: + - supports-color + + '@babel/helper-string-parser@7.27.1': {} + + '@babel/helper-validator-identifier@7.27.1': {} + + '@babel/helper-validator-option@7.27.1': {} + + '@babel/helpers@7.27.6': + dependencies: + '@babel/template': 7.27.2 + '@babel/types': 7.28.1 + + '@babel/parser@7.28.0': + dependencies: + '@babel/types': 7.28.1 + + '@babel/plugin-proposal-decorators@7.28.0(@babel/core@7.28.0)': + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.28.0) + '@babel/helper-plugin-utils': 7.27.1 + '@babel/plugin-syntax-decorators': 7.27.1(@babel/core@7.28.0) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-syntax-decorators@7.27.1(@babel/core@7.28.0)': + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-import-attributes@7.27.1(@babel/core@7.28.0)': + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.28.0)': + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.28.0)': + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-typescript@7.27.1(@babel/core@7.28.0)': + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-typescript@7.28.0(@babel/core@7.28.0)': + dependencies: + '@babel/core': 7.28.0 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.28.0) + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.28.0) + transitivePeerDependencies: + - supports-color + + '@babel/runtime@7.27.6': {} + + '@babel/template@7.27.2': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/parser': 7.28.0 + '@babel/types': 7.28.1 + + '@babel/traverse@7.28.0': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/generator': 7.28.0 + '@babel/helper-globals': 7.28.0 + '@babel/parser': 7.28.0 + '@babel/template': 7.27.2 + '@babel/types': 7.28.1 + debug: 4.4.1 + transitivePeerDependencies: + - supports-color + + '@babel/types@7.28.1': + dependencies: + '@babel/helper-string-parser': 7.27.1 + '@babel/helper-validator-identifier': 7.27.1 + + '@cool-vue/crud@8.0.6(typescript@5.5.4)': + dependencies: + '@vue/runtime-core': 3.5.18 + element-plus: 2.10.4(vue@3.5.18(typescript@5.5.4)) + lodash-es: 4.17.21 + vue: 3.5.18(typescript@5.5.4) + transitivePeerDependencies: + - '@vue/composition-api' + - typescript + + '@cool-vue/vite-plugin@8.2.2': + dependencies: + '@vue/compiler-sfc': 3.5.18 + axios: 1.11.0 + glob: 10.4.5 + lodash: 4.17.21 + magic-string: 0.30.17 + prettier: 3.6.2 + svgo: 3.3.2 + transitivePeerDependencies: + - debug + + '@ctrl/tinycolor@3.6.1': {} + + '@element-plus/icons-vue@2.3.1(vue@3.5.18(typescript@5.5.4))': + dependencies: + vue: 3.5.18(typescript@5.5.4) + + '@esbuild/aix-ppc64@0.21.5': + optional: true + + '@esbuild/android-arm64@0.21.5': + optional: true + + '@esbuild/android-arm@0.21.5': + optional: true + + '@esbuild/android-x64@0.21.5': + optional: true + + '@esbuild/darwin-arm64@0.21.5': + optional: true + + '@esbuild/darwin-x64@0.21.5': + optional: true + + '@esbuild/freebsd-arm64@0.21.5': + optional: true + + '@esbuild/freebsd-x64@0.21.5': + optional: true + + '@esbuild/linux-arm64@0.21.5': + optional: true + + '@esbuild/linux-arm@0.21.5': + optional: true + + '@esbuild/linux-ia32@0.21.5': + optional: true + + '@esbuild/linux-loong64@0.21.5': + optional: true + + '@esbuild/linux-mips64el@0.21.5': + optional: true + + '@esbuild/linux-ppc64@0.21.5': + optional: true + + '@esbuild/linux-riscv64@0.21.5': + optional: true + + '@esbuild/linux-s390x@0.21.5': + optional: true + + '@esbuild/linux-x64@0.21.5': + optional: true + + '@esbuild/netbsd-x64@0.21.5': + optional: true + + '@esbuild/openbsd-x64@0.21.5': + optional: true + + '@esbuild/sunos-x64@0.21.5': + optional: true + + '@esbuild/win32-arm64@0.21.5': + optional: true + + '@esbuild/win32-ia32@0.21.5': + optional: true + + '@esbuild/win32-x64@0.21.5': + optional: true + + '@eslint-community/eslint-utils@4.7.0(eslint@9.31.0(jiti@1.21.7))': + dependencies: + eslint: 9.31.0(jiti@1.21.7) + eslint-visitor-keys: 3.4.3 + + '@eslint-community/regexpp@4.12.1': {} + + '@eslint/config-array@0.21.0': + dependencies: + '@eslint/object-schema': 2.1.6 + debug: 4.4.1 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + + '@eslint/config-helpers@0.3.0': {} + + '@eslint/core@0.15.1': + dependencies: + '@types/json-schema': 7.0.15 + + '@eslint/eslintrc@3.3.1': + dependencies: + ajv: 6.12.6 + debug: 4.4.1 + espree: 10.4.0 + globals: 14.0.0 + ignore: 5.3.2 + import-fresh: 3.3.1 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + + '@eslint/js@9.31.0': {} + + '@eslint/object-schema@2.1.6': {} + + '@eslint/plugin-kit@0.3.4': + dependencies: + '@eslint/core': 0.15.1 + levn: 0.4.1 + + '@floating-ui/core@1.7.2': + dependencies: + '@floating-ui/utils': 0.2.10 + + '@floating-ui/dom@1.7.2': + dependencies: + '@floating-ui/core': 1.7.2 + '@floating-ui/utils': 0.2.10 + + '@floating-ui/utils@0.2.10': {} + + '@humanfs/core@0.19.1': {} + + '@humanfs/node@0.16.6': + dependencies: + '@humanfs/core': 0.19.1 + '@humanwhocodes/retry': 0.3.1 + + '@humanwhocodes/module-importer@1.0.1': {} + + '@humanwhocodes/retry@0.3.1': {} + + '@humanwhocodes/retry@0.4.3': {} + + '@intlify/bundle-utils@10.0.1(vue-i18n@11.1.10(vue@3.5.18(typescript@5.5.4)))': + dependencies: + '@intlify/message-compiler': 11.1.10 + '@intlify/shared': 11.1.10 + acorn: 8.15.0 + escodegen: 2.1.0 + estree-walker: 2.0.2 + jsonc-eslint-parser: 2.4.0 + mlly: 1.7.4 + source-map-js: 1.2.1 + yaml-eslint-parser: 1.3.0 + optionalDependencies: + vue-i18n: 11.1.10(vue@3.5.18(typescript@5.5.4)) + + '@intlify/core-base@11.1.10': + dependencies: + '@intlify/message-compiler': 11.1.10 + '@intlify/shared': 11.1.10 + + '@intlify/message-compiler@11.1.10': + dependencies: + '@intlify/shared': 11.1.10 + source-map-js: 1.2.1 + + '@intlify/shared@11.1.10': {} + + '@intlify/unplugin-vue-i18n@6.0.8(@vue/compiler-dom@3.5.18)(eslint@9.31.0(jiti@1.21.7))(rollup@4.45.1)(typescript@5.5.4)(vue-i18n@11.1.10(vue@3.5.18(typescript@5.5.4)))(vue@3.5.18(typescript@5.5.4))': + dependencies: + '@eslint-community/eslint-utils': 4.7.0(eslint@9.31.0(jiti@1.21.7)) + '@intlify/bundle-utils': 10.0.1(vue-i18n@11.1.10(vue@3.5.18(typescript@5.5.4))) + '@intlify/shared': 11.1.10 + '@intlify/vue-i18n-extensions': 8.0.0(@intlify/shared@11.1.10)(@vue/compiler-dom@3.5.18)(vue-i18n@11.1.10(vue@3.5.18(typescript@5.5.4)))(vue@3.5.18(typescript@5.5.4)) + '@rollup/pluginutils': 5.2.0(rollup@4.45.1) + '@typescript-eslint/scope-manager': 8.38.0 + '@typescript-eslint/typescript-estree': 8.38.0(typescript@5.5.4) + debug: 4.4.1 + fast-glob: 3.3.3 + js-yaml: 4.1.0 + json5: 2.2.3 + pathe: 1.1.2 + picocolors: 1.1.1 + source-map-js: 1.2.1 + unplugin: 1.16.1 + vue: 3.5.18(typescript@5.5.4) + optionalDependencies: + vue-i18n: 11.1.10(vue@3.5.18(typescript@5.5.4)) + transitivePeerDependencies: + - '@vue/compiler-dom' + - eslint + - rollup + - supports-color + - typescript + + '@intlify/vue-i18n-extensions@8.0.0(@intlify/shared@11.1.10)(@vue/compiler-dom@3.5.18)(vue-i18n@11.1.10(vue@3.5.18(typescript@5.5.4)))(vue@3.5.18(typescript@5.5.4))': + dependencies: + '@babel/parser': 7.28.0 + optionalDependencies: + '@intlify/shared': 11.1.10 + '@vue/compiler-dom': 3.5.18 + vue: 3.5.18(typescript@5.5.4) + vue-i18n: 11.1.10(vue@3.5.18(typescript@5.5.4)) + + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.1.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + + '@jridgewell/gen-mapping@0.3.12': + dependencies: + '@jridgewell/sourcemap-codec': 1.5.4 + '@jridgewell/trace-mapping': 0.3.29 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/source-map@0.3.10': + dependencies: + '@jridgewell/gen-mapping': 0.3.12 + '@jridgewell/trace-mapping': 0.3.29 + + '@jridgewell/sourcemap-codec@1.5.4': {} + + '@jridgewell/trace-mapping@0.3.29': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.4 + + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.19.1 + + '@one-ini/wasm@0.1.1': {} + + '@parcel/watcher-android-arm64@2.5.1': + optional: true + + '@parcel/watcher-darwin-arm64@2.5.1': + optional: true + + '@parcel/watcher-darwin-x64@2.5.1': + optional: true + + '@parcel/watcher-freebsd-x64@2.5.1': + optional: true + + '@parcel/watcher-linux-arm-glibc@2.5.1': + optional: true + + '@parcel/watcher-linux-arm-musl@2.5.1': + optional: true + + '@parcel/watcher-linux-arm64-glibc@2.5.1': + optional: true + + '@parcel/watcher-linux-arm64-musl@2.5.1': + optional: true + + '@parcel/watcher-linux-x64-glibc@2.5.1': + optional: true + + '@parcel/watcher-linux-x64-musl@2.5.1': + optional: true + + '@parcel/watcher-win32-arm64@2.5.1': + optional: true + + '@parcel/watcher-win32-ia32@2.5.1': + optional: true + + '@parcel/watcher-win32-x64@2.5.1': + optional: true + + '@parcel/watcher@2.5.1': + dependencies: + detect-libc: 1.0.3 + is-glob: 4.0.3 + micromatch: 4.0.8 + node-addon-api: 7.1.1 + optionalDependencies: + '@parcel/watcher-android-arm64': 2.5.1 + '@parcel/watcher-darwin-arm64': 2.5.1 + '@parcel/watcher-darwin-x64': 2.5.1 + '@parcel/watcher-freebsd-x64': 2.5.1 + '@parcel/watcher-linux-arm-glibc': 2.5.1 + '@parcel/watcher-linux-arm-musl': 2.5.1 + '@parcel/watcher-linux-arm64-glibc': 2.5.1 + '@parcel/watcher-linux-arm64-musl': 2.5.1 + '@parcel/watcher-linux-x64-glibc': 2.5.1 + '@parcel/watcher-linux-x64-musl': 2.5.1 + '@parcel/watcher-win32-arm64': 2.5.1 + '@parcel/watcher-win32-ia32': 2.5.1 + '@parcel/watcher-win32-x64': 2.5.1 + optional: true + + '@pkgjs/parseargs@0.11.0': + optional: true + + '@pkgr/core@0.2.9': {} + + '@polka/url@1.0.0-next.29': {} + + '@rolldown/pluginutils@1.0.0-beta.29': {} + + '@rollup/pluginutils@5.2.0(rollup@4.45.1)': + dependencies: + '@types/estree': 1.0.8 + estree-walker: 2.0.2 + picomatch: 4.0.3 + optionalDependencies: + rollup: 4.45.1 + + '@rollup/rollup-android-arm-eabi@4.45.1': + optional: true + + '@rollup/rollup-android-arm64@4.45.1': + optional: true + + '@rollup/rollup-darwin-arm64@4.45.1': + optional: true + + '@rollup/rollup-darwin-x64@4.45.1': + optional: true + + '@rollup/rollup-freebsd-arm64@4.45.1': + optional: true + + '@rollup/rollup-freebsd-x64@4.45.1': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.45.1': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.45.1': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.45.1': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.45.1': + optional: true + + '@rollup/rollup-linux-loongarch64-gnu@4.45.1': + optional: true + + '@rollup/rollup-linux-powerpc64le-gnu@4.45.1': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.45.1': + optional: true + + '@rollup/rollup-linux-riscv64-musl@4.45.1': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.45.1': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.45.1': + optional: true + + '@rollup/rollup-linux-x64-musl@4.45.1': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.45.1': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.45.1': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.45.1': + optional: true + + '@rushstack/eslint-patch@1.12.0': {} + + '@sec-ant/readable-stream@0.4.1': {} + + '@sindresorhus/merge-streams@4.0.0': {} + + '@sxzz/popperjs-es@2.11.7': {} + + '@transloadit/prettier-bytes@0.0.7': {} + + '@trysound/sax@0.2.0': {} + + '@tsconfig/node20@20.1.6': {} + + '@types/estree@1.0.8': {} + + '@types/event-emitter@0.3.5': {} + + '@types/file-saver@2.0.7': {} + + '@types/json-schema@7.0.15': {} + + '@types/lodash-es@4.17.12': + dependencies: + '@types/lodash': 4.17.20 + + '@types/lodash@4.17.20': {} + + '@types/mockjs@1.0.10': {} + + '@types/node@20.19.9': + dependencies: + undici-types: 6.21.0 + + '@types/nprogress@0.2.3': {} + + '@types/store@2.0.5': {} + + '@types/web-bluetooth@0.0.16': {} + + '@types/web-bluetooth@0.0.21': {} + + '@typescript-eslint/eslint-plugin@8.38.0(@typescript-eslint/parser@8.38.0(eslint@9.31.0(jiti@1.21.7))(typescript@5.5.4))(eslint@9.31.0(jiti@1.21.7))(typescript@5.5.4)': + dependencies: + '@eslint-community/regexpp': 4.12.1 + '@typescript-eslint/parser': 8.38.0(eslint@9.31.0(jiti@1.21.7))(typescript@5.5.4) + '@typescript-eslint/scope-manager': 8.38.0 + '@typescript-eslint/type-utils': 8.38.0(eslint@9.31.0(jiti@1.21.7))(typescript@5.5.4) + '@typescript-eslint/utils': 8.38.0(eslint@9.31.0(jiti@1.21.7))(typescript@5.5.4) + '@typescript-eslint/visitor-keys': 8.38.0 + eslint: 9.31.0(jiti@1.21.7) + graphemer: 1.4.0 + ignore: 7.0.5 + natural-compare: 1.4.0 + ts-api-utils: 2.1.0(typescript@5.5.4) + typescript: 5.5.4 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/parser@8.38.0(eslint@9.31.0(jiti@1.21.7))(typescript@5.5.4)': + dependencies: + '@typescript-eslint/scope-manager': 8.38.0 + '@typescript-eslint/types': 8.38.0 + '@typescript-eslint/typescript-estree': 8.38.0(typescript@5.5.4) + '@typescript-eslint/visitor-keys': 8.38.0 + debug: 4.4.1 + eslint: 9.31.0(jiti@1.21.7) + typescript: 5.5.4 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/project-service@8.38.0(typescript@5.5.4)': + dependencies: + '@typescript-eslint/tsconfig-utils': 8.38.0(typescript@5.5.4) + '@typescript-eslint/types': 8.38.0 + debug: 4.4.1 + typescript: 5.5.4 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/scope-manager@8.38.0': + dependencies: + '@typescript-eslint/types': 8.38.0 + '@typescript-eslint/visitor-keys': 8.38.0 + + '@typescript-eslint/tsconfig-utils@8.38.0(typescript@5.5.4)': + dependencies: + typescript: 5.5.4 + + '@typescript-eslint/type-utils@8.38.0(eslint@9.31.0(jiti@1.21.7))(typescript@5.5.4)': + dependencies: + '@typescript-eslint/types': 8.38.0 + '@typescript-eslint/typescript-estree': 8.38.0(typescript@5.5.4) + '@typescript-eslint/utils': 8.38.0(eslint@9.31.0(jiti@1.21.7))(typescript@5.5.4) + debug: 4.4.1 + eslint: 9.31.0(jiti@1.21.7) + ts-api-utils: 2.1.0(typescript@5.5.4) + typescript: 5.5.4 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/types@8.38.0': {} + + '@typescript-eslint/typescript-estree@8.38.0(typescript@5.5.4)': + dependencies: + '@typescript-eslint/project-service': 8.38.0(typescript@5.5.4) + '@typescript-eslint/tsconfig-utils': 8.38.0(typescript@5.5.4) + '@typescript-eslint/types': 8.38.0 + '@typescript-eslint/visitor-keys': 8.38.0 + debug: 4.4.1 + fast-glob: 3.3.3 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.7.2 + ts-api-utils: 2.1.0(typescript@5.5.4) + typescript: 5.5.4 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@8.38.0(eslint@9.31.0(jiti@1.21.7))(typescript@5.5.4)': + dependencies: + '@eslint-community/eslint-utils': 4.7.0(eslint@9.31.0(jiti@1.21.7)) + '@typescript-eslint/scope-manager': 8.38.0 + '@typescript-eslint/types': 8.38.0 + '@typescript-eslint/typescript-estree': 8.38.0(typescript@5.5.4) + eslint: 9.31.0(jiti@1.21.7) + typescript: 5.5.4 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/visitor-keys@8.38.0': + dependencies: + '@typescript-eslint/types': 8.38.0 + eslint-visitor-keys: 4.2.1 + + '@uppy/companion-client@2.2.2': + dependencies: + '@uppy/utils': 4.1.3 + namespace-emitter: 2.0.1 + + '@uppy/core@2.3.4': + dependencies: + '@transloadit/prettier-bytes': 0.0.7 + '@uppy/store-default': 2.1.1 + '@uppy/utils': 4.1.3 + lodash.throttle: 4.1.1 + mime-match: 1.0.2 + namespace-emitter: 2.0.1 + nanoid: 3.3.11 + preact: 10.26.9 + + '@uppy/store-default@2.1.1': {} + + '@uppy/utils@4.1.3': + dependencies: + lodash.throttle: 4.1.1 + + '@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4)': + dependencies: + '@uppy/companion-client': 2.2.2 + '@uppy/core': 2.3.4 + '@uppy/utils': 4.1.3 + nanoid: 3.3.11 + + '@vitejs/plugin-vue-jsx@4.2.0(vite@5.4.19(@types/node@20.19.9)(sass@1.81.0)(terser@5.43.1))(vue@3.5.18(typescript@5.5.4))': + dependencies: + '@babel/core': 7.28.0 + '@babel/plugin-transform-typescript': 7.28.0(@babel/core@7.28.0) + '@rolldown/pluginutils': 1.0.0-beta.29 + '@vue/babel-plugin-jsx': 1.4.0(@babel/core@7.28.0) + vite: 5.4.19(@types/node@20.19.9)(sass@1.81.0)(terser@5.43.1) + vue: 3.5.18(typescript@5.5.4) + transitivePeerDependencies: + - supports-color + + '@vitejs/plugin-vue@5.2.4(vite@5.4.19(@types/node@20.19.9)(sass@1.81.0)(terser@5.43.1))(vue@3.5.18(typescript@5.5.4))': + dependencies: + vite: 5.4.19(@types/node@20.19.9)(sass@1.81.0)(terser@5.43.1) + vue: 3.5.18(typescript@5.5.4) + + '@volar/language-core@2.4.15': + dependencies: + '@volar/source-map': 2.4.15 + + '@volar/source-map@2.4.15': {} + + '@volar/typescript@2.4.15': + dependencies: + '@volar/language-core': 2.4.15 + path-browserify: 1.0.1 + vscode-uri: 3.1.0 + + '@vue/babel-helper-vue-transform-on@1.4.0': {} + + '@vue/babel-plugin-jsx@1.4.0(@babel/core@7.28.0)': + dependencies: + '@babel/helper-module-imports': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.0) + '@babel/template': 7.27.2 + '@babel/traverse': 7.28.0 + '@babel/types': 7.28.1 + '@vue/babel-helper-vue-transform-on': 1.4.0 + '@vue/babel-plugin-resolve-type': 1.4.0(@babel/core@7.28.0) + '@vue/shared': 3.5.18 + optionalDependencies: + '@babel/core': 7.28.0 + transitivePeerDependencies: + - supports-color + + '@vue/babel-plugin-resolve-type@1.4.0(@babel/core@7.28.0)': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/core': 7.28.0 + '@babel/helper-module-imports': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/parser': 7.28.0 + '@vue/compiler-sfc': 3.5.18 + transitivePeerDependencies: + - supports-color + + '@vue/compiler-core@3.5.18': + dependencies: + '@babel/parser': 7.28.0 + '@vue/shared': 3.5.18 + entities: 4.5.0 + estree-walker: 2.0.2 + source-map-js: 1.2.1 + + '@vue/compiler-dom@3.5.18': + dependencies: + '@vue/compiler-core': 3.5.18 + '@vue/shared': 3.5.18 + + '@vue/compiler-sfc@3.5.18': + dependencies: + '@babel/parser': 7.28.0 + '@vue/compiler-core': 3.5.18 + '@vue/compiler-dom': 3.5.18 + '@vue/compiler-ssr': 3.5.18 + '@vue/shared': 3.5.18 + estree-walker: 2.0.2 + magic-string: 0.30.17 + postcss: 8.5.6 + source-map-js: 1.2.1 + + '@vue/compiler-ssr@3.5.18': + dependencies: + '@vue/compiler-dom': 3.5.18 + '@vue/shared': 3.5.18 + + '@vue/compiler-vue2@2.7.16': + dependencies: + de-indent: 1.0.2 + he: 1.2.0 + + '@vue/devtools-api@6.6.4': {} + + '@vue/devtools-core@7.7.7(vite@5.4.19(@types/node@20.19.9)(sass@1.81.0)(terser@5.43.1))(vue@3.5.18(typescript@5.5.4))': + dependencies: + '@vue/devtools-kit': 7.7.7 + '@vue/devtools-shared': 7.7.7 + mitt: 3.0.1 + nanoid: 5.1.5 + pathe: 2.0.3 + vite-hot-client: 2.1.0(vite@5.4.19(@types/node@20.19.9)(sass@1.81.0)(terser@5.43.1)) + vue: 3.5.18(typescript@5.5.4) + transitivePeerDependencies: + - vite + + '@vue/devtools-kit@7.7.7': + dependencies: + '@vue/devtools-shared': 7.7.7 + birpc: 2.5.0 + hookable: 5.5.3 + mitt: 3.0.1 + perfect-debounce: 1.0.0 + speakingurl: 14.0.1 + superjson: 2.2.2 + + '@vue/devtools-shared@7.7.7': + dependencies: + rfdc: 1.4.1 + + '@vue/eslint-config-prettier@10.2.0(eslint@9.31.0(jiti@1.21.7))(prettier@3.6.2)': + dependencies: + eslint: 9.31.0(jiti@1.21.7) + eslint-config-prettier: 10.1.8(eslint@9.31.0(jiti@1.21.7)) + eslint-plugin-prettier: 5.5.3(eslint-config-prettier@10.1.8(eslint@9.31.0(jiti@1.21.7)))(eslint@9.31.0(jiti@1.21.7))(prettier@3.6.2) + prettier: 3.6.2 + transitivePeerDependencies: + - '@types/eslint' + + '@vue/eslint-config-typescript@14.6.0(eslint-plugin-vue@9.33.0(eslint@9.31.0(jiti@1.21.7)))(eslint@9.31.0(jiti@1.21.7))(typescript@5.5.4)': + dependencies: + '@typescript-eslint/utils': 8.38.0(eslint@9.31.0(jiti@1.21.7))(typescript@5.5.4) + eslint: 9.31.0(jiti@1.21.7) + eslint-plugin-vue: 9.33.0(eslint@9.31.0(jiti@1.21.7)) + fast-glob: 3.3.3 + typescript-eslint: 8.38.0(eslint@9.31.0(jiti@1.21.7))(typescript@5.5.4) + vue-eslint-parser: 10.2.0(eslint@9.31.0(jiti@1.21.7)) + optionalDependencies: + typescript: 5.5.4 + transitivePeerDependencies: + - supports-color + + '@vue/language-core@2.2.12(typescript@5.5.4)': + dependencies: + '@volar/language-core': 2.4.15 + '@vue/compiler-dom': 3.5.18 + '@vue/compiler-vue2': 2.7.16 + '@vue/shared': 3.5.18 + alien-signals: 1.0.13 + minimatch: 9.0.5 + muggle-string: 0.4.1 + path-browserify: 1.0.1 + optionalDependencies: + typescript: 5.5.4 + + '@vue/reactivity@3.5.18': + dependencies: + '@vue/shared': 3.5.18 + + '@vue/runtime-core@3.5.18': + dependencies: + '@vue/reactivity': 3.5.18 + '@vue/shared': 3.5.18 + + '@vue/runtime-dom@3.5.18': + dependencies: + '@vue/reactivity': 3.5.18 + '@vue/runtime-core': 3.5.18 + '@vue/shared': 3.5.18 + csstype: 3.1.3 + + '@vue/server-renderer@3.5.18(vue@3.5.18(typescript@5.5.4))': + dependencies: + '@vue/compiler-ssr': 3.5.18 + '@vue/shared': 3.5.18 + vue: 3.5.18(typescript@5.5.4) + + '@vue/shared@3.5.18': {} + + '@vue/test-utils@2.4.6': + dependencies: + js-beautify: 1.15.4 + vue-component-type-helpers: 2.2.12 + + '@vue/tsconfig@0.5.1': {} + + '@vueuse/core@12.8.2(typescript@5.5.4)': + dependencies: + '@types/web-bluetooth': 0.0.21 + '@vueuse/metadata': 12.8.2 + '@vueuse/shared': 12.8.2(typescript@5.5.4) + vue: 3.5.18(typescript@5.5.4) + transitivePeerDependencies: + - typescript + + '@vueuse/core@9.13.0(vue@3.5.18(typescript@5.5.4))': + dependencies: + '@types/web-bluetooth': 0.0.16 + '@vueuse/metadata': 9.13.0 + '@vueuse/shared': 9.13.0(vue@3.5.18(typescript@5.5.4)) + vue-demi: 0.14.10(vue@3.5.18(typescript@5.5.4)) + transitivePeerDependencies: + - '@vue/composition-api' + - vue + + '@vueuse/metadata@12.8.2': {} + + '@vueuse/metadata@9.13.0': {} + + '@vueuse/shared@12.8.2(typescript@5.5.4)': + dependencies: + vue: 3.5.18(typescript@5.5.4) + transitivePeerDependencies: + - typescript + + '@vueuse/shared@9.13.0(vue@3.5.18(typescript@5.5.4))': + dependencies: + vue-demi: 0.14.10(vue@3.5.18(typescript@5.5.4)) + transitivePeerDependencies: + - '@vue/composition-api' + - vue + + '@wangeditor/basic-modules@1.1.7(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2))(dom7@3.0.0)(lodash.throttle@4.1.1)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2)': + dependencies: + '@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2) + dom7: 3.0.0 + is-url: 1.2.4 + lodash.throttle: 4.1.1 + nanoid: 3.3.11 + slate: 0.72.8 + snabbdom: 3.6.2 + + '@wangeditor/code-highlight@1.0.3(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2))(dom7@3.0.0)(slate@0.72.8)(snabbdom@3.6.2)': + dependencies: + '@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2) + dom7: 3.0.0 + prismjs: 1.30.0 + slate: 0.72.8 + snabbdom: 3.6.2 + + '@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2)': + dependencies: + '@types/event-emitter': 0.3.5 + '@uppy/core': 2.3.4 + '@uppy/xhr-upload': 2.1.3(@uppy/core@2.3.4) + dom7: 3.0.0 + event-emitter: 0.3.5 + html-void-elements: 2.0.1 + i18next: 20.6.1 + is-hotkey: 0.2.0 + lodash.camelcase: 4.3.0 + lodash.clonedeep: 4.5.0 + lodash.debounce: 4.0.8 + lodash.foreach: 4.5.0 + lodash.isequal: 4.5.0 + lodash.throttle: 4.1.1 + lodash.toarray: 4.4.0 + nanoid: 3.3.11 + scroll-into-view-if-needed: 2.2.31 + slate: 0.72.8 + slate-history: 0.66.0(slate@0.72.8) + snabbdom: 3.6.2 + + '@wangeditor/editor-for-vue@5.1.12(@wangeditor/editor@5.1.23)(vue@3.5.18(typescript@5.5.4))': + dependencies: + '@wangeditor/editor': 5.1.23 + vue: 3.5.18(typescript@5.5.4) + + '@wangeditor/editor@5.1.23': + dependencies: + '@uppy/core': 2.3.4 + '@uppy/xhr-upload': 2.1.3(@uppy/core@2.3.4) + '@wangeditor/basic-modules': 1.1.7(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2))(dom7@3.0.0)(lodash.throttle@4.1.1)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2) + '@wangeditor/code-highlight': 1.0.3(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2))(dom7@3.0.0)(slate@0.72.8)(snabbdom@3.6.2) + '@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2) + '@wangeditor/list-module': 1.0.5(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2))(dom7@3.0.0)(slate@0.72.8)(snabbdom@3.6.2) + '@wangeditor/table-module': 1.1.4(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2))(dom7@3.0.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2) + '@wangeditor/upload-image-module': 1.0.2(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(@wangeditor/basic-modules@1.1.7(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2))(dom7@3.0.0)(lodash.throttle@4.1.1)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2))(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2))(dom7@3.0.0)(lodash.foreach@4.5.0)(slate@0.72.8)(snabbdom@3.6.2) + '@wangeditor/video-module': 1.1.4(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2))(dom7@3.0.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2) + dom7: 3.0.0 + is-hotkey: 0.2.0 + lodash.camelcase: 4.3.0 + lodash.clonedeep: 4.5.0 + lodash.debounce: 4.0.8 + lodash.foreach: 4.5.0 + lodash.isequal: 4.5.0 + lodash.throttle: 4.1.1 + lodash.toarray: 4.4.0 + nanoid: 3.3.11 + slate: 0.72.8 + snabbdom: 3.6.2 + + '@wangeditor/list-module@1.0.5(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2))(dom7@3.0.0)(slate@0.72.8)(snabbdom@3.6.2)': + dependencies: + '@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2) + dom7: 3.0.0 + slate: 0.72.8 + snabbdom: 3.6.2 + + '@wangeditor/table-module@1.1.4(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2))(dom7@3.0.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2)': + dependencies: + '@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2) + dom7: 3.0.0 + lodash.isequal: 4.5.0 + lodash.throttle: 4.1.1 + nanoid: 3.3.11 + slate: 0.72.8 + snabbdom: 3.6.2 + + '@wangeditor/upload-image-module@1.0.2(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(@wangeditor/basic-modules@1.1.7(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2))(dom7@3.0.0)(lodash.throttle@4.1.1)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2))(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2))(dom7@3.0.0)(lodash.foreach@4.5.0)(slate@0.72.8)(snabbdom@3.6.2)': + dependencies: + '@uppy/core': 2.3.4 + '@uppy/xhr-upload': 2.1.3(@uppy/core@2.3.4) + '@wangeditor/basic-modules': 1.1.7(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2))(dom7@3.0.0)(lodash.throttle@4.1.1)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2) + '@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2) + dom7: 3.0.0 + lodash.foreach: 4.5.0 + slate: 0.72.8 + snabbdom: 3.6.2 + + '@wangeditor/video-module@1.1.4(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2))(dom7@3.0.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2)': + dependencies: + '@uppy/core': 2.3.4 + '@uppy/xhr-upload': 2.1.3(@uppy/core@2.3.4) + '@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.11)(slate@0.72.8)(snabbdom@3.6.2) + dom7: 3.0.0 + nanoid: 3.3.11 + slate: 0.72.8 + snabbdom: 3.6.2 + + abbrev@2.0.0: {} + + acorn-jsx@5.3.2(acorn@8.15.0): + dependencies: + acorn: 8.15.0 + + acorn@8.15.0: {} + + adler-32@1.3.1: {} + + ajv@6.12.6: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + + alien-signals@1.0.13: {} + + ansi-regex@5.0.1: {} + + ansi-regex@6.1.0: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@6.2.1: {} + + any-promise@1.3.0: {} + + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + + arg@5.0.2: {} + + argparse@2.0.1: {} + + async-validator@4.2.5: {} + + asynckit@0.4.0: {} + + autoprefixer@10.4.21(postcss@8.5.6): + dependencies: + browserslist: 4.25.1 + caniuse-lite: 1.0.30001727 + fraction.js: 4.3.7 + normalize-range: 0.1.2 + picocolors: 1.1.1 + postcss: 8.5.6 + postcss-value-parser: 4.2.0 + + axios@1.11.0: + dependencies: + follow-redirects: 1.15.9 + form-data: 4.0.4 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + + balanced-match@1.0.2: {} + + binary-extensions@2.3.0: {} + + birpc@2.5.0: {} + + boolbase@1.0.0: {} + + brace-expansion@1.1.12: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + brace-expansion@2.0.2: + dependencies: + balanced-match: 1.0.2 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + browserslist@4.25.1: + dependencies: + caniuse-lite: 1.0.30001727 + electron-to-chromium: 1.5.190 + node-releases: 2.0.19 + update-browserslist-db: 1.1.3(browserslist@4.25.1) + + buffer-from@1.1.2: {} + + bundle-name@4.1.0: + dependencies: + run-applescript: 7.0.0 + + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + callsites@3.1.0: {} + + camelcase-css@2.0.1: {} + + caniuse-lite@1.0.30001727: {} + + cfb@1.2.2: + dependencies: + adler-32: 1.3.1 + crc-32: 1.2.2 + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + chardet@2.1.0: {} + + chokidar@3.6.0: + dependencies: + anymatch: 3.1.3 + braces: 3.0.3 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + + chokidar@4.0.3: + dependencies: + readdirp: 4.1.2 + + cliui@8.0.1: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + codepage@1.15.0: {} + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + + commander@10.0.1: {} + + commander@2.20.3: {} + + commander@4.1.1: {} + + commander@7.2.0: {} + + compute-scroll-into-view@1.0.20: {} + + concat-map@0.0.1: {} + + confbox@0.1.8: {} + + config-chain@1.1.13: + dependencies: + ini: 1.3.8 + proto-list: 1.2.4 + + convert-source-map@2.0.0: {} + + copy-anything@3.0.5: + dependencies: + is-what: 4.1.16 + + core-js@3.44.0: {} + + crc-32@1.2.2: {} + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + css-select@5.2.2: + dependencies: + boolbase: 1.0.0 + css-what: 6.2.2 + domhandler: 5.0.3 + domutils: 3.2.2 + nth-check: 2.1.1 + + css-tree@2.2.1: + dependencies: + mdn-data: 2.0.28 + source-map-js: 1.2.1 + + css-tree@2.3.1: + dependencies: + mdn-data: 2.0.30 + source-map-js: 1.2.1 + + css-what@6.2.2: {} + + cssesc@3.0.0: {} + + csso@5.0.5: + dependencies: + css-tree: 2.2.1 + + csstype@3.1.3: {} + + d@1.0.2: + dependencies: + es5-ext: 0.10.64 + type: 2.7.3 + + dayjs@1.11.13: {} + + de-indent@1.0.2: {} + + debug@4.4.1: + dependencies: + ms: 2.1.3 + + deep-is@0.1.4: {} + + default-browser-id@5.0.0: {} + + default-browser@5.2.1: + dependencies: + bundle-name: 4.1.0 + default-browser-id: 5.0.0 + + define-lazy-prop@2.0.0: {} + + define-lazy-prop@3.0.0: {} + + delayed-stream@1.0.0: {} + + detect-libc@1.0.3: + optional: true + + didyoumean@1.2.2: {} + + dlv@1.1.3: {} + + dom-serializer@2.0.0: + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + entities: 4.5.0 + + dom7@3.0.0: + dependencies: + ssr-window: 3.0.0 + + domelementtype@2.3.0: {} + + domhandler@5.0.3: + dependencies: + domelementtype: 2.3.0 + + domutils@3.2.2: + dependencies: + dom-serializer: 2.0.0 + domelementtype: 2.3.0 + domhandler: 5.0.3 + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + eastasianwidth@0.2.0: {} + + echarts@5.6.0: + dependencies: + tslib: 2.3.0 + zrender: 5.6.1 + + editorconfig@1.0.4: + dependencies: + '@one-ini/wasm': 0.1.1 + commander: 10.0.1 + minimatch: 9.0.1 + semver: 7.7.2 + + electron-to-chromium@1.5.190: {} + + element-plus@2.10.2(vue@3.5.18(typescript@5.5.4)): + dependencies: + '@ctrl/tinycolor': 3.6.1 + '@element-plus/icons-vue': 2.3.1(vue@3.5.18(typescript@5.5.4)) + '@floating-ui/dom': 1.7.2 + '@popperjs/core': '@sxzz/popperjs-es@2.11.7' + '@types/lodash': 4.17.20 + '@types/lodash-es': 4.17.12 + '@vueuse/core': 9.13.0(vue@3.5.18(typescript@5.5.4)) + async-validator: 4.2.5 + dayjs: 1.11.13 + escape-html: 1.0.3 + lodash: 4.17.21 + lodash-es: 4.17.21 + lodash-unified: 1.0.3(@types/lodash-es@4.17.12)(lodash-es@4.17.21)(lodash@4.17.21) + memoize-one: 6.0.0 + normalize-wheel-es: 1.2.0 + vue: 3.5.18(typescript@5.5.4) + transitivePeerDependencies: + - '@vue/composition-api' + + element-plus@2.10.4(vue@3.5.18(typescript@5.5.4)): + dependencies: + '@ctrl/tinycolor': 3.6.1 + '@element-plus/icons-vue': 2.3.1(vue@3.5.18(typescript@5.5.4)) + '@floating-ui/dom': 1.7.2 + '@popperjs/core': '@sxzz/popperjs-es@2.11.7' + '@types/lodash': 4.17.20 + '@types/lodash-es': 4.17.12 + '@vueuse/core': 9.13.0(vue@3.5.18(typescript@5.5.4)) + async-validator: 4.2.5 + dayjs: 1.11.13 + escape-html: 1.0.3 + lodash: 4.17.21 + lodash-es: 4.17.21 + lodash-unified: 1.0.3(@types/lodash-es@4.17.12)(lodash-es@4.17.21)(lodash@4.17.21) + memoize-one: 6.0.0 + normalize-wheel-es: 1.2.0 + vue: 3.5.18(typescript@5.5.4) + transitivePeerDependencies: + - '@vue/composition-api' + + emoji-regex@8.0.0: {} + + emoji-regex@9.2.2: {} + + entities@4.5.0: {} + + error-stack-parser-es@0.1.5: {} + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-object-atoms@1.1.1: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + es5-ext@0.10.64: + dependencies: + es6-iterator: 2.0.3 + es6-symbol: 3.1.4 + esniff: 2.0.1 + next-tick: 1.1.0 + + es6-iterator@2.0.3: + dependencies: + d: 1.0.2 + es5-ext: 0.10.64 + es6-symbol: 3.1.4 + + es6-symbol@3.1.4: + dependencies: + d: 1.0.2 + ext: 1.7.0 + + esbuild@0.21.5: + optionalDependencies: + '@esbuild/aix-ppc64': 0.21.5 + '@esbuild/android-arm': 0.21.5 + '@esbuild/android-arm64': 0.21.5 + '@esbuild/android-x64': 0.21.5 + '@esbuild/darwin-arm64': 0.21.5 + '@esbuild/darwin-x64': 0.21.5 + '@esbuild/freebsd-arm64': 0.21.5 + '@esbuild/freebsd-x64': 0.21.5 + '@esbuild/linux-arm': 0.21.5 + '@esbuild/linux-arm64': 0.21.5 + '@esbuild/linux-ia32': 0.21.5 + '@esbuild/linux-loong64': 0.21.5 + '@esbuild/linux-mips64el': 0.21.5 + '@esbuild/linux-ppc64': 0.21.5 + '@esbuild/linux-riscv64': 0.21.5 + '@esbuild/linux-s390x': 0.21.5 + '@esbuild/linux-x64': 0.21.5 + '@esbuild/netbsd-x64': 0.21.5 + '@esbuild/openbsd-x64': 0.21.5 + '@esbuild/sunos-x64': 0.21.5 + '@esbuild/win32-arm64': 0.21.5 + '@esbuild/win32-ia32': 0.21.5 + '@esbuild/win32-x64': 0.21.5 + + escalade@3.2.0: {} + + escape-html@1.0.3: {} + + escape-string-regexp@4.0.0: {} + + escodegen@2.1.0: + dependencies: + esprima: 4.0.1 + estraverse: 5.3.0 + esutils: 2.0.3 + optionalDependencies: + source-map: 0.6.1 + + eslint-config-prettier@10.1.8(eslint@9.31.0(jiti@1.21.7)): + dependencies: + eslint: 9.31.0(jiti@1.21.7) + + eslint-plugin-prettier@5.5.3(eslint-config-prettier@10.1.8(eslint@9.31.0(jiti@1.21.7)))(eslint@9.31.0(jiti@1.21.7))(prettier@3.6.2): + dependencies: + eslint: 9.31.0(jiti@1.21.7) + prettier: 3.6.2 + prettier-linter-helpers: 1.0.0 + synckit: 0.11.11 + optionalDependencies: + eslint-config-prettier: 10.1.8(eslint@9.31.0(jiti@1.21.7)) + + eslint-plugin-vue@9.33.0(eslint@9.31.0(jiti@1.21.7)): + dependencies: + '@eslint-community/eslint-utils': 4.7.0(eslint@9.31.0(jiti@1.21.7)) + eslint: 9.31.0(jiti@1.21.7) + globals: 13.24.0 + natural-compare: 1.4.0 + nth-check: 2.1.1 + postcss-selector-parser: 6.1.2 + semver: 7.7.2 + vue-eslint-parser: 9.4.3(eslint@9.31.0(jiti@1.21.7)) + xml-name-validator: 4.0.0 + transitivePeerDependencies: + - supports-color + + eslint-scope@7.2.2: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + + eslint-scope@8.4.0: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + + eslint-visitor-keys@3.4.3: {} + + eslint-visitor-keys@4.2.1: {} + + eslint@9.31.0(jiti@1.21.7): + dependencies: + '@eslint-community/eslint-utils': 4.7.0(eslint@9.31.0(jiti@1.21.7)) + '@eslint-community/regexpp': 4.12.1 + '@eslint/config-array': 0.21.0 + '@eslint/config-helpers': 0.3.0 + '@eslint/core': 0.15.1 + '@eslint/eslintrc': 3.3.1 + '@eslint/js': 9.31.0 + '@eslint/plugin-kit': 0.3.4 + '@humanfs/node': 0.16.6 + '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.4.3 + '@types/estree': 1.0.8 + '@types/json-schema': 7.0.15 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.6 + debug: 4.4.1 + escape-string-regexp: 4.0.0 + eslint-scope: 8.4.0 + eslint-visitor-keys: 4.2.1 + espree: 10.4.0 + esquery: 1.6.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 8.0.0 + find-up: 5.0.0 + glob-parent: 6.0.2 + ignore: 5.3.2 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + json-stable-stringify-without-jsonify: 1.0.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.4 + optionalDependencies: + jiti: 1.21.7 + transitivePeerDependencies: + - supports-color + + esniff@2.0.1: + dependencies: + d: 1.0.2 + es5-ext: 0.10.64 + event-emitter: 0.3.5 + type: 2.7.3 + + espree@10.4.0: + dependencies: + acorn: 8.15.0 + acorn-jsx: 5.3.2(acorn@8.15.0) + eslint-visitor-keys: 4.2.1 + + espree@9.6.1: + dependencies: + acorn: 8.15.0 + acorn-jsx: 5.3.2(acorn@8.15.0) + eslint-visitor-keys: 3.4.3 + + esprima@4.0.1: {} + + esquery@1.6.0: + dependencies: + estraverse: 5.3.0 + + esrecurse@4.3.0: + dependencies: + estraverse: 5.3.0 + + estraverse@5.3.0: {} + + estree-walker@2.0.2: {} + + esutils@2.0.3: {} + + event-emitter@0.3.5: + dependencies: + d: 1.0.2 + es5-ext: 0.10.64 + + execa@9.6.0: + dependencies: + '@sindresorhus/merge-streams': 4.0.0 + cross-spawn: 7.0.6 + figures: 6.1.0 + get-stream: 9.0.1 + human-signals: 8.0.1 + is-plain-obj: 4.1.0 + is-stream: 4.0.1 + npm-run-path: 6.0.0 + pretty-ms: 9.2.0 + signal-exit: 4.1.0 + strip-final-newline: 4.0.0 + yoctocolors: 2.1.1 + + ext@1.7.0: + dependencies: + type: 2.7.3 + + fast-deep-equal@3.1.3: {} + + fast-diff@1.3.0: {} + + fast-glob@3.3.3: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + + fast-json-stable-stringify@2.1.0: {} + + fast-levenshtein@2.0.6: {} + + fastq@1.19.1: + dependencies: + reusify: 1.1.0 + + figures@6.1.0: + dependencies: + is-unicode-supported: 2.1.0 + + file-entry-cache@8.0.0: + dependencies: + flat-cache: 4.0.1 + + file-saver@2.0.5: {} + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + find-up@5.0.0: + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + flat-cache@4.0.1: + dependencies: + flatted: 3.3.3 + keyv: 4.5.4 + + flatted@3.3.3: {} + + follow-redirects@1.15.9: {} + + foreground-child@3.3.1: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + + form-data@4.0.4: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + hasown: 2.0.2 + mime-types: 2.1.35 + + frac@1.1.2: {} + + fraction.js@4.3.7: {} + + fs-extra@10.1.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + + fs-extra@11.3.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + gensync@1.0.0-beta.2: {} + + get-caller-file@2.0.5: {} + + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + math-intrinsics: 1.1.0 + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.1 + + get-stream@9.0.1: + dependencies: + '@sec-ant/readable-stream': 0.4.1 + is-stream: 4.0.1 + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 + + glob@10.4.5: + dependencies: + foreground-child: 3.3.1 + jackspeak: 3.4.3 + minimatch: 9.0.5 + minipass: 7.1.2 + package-json-from-dist: 1.0.1 + path-scurry: 1.11.1 + + globals@13.24.0: + dependencies: + type-fest: 0.20.2 + + globals@14.0.0: {} + + gopd@1.2.0: {} + + graceful-fs@4.2.11: {} + + graphemer@1.4.0: {} + + has-flag@4.0.0: {} + + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + he@1.2.0: {} + + hookable@5.5.3: {} + + html-void-elements@2.0.1: {} + + human-signals@8.0.1: {} + + i18next@20.6.1: + dependencies: + '@babel/runtime': 7.27.6 + + ignore@5.3.2: {} + + ignore@7.0.5: {} + + immer@9.0.21: {} + + immutable@5.1.3: {} + + import-fresh@3.3.1: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + imurmurhash@0.1.4: {} + + ini@1.3.8: {} + + is-binary-path@2.1.0: + dependencies: + binary-extensions: 2.3.0 + + is-core-module@2.16.1: + dependencies: + hasown: 2.0.2 + + is-docker@2.2.1: {} + + is-docker@3.0.0: {} + + is-extglob@2.1.1: {} + + is-fullwidth-code-point@3.0.0: {} + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-hotkey@0.2.0: {} + + is-inside-container@1.0.0: + dependencies: + is-docker: 3.0.0 + + is-number@7.0.0: {} + + is-plain-obj@4.1.0: {} + + is-plain-object@5.0.0: {} + + is-stream@4.0.1: {} + + is-unicode-supported@2.1.0: {} + + is-url@1.2.4: {} + + is-what@4.1.16: {} + + is-wsl@2.2.0: + dependencies: + is-docker: 2.2.1 + + is-wsl@3.1.0: + dependencies: + is-inside-container: 1.0.0 + + isexe@2.0.0: {} + + jackspeak@3.4.3: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + + jiti@1.21.7: {} + + js-beautify@1.15.4: + dependencies: + config-chain: 1.1.13 + editorconfig: 1.0.4 + glob: 10.4.5 + js-cookie: 3.0.5 + nopt: 7.2.1 + + js-cookie@3.0.5: {} + + js-tokens@4.0.0: {} + + js-yaml@4.1.0: + dependencies: + argparse: 2.0.1 + + jsesc@3.1.0: {} + + json-buffer@3.0.1: {} + + json-schema-traverse@0.4.1: {} + + json-stable-stringify-without-jsonify@1.0.1: {} + + json5@2.2.3: {} + + jsonc-eslint-parser@2.4.0: + dependencies: + acorn: 8.15.0 + eslint-visitor-keys: 3.4.3 + espree: 9.6.1 + semver: 7.7.2 + + jsonfile@6.1.0: + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + + keyv@4.5.4: + dependencies: + json-buffer: 3.0.1 + + kolorist@1.8.0: {} + + levn@0.4.1: + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + + lilconfig@3.1.3: {} + + lines-and-columns@1.2.4: {} + + locate-path@6.0.0: + dependencies: + p-locate: 5.0.0 + + lodash-es@4.17.21: {} + + lodash-unified@1.0.3(@types/lodash-es@4.17.12)(lodash-es@4.17.21)(lodash@4.17.21): + dependencies: + '@types/lodash-es': 4.17.12 + lodash: 4.17.21 + lodash-es: 4.17.21 + + lodash.camelcase@4.3.0: {} + + lodash.clonedeep@4.5.0: {} + + lodash.debounce@4.0.8: {} + + lodash.foreach@4.5.0: {} + + lodash.isequal@4.5.0: {} + + lodash.merge@4.6.2: {} + + lodash.throttle@4.1.1: {} + + lodash.toarray@4.4.0: {} + + lodash@4.17.21: {} + + lru-cache@10.4.3: {} + + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 + + magic-string@0.30.17: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.4 + + marked@14.1.4: {} + + math-intrinsics@1.1.0: {} + + mdn-data@2.0.28: {} + + mdn-data@2.0.30: {} + + memoize-one@6.0.0: {} + + merge2@1.4.1: {} + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + + mime-db@1.52.0: {} + + mime-match@1.0.2: + dependencies: + wildcard: 1.1.2 + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + minimatch@3.1.2: + dependencies: + brace-expansion: 1.1.12 + + minimatch@9.0.1: + dependencies: + brace-expansion: 2.0.2 + + minimatch@9.0.5: + dependencies: + brace-expansion: 2.0.2 + + minipass@7.1.2: {} + + mitt@3.0.1: {} + + mlly@1.7.4: + dependencies: + acorn: 8.15.0 + pathe: 2.0.3 + pkg-types: 1.3.1 + ufo: 1.6.1 + + mrmime@2.0.1: {} + + ms@2.1.3: {} + + muggle-string@0.4.1: {} + + mz@2.7.0: + dependencies: + any-promise: 1.3.0 + object-assign: 4.1.1 + thenify-all: 1.6.0 + + namespace-emitter@2.0.1: {} + + nanoid@3.3.11: {} + + nanoid@5.1.5: {} + + natural-compare@1.4.0: {} + + next-tick@1.1.0: {} + + node-addon-api@7.1.1: + optional: true + + node-releases@2.0.19: {} + + nopt@7.2.1: + dependencies: + abbrev: 2.0.0 + + normalize-path@3.0.0: {} + + normalize-range@0.1.2: {} + + normalize-wheel-es@1.2.0: {} + + npm-run-path@6.0.0: + dependencies: + path-key: 4.0.0 + unicorn-magic: 0.3.0 + + nprogress@0.2.0: {} + + nth-check@2.1.1: + dependencies: + boolbase: 1.0.0 + + object-assign@4.1.1: {} + + object-hash@3.0.0: {} + + open@10.2.0: + dependencies: + default-browser: 5.2.1 + define-lazy-prop: 3.0.0 + is-inside-container: 1.0.0 + wsl-utils: 0.1.0 + + open@8.4.2: + dependencies: + define-lazy-prop: 2.0.0 + is-docker: 2.2.1 + is-wsl: 2.2.0 + + optionator@0.9.4: + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.5 + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + p-locate@5.0.0: + dependencies: + p-limit: 3.1.0 + + package-json-from-dist@1.0.1: {} + + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 + + parse-ms@4.0.0: {} + + path-browserify@1.0.1: {} + + path-exists@4.0.0: {} + + path-key@3.1.1: {} + + path-key@4.0.0: {} + + path-parse@1.0.7: {} + + path-scurry@1.11.1: + dependencies: + lru-cache: 10.4.3 + minipass: 7.1.2 + + pathe@1.1.2: {} + + pathe@2.0.3: {} + + perfect-debounce@1.0.0: {} + + picocolors@1.1.1: {} + + picomatch@2.3.1: {} + + picomatch@4.0.3: {} + + pify@2.3.0: {} + + pinia@2.3.1(typescript@5.5.4)(vue@3.5.18(typescript@5.5.4)): + dependencies: + '@vue/devtools-api': 6.6.4 + vue: 3.5.18(typescript@5.5.4) + vue-demi: 0.14.10(vue@3.5.18(typescript@5.5.4)) + optionalDependencies: + typescript: 5.5.4 + transitivePeerDependencies: + - '@vue/composition-api' + + pirates@4.0.7: {} + + pkg-types@1.3.1: + dependencies: + confbox: 0.1.8 + mlly: 1.7.4 + pathe: 2.0.3 + + postcss-import@15.1.0(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + postcss-value-parser: 4.2.0 + read-cache: 1.0.0 + resolve: 1.22.10 + + postcss-js@4.0.1(postcss@8.5.6): + dependencies: + camelcase-css: 2.0.1 + postcss: 8.5.6 + + postcss-load-config@4.0.2(postcss@8.5.6): + dependencies: + lilconfig: 3.1.3 + yaml: 2.8.0 + optionalDependencies: + postcss: 8.5.6 + + postcss-nested@6.2.0(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + postcss-selector-parser: 6.1.2 + + postcss-selector-parser@6.1.2: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + + postcss-value-parser@4.2.0: {} + + postcss@8.5.6: + dependencies: + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + preact@10.26.9: {} + + prelude-ls@1.2.1: {} + + prettier-linter-helpers@1.0.0: + dependencies: + fast-diff: 1.3.0 + + prettier@3.6.2: {} + + pretty-ms@9.2.0: + dependencies: + parse-ms: 4.0.0 + + prismjs@1.30.0: {} + + proto-list@1.2.4: {} + + proxy-from-env@1.1.0: {} + + punycode@2.3.1: {} + + queue-microtask@1.2.3: {} + + read-cache@1.0.0: + dependencies: + pify: 2.3.0 + + readdirp@3.6.0: + dependencies: + picomatch: 2.3.1 + + readdirp@4.1.2: {} + + require-directory@2.1.1: {} + + resolve-from@4.0.0: {} + + resolve@1.22.10: + dependencies: + is-core-module: 2.16.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + reusify@1.1.0: {} + + rfdc@1.4.1: {} + + rollup-plugin-visualizer@5.14.0(rollup@4.45.1): + dependencies: + open: 8.4.2 + picomatch: 4.0.3 + source-map: 0.7.4 + yargs: 17.7.2 + optionalDependencies: + rollup: 4.45.1 + + rollup@4.45.1: + dependencies: + '@types/estree': 1.0.8 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.45.1 + '@rollup/rollup-android-arm64': 4.45.1 + '@rollup/rollup-darwin-arm64': 4.45.1 + '@rollup/rollup-darwin-x64': 4.45.1 + '@rollup/rollup-freebsd-arm64': 4.45.1 + '@rollup/rollup-freebsd-x64': 4.45.1 + '@rollup/rollup-linux-arm-gnueabihf': 4.45.1 + '@rollup/rollup-linux-arm-musleabihf': 4.45.1 + '@rollup/rollup-linux-arm64-gnu': 4.45.1 + '@rollup/rollup-linux-arm64-musl': 4.45.1 + '@rollup/rollup-linux-loongarch64-gnu': 4.45.1 + '@rollup/rollup-linux-powerpc64le-gnu': 4.45.1 + '@rollup/rollup-linux-riscv64-gnu': 4.45.1 + '@rollup/rollup-linux-riscv64-musl': 4.45.1 + '@rollup/rollup-linux-s390x-gnu': 4.45.1 + '@rollup/rollup-linux-x64-gnu': 4.45.1 + '@rollup/rollup-linux-x64-musl': 4.45.1 + '@rollup/rollup-win32-arm64-msvc': 4.45.1 + '@rollup/rollup-win32-ia32-msvc': 4.45.1 + '@rollup/rollup-win32-x64-msvc': 4.45.1 + fsevents: 2.3.3 + + run-applescript@7.0.0: {} + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + + sass@1.81.0: + dependencies: + chokidar: 4.0.3 + immutable: 5.1.3 + source-map-js: 1.2.1 + optionalDependencies: + '@parcel/watcher': 2.5.1 + + scroll-into-view-if-needed@2.2.31: + dependencies: + compute-scroll-into-view: 1.0.20 + + semver@6.3.1: {} + + semver@7.7.2: {} + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + signal-exit@4.1.0: {} + + sirv@3.0.1: + dependencies: + '@polka/url': 1.0.0-next.29 + mrmime: 2.0.1 + totalist: 3.0.1 + + slate-history@0.66.0(slate@0.72.8): + dependencies: + is-plain-object: 5.0.0 + slate: 0.72.8 + + slate@0.72.8: + dependencies: + immer: 9.0.21 + is-plain-object: 5.0.0 + tiny-warning: 1.0.3 + + snabbdom@3.6.2: {} + + sortablejs@1.14.0: {} + + source-map-js@1.2.1: {} + + source-map-support@0.5.21: + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + + source-map@0.6.1: {} + + source-map@0.7.4: {} + + speakingurl@14.0.1: {} + + ssf@0.11.2: + dependencies: + frac: 1.1.2 + + ssr-window@3.0.0: {} + + store@2.0.12: {} + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.0 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.1.0: + dependencies: + ansi-regex: 6.1.0 + + strip-final-newline@4.0.0: {} + + strip-json-comments@3.1.1: {} + + sucrase@3.35.0: + dependencies: + '@jridgewell/gen-mapping': 0.3.12 + commander: 4.1.1 + glob: 10.4.5 + lines-and-columns: 1.2.4 + mz: 2.7.0 + pirates: 4.0.7 + ts-interface-checker: 0.1.13 + + superjson@2.2.2: + dependencies: + copy-anything: 3.0.5 + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + supports-preserve-symlinks-flag@1.0.0: {} + + svgo@3.3.2: + dependencies: + '@trysound/sax': 0.2.0 + commander: 7.2.0 + css-select: 5.2.2 + css-tree: 2.3.1 + css-what: 6.2.2 + csso: 5.0.5 + picocolors: 1.1.1 + + synckit@0.11.11: + dependencies: + '@pkgr/core': 0.2.9 + + tailwindcss@3.4.17: + dependencies: + '@alloc/quick-lru': 5.2.0 + arg: 5.0.2 + chokidar: 3.6.0 + didyoumean: 1.2.2 + dlv: 1.1.3 + fast-glob: 3.3.3 + glob-parent: 6.0.2 + is-glob: 4.0.3 + jiti: 1.21.7 + lilconfig: 3.1.3 + micromatch: 4.0.8 + normalize-path: 3.0.0 + object-hash: 3.0.0 + picocolors: 1.1.1 + postcss: 8.5.6 + postcss-import: 15.1.0(postcss@8.5.6) + postcss-js: 4.0.1(postcss@8.5.6) + postcss-load-config: 4.0.2(postcss@8.5.6) + postcss-nested: 6.2.0(postcss@8.5.6) + postcss-selector-parser: 6.1.2 + resolve: 1.22.10 + sucrase: 3.35.0 + transitivePeerDependencies: + - ts-node + + terser@5.43.1: + dependencies: + '@jridgewell/source-map': 0.3.10 + acorn: 8.15.0 + commander: 2.20.3 + source-map-support: 0.5.21 + + thenify-all@1.6.0: + dependencies: + thenify: 3.3.1 + + thenify@3.3.1: + dependencies: + any-promise: 1.3.0 + + tiny-warning@1.0.3: {} + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + totalist@3.0.1: {} + + ts-api-utils@2.1.0(typescript@5.5.4): + dependencies: + typescript: 5.5.4 + + ts-interface-checker@0.1.13: {} + + tslib@2.3.0: {} + + type-check@0.4.0: + dependencies: + prelude-ls: 1.2.1 + + type-fest@0.20.2: {} + + type@2.7.3: {} + + typescript-eslint@8.38.0(eslint@9.31.0(jiti@1.21.7))(typescript@5.5.4): + dependencies: + '@typescript-eslint/eslint-plugin': 8.38.0(@typescript-eslint/parser@8.38.0(eslint@9.31.0(jiti@1.21.7))(typescript@5.5.4))(eslint@9.31.0(jiti@1.21.7))(typescript@5.5.4) + '@typescript-eslint/parser': 8.38.0(eslint@9.31.0(jiti@1.21.7))(typescript@5.5.4) + '@typescript-eslint/typescript-estree': 8.38.0(typescript@5.5.4) + '@typescript-eslint/utils': 8.38.0(eslint@9.31.0(jiti@1.21.7))(typescript@5.5.4) + eslint: 9.31.0(jiti@1.21.7) + typescript: 5.5.4 + transitivePeerDependencies: + - supports-color + + typescript@5.5.4: {} + + ufo@1.6.1: {} + + undici-types@6.21.0: {} + + unicorn-magic@0.3.0: {} + + universalify@2.0.1: {} + + unplugin@1.16.1: + dependencies: + acorn: 8.15.0 + webpack-virtual-modules: 0.6.2 + + update-browserslist-db@1.1.3(browserslist@4.25.1): + dependencies: + browserslist: 4.25.1 + escalade: 3.2.0 + picocolors: 1.1.1 + + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 + + util-deprecate@1.0.2: {} + + vite-hot-client@2.1.0(vite@5.4.19(@types/node@20.19.9)(sass@1.81.0)(terser@5.43.1)): + dependencies: + vite: 5.4.19(@types/node@20.19.9)(sass@1.81.0)(terser@5.43.1) + + vite-plugin-compression@0.5.1(vite@5.4.19(@types/node@20.19.9)(sass@1.81.0)(terser@5.43.1)): + dependencies: + chalk: 4.1.2 + debug: 4.4.1 + fs-extra: 10.1.0 + vite: 5.4.19(@types/node@20.19.9)(sass@1.81.0)(terser@5.43.1) + transitivePeerDependencies: + - supports-color + + vite-plugin-inspect@0.8.9(rollup@4.45.1)(vite@5.4.19(@types/node@20.19.9)(sass@1.81.0)(terser@5.43.1)): + dependencies: + '@antfu/utils': 0.7.10 + '@rollup/pluginutils': 5.2.0(rollup@4.45.1) + debug: 4.4.1 + error-stack-parser-es: 0.1.5 + fs-extra: 11.3.0 + open: 10.2.0 + perfect-debounce: 1.0.0 + picocolors: 1.1.1 + sirv: 3.0.1 + vite: 5.4.19(@types/node@20.19.9)(sass@1.81.0)(terser@5.43.1) + transitivePeerDependencies: + - rollup + - supports-color + + vite-plugin-vue-devtools@7.7.7(rollup@4.45.1)(vite@5.4.19(@types/node@20.19.9)(sass@1.81.0)(terser@5.43.1))(vue@3.5.18(typescript@5.5.4)): + dependencies: + '@vue/devtools-core': 7.7.7(vite@5.4.19(@types/node@20.19.9)(sass@1.81.0)(terser@5.43.1))(vue@3.5.18(typescript@5.5.4)) + '@vue/devtools-kit': 7.7.7 + '@vue/devtools-shared': 7.7.7 + execa: 9.6.0 + sirv: 3.0.1 + vite: 5.4.19(@types/node@20.19.9)(sass@1.81.0)(terser@5.43.1) + vite-plugin-inspect: 0.8.9(rollup@4.45.1)(vite@5.4.19(@types/node@20.19.9)(sass@1.81.0)(terser@5.43.1)) + vite-plugin-vue-inspector: 5.3.2(vite@5.4.19(@types/node@20.19.9)(sass@1.81.0)(terser@5.43.1)) + transitivePeerDependencies: + - '@nuxt/kit' + - rollup + - supports-color + - vue + + vite-plugin-vue-inspector@5.3.2(vite@5.4.19(@types/node@20.19.9)(sass@1.81.0)(terser@5.43.1)): + dependencies: + '@babel/core': 7.28.0 + '@babel/plugin-proposal-decorators': 7.28.0(@babel/core@7.28.0) + '@babel/plugin-syntax-import-attributes': 7.27.1(@babel/core@7.28.0) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.28.0) + '@babel/plugin-transform-typescript': 7.28.0(@babel/core@7.28.0) + '@vue/babel-plugin-jsx': 1.4.0(@babel/core@7.28.0) + '@vue/compiler-dom': 3.5.18 + kolorist: 1.8.0 + magic-string: 0.30.17 + vite: 5.4.19(@types/node@20.19.9)(sass@1.81.0)(terser@5.43.1) + transitivePeerDependencies: + - supports-color + + vite@5.4.19(@types/node@20.19.9)(sass@1.81.0)(terser@5.43.1): + dependencies: + esbuild: 0.21.5 + postcss: 8.5.6 + rollup: 4.45.1 + optionalDependencies: + '@types/node': 20.19.9 + fsevents: 2.3.3 + sass: 1.81.0 + terser: 5.43.1 + + vscode-uri@3.1.0: {} + + vue-component-type-helpers@2.2.12: {} + + vue-demi@0.13.11(vue@3.5.18(typescript@5.5.4)): + dependencies: + vue: 3.5.18(typescript@5.5.4) + + vue-demi@0.14.10(vue@3.5.18(typescript@5.5.4)): + dependencies: + vue: 3.5.18(typescript@5.5.4) + + vue-echarts@7.0.3(@vue/runtime-core@3.5.18)(echarts@5.6.0)(vue@3.5.18(typescript@5.5.4)): + dependencies: + echarts: 5.6.0 + vue: 3.5.18(typescript@5.5.4) + vue-demi: 0.13.11(vue@3.5.18(typescript@5.5.4)) + optionalDependencies: + '@vue/runtime-core': 3.5.18 + transitivePeerDependencies: + - '@vue/composition-api' + + vue-eslint-parser@10.2.0(eslint@9.31.0(jiti@1.21.7)): + dependencies: + debug: 4.4.1 + eslint: 9.31.0(jiti@1.21.7) + eslint-scope: 8.4.0 + eslint-visitor-keys: 4.2.1 + espree: 10.4.0 + esquery: 1.6.0 + semver: 7.7.2 + transitivePeerDependencies: + - supports-color + + vue-eslint-parser@9.4.3(eslint@9.31.0(jiti@1.21.7)): + dependencies: + debug: 4.4.1 + eslint: 9.31.0(jiti@1.21.7) + eslint-scope: 7.2.2 + eslint-visitor-keys: 3.4.3 + espree: 9.6.1 + esquery: 1.6.0 + lodash: 4.17.21 + semver: 7.7.2 + transitivePeerDependencies: + - supports-color + + vue-i18n@11.1.10(vue@3.5.18(typescript@5.5.4)): + dependencies: + '@intlify/core-base': 11.1.10 + '@intlify/shared': 11.1.10 + '@vue/devtools-api': 6.6.4 + vue: 3.5.18(typescript@5.5.4) + + vue-router@4.5.1(vue@3.5.18(typescript@5.5.4)): + dependencies: + '@vue/devtools-api': 6.6.4 + vue: 3.5.18(typescript@5.5.4) + + vue-tsc@2.2.12(typescript@5.5.4): + dependencies: + '@volar/typescript': 2.4.15 + '@vue/language-core': 2.2.12(typescript@5.5.4) + typescript: 5.5.4 + + vue@3.5.18(typescript@5.5.4): + dependencies: + '@vue/compiler-dom': 3.5.18 + '@vue/compiler-sfc': 3.5.18 + '@vue/runtime-dom': 3.5.18 + '@vue/server-renderer': 3.5.18(vue@3.5.18(typescript@5.5.4)) + '@vue/shared': 3.5.18 + optionalDependencies: + typescript: 5.5.4 + + vuedraggable@4.1.0(vue@3.5.18(typescript@5.5.4)): + dependencies: + sortablejs: 1.14.0 + vue: 3.5.18(typescript@5.5.4) + + webpack-virtual-modules@0.6.2: {} + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + wildcard@1.1.2: {} + + wmf@1.0.2: {} + + word-wrap@1.2.5: {} + + word@0.3.0: {} + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.1 + string-width: 5.1.2 + strip-ansi: 7.1.0 + + wsl-utils@0.1.0: + dependencies: + is-wsl: 3.1.0 + + xlsx@0.18.5: + dependencies: + adler-32: 1.3.1 + cfb: 1.2.2 + codepage: 1.15.0 + crc-32: 1.2.2 + ssf: 0.11.2 + wmf: 1.0.2 + word: 0.3.0 + + xml-name-validator@4.0.0: {} + + y18n@5.0.8: {} + + yallist@3.1.1: {} + + yaml-eslint-parser@1.3.0: + dependencies: + eslint-visitor-keys: 3.4.3 + yaml: 2.8.0 + + yaml@2.8.0: {} + + yargs-parser@21.1.1: {} + + yargs@17.7.2: + dependencies: + cliui: 8.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + + yocto-queue@0.1.0: {} + + yoctocolors@2.1.1: {} + + zrender@5.6.1: + dependencies: + tslib: 2.3.0 diff --git a/cool-admin-vue/pnpm-workspace.yaml b/cool-admin-vue/pnpm-workspace.yaml new file mode 100644 index 0000000..66e446c --- /dev/null +++ b/cool-admin-vue/pnpm-workspace.yaml @@ -0,0 +1,6 @@ +onlyBuiltDependencies: + - '@parcel/watcher' + - core-js + - es5-ext + - esbuild + - vue-demi diff --git a/cool-admin-vue/postcss.config.js b/cool-admin-vue/postcss.config.js new file mode 100644 index 0000000..0f77216 --- /dev/null +++ b/cool-admin-vue/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {} + } +}; diff --git a/cool-admin-vue/src/App.vue b/cool-admin-vue/src/App.vue new file mode 100644 index 0000000..359a98b --- /dev/null +++ b/cool-admin-vue/src/App.vue @@ -0,0 +1,8 @@ + + + diff --git a/cool-admin-vue/src/config/dev.ts b/cool-admin-vue/src/config/dev.ts new file mode 100644 index 0000000..0501cd2 --- /dev/null +++ b/cool-admin-vue/src/config/dev.ts @@ -0,0 +1,9 @@ +import { host, value } from './proxy'; + +export default { + // 根地址 + host, + + // 请求地址 + baseUrl: `/${value}` +}; diff --git a/cool-admin-vue/src/config/index.ts b/cool-admin-vue/src/config/index.ts new file mode 100644 index 0000000..3844c5d --- /dev/null +++ b/cool-admin-vue/src/config/index.ts @@ -0,0 +1,62 @@ +import { storage } from '../cool'; +import dev from './dev'; +import prod from './prod'; + +// 是否开发模式 +export const isDev = import.meta.env.DEV; + +// 配置 +export const config = { + // 项目信息 + app: { + name: import.meta.env.VITE_NAME, + + // 菜单 + menu: { + // 是否分组显示 + isGroup: false, + // 自定义菜单列表 + list: [] + }, + + // 路由 + router: { + // 模式 + mode: import.meta.env.MODE == 'static' ? 'hash' : 'history', + // 转场动画 + transition: 'slide' + } + }, + + // 国际化配置 + i18n: { + locale: storage.get('locale') || 'zh-cn', + languages: [ + { + label: '中文', + value: 'zh-cn' + }, + { + label: '繁体中文', + value: 'zh-tw' + }, + { + label: 'English', + value: 'en' + } + ] + }, + + // 忽略规则 + ignore: { + // 不显示请求进度条 + NProgress: ['__cool_*'], + // 页面不需要登录验证 + token: [] + }, + + // 当前环境 + ...(isDev ? dev : prod) +}; + +export * from './proxy'; diff --git a/cool-admin-vue/src/config/prod.ts b/cool-admin-vue/src/config/prod.ts new file mode 100644 index 0000000..a86fbc5 --- /dev/null +++ b/cool-admin-vue/src/config/prod.ts @@ -0,0 +1,17 @@ +import { proxy } from './proxy'; + +export default { + // 根地址 + host: proxy['/prod/'].target, + + // 请求地址 + get baseUrl() { + const mode = import.meta.env.MODE; + + if (mode == 'static') { + return location.origin; + } else { + return '/api'; + } + } +}; diff --git a/cool-admin-vue/src/config/proxy.ts b/cool-admin-vue/src/config/proxy.ts new file mode 100644 index 0000000..4f4e5db --- /dev/null +++ b/cool-admin-vue/src/config/proxy.ts @@ -0,0 +1,18 @@ +const proxy = { + '/dev/': { + target: 'http://127.0.0.1:8001', + changeOrigin: true, + rewrite: (path: string) => path.replace(/^\/dev/, '') + }, + + '/prod/': { + target: 'https://show.cool-admin.com', + changeOrigin: true, + rewrite: (path: string) => path.replace(/^\/prod/, '/api') + } +}; + +const value = 'dev'; +const host = proxy[`/${value}/`]?.target; + +export { proxy, host, value }; diff --git a/cool-admin-vue/src/cool/bootstrap/eps.ts b/cool-admin-vue/src/cool/bootstrap/eps.ts new file mode 100644 index 0000000..f42ce08 --- /dev/null +++ b/cool-admin-vue/src/cool/bootstrap/eps.ts @@ -0,0 +1,62 @@ +import { merge } from 'lodash-es'; +import { BaseService, service } from '../service'; +import { isDev } from '/@/config'; +import { eps } from 'virtual:eps'; +import { hmr } from '../hooks'; + +export function createEps() { + // 设置 request 方法 + function set(d: any) { + if (d.namespace) { + const a = new BaseService(d.namespace); + + for (const i in d) { + const { path, method = 'get' } = d[i]; + + if (path) { + a.request = a.request; + + a[i] = function (data?: any) { + return this.request({ + url: path, + method, + [method.toLocaleLowerCase() == 'post' ? 'data' : 'params']: data + }); + }; + } + } + + for (const i in a) { + d[i] = a[i]; + } + } else { + for (const i in d) { + set(d[i]); + } + } + } + + // 遍历每一个方法 + set(eps.service); + + // 合并 eps + merge(service, eps.service); + + // 热更新处理 + hmr.setData('service', service); + + // 提示 + if (isDev) { + console.log('[cool-eps] updated'); + } +} + +// 监听 vite 触发事件 +if (import.meta.hot) { + import.meta.hot.on('eps-update', ({ service }) => { + if (service) { + eps.service = service; + } + createEps(); + }); +} diff --git a/cool-admin-vue/src/cool/bootstrap/index.ts b/cool-admin-vue/src/cool/bootstrap/index.ts new file mode 100644 index 0000000..fa4bd06 --- /dev/null +++ b/cool-admin-vue/src/cool/bootstrap/index.ts @@ -0,0 +1,24 @@ +import { createPinia } from 'pinia'; +import { type App } from 'vue'; +import { createModule } from './module'; +import { router } from '../router'; +import { Loading } from '../utils'; +import { createEps } from './eps'; +import 'virtual:svg-register'; + +export async function bootstrap(app: App) { + // pinia + app.use(createPinia()); + + // 路由 + app.use(router); + + // 模块 + const { eventLoop } = createModule(app); + + // eps + createEps(); + + // 加载 + Loading.set([eventLoop()]); +} diff --git a/cool-admin-vue/src/cool/bootstrap/module.ts b/cool-admin-vue/src/cool/bootstrap/module.ts new file mode 100644 index 0000000..7c3c462 --- /dev/null +++ b/cool-admin-vue/src/cool/bootstrap/module.ts @@ -0,0 +1,126 @@ +import { type App, type Directive } from 'vue'; +import { assign, isFunction, orderBy, mergeWith } from 'lodash-es'; +import { filename } from '../utils'; +import { module } from '../module'; +import { hmr } from '../hooks'; +import { config } from '/@/config'; + +// 扫描文件 +const files = import.meta.glob('/src/{modules,plugins}/*/{config.ts,service/**,directives/**}', { + eager: true, + import: 'default' +}); + +// 模块列表 +module.list = hmr.getData('modules', []); + +// 解析 +for (const i in files) { + // 分割 + const [, , type, name, action] = i.split('/'); + + // 文件名 + const n = filename(i); + + // 文件内容 + const v = files[i]; + + // 模块是否存在 + const m = module.get(name); + + // 数据 + const d = m || { + name, + type, + value: null, + services: [], + directives: [] + }; + + // 配置 + if (action == 'config.ts') { + d.value = v; + } + // 服务 + else if (action == 'service') { + const s = new (v as any)(); + + if (s) { + d.services?.push({ + path: s.namespace, + value: s + }); + } + } + // 指令 + else if (action == 'directives') { + d.directives?.push({ name: n, value: v as Directive }); + } + + if (!m) { + module.add(d); + } +} + +// 创建 +export function createModule(app: App) { + // 排序 + module.list.forEach(e => { + const d = isFunction(e.value) ? e.value(app) : e.value; + + if (d) { + assign(e, d); + } + + if (!d.order) { + e.order = 0; + } + }); + + const list = orderBy(module.list, 'order', 'desc').map(e => { + if (e.enable !== false) { + // 初始化 + e.install?.(app, e.options); + + // 注册组件 + e.components?.forEach(async (c: any) => { + const v = await (isFunction(c) ? c() : c); + const n = v.default || v; + + if (n.name) { + app.component(n.name, n); + } + }); + + // 注册指令 + e.directives?.forEach(v => { + app.directive(v.name, v.value); + }); + + // 合并忽略配置 + config.ignore = mergeWith({}, config.ignore, e.ignore, (a, b) => a?.concat(b)); + } + + // 附加值 + e.pages?.forEach(v => { + v.isPage = true; + }); + + return e; + }); + + return { + // 模块列表 + list, + // 事件加载 + async eventLoop() { + const events: any = {}; + + for (let i = 0; i < list.length; i++) { + if (list[i].onLoad) { + assign(events, await list[i]?.onLoad?.(events)); + } + } + } + }; +} diff --git a/cool-admin-vue/src/cool/hooks/browser.ts b/cool-admin-vue/src/cool/hooks/browser.ts new file mode 100644 index 0000000..77c2a9f --- /dev/null +++ b/cool-admin-vue/src/cool/hooks/browser.ts @@ -0,0 +1,41 @@ +import { useEventListener } from '@vueuse/core'; +import { reactive, watch } from 'vue'; +import { getBrowser } from '../utils'; + +// 使用 reactive 创建一个响应式的浏览器对象 +const browser = reactive(getBrowser()); + +// 存储屏幕变化事件的回调函数数组 +const events: (() => void)[] = []; + +// 监听浏览器屏幕属性的变化 +watch( + () => browser.screen, // 监听的属性 + () => { + // 当屏幕属性变化时,执行所有注册的回调函数 + events.forEach(ev => ev()); + } +); + +// 监听窗口的 resize 事件,并更新浏览器对象 +useEventListener(window, 'resize', () => { + // 使用 Object.assign 更新响应式对象的属性 + Object.assign(browser, getBrowser()); +}); + +// 导出一个自定义的 hook +export function useBrowser() { + return { + browser, // 返回响应式的浏览器对象 + // 注册屏幕变化的回调函数 + onScreenChange(ev: () => void, immediate = true) { + // 将回调函数添加到事件数组中 + events.push(ev); + + // 如果 immediate 为 true,立即执行回调函数 + if (immediate) { + ev(); + } + } + }; +} diff --git a/cool-admin-vue/src/cool/hooks/hmr.ts b/cool-admin-vue/src/cool/hooks/hmr.ts new file mode 100644 index 0000000..e9d4b15 --- /dev/null +++ b/cool-admin-vue/src/cool/hooks/hmr.ts @@ -0,0 +1,32 @@ +// 解决热更新后数据失效问题 +// 初始化数据对象,如果热更新数据存在则使用它 +const data = import.meta.hot?.data.getData?.() || {}; + +// 检查是否支持热更新 +if (import.meta.hot) { + // 将当前数据存储函数赋值给热更新数据对象 + import.meta.hot.data.getData = () => { + return data; + }; +} + +// 导出一个热更新模块对象 +export const hmr = { + data, // 当前数据对象 + + // 设置数据的方法 + setData(key: string, value: any) { + // 将指定键值对存入数据对象 + data[key] = value; + }, + + // 获取数据的方法 + getData(key: string, defaultValue?: any) { + // 如果指定键不存在且提供了默认值,则设置默认值 + if (defaultValue !== undefined && !data[key]) { + this.setData(key, defaultValue); + } + // 返回指定键的值 + return data[key]; + } +}; diff --git a/cool-admin-vue/src/cool/hooks/index.ts b/cool-admin-vue/src/cool/hooks/index.ts new file mode 100644 index 0000000..ff551a7 --- /dev/null +++ b/cool-admin-vue/src/cool/hooks/index.ts @@ -0,0 +1,58 @@ +import { getCurrentInstance, type Ref, reactive } from 'vue'; +import { useRoute, useRouter } from 'vue-router'; +import { service } from '../service'; +import { useBrowser } from './browser'; +import { useMitt } from './mitt'; + +// 创建一个响应式的 refs 对象,并提供设置 refs 的方法 +export function useRefs() { + const refs = reactive<{ [key: string]: any }>({}); + + // 设置 refs 的方法,返回一个函数用于更新特定 ref + function setRefs(name: string) { + return (el: any) => { + refs[name] = el; + return () => refs[name]; // 返回一个函数用于获取当前 ref + }; + } + + return { refs, setRefs }; +} + +// 获取指定名称的父组件实例,并将其暴露的属性赋值给传入的 Ref +export function useParent(name: string, r: Ref) { + const instance = getCurrentInstance(); + + if (instance) { + let parent = instance.proxy?.$.parent; + + // 遍历父组件链,直到找到匹配的组件名称 + while (parent && parent.type?.name !== name) { + parent = parent?.parent; + } + + // 如果找到匹配的父组件,将其暴露的属性赋值给 Ref + if (parent && parent.type.name === name) { + r.value = parent.exposed; + } + } + + return r; +} + +// 组合多个功能模块,返回一个包含服务、路由、事件总线等的对象 +export function useCool() { + return { + service, + route: useRoute(), + router: useRouter(), + mitt: useMitt(), + ...useBrowser(), + ...useRefs() + }; +} + +// 导出其他模块的功能 +export * from './browser'; +export * from './hmr'; +export * from './mitt'; diff --git a/cool-admin-vue/src/cool/hooks/mitt.ts b/cool-admin-vue/src/cool/hooks/mitt.ts new file mode 100644 index 0000000..a530ac0 --- /dev/null +++ b/cool-admin-vue/src/cool/hooks/mitt.ts @@ -0,0 +1,9 @@ +import Mitt, { type Emitter } from 'mitt'; +import { hmr } from './hmr'; + +export const mitt: Emitter = hmr.getData('mitt', Mitt()); + +// 返回 mitt 实例,用于在应用中进行事件的发布和订阅 +export function useMitt() { + return mitt; +} diff --git a/cool-admin-vue/src/cool/index.ts b/cool-admin-vue/src/cool/index.ts new file mode 100644 index 0000000..bb7cc6a --- /dev/null +++ b/cool-admin-vue/src/cool/index.ts @@ -0,0 +1,7 @@ +export * from './service'; +export * from './bootstrap'; +export * from './hooks'; +export * from './module'; +export * from './router'; +export * from './types'; +export { storage } from './utils'; diff --git a/cool-admin-vue/src/cool/index.vue b/cool-admin-vue/src/cool/index.vue new file mode 100644 index 0000000..7ee30f4 --- /dev/null +++ b/cool-admin-vue/src/cool/index.vue @@ -0,0 +1,39 @@ + + + diff --git a/cool-admin-vue/src/cool/module/index.ts b/cool-admin-vue/src/cool/module/index.ts new file mode 100644 index 0000000..a289d67 --- /dev/null +++ b/cool-admin-vue/src/cool/module/index.ts @@ -0,0 +1,43 @@ +import type { Module } from '../types'; +import { hmr } from '../hooks'; +import { ctx } from 'virtual:ctx'; + +// 获取模块列表,若不存在则初始化为空数组 +const list: Module[] = hmr.getData('modules', []); + +// 定义模块对象 +const module = { + // 模块列表 + list, + + // 模块目录 + dirs: ctx.modules, + + // 请求对象,初始化为已解决的 Promise + req: Promise.resolve(), + + // 根据名称获取模块 + get(name: string): Module { + // 使用 find 方法查找模块,假设模块名称是唯一的 + return this.list.find(e => e.name == name)!; + }, + + // 获取模块的配置选项 + config(name: string) { + // 如果模块存在,返回其配置选项,否则返回空对象 + return this.get(name).options || {}; + }, + + // 添加新模块到列表中 + add(data: Module) { + this.list.push(data); + }, + + // 返回请求对象 + wait() { + return this.req; + } +}; + +// 导出模块对象 +export { module }; diff --git a/cool-admin-vue/src/cool/router/index.ts b/cool-admin-vue/src/cool/router/index.ts new file mode 100644 index 0000000..41b4165 --- /dev/null +++ b/cool-admin-vue/src/cool/router/index.ts @@ -0,0 +1,247 @@ +import { ElMessage } from 'element-plus'; +import { + createRouter, + createRouterMatcher, + createWebHashHistory, + createWebHistory, + type RouteRecordRaw +} from 'vue-router'; +import { type Router, storage, module } from '/@/cool'; +import { isArray } from 'lodash-es'; +import { useBase } from '/$/base'; +import { Loading } from '../utils'; +import { config, isDev } from '/@/config'; + +// 基本路径 +const baseUrl = import.meta.env.BASE_URL; + +// 扫描文件 +const files = import.meta.glob(['/src/modules/*/{views,pages}/**/*', '!**/components']); + +// 默认路由 +const routes: RouteRecordRaw[] = [ + { + path: '/', + name: 'index', + component: () => import('/$/base/pages/main/index.vue'), + children: [] + }, + { + path: '/:catchAll(.*)', + name: '404', + component: () => import('/$/base/pages/error/404.vue') + } +]; + +// 创建路由器 +const router = createRouter({ + history: + config.app.router.mode == 'history' + ? createWebHistory(baseUrl) + : createWebHashHistory(baseUrl), + routes +}) as Router; + +// 组件加载后 +router.beforeResolve(() => { + Loading.close(); +}); + +let lock = false; + +// 错误监听 +router.onError((error: Error) => { + if (!lock) { + lock = true; + + // 显示错误信息 + ElMessage.error(`页面存在错误:${error.message}`); + console.error(error); + + // 如果是动态加载模块失败的错误,且非开发环境,则刷新页面 + if (error.message?.includes('Failed to fetch dynamically imported module')) { + if (!isDev) { + window.location.reload(); + } + } + + // 短暂延迟后解锁,允许后续错误处理 + setTimeout(() => { + lock = false; + }, 0); + } +}); + +// 添加视图,页面路由 +router.append = function (routeData) { + if (!routeData) { + return false; // 如果没有路由数据,直接返回 + } + + // 确保 routeData 是数组 + const routeList = isArray(routeData) ? routeData : [routeData]; + + routeList.forEach(route => { + if (!route.meta) { + route.meta = {}; // 初始化 meta 对象 + } + + // 如果没有指定组件路径 + if (!route.component) { + const viewPath = route.viewPath; + + if (viewPath) { + if (viewPath.startsWith('http')) { + // 如果是外部链接,使用 iframe 组件 + route.meta.iframeUrl = viewPath; + route.component = () => import('/$/base/views/frame.vue'); + } else { + // 从文件系统中动态导入组件 + route.component = files['/src/' + viewPath.replace('cool/', '')]; + } + } else if (!route.redirect) { + // 如果没有组件路径且没有重定向,默认重定向到 404 + route.redirect = '/404'; + } + } + + // 支持 props 接收参数 + route.props = true; + + // 标记为动态添加的路由 + route.meta.dynamic = true; + + // 判断是页面还是视图,并添加到相应的路由 + if (route.isPage || route.viewPath?.includes('/pages/')) { + router.addRoute(route); + } else { + router.addRoute('index', route); + } + }); +}; + +// 删除路由 +router.del = function (routeName) { + const allRoutes = router.getRoutes(); + + allRoutes.forEach(route => { + if (route.name === routeName) { + router.removeRoute(routeName); // 移除指定名称的路由 + } + }); +}; + +// 清空路由 +router.clear = function () { + const allRoutes = router.getRoutes(); + + allRoutes.forEach(route => { + if (route.name && route.meta?.dynamic) { + router.removeRoute(route.name); // 移除所有动态添加的路由 + } + }); +}; + +// 找路由 +router.find = function (path: string) { + const { menu } = useBase(); + + // 获取已注册的路由 + const registeredRoutes = router.getRoutes(); + + // 构建路由列表,包括已注册的路由、菜单配置和模块自定义路由 + const routeList: any[] = [ + ...registeredRoutes.map(route => ({ + ...route, + isReg: true + })), + ...menu.routes, + ...module.list.flatMap(module => (module.views || []).concat(module.pages || [])) + ]; + + let isRegistered = false; + let matchedRoute: (typeof routeList)[number] | undefined; + + // 创建路由匹配器 + const matcher = createRouterMatcher(routeList, {}); + + // 查找匹配的路由 + matcher.getRoutes().find(route => { + const routeRegex = new RegExp(route.re); + + if (routeRegex.test(path)) { + if (path === '/') { + // 如果路径是根路径,查找标记为首页的路由 + matchedRoute = routeList.find(route => route.meta?.isHome); + } else { + // 否则查找路径匹配且名称不是 'index' 的路由 + matchedRoute = routeList.find( + r => r.path === route.record.path && r.name !== 'index' + ); + } + + if (matchedRoute) { + isRegistered = !!matchedRoute.isReg; // 检查路由是否已注册 + } + + return true; + } + return false; + }); + + return { + route: matchedRoute, + isReg: isRegistered + }; +}; + +// 路由守卫 +router.beforeEach(async (to, from, next) => { + // 等待应用配置加载完 + await Loading.wait(); + + // 获取用户和进程数据 + const { user, process } = useBase(); + + // 查找路由信息 + const { isReg, route } = router.find(to.path); + + // 如果路由不存在 + if (!route) { + next(user.token ? '/404' : '/login'); // 根据用户登录状态重定向 + return; + } + + // 如果路由未注册 + if (!isReg) { + router.append(route); // 注册路由 + next(to.fullPath); // 重定向到原路径 + return; + } + + // 如果用户已登录 + if (user.token) { + if (to.path.includes('/login')) { + // 如果在登录页且 Token 未过期,重定向到首页 + if (!storage.isExpired('token')) { + next('/'); + return; + } + } else { + process.add(to); // 添加路由进程 + } + } else { + // 清除用户信息 + user.clear(); + + // 如果路径不在忽略 Token 验证的列表中,重定向到登录页 + if (!config.ignore.token.some(ignorePath => to.path === ignorePath)) { + next('/login'); + return; + } + } + + next(); // 继续导航 +}); + +export { router }; diff --git a/cool-admin-vue/src/cool/service/base.ts b/cool-admin-vue/src/cool/service/base.ts new file mode 100644 index 0000000..5cee840 --- /dev/null +++ b/cool-admin-vue/src/cool/service/base.ts @@ -0,0 +1,86 @@ +import { config } from '/@/config'; +import { request } from './request'; +import { AxiosRequestConfig } from 'axios'; + +export class BaseService { + namespace?: string; + + constructor(namespace?: string) { + if (namespace) { + this.namespace = namespace; + } + } + + // 发送请求 + async request(options: AxiosRequestConfig = {}) { + let url = options.url; + + if (url && url.indexOf('http') < 0) { + if (this.namespace) { + url = this.namespace + url; + } + + if (options.proxy !== false) { + url = config.baseUrl + '/' + url; + } + } + + return request({ + ...options, + url + }); + } + + // 获取列表 + async list(data: any) { + return this.request({ + url: '/list', + method: 'POST', + data + }); + } + + // 分页查询 + async page(data: any) { + return this.request({ + url: '/page', + method: 'POST', + data + }); + } + + // 获取信息 + async info(params: any) { + return this.request({ + url: '/info', + params + }); + } + + // 更新数据 + async update(data: any) { + return this.request({ + url: '/update', + method: 'POST', + data + }); + } + + // 删除数据 + async delete(data: any) { + return this.request({ + url: '/delete', + method: 'POST', + data + }); + } + + // 添加数据 + async add(data: any) { + return this.request({ + url: '/add', + method: 'POST', + data + }); + } +} diff --git a/cool-admin-vue/src/cool/service/index.ts b/cool-admin-vue/src/cool/service/index.ts new file mode 100644 index 0000000..1474751 --- /dev/null +++ b/cool-admin-vue/src/cool/service/index.ts @@ -0,0 +1,10 @@ +import { hmr } from '../hooks'; +import { BaseService } from './base'; + +// service 数据集合 +export const service: Eps.Service = hmr.getData('service', { + request: new BaseService().request +}); + +export * from './base'; +export * from './stream'; diff --git a/cool-admin-vue/src/cool/service/request.ts b/cool-admin-vue/src/cool/service/request.ts new file mode 100644 index 0000000..51b16d5 --- /dev/null +++ b/cool-admin-vue/src/cool/service/request.ts @@ -0,0 +1,168 @@ +import axios from 'axios'; +import NProgress from 'nprogress'; +import 'nprogress/nprogress.css'; +import { ElMessage } from 'element-plus'; +import { endsWith } from 'lodash-es'; +import { storage } from '/@/cool/utils'; +import { useBase } from '/$/base'; +import { router } from '../router'; +import { config, isDev } from '/@/config'; + +// 创建 axios 实例 +const request = axios.create({ + timeout: import.meta.env.VITE_TIMEOUT, // 设置请求超时时间 + withCredentials: false // 不携带凭证 +}); + +// 配置 NProgress +NProgress.configure({ + showSpinner: true // 显示加载指示器 +}); + +// 请求队列,用于存储待处理的请求 +let queue: Array<(token: string) => void> = []; + +// 标识是否正在刷新 token +let isRefreshing = false; + +// 请求拦截器 +request.interceptors.request.use( + (req: any) => { + const { user } = useBase(); // 获取用户信息 + + if (req.url) { + // 控制请求进度条的显示 + if ( + !config.ignore.NProgress.some(e => req.url.match(new RegExp(`${e}.*`))) && + (req.NProgress ?? true) + ) { + NProgress.start(); + } + } + + // 在开发环境中打印请求信息 + if (isDev) { + console.group(req.url); + console.log('method:', req.method); + console.table('data:', req.method == 'get' ? req.params : req.data); + console.groupEnd(); + } + + if (!req.headers) { + req.headers = {}; + } + + // 设置请求头中的语言 + if (req.headers['language'] !== null) { + req.headers['language'] = config.i18n.locale; + } + + // 验证 token + if (user.token) { + // 设置请求头中的 Authorization + if (req.headers['Authorization'] !== null) { + req.headers['Authorization'] = user.token; + } + + // 忽略特定请求 + if (['eps', 'refreshToken'].some(e => endsWith(req.url, e))) { + return req; + } + + // 判断 token 是否过期 + if (storage.isExpired('token')) { + // 判断 refreshToken 是否过期 + if (storage.isExpired('refreshToken')) { + ElMessage.error('登录状态已失效,请重新登录'); + user.logout(); + } else { + // 如果不在刷新中,则刷新 token + if (!isRefreshing) { + isRefreshing = true; + + user.refreshToken() + .then(token => { + queue.forEach(cb => cb(token)); // 处理队列中的请求 + queue = []; + isRefreshing = false; + }) + .catch(() => { + user.logout(); + }); + } + + // 返回一个新的 Promise,等待 token 刷新完成 + return new Promise(resolve => { + queue.push(token => { + if (req.headers) { + req.headers['Authorization'] = token; // 重新设置 token + } + resolve(req); + }); + }); + } + } + } + + return req; + }, + error => { + return Promise.reject(error); // 请求错误处理 + } +); + +// 响应拦截器 +request.interceptors.response.use( + res => { + NProgress.done(); // 结束进度条 + + if (!res?.data) { + return res; + } + + const { code, data, message } = res.data; + + if (!code) { + return res.data; // 返回数据 + } + + switch (code) { + case 1000: + return data; // 成功返回数据 + default: + return Promise.reject({ code, message }); // 处理错误 + } + }, + async error => { + NProgress.done(); // 结束进度条 + + if (error.response) { + const { status } = error.response; + const { user } = useBase(); + + if (status == 401) { + user.logout(); // 未授权,登出用户 + } else { + if (!isDev) { + switch (status) { + case 403: + router.push('/403'); // 禁止访问 + break; + + case 500: + router.push('/500'); // 服务器错误 + break; + + case 502: + router.push('/502'); // 网关错误 + break; + } + } + } + } + + return Promise.reject({ message: error.response?.data?.message || error.message }); // 返回错误信息 + } +); + +export { request }; diff --git a/cool-admin-vue/src/cool/service/stream.ts b/cool-admin-vue/src/cool/service/stream.ts new file mode 100644 index 0000000..c941719 --- /dev/null +++ b/cool-admin-vue/src/cool/service/stream.ts @@ -0,0 +1,103 @@ +import { useBase } from '/$/base'; +import { config } from '/@/config'; + +export function useStream() { + const { user } = useBase(); + let abortController: AbortController | null = null; + + // 调用 + async function invoke({ + url, + method = 'POST', + data, + cb + }: { + url: string; + method?: string; + data?: any; + cb?: (result: any) => void; + }) { + abortController = new AbortController(); + + let cacheText = ''; + + return fetch(config.baseUrl + url, { + method, + headers: { + Authorization: user.token, + 'Content-Type': 'application/json' + }, + body: JSON.stringify(data), + signal: abortController?.signal + }) + .then(res => { + if (res.body) { + const reader = res.body.getReader(); + const decoder = new TextDecoder('utf-8'); + const stream = new ReadableStream({ + start(controller) { + function push() { + reader.read().then(({ done, value }) => { + if (done) { + controller.close(); + return; + } + + let text = decoder.decode(value, { stream: true }); + + if (cb) { + if (cacheText) { + text = cacheText + text; + } + + if (text.indexOf('data:') == 0) { + text = '\n\n' + text; + } + + try { + const arr = text + .split(/\n\ndata:/g) + .filter(Boolean) + .map(e => JSON.parse(e)); + + arr.forEach(cb); + + cacheText = ''; + } catch (err) { + console.error('[parse text]', text); + cacheText = text; + } + } + + controller.enqueue(text); + push(); + }); + } + push(); + } + }); + + return new Response(stream); + } + + return res; + }) + .catch(err => { + console.error(err); + throw err; + }); + } + + // 取消 + function cancel() { + if (abortController) { + abortController.abort(); + abortController = null; + } + } + + return { + invoke, + cancel + }; +} diff --git a/cool-admin-vue/src/cool/types/index.ts b/cool-admin-vue/src/cool/types/index.ts new file mode 100644 index 0000000..8d9772e --- /dev/null +++ b/cool-admin-vue/src/cool/types/index.ts @@ -0,0 +1,60 @@ +import type { Component, Directive, App } from 'vue'; +import type { Router as VueRouter, RouteRecordRaw } from 'vue-router'; + +export declare type Merge = Omit & B; + +export declare interface ModuleConfig { + enable?: boolean; + name?: string; + label?: string; + description?: string; + order?: number; + version?: string; + logo?: string; + author?: string; + updateTime?: string; + demo?: { name: string; component: Component }[] | string; + doc?: string; + ignore?: { + NProgress?: string[]; + token?: string[]; + }; + options?: { + [key: string]: any; + }; + toolbar?: { + order?: number; + pc?: boolean; + h5?: boolean; + component: any; + }; + index?: { + component: any; + }; + components?: Component[]; + views?: RouteRecordRaw[]; + pages?: (RouteRecordRaw & { isPage?: boolean })[]; + install?(app: App, options?: any): any; + onLoad?(events: { + hasToken: (cb: () => Promise | void) => Promise | void; + [key: string]: any; + }): Promise<{ [key: string]: any }> | Promise | void; +} + +export declare interface Module extends ModuleConfig { + name: string; + options: { + [key: string]: any; + }; + value?: any; + services?: { path: string; value: any }[]; + directives?: { name: string; value: Directive }[]; + [key: string]: any; +} + +export declare interface Router extends VueRouter { + find(path: string): { route: RouteRecordRaw; isReg: boolean }; + del(name: string): void; + clear(): void; + append(data: any | any[]): void; +} diff --git a/cool-admin-vue/src/cool/utils/index.ts b/cool-admin-vue/src/cool/utils/index.ts new file mode 100644 index 0000000..8962b79 --- /dev/null +++ b/cool-admin-vue/src/cool/utils/index.ts @@ -0,0 +1,301 @@ +import { isArray, isNumber, isString, orderBy } from 'lodash-es'; +import { resolveComponent } from 'vue'; +import storage from './storage'; + +// 首字母大写 +export function firstUpperCase(value: string): string { + return value.replace(/\b(\w)(\w*)/g, function ($0, $1, $2) { + return $1.toUpperCase() + $2; + }); +} + +// 获取方法名 +export function getNames(value: any) { + return Object.getOwnPropertyNames(value.constructor.prototype); +} + +// 获取地址栏参数 +export function getUrlParam(name: string): string | null { + const reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)'); + const r = window.location.search.substr(1).match(reg); + if (r != null) return decodeURIComponent(r[2]); + return null; +} + +// 文件名 +export function filename(path: string): string { + return basename(path.substring(0, path.lastIndexOf('.'))); +} + +// 路径名称 +export function basename(path: string): string { + let index = path.lastIndexOf('/'); + index = index > -1 ? index : path.lastIndexOf('\\'); + if (index < 0) { + return path; + } + return path.substring(index + 1); +} + +// 文件扩展名 +export function extname(path: string): string { + return path.substring(path.lastIndexOf('.') + 1).split(/(\?|&)/)[0]; +} + +// 横杠转驼峰 +export function toCamel(str: string): string { + return str.replace(/([^-])(?:-+([^-]))/g, function ($0, $1, $2) { + return $1 + $2.toUpperCase(); + }); +} + +// uuid +export function uuid(separator = '-'): string { + const s: any[] = []; + const hexDigits = '0123456789abcdef'; + for (let i = 0; i < 36; i++) { + s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1); + } + s[14] = '4'; + s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1); + s[8] = s[13] = s[18] = s[23] = separator; + + return s.join(''); +} + +// 浏览器信息 +export function getBrowser() { + const { clientHeight, clientWidth } = document.documentElement; + + // 浏览器信息 + const ua = navigator.userAgent.toLowerCase(); + + // 浏览器类型 + let type = (ua.match(/firefox|chrome|safari|opera/g) || 'other')[0]; + + if ((ua.match(/msie|trident/g) || [])[0]) { + type = 'msie'; + } + + // 平台标签 + let tag = ''; + + const isTocuh = + 'ontouchstart' in window || ua.indexOf('touch') !== -1 || ua.indexOf('mobile') !== -1; + if (isTocuh) { + if (ua.indexOf('ipad') !== -1) { + tag = 'pad'; + } else if (ua.indexOf('mobile') !== -1) { + tag = 'mobile'; + } else if (ua.indexOf('android') !== -1) { + tag = 'androidPad'; + } else { + tag = 'pc'; + } + } else { + tag = 'pc'; + } + + // 浏览器内核 + let prefix = ''; + + switch (type) { + case 'chrome': + case 'safari': + case 'mobile': + prefix = 'webkit'; + break; + case 'msie': + prefix = 'ms'; + break; + case 'firefox': + prefix = 'Moz'; + break; + case 'opera': + prefix = 'O'; + break; + default: + prefix = 'webkit'; + break; + } + + // 操作平台 + const plat = ua.indexOf('android') > 0 ? 'android' : navigator.platform.toLowerCase(); + + // 屏幕信息 + let screen = 'full'; + + if (clientWidth < 768) { + screen = 'xs'; + } else if (clientWidth < 992) { + screen = 'sm'; + } else if (clientWidth < 1200) { + screen = 'md'; + } else if (clientWidth < 1920) { + screen = 'xl'; + } else { + screen = 'full'; + } + + // 是否 ios + const isIOS = !!navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); + + // 是否 PC 端 + const isPC = tag === 'pc'; + + // 是否移动端 + const isMobile = isPC ? false : true; + + // 是否移动端 + 屏幕宽过小 + const isMini = screen === 'xs' || isMobile; + + return { + height: clientHeight, + width: clientWidth, + type, + plat, + tag, + prefix, + isMobile, + isIOS, + isPC, + isMini, + screen + }; +} + +// 路径转数组 +export function deepPaths(paths: string[], splitor?: string) { + const list: any[] = []; + + paths.forEach(e => { + const arr: string[] = e.split(splitor || '/').filter(Boolean); + + let c = list; + + arr.forEach((a, i) => { + let d = c.find(e => e.label == a); + + if (!d) { + d = { + label: a, + value: a, + children: arr[i + 1] ? [] : null + }; + + c.push(d); + } + + if (d.children) { + c = d.children; + } + }); + }); + + return list; +} + +// 列表转树形 +export function deepTree(list: any[], sort?: 'desc' | 'asc'): any[] { + const newList: any[] = []; + const map: any = {}; + + orderBy(list, 'orderNum', sort) + .map(e => { + map[e.id] = e; + return e; + }) + .forEach(e => { + const parent = map[e.parentId]; + + if (parent) { + (parent.children || (parent.children = [])).push(e); + } else { + newList.push(e); + } + }); + + return newList; +} + +// 树形转列表 +export function revDeepTree(list: any[]) { + const arr: any[] = []; + let id = 0; + + function deep(list: any[], parentId: number) { + list.forEach(e => { + if (!e.id) { + e.id = ++id; + } + + if (!e.parentId) { + e.parentId = parentId; + } + + arr.push(e); + + if (e.children && isArray(e.children) && e.id) { + deep(e.children, e.id); + } + }); + } + + deep(list || [], 0); + + return arr; +} + +// 路径转对象 +export function path2Obj(list: any[]) { + const data: any = {}; + + list.forEach(({ path, value }) => { + if (path) { + const arr: string[] = path.split('/'); + const parents = arr.slice(0, arr.length - 1); + const name = basename(path).replace('.ts', ''); + + let curr = data; + + parents.forEach(k => { + if (!curr[k]) { + curr[k] = {}; + } + + curr = curr[k]; + }); + + curr[name] = value; + } + }); + + return data; +} + +// 是否是组件 +export function isComponent(name: string) { + return !isString(resolveComponent(name)); +} + +// 是否Promise +export function isPromise(val: any) { + return val && Object.prototype.toString.call(val) === '[object Promise]'; +} + +// 单位转换 +export function parsePx(val: string | number) { + return isNumber(val) ? `${val}px` : val; +} + +// 延迟 +export function sleep(duration: number) { + return new Promise(resolve => { + setTimeout(() => { + resolve(true); + }, duration); + }); +} + +export { storage }; +export * from './loading'; diff --git a/cool-admin-vue/src/cool/utils/loading.ts b/cool-admin-vue/src/cool/utils/loading.ts new file mode 100644 index 0000000..ac552ff --- /dev/null +++ b/cool-admin-vue/src/cool/utils/loading.ts @@ -0,0 +1,37 @@ +export const Loading = { + resolve: null as (() => void) | null, + next: null as Promise | null, + + async set(list: Promise[]) { + try { + await Promise.all(list); + } catch (e) { + console.error('[Loading] Error: ', e); + } + + if (this.resolve) { + this.resolve(); + } + }, + + async wait() { + if (this.next) { + return this.next; + } + return Promise.resolve(); + }, + + close() { + const el = document.getElementById('Loading'); + + if (el) { + setTimeout(() => { + el.classList.add('is-hide'); + }, 0); + } + } +}; + +Loading.next = new Promise(resolve => { + Loading.resolve = resolve; +}); diff --git a/cool-admin-vue/src/cool/utils/storage.ts b/cool-admin-vue/src/cool/utils/storage.ts new file mode 100644 index 0000000..1763c6e --- /dev/null +++ b/cool-admin-vue/src/cool/utils/storage.ts @@ -0,0 +1,83 @@ +import store from 'store'; + +export default { + // 后缀标识 + suffix: '_deadtime', + + /** + * 获取 + * @param {string} key 关键字 + */ + get(key: string) { + return store.get(key); + }, + + /** + * 获取全部 + */ + info() { + const data: Record = {}; + + store.each((value: any, key: any) => { + data[key] = value; + }); + + return data; + }, + + /** + * 设置 + * @param {string} key 关键字 + * @param {*} value 值 + * @param {number} expires 过期时间 + */ + set(key: string, value: any, expires?: number) { + store.set(key, value); + + if (expires) { + const expirationTime = Date.now() + expires * 1000; + store.set(`${key}${this.suffix}`, expirationTime); + } + }, + + /** + * 是否过期 + * @param {string} key 关键字 + */ + isExpired(key: string) { + const expiration = this.getExpiration(key) || 0; + return expiration - Date.now() <= 2000; + }, + + /** + * 获取到期时间 + * @param {string} key 关键字 + */ + getExpiration(key: string) { + return this.get(key + this.suffix); + }, + + /** + * 移除 + * @param {string} key 关键字 + */ + remove(key: string) { + store.remove(key); + this.removeExpiration(key); + }, + + /** + * 移除到期时间 + * @param {string} key 关键字 + */ + removeExpiration(key: string) { + store.remove(key + this.suffix); + }, + + /** + * 清理 + */ + clearAll() { + store.clearAll(); + } +}; diff --git a/cool-admin-vue/src/main.ts b/cool-admin-vue/src/main.ts new file mode 100644 index 0000000..870bc82 --- /dev/null +++ b/cool-admin-vue/src/main.ts @@ -0,0 +1,14 @@ +import { createApp } from 'vue'; +import App from './App.vue'; +import { bootstrap } from './cool'; + +const app = createApp(App); + +// 启动 +bootstrap(app) + .then(() => { + app.mount('#app'); + }) + .catch(err => { + console.error('COOL-ADMIN 启动失败', err); + }); diff --git a/cool-admin-vue/src/modules/base/components/avatar/index.tsx b/cool-admin-vue/src/modules/base/components/avatar/index.tsx new file mode 100644 index 0000000..8e38926 --- /dev/null +++ b/cool-admin-vue/src/modules/base/components/avatar/index.tsx @@ -0,0 +1,53 @@ +import { defineComponent, type PropType } from 'vue'; +import { UserFilled } from '@element-plus/icons-vue'; + +export default defineComponent({ + name: 'cl-avatar', + + props: { + modelValue: String, + src: String, + icon: { + type: null, + default: UserFilled + }, + size: { + type: [String, Number] as PropType<'large' | 'default' | 'small' | number>, + default: 40 + }, + shape: { + type: String as PropType<'circle' | 'square'>, + default: 'square' + }, + fit: { + type: String as PropType<'fill' | 'contain' | 'cover' | 'none' | 'scale-down'>, + default: 'cover' + } + }, + + setup(props) { + return () => { + const height = props.size + 'px'; + + return ( +
+ +
+ ); + }; + } +}); diff --git a/cool-admin-vue/src/modules/base/components/code/json.vue b/cool-admin-vue/src/modules/base/components/code/json.vue new file mode 100644 index 0000000..2cd15f8 --- /dev/null +++ b/cool-admin-vue/src/modules/base/components/code/json.vue @@ -0,0 +1,156 @@ + + + + + diff --git a/cool-admin-vue/src/modules/base/components/dept/check.vue b/cool-admin-vue/src/modules/base/components/dept/check.vue new file mode 100644 index 0000000..acfe65e --- /dev/null +++ b/cool-admin-vue/src/modules/base/components/dept/check.vue @@ -0,0 +1,111 @@ + + + + + diff --git a/cool-admin-vue/src/modules/base/components/dept/select.vue b/cool-admin-vue/src/modules/base/components/dept/select.vue new file mode 100644 index 0000000..b1a02ba --- /dev/null +++ b/cool-admin-vue/src/modules/base/components/dept/select.vue @@ -0,0 +1,87 @@ + + + + + diff --git a/cool-admin-vue/src/modules/base/components/editor/index.tsx b/cool-admin-vue/src/modules/base/components/editor/index.tsx new file mode 100644 index 0000000..d4059a9 --- /dev/null +++ b/cool-admin-vue/src/modules/base/components/editor/index.tsx @@ -0,0 +1,44 @@ +import { defineComponent, h, resolveComponent, ref, reactive, watch } from 'vue'; +import { isComponent } from '/@/cool/utils'; +import { assign } from 'lodash-es'; +import { useI18n } from 'vue-i18n'; + +export default defineComponent({ + name: 'cl-editor', + + props: { + name: { + type: String, + required: true + } + }, + + setup(props, { slots, expose }) { + const Editor = ref(); + const ex = reactive({}); + const { t } = useI18n(); + + watch(Editor, v => { + if (v) { + assign(ex, v); + } + }); + + expose(ex); + + return () => { + return isComponent(props.name) ? ( + h( + resolveComponent(props.name), + { + ...props, + ref: Editor + }, + slots + ) + ) : ( + + ); + }; + } +}); diff --git a/cool-admin-vue/src/modules/base/components/icon/svg.vue b/cool-admin-vue/src/modules/base/components/icon/svg.vue new file mode 100644 index 0000000..3bee493 --- /dev/null +++ b/cool-admin-vue/src/modules/base/components/icon/svg.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/cool-admin-vue/src/modules/base/components/image/index.vue b/cool-admin-vue/src/modules/base/components/image/index.vue new file mode 100644 index 0000000..cc36494 --- /dev/null +++ b/cool-admin-vue/src/modules/base/components/image/index.vue @@ -0,0 +1,111 @@ + + + + + diff --git a/cool-admin-vue/src/modules/base/components/link/index.vue b/cool-admin-vue/src/modules/base/components/link/index.vue new file mode 100644 index 0000000..1aa496a --- /dev/null +++ b/cool-admin-vue/src/modules/base/components/link/index.vue @@ -0,0 +1,75 @@ + + + + + diff --git a/cool-admin-vue/src/modules/base/components/menu/check.vue b/cool-admin-vue/src/modules/base/components/menu/check.vue new file mode 100644 index 0000000..12f9d93 --- /dev/null +++ b/cool-admin-vue/src/modules/base/components/menu/check.vue @@ -0,0 +1,99 @@ + + + + + diff --git a/cool-admin-vue/src/modules/base/components/menu/file.vue b/cool-admin-vue/src/modules/base/components/menu/file.vue new file mode 100644 index 0000000..597f398 --- /dev/null +++ b/cool-admin-vue/src/modules/base/components/menu/file.vue @@ -0,0 +1,174 @@ + + + + + diff --git a/cool-admin-vue/src/modules/base/components/menu/icon.vue b/cool-admin-vue/src/modules/base/components/menu/icon.vue new file mode 100644 index 0000000..02d5b3f --- /dev/null +++ b/cool-admin-vue/src/modules/base/components/menu/icon.vue @@ -0,0 +1,84 @@ + + + + + diff --git a/cool-admin-vue/src/modules/base/components/menu/perms.vue b/cool-admin-vue/src/modules/base/components/menu/perms.vue new file mode 100644 index 0000000..ee043e9 --- /dev/null +++ b/cool-admin-vue/src/modules/base/components/menu/perms.vue @@ -0,0 +1,95 @@ + + + + + diff --git a/cool-admin-vue/src/modules/base/components/menu/select.vue b/cool-admin-vue/src/modules/base/components/menu/select.vue new file mode 100644 index 0000000..86c8435 --- /dev/null +++ b/cool-admin-vue/src/modules/base/components/menu/select.vue @@ -0,0 +1,86 @@ + + + + + diff --git a/cool-admin-vue/src/modules/base/components/num/index.vue b/cool-admin-vue/src/modules/base/components/num/index.vue new file mode 100644 index 0000000..017d2ed --- /dev/null +++ b/cool-admin-vue/src/modules/base/components/num/index.vue @@ -0,0 +1,61 @@ + + + + + diff --git a/cool-admin-vue/src/modules/base/config.ts b/cool-admin-vue/src/modules/base/config.ts new file mode 100644 index 0000000..cac5e6f --- /dev/null +++ b/cool-admin-vue/src/modules/base/config.ts @@ -0,0 +1,94 @@ +import { type ModuleConfig } from '/@/cool'; +import { useStore } from './store'; +import { config } from '/@/config'; +import { t } from '/@/plugins/i18n'; +import './static/css/index.scss'; + +export default (): ModuleConfig => { + return { + order: 99, + ignore: { + NProgress: [ + '/base/open/eps', + '/base/comm/person', + '/base/comm/permmenu', + '/base/comm/upload', + '/base/comm/uploadMode' + ], + token: ['/login', '/401', '/403', '/404', '/500', '/502'] + }, + components: Object.values(import.meta.glob('./components/**/*.{vue,tsx}')), + views: [ + { + path: '/my/info', + meta: { + label: t('个人中心') + }, + component: () => import('./views/info.vue') + } + ], + pages: [ + { + path: '/login', + component: () => import('./pages/login/index.vue') + }, + ...['401', '403', '404', '500', '502'].map(code => { + return { + path: `/${code}`, + meta: { + process: false + }, + component: () => import(`./pages/error/${code}.vue`) + }; + }) + ], + install() { + // 设置标题 + document.title = config.app.name; + + // 设置加载文案 + const loading = document.querySelector('#Loading'); + + if (loading) { + const name = loading.querySelector('.preload__name'); + const title = loading.querySelector('.preload__title'); + const subTitle = loading.querySelector('.preload__sub-title'); + + if (name) { + name.innerHTML = config.app.name; + } + if (title) { + title.innerHTML = t('正在加载资源...'); + } + if (subTitle) { + subTitle.innerHTML = t('初次加载资源可能需要较多时间,请耐心等待'); + } + } + }, + async onLoad() { + const { user, menu, app } = useStore(); + + // token 事件 + async function hasToken(cb: () => Promise | void) { + if (cb) { + app.addEvent('hasToken', cb); + + if (user.token) { + await cb(); + } + } + } + + await hasToken(async () => { + // 获取用户信息 + user.get(); + // 获取菜单权限 + await menu.get(); + }); + + return { + hasToken + }; + } + }; +}; diff --git a/cool-admin-vue/src/modules/base/directives/permission.ts b/cool-admin-vue/src/modules/base/directives/permission.ts new file mode 100644 index 0000000..969863a --- /dev/null +++ b/cool-admin-vue/src/modules/base/directives/permission.ts @@ -0,0 +1,13 @@ +import { checkPerm } from '../utils/permission'; + +function change(el: HTMLElement, binding: { value: any }) { + el.style.display = checkPerm(binding.value) ? el.getAttribute('_display') || '' : 'none'; +} + +export default { + created(el: HTMLElement, binding: { value: any }) { + el.setAttribute('_display', el.style.display || ''); + change(el, binding); + }, + updated: change +}; diff --git a/cool-admin-vue/src/modules/base/index.ts b/cool-admin-vue/src/modules/base/index.ts new file mode 100644 index 0000000..b09f19d --- /dev/null +++ b/cool-admin-vue/src/modules/base/index.ts @@ -0,0 +1,9 @@ +import { useStore } from './store'; + +export function useBase() { + return { + ...useStore() + }; +} + +export * from './utils'; diff --git a/cool-admin-vue/src/modules/base/locales/en.json b/cool-admin-vue/src/modules/base/locales/en.json new file mode 100644 index 0000000..f48f186 --- /dev/null +++ b/cool-admin-vue/src/modules/base/locales/en.json @@ -0,0 +1,143 @@ +{ + "删除": "Delete", + "新增成员": "Add Member", + "目录": "Directory", + "菜单": "Menu", + "权限": "Permission", + "是否显示": "Show/Hide", + "图标": "Icon", + "节点路由": "Node Route", + "路由缓存": "Route Cache", + "文件路径": "File Path", + "排序号": "Sorting Number", + "节点类型": "Node Type", + "节点名称": "Node Name", + "上级节点": "Parent Node", + "请输入节点路由,如:/test": "Please enter the node route, e.g.: /test", + "开启": "Enable", + "关闭": "Disable", + "请填写排序号": "Please fill in the sorting number", + "导入": "Import", + "如遇到问题无法导入菜单,请检查文件并尝试重新导入。": "If you encounter problems importing the menu, please check the file and try to import again.", + "角色标签": "Character Tag", + "请填写新密码": "Please fill in the new password", + "保存修改": "Save Changes", + "修改成功": "Modification Successful", + "拼命加载中": "Loading拼命", + "转移": "Transfer", + "搜索用户名、姓名": "Search Username, Name", + "用户列表": "User List", + "用户名": "Username", + "姓名": "Name", + "部门名称": "Department Name", + "角色": "Role", + "状态": "Status", + "手机号码": "Mobile Phone Number", + "选择头像": "Select Avatar", + "密码": "Password", + "密码长度在 6 到 16 个字符": "Password length should be between 6 and 16 characters", + "邮箱": "Email", + "启用": "Enable", + "禁用": "Disable", + "部门转移": "Department Transfer", + "请输入备注": "Please enter remarks", + "清空": "Clear", + "日志保存天数": "Log save days", + "搜索请求地址、用户昵称、ip": "Search request address, user nickname, IP", + "用户ID": "User ID", + "用户昵称": "User nickname", + "请求地址": "Request address", + "参数": "Parameter", + "请求时间": "Request time", + "保存成功": "Save successful", + "是否要清空日志?": "Do you want to clear the log?", + "提示": "Tip", + "清空成功": "Clear successful", + "基本信息": "Basic information", + "头像": "Avatar", + "昵称": "Nickname", + "请填写昵称": "Please fill in the nickname", + "原密码": "Original password", + "请填写原密码": "Please fill in the original password", + "新密码": "New password", + "菜单导入": "Menu Import", + "添加": "Add", + "导入成功": "Import Success", + "{file}文件格式错误:{error}": "{file} File Format Error: {error}", + "导出": "Export", + "选择菜单": "Select Menu", + "请先选择要导出的菜单": "Please select the menu to export first", + "菜单数据": "Menu Data", + "退出登录": "Log out", + "确定退出登录吗?": "Are you sure you want to log out?", + "搜索关键字": "Search Keyword", + "关闭当前": "Close Current", + "关闭其他": "Close Others", + "关闭所有": "Close All", + "{label} 没有子菜单,请先添加": "{label} has no sub-menus. Please add them first", + "快速开发后台权限管理系统": "Quick Development Background Permission Management System", + "请输入用户名": "Please enter your username", + "请输入密码": "Please enter your password", + "验证码": "Verification Code", + "登录": "Log in", + "用户名不能为空": "Username cannot be empty", + "密码不能为空": "Password cannot be empty", + "图片验证码不能为空": "Image verification code cannot be empty", + "验证码获取失败": "Failed to obtain verification code", + "马上回来": "Be right back", + "糟糕,出了点问题": "Oops, something went wrong", + "找不到您要查找的页面": "Page not found", + "您无权访问此页面": "You are not authorized to access this page", + "认证失败,请重新登录!": "Authentication failed, please log in again!", + "返回首页": "Return to home page", + "重新登录": "Log in again", + "返回登录页": "Return to login page", + "自定义输入": "Custom input", + "请输入": "Please enter", + "输入关键字进行过滤": "Enter keywords for filtering", + "复制": "Copy", + "行为": "Behavior", + "ip": "IP", + "数据类型 0-字符串 1-富文本 2-文件 ": "Data type 0 - String 1 - Rich text 2 - File", + "键": "Key", + "选择部门": "Select Department", + "请选择部门": "Please Select Department", + "转移到新部门,是否继续?": "Transfer to a new department. Continue?", + "转移成功": "Transfer Successful", + "组织架构": "Organization Structure", + "刷新": "Refresh", + "拖动排序": "Drag to Sort", + "编辑部门": "Edit Department", + "上级部门": "Superior Department", + "排序": "Sort", + "新增部门 “{name}” 成功": "Successfully added new department “{name}”", + "删除成功": "Delete Successful", + "“{name}” 部门的用户已成功转移到 “{parentName}” 部门。": "Users in the “{name}” department have been successfully transferred to the “{parentName}” department.", + "此操作将会删除 “{name}” 部门的所有用户,是否确认?": "This operation will delete all users in the “{name}” department. Are you sure?", + "直接删除": "Delete Directly", + "保留用户": "Keep Users", + "部门架构已发生改变,是否保存?": "The department structure has changed. Do you want to save?", + "更新排序成功": "Successfully updated sorting", + "新增": "Add", + "编辑": "Edit", + "个人中心": "Personal Center", + "正在加载资源...": "Loading resources...", + "初次加载资源可能需要较多时间,请耐心等待": "It may take some time for the initial resource loading. Please wait patiently.", + "搜索名称": "Search Name", + "是否关联上下级": "Whether to associate with superiors and subordinates", + "名称": "Name", + "标识": "Identifier", + "备注": "Remarks", + "功能权限": "Function Permissions", + "数据权限": "Data Permissions", + "创建时间": "Creation Time", + "更新时间": "Update Time", + "数据类型": "Data Type", + "搜索名称、keyName": "Search Name, keyName", + "字符串": "String", + "富文本": "Rich Text", + "文件": "File", + "请输入Key": "Please enter Key", + "类型": "Type", + "数据": "Data" +} \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/locales/zh-cn.json b/cool-admin-vue/src/modules/base/locales/zh-cn.json new file mode 100644 index 0000000..ac9bfdf --- /dev/null +++ b/cool-admin-vue/src/modules/base/locales/zh-cn.json @@ -0,0 +1,143 @@ +{ + "个人中心": "个人中心", + "正在加载资源...": "正在加载资源...", + "初次加载资源可能需要较多时间,请耐心等待": "初次加载资源可能需要较多时间,请耐心等待", + "搜索名称": "搜索名称", + "是否关联上下级": "是否关联上下级", + "名称": "名称", + "标识": "标识", + "备注": "备注", + "功能权限": "功能权限", + "数据权限": "数据权限", + "创建时间": "创建时间", + "更新时间": "更新时间", + "数据类型": "数据类型", + "搜索名称、keyName": "搜索名称、keyName", + "字符串": "字符串", + "富文本": "富文本", + "文件": "文件", + "请输入Key": "请输入Key", + "类型": "类型", + "数据": "数据", + "请输入备注": "请输入备注", + "清空": "清空", + "日志保存天数": "日志保存天数", + "搜索请求地址、用户昵称、ip": "搜索请求地址、用户昵称、ip", + "用户ID": "用户ID", + "用户昵称": "用户昵称", + "请求地址": "请求地址", + "参数": "参数", + "请求时间": "请求时间", + "保存成功": "保存成功", + "是否要清空日志?": "是否要清空日志?", + "提示": "提示", + "清空成功": "清空成功", + "基本信息": "基本信息", + "头像": "头像", + "昵称": "昵称", + "请填写昵称": "请填写昵称", + "原密码": "原密码", + "请填写原密码": "请填写原密码", + "新密码": "新密码", + "请填写新密码": "请填写新密码", + "保存修改": "保存修改", + "修改成功": "修改成功", + "拼命加载中": "拼命加载中", + "转移": "转移", + "搜索用户名、姓名": "搜索用户名、姓名", + "用户列表": "用户列表", + "用户名": "用户名", + "姓名": "姓名", + "部门名称": "部门名称", + "角色": "角色", + "状态": "状态", + "手机号码": "手机号码", + "选择头像": "选择头像", + "密码": "密码", + "密码长度在 6 到 16 个字符": "密码长度在 6 到 16 个字符", + "邮箱": "邮箱", + "启用": "启用", + "禁用": "禁用", + "部门转移": "部门转移", + "选择部门": "选择部门", + "请选择部门": "请选择部门", + "转移到新部门,是否继续?": "转移到新部门,是否继续?", + "转移成功": "转移成功", + "组织架构": "组织架构", + "刷新": "刷新", + "拖动排序": "拖动排序", + "编辑部门": "编辑部门", + "上级部门": "上级部门", + "排序": "排序", + "新增部门 “{name}” 成功": "新增部门 “{name}” 成功", + "删除成功": "删除成功", + "“{name}” 部门的用户已成功转移到 “{parentName}” 部门。": "“{name}” 部门的用户已成功转移到 “{parentName}” 部门。", + "此操作将会删除 “{name}” 部门的所有用户,是否确认?": "此操作将会删除 “{name}” 部门的所有用户,是否确认?", + "直接删除": "直接删除", + "保留用户": "保留用户", + "部门架构已发生改变,是否保存?": "部门架构已发生改变,是否保存?", + "更新排序成功": "更新排序成功", + "新增": "新增", + "编辑": "编辑", + "删除": "删除", + "新增成员": "新增成员", + "目录": "目录", + "菜单": "菜单", + "权限": "权限", + "是否显示": "是否显示", + "图标": "图标", + "节点路由": "节点路由", + "路由缓存": "路由缓存", + "文件路径": "文件路径", + "排序号": "排序号", + "节点类型": "节点类型", + "节点名称": "节点名称", + "上级节点": "上级节点", + "请输入节点路由,如:/test": "请输入节点路由,如:/test", + "开启": "开启", + "关闭": "关闭", + "请填写排序号": "请填写排序号", + "导入": "导入", + "如遇到问题无法导入菜单,请检查文件并尝试重新导入。": "如遇到问题无法导入菜单,请检查文件并尝试重新导入。", + "菜单导入": "菜单导入", + "添加": "添加", + "导入成功": "导入成功", + "{file}文件格式错误:{error}": "{file}文件格式错误:{error}", + "导出": "导出", + "选择菜单": "选择菜单", + "请先选择要导出的菜单": "请先选择要导出的菜单", + "菜单数据": "菜单数据", + "退出登录": "退出登录", + "确定退出登录吗?": "确定退出登录吗?", + "搜索关键字": "搜索关键字", + "关闭当前": "关闭当前", + "关闭其他": "关闭其他", + "关闭所有": "关闭所有", + "{label} 没有子菜单,请先添加": "{label} 没有子菜单,请先添加", + "快速开发后台权限管理系统": "快速开发后台权限管理系统", + "请输入用户名": "请输入用户名", + "请输入密码": "请输入密码", + "验证码": "验证码", + "登录": "登录", + "用户名不能为空": "用户名不能为空", + "密码不能为空": "密码不能为空", + "图片验证码不能为空": "图片验证码不能为空", + "验证码获取失败": "验证码获取失败", + "马上回来": "马上回来", + "糟糕,出了点问题": "糟糕,出了点问题", + "找不到您要查找的页面": "找不到您要查找的页面", + "您无权访问此页面": "您无权访问此页面", + "认证失败,请重新登录!": "认证失败,请重新登录!", + "返回首页": "返回首页", + "重新登录": "重新登录", + "返回登录页": "返回登录页", + "自定义输入": "自定义输入", + "请输入": "请输入", + "输入关键字进行过滤": "输入关键字进行过滤", + "复制": "复制", + "行为": "行为", + "ip": "ip", + "数据类型 0-字符串 1-富文本 2-文件 ": "数据类型 0-字符串 1-富文本 2-文件 ", + "键": "键", + "角色标签": "角色标签" +} \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/locales/zh-tw.json b/cool-admin-vue/src/modules/base/locales/zh-tw.json new file mode 100644 index 0000000..867fe59 --- /dev/null +++ b/cool-admin-vue/src/modules/base/locales/zh-tw.json @@ -0,0 +1,143 @@ +{ + "请填写新密码": "請填寫新密碼", + "保存修改": "保存修改", + "修改成功": "修改成功", + "拼命加载中": "拼命加載中", + "转移": "轉移", + "搜索用户名、姓名": "搜索用戶名、姓名", + "用户列表": "用戶列表", + "用户名": "用戶名", + "姓名": "姓名", + "部门名称": "部門名稱", + "角色": "角色", + "状态": "狀態", + "手机号码": "手機號碼", + "选择头像": "選擇頭像", + "密码": "密碼", + "密码长度在 6 到 16 个字符": "密碼長度在6到16個字符", + "邮箱": "郵箱", + "启用": "啟用", + "禁用": "禁用", + "部门转移": "部門轉移", + "请输入备注": "請輸入備註", + "清空": "清空", + "日志保存天数": "日誌保存天數", + "搜索请求地址、用户昵称、ip": "搜索請求地址、用戶暱稱、ip", + "用户ID": "用戶ID", + "用户昵称": "用戶暱稱", + "请求地址": "請求地址", + "参数": "參數", + "请求时间": "請求時間", + "保存成功": "保存成功", + "是否要清空日志?": "是否要清空日誌?", + "提示": "提示", + "清空成功": "清空成功", + "基本信息": "基本信息", + "头像": "頭像", + "昵称": "暱稱", + "请填写昵称": "請填寫暱稱", + "原密码": "原密碼", + "请填写原密码": "請填寫原密碼", + "新密码": "新密碼", + "角色标签": "角色標籤", + "个人中心": "個人中心", + "正在加载资源...": "正在加載資源...", + "初次加载资源可能需要较多时间,请耐心等待": "初次加載資源可能需要較多時間,請耐心等待", + "搜索名称": "搜索名稱", + "是否关联上下级": "是否關聯上下級", + "名称": "名稱", + "标识": "標識", + "备注": "備註", + "功能权限": "功能權限", + "数据权限": "數據權限", + "创建时间": "創建時間", + "更新时间": "更新時間", + "数据类型": "數據類型", + "搜索名称、keyName": "搜索名稱、keyName", + "字符串": "字串", + "富文本": "富文本", + "文件": "文件", + "请输入Key": "請輸入Key", + "类型": "類型", + "数据": "數據", + "删除": "刪除", + "新增成员": "新增成員", + "目录": "目錄", + "菜单": "菜單", + "权限": "權限", + "是否显示": "是否顯示", + "图标": "圖標", + "节点路由": "節點路由", + "路由缓存": "路由緩存", + "文件路径": "文件路徑", + "排序号": "排序號", + "节点类型": "節點類型", + "节点名称": "節點名稱", + "上级节点": "上級節點", + "请输入节点路由,如:/test": "請輸入節點路由,如:/test", + "开启": "開啟", + "关闭": "關閉", + "请填写排序号": "請填寫排序號", + "导入": "導入", + "如遇到问题无法导入菜单,请检查文件并尝试重新导入。": "如遇到問題無法導入菜單,請檢查文件並嘗試重新導入。", + "用户名不能为空": "用戶名不得為空", + "密码不能为空": "密碼不得為空", + "图片验证码不能为空": "圖片驗證碼不得為空", + "验证码获取失败": "驗證碼獲取失敗", + "马上回来": "馬上回來", + "糟糕,出了点问题": "糟糕,出了點問題", + "找不到您要查找的页面": "找不到您要查找的頁面", + "您无权访问此页面": "您無權訪問此頁面", + "认证失败,请重新登录!": "認證失敗,請重新登錄!", + "返回首页": "返回首頁", + "重新登录": "重新登錄", + "返回登录页": "返回登錄頁", + "自定义输入": "自定義輸入", + "请输入": "請輸入", + "输入关键字进行过滤": "輸入關鍵字進行過濾", + "复制": "複製", + "行为": "行為", + "ip": "IP", + "数据类型 0-字符串 1-富文本 2-文件 ": "數據類型 0-字串 1-富文本 2-文件 ", + "键": "鍵", + "菜单导入": "菜單導入", + "添加": "添加", + "导入成功": "導入成功", + "{file}文件格式错误:{error}": "{file}文件格式錯誤:{error}", + "导出": "導出", + "选择菜单": "選擇菜單", + "请先选择要导出的菜单": "請先選擇要導出的菜單", + "菜单数据": "菜單數據", + "退出登录": "退出登錄", + "确定退出登录吗?": "確定退出登錄嗎?", + "搜索关键字": "搜索關鍵字", + "关闭当前": "關閉當前", + "关闭其他": "關閉其他", + "关闭所有": "關閉所有", + "{label} 没有子菜单,请先添加": "{label} 沒有子菜單,請先添加", + "快速开发后台权限管理系统": "快速開發後台權限管理系統", + "请输入用户名": "請輸入用戶名", + "请输入密码": "請輸入密碼", + "验证码": "驗證碼", + "登录": "登錄", + "选择部门": "選擇部門", + "请选择部门": "請選擇部門", + "转移到新部门,是否继续?": "轉移到新部門,是否繼續?", + "转移成功": "轉移成功", + "组织架构": "組織架構", + "刷新": "刷新", + "拖动排序": "拖動排序", + "编辑部门": "編輯部門", + "上级部门": "上級部門", + "排序": "排序", + "新增部门 “{name}” 成功": "新增部門 “{name}” 成功", + "删除成功": "刪除成功", + "“{name}” 部门的用户已成功转移到 “{parentName}” 部门。": "“{name}” 部門的用戶已成功轉移到 “{parentName}” 部門。", + "此操作将会删除 “{name}” 部门的所有用户,是否确认?": "此操作將會刪除 “{name}” 部門的所有用戶,是否確認?", + "直接删除": "直接刪除", + "保留用户": "保留用戶", + "部门架构已发生改变,是否保存?": "部門架構已發生改變,是否保存?", + "更新排序成功": "更新排序成功", + "新增": "新增", + "编辑": "編輯" +} \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/pages/error/401.vue b/cool-admin-vue/src/modules/base/pages/error/401.vue new file mode 100644 index 0000000..d2a6108 --- /dev/null +++ b/cool-admin-vue/src/modules/base/pages/error/401.vue @@ -0,0 +1,11 @@ + + + diff --git a/cool-admin-vue/src/modules/base/pages/error/403.vue b/cool-admin-vue/src/modules/base/pages/error/403.vue new file mode 100644 index 0000000..179617a --- /dev/null +++ b/cool-admin-vue/src/modules/base/pages/error/403.vue @@ -0,0 +1,11 @@ + + + diff --git a/cool-admin-vue/src/modules/base/pages/error/404.vue b/cool-admin-vue/src/modules/base/pages/error/404.vue new file mode 100644 index 0000000..a3e1de1 --- /dev/null +++ b/cool-admin-vue/src/modules/base/pages/error/404.vue @@ -0,0 +1,11 @@ + + + diff --git a/cool-admin-vue/src/modules/base/pages/error/500.vue b/cool-admin-vue/src/modules/base/pages/error/500.vue new file mode 100644 index 0000000..e067e2f --- /dev/null +++ b/cool-admin-vue/src/modules/base/pages/error/500.vue @@ -0,0 +1,11 @@ + + + diff --git a/cool-admin-vue/src/modules/base/pages/error/502.vue b/cool-admin-vue/src/modules/base/pages/error/502.vue new file mode 100644 index 0000000..d9680d7 --- /dev/null +++ b/cool-admin-vue/src/modules/base/pages/error/502.vue @@ -0,0 +1,11 @@ + + + diff --git a/cool-admin-vue/src/modules/base/pages/error/components/error-page.vue b/cool-admin-vue/src/modules/base/pages/error/components/error-page.vue new file mode 100644 index 0000000..bfb7527 --- /dev/null +++ b/cool-admin-vue/src/modules/base/pages/error/components/error-page.vue @@ -0,0 +1,140 @@ + + + + + diff --git a/cool-admin-vue/src/modules/base/pages/login/components/pic-captcha.vue b/cool-admin-vue/src/modules/base/pages/login/components/pic-captcha.vue new file mode 100644 index 0000000..87af631 --- /dev/null +++ b/cool-admin-vue/src/modules/base/pages/login/components/pic-captcha.vue @@ -0,0 +1,110 @@ + + + + + diff --git a/cool-admin-vue/src/modules/base/pages/login/index.vue b/cool-admin-vue/src/modules/base/pages/login/index.vue new file mode 100644 index 0000000..2a235b8 --- /dev/null +++ b/cool-admin-vue/src/modules/base/pages/login/index.vue @@ -0,0 +1,307 @@ + + + + + diff --git a/cool-admin-vue/src/modules/base/pages/login/static/bg.svg b/cool-admin-vue/src/modules/base/pages/login/static/bg.svg new file mode 100644 index 0000000..a96530d --- /dev/null +++ b/cool-admin-vue/src/modules/base/pages/login/static/bg.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + diff --git a/cool-admin-vue/src/modules/base/pages/main/components/amenu.vue b/cool-admin-vue/src/modules/base/pages/main/components/amenu.vue new file mode 100644 index 0000000..b34000d --- /dev/null +++ b/cool-admin-vue/src/modules/base/pages/main/components/amenu.vue @@ -0,0 +1,151 @@ + + + + + diff --git a/cool-admin-vue/src/modules/base/pages/main/components/bmenu.tsx b/cool-admin-vue/src/modules/base/pages/main/components/bmenu.tsx new file mode 100644 index 0000000..6f0be72 --- /dev/null +++ b/cool-admin-vue/src/modules/base/pages/main/components/bmenu.tsx @@ -0,0 +1,153 @@ +import { defineComponent, h, watch } from 'vue'; +import { useBase } from '/$/base'; +import { useCool } from '/@/cool'; +import { debounce } from 'lodash-es'; + +export default defineComponent({ + name: 'b-menu', + + props: { + keyWord: String + }, + + setup(props) { + const { router, route, browser, refs, setRefs } = useCool(); + const { menu, app } = useBase(); + + // 页面跳转 + function onSelect(url: string) { + if (url != route.path) { + router.push(url); + } + + // 小屏下点击收起左侧菜单 + if (browser.isMini) { + app.fold(true); + } + } + + // 渲染子菜单 + function renderMenu() { + function deep(list: Menu.Item[], show?: boolean) { + const keyWord = props.keyWord?.toLowerCase() || ''; + + function filterMenu(item: Menu.Item): boolean { + if (!item.isShow) return false; + + if (show) { + return true; + } + + if (item.meta?.label?.toLowerCase().includes(keyWord)) return true; + + if (item.children) { + return item.children.some(filterMenu); + } + + return false; + } + + return list.filter(filterMenu).map(e => { + if (e.meta?.label?.toLowerCase().includes(keyWord)) { + show = true; + } + + const item = (e: Menu.Item) => { + const arr = [ + , + + {e.meta?.label} + + ]; + + if (e.type == 1 && e.badge) { + arr.push( +
+ {e.badge} +
+ ); + } + return arr; + }; + + if (e.type == 0) { + return h( + , + { + index: String(e.id), + key: e.id, + popperClass: 'app-slider__menu' + }, + { + title() { + return item(e); + }, + default() { + return deep(e.children || [], show); + } + } + ); + } else { + return h( + , + { + index: e.meta?.isHome ? '/' : e.path, + key: e.id + }, + { + default() { + return item(e); + } + } + ); + } + }); + } + + return deep(menu.list); + } + + // 展开所有 + const expand = debounce(() => { + if (!props.keyWord) { + return; + } + + const deep = (list: Menu.Item[]) => { + list.forEach(e => { + if (e.type == 0) { + try { + refs.menu?.open(String(e.id)); + } catch (err) { } + + if (e.children) { + deep(e.children); + } + } + }); + }; + + deep(menu.list); + }, 300); + + watch(() => props.keyWord, expand); + + return () => { + return ( +
+ + {renderMenu()} + +
+ ); + }; + } +}); diff --git a/cool-admin-vue/src/modules/base/pages/main/components/global.vue b/cool-admin-vue/src/modules/base/pages/main/components/global.vue new file mode 100644 index 0000000..7134814 --- /dev/null +++ b/cool-admin-vue/src/modules/base/pages/main/components/global.vue @@ -0,0 +1,37 @@ + + + diff --git a/cool-admin-vue/src/modules/base/pages/main/components/process.vue b/cool-admin-vue/src/modules/base/pages/main/components/process.vue new file mode 100644 index 0000000..cf82f72 --- /dev/null +++ b/cool-admin-vue/src/modules/base/pages/main/components/process.vue @@ -0,0 +1,279 @@ + + + + + diff --git a/cool-admin-vue/src/modules/base/pages/main/components/route-nav.vue b/cool-admin-vue/src/modules/base/pages/main/components/route-nav.vue new file mode 100644 index 0000000..54b9bfb --- /dev/null +++ b/cool-admin-vue/src/modules/base/pages/main/components/route-nav.vue @@ -0,0 +1,87 @@ + + + + + diff --git a/cool-admin-vue/src/modules/base/pages/main/components/slider.vue b/cool-admin-vue/src/modules/base/pages/main/components/slider.vue new file mode 100644 index 0000000..635262c --- /dev/null +++ b/cool-admin-vue/src/modules/base/pages/main/components/slider.vue @@ -0,0 +1,188 @@ + + + + + diff --git a/cool-admin-vue/src/modules/base/pages/main/components/topbar.vue b/cool-admin-vue/src/modules/base/pages/main/components/topbar.vue new file mode 100644 index 0000000..5559d13 --- /dev/null +++ b/cool-admin-vue/src/modules/base/pages/main/components/topbar.vue @@ -0,0 +1,219 @@ + + + + + + + diff --git a/cool-admin-vue/src/modules/base/pages/main/components/views.vue b/cool-admin-vue/src/modules/base/pages/main/components/views.vue new file mode 100644 index 0000000..0ae0219 --- /dev/null +++ b/cool-admin-vue/src/modules/base/pages/main/components/views.vue @@ -0,0 +1,99 @@ + + + + + diff --git a/cool-admin-vue/src/modules/base/pages/main/index.vue b/cool-admin-vue/src/modules/base/pages/main/index.vue new file mode 100644 index 0000000..e078958 --- /dev/null +++ b/cool-admin-vue/src/modules/base/pages/main/index.vue @@ -0,0 +1,132 @@ + + + + + diff --git a/cool-admin-vue/src/modules/base/static/css/index.scss b/cool-admin-vue/src/modules/base/static/css/index.scss new file mode 100644 index 0000000..e31abc7 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/css/index.scss @@ -0,0 +1,81 @@ +#app { + height: 100vh; + width: 100vw; + overflow: hidden; +} + +:root { + --bg-color: var(--el-fill-color-lighter); +} + +a { + text-decoration: none; +} + +input, +button { + outline: none; +} + +input { + &:-webkit-autofill { + box-shadow: 0 0 0px 1000px white inset; + } +} + +// scrollbar +::-webkit-scrollbar { + width: 6px; +} + +::-webkit-scrollbar:horizontal { + height: 6px; +} + +::-webkit-scrollbar-track { + border-radius: 10px; +} + +::-webkit-scrollbar-thumb { + background-color: #0003; + border-radius: 10px; + transition: all 0.2s ease-in-out; +} + +::-webkit-scrollbar-thumb:hover { + cursor: pointer; + background-color: #0000004d; +} + +.dark ::-webkit-scrollbar-thumb { + background-color: #fff3; +} + +.dark ::-webkit-scrollbar-thumb:hover { + background-color: #fff6; +} + +// custom +.cl-comm__icon { + display: flex; + align-items: center; + justify-content: center; + height: 26px; + width: 26px; + background-color: var(--el-bg-color); + border: 1px solid var(--el-fill-color-dark); + border-radius: 6px; + transition: all 0.2s ease-in-out; + outline: none; + cursor: pointer; + flex-shrink: 0; + + .cl-svg { + font-size: 16px; + color: var(--el-text-color-primary); + } + + &:hover { + background-color: var(--el-fill-color-light); + } +} diff --git a/cool-admin-vue/src/modules/base/static/svg/amount.svg b/cool-admin-vue/src/modules/base/static/svg/amount.svg new file mode 100644 index 0000000..78fae7f --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/amount.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/back.svg b/cool-admin-vue/src/modules/base/static/svg/back.svg new file mode 100644 index 0000000..1212879 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/back.svg @@ -0,0 +1,17 @@ + + + + diff --git a/cool-admin-vue/src/modules/base/static/svg/close-border.svg b/cool-admin-vue/src/modules/base/static/svg/close-border.svg new file mode 100644 index 0000000..4c125fa --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/close-border.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/close.svg b/cool-admin-vue/src/modules/base/static/svg/close.svg new file mode 100644 index 0000000..b45fab1 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/close.svg @@ -0,0 +1,21 @@ + + + + + diff --git a/cool-admin-vue/src/modules/base/static/svg/delete.svg b/cool-admin-vue/src/modules/base/static/svg/delete.svg new file mode 100644 index 0000000..fccd1e8 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/delete.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/edit.svg b/cool-admin-vue/src/modules/base/static/svg/edit.svg new file mode 100644 index 0000000..e1de5c5 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/edit.svg @@ -0,0 +1,21 @@ + + + + + diff --git a/cool-admin-vue/src/modules/base/static/svg/exit.svg b/cool-admin-vue/src/modules/base/static/svg/exit.svg new file mode 100644 index 0000000..f6071c5 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/exit.svg @@ -0,0 +1,25 @@ + + + + + + diff --git a/cool-admin-vue/src/modules/base/static/svg/expand.svg b/cool-admin-vue/src/modules/base/static/svg/expand.svg new file mode 100644 index 0000000..453a7b3 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/expand.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/export.svg b/cool-admin-vue/src/modules/base/static/svg/export.svg new file mode 100644 index 0000000..65c8e16 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/export.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/fail.svg b/cool-admin-vue/src/modules/base/static/svg/fail.svg new file mode 100644 index 0000000..545abc6 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/fail.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/fold.svg b/cool-admin-vue/src/modules/base/static/svg/fold.svg new file mode 100644 index 0000000..feb1d41 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/fold.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/github.svg b/cool-admin-vue/src/modules/base/static/svg/github.svg new file mode 100644 index 0000000..a2663ad --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/github.svg @@ -0,0 +1,17 @@ + + + + diff --git a/cool-admin-vue/src/modules/base/static/svg/home.svg b/cool-admin-vue/src/modules/base/static/svg/home.svg new file mode 100644 index 0000000..d6f732d --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/home.svg @@ -0,0 +1,17 @@ + + + + diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-activity.svg b/cool-admin-vue/src/modules/base/static/svg/icon-activity.svg new file mode 100644 index 0000000..be00ee9 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-activity.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-amount.svg b/cool-admin-vue/src/modules/base/static/svg/icon-amount.svg new file mode 100644 index 0000000..13c68d9 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-amount.svg @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-app.svg b/cool-admin-vue/src/modules/base/static/svg/icon-app.svg new file mode 100644 index 0000000..1d82a1c --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-app.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-approve.svg b/cool-admin-vue/src/modules/base/static/svg/icon-approve.svg new file mode 100644 index 0000000..e77593c --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-approve.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-auth.svg b/cool-admin-vue/src/modules/base/static/svg/icon-auth.svg new file mode 100644 index 0000000..b299f59 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-auth.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-ban.svg b/cool-admin-vue/src/modules/base/static/svg/icon-ban.svg new file mode 100644 index 0000000..0376a77 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-ban.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-call.svg b/cool-admin-vue/src/modules/base/static/svg/icon-call.svg new file mode 100644 index 0000000..d35cabc --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-call.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-camera.svg b/cool-admin-vue/src/modules/base/static/svg/icon-camera.svg new file mode 100644 index 0000000..97dff8f --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-camera.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-card.svg b/cool-admin-vue/src/modules/base/static/svg/icon-card.svg new file mode 100644 index 0000000..f6ae0e8 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-card.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-cart.svg b/cool-admin-vue/src/modules/base/static/svg/icon-cart.svg new file mode 100644 index 0000000..f6833eb --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-cart.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-common.svg b/cool-admin-vue/src/modules/base/static/svg/icon-common.svg new file mode 100644 index 0000000..7fe6060 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-common.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-component.svg b/cool-admin-vue/src/modules/base/static/svg/icon-component.svg new file mode 100644 index 0000000..a44dae7 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-component.svg @@ -0,0 +1,17 @@ + + + + diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-count.svg b/cool-admin-vue/src/modules/base/static/svg/icon-count.svg new file mode 100644 index 0000000..daf26ba --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-count.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-crown.svg b/cool-admin-vue/src/modules/base/static/svg/icon-crown.svg new file mode 100644 index 0000000..71429de --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-crown.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-data.svg b/cool-admin-vue/src/modules/base/static/svg/icon-data.svg new file mode 100644 index 0000000..1dbfe70 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-data.svg @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-db.svg b/cool-admin-vue/src/modules/base/static/svg/icon-db.svg new file mode 100644 index 0000000..4a5d345 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-db.svg @@ -0,0 +1,15 @@ + + + + + + + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-delete.svg b/cool-admin-vue/src/modules/base/static/svg/icon-delete.svg new file mode 100644 index 0000000..610d33e --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-delete.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-dept.svg b/cool-admin-vue/src/modules/base/static/svg/icon-dept.svg new file mode 100644 index 0000000..f0af65d --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-dept.svg @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-design.svg b/cool-admin-vue/src/modules/base/static/svg/icon-design.svg new file mode 100644 index 0000000..3aed42f --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-design.svg @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-device.svg b/cool-admin-vue/src/modules/base/static/svg/icon-device.svg new file mode 100644 index 0000000..f82b640 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-device.svg @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-dict.svg b/cool-admin-vue/src/modules/base/static/svg/icon-dict.svg new file mode 100644 index 0000000..444ceee --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-dict.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-discover.svg b/cool-admin-vue/src/modules/base/static/svg/icon-discover.svg new file mode 100644 index 0000000..3747d7e --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-discover.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-doc.svg b/cool-admin-vue/src/modules/base/static/svg/icon-doc.svg new file mode 100644 index 0000000..d82fa34 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-doc.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-download.svg b/cool-admin-vue/src/modules/base/static/svg/icon-download.svg new file mode 100644 index 0000000..b86f044 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-download.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-emoji.svg b/cool-admin-vue/src/modules/base/static/svg/icon-emoji.svg new file mode 100644 index 0000000..2809858 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-emoji.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-favor.svg b/cool-admin-vue/src/modules/base/static/svg/icon-favor.svg new file mode 100644 index 0000000..98ad58e --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-favor.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-file.svg b/cool-admin-vue/src/modules/base/static/svg/icon-file.svg new file mode 100644 index 0000000..5ab59d6 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-file.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-folder.svg b/cool-admin-vue/src/modules/base/static/svg/icon-folder.svg new file mode 100644 index 0000000..7ad8ab7 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-folder.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-goods.svg b/cool-admin-vue/src/modules/base/static/svg/icon-goods.svg new file mode 100644 index 0000000..391d0ea --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-goods.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-home.svg b/cool-admin-vue/src/modules/base/static/svg/icon-home.svg new file mode 100644 index 0000000..94cf445 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-home.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-hot.svg b/cool-admin-vue/src/modules/base/static/svg/icon-hot.svg new file mode 100644 index 0000000..b907eeb --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-hot.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-info.svg b/cool-admin-vue/src/modules/base/static/svg/icon-info.svg new file mode 100644 index 0000000..4805c9a --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-info.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-iot.svg b/cool-admin-vue/src/modules/base/static/svg/icon-iot.svg new file mode 100644 index 0000000..f7ccae0 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-iot.svg @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-light.svg b/cool-admin-vue/src/modules/base/static/svg/icon-light.svg new file mode 100644 index 0000000..b07a126 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-light.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-like.svg b/cool-admin-vue/src/modules/base/static/svg/icon-like.svg new file mode 100644 index 0000000..c49af81 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-like.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-list.svg b/cool-admin-vue/src/modules/base/static/svg/icon-list.svg new file mode 100644 index 0000000..a53f8ba --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-list.svg @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-local.svg b/cool-admin-vue/src/modules/base/static/svg/icon-local.svg new file mode 100644 index 0000000..6bedcdf --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-local.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-log.svg b/cool-admin-vue/src/modules/base/static/svg/icon-log.svg new file mode 100644 index 0000000..e35c47b --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-log.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-map.svg b/cool-admin-vue/src/modules/base/static/svg/icon-map.svg new file mode 100644 index 0000000..9befbd4 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-map.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-match.svg b/cool-admin-vue/src/modules/base/static/svg/icon-match.svg new file mode 100644 index 0000000..f7c68ef --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-match.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-menu.svg b/cool-admin-vue/src/modules/base/static/svg/icon-menu.svg new file mode 100644 index 0000000..b58dbf9 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-menu.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-monitor.svg b/cool-admin-vue/src/modules/base/static/svg/icon-monitor.svg new file mode 100644 index 0000000..5fa7b77 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-monitor.svg @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-msg.svg b/cool-admin-vue/src/modules/base/static/svg/icon-msg.svg new file mode 100644 index 0000000..54c0992 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-msg.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-news.svg b/cool-admin-vue/src/modules/base/static/svg/icon-news.svg new file mode 100644 index 0000000..5cec609 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-news.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-notice.svg b/cool-admin-vue/src/modules/base/static/svg/icon-notice.svg new file mode 100644 index 0000000..5c8048d --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-notice.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-params.svg b/cool-admin-vue/src/modules/base/static/svg/icon-params.svg new file mode 100644 index 0000000..9683e72 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-params.svg @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-phone.svg b/cool-admin-vue/src/modules/base/static/svg/icon-phone.svg new file mode 100644 index 0000000..8910aab --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-phone.svg @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-pic.svg b/cool-admin-vue/src/modules/base/static/svg/icon-pic.svg new file mode 100644 index 0000000..02265cd --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-pic.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-question.svg b/cool-admin-vue/src/modules/base/static/svg/icon-question.svg new file mode 100644 index 0000000..1731198 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-question.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-quick.svg b/cool-admin-vue/src/modules/base/static/svg/icon-quick.svg new file mode 100644 index 0000000..61bdb79 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-quick.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-rank.svg b/cool-admin-vue/src/modules/base/static/svg/icon-rank.svg new file mode 100644 index 0000000..60916c5 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-rank.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-reward.svg b/cool-admin-vue/src/modules/base/static/svg/icon-reward.svg new file mode 100644 index 0000000..f01f848 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-reward.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-search.svg b/cool-admin-vue/src/modules/base/static/svg/icon-search.svg new file mode 100644 index 0000000..166aebf --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-search.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-set.svg b/cool-admin-vue/src/modules/base/static/svg/icon-set.svg new file mode 100644 index 0000000..fb53057 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-set.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-tag.svg b/cool-admin-vue/src/modules/base/static/svg/icon-tag.svg new file mode 100644 index 0000000..84adbce --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-tag.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-task.svg b/cool-admin-vue/src/modules/base/static/svg/icon-task.svg new file mode 100644 index 0000000..470280f --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-task.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-time.svg b/cool-admin-vue/src/modules/base/static/svg/icon-time.svg new file mode 100644 index 0000000..7ac6296 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-time.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-tutorial.svg b/cool-admin-vue/src/modules/base/static/svg/icon-tutorial.svg new file mode 100644 index 0000000..cc2323e --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-tutorial.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-unlock.svg b/cool-admin-vue/src/modules/base/static/svg/icon-unlock.svg new file mode 100644 index 0000000..78b6413 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-unlock.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-user.svg b/cool-admin-vue/src/modules/base/static/svg/icon-user.svg new file mode 100644 index 0000000..66d8df7 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-user.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-video.svg b/cool-admin-vue/src/modules/base/static/svg/icon-video.svg new file mode 100644 index 0000000..1eee5b9 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-video.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-vip.svg b/cool-admin-vue/src/modules/base/static/svg/icon-vip.svg new file mode 100644 index 0000000..31f4f67 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-vip.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-warn.svg b/cool-admin-vue/src/modules/base/static/svg/icon-warn.svg new file mode 100644 index 0000000..3eab18d --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-warn.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-work.svg b/cool-admin-vue/src/modules/base/static/svg/icon-work.svg new file mode 100644 index 0000000..bea8473 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-work.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/icon-workbench.svg b/cool-admin-vue/src/modules/base/static/svg/icon-workbench.svg new file mode 100644 index 0000000..ff959d3 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/icon-workbench.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/image.svg b/cool-admin-vue/src/modules/base/static/svg/image.svg new file mode 100644 index 0000000..fca2c66 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/image.svg @@ -0,0 +1,17 @@ + + + + diff --git a/cool-admin-vue/src/modules/base/static/svg/import.svg b/cool-admin-vue/src/modules/base/static/svg/import.svg new file mode 100644 index 0000000..ae272f2 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/import.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/left.svg b/cool-admin-vue/src/modules/base/static/svg/left.svg new file mode 100644 index 0000000..f49a79b --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/left.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/my.svg b/cool-admin-vue/src/modules/base/static/svg/my.svg new file mode 100644 index 0000000..a422ae4 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/my.svg @@ -0,0 +1,21 @@ + + + + + diff --git a/cool-admin-vue/src/modules/base/static/svg/order.svg b/cool-admin-vue/src/modules/base/static/svg/order.svg new file mode 100644 index 0000000..1dbbc68 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/order.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/play.svg b/cool-admin-vue/src/modules/base/static/svg/play.svg new file mode 100644 index 0000000..e5b5f40 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/play.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/plus-border.svg b/cool-admin-vue/src/modules/base/static/svg/plus-border.svg new file mode 100644 index 0000000..a36cf9d --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/plus-border.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/plus.svg b/cool-admin-vue/src/modules/base/static/svg/plus.svg new file mode 100644 index 0000000..4207733 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/plus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/refresh.svg b/cool-admin-vue/src/modules/base/static/svg/refresh.svg new file mode 100644 index 0000000..a9f1281 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/refresh.svg @@ -0,0 +1,21 @@ + + + + + diff --git a/cool-admin-vue/src/modules/base/static/svg/right.svg b/cool-admin-vue/src/modules/base/static/svg/right.svg new file mode 100644 index 0000000..d488008 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/screen-full.svg b/cool-admin-vue/src/modules/base/static/svg/screen-full.svg new file mode 100644 index 0000000..a0e4c57 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/screen-full.svg @@ -0,0 +1,17 @@ + + + + diff --git a/cool-admin-vue/src/modules/base/static/svg/screen-normal.svg b/cool-admin-vue/src/modules/base/static/svg/screen-normal.svg new file mode 100644 index 0000000..c5d80d5 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/screen-normal.svg @@ -0,0 +1,17 @@ + + + + diff --git a/cool-admin-vue/src/modules/base/static/svg/search.svg b/cool-admin-vue/src/modules/base/static/svg/search.svg new file mode 100644 index 0000000..54e1135 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/search.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/set.svg b/cool-admin-vue/src/modules/base/static/svg/set.svg new file mode 100644 index 0000000..aa84b0a --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/set.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/sort.svg b/cool-admin-vue/src/modules/base/static/svg/sort.svg new file mode 100644 index 0000000..f842b4b --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/sort.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/stats.svg b/cool-admin-vue/src/modules/base/static/svg/stats.svg new file mode 100644 index 0000000..25eec42 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/stats.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/success.svg b/cool-admin-vue/src/modules/base/static/svg/success.svg new file mode 100644 index 0000000..66d15fd --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/success.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/team.svg b/cool-admin-vue/src/modules/base/static/svg/team.svg new file mode 100644 index 0000000..32acf07 --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/team.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/static/svg/trend.svg b/cool-admin-vue/src/modules/base/static/svg/trend.svg new file mode 100644 index 0000000..aa8215b --- /dev/null +++ b/cool-admin-vue/src/modules/base/static/svg/trend.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cool-admin-vue/src/modules/base/store/app.ts b/cool-admin-vue/src/modules/base/store/app.ts new file mode 100644 index 0000000..0a0bd57 --- /dev/null +++ b/cool-admin-vue/src/modules/base/store/app.ts @@ -0,0 +1,69 @@ +import { defineStore } from 'pinia'; +import { reactive, ref } from 'vue'; +import { merge } from 'lodash-es'; +import { useBrowser } from '/@/cool'; +import { storage } from '/@/cool/utils'; +import { config } from '/@/config'; + +export const useAppStore = defineStore('app', function () { + const { browser, onScreenChange } = useBrowser(); + + // 基本信息 + const info = reactive({ + ...config.app + }); + + // 设置基本信息 + function set(data: any) { + merge(info, data); + storage.set('__app__', info); + } + + // 是否折叠 + const isFold = ref(false); + + // 折叠 + function fold(v?: boolean) { + if (v === undefined) { + v = !isFold.value; + } + + isFold.value = v; + } + + // 是否全屏 + const isFull = ref(false); + + // 设置全屏 + function setFull(state: boolean) { + isFull.value = state; + } + + // 事件 + const events = reactive<{ [key: string]: any[] }>({ + hasToken: [] + }); + + // 添加事件 + function addEvent(name: string, func: any) { + if (func) { + events[name].push(func); + } + } + + // 监听屏幕变化 + onScreenChange(() => { + isFold.value = browser.isMini; + }); + + return { + info, + isFold, + fold, + isFull, + setFull, + events, + set, + addEvent + }; +}); diff --git a/cool-admin-vue/src/modules/base/store/index.ts b/cool-admin-vue/src/modules/base/store/index.ts new file mode 100644 index 0000000..1aa03f8 --- /dev/null +++ b/cool-admin-vue/src/modules/base/store/index.ts @@ -0,0 +1,18 @@ +import { useAppStore } from './app'; +import { useMenuStore } from './menu'; +import { useProcessStore } from './process'; +import { useUserStore } from './user'; + +export function useStore() { + const app = useAppStore(); + const menu = useMenuStore(); + const process = useProcessStore(); + const user = useUserStore(); + + return { + app, + menu, + process, + user + }; +} diff --git a/cool-admin-vue/src/modules/base/store/menu.ts b/cool-admin-vue/src/modules/base/store/menu.ts new file mode 100644 index 0000000..5dfbc1d --- /dev/null +++ b/cool-admin-vue/src/modules/base/store/menu.ts @@ -0,0 +1,205 @@ +import { defineStore } from 'pinia'; +import { ref } from 'vue'; +import { deepTree, revDeepTree, storage } from '/@/cool/utils'; +import { isArray, isEmpty, orderBy } from 'lodash-es'; +import { router, service } from '/@/cool'; +import { revisePath } from '../utils'; +import { config } from '/@/config'; + +// 本地缓存 +const data = storage.info(); + +export const useMenuStore = defineStore('menu', function () { + // 所有菜单 + const all = ref([]); + + // 视图路由 + const routes = ref([]); + + // 菜单组 + const group = ref(data['base.menuGroup'] || []); + + // 左侧菜单列表 + const list = ref([]); + + // 权限列表 + const perms = ref(data['base.menuPerms'] || []); + + // 设置左侧菜单 + function setMenu(i: number = 0) { + // 显示分组显示菜单 + if (config.app.menu.isGroup) { + list.value = group.value.filter(e => e.isShow)[i]?.children || []; + } else { + list.value = group.value; + } + } + + // 设置权限 + function setPerms(list: Menu.List) { + function deep(d: any) { + if (typeof d == 'object') { + if (d.permission) { + if (d.namespace) { + d._permission = {}; + for (const i in d.permission) { + d._permission[i] = + list.findIndex(e => + e + .replace(/:/g, '/') + .includes(`${d.namespace.replace('admin/', '')}/${i}`) + ) >= 0; + } + } else { + console.error('namespace is required', d); + } + } else { + for (const i in d) { + deep(d[i]); + } + } + } + } + + perms.value = list; + storage.set('base.menuPerms', list); + + deep(service); + } + + // 设置视图 + function setRoutes(list: Menu.List) { + // 获取第一个菜单路径 + const fp = getPath(group.value); + + // 查找符合路由 + const route = list.find(e => (e.meta!.isHome = e.path == fp)); + + // 过滤菜单 + routes.value = list.filter(e => e.type == 1); + + if (route) { + // 移除旧路由 + router.del('home'); + router.del('homeRedirect'); + + // 添加一个重定向 + if (route.path != '/') { + const item = routes.value.find(e => e.name == 'homeRedirect'); + + if (item) { + item.path = route.path; + } else { + routes.value.push({ + path: route.path, + redirect: '/', + name: 'homeRedirect' + } as any); + } + } + + // 设置为首页 + route.path = '/'; + route.name = 'home'; + } + } + + // 设置菜单组 + function setGroup(list: Menu.List) { + group.value = orderBy(deepTree(list), 'orderNum'); + storage.set('base.menuGroup', group.value); + } + + // 获取菜单,权限信息 + async function get() { + function next(res: { menus: Menu.List; perms?: any[] }) { + // 所有菜单 + all.value = res.menus; + + // 菜单格式化 + const list = res.menus + ?.filter(e => e.type != 2) + .map(e => { + const path = revisePath(e.router || String(e.id)); + const isShow = e.isShow === undefined ? true : e.isShow; + + return { + ...e, + path, + isShow, + meta: { + ...e.meta, + label: e.name, // 菜单名称的唯一标识 + keepAlive: e.keepAlive || 0 + }, + name: `${e.name}-${e.id}`, // 避免重复命名之前的冲突 + children: [] + }; + }); + + // 设置权限 + setPerms(res.perms || []); + + // 设置菜单组 + setGroup(list); + + // 设置视图路由 + setRoutes(list); + + // 设置菜单 + setMenu(); + + return list; + } + + // 自定义菜单 + if (!isEmpty(config.app.menu.list)) { + next({ + menus: revDeepTree(config.app.menu.list || []) + }); + } else { + // 动态菜单 + await service.base.comm.permmenu().then(next); + } + } + + // 获取菜单路径 + function getPath(data: Menu.Item | Menu.List) { + const list = isArray(data) ? data : [data]; + + let path = ''; + + function deep(arr: Menu.List) { + arr.forEach((e: Menu.Item) => { + switch (e.type) { + case 0: + deep(e.children || []); + break; + case 1: + if (!path) { + path = e.path; + } + break; + } + }); + } + + deep(list); + + return path; + } + + return { + all, + routes, + group, + list, + perms, + get, + setPerms, + setMenu, + setRoutes, + setGroup, + getPath + }; +}); diff --git a/cool-admin-vue/src/modules/base/store/process.ts b/cool-admin-vue/src/modules/base/store/process.ts new file mode 100644 index 0000000..076a1c0 --- /dev/null +++ b/cool-admin-vue/src/modules/base/store/process.ts @@ -0,0 +1,74 @@ +import { defineStore } from 'pinia'; +import { ref } from 'vue'; +import { assign } from 'lodash-es'; + +export const useProcessStore = defineStore('process', function () { + const list = ref([]); + + // 添加 + function add(data: any) { + list.value.forEach((e: Process.Item) => { + e.active = false; + }); + + if (!data.meta) { + data.meta = {}; + } + + if (!data.meta?.isHome && data.meta?.process !== false) { + const index = list.value.findIndex(e => e.path === data.path); + + if (index < 0) { + list.value.push({ + ...data, + active: true + }); + } else { + assign(list.value[index], data, { active: true }); + } + } + } + + // 关闭当前 + function close() { + const index = list.value.findIndex(e => e.active); + + if (index > -1) { + list.value.splice(index, 1); + } + } + + // 移除 + function remove(index: number) { + list.value.splice(index, 1); + } + + // 设置 + function set(data: Process.Item[]) { + list.value = data; + } + + // 清空 + function clear() { + list.value = []; + } + + // 设置标题 + function setTitle(title: string) { + const item = list.value.find(e => e.active); + + if (item) { + item.meta.label = title; + } + } + + return { + list, + add, + remove, + close, + set, + clear, + setTitle + }; +}); diff --git a/cool-admin-vue/src/modules/base/store/user.ts b/cool-admin-vue/src/modules/base/store/user.ts new file mode 100644 index 0000000..071a2cf --- /dev/null +++ b/cool-admin-vue/src/modules/base/store/user.ts @@ -0,0 +1,88 @@ +import { defineStore } from 'pinia'; +import { ref } from 'vue'; +import { storage } from '/@/cool/utils'; +import { service, router } from '/@/cool'; + +// 本地缓存 +const data = storage.info(); + +export const useUserStore = defineStore('user', function () { + // 标识 + const token = ref(data.token); + + // 设置标识 + function setToken(data: { + token: string; + expire: number; + refreshToken: string; + refreshExpire: number; + }) { + // 请求的唯一标识 + token.value = data.token; + storage.set('token', data.token, data.expire); + + // 刷新 token 的唯一标识 + storage.set('refreshToken', data.refreshToken, data.refreshExpire); + } + + // 刷新标识 + async function refreshToken(): Promise { + return new Promise((resolve, reject) => { + service.base.open + .refreshToken({ + refreshToken: storage.get('refreshToken') + }) + .then(res => { + setToken(res); + resolve(res.token); + }) + .catch(err => { + logout(); + reject(err); + }); + }); + } + + // 用户信息 + const info = ref(data.userInfo); + + // 设置用户信息 + function set(value: any) { + info.value = value; + storage.set('userInfo', value); + } + + // 清除用户 + function clear() { + storage.remove('userInfo'); + storage.remove('token'); + token.value = ''; + info.value = null; + } + + // 退出 + async function logout() { + clear(); + router.clear(); + router.push('/login'); + } + + // 获取用户信息 + async function get() { + return service.base.comm.person().then(res => { + set(res); + return res; + }); + } + + return { + token, + info, + get, + set, + logout, + clear, + setToken, + refreshToken + }; +}); diff --git a/cool-admin-vue/src/modules/base/types/index.d.ts b/cool-admin-vue/src/modules/base/types/index.d.ts new file mode 100644 index 0000000..81675fe --- /dev/null +++ b/cool-admin-vue/src/modules/base/types/index.d.ts @@ -0,0 +1,52 @@ +declare namespace Menu { + enum Type { + '目录' = 0, + '菜单' = 1, + '权限' = 2 + } + + interface Item { + id: number; + parentId: number; + path: string; + router?: string; + viewPath?: string; + type: Type; + name: string; + icon: string; + badge?: number; + badgeColor?: 'primary' | 'success' | 'warning' | 'danger' | 'info'; + orderNum: number; + isShow: number | boolean; + keepAlive?: number; + meta?: { + label?: string; + keepAlive?: number | boolean; + iframeUrl?: string; + isHome?: boolean; + [key: string]: any; + }; + children?: Item[]; + component?: any; + redirect?: string; + [key: string]: any; + } + + type List = Item[]; +} + +declare namespace Process { + interface Item { + active: boolean; + name: string; + path: string; + fullPath: string; + meta: { + label: string; + [key: string]: any; + }; + [key: string]: any; + } + + type List = Item[]; +} diff --git a/cool-admin-vue/src/modules/base/utils/index.ts b/cool-admin-vue/src/modules/base/utils/index.ts new file mode 100644 index 0000000..fa24a0b --- /dev/null +++ b/cool-admin-vue/src/modules/base/utils/index.ts @@ -0,0 +1,9 @@ +export function revisePath(path: string) { + if (!path) { + return ''; + } + + return path.startsWith('/') ? path : `/${path}`; +} + +export * from './permission'; diff --git a/cool-admin-vue/src/modules/base/utils/permission.ts b/cool-admin-vue/src/modules/base/utils/permission.ts new file mode 100644 index 0000000..efa9f60 --- /dev/null +++ b/cool-admin-vue/src/modules/base/utils/permission.ts @@ -0,0 +1,30 @@ +import { useStore } from '../store'; +import { isObject } from 'lodash-es'; + +function parse(value: any) { + const { menu } = useStore(); + + if (typeof value == 'string') { + return value ? menu.perms.some((e: any) => e.includes(value.replace(/\s/g, ''))) : false; + } else { + return Boolean(value); + } +} + +export function checkPerm(value: string | { or?: string[]; and?: string[] }) { + if (!value) { + return false; + } + + if (isObject(value)) { + if (value.or) { + return value.or.some(parse); + } + + if (value.and) { + return value.and.some((e: any) => !parse(e)) ? false : true; + } + } + + return parse(value); +} diff --git a/cool-admin-vue/src/modules/base/views/frame.vue b/cool-admin-vue/src/modules/base/views/frame.vue new file mode 100644 index 0000000..4c0a491 --- /dev/null +++ b/cool-admin-vue/src/modules/base/views/frame.vue @@ -0,0 +1,49 @@ + + + + + diff --git a/cool-admin-vue/src/modules/base/views/info.vue b/cool-admin-vue/src/modules/base/views/info.vue new file mode 100644 index 0000000..8c836e7 --- /dev/null +++ b/cool-admin-vue/src/modules/base/views/info.vue @@ -0,0 +1,119 @@ + + + + + diff --git a/cool-admin-vue/src/modules/base/views/log.vue b/cool-admin-vue/src/modules/base/views/log.vue new file mode 100644 index 0000000..3204876 --- /dev/null +++ b/cool-admin-vue/src/modules/base/views/log.vue @@ -0,0 +1,153 @@ + + + diff --git a/cool-admin-vue/src/modules/base/views/menu/components/exp.vue b/cool-admin-vue/src/modules/base/views/menu/components/exp.vue new file mode 100644 index 0000000..eb85384 --- /dev/null +++ b/cool-admin-vue/src/modules/base/views/menu/components/exp.vue @@ -0,0 +1,109 @@ + + + diff --git a/cool-admin-vue/src/modules/base/views/menu/components/imp.vue b/cool-admin-vue/src/modules/base/views/menu/components/imp.vue new file mode 100644 index 0000000..73faf95 --- /dev/null +++ b/cool-admin-vue/src/modules/base/views/menu/components/imp.vue @@ -0,0 +1,122 @@ + + + diff --git a/cool-admin-vue/src/modules/base/views/menu/index.vue b/cool-admin-vue/src/modules/base/views/menu/index.vue new file mode 100644 index 0000000..597a004 --- /dev/null +++ b/cool-admin-vue/src/modules/base/views/menu/index.vue @@ -0,0 +1,404 @@ + + + diff --git a/cool-admin-vue/src/modules/base/views/param.vue b/cool-admin-vue/src/modules/base/views/param.vue new file mode 100644 index 0000000..c7ef57e --- /dev/null +++ b/cool-admin-vue/src/modules/base/views/param.vue @@ -0,0 +1,226 @@ + + + diff --git a/cool-admin-vue/src/modules/base/views/role.vue b/cool-admin-vue/src/modules/base/views/role.vue new file mode 100644 index 0000000..8dadea2 --- /dev/null +++ b/cool-admin-vue/src/modules/base/views/role.vue @@ -0,0 +1,165 @@ + + + diff --git a/cool-admin-vue/src/modules/base/views/user/components/dept-list.vue b/cool-admin-vue/src/modules/base/views/user/components/dept-list.vue new file mode 100644 index 0000000..19d5519 --- /dev/null +++ b/cool-admin-vue/src/modules/base/views/user/components/dept-list.vue @@ -0,0 +1,503 @@ + + + + + diff --git a/cool-admin-vue/src/modules/base/views/user/components/user-move.vue b/cool-admin-vue/src/modules/base/views/user/components/user-move.vue new file mode 100644 index 0000000..8d51495 --- /dev/null +++ b/cool-admin-vue/src/modules/base/views/user/components/user-move.vue @@ -0,0 +1,74 @@ + + + diff --git a/cool-admin-vue/src/modules/base/views/user/index.vue b/cool-admin-vue/src/modules/base/views/user/index.vue new file mode 100644 index 0000000..bcd761c --- /dev/null +++ b/cool-admin-vue/src/modules/base/views/user/index.vue @@ -0,0 +1,342 @@ + + + diff --git a/cool-admin-vue/src/modules/demo/config.ts b/cool-admin-vue/src/modules/demo/config.ts new file mode 100644 index 0000000..13c4911 --- /dev/null +++ b/cool-admin-vue/src/modules/demo/config.ts @@ -0,0 +1,27 @@ +import { type ModuleConfig } from '/@/cool'; + +export default (): ModuleConfig => { + return { + components: [() => import('./views/crud/components/code.vue')], + + views: [ + { + // 单个参数 + // path: "/demo/test/route/:id", + + // 多个参数 + // path: "/demo/test/route/:id/:name", + + // 参数可选 + path: '/demo/test/route/:id/:name?', + + // 更多看文档:https://router.vuejs.org/zh/guide/essentials/route-matching-syntax.html + + meta: { + label: '动态路由参数' + }, + component: () => import('./views/test/route.vue') + } + ] + }; +}; diff --git a/cool-admin-vue/src/modules/demo/directives/color.ts b/cool-admin-vue/src/modules/demo/directives/color.ts new file mode 100644 index 0000000..8c5b1c6 --- /dev/null +++ b/cool-admin-vue/src/modules/demo/directives/color.ts @@ -0,0 +1,5 @@ +export default { + created(el: HTMLElement, binding: any) { + el.style.color = binding.value; + } +}; diff --git a/cool-admin-vue/src/modules/demo/locales/en.json b/cool-admin-vue/src/modules/demo/locales/en.json new file mode 100644 index 0000000..20572fb --- /dev/null +++ b/cool-admin-vue/src/modules/demo/locales/en.json @@ -0,0 +1,54 @@ +{ + "浏览量": "Views", + "访客数": "Visitors", + "总用户数": "Total Users", + "日增用户数": "Daily New Users", + "付款笔数": "Payment Transactions", + "转化率": "Conversion Rate", + "总销售额": "Total Sales", + "周同比": "Week-on-Week", + "日同比": "Day-on-Day", + "类别占比": "Category Share", + "启用": "Enabled", + "描述": "Description", + "未知": "Unknown", + "男": "Male", + "女": "Female", + "禁用": "Disabled", + "正常": "Normal", + "已注销": "Canceled", + "小程序": "Mini Program", + "公众号": "Official Account", + "H5": "H5", + "登录唯一ID": "Login Unique ID", + "头像": "Avatar", + "昵称": "Nickname", + "手机号": "Mobile Phone Number", + "性别": "Gender", + "状态": "Status", + "登录方式": "Login Method", + "来源": "Source", + "密码": "Password", + "介绍": "Introduction", + "余额": "Balance", + "标题": "Title", + "ID": "ID", + "创建时间": "Create Time", + "更新时间": "Update Time", + "搜索手机号、昵称": "Search Mobile Number, Nickname", + "{year}年": "{year} Year", + "销售金额": "Sales Amount", + "销售订单": "Sales Order", + "{i}月": "{i} Month", + "热门商品排行": "Popular Product Ranking", + "今日": "Today", + "本周": "This Week", + "本月": "This Month", + "全年": "Full Year", + "排名": "Ranking", + "商品名称": "Product Name", + "商品金额": "Product Amount", + "下单次数": "Order Placed Times", + "日涨幅": "Daily Increase", + "上架时间": "Listing Time" +} \ No newline at end of file diff --git a/cool-admin-vue/src/modules/demo/locales/zh-cn.json b/cool-admin-vue/src/modules/demo/locales/zh-cn.json new file mode 100644 index 0000000..8182c78 --- /dev/null +++ b/cool-admin-vue/src/modules/demo/locales/zh-cn.json @@ -0,0 +1,54 @@ +{ + "未知": "未知", + "男": "男", + "女": "女", + "禁用": "禁用", + "正常": "正常", + "已注销": "已注销", + "小程序": "小程序", + "公众号": "公众号", + "H5": "H5", + "登录唯一ID": "登录唯一ID", + "头像": "头像", + "昵称": "昵称", + "手机号": "手机号", + "性别": "性别", + "状态": "状态", + "登录方式": "登录方式", + "来源": "来源", + "密码": "密码", + "介绍": "介绍", + "余额": "余额", + "标题": "标题", + "ID": "ID", + "创建时间": "创建时间", + "更新时间": "更新时间", + "搜索手机号、昵称": "搜索手机号、昵称", + "{year}年": "{year}年", + "销售金额": "销售金额", + "销售订单": "销售订单", + "{i}月": "{i}月", + "热门商品排行": "热门商品排行", + "今日": "今日", + "本周": "本周", + "本月": "本月", + "全年": "全年", + "排名": "排名", + "商品名称": "商品名称", + "商品金额": "商品金额", + "下单次数": "下单次数", + "日涨幅": "日涨幅", + "上架时间": "上架时间", + "浏览量": "浏览量", + "访客数": "访客数", + "总用户数": "总用户数", + "日增用户数": "日增用户数", + "付款笔数": "付款笔数", + "转化率": "转化率", + "总销售额": "总销售额", + "周同比": "周同比", + "日同比": "日同比", + "类别占比": "类别占比", + "启用": "启用", + "描述": "描述" +} \ No newline at end of file diff --git a/cool-admin-vue/src/modules/demo/locales/zh-tw.json b/cool-admin-vue/src/modules/demo/locales/zh-tw.json new file mode 100644 index 0000000..74117a5 --- /dev/null +++ b/cool-admin-vue/src/modules/demo/locales/zh-tw.json @@ -0,0 +1,54 @@ +{ + "浏览量": "瀏覽量", + "访客数": "訪客數", + "总用户数": "總用戶數", + "日增用户数": "日增用戶數", + "付款笔数": "付款筆數", + "转化率": "轉化率", + "总销售额": "總銷售額", + "周同比": "周同比", + "日同比": "日同比", + "类别占比": "類別占比", + "启用": "啟用", + "描述": "描述", + "未知": "未知", + "男": "男", + "女": "女", + "禁用": "禁用", + "正常": "正常", + "已注销": "已註銷", + "小程序": "小程序", + "公众号": "公眾號", + "H5": "H5", + "登录唯一ID": "登錄唯一ID", + "头像": "頭像", + "昵称": "暱稱", + "手机号": "手機號", + "性别": "性別", + "状态": "狀態", + "登录方式": "登錄方式", + "来源": "來源", + "密码": "密碼", + "介绍": "介紹", + "余额": "餘額", + "标题": "標題", + "ID": "ID", + "创建时间": "創建時間", + "更新时间": "更新時間", + "搜索手机号、昵称": "搜索手機號、暱稱", + "{year}年": "{year}年", + "销售金额": "銷售金額", + "销售订单": "銷售訂單", + "{i}月": "{i}月", + "热门商品排行": "熱門商品排行", + "今日": "今日", + "本周": "本周", + "本月": "本月", + "全年": "全年", + "排名": "排名", + "商品名称": "商品名稱", + "商品金额": "商品金額", + "下单次数": "下單次數", + "日涨幅": "日漲幅", + "上架时间": "上架時間" +} \ No newline at end of file diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/adv-search/base.vue b/cool-admin-vue/src/modules/demo/views/crud/components/adv-search/base.vue new file mode 100644 index 0000000..0b74d4a --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/adv-search/base.vue @@ -0,0 +1,138 @@ + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/adv-search/custom.vue b/cool-admin-vue/src/modules/demo/views/crud/components/adv-search/custom.vue new file mode 100644 index 0000000..94ce40c --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/adv-search/custom.vue @@ -0,0 +1,152 @@ + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/code.vue b/cool-admin-vue/src/modules/demo/views/crud/components/code.vue new file mode 100644 index 0000000..96b90f1 --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/code.vue @@ -0,0 +1,45 @@ + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/crud/all.vue b/cool-admin-vue/src/modules/demo/views/crud/components/crud/all.vue new file mode 100644 index 0000000..bea553f --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/crud/all.vue @@ -0,0 +1,578 @@ + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/crud/base.vue b/cool-admin-vue/src/modules/demo/views/crud/components/crud/base.vue new file mode 100644 index 0000000..b3851af --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/crud/base.vue @@ -0,0 +1,145 @@ + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/crud/dict.vue b/cool-admin-vue/src/modules/demo/views/crud/components/crud/dict.vue new file mode 100644 index 0000000..da64ac8 --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/crud/dict.vue @@ -0,0 +1,164 @@ + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/crud/event.vue b/cool-admin-vue/src/modules/demo/views/crud/components/crud/event.vue new file mode 100644 index 0000000..f75dd27 --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/crud/event.vue @@ -0,0 +1,182 @@ + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/crud/select-table.vue b/cool-admin-vue/src/modules/demo/views/crud/components/crud/select-table.vue new file mode 100644 index 0000000..0a4a33c --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/crud/select-table.vue @@ -0,0 +1,155 @@ + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/crud/service.vue b/cool-admin-vue/src/modules/demo/views/crud/components/crud/service.vue new file mode 100644 index 0000000..fda349b --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/crud/service.vue @@ -0,0 +1,179 @@ + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/crud/user-select.vue b/cool-admin-vue/src/modules/demo/views/crud/components/crud/user-select.vue new file mode 100644 index 0000000..afbd6ab --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/crud/user-select.vue @@ -0,0 +1,77 @@ + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/form/children.vue b/cool-admin-vue/src/modules/demo/views/crud/components/form/children.vue new file mode 100644 index 0000000..3730ef4 --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/form/children.vue @@ -0,0 +1,118 @@ + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/form/component/index.vue b/cool-admin-vue/src/modules/demo/views/crud/components/form/component/index.vue new file mode 100644 index 0000000..c404408 --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/form/component/index.vue @@ -0,0 +1,124 @@ + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/form/component/select-labels.vue b/cool-admin-vue/src/modules/demo/views/crud/components/form/component/select-labels.vue new file mode 100644 index 0000000..e21e5af --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/form/component/select-labels.vue @@ -0,0 +1,42 @@ + + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/form/component/select-status.vue b/cool-admin-vue/src/modules/demo/views/crud/components/form/component/select-status.vue new file mode 100644 index 0000000..2dfabea --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/form/component/select-status.vue @@ -0,0 +1,47 @@ + + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/form/component/select-work.vue b/cool-admin-vue/src/modules/demo/views/crud/components/form/component/select-work.vue new file mode 100644 index 0000000..6ff625f --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/form/component/select-work.vue @@ -0,0 +1,63 @@ + + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/form/component/select-work2.vue b/cool-admin-vue/src/modules/demo/views/crud/components/form/component/select-work2.vue new file mode 100644 index 0000000..818a215 --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/form/component/select-work2.vue @@ -0,0 +1,42 @@ + + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/form/config.vue b/cool-admin-vue/src/modules/demo/views/crud/components/form/config.vue new file mode 100644 index 0000000..32d6604 --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/form/config.vue @@ -0,0 +1,122 @@ + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/form/crud.vue b/cool-admin-vue/src/modules/demo/views/crud/components/form/crud.vue new file mode 100644 index 0000000..ca4d892 --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/form/crud.vue @@ -0,0 +1,151 @@ + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/form/disabled.vue b/cool-admin-vue/src/modules/demo/views/crud/components/form/disabled.vue new file mode 100644 index 0000000..1a109ad --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/form/disabled.vue @@ -0,0 +1,64 @@ + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/form/event.vue b/cool-admin-vue/src/modules/demo/views/crud/components/form/event.vue new file mode 100644 index 0000000..201ecf8 --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/form/event.vue @@ -0,0 +1,93 @@ + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/form/group.vue b/cool-admin-vue/src/modules/demo/views/crud/components/form/group.vue new file mode 100644 index 0000000..fc2e07b --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/form/group.vue @@ -0,0 +1,105 @@ + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/form/hidden.vue b/cool-admin-vue/src/modules/demo/views/crud/components/form/hidden.vue new file mode 100644 index 0000000..e28a665 --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/form/hidden.vue @@ -0,0 +1,77 @@ + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/form/layout.vue b/cool-admin-vue/src/modules/demo/views/crud/components/form/layout.vue new file mode 100644 index 0000000..b4ab074 --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/form/layout.vue @@ -0,0 +1,98 @@ + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/form/open.vue b/cool-admin-vue/src/modules/demo/views/crud/components/form/open.vue new file mode 100644 index 0000000..8105135 --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/form/open.vue @@ -0,0 +1,84 @@ + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/form/options.vue b/cool-admin-vue/src/modules/demo/views/crud/components/form/options.vue new file mode 100644 index 0000000..8c51305 --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/form/options.vue @@ -0,0 +1,172 @@ + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/form/plugin/index.vue b/cool-admin-vue/src/modules/demo/views/crud/components/form/plugin/index.vue new file mode 100644 index 0000000..bd65b40 --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/form/plugin/index.vue @@ -0,0 +1,109 @@ + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/form/plugin/role.ts b/cool-admin-vue/src/modules/demo/views/crud/components/form/plugin/role.ts new file mode 100644 index 0000000..f924c1e --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/form/plugin/role.ts @@ -0,0 +1,20 @@ +/** + * 角色权限控制 + * @param role + * @returns + */ +export function setRole(role?: string): ClForm.Plugin { + return ({ exposed }) => { + function deep(arr: ClForm.Item[]) { + arr.forEach(e => { + if (e.role) { + e.hidden = e.role != role; + } + + deep(e.children || []); + }); + } + + deep(exposed.config.items); + }; +} diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/form/required.vue b/cool-admin-vue/src/modules/demo/views/crud/components/form/required.vue new file mode 100644 index 0000000..7de191f --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/form/required.vue @@ -0,0 +1,94 @@ + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/form/rules.vue b/cool-admin-vue/src/modules/demo/views/crud/components/form/rules.vue new file mode 100644 index 0000000..818f8d5 --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/form/rules.vue @@ -0,0 +1,123 @@ + + + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/form/setFocus.vue b/cool-admin-vue/src/modules/demo/views/crud/components/form/setFocus.vue new file mode 100644 index 0000000..467e039 --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/form/setFocus.vue @@ -0,0 +1,63 @@ + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/other/context-menu.vue b/cool-admin-vue/src/modules/demo/views/crud/components/other/context-menu.vue new file mode 100644 index 0000000..3551d16 --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/other/context-menu.vue @@ -0,0 +1,71 @@ + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/other/tips.vue b/cool-admin-vue/src/modules/demo/views/crud/components/other/tips.vue new file mode 100644 index 0000000..15d545d --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/other/tips.vue @@ -0,0 +1,150 @@ + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/other/tsx/index.scss b/cool-admin-vue/src/modules/demo/views/crud/components/other/tsx/index.scss new file mode 100644 index 0000000..bd99427 --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/other/tsx/index.scss @@ -0,0 +1,28 @@ +.tsx-list { + .item { + display: flex; + align-items: center; + justify-content: space-between; + border: 1px solid var(--el-border-color); + padding: 10px; + margin-bottom: 10px; + cursor: pointer; + border-radius: var(--el-border-radius-base); + + .el-icon { + display: none; + } + + &:hover { + background-color: var(--el-bg-color-page); + } + + &.is-active { + color: var(--el-color-primary); + + .el-icon { + display: block; + } + } + } +} diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/other/tsx/index.tsx b/cool-admin-vue/src/modules/demo/views/crud/components/other/tsx/index.tsx new file mode 100644 index 0000000..ae3396b --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/other/tsx/index.tsx @@ -0,0 +1,109 @@ +import { defineComponent, ref } from 'vue'; +import { Check } from '@element-plus/icons-vue'; +import './index.scss'; + +interface Item { + name: string; + value: number; +} + +export default defineComponent({ + emits: ['checked'], + + setup(props, { emit, expose, slots }) { + // 列表数据 + const list = ref([ + { + name: '鸡腿堡', + value: 1 + }, + { + name: '牛肉堡', + value: 2 + } + ]); + + // 选择值 + const active = ref(); + + // 是否可见 + const visible = ref(false); + + // 打开 + function open() { + visible.value = true; + } + + // 选择 + function toCheck(item: Item) { + active.value = item.value; + + // 自定义事件 + emit('checked', item); + } + + // 暴露方法和变量,使上级可以使用 ref 的方式来调用 + expose({ + toCheck + }); + + // 必须返回一个方法 + return () => { + return ( +
+
+ + tsx + + tsx示例 +
+ +
+ 预览 + + + {/* ref 的绑定值必须 .value */} + +
+ {/* 循环的使用 */} + {list.value.map(item => { + // 插槽的使用 + return slots.default ? ( + slots.default(item) + ) : ( +
toCheck(item)} + > + {item.name} + + + + +
+ ); + })} +
+
+
+ +
+ 2024-01-01 +
+
+ ); + }; + } + + // 不推荐用该方法,在 setup 中返回模板信息 + // render() { + // return
; + // } +}); diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/search/base.vue b/cool-admin-vue/src/modules/demo/views/crud/components/search/base.vue new file mode 100644 index 0000000..ef9c311 --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/search/base.vue @@ -0,0 +1,147 @@ + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/search/collapse.vue b/cool-admin-vue/src/modules/demo/views/crud/components/search/collapse.vue new file mode 100644 index 0000000..afcb4ad --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/search/collapse.vue @@ -0,0 +1,110 @@ + + + +x diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/search/custom.vue b/cool-admin-vue/src/modules/demo/views/crud/components/search/custom.vue new file mode 100644 index 0000000..51e8bf7 --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/search/custom.vue @@ -0,0 +1,176 @@ + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/search/layout.vue b/cool-admin-vue/src/modules/demo/views/crud/components/search/layout.vue new file mode 100644 index 0000000..ae4d3ee --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/search/layout.vue @@ -0,0 +1,149 @@ + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/search/plugin.vue b/cool-admin-vue/src/modules/demo/views/crud/components/search/plugin.vue new file mode 100644 index 0000000..93ba5a3 --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/search/plugin.vue @@ -0,0 +1,128 @@ + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/table/base.vue b/cool-admin-vue/src/modules/demo/views/crud/components/table/base.vue new file mode 100644 index 0000000..053a3cd --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/table/base.vue @@ -0,0 +1,109 @@ + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/table/children.vue b/cool-admin-vue/src/modules/demo/views/crud/components/table/children.vue new file mode 100644 index 0000000..fd4b71f --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/table/children.vue @@ -0,0 +1,95 @@ + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/table/column-custom.vue b/cool-admin-vue/src/modules/demo/views/crud/components/table/column-custom.vue new file mode 100644 index 0000000..c362331 --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/table/column-custom.vue @@ -0,0 +1,108 @@ + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/table/component/index.vue b/cool-admin-vue/src/modules/demo/views/crud/components/table/component/index.vue new file mode 100644 index 0000000..005d153 --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/table/component/index.vue @@ -0,0 +1,108 @@ + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/table/component/user-info.vue b/cool-admin-vue/src/modules/demo/views/crud/components/table/component/user-info.vue new file mode 100644 index 0000000..f4fd232 --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/table/component/user-info.vue @@ -0,0 +1,34 @@ + + + + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/table/context-menu.vue b/cool-admin-vue/src/modules/demo/views/crud/components/table/context-menu.vue new file mode 100644 index 0000000..43f77f4 --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/table/context-menu.vue @@ -0,0 +1,191 @@ + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/table/dict.vue b/cool-admin-vue/src/modules/demo/views/crud/components/table/dict.vue new file mode 100644 index 0000000..083297d --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/table/dict.vue @@ -0,0 +1,156 @@ + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/table/formatter.vue b/cool-admin-vue/src/modules/demo/views/crud/components/table/formatter.vue new file mode 100644 index 0000000..3cd0172 --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/table/formatter.vue @@ -0,0 +1,95 @@ + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/table/hidden.vue b/cool-admin-vue/src/modules/demo/views/crud/components/table/hidden.vue new file mode 100644 index 0000000..c81ad16 --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/table/hidden.vue @@ -0,0 +1,127 @@ + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/table/op.vue b/cool-admin-vue/src/modules/demo/views/crud/components/table/op.vue new file mode 100644 index 0000000..d15cbe0 --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/table/op.vue @@ -0,0 +1,182 @@ + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/table/plugin/base.vue b/cool-admin-vue/src/modules/demo/views/crud/components/table/plugin/base.vue new file mode 100644 index 0000000..d8f2445 --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/table/plugin/base.vue @@ -0,0 +1,130 @@ + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/table/plugin/row-edit.vue b/cool-admin-vue/src/modules/demo/views/crud/components/table/plugin/row-edit.vue new file mode 100644 index 0000000..de8c2d0 --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/table/plugin/row-edit.vue @@ -0,0 +1,124 @@ + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/table/plugin/to-tree.vue b/cool-admin-vue/src/modules/demo/views/crud/components/table/plugin/to-tree.vue new file mode 100644 index 0000000..d2c58be --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/table/plugin/to-tree.vue @@ -0,0 +1,87 @@ + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/table/search.vue b/cool-admin-vue/src/modules/demo/views/crud/components/table/search.vue new file mode 100644 index 0000000..88cb8ea --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/table/search.vue @@ -0,0 +1,137 @@ + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/table/selection.vue b/cool-admin-vue/src/modules/demo/views/crud/components/table/selection.vue new file mode 100644 index 0000000..87549ac --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/table/selection.vue @@ -0,0 +1,109 @@ + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/table/slot.vue b/cool-admin-vue/src/modules/demo/views/crud/components/table/slot.vue new file mode 100644 index 0000000..929ddb1 --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/table/slot.vue @@ -0,0 +1,97 @@ + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/table/span-method.vue b/cool-admin-vue/src/modules/demo/views/crud/components/table/span-method.vue new file mode 100644 index 0000000..d752ed9 --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/table/span-method.vue @@ -0,0 +1,115 @@ + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/table/summary.vue b/cool-admin-vue/src/modules/demo/views/crud/components/table/summary.vue new file mode 100644 index 0000000..05e37cf --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/table/summary.vue @@ -0,0 +1,95 @@ + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/upsert/base.vue b/cool-admin-vue/src/modules/demo/views/crud/components/upsert/base.vue new file mode 100644 index 0000000..96f76d0 --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/upsert/base.vue @@ -0,0 +1,133 @@ + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/upsert/event.vue b/cool-admin-vue/src/modules/demo/views/crud/components/upsert/event.vue new file mode 100644 index 0000000..e7b15a9 --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/upsert/event.vue @@ -0,0 +1,210 @@ + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/upsert/hook/index.vue b/cool-admin-vue/src/modules/demo/views/crud/components/upsert/hook/index.vue new file mode 100644 index 0000000..f5dfcc0 --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/upsert/hook/index.vue @@ -0,0 +1,200 @@ + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/upsert/hook/reg-pca2.ts b/cool-admin-vue/src/modules/demo/views/crud/components/upsert/hook/reg-pca2.ts new file mode 100644 index 0000000..472a9c8 --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/upsert/hook/reg-pca2.ts @@ -0,0 +1,14 @@ +import { registerFormHook } from '@cool-vue/crud'; + +// 注册 hook +registerFormHook('pca2', (value, { method, form, prop }) => { + if (method == 'bind') { + return [form.province, form.city, form.district]; + } else { + const [province, city, district] = value || []; + form.province = province; + form.city = city; + form.district = district; + form[prop] = undefined; + } +}); diff --git a/cool-admin-vue/src/modules/demo/views/crud/components/upsert/mode.vue b/cool-admin-vue/src/modules/demo/views/crud/components/upsert/mode.vue new file mode 100644 index 0000000..1b7fb8d --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/components/upsert/mode.vue @@ -0,0 +1,146 @@ + + + diff --git a/cool-admin-vue/src/modules/demo/views/crud/index.vue b/cool-admin-vue/src/modules/demo/views/crud/index.vue new file mode 100644 index 0000000..a7a712d --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/crud/index.vue @@ -0,0 +1,327 @@ + + + + + diff --git a/cool-admin-vue/src/modules/demo/views/home/components/category-ratio.vue b/cool-admin-vue/src/modules/demo/views/home/components/category-ratio.vue new file mode 100644 index 0000000..d8f6159 --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/home/components/category-ratio.vue @@ -0,0 +1,69 @@ + + + + + diff --git a/cool-admin-vue/src/modules/demo/views/home/components/count-effect.vue b/cool-admin-vue/src/modules/demo/views/home/components/count-effect.vue new file mode 100644 index 0000000..845b446 --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/home/components/count-effect.vue @@ -0,0 +1,89 @@ + + + + + diff --git a/cool-admin-vue/src/modules/demo/views/home/components/count-paid.vue b/cool-admin-vue/src/modules/demo/views/home/components/count-paid.vue new file mode 100644 index 0000000..c33d996 --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/home/components/count-paid.vue @@ -0,0 +1,30 @@ + + + diff --git a/cool-admin-vue/src/modules/demo/views/home/components/count-user.vue b/cool-admin-vue/src/modules/demo/views/home/components/count-user.vue new file mode 100644 index 0000000..aee2948 --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/home/components/count-user.vue @@ -0,0 +1,58 @@ + + + + + diff --git a/cool-admin-vue/src/modules/demo/views/home/components/count-views.vue b/cool-admin-vue/src/modules/demo/views/home/components/count-views.vue new file mode 100644 index 0000000..5e591c8 --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/home/components/count-views.vue @@ -0,0 +1,110 @@ + + + + + diff --git a/cool-admin-vue/src/modules/demo/views/home/components/hot-goods.vue b/cool-admin-vue/src/modules/demo/views/home/components/hot-goods.vue new file mode 100644 index 0000000..8c02f23 --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/home/components/hot-goods.vue @@ -0,0 +1,179 @@ + + + + + diff --git a/cool-admin-vue/src/modules/demo/views/home/components/tab-chart.vue b/cool-admin-vue/src/modules/demo/views/home/components/tab-chart.vue new file mode 100644 index 0000000..0656b78 --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/home/components/tab-chart.vue @@ -0,0 +1,152 @@ + + + + + diff --git a/cool-admin-vue/src/modules/demo/views/home/index.vue b/cool-admin-vue/src/modules/demo/views/home/index.vue new file mode 100644 index 0000000..34ea22a --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/home/index.vue @@ -0,0 +1,106 @@ + + + + + diff --git a/cool-admin-vue/src/modules/demo/views/test/route.vue b/cool-admin-vue/src/modules/demo/views/test/route.vue new file mode 100644 index 0000000..9f438f1 --- /dev/null +++ b/cool-admin-vue/src/modules/demo/views/test/route.vue @@ -0,0 +1,52 @@ + + + + + diff --git a/cool-admin-vue/src/modules/dict/config.ts b/cool-admin-vue/src/modules/dict/config.ts new file mode 100644 index 0000000..291820c --- /dev/null +++ b/cool-admin-vue/src/modules/dict/config.ts @@ -0,0 +1,16 @@ +import { type ModuleConfig } from '/@/cool'; +import { useDict } from './index'; + +export default (): ModuleConfig => { + return { + ignore: { + NProgress: ['/dict/info/data'] + }, + onLoad({ hasToken }) { + const { dict } = useDict(); + hasToken(() => { + dict.refresh(); + }); + } + }; +}; diff --git a/cool-admin-vue/src/modules/dict/index.ts b/cool-admin-vue/src/modules/dict/index.ts new file mode 100644 index 0000000..26e543e --- /dev/null +++ b/cool-admin-vue/src/modules/dict/index.ts @@ -0,0 +1,7 @@ +import { useStore } from './store'; + +export function useDict() { + return { + ...useStore() + }; +} diff --git a/cool-admin-vue/src/modules/dict/locales/en.json b/cool-admin-vue/src/modules/dict/locales/en.json new file mode 100644 index 0000000..60e2043 --- /dev/null +++ b/cool-admin-vue/src/modules/dict/locales/en.json @@ -0,0 +1,16 @@ +{ + "搜索名称": "Search Name", + "请填写值": "Please fill in the value", + "使用文件": "Use File", + "类型": "Type", + "字典列表": "Dictionary List", + "名称": "Name", + "上级节点": "Parent Node", + "值": "Value", + "排序": "Sort", + "备注": "Remarks", + "新增": "Add", + "ID": "ID", + "创建时间": "Create Time", + "更新时间": "Update Time" +} \ No newline at end of file diff --git a/cool-admin-vue/src/modules/dict/locales/zh-cn.json b/cool-admin-vue/src/modules/dict/locales/zh-cn.json new file mode 100644 index 0000000..196194c --- /dev/null +++ b/cool-admin-vue/src/modules/dict/locales/zh-cn.json @@ -0,0 +1,16 @@ +{ + "搜索名称": "搜索名称", + "请填写值": "请填写值", + "使用文件": "使用文件", + "类型": "类型", + "字典列表": "字典列表", + "名称": "名称", + "上级节点": "上级节点", + "值": "值", + "排序": "排序", + "备注": "备注", + "新增": "新增", + "ID": "ID", + "创建时间": "创建时间", + "更新时间": "更新时间" +} \ No newline at end of file diff --git a/cool-admin-vue/src/modules/dict/locales/zh-tw.json b/cool-admin-vue/src/modules/dict/locales/zh-tw.json new file mode 100644 index 0000000..f91fb7a --- /dev/null +++ b/cool-admin-vue/src/modules/dict/locales/zh-tw.json @@ -0,0 +1,16 @@ +{ + "搜索名称": "搜尋名稱", + "请填写值": "請填寫值", + "使用文件": "使用文件", + "类型": "類型", + "字典列表": "字典列表", + "名称": "名稱", + "上级节点": "上級節點", + "值": "值", + "排序": "排序", + "备注": "備註", + "新增": "新增", + "ID": "ID", + "创建时间": "創建時間", + "更新时间": "更新時間" +} \ No newline at end of file diff --git a/cool-admin-vue/src/modules/dict/store/dict.ts b/cool-admin-vue/src/modules/dict/store/dict.ts new file mode 100644 index 0000000..f4c3638 --- /dev/null +++ b/cool-admin-vue/src/modules/dict/store/dict.ts @@ -0,0 +1,65 @@ +import { defineStore } from 'pinia'; +import { computed, reactive, toRaw } from 'vue'; +import { service } from '/@/cool'; +import { deepTree } from '/@/cool/utils'; +import { isDev } from '/@/config'; +import { assign, isArray, orderBy } from 'lodash-es'; +import { deepFind, isEmpty } from '../utils'; + +const useDictStore = defineStore('dict', () => { + // 对象数据 + const data = reactive({}); + + // 获取 + function get(name: Dict.Key, sort?: 'desc' | 'asc') { + return computed(() => orderBy(data[name] || [], 'orderNum', sort)); + } + + // 查找 + function find(name: Dict.Key, value: any | any[]) { + const arr = isArray(value) ? value : [value]; + return arr.filter(e => e !== undefined).map(v => deepFind(v, get(name).value)); + } + + // 刷新 + async function refresh(types?: Dict.Key[]) { + return service.dict.info + .data({ + types: types?.filter(e => !isEmpty(e)) + }) + .then((res: Dict.Data) => { + const d = {}; + + for (const [i, arr] of Object.entries(res)) { + arr.forEach(e => { + e.label = e.name; + + if (isEmpty(e.value)) { + e.value = e.id; + } + }); + + d[i] = deepTree(arr, 'desc'); + } + + assign(data, d); + + if (isDev) { + console.group('字典数据'); + console.log(toRaw(data)); + console.groupEnd(); + } + + return data; + }); + } + + return { + data, + get, + find, + refresh + }; +}); + +export { useDictStore }; diff --git a/cool-admin-vue/src/modules/dict/store/index.ts b/cool-admin-vue/src/modules/dict/store/index.ts new file mode 100644 index 0000000..9261de5 --- /dev/null +++ b/cool-admin-vue/src/modules/dict/store/index.ts @@ -0,0 +1,9 @@ +import { useDictStore } from './dict'; + +export function useStore() { + const dict = useDictStore(); + + return { + dict + }; +} diff --git a/cool-admin-vue/src/modules/dict/types/index.d.ts b/cool-admin-vue/src/modules/dict/types/index.d.ts new file mode 100644 index 0000000..d2cd99d --- /dev/null +++ b/cool-admin-vue/src/modules/dict/types/index.d.ts @@ -0,0 +1,15 @@ +namespace Dict { + type Key = Eps.DictKey | (string & {}); + + interface Item { + id: string; + label: string; + value: any; + children?: Item[]; + [key: string]: any; + } + + interface Data { + [key: string]: Item[]; + } +} diff --git a/cool-admin-vue/src/modules/dict/utils/index.ts b/cool-admin-vue/src/modules/dict/utils/index.ts new file mode 100644 index 0000000..cf19f63 --- /dev/null +++ b/cool-admin-vue/src/modules/dict/utils/index.ts @@ -0,0 +1,31 @@ +export function deepFind(value: any, list: any[], options?: { allLevels: boolean }) { + const { allLevels = true } = options || {}; + + function deep(arr: any[], name: string[]): any | undefined { + for (const e of arr) { + if (e.value === value) { + if (allLevels) { + return { + ...e, + label: [...name, e.label].join(' / ') + }; + } else { + return e; + } + } else if (e.children) { + const d = deep(e.children, [...name, e.label]); + + if (d !== undefined) { + return d; + } + } + } + return undefined; + } + + return deep(list, []); +} + +export function isEmpty(val: any) { + return val === '' || val === null || val === undefined; +} diff --git a/cool-admin-vue/src/modules/dict/views/list.vue b/cool-admin-vue/src/modules/dict/views/list.vue new file mode 100644 index 0000000..6d2859b --- /dev/null +++ b/cool-admin-vue/src/modules/dict/views/list.vue @@ -0,0 +1,281 @@ + + + diff --git a/cool-admin-vue/src/modules/helper/components/ai-code/btn.vue b/cool-admin-vue/src/modules/helper/components/ai-code/btn.vue new file mode 100644 index 0000000..b40449c --- /dev/null +++ b/cool-admin-vue/src/modules/helper/components/ai-code/btn.vue @@ -0,0 +1,71 @@ + + + + + diff --git a/cool-admin-vue/src/modules/helper/components/ai-code/dev.vue b/cool-admin-vue/src/modules/helper/components/ai-code/dev.vue new file mode 100644 index 0000000..6aaf325 --- /dev/null +++ b/cool-admin-vue/src/modules/helper/components/ai-code/dev.vue @@ -0,0 +1,76 @@ +

(7sGN3 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 J#I3(e{|iSLl9T`d literal 0 HcmV?d00001 diff --git a/cool-admin-java/src/main/resources/cool/captcha/bgimages/i.jpg b/cool-admin-java/src/main/resources/cool/captcha/bgimages/i.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f9714d9c98878859ca0b55b4ab94ac033aa0f2f1 GIT binary patch literal 133325 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