From e8459e755e963c0ec5796c397898ecdc1192fff5 Mon Sep 17 00:00:00 2001 From: Yanko <747575620@qq.com> Date: Thu, 15 Aug 2024 09:39:45 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96MES?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 4 + Jenkinsfile | 154 + NuGet.config | 7 + backend/.dockerignore | 25 + .../BPA.MES.Base.Application.csproj | 40 + .../BPA.MES.Base.Application.xml | 9376 +++++++++++++++++ .../Const/ClaimConst.cs | 88 + .../Const/DeviceTypeEnum.cs | 40 + .../Const/ELogType.cs | 10 + .../Const/OrderStatusEnum.cs | 26 + .../Const/WorkOrderStatusEnum.cs | 40 + .../Entitys/Agv/AgvLineEntity.cs | 33 + .../Entitys/Agv/AgvPointEntity.cs | 21 + .../Entitys/App/Pztj_BucketInfoEntity.cs | 22 + .../App/Pztj_BucketMaterialsRecordEntity.cs | 38 + .../Entitys/App/Pztj_CraftStepsEntity.cs | 36 + .../Entitys/App/Pztj_CraftsInfoEntity.cs | 25 + .../Entitys/App/Pztj_DevicesInfoEntity.cs | 43 + .../Entitys/App/Pztj_FinalsInfoEntity.cs | 33 + .../Entitys/App/Pztj_LineDevicesEntity.cs | 21 + .../Entitys/App/Pztj_LineStocksEntity.cs | 21 + .../Entitys/App/Pztj_MaterialsInfoEntity.cs | 34 + .../Entitys/App/Pztj_StockInfoEntity.cs | 30 + .../Entitys/App/Pztj_WorkInfoEntity.cs | 48 + .../Entitys/App/Pztj_WorkInfoItemEntity.cs | 21 + .../Entitys/App/Pztj_WorkInfoStatusEntity.cs | 33 + .../Entitys/App/WorkBatchEntity.cs | 26 + .../App/WorkInfoCraftstepRecordEntity.cs | 67 + .../App/WorkInfoMaterialsRecordEntity.cs | 63 + .../Entitys/Base/DeviceProductEntity.cs | 26 + .../Base/DeviceProductFunctionEntity.cs | 38 + .../Entitys/Base/DeviceProductParmEntity.cs | 30 + .../Entitys/Base/DeviceRecipeEntity.cs | 22 + .../Entitys/Base/DictDataEntity.cs | 33 + .../Entitys/Base/DictTypeEntity.cs | 26 + .../Entitys/Base/GroupInfoEntity.cs | 21 + .../Entitys/Base/MQTTInfoEntity.cs | 29 + .../Entitys/Base/OperLogEntity.cs | 31 + .../Entitys/Base/OrderInfoEntity.cs | 13 + .../Entitys/Base/ProductLineEntity.cs | 25 + .../Entitys/Base/RecipeMaterialEntity.cs | 36 + .../Entitys/Base/RecipesGroupEntity.cs | 21 + .../Entitys/Base/RecipesInfoEntity.cs | 22 + .../Entitys/Base/StoreInfoEntity.cs | 30 + .../Entitys/KepData/AlarmLog.cs | 27 + .../Entitys/KepData/DataVAlarmLimit.cs | 33 + .../Entitys/KepData/ch1_device1.cs | 20 + .../Entitys/Logs/AlarmLogEntity.cs | 54 + .../Entitys/Logs/ProgramLogEntity.cs | 39 + .../Entitys/Logs/RunLogEntity.cs | 45 + .../Entitys/Logs/UserLogEntity.cs | 36 + .../Entitys/Order/OrderEntity.cs | 24 + .../Entitys/Order/OrderInfoEntity.cs | 30 + .../Entitys/Order/OrderWorkEntity.cs | 18 + .../Entitys/Sys/AccountEntity.cs | 29 + .../Entitys/Sys/EmployeeEntity.cs | 38 + .../Entitys/Sys/ModuleEntity.cs | 46 + .../Entitys/Sys/RoleEntity.cs | 32 + .../Entitys/Sys/RoleModuleEntity.cs | 26 + .../Filters/AGVAttribute.cs | 39 + .../Filters/OperLogAttribute.cs | 46 + .../BPA.MES.Base.Application/GlobalUsings.cs | 19 + .../BPA.MES.Base.Application/MQTT/IMessage.cs | 21 + .../MQTT/MQTTService.cs | 145 + .../MQTT/MessageID.cs | 14 + .../MQTT/MsgPackage.cs | 18 + .../BPA.MES.Base.Application/MQTT/Topics.cs | 42 + .../AGVService/Dtos/AGVThirdPartyDto.cs | 473 + .../Services/AGVService/Dtos/AgvLineDto.cs | 95 + .../Services/AGVService/Dtos/AgvPointDto.cs | 83 + .../Services/AGVThirdPartyService.cs | 170 + .../AGVService/Services/AgvLineService.cs | 115 + .../AGVService/Services/AgvPointService.cs | 115 + .../Services/IAGVThirdPartyService.cs | 40 + .../AGVService/Services/IAgvLineService.cs | 43 + .../AGVService/Services/IAgvPointService.cs | 43 + .../Services/BaseService.cs | 50 + .../BucketInfoService/Dtos/BucketInfoDto.cs | 75 + .../Dtos/BucketMaterialsRecordDto.cs | 135 + .../Services/BucketInfoService.cs | 168 + .../Services/BucketMaterialsRecordServcie.cs | 140 + .../Services/IBucketInfoService.cs | 53 + .../Services/IBucketMaterialsRecordService.cs | 49 + .../CraftsInfoService/Dtos/CraftsInfoDto.cs | 83 + .../CraftsInfoService/Dtos/CraftsStepsDto.cs | 100 + .../Services/CraftsInfoService.cs | 130 + .../Services/CraftsStepsService.cs | 144 + .../Services/ICraftsInfoService.cs | 48 + .../Services/ICraftsStepsService.cs | 54 + .../Dtos/DeviceProductDto.cs | 87 + .../Dtos/DeviceProductFunctionDto.cs | 111 + .../Dtos/DeviceProductParmDto.cs | 91 + .../Services/DeviceProductFunctionService.cs | 128 + .../Services/DeviceProductParmService.cs | 115 + .../Services/DeviceProductService.cs | 127 + .../Services/IDeviceProductFunctionService.cs | 48 + .../Services/IDeviceProductParmService.cs | 48 + .../Services/IDeviceProductService.cs | 48 + .../DeviceService/Dtos/DeviceRecipeDto.cs | 99 + .../DeviceService/Dtos/DevicesInfoDto.cs | 88 + .../Services/DeviceRecipeService.cs | 144 + .../Services/DevicesInfoService.cs | 119 + .../Services/IDeviceRecipeService.cs | 49 + .../Services/IDevicesInfoService.cs | 48 + .../Services/DictService/Dtos/DictDataDto.cs | 102 + .../Services/DictService/Dtos/DictTypeDto.cs | 86 + .../DictService/Services/DictDataService.cs | 123 + .../DictService/Services/DictTypeService.cs | 110 + .../DictService/Services/IDictDataService.cs | 43 + .../DictService/Services/IDictTypeService.cs | 44 + .../FinalsInfoService/Dtos/FinalsInfoDto.cs | 87 + .../Services/FinalsInfoService.cs | 123 + .../Services/IFinalsInfoService.cs | 49 + .../Services/ICRUDService.cs | 43 + .../KepServerDataService/Dto/DataVDataDto.cs | 15 + .../Services/IKepDataService.cs | 14 + .../Services/KepDataService.cs | 224 + .../Services/LogService/Dtos/AlarmLogDto.cs | 123 + .../Services/LogService/Dtos/ProgramLogDto.cs | 101 + .../Services/LogService/Dtos/RunLogDto.cs | 99 + .../Services/LogService/Dtos/UserLogDto.cs | 91 + .../LogService/Services/AlarmLogService.cs | 100 + .../LogService/Services/IAlarmLogService.cs | 43 + .../LogService/Services/IProgramLogService.cs | 43 + .../LogService/Services/IRunLogService.cs | 43 + .../LogService/Services/IUserLogService.cs | 43 + .../LogService/Services/ProgramLogService.cs | 98 + .../LogService/Services/RunLogService.cs | 99 + .../LogService/Services/UserLogService.cs | 95 + .../MaterialService/Dtos/MaterialsInfoDto.cs | 97 + .../Services/IMaterialsInfoService.cs | 48 + .../Services/MaterialsInfoService.cs | 133 + .../OperLogService/Dtos/OperLogDto.cs | 37 + .../Services/IOperLogService.cs | 17 + .../OperLogService/Services/OperLogService.cs | 12 + .../OrderService/Dtos/OrderBaseDto.cs | 78 + .../OrderService/Dtos/OrderQueryPageInput.cs | 16 + .../OrderService/Service/IOrderService.cs | 57 + .../OrderService/Service/OrderService.cs | 374 + .../ProductLineService/Dtos/GroupInfoDto.cs | 68 + .../Dtos/ProductLineDeviceDto.cs | 90 + .../ProductLineService/Dtos/ProductLineDto.cs | 76 + .../Dtos/ProductLineStockDto.cs | 99 + .../Services/GroupInfoService.cs | 116 + .../Services/IGroupInfoService.cs | 48 + .../Services/IProductLineService.cs | 100 + .../Services/ProductLineService.cs | 268 + .../RecipesService/Dtos/RecipeMaterialDto.cs | 98 + .../RecipesService/Dtos/RecipesInfoDto.cs | 84 + .../Services/IRecipeMaterialService.cs | 49 + .../Services/IRecipesInfoService.cs | 54 + .../Services/RecipeMaterialService.cs | 130 + .../Services/RecipesInfoService.cs | 136 + .../ReportService/Dtos/MaterialsInputDto.cs | 15 + .../ReportService/Dtos/MaterialsOutDto.cs | 15 + .../ReportService/Dtos/ProductInputDto.cs | 15 + .../ReportService/Dtos/ProductOutDto.cs | 15 + .../Services/ReportService/IReportService.cs | 26 + .../Services/ReportService/ReportService.cs | 69 + .../StockInfoService/Dtos/StockInfoDto.cs | 83 + .../Services/IStockInfoService.cs | 49 + .../Services/StockInfoService.cs | 123 + .../SysCacheService/ISysCacheService.cs | 15 + .../SysCacheService/SysCacheService.cs | 163 + .../SystemService/Dtos/AccountInput.cs | 98 + .../SystemService/Dtos/AccountOutput.cs | 29 + .../SystemService/Dtos/AuthorizeInput.cs | 97 + .../SystemService/Dtos/AuthorizeOutput.cs | 27 + .../SystemService/Dtos/EmployeeInput.cs | 101 + .../SystemService/Dtos/EmployeeOutput.cs | 45 + .../Services/SystemService/Dtos/Mapper.cs | 8 + .../SystemService/Dtos/ModuleInput.cs | 94 + .../SystemService/Dtos/ModuleOutput.cs | 48 + .../SystemService/Dtos/ModuleTreeInput.cs | 108 + .../SystemService/Dtos/ModuleTreeOutput.cs | 59 + .../Services/SystemService/Dtos/RoleInput.cs | 71 + .../SystemService/Dtos/RoleModuleDto.cs | 50 + .../Services/SystemService/Dtos/RoleOutput.cs | 24 + .../SystemService/Dtos/UserRoleCacheDto.cs | 62 + .../Services/AuthorizeService.cs | 467 + .../Services/IAuthorizeService.cs | 50 + .../WorkInfoService/Dtos/WorkBatchDto.cs | 98 + .../Dtos/WorkInfoCraftstepRecordDto.cs | 91 + .../WorkInfoService/Dtos/WorkInfoDto.cs | 203 + .../WorkInfoService/Dtos/WorkInfoItemDto.cs | 71 + .../Dtos/WorkInfoMaterialsRecordDto.cs | 112 + .../WorkInfoService/Dtos/WorkInfoStatusDto.cs | 130 + .../Services/IWorkBatchService.cs | 43 + .../Services/IWorkInfoService.cs | 90 + .../Services/IWorkInfoStatusService.cs | 13 + .../Services/WorkBatchService.cs | 81 + .../Services/WorkInfoService.cs | 670 ++ .../Services/WorkInfoStatusService.cs | 12 + .../Subscriber/ToDoEventSubscriber.cs | 28 + .../applicationsettings.json | 12 + .../BPA.MES.Base.Core.csproj | 26 + .../BPA.MES.Base.Core/BPA.MES.Base.Core.xml | 136 + backend/BPA.MES.Base.Core/DEntityBase.cs | 27 + backend/BPA.MES.Base.Core/EmptyExtensions.cs | 21 + .../BPA.MES.Base.Core/KepServerSqlsugar.cs | 64 + backend/BPA.MES.Base.Core/RequestPage.cs | 22 + .../BPA.MES.Base.Core/SqlSugarPagedList.cs | 109 + backend/BPA.MES.Base.Core/SqlsugarSetup.cs | 52 + backend/BPA.MES.Base.Core/TreeExtensions.cs | 65 + .../BPA.MES.Base.Web.Core.csproj | 19 + .../BPA.MES.Base.Web.Core.xml | 22 + .../Handlers/JwtHandler.cs | 72 + backend/BPA.MES.Base.Web.Core/Startup.cs | 87 + .../.config/dotnet-tools.json | 5 + .../BPA.MES.Base.Web.Entry.csproj | 33 + .../BPA.MES.Base.Web.Entry.csproj.user | 10 + backend/BPA.MES.Base.Web.Entry/Dockerfile | 25 + backend/BPA.MES.Base.Web.Entry/Program.cs | 1 + .../SingleFilePublish.cs | 22 + .../appsettings.Development.json | 10 + .../BPA.MES.Base.Web.Entry/appsettings.json | 20 + backend/BPA.MES.Base.sln | 43 + backend/NuGet.config | 7 + backend/dockerfile | 30 + frontend/.editorconfig | 16 + frontend/.eslintignore | 8 + frontend/.eslintrc.js | 7 + frontend/.gitignore | 41 + frontend/.prettierignore | 22 + frontend/.prettierrc.js | 21 + frontend/README.md | 57 + frontend/config/config.ts | 132 + frontend/config/defaultSettings.ts | 28 + frontend/config/proxy.ts | 26 + frontend/config/routes.ts | 75 + frontend/default.conf | 13 + frontend/dockerfile | 4 + frontend/jest.config.ts | 23 + frontend/jsconfig.json | 11 + frontend/package.json | 106 + frontend/playwright.config.ts | 22 + frontend/public/CNAME | 1 + frontend/public/favicon.ico | Bin 0 -> 4286 bytes frontend/public/icons/icon-128x128.png | Bin 0 -> 1329 bytes frontend/public/icons/icon-192x192.png | Bin 0 -> 1856 bytes frontend/public/icons/icon-512x512.png | Bin 0 -> 5082 bytes frontend/public/logo.png | Bin 0 -> 77326 bytes frontend/public/logo.svg | 1 + frontend/public/nc.png | Bin 0 -> 366817 bytes frontend/public/pro_icon.svg | 5 + frontend/src/api/AuthTemplate.ts | 119 + frontend/src/api/Bucket.ts | 132 + frontend/src/api/DeviceInfo.ts | 119 + frontend/src/api/Material.ts | 334 + frontend/src/api/StockService.ts | 119 + frontend/src/api/agvbasicService.ts | 60 + frontend/src/api/agvlineService.ts | 60 + frontend/src/api/craftsinfo.ts | 159 + .../api/deviceInfo/dtos/deviceProduct.d.ts | 72 + .../dtos/deviceProductFunction.d.ts | 77 + .../deviceInfo/dtos/deviceProductParm.d.ts | 74 + .../api/deviceInfo/services/deviceProduct.ts | 88 + .../services/deviceProductFunction.ts | 83 + .../deviceInfo/services/deviceProductParm.ts | 83 + frontend/src/api/dictType/dto.d.ts | 145 + frontend/src/api/dictType/service.ts | 164 + frontend/src/api/finalService.ts | 123 + frontend/src/api/groupService.ts | 60 + frontend/src/api/kepService.ts | 48 + frontend/src/api/logs/dto.d.ts | 316 + frontend/src/api/logs/service.ts | 338 + frontend/src/api/materialService.ts | 70 + frontend/src/api/orderService.ts | 95 + frontend/src/api/productlineService.ts | 124 + frontend/src/api/recipeService.ts | 90 + frontend/src/api/reportService.ts | 34 + frontend/src/api/storeService.ts | 59 + frontend/src/api/sys/dto.d.ts | 146 + frontend/src/api/sys/service.ts | 294 + frontend/src/api/template/dto.d.ts | 67 + frontend/src/api/template/service.ts | 83 + frontend/src/api/workService.ts | 121 + frontend/src/app.tsx | 145 + frontend/src/assets/images/loginFace.png | Bin 0 -> 53185 bytes frontend/src/assets/images/logo.png | Bin 0 -> 109743 bytes frontend/src/components/Footer/index.less | 8 + frontend/src/components/Footer/index.tsx | 43 + .../src/components/HeaderRight/index.less | 11 + frontend/src/components/HeaderRight/index.tsx | 114 + .../components/KepData/img/20231113152729.png | Bin 0 -> 33109 bytes .../components/KepData/img/20231113174659.png | Bin 0 -> 100413 bytes .../src/components/KepData/img/313x289.png | Bin 0 -> 135507 bytes frontend/src/components/KepData/img/555.png | Bin 0 -> 571251 bytes frontend/src/components/KepData/img/R-C.gif | Bin 0 -> 685027 bytes frontend/src/components/KepData/img/aaaa.png | Bin 0 -> 56771 bytes frontend/src/components/KepData/img/bg.png | Bin 0 -> 206566 bytes .../KepData/img/center-details-data1.png | Bin 0 -> 34624 bytes .../KepData/img/center-details-data2.png | Bin 0 -> 45176 bytes .../KepData/img/center-details-data3.png | Bin 0 -> 38417 bytes .../KepData/img/center-details-data4.png | Bin 0 -> 44937 bytes .../KepData/img/center-details-data5.png | Bin 0 -> 26772 bytes .../KepData/img/center-details-data6.png | Bin 0 -> 25785 bytes frontend/src/components/KepData/img/cyg.png | Bin 0 -> 246666 bytes frontend/src/components/KepData/img/ssssx.png | Bin 0 -> 3792 bytes frontend/src/components/KepData/img/title.png | Bin 0 -> 2288 bytes .../src/components/KepData/img/title1.png | Bin 0 -> 2469 bytes frontend/src/components/KepData/img/top.png | Bin 0 -> 8093 bytes .../KepData/img/屏幕截图 20.png | Bin 0 -> 14348 bytes .../src/components/KepData/index copy 2.less | 110 + .../src/components/KepData/index copy 2.tsx | 791 ++ .../src/components/KepData/index copy.less | 93 + .../src/components/KepData/index copy.tsx | 463 + frontend/src/components/KepData/index.less | 117 + frontend/src/components/KepData/index.tsx | 2806 +++++ .../src/components/SelectSearchPage/index.tsx | 44 + frontend/src/components/datav.rar | Bin 0 -> 290112 bytes .../src/components/datav/BottomLeftChart1.js | 60 + .../components/datav/BottomLeftChart1.less | 37 + .../src/components/datav/BottomLeftChart2.js | 79 + .../components/datav/BottomLeftChart2.less | 24 + .../src/components/datav/BottomRightTable1.js | 38 + .../components/datav/BottomRightTable1.less | 28 + .../src/components/datav/BottomRightTable2.js | 34 + .../components/datav/BottomRightTable2.less | 28 + .../src/components/datav/BottomRightTable3.js | 34 + .../components/datav/BottomRightTable3.less | 28 + .../src/components/datav/BottomRightTable4.js | 34 + .../components/datav/BottomRightTable4.less | 28 + frontend/src/components/datav/TopLeftCmp.js | 76 + frontend/src/components/datav/TopLeftCmp.less | 64 + frontend/src/components/datav/TopMiddleCmp.js | 120 + .../src/components/datav/TopMiddleCmp.less | 13 + frontend/src/components/datav/TopRightCmp.js | 143 + .../src/components/datav/TopRightCmp.less | 13 + frontend/src/components/datav/img/313x289.png | Bin 0 -> 135507 bytes frontend/src/components/datav/img/bg.png | Bin 0 -> 206566 bytes frontend/src/components/datav/img/icon1.png | Bin 0 -> 2043 bytes frontend/src/components/datav/img/icon2.png | Bin 0 -> 5782 bytes frontend/src/components/datav/img/icon3.png | Bin 0 -> 2079 bytes frontend/src/components/datav/img/icon4.png | Bin 0 -> 7905 bytes frontend/src/components/datav/img/wendu.png | Bin 0 -> 56771 bytes frontend/src/components/datav/index.js | 72 + frontend/src/components/datav/index.less | 105 + frontend/src/global.less | 57 + frontend/src/global.tsx | 90 + frontend/src/manifest.json | 22 + frontend/src/pages/404.tsx | 18 + frontend/src/pages/agvbasic copy/index.tsx | 234 + frontend/src/pages/agvbasic/index.tsx | 235 + frontend/src/pages/agvline/index.tsx | 324 + frontend/src/pages/bucket/index.less | 12 + frontend/src/pages/bucket/index.tsx | 509 + frontend/src/pages/craftInfo/index.less | 12 + frontend/src/pages/craftInfo/kettle.tsx | 538 + frontend/src/pages/craftInfo/pot.tsx | 662 ++ frontend/src/pages/deviceInfo/index.tsx | 252 + frontend/src/pages/deviceProductInfo/func.tsx | 7 + .../src/pages/deviceProductInfo/index.less | 3 + .../src/pages/deviceProductInfo/index.tsx | 486 + frontend/src/pages/dict/index.tsx | 512 + frontend/src/pages/final/index.less | 4 + frontend/src/pages/final/index.tsx | 335 + frontend/src/pages/group/index.tsx | 272 + frontend/src/pages/kep/alarmLimit/index.tsx | 208 + frontend/src/pages/kep/datav/index.tsx | 27 + frontend/src/pages/locales/zh-CN.js | 0 frontend/src/pages/logs/alarmlog.tsx | 145 + frontend/src/pages/logs/programlog.tsx | 129 + frontend/src/pages/logs/runlog.tsx | 127 + frontend/src/pages/logs/userlog.tsx | 130 + frontend/src/pages/manufacturing/index.less | 37 + frontend/src/pages/manufacturing/index.tsx | 915 ++ frontend/src/pages/materials/index.tsx | 276 + frontend/src/pages/order/index.tsx | 549 + frontend/src/pages/productLine/index.less | 37 + frontend/src/pages/productLine/index.tsx | 813 ++ frontend/src/pages/recipe/index.less | 37 + frontend/src/pages/recipe/index.tsx | 418 + frontend/src/pages/report/material/index.tsx | 90 + frontend/src/pages/report/product/index.tsx | 95 + frontend/src/pages/stock/index.tsx | 298 + frontend/src/pages/storeinfo/index.tsx | 227 + frontend/src/pages/system/account/index.tsx | 166 + frontend/src/pages/system/module/index.less | 0 frontend/src/pages/system/module/index.tsx | 351 + frontend/src/pages/system/role/index.less | 54 + frontend/src/pages/system/role/index.tsx | 338 + frontend/src/pages/system/user/index.less | 163 + frontend/src/pages/system/user/index.tsx | 419 + frontend/src/pages/template/index.less | 0 frontend/src/pages/template/index.tsx | 168 + frontend/src/pages/user/login/index.less | 161 + frontend/src/pages/user/login/index.tsx | 97 + frontend/src/pages/welcome/index.tsx | 20 + frontend/src/pages/workInfo/index.less | 5 + frontend/src/pages/workInfo/index.tsx | 1043 ++ frontend/src/requestErrorConfig.ts | 96 + frontend/src/service-worker.js | 65 + frontend/src/types/Bucket.d.ts | 148 + frontend/src/types/ClassGroup.d.ts | 120 + frontend/src/types/CraftFunc.d.ts | 196 + frontend/src/types/Crafts.d.ts | 170 + frontend/src/types/DeviceInfo.d.ts | 116 + frontend/src/types/FinalInfo.d.ts | 112 + frontend/src/types/GroupInfo.d.ts | 112 + frontend/src/types/Materials.d.ts | 126 + frontend/src/types/MyResponse.d.ts | 23 + frontend/src/types/OrderType.ts | 34 + frontend/src/types/ProductlineInfo.d.ts | 158 + frontend/src/types/Recipe.d.ts | 29 + frontend/src/types/ReportType.ts | 26 + frontend/src/types/StockInfo.d.ts | 109 + frontend/src/types/StoreInfo.d.ts | 15 + frontend/src/types/UnitTypes.d.ts | 26 + frontend/src/types/WorkInfo.d.ts | 155 + frontend/src/types/agvbasicInfo.d.ts | 113 + frontend/src/types/agvlineInfo.d.ts | 118 + frontend/src/typings.d.ts | 26 + frontend/src/utils/Token.ts | 12 + frontend/src/utils/eventEmitter.ts | 43 + frontend/tsconfig.json | 23 + frontend/types/cache/cache.json | 1 + frontend/types/cache/mock/mock.cache.js | 0 k8s_pztjapi.yaml | 64 + k8s_pztjweb.yaml | 55 + lib/资料.txt | 0 node_modules/.yarn-integrity | 10 + yarn.lock | 4 + 423 files changed, 49169 insertions(+) create mode 100644 .gitignore create mode 100644 Jenkinsfile create mode 100644 NuGet.config create mode 100644 backend/.dockerignore create mode 100644 backend/BPA.MES.Base.Application/BPA.MES.Base.Application.csproj create mode 100644 backend/BPA.MES.Base.Application/BPA.MES.Base.Application.xml create mode 100644 backend/BPA.MES.Base.Application/Const/ClaimConst.cs create mode 100644 backend/BPA.MES.Base.Application/Const/DeviceTypeEnum.cs create mode 100644 backend/BPA.MES.Base.Application/Const/ELogType.cs create mode 100644 backend/BPA.MES.Base.Application/Const/OrderStatusEnum.cs create mode 100644 backend/BPA.MES.Base.Application/Const/WorkOrderStatusEnum.cs create mode 100644 backend/BPA.MES.Base.Application/Entitys/Agv/AgvLineEntity.cs create mode 100644 backend/BPA.MES.Base.Application/Entitys/Agv/AgvPointEntity.cs create mode 100644 backend/BPA.MES.Base.Application/Entitys/App/Pztj_BucketInfoEntity.cs create mode 100644 backend/BPA.MES.Base.Application/Entitys/App/Pztj_BucketMaterialsRecordEntity.cs create mode 100644 backend/BPA.MES.Base.Application/Entitys/App/Pztj_CraftStepsEntity.cs create mode 100644 backend/BPA.MES.Base.Application/Entitys/App/Pztj_CraftsInfoEntity.cs create mode 100644 backend/BPA.MES.Base.Application/Entitys/App/Pztj_DevicesInfoEntity.cs create mode 100644 backend/BPA.MES.Base.Application/Entitys/App/Pztj_FinalsInfoEntity.cs create mode 100644 backend/BPA.MES.Base.Application/Entitys/App/Pztj_LineDevicesEntity.cs create mode 100644 backend/BPA.MES.Base.Application/Entitys/App/Pztj_LineStocksEntity.cs create mode 100644 backend/BPA.MES.Base.Application/Entitys/App/Pztj_MaterialsInfoEntity.cs create mode 100644 backend/BPA.MES.Base.Application/Entitys/App/Pztj_StockInfoEntity.cs create mode 100644 backend/BPA.MES.Base.Application/Entitys/App/Pztj_WorkInfoEntity.cs create mode 100644 backend/BPA.MES.Base.Application/Entitys/App/Pztj_WorkInfoItemEntity.cs create mode 100644 backend/BPA.MES.Base.Application/Entitys/App/Pztj_WorkInfoStatusEntity.cs create mode 100644 backend/BPA.MES.Base.Application/Entitys/App/WorkBatchEntity.cs create mode 100644 backend/BPA.MES.Base.Application/Entitys/App/WorkInfoCraftstepRecordEntity.cs create mode 100644 backend/BPA.MES.Base.Application/Entitys/App/WorkInfoMaterialsRecordEntity.cs create mode 100644 backend/BPA.MES.Base.Application/Entitys/Base/DeviceProductEntity.cs create mode 100644 backend/BPA.MES.Base.Application/Entitys/Base/DeviceProductFunctionEntity.cs create mode 100644 backend/BPA.MES.Base.Application/Entitys/Base/DeviceProductParmEntity.cs create mode 100644 backend/BPA.MES.Base.Application/Entitys/Base/DeviceRecipeEntity.cs create mode 100644 backend/BPA.MES.Base.Application/Entitys/Base/DictDataEntity.cs create mode 100644 backend/BPA.MES.Base.Application/Entitys/Base/DictTypeEntity.cs create mode 100644 backend/BPA.MES.Base.Application/Entitys/Base/GroupInfoEntity.cs create mode 100644 backend/BPA.MES.Base.Application/Entitys/Base/MQTTInfoEntity.cs create mode 100644 backend/BPA.MES.Base.Application/Entitys/Base/OperLogEntity.cs create mode 100644 backend/BPA.MES.Base.Application/Entitys/Base/OrderInfoEntity.cs create mode 100644 backend/BPA.MES.Base.Application/Entitys/Base/ProductLineEntity.cs create mode 100644 backend/BPA.MES.Base.Application/Entitys/Base/RecipeMaterialEntity.cs create mode 100644 backend/BPA.MES.Base.Application/Entitys/Base/RecipesGroupEntity.cs create mode 100644 backend/BPA.MES.Base.Application/Entitys/Base/RecipesInfoEntity.cs create mode 100644 backend/BPA.MES.Base.Application/Entitys/Base/StoreInfoEntity.cs create mode 100644 backend/BPA.MES.Base.Application/Entitys/KepData/AlarmLog.cs create mode 100644 backend/BPA.MES.Base.Application/Entitys/KepData/DataVAlarmLimit.cs create mode 100644 backend/BPA.MES.Base.Application/Entitys/KepData/ch1_device1.cs create mode 100644 backend/BPA.MES.Base.Application/Entitys/Logs/AlarmLogEntity.cs create mode 100644 backend/BPA.MES.Base.Application/Entitys/Logs/ProgramLogEntity.cs create mode 100644 backend/BPA.MES.Base.Application/Entitys/Logs/RunLogEntity.cs create mode 100644 backend/BPA.MES.Base.Application/Entitys/Logs/UserLogEntity.cs create mode 100644 backend/BPA.MES.Base.Application/Entitys/Order/OrderEntity.cs create mode 100644 backend/BPA.MES.Base.Application/Entitys/Order/OrderInfoEntity.cs create mode 100644 backend/BPA.MES.Base.Application/Entitys/Order/OrderWorkEntity.cs create mode 100644 backend/BPA.MES.Base.Application/Entitys/Sys/AccountEntity.cs create mode 100644 backend/BPA.MES.Base.Application/Entitys/Sys/EmployeeEntity.cs create mode 100644 backend/BPA.MES.Base.Application/Entitys/Sys/ModuleEntity.cs create mode 100644 backend/BPA.MES.Base.Application/Entitys/Sys/RoleEntity.cs create mode 100644 backend/BPA.MES.Base.Application/Entitys/Sys/RoleModuleEntity.cs create mode 100644 backend/BPA.MES.Base.Application/Filters/AGVAttribute.cs create mode 100644 backend/BPA.MES.Base.Application/Filters/OperLogAttribute.cs create mode 100644 backend/BPA.MES.Base.Application/GlobalUsings.cs create mode 100644 backend/BPA.MES.Base.Application/MQTT/IMessage.cs create mode 100644 backend/BPA.MES.Base.Application/MQTT/MQTTService.cs create mode 100644 backend/BPA.MES.Base.Application/MQTT/MessageID.cs create mode 100644 backend/BPA.MES.Base.Application/MQTT/MsgPackage.cs create mode 100644 backend/BPA.MES.Base.Application/MQTT/Topics.cs create mode 100644 backend/BPA.MES.Base.Application/Services/AGVService/Dtos/AGVThirdPartyDto.cs create mode 100644 backend/BPA.MES.Base.Application/Services/AGVService/Dtos/AgvLineDto.cs create mode 100644 backend/BPA.MES.Base.Application/Services/AGVService/Dtos/AgvPointDto.cs create mode 100644 backend/BPA.MES.Base.Application/Services/AGVService/Services/AGVThirdPartyService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/AGVService/Services/AgvLineService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/AGVService/Services/AgvPointService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/AGVService/Services/IAGVThirdPartyService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/AGVService/Services/IAgvLineService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/AGVService/Services/IAgvPointService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/BaseService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/BucketInfoService/Dtos/BucketInfoDto.cs create mode 100644 backend/BPA.MES.Base.Application/Services/BucketInfoService/Dtos/BucketMaterialsRecordDto.cs create mode 100644 backend/BPA.MES.Base.Application/Services/BucketInfoService/Services/BucketInfoService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/BucketInfoService/Services/BucketMaterialsRecordServcie.cs create mode 100644 backend/BPA.MES.Base.Application/Services/BucketInfoService/Services/IBucketInfoService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/BucketInfoService/Services/IBucketMaterialsRecordService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/CraftsInfoService/Dtos/CraftsInfoDto.cs create mode 100644 backend/BPA.MES.Base.Application/Services/CraftsInfoService/Dtos/CraftsStepsDto.cs create mode 100644 backend/BPA.MES.Base.Application/Services/CraftsInfoService/Services/CraftsInfoService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/CraftsInfoService/Services/CraftsStepsService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/CraftsInfoService/Services/ICraftsInfoService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/CraftsInfoService/Services/ICraftsStepsService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/DeviceProductService/Dtos/DeviceProductDto.cs create mode 100644 backend/BPA.MES.Base.Application/Services/DeviceProductService/Dtos/DeviceProductFunctionDto.cs create mode 100644 backend/BPA.MES.Base.Application/Services/DeviceProductService/Dtos/DeviceProductParmDto.cs create mode 100644 backend/BPA.MES.Base.Application/Services/DeviceProductService/Services/DeviceProductFunctionService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/DeviceProductService/Services/DeviceProductParmService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/DeviceProductService/Services/DeviceProductService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/DeviceProductService/Services/IDeviceProductFunctionService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/DeviceProductService/Services/IDeviceProductParmService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/DeviceProductService/Services/IDeviceProductService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/DeviceService/Dtos/DeviceRecipeDto.cs create mode 100644 backend/BPA.MES.Base.Application/Services/DeviceService/Dtos/DevicesInfoDto.cs create mode 100644 backend/BPA.MES.Base.Application/Services/DeviceService/Services/DeviceRecipeService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/DeviceService/Services/DevicesInfoService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/DeviceService/Services/IDeviceRecipeService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/DeviceService/Services/IDevicesInfoService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/DictService/Dtos/DictDataDto.cs create mode 100644 backend/BPA.MES.Base.Application/Services/DictService/Dtos/DictTypeDto.cs create mode 100644 backend/BPA.MES.Base.Application/Services/DictService/Services/DictDataService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/DictService/Services/DictTypeService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/DictService/Services/IDictDataService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/DictService/Services/IDictTypeService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/FinalsInfoService/Dtos/FinalsInfoDto.cs create mode 100644 backend/BPA.MES.Base.Application/Services/FinalsInfoService/Services/FinalsInfoService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/FinalsInfoService/Services/IFinalsInfoService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/ICRUDService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/KepServerDataService/Dto/DataVDataDto.cs create mode 100644 backend/BPA.MES.Base.Application/Services/KepServerDataService/Services/IKepDataService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/KepServerDataService/Services/KepDataService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/LogService/Dtos/AlarmLogDto.cs create mode 100644 backend/BPA.MES.Base.Application/Services/LogService/Dtos/ProgramLogDto.cs create mode 100644 backend/BPA.MES.Base.Application/Services/LogService/Dtos/RunLogDto.cs create mode 100644 backend/BPA.MES.Base.Application/Services/LogService/Dtos/UserLogDto.cs create mode 100644 backend/BPA.MES.Base.Application/Services/LogService/Services/AlarmLogService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/LogService/Services/IAlarmLogService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/LogService/Services/IProgramLogService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/LogService/Services/IRunLogService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/LogService/Services/IUserLogService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/LogService/Services/ProgramLogService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/LogService/Services/RunLogService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/LogService/Services/UserLogService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/MaterialService/Dtos/MaterialsInfoDto.cs create mode 100644 backend/BPA.MES.Base.Application/Services/MaterialService/Services/IMaterialsInfoService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/MaterialService/Services/MaterialsInfoService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/OperLogService/Dtos/OperLogDto.cs create mode 100644 backend/BPA.MES.Base.Application/Services/OperLogService/Services/IOperLogService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/OperLogService/Services/OperLogService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/OrderService/Dtos/OrderBaseDto.cs create mode 100644 backend/BPA.MES.Base.Application/Services/OrderService/Dtos/OrderQueryPageInput.cs create mode 100644 backend/BPA.MES.Base.Application/Services/OrderService/Service/IOrderService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/OrderService/Service/OrderService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/ProductLineService/Dtos/GroupInfoDto.cs create mode 100644 backend/BPA.MES.Base.Application/Services/ProductLineService/Dtos/ProductLineDeviceDto.cs create mode 100644 backend/BPA.MES.Base.Application/Services/ProductLineService/Dtos/ProductLineDto.cs create mode 100644 backend/BPA.MES.Base.Application/Services/ProductLineService/Dtos/ProductLineStockDto.cs create mode 100644 backend/BPA.MES.Base.Application/Services/ProductLineService/Services/GroupInfoService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/ProductLineService/Services/IGroupInfoService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/ProductLineService/Services/IProductLineService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/ProductLineService/Services/ProductLineService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/RecipesService/Dtos/RecipeMaterialDto.cs create mode 100644 backend/BPA.MES.Base.Application/Services/RecipesService/Dtos/RecipesInfoDto.cs create mode 100644 backend/BPA.MES.Base.Application/Services/RecipesService/Services/IRecipeMaterialService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/RecipesService/Services/IRecipesInfoService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/RecipesService/Services/RecipeMaterialService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/RecipesService/Services/RecipesInfoService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/ReportService/Dtos/MaterialsInputDto.cs create mode 100644 backend/BPA.MES.Base.Application/Services/ReportService/Dtos/MaterialsOutDto.cs create mode 100644 backend/BPA.MES.Base.Application/Services/ReportService/Dtos/ProductInputDto.cs create mode 100644 backend/BPA.MES.Base.Application/Services/ReportService/Dtos/ProductOutDto.cs create mode 100644 backend/BPA.MES.Base.Application/Services/ReportService/IReportService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/ReportService/ReportService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/StockInfoService/Dtos/StockInfoDto.cs create mode 100644 backend/BPA.MES.Base.Application/Services/StockInfoService/Services/IStockInfoService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/StockInfoService/Services/StockInfoService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/SysCacheService/ISysCacheService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/SysCacheService/SysCacheService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/SystemService/Dtos/AccountInput.cs create mode 100644 backend/BPA.MES.Base.Application/Services/SystemService/Dtos/AccountOutput.cs create mode 100644 backend/BPA.MES.Base.Application/Services/SystemService/Dtos/AuthorizeInput.cs create mode 100644 backend/BPA.MES.Base.Application/Services/SystemService/Dtos/AuthorizeOutput.cs create mode 100644 backend/BPA.MES.Base.Application/Services/SystemService/Dtos/EmployeeInput.cs create mode 100644 backend/BPA.MES.Base.Application/Services/SystemService/Dtos/EmployeeOutput.cs create mode 100644 backend/BPA.MES.Base.Application/Services/SystemService/Dtos/Mapper.cs create mode 100644 backend/BPA.MES.Base.Application/Services/SystemService/Dtos/ModuleInput.cs create mode 100644 backend/BPA.MES.Base.Application/Services/SystemService/Dtos/ModuleOutput.cs create mode 100644 backend/BPA.MES.Base.Application/Services/SystemService/Dtos/ModuleTreeInput.cs create mode 100644 backend/BPA.MES.Base.Application/Services/SystemService/Dtos/ModuleTreeOutput.cs create mode 100644 backend/BPA.MES.Base.Application/Services/SystemService/Dtos/RoleInput.cs create mode 100644 backend/BPA.MES.Base.Application/Services/SystemService/Dtos/RoleModuleDto.cs create mode 100644 backend/BPA.MES.Base.Application/Services/SystemService/Dtos/RoleOutput.cs create mode 100644 backend/BPA.MES.Base.Application/Services/SystemService/Dtos/UserRoleCacheDto.cs create mode 100644 backend/BPA.MES.Base.Application/Services/SystemService/Services/AuthorizeService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/SystemService/Services/IAuthorizeService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/WorkInfoService/Dtos/WorkBatchDto.cs create mode 100644 backend/BPA.MES.Base.Application/Services/WorkInfoService/Dtos/WorkInfoCraftstepRecordDto.cs create mode 100644 backend/BPA.MES.Base.Application/Services/WorkInfoService/Dtos/WorkInfoDto.cs create mode 100644 backend/BPA.MES.Base.Application/Services/WorkInfoService/Dtos/WorkInfoItemDto.cs create mode 100644 backend/BPA.MES.Base.Application/Services/WorkInfoService/Dtos/WorkInfoMaterialsRecordDto.cs create mode 100644 backend/BPA.MES.Base.Application/Services/WorkInfoService/Dtos/WorkInfoStatusDto.cs create mode 100644 backend/BPA.MES.Base.Application/Services/WorkInfoService/Services/IWorkBatchService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/WorkInfoService/Services/IWorkInfoService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/WorkInfoService/Services/IWorkInfoStatusService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/WorkInfoService/Services/WorkBatchService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/WorkInfoService/Services/WorkInfoService.cs create mode 100644 backend/BPA.MES.Base.Application/Services/WorkInfoService/Services/WorkInfoStatusService.cs create mode 100644 backend/BPA.MES.Base.Application/Subscriber/ToDoEventSubscriber.cs create mode 100644 backend/BPA.MES.Base.Application/applicationsettings.json create mode 100644 backend/BPA.MES.Base.Core/BPA.MES.Base.Core.csproj create mode 100644 backend/BPA.MES.Base.Core/BPA.MES.Base.Core.xml create mode 100644 backend/BPA.MES.Base.Core/DEntityBase.cs create mode 100644 backend/BPA.MES.Base.Core/EmptyExtensions.cs create mode 100644 backend/BPA.MES.Base.Core/KepServerSqlsugar.cs create mode 100644 backend/BPA.MES.Base.Core/RequestPage.cs create mode 100644 backend/BPA.MES.Base.Core/SqlSugarPagedList.cs create mode 100644 backend/BPA.MES.Base.Core/SqlsugarSetup.cs create mode 100644 backend/BPA.MES.Base.Core/TreeExtensions.cs create mode 100644 backend/BPA.MES.Base.Web.Core/BPA.MES.Base.Web.Core.csproj create mode 100644 backend/BPA.MES.Base.Web.Core/BPA.MES.Base.Web.Core.xml create mode 100644 backend/BPA.MES.Base.Web.Core/Handlers/JwtHandler.cs create mode 100644 backend/BPA.MES.Base.Web.Core/Startup.cs create mode 100644 backend/BPA.MES.Base.Web.Entry/.config/dotnet-tools.json create mode 100644 backend/BPA.MES.Base.Web.Entry/BPA.MES.Base.Web.Entry.csproj create mode 100644 backend/BPA.MES.Base.Web.Entry/BPA.MES.Base.Web.Entry.csproj.user create mode 100644 backend/BPA.MES.Base.Web.Entry/Dockerfile create mode 100644 backend/BPA.MES.Base.Web.Entry/Program.cs create mode 100644 backend/BPA.MES.Base.Web.Entry/SingleFilePublish.cs create mode 100644 backend/BPA.MES.Base.Web.Entry/appsettings.Development.json create mode 100644 backend/BPA.MES.Base.Web.Entry/appsettings.json create mode 100644 backend/BPA.MES.Base.sln create mode 100644 backend/NuGet.config create mode 100644 backend/dockerfile create mode 100644 frontend/.editorconfig create mode 100644 frontend/.eslintignore create mode 100644 frontend/.eslintrc.js create mode 100644 frontend/.gitignore create mode 100644 frontend/.prettierignore create mode 100644 frontend/.prettierrc.js create mode 100644 frontend/README.md create mode 100644 frontend/config/config.ts create mode 100644 frontend/config/defaultSettings.ts create mode 100644 frontend/config/proxy.ts create mode 100644 frontend/config/routes.ts create mode 100644 frontend/default.conf create mode 100644 frontend/dockerfile create mode 100644 frontend/jest.config.ts create mode 100644 frontend/jsconfig.json create mode 100644 frontend/package.json create mode 100644 frontend/playwright.config.ts create mode 100644 frontend/public/CNAME create mode 100644 frontend/public/favicon.ico create mode 100644 frontend/public/icons/icon-128x128.png create mode 100644 frontend/public/icons/icon-192x192.png create mode 100644 frontend/public/icons/icon-512x512.png create mode 100644 frontend/public/logo.png create mode 100644 frontend/public/logo.svg create mode 100644 frontend/public/nc.png create mode 100644 frontend/public/pro_icon.svg create mode 100644 frontend/src/api/AuthTemplate.ts create mode 100644 frontend/src/api/Bucket.ts create mode 100644 frontend/src/api/DeviceInfo.ts create mode 100644 frontend/src/api/Material.ts create mode 100644 frontend/src/api/StockService.ts create mode 100644 frontend/src/api/agvbasicService.ts create mode 100644 frontend/src/api/agvlineService.ts create mode 100644 frontend/src/api/craftsinfo.ts create mode 100644 frontend/src/api/deviceInfo/dtos/deviceProduct.d.ts create mode 100644 frontend/src/api/deviceInfo/dtos/deviceProductFunction.d.ts create mode 100644 frontend/src/api/deviceInfo/dtos/deviceProductParm.d.ts create mode 100644 frontend/src/api/deviceInfo/services/deviceProduct.ts create mode 100644 frontend/src/api/deviceInfo/services/deviceProductFunction.ts create mode 100644 frontend/src/api/deviceInfo/services/deviceProductParm.ts create mode 100644 frontend/src/api/dictType/dto.d.ts create mode 100644 frontend/src/api/dictType/service.ts create mode 100644 frontend/src/api/finalService.ts create mode 100644 frontend/src/api/groupService.ts create mode 100644 frontend/src/api/kepService.ts create mode 100644 frontend/src/api/logs/dto.d.ts create mode 100644 frontend/src/api/logs/service.ts create mode 100644 frontend/src/api/materialService.ts create mode 100644 frontend/src/api/orderService.ts create mode 100644 frontend/src/api/productlineService.ts create mode 100644 frontend/src/api/recipeService.ts create mode 100644 frontend/src/api/reportService.ts create mode 100644 frontend/src/api/storeService.ts create mode 100644 frontend/src/api/sys/dto.d.ts create mode 100644 frontend/src/api/sys/service.ts create mode 100644 frontend/src/api/template/dto.d.ts create mode 100644 frontend/src/api/template/service.ts create mode 100644 frontend/src/api/workService.ts create mode 100644 frontend/src/app.tsx create mode 100644 frontend/src/assets/images/loginFace.png create mode 100644 frontend/src/assets/images/logo.png create mode 100644 frontend/src/components/Footer/index.less create mode 100644 frontend/src/components/Footer/index.tsx create mode 100644 frontend/src/components/HeaderRight/index.less create mode 100644 frontend/src/components/HeaderRight/index.tsx create mode 100644 frontend/src/components/KepData/img/20231113152729.png create mode 100644 frontend/src/components/KepData/img/20231113174659.png create mode 100644 frontend/src/components/KepData/img/313x289.png create mode 100644 frontend/src/components/KepData/img/555.png create mode 100644 frontend/src/components/KepData/img/R-C.gif create mode 100644 frontend/src/components/KepData/img/aaaa.png create mode 100644 frontend/src/components/KepData/img/bg.png create mode 100644 frontend/src/components/KepData/img/center-details-data1.png create mode 100644 frontend/src/components/KepData/img/center-details-data2.png create mode 100644 frontend/src/components/KepData/img/center-details-data3.png create mode 100644 frontend/src/components/KepData/img/center-details-data4.png create mode 100644 frontend/src/components/KepData/img/center-details-data5.png create mode 100644 frontend/src/components/KepData/img/center-details-data6.png create mode 100644 frontend/src/components/KepData/img/cyg.png create mode 100644 frontend/src/components/KepData/img/ssssx.png create mode 100644 frontend/src/components/KepData/img/title.png create mode 100644 frontend/src/components/KepData/img/title1.png create mode 100644 frontend/src/components/KepData/img/top.png create mode 100644 frontend/src/components/KepData/img/屏幕截图 20.png create mode 100644 frontend/src/components/KepData/index copy 2.less create mode 100644 frontend/src/components/KepData/index copy 2.tsx create mode 100644 frontend/src/components/KepData/index copy.less create mode 100644 frontend/src/components/KepData/index copy.tsx create mode 100644 frontend/src/components/KepData/index.less create mode 100644 frontend/src/components/KepData/index.tsx create mode 100644 frontend/src/components/SelectSearchPage/index.tsx create mode 100644 frontend/src/components/datav.rar create mode 100644 frontend/src/components/datav/BottomLeftChart1.js create mode 100644 frontend/src/components/datav/BottomLeftChart1.less create mode 100644 frontend/src/components/datav/BottomLeftChart2.js create mode 100644 frontend/src/components/datav/BottomLeftChart2.less create mode 100644 frontend/src/components/datav/BottomRightTable1.js create mode 100644 frontend/src/components/datav/BottomRightTable1.less create mode 100644 frontend/src/components/datav/BottomRightTable2.js create mode 100644 frontend/src/components/datav/BottomRightTable2.less create mode 100644 frontend/src/components/datav/BottomRightTable3.js create mode 100644 frontend/src/components/datav/BottomRightTable3.less create mode 100644 frontend/src/components/datav/BottomRightTable4.js create mode 100644 frontend/src/components/datav/BottomRightTable4.less create mode 100644 frontend/src/components/datav/TopLeftCmp.js create mode 100644 frontend/src/components/datav/TopLeftCmp.less create mode 100644 frontend/src/components/datav/TopMiddleCmp.js create mode 100644 frontend/src/components/datav/TopMiddleCmp.less create mode 100644 frontend/src/components/datav/TopRightCmp.js create mode 100644 frontend/src/components/datav/TopRightCmp.less create mode 100644 frontend/src/components/datav/img/313x289.png create mode 100644 frontend/src/components/datav/img/bg.png create mode 100644 frontend/src/components/datav/img/icon1.png create mode 100644 frontend/src/components/datav/img/icon2.png create mode 100644 frontend/src/components/datav/img/icon3.png create mode 100644 frontend/src/components/datav/img/icon4.png create mode 100644 frontend/src/components/datav/img/wendu.png create mode 100644 frontend/src/components/datav/index.js create mode 100644 frontend/src/components/datav/index.less create mode 100644 frontend/src/global.less create mode 100644 frontend/src/global.tsx create mode 100644 frontend/src/manifest.json create mode 100644 frontend/src/pages/404.tsx create mode 100644 frontend/src/pages/agvbasic copy/index.tsx create mode 100644 frontend/src/pages/agvbasic/index.tsx create mode 100644 frontend/src/pages/agvline/index.tsx create mode 100644 frontend/src/pages/bucket/index.less create mode 100644 frontend/src/pages/bucket/index.tsx create mode 100644 frontend/src/pages/craftInfo/index.less create mode 100644 frontend/src/pages/craftInfo/kettle.tsx create mode 100644 frontend/src/pages/craftInfo/pot.tsx create mode 100644 frontend/src/pages/deviceInfo/index.tsx create mode 100644 frontend/src/pages/deviceProductInfo/func.tsx create mode 100644 frontend/src/pages/deviceProductInfo/index.less create mode 100644 frontend/src/pages/deviceProductInfo/index.tsx create mode 100644 frontend/src/pages/dict/index.tsx create mode 100644 frontend/src/pages/final/index.less create mode 100644 frontend/src/pages/final/index.tsx create mode 100644 frontend/src/pages/group/index.tsx create mode 100644 frontend/src/pages/kep/alarmLimit/index.tsx create mode 100644 frontend/src/pages/kep/datav/index.tsx create mode 100644 frontend/src/pages/locales/zh-CN.js create mode 100644 frontend/src/pages/logs/alarmlog.tsx create mode 100644 frontend/src/pages/logs/programlog.tsx create mode 100644 frontend/src/pages/logs/runlog.tsx create mode 100644 frontend/src/pages/logs/userlog.tsx create mode 100644 frontend/src/pages/manufacturing/index.less create mode 100644 frontend/src/pages/manufacturing/index.tsx create mode 100644 frontend/src/pages/materials/index.tsx create mode 100644 frontend/src/pages/order/index.tsx create mode 100644 frontend/src/pages/productLine/index.less create mode 100644 frontend/src/pages/productLine/index.tsx create mode 100644 frontend/src/pages/recipe/index.less create mode 100644 frontend/src/pages/recipe/index.tsx create mode 100644 frontend/src/pages/report/material/index.tsx create mode 100644 frontend/src/pages/report/product/index.tsx create mode 100644 frontend/src/pages/stock/index.tsx create mode 100644 frontend/src/pages/storeinfo/index.tsx create mode 100644 frontend/src/pages/system/account/index.tsx create mode 100644 frontend/src/pages/system/module/index.less create mode 100644 frontend/src/pages/system/module/index.tsx create mode 100644 frontend/src/pages/system/role/index.less create mode 100644 frontend/src/pages/system/role/index.tsx create mode 100644 frontend/src/pages/system/user/index.less create mode 100644 frontend/src/pages/system/user/index.tsx create mode 100644 frontend/src/pages/template/index.less create mode 100644 frontend/src/pages/template/index.tsx create mode 100644 frontend/src/pages/user/login/index.less create mode 100644 frontend/src/pages/user/login/index.tsx create mode 100644 frontend/src/pages/welcome/index.tsx create mode 100644 frontend/src/pages/workInfo/index.less create mode 100644 frontend/src/pages/workInfo/index.tsx create mode 100644 frontend/src/requestErrorConfig.ts create mode 100644 frontend/src/service-worker.js create mode 100644 frontend/src/types/Bucket.d.ts create mode 100644 frontend/src/types/ClassGroup.d.ts create mode 100644 frontend/src/types/CraftFunc.d.ts create mode 100644 frontend/src/types/Crafts.d.ts create mode 100644 frontend/src/types/DeviceInfo.d.ts create mode 100644 frontend/src/types/FinalInfo.d.ts create mode 100644 frontend/src/types/GroupInfo.d.ts create mode 100644 frontend/src/types/Materials.d.ts create mode 100644 frontend/src/types/MyResponse.d.ts create mode 100644 frontend/src/types/OrderType.ts create mode 100644 frontend/src/types/ProductlineInfo.d.ts create mode 100644 frontend/src/types/Recipe.d.ts create mode 100644 frontend/src/types/ReportType.ts create mode 100644 frontend/src/types/StockInfo.d.ts create mode 100644 frontend/src/types/StoreInfo.d.ts create mode 100644 frontend/src/types/UnitTypes.d.ts create mode 100644 frontend/src/types/WorkInfo.d.ts create mode 100644 frontend/src/types/agvbasicInfo.d.ts create mode 100644 frontend/src/types/agvlineInfo.d.ts create mode 100644 frontend/src/typings.d.ts create mode 100644 frontend/src/utils/Token.ts create mode 100644 frontend/src/utils/eventEmitter.ts create mode 100644 frontend/tsconfig.json create mode 100644 frontend/types/cache/cache.json create mode 100644 frontend/types/cache/mock/mock.cache.js create mode 100644 k8s_pztjapi.yaml create mode 100644 k8s_pztjweb.yaml create mode 100644 lib/资料.txt create mode 100644 node_modules/.yarn-integrity create mode 100644 yarn.lock diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3a8ec6c --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.vs +obj +bin +Properties diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000..4a6ca4d --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,154 @@ + +pipeline{ + agent any + parameters { + choice( + description: 'pztjwebi:开发环境1', + name: 'environment', + choices: ['pztj'] + ) + + choice( + description: '前端or后端', + name: 'projectqh', + choices: ['backend','frontend'] + ) + + choice( + description: '执行操作(发布|回滚)', + name: 'operation', + choices: ['develop', 'rollback'] + ) + + choice( + description: '分支名', + name: 'branchName', + choices: ['master'] + ) + + string( + name: 'tag', + defaultValue: '', + description: '版本tag' + ) + + } + + stages + { + stage('Prepare') { + steps { + script{ + echo "1.Prepare Stage" + echo "当前环境${params.environment}" + if(params.operation=='develop') + { + checkout scm + script { + build_tag = sh(returnStdout: true, script: 'git rev-parse --short HEAD').trim() + if (env.BRANCH_NAME != 'master') { + build_tag = "${env.BRANCH_NAME}-${build_tag}" + } + } + } + else{ + script { + if(params.branchName!= 'master') + { + build_tag = "${params.branchName}-${params.tag}" + } + else + { + build_tag="${params.tag}" + } + } + } + } + } + } + stage('Test') { + steps { + script{ + echo "2.Test Stage" + } + } + + } + stage('Build') { + steps { + script{ + echo "3.Build Docker Image Stage" + if(params.operation=='develop') + { + if(params.projectqh=='backend') + { + sh "cp -r backend/* ./" + sh "docker build -f backend/dockerfile -t 10.2.1.24:10242/bpa/pztjapi:${build_tag} ." + } + else if(params.projectqh=='frontend') + { + sh "docker build -f frontend/dockerfile -t 10.2.1.24:10242/bpa/pztjweb:${build_tag} ." + } + + } + } + } + } + + + stage('Push') { + steps { + script{ + echo "4.Push Docker Image Stage" + withCredentials([usernamePassword(credentialsId: 'harbor', passwordVariable: 'harborPassword', usernameVariable: 'harborUser')]) { + sh "docker login -u ${harborUser} -p ${harborPassword} 10.2.1.24:10242" + if(params.operation=='develop') + { + if(params.projectqh=='backend') + { + sh "docker push 10.2.1.24:10242/bpa/pztjapi:${build_tag}" + + } + else if(params.projectqh=='frontend') + { + sh "docker push 10.2.1.24:10242/bpa/pztjweb:${build_tag}" + } + + } + } + } + } + + + + } + stage('Deploy') { + + steps { + script{ + echo "5. Deploy Stage" + // if(params.environment=='test') + // { + // input "确认要部署线上环境吗?" + // } + if(params.projectqh=='backend') + { + + sh "sed -i 's//${build_tag}/' k8s_pztjapi.yaml" + sh "sed -i 's//${env.BRANCH_NAME}/' k8s_pztjapi.yaml" + sh "sed -i 's//${params.environment}/' k8s_pztjapi.yaml" + sh "kubectl apply -f k8s_pztjapi.yaml --record" + } + else if(params.projectqh=='frontend') + { + sh "sed -i 's//${build_tag}/' k8s_pztjweb.yaml" + sh "sed -i 's//${env.BRANCH_NAME}/' k8s_pztjweb.yaml" + sh "sed -i 's//${params.environment}/' k8s_pztjweb.yaml" + sh "kubectl apply -f k8s_pztjweb.yaml --record" + } + + } + } + } + } +} diff --git a/NuGet.config b/NuGet.config new file mode 100644 index 0000000..b149801 --- /dev/null +++ b/NuGet.config @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/backend/.dockerignore b/backend/.dockerignore new file mode 100644 index 0000000..3729ff0 --- /dev/null +++ b/backend/.dockerignore @@ -0,0 +1,25 @@ +**/.classpath +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/azds.yaml +**/bin +**/charts +**/docker-compose* +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/obj +**/secrets.dev.yaml +**/values.dev.yaml +LICENSE +README.md \ No newline at end of file diff --git a/backend/BPA.MES.Base.Application/BPA.MES.Base.Application.csproj b/backend/BPA.MES.Base.Application/BPA.MES.Base.Application.csproj new file mode 100644 index 0000000..ee853ef --- /dev/null +++ b/backend/BPA.MES.Base.Application/BPA.MES.Base.Application.csproj @@ -0,0 +1,40 @@ + + + + + net6.0 + 1701;1702;1591 + BPA.MES.Base.Application.xml + enable + + + + + + + + + + + PreserveNewest + + + + + + + + + + + + + + + + + + + + + diff --git a/backend/BPA.MES.Base.Application/BPA.MES.Base.Application.xml b/backend/BPA.MES.Base.Application/BPA.MES.Base.Application.xml new file mode 100644 index 0000000..27a7288 --- /dev/null +++ b/backend/BPA.MES.Base.Application/BPA.MES.Base.Application.xml @@ -0,0 +1,9376 @@ + + + + BPA.MES.Base.Application + + + + + 名 称 : + 创 建 人 :yangxiao + 创建时间 : 2023/3/4 10:15:54 + 描 述 : + + + + + 用户Id + + + + + 账号 + + + + + 名称 + + + + + 头像 + + + + + 电话 + + + + + 性别 + + + + + 是否授权 + + + + + 角色Id + + + + + 微信session_key + + + + + 是否超级管理 + + + + + 租户Id + + + + + 用户组织机构Id + + + + + 用户组织机构名称 + + + + + 是否是管理员 + + + + + 所有缓存关键字集合 + + + + + 地址 + + + + + 密码 + + + + + 账号 + + + + + 名 称 :产线设备类型 + 创 建 人 :yangxiao + 创建时间 : 2023/7/24 16:56:13 + 描 述 : + + + + + 锅 + + + + + 釜 + + + + + 配料状态 + + + + + 工艺状态 + + + + + 未开始 + + + + + 进行中 + + + + + 完成 + + + + + 名 称 :工单枚举 + 创 建 人 :yangxiao + 创建时间 :2023/7/21 15:04:24 + 描 述 : + + + + + 未知 + + + + + 草稿 + + + + + 已下发 + + + + + 已接受 + + + + + 已启动 + + + + + 已完成 + + + + + 废弃 + + + + + 名 称 : + 创 建 人 :yangxiao + 创建时间 : 2023/7/27 9:35:27 + 描 述 : + + + + + 自定义编码 + + + + + 线路名称 + + + + + 开始点位 + + + + + 结束点位 + + + + + 描述 + + + + + 名 称 : + 创 建 人 :yangxiao + 创建时间 : 2023/7/27 9:36:07 + 描 述 : + + + + + 点位名称 + + + + + 点位编码 + + + + + 名 称 :胖子天骄桶管理 + 创 建 人 :yangxiao + 创建时间 : 2023/7/14 11:33:10 + 描 述 : + + + + + 桶名称 + + + + + 桶编号 + + + + + 名 称 :桶原料记录 + 创 建 人 :yangxiao + 创建时间 : 2023/7/14 11:47:33 + 描 述 : + + + + + 桶Id + + + + + 物料Id + + + + + 添加时间 + + + + + 重量 + + + + + 工单Id + + + + + 名 称 :胖子天骄工艺基础信息 + 创 建 人 :yangxiao + 创建时间 : 2023/7/14 14:43:37 + 描 述 : + + + + + 工艺名称 + + + + + 设备产品Id + + + + + 工艺描述 + + + + + 名 称 :工艺路线 + 创 建 人 :yangxiao + 创建时间 : 2023/7/17 17:01:26 + 描 述 : + + + + + 工艺Id + + + + + 步骤 + + + + + 功能描述 + + + + + 设备产品功能Id + + + + + 功能参数 + + + + + 名 称 :胖子天骄设备基础表 + 创 建 人 :yangxiao + 创建时间 : 2023/7/14 11:26:34 + 描 述 : + + + + + 名称 + + + + + 编码 + + + + + 设备类型 + + + + + 设备描述 + + + + + 设备维保时间 + + + + + 设备创建时间 + + + + + 名 称 :胖子天骄成品基础信息管理 + 创 建 人 :yangxiao + 创建时间 : 2023/7/14 14:07:56 + 描 述 : + + + + + 成品编号 + + + + + 成品名称 + + + + + 配方Id + + + + + 工艺Id + + + + + 添加时间 + + + + + 名 称 :产线设备 + 创 建 人 :yangxiao + 创建时间 : 2023/7/20 16:45:05 + 描 述 : + + + + + 产线Id + + + + + 产线设备 + + + + + 名 称 :产线料仓 + 创 建 人 :yangxiao + 创建时间 :2023/7/20 16:45:40 + 描 述 : + + + + + 产线Id + + + + + 产线料仓 + + + + + 名 称 :胖子天骄原料管理 + 创 建 人 :yangxiao + 创建时间 : 2023/7/14 11:32:06 + 描 述 : + + + + + 原料名称 + + + + + 原料编号 + + + + + 原料单位 + + + + + 原料分组 + + + + + 每升重量 + + + + + 名 称 :胖子天骄料仓管理 + 创 建 人 :yangxiao + 创建时间 : 2023/7/14 11:31:34 + 描 述 : + + + + + 料仓编码 + + + + + 料仓名称 + + + + + 物料Id + + + + + 料仓容积 + + + + + 名 称 :工单基础信息 + 创 建 人 :yangxiao + 创建时间 : 2023/7/18 17:54:43 + 描 述 : + + + + + 工单名称 + + + + + 产线Id + + + + + 成品Id + + + + + 指定设备Id + + + + + 产量 + + + + + 批次号 + + + + + 工单当前状态 + + + + + 创建时间 + + + + + 名 称 :工单拆分 + 创 建 人 :yangxiao + 创建时间 : 2023/7/18 18:12:55 + 描 述 : + + + + + 工单名称 + + + + + 产量 + + + + + 名 称 :工单状态 + 创 建 人 :yangxiao + 创建时间 :2023/7/18 18:07:21 + 描 述 : + + + + + 工单Id + + + + + 工单状态 + + + + + 创建时间 + + + + + 备注 + + + + + 名 称 : + 创 建 人 :yangxiao + 创建时间 : 2023/8/9 18:22:42 + 描 述 : + + + + + 批次名词 + + + + + 创建时间 + + + + + 状态 + + + + + 名 称 : + 创 建 人 :yangxiao + 创建时间 : 2023/8/10 10:03:15 + 描 述 : + + + + + 工单Id + + + + + 工艺Id + + + + + 工艺名称 + + + + + 工艺步骤Id + + + + + 步骤 + + + + + 工艺步骤名称 + + + + + 工艺参数 + + + + + 设备类型功能Id + + + + + 设备类型功能名称 + + + + + 执行状态 + + + + + 更新时间 + + + + + 第几锅 + + + + + 名 称 : + 创 建 人 :yangxiao + 创建时间 : 2023/8/9 18:22:42 + 描 述 : + + + + + 物料名称 + + + + + 物料id + + + + + 工单id + + + + + 重量 + + + + + 第几锅 + + + + + 配方Id + + + + + 配方名称 + + + + + 物料状态 + + + + + 更新时间 + + + + + 误差 + + + + + 名 称 :设备产品 + 创 建 人 :yangxiao + 创建时间 : 2023/8/1 16:34:53 + 描 述 : + + + + + 设备产品名称 + + + + + 设备产品编码 + + + + + 设备产品描述 + + + + + 名 称 :设备功能 + 创 建 人 :yangxiao + 创建时间 : 2023/8/2 16:03:10 + 描 述 : + + + + + 设备产品Id + + + + + 功能名称 + + + + + 功能编码 + + + + + 描述 + + + + + 方法参数 + + + + + 名 称 :设备属性 + 创 建 人 :yangxiao + 创建时间 : 2023/7/31 15:06:00 + 描 述 : + + + + + 设备产品Id + + + + + 名称 + + + + + 编码 + + + + + 描述 + + + + + 名 称 :设备配方表 + 创 建 人 :yangxiao + 创建时间 :2023/3/2 13:57:00 + 描 述 : + + + + + 设备Id + + + + + 配方Id + + + + + 名 称 :码表数据 + 创 建 人 :yangxiao + 创建时间 : 2023/8/9 9:47:53 + 描 述 : + + + + + 类型id + + + + + 值 + + + + + 编码 + + + + + 排序 + + + + + 添加时间 + + + + + 名 称 :数据码表 + 创 建 人 :yangxiao + 创建时间 : 2023/8/9 9:48:05 + 描 述 : + + + + + 名称 + + + + + 编码 + + + + + 排序 + + + + + 名 称 :分组信息 + 创 建 人 :yangxiao + 创建时间 : 2023/3/10 14:01:15 + 描 述 : + + + + + 名称 + + + + + 介绍 + + + + + 名 称 : + 创 建 人 :yangxiao + 创建时间 : 2023/7/24 17:28:56 + 描 述 : + + + + + 地址 + + + + + 密码 + + + + + 账号 + + + + + 消息发布路由 4.0和5.0不一样 + + + + + 名 称 :操作日志 + 创 建 人 :yangxiao + 创建时间 :2023/7/20 15:10:59 + 描 述 : + + + + + 操作标题 + + + + + 内容 + + + + + 返回值 + + + + + 创建时间 + + + + + 名 称 :订单服务 + 创 建 人 :yangxiao + 创建时间 : 2023/7/18 18:11:48 + 描 述 : + + + + + 名 称 :产线管理 + 创 建 人 :yangxiao + 创建时间 : 2023/7/18 10:42:35 + 描 述 : + + + + + 产线名称 + + + + + 产线编码 + + + + + 产线描述 + + + + + 名 称 :配方物料信息 + 创 建 人 :yangxiao + 创建时间 : 2023/3/2 13:58:19 + 描 述 : + + + + + 物料Id + + + + + 配方Id + + + + + 重量 + + + + + 描述 + + + + + 误差 + + + + + 名 称 :配方分组 + 创 建 人 :yangxiao + 创建时间 : 2023/3/10 14:56:03 + 描 述 : + + + + + 组Id + + + + + 产品Id + + + + + 名 称 :配方信息 + 创 建 人 :yangxiao + 创建时间 : 2023/3/2 13:57:15 + 描 述 : + + + + + 名称 + + + + + 自定义编码 + + + + + 名 称 :店铺信息 + 创 建 人 :yangxiao + 创建时间 : 2023/3/2 13:52:13 + 描 述 : + + + + + 名称 + + + + + 地址 + + + + + 联系电话 + + + + + 负责人 + + + + + 当前值 + + + + + 报警信息 + + + + + 大屏报警限制 + + + + + 限制名称 + + + + + 最小限制值 + + + + + 最大限制值 + + + + + 名 称 :报警日志 + 创 建 人 :yangxiao + 创建时间 : 2023/8/21 10:17:57 + 描 述 : + + + + + 报警信息 + + + + + 报警值 + + + + + 报警等级 + + + + + 设备名称 + + + + + 日期 + + + + + 时间 + + + + + 创建时间 + + + + + 类型 + + + + + 名 称 :程序日志 + 创 建 人 :yangxiao + 创建时间 : 2023/8/21 10:18:13 + 描 述 : + + + + + 日志类型 + + + + + 日志消息 + + + + + 日期 + + + + + 时间 + + + + + 日志消息 + + + + + 名 称 :运行日志 + 创 建 人 :yangxiao + 创建时间 : 2023/8/21 10:18:34 + 描 述 : + + + + + 日志类别 + + + + + 日志消息 + + + + + 日期 + + + + + 时间 + + + + + 日志消息 + + + + + 更新时间 + + + + + 名 称 :用户日志 + 创 建 人 :yangxiao + 创建时间 : 2023/8/21 10:18:50 + 描 述 : + + + + + 权限 + + + + + 用户名 + + + + + 日志消息 + + + + + 日志时间 + + + + + 状态 + + + + + 订单ID + + + + + 成品Id + + + + + 数量 + + + + + 订单关联工单 + + + + + 名 称 :账户信息 + 创 建 人 :yangxiao + 创建时间 : 2023/1/3 10:18:43 + 描 述 : + + + + + 账号 + + + + + 密码 + + + + + 员工表Id + + + + + 名 称 :员工信息 + 创 建 人 :yangxiao + 创建时间 : 2023/1/4 17:44:31 + 描 述 : + + + + + 员工姓名 + + + + + 1男2女 + + + + + 1启用 2禁用 + + + + + 超管 + + + + + 角色Id + + + + + 名 称 :模块菜单表 + 创 建 人 :yangxiao + 创建时间 : 2023/1/4 17:32:15 + 描 述 : + + + + + 类别 1:菜单,2:视图,3:功能 + + + + + 菜单打开方式 0:框架内嵌,1:新开页面 + + + + + 父级编号 + + + + + 名称 + + + + + 图标 + + + + + 地址 + + + + + 状态 + + + + + 名 称 :角色信息 + 创 建 人 :yangxiao + 创建时间 : 2023/1/4 17:32:32 + 描 述 : + + + + + 角色名称 + + + + + 角色类型 1超级管理员,2其他 + + + + + 角色描述 + + + + + 是否删除 + + + + + 名 称 :角色权限表 + 创 建 人 :yangxiao + 创建时间 : 2023/8/31 15:56:02 + 描 述 : + + + + + 角色Id + + + + + 模块Id + + + + + 父级模块 + + + + + 执行操作前后 + + + + + + + + 名 称 :接口AOP + 创 建 人 :yangxiao + 创建时间 : 2023/7/20 15:04:06 + 描 述 : + + + + + 执行操作前后 + + + + + + + + 名 称 :MQTT消息基类 + 创 建 人 :yangxiao + 创建时间 : 2023/7/21 10:24:24 + 描 述 : + + + + + 消息ID + + + + + 消息版本 + + + + + 名 称 :MQTT通信库 + 创 建 人 :yangxiao + 创建时间 : 2022/11/18 15:38:40 + 描 述 : + + + + + Mqtt通用服务 + + + + + code + + + + + reason_code + + + + + + + + + + 消息内容 + + + + + 消息长度 + + + + + 名 称 : + 创 建 人 :yangxiao + 创建时间 : 2022/11/18 15:37:07 + 描 述 : + + + + + 设备控制主题,前端通过消息控制设备动作(客户端/前端 --> 设备) + + + + + 工单推送主题,中控将创建的工单推送到对应的产线 (中控系统 --> 产线) + + + + + 前端展示数据推送,数据服务将设备数据推送到前端界面展示 (数据中心服务 --> 客户端/前端) + + + + + 工单状态(信息系统 --> 中控系统) + + + + + 任务下发成功 回调 + + + + + 上下料回调 + + + + + 名 称 : + 创 建 人 :yangxiao + 创建时间 : 2023/8/7 9:59:47 + 描 述 : + + + + + 自定义编码 + + + + + 线路名称 + + + + + 开始点位 + + + + + 结束点位 + + + + + 描述 + + + + + 增加 + + + + + 修改 + + + + + 主键 + + + + + 刪除 + + + + + 主键 + + + + + 普通查询条件 + + + + + 主键 + + + + + 分页查询条件 + + + + + 名称 + + + + + 编码 + + + + + 输出 + + + + + 主键 + + + + + 名 称 : + 创 建 人 :yangxiao + 创建时间 : 2023/8/7 10:00:01 + 描 述 : + + + + + 点位名称 + + + + + 点位编码 + + + + + 增加 + + + + + 修改 + + + + + 主键 + + + + + 刪除 + + + + + 主键 + + + + + 普通查询条件 + + + + + 主键 + + + + + 分页查询条件 + + + + + 名称 + + + + + 编码 + + + + + 输出 + + + + + 主键 + + + + + 任务完成回报Dto + + + + + 上游系统任务号,全局唯一 + + + + + 仓库编号 + + + + + 任务快仓系统编号 + + + + + 任务状态 + + + + + 内部任务类型 + + + + + 数据字段 + + + + + 上下料交互请求DTO + + + + + AGV编号 + + + + + 容器编号,如果一次上/下多个容器,则多个容器用英文逗号分隔 + + + + + 上游设备ID + + + + + 上游设备ID,多个用英文逗号分隔 + + + + + 快仓任务编号 + + + + + 消息ID + + + + + 交互阶段LOAD:上料阶段 UNLOAD:下料阶段 + + + + + 上游任务号 + + + + + 货到货 + + + + + AGV编号 + + + + + 容器编号 + + + + + 上料点位 + + + + + 上料货位编号 + + + + + 下料点位 + + + + + 下料货位编号 + + + + + 是否需要上料交互 + + + + + 点到点 + + + + + AGV编号 + + + + + 容器编号 + + + + + 上料点位 + + + + + 下料点位 + + + + + 是否需要上料交互 + + + + + 顶升完成 + + + + + 开始移动 + + + + + 放下完成 + + + + + 任务完成 + + + + + 任务取消 + + + + + 任务异常取消 + + + + + 任务异常完成 + + + + + 1) 辊筒货位到货位搬运 + + + + + 是否成功 + + + + + 状态码 + + + + + 消息 + + + + + 返回数据数组 + + + + + 状态码 + + + + + 消息体 + + + + + 任务编号 + + + + + AGV请求 + + + + + 快仓api地址 + + + + + 任务编码 + + + + + 仓库编码 默认值1 + + + + + 优先级 0-99 越高越先执行 + + + + + 任务下发起止点信息 + + + + + 用户自定义信息编号 + + + + + 起点点位 + + + + + 终点点位 + + + + + 上料方式 自动/人工 + + + + + 上料交互方式 //接口对接 false + + + + + 下料方式 true自动/false人工 + + + + + 接口对接 false + + + + + 起点设备ID + + + + + 目标设备ID + + + + + 名 称 :AGV线路管理 + 创 建 人 :yangxiao + 创建时间 : 2023/8/7 10:03:21 + 描 述 : + + + + + 增加 + + + + + + + 删除 + + + + + + + + 详情 + + + + + + + + 列表 + + + + + + + 分页 + + + + + + + 下拉 + + + + + + + 更新 + + + + + + + + 名 称 :AGV点位管理 + 创 建 人 :yangxiao + 创建时间 : 2023/8/7 10:03:37 + 描 述 : + + + + + 增加 + + + + + + + 删除 + + + + + + + + 详情 + + + + + + + + 列表 + + + + + + + 分页 + + + + + + + 下拉 + + + + + + + 更新 + + + + + + + + AGV第三方api + + + + + 下发任务 + + + + + + + 取消任务 + + + + + + + 上下料反馈给AGV接口 + + + + + + + 任务反馈(暴露给AGV厂商) + + + + + + + AGV上下料交互请求 (暴露给AGV厂商) + + + + + + + 名 称 : + 创 建 人 :yangxiao + 创建时间 : 2023/8/7 10:02:54 + 描 述 : + + + + + 增加 + + + + + + 移除 + + + + + + 更新 + + + + + + 不分页列表 + + + + + + 分页列表 + + + + + + 查询单条 + + + + + + + 名 称 :AVG点位 + 创 建 人 :yangxiao + 创建时间 : 2023/8/7 10:03:06 + 描 述 : + + + + + 增加 + + + + + + 移除 + + + + + + 更新 + + + + + + 不分页列表 + + + + + + 分页列表 + + + + + + 查询单条 + + + + + + + 下发任务 + + + + + + + 取消任务 + + + + + + + 任务回调 + + + + + + + AGV上下料交互请求 + + + + + + + 上下料反馈给AGV接口 + + + + + + + 名 称 : + 创 建 人 :yangxiao + 创建时间 : 2023/7/17 16:13:10 + 描 述 : + + + + + 初始化数据库 + + + + + + 测试 + + + + + 名 称 : + 创 建 人 :yangxiao + 创建时间 : 2023/7/17 15:43:00 + 描 述 : + + + + + 桶名称 + + + + + 桶编号 + + + + + 增加 + + + + + 更新 + + + + + 主键 + + + + + 删除 + + + + + 主键 + + + + + 分页 + + + + + 名称 + + + + + 编码 + + + + + 输出 + + + + + 主键 + + + + + 当前原料名称 + + + + + 名 称 : + 创 建 人 :yangxiao + 创建时间 : 2023/7/17 17:29:52 + 描 述 : + + + + + 桶Id + + + + + 物料Id + + + + + 添加时间 + + + + + 物料重量 + + + + + 工单Id + + + + + 更新 + + + + + 主键 + + + + + 删除 + + + + + 主键 + + + + + 不分页 + + + + + 工单Id + + + + + 桶Id + + + + + 桶编号 + + + + + 分页 + + + + + 名称 + + + + + 编码 + + + + + 桶Id + + + + + 清空桶 + + + + + 输出 + + + + + 主键 + + + + + 原料名称 + + + + + 桶名称 + + + + + 工单名称 + + + + + 桶编码 + + + + + 计划重量 + + + + + 第几锅 + + + + + 名 称 :桶服务 + 创 建 人 :yangxiao + 创建时间 :2023/3/2 16:11:04 + 描 述 :基础数据管理 + + + + + 增加 + + + + + + + 新增并返回 + + + + + + + 删除 + + + + + + + + 详情 + + + + + + + + 列表 + + + + + + + 分页 + + + + + + + 下拉 + + + + + + + 更新 + + + + + + + + 名 称 :桶记录 + 创 建 人 :yangxiao + 创建时间 :2023/3/2 16:11:04 + 描 述 :基础数据管理 + + + + + 增加 + + + + + + + 删除 + + + + + + + + 详情 + + + + + + + + 列表 + + + + + + + 分页 + + + + + + + 更新 + + + + + + + + 清空桶 + + + + + + + 名 称 : + 创 建 人 :yangxiao + 创建时间 : 2023/7/17 15:43:10 + 描 述 : + + + + + 增加 + + + + + + 增加并返回数据 + + + + + + 移除 + + + + + + 更新 + + + + + + 不分页列表 + + + + + + 分页列表 + + + + + + 下拉列表 + + + + + + 查询单条 + + + + + + + 名 称 :桶记录 + 创 建 人 :yangxiao + 创建时间 : 2023/7/17 17:37:03 + 描 述 : + + + + + 增加 + + + + + + 移除 + + + + + + 更新 + + + + + + 不分页列表 + + + + + + 分页列表 + + + + + + 查询单条 + + + + + + + 清空桶 + + + + + + + 名 称 :产品分组 + 创 建 人 :yangxiao + 创建时间 : 2023/3/10 13:59:43 + 描 述 : + + + + + 工艺名称 + + + + + 设备类型 0:炒锅 1:反应釜 + + + + + 工艺描述 + + + + + 增加 + + + + + 更新 + + + + + 主键 + + + + + 删除 + + + + + 主键 + + + + + 分页 + + + + + 名称 + + + + + 设备类型 0:炒锅 1:反应釜 + + + + + 不分页 + + + + + 输出 + + + + + 主键 + + + + + + 名 称 :产线管理 + 创 建 人 :yangxiao + 创建时间 : 2023/7/18 14:03:27 + 描 述 : + + + + + 工艺Id + + + + + 步骤 + + + + + 功能描述 + + + + + 设备产品功能Id + + + + + 功能参数 + + + + + 增加 + + + + + 更新 + + + + + 主键 + + + + + 删除 + + + + + 主键 + + + + + 分页 + + + + + 名称 + + + + + 编码 + + + + + 工艺Id + + + + + 输出 + + + + + 主键 + + + + + 工艺名称 + + + + + 设备产品功能名称 + + + + + 设备产品Id + + + + + 名 称 :工艺信息 + 创 建 人 :yangxiao + 创建时间 :2023/3/10 14:03:06 + 描 述 :配方工艺管理 + + + + + 增加 + + + + + + + 删除 + + + + + + + + 详情 + + + + + + + + 列表 + + + + + + + 分页 + + + + + + + 下拉 + + + + + + 更新 + + + + + + + + 名 称 :工艺路线服务 + 创 建 人 :yangxiao + 创建时间 :2023/3/2 16:11:04 + 描 述 :CraftsInfo 工艺管理 CraftsSteps工艺步骤管理 + + + + + 增加 + + + + + + + 删除 + + + + + + + + 详情 + + + + + + + + 列表 + + + + + + + 分页 + + + + + + + 下拉 + + + + + + + 更新 + + + + + + + + 批量更新 + + + + + + + 名 称 :工艺信息 + 创 建 人 :yangxiao + 创建时间 :2023/3/10 14:03:21 + 描 述 : + + + + + 增加 + + + + + + 移除 + + + + + + 更新 + + + + + + 不分页列表 + + + + + + 分页列表 + + + + + + 下拉列表 + + + + + + 查询单条 + + + + + + + 名 称 :产线管理 + 创 建 人 :yangxiao + 创建时间 :2023/7/18 14:05:16 + 描 述 : + + + + + 增加 + + + + + + 移除 + + + + + + 更新 + + + + + + 批量更新 + + + + + + + 不分页列表 + + + + + + 分页列表 + + + + + + 下拉列表 + + + + + + 查询单条 + + + + + + + 名 称 :设备产品信息 + 创 建 人 :yangxiao + 创建时间 : 2023/8/2 16:19:15 + 描 述 : + + + + + 设备产品名称 + + + + + 设备产品编码 + + + + + 设备产品描述 + + + + + 增加 + + + + + 修改 + + + + + 主键 + + + + + 刪除 + + + + + 主键 + + + + + 普通查询条件 + + + + + 主键 + + + + + 分页查询条件 + + + + + 名称 + + + + + 编码 + + + + + 输出 + + + + + 主键 + + + + + 名 称 :设备产品模型功能 + 创 建 人 :yangxiao + 创建时间 : 2023/7/31 18:04:53 + 描 述 : + + + + + 设备产品Id + + + + + 功能名称 + + + + + 功能编码 + + + + + 描述 + + + + + 方法参数 + + + + + 增加 + + + + + 修改 + + + + + 主键 + + + + + 刪除 + + + + + 主键 + + + + + 普通查询条件 + + + + + 主键 + + + + + 设备产品Id + + + + + 设备产品名称 + + + + + 设备产品编号 + + + + + 分页查询条件 + + + + + 名称 + + + + + 编码 + + + + + 设备产品Id + + + + + 输出 + + + + + 主键 + + + + + 名 称 :设备产品参数 + 创 建 人 :yangxiao + 创建时间 : 2023/7/31 18:04:53 + 描 述 : + + + + + 设备产品Id + + + + + 名称 + + + + + 编码 + + + + + 描述 + + + + + 增加 + + + + + 修改 + + + + + 主键 + + + + + 刪除 + + + + + 主键 + + + + + 普通查询条件 + + + + + 主键 + + + + + 分页查询条件 + + + + + 名称 + + + + + 编码 + + + + + 输出 + + + + + 主键 + + + + + 名 称 :设备产品功能服务 + 创 建 人 :yangxiao + 创建时间 : 2023/7/31 18:03:25 + 描 述 : + + + + + 增加 + + + + + + + 删除 + + + + + + + + 详情 + + + + + + + + 列表 + + + + + + + 分页 + + + + + + + 下拉 + + + + + + + 更新 + + + + + + + + 名 称 :设备参数 + 创 建 人 :yangxiao + 创建时间 : 2023/7/31 18:03:25 + 描 述 : + + + + + 增加 + + + + + + + 删除 + + + + + + + + 详情 + + + + + + + + 列表 + + + + + + + 分页 + + + + + + + 下拉 + + + + + + + 更新 + + + + + + + + 名 称 :设备产品 + 创 建 人 :yangxiao + 创建时间 : 2023/7/31 18:03:25 + 描 述 : + + + + + 增加 + + + + + + + 删除 + + + + + + + + 详情 + + + + + + + + 列表 + + + + + + + 分页 + + + + + + + 下拉 + + + + + + + 更新 + + + + + + + + 名 称 :设备产品功能 + 创 建 人 :yangxiao + 创建时间 : 2023/7/31 18:02:57 + 描 述 : + + + + + 增加 + + + + + + 删除 + + + + + + 更新 + + + + + + 不分页列表 + + + + + + 分页列表 + + + + + + 下拉列表 + + + + + + 查询单条 + + + + + + + 名 称 :设备产品参数 + 创 建 人 :yangxiao + 创建时间 : 2023/7/31 18:02:57 + 描 述 : + + + + + 增加 + + + + + + 删除 + + + + + + 更新 + + + + + + 不分页列表 + + + + + + 分页列表 + + + + + + 下拉列表 + + + + + + 查询单条 + + + + + + + 名 称 :设备产品基础信息 + 创 建 人 :yangxiao + 创建时间 : 2023/8/2 16:19:35 + 描 述 : + + + + + 增加 + + + + + + 删除 + + + + + + 更新 + + + + + + 不分页列表 + + + + + + 分页列表 + + + + + + 下拉列表 + + + + + + 查询单条 + + + + + + + 名 称 :设备Dto类 + 创 建 人 :yangxiao + 创建时间 : 2023/3/2 16:12:06 + 描 述 : + + + + + 增加 + + + + + 更新 + + + + + 删除 + + + + + 主键 + + + + + 不分页 + + + + + 设备Id + + + + + 分页 + + + + + 设备Id + + + + + 配方数组 + + + + + 输出 + + + + + 设备名称 + + + + + 配方名称 + + + + + 配方代码 + + + + + 分组Id + + + + + 分组名称 + + + + + 配方图片地址 + + + + + 名 称 :设备Dto类 + 创 建 人 :yangxiao + 创建时间 : 2023/3/2 16:12:06 + 描 述 : + + + + + 名称 + + 设备名称 + + + + 编码 + + + + + 设备类型 + + + + + 设备描述 + + 设备描述 + + + + 设备维保时间 + + 2023-7-17 + + + + 增加 + + + + + 更新 + + + + + 主键 + + + + + 删除 + + + + + 主键 + + + + + 分页 + + + + + 名称 + + + + + 编码 + + + + + 输出 + + + + + 主键 + + + + + 名 称 :设备服务 + 创 建 人 :yangxiao + 创建时间 :2023/3/2 16:11:04 + 描 述 :基础信息管理 + + + + + 增加 + + + + + + + 批量下发配方 + + + + + + + + 删除 + + + + + + + + 详情 + + + + + + + + 列表 + + + + + + + 分页 + + + + + + + 更新 + + + + + + + + 名 称 :设备服务 + 创 建 人 :yangxiao + 创建时间 :2023/3/2 16:11:04 + 描 述 :基础数据管理 + + + + + 增加 + + + + + + + 删除 + + + + + + + + 详情 + + + + + + + + 列表 + + + + + + + 分页 + + + + + + + 下拉 + + + + + + + 更新 + + + + + + + + 名 称 :设备配方服务 + 创 建 人 :yangxiao + 创建时间 :2023/3/2 18:30:58 + 描 述 : + + + + + 增加 + + + + + + 移除 + + + + + + 更新 + + + + + + 不分页列表 + + + + + + 分页列表 + + + + + + 查询单条 + + + + + + + 批量下发配方 + + + + + + + 名 称 :设备服务 + 创 建 人 :yangxiao + 创建时间 :2023/3/2 18:30:58 + 描 述 : + + + + + 增加 + + + + + + 移除 + + + + + + 更新 + + + + + + 不分页列表 + + + + + + 分页列表 + + + + + + 下拉列表 + + + + + + 查询单条 + + + + + + + 名 称 :码表数据 + 创 建 人 :yangxiao + 创建时间 : 2023/8/9 9:56:11 + 描 述 : + + + + + 类型id + + + + + 值 + + + + + 编码 + + + + + 排序 + + + + + 增加 + + + + + 修改 + + + + + 主键 + + + + + 刪除 + + + + + 主键 + + + + + 普通查询条件 + + + + + 码表类型Id + + + + + 码表类型编码 + + + + + 主键 + + + + + 分页查询条件 + + + + + 名称 + + + + + 编码 + + + + + 码表类型Id + + + + + 输出 + + + + + 主键 + + + + + 名 称 :码表类型 + 创 建 人 :yangxiao + 创建时间 : 2023/8/9 9:56:00 + 描 述 : + + + + + 名称 + + + + + 编码 + + + + + 排序 + + + + + 增加 + + + + + 修改 + + + + + 主键 + + + + + 刪除 + + + + + 主键 + + + + + 普通查询条件 + + + + + 主键 + + + + + 分页查询条件 + + + + + 名称 + + + + + 编码 + + + + + 输出 + + + + + 主键 + + + + + 名 称 :码表管理 + 创 建 人 :yangxiao + 创建时间 : 2023/8/9 10:01:19 + 描 述 : + + + + + 增加 + + + + + + + 删除 + + + + + + + + 详情 + + + + + + + + 列表 + + + + + + + 分页 + + + + + + + 下拉 + + + + + + + 更新 + + + + + + + + 名 称 :码表类型管理 + 创 建 人 :yangxiao + 创建时间 : 2023/8/9 10:01:35 + 描 述 : + + + + + 增加 + + + + + + + 删除 + + + + + + + + 详情 + + + + + + + + 列表 + + + + + + + 分页 + + + + + + + 下拉 + + + + + + + 更新 + + + + + + + + 名 称 :码表数据 + 创 建 人 :yangxiao + 创建时间 : 2023/8/9 10:00:06 + 描 述 : + + + + + 增加 + + + + + + 移除 + + + + + + 更新 + + + + + + 不分页列表 + + + + + + 分页列表 + + + + + + 查询单条 + + + + + + + 名 称 : + 创 建 人 :yangxiao + 创建时间 : 2023/8/9 10:00:23 + 描 述 : + + + + + 增加 + + + + + + 移除 + + + + + + 更新 + + + + + + 不分页列表 + + + + + + 分页列表 + + + + + + 查询单条 + + + + + + + 名 称 :成品管理 + 创 建 人 :yangxiao + 创建时间 : 2023/7/17 15:59:39 + 描 述 : + + + + + 成品编号 + + + + + 成品名称 + + + + + 配方Id + + + + + 工艺Id + + + + + 增加 + + + + + 更新 + + + + + 主键 + + + + + 删除 + + + + + 主键 + + + + + 分页 + + + + + 名称 + + + + + 编码 + + + + + 输出 + + + + + 主键 + + + + + 配方名称 + + + + + 工艺名称 + + + + + 名 称 :成品管理服务 + 创 建 人 :yangxiao + 创建时间 :2023/3/2 16:11:04 + 描 述 :基础数据管理 + + + + + 增加 + + + + + + + 删除 + + + + + + + + 详情 + + + + + + + + 列表 + + + + + + + 分页 + + + + + + + 下拉 + + + + + + + 更新 + + + + + + + + 名 称 :成品信息管理 + 创 建 人 :yangxiao + 创建时间 : 2023/7/17 16:02:25 + 描 述 : + + + + + 增加 + + + + + + 移除 + + + + + + 更新 + + + + + + 不分页列表 + + + + + + 分页列表 + + + + + + 下拉列表 + + + + + + 查询单条 + + + + + + + 名 称 : + 创 建 人 :yangxiao + 创建时间 : 2023/8/21 10:59:30 + 描 述 : + + + + + 增加 + + + + + + 移除 + + + + + + 更新 + + + + + + 不分页列表 + + + + + + 分页列表 + + + + + + 查询单条 + + + + + + + 添加报警限制 + + + + + + + 修改报警限制 + + + + + + + 获取报警限制 + + + + + + 删除报警限制 + + + + + + 名 称 : + 创 建 人 :yangxiao + 创建时间 :2023/8/21 10:20:37 + 描 述 : + + + + + 报警信息 + + + + + 报警值 + + + + + 报警等级 + + + + + 类型 + + + + + 设备名称 + + + + + 日期 + + + + + 时间 + + + + + 日志消息 + + + + + 增加 + + + + + 更新 + + + + + 主键 + + + + + 删除 + + + + + 主键 + + + + + 不分页 + + + + + 分页 + + + + + 报警信息 + + + + + 报警值 + + + + + 报警等级 + + + + + 设备名称 + + + + + 开始时间 + + + + + 结束时间 + + + + + 输出 + + + + + 主键 + + + + + 名 称 : + 创 建 人 :yangxiao + 创建时间 : 2023/8/21 10:20:55 + 描 述 : + + + + + 日志类型 + + + + + 日志消息 + + + + + 日期 + + + + + 时间 + + + + + 日志消息 + + + + + 增加 + + + + + 更新 + + + + + 主键 + + + + + 删除 + + + + + 主键 + + + + + 不分页 + + + + + 分页 + + + + + 日志类型 + + + + + 日志消息 + + + + + 开始时间 + + + + + 结束时间 + + + + + 输出 + + + + + 主键 + + + + + 名 称 : + 创 建 人 :yangxiao + 创建时间 : 2023/8/21 10:21:11 + 描 述 : + + + + + 日志类别 + + + + + 日志消息 + + + + + 日期 + + + + + 时间 + + + + + 日志消息 + + + + + 增加 + + + + + 更新 + + + + + 主键 + + + + + 删除 + + + + + 主键 + + + + + 不分页 + + + + + 分页 + + + + + 日志类别 + + + + + 日志消息 + + + + + 开始时间 + + + + + 结束时间 + + + + + 输出 + + + + + 主键 + + + + + 名 称 :用户权限 + 创 建 人 :yangxiao + 创建时间 : 2023/8/21 10:21:40 + 描 述 : + + + + + 权限 + + + + + 用户名 + + + + + 日志消息 + + + + + 日志时间 + + + + + 增加 + + + + + 更新 + + + + + 主键 + + + + + 删除 + + + + + 主键 + + + + + 不分页 + + + + + 分页 + + + + + 用户名 + + + + + 日志消息 + + + + + 输出 + + + + + 主键 + + + + + 名 称 :报警日志 + 创 建 人 :yangxiao + 创建时间 :2023/8/21 11:02:36 + 描 述 : + + + + + 增加 + + + + + + + 删除 + + + + + + + + 详情 + + + + + + + + 列表 + + + + + + + 分页 + + + + + + + 更新 + + + + + + + + 名 称 : + 创 建 人 :yangxiao + 创建时间 : 2023/8/21 10:30:26 + 描 述 : + + + + + 增加 + + + + + + 移除 + + + + + + 更新 + + + + + + 不分页列表 + + + + + + 分页列表 + + + + + + 查询单条 + + + + + + + 名 称 : + 创 建 人 :yangxiao + 创建时间 : 2023/8/21 10:30:39 + 描 述 : + + + + + 增加 + + + + + + 移除 + + + + + + 更新 + + + + + + 不分页列表 + + + + + + 分页列表 + + + + + + 查询单条 + + + + + + + 名 称 : + 创 建 人 :yangxiao + 创建时间 : 2023/8/21 10:30:53 + 描 述 : + + + + + 增加 + + + + + + 移除 + + + + + + 更新 + + + + + + 不分页列表 + + + + + + 分页列表 + + + + + + 查询单条 + + + + + + + 名 称 : + 创 建 人 :yangxiao + 创建时间 : 2023/8/21 10:31:05 + 描 述 : + + + + + 增加 + + + + + + 移除 + + + + + + 更新 + + + + + + 不分页列表 + + + + + + 分页列表 + + + + + + 查询单条 + + + + + + + 名 称 :系统日志 + 创 建 人 :yangxiao + 创建时间 :2023/8/21 11:16:20 + 描 述 : + + + + + 增加 + + + + + + + 删除 + + + + + + + + 详情 + + + + + + + + 列表 + + + + + + + 分页 + + + + + + + 更新 + + + + + + + + 名 称 :运行日志 + 创 建 人 :yangxiao + 创建时间 :2023/8/21 11:16:32 + 描 述 : + + + + + 增加 + + + + + + + 删除 + + + + + + + + 详情 + + + + + + + + 列表 + + + + + + + 分页 + + + + + + + 更新 + + + + + + + + 名 称 :用户操作日志 + 创 建 人 :yangxiao + 创建时间 :2023/8/21 11:16:44 + 描 述 : + + + + + 增加 + + + + + + + 删除 + + + + + + + + 详情 + + + + + + + + 列表 + + + + + + + 分页 + + + + + + + 更新 + + + + + + + + 名 称 :设备Dto类 + 创 建 人 :yangxiao + 创建时间 : 2023/3/2 16:12:06 + 描 述 : + + + + + 原料名称 + + + + + + 原料编号 + + + + + + 原料单位 + + + + + + 原料分组 + + + + + + 每升重量 + + + + + 增加 + + + + + 更新 + + + + + 主键 + + + + + + 删除 + + + + + 主键 + + + + + + 分页 + + + + + 名称 + + + + + + 编码 + + + + + + 输出 + + + + + 主键 + + + + + + 类型名称 + + + + + 名 称 :物料服务 + 创 建 人 :yangxiao + 创建时间 :2023/3/2 18:31:53 + 描 述 : + + + + + 增加 + + + + + + 移除 + + + + + + 更新 + + + + + + 不分页列表 + + + + + + 分页列表 + + + + + + 下拉列表 + + + + + + 查询单条 + + + + + + + 名 称 :原料服务 + 创 建 人 :yangxiao + 创建时间 :2023年7月17日15:41:09 + 描 述 :基础数据管理 + + + + + 增加 + + + + + + + 删除 + + + + + + + + 详情 + + + + + + + + 列表 + + + + + + + 分页 + + + + + + + 下拉 + + + + + + + 更新 + + + + + + + + 名 称 : + 创 建 人 :yangxiao + 创建时间 : 2023/7/20 15:15:48 + 描 述 : + + + + + 操作标题 + + + + + 内容 + + + + + 创建时间 + + + + + 增加 + + + + + 名 称 :日志服务 + 创 建 人 :yangxiao + 创建时间 : 2023/7/20 15:17:58 + 描 述 : + + + + + 增加 + + + + + + 名 称 :操作日志 + 创 建 人 :yangxiao + 创建时间 : 2023/7/20 15:17:24 + 描 述 : + + + + + 状态 + + + + + 分配进度 + + + + + 生产进度 + + + + + 成品 + + + + + 产线 + + + + + 数量 + + + + + 成品数量限制 + + + + + 成品 + + + + + 分页列表 + + + + + + 新增 + + + + + + + 修改 + + + + + + + 获取订单的商品 + + + + + + + 添加工单 并绑定订单 + + + + + + + 获取成品剩余制作数量 + + + + + + + 分页列表 + + + + + + 新增 + + + + + + + 修改 + + + + + + + 删除 + + + + + + + 获取订单的商品 + + + + + + + 添加工单 并绑定订单 + + + + + + + 生成工单时验证成品数量 + + + + + + 获取成品剩余制作数量 + + + + + + + 名 称 :产品分组 + 创 建 人 :yangxiao + 创建时间 : 2023/3/10 13:59:43 + 描 述 : + + + + + 名称 + + + + + 介绍 + + + + + 增加 + + + + + 更新 + + + + + 主键 + + + + + 删除 + + + + + 主键 + + + + + 分页 + + + + + 名称 + + + + + 输出 + + + + + 主键 + + + + + + 名 称 :产线设备 + 创 建 人 :yangxiao + 创建时间 : 2023/7/20 17:00:32 + 描 述 : + + + + + 产线Id + + + + + 产线设备 + + + + + 产线设备不分页 + + + + + 名称 + + + + + 产线Id + + + + + 产线设备分页 + + + + + 名称 + + + + + 产线Id + + + + + 删除产线设备 + + + + + 主键 + + + + + 产线设备关联信息 + + + + + 主键 + + + + + 名称 + + 设备名称 + + + + 编码 + + + + + 设备类型 + + + + + 设备描述 + + 设备描述 + + + + 名 称 :产线管理 + 创 建 人 :yangxiao + 创建时间 : 2023/7/18 14:03:27 + 描 述 : + + + + + 产线名称 + + + + + 产线编码 + + + + + 产线描述 + + + + + 增加 + + + + + 更新 + + + + + 主键 + + + + + 删除 + + + + + 主键 + + + + + 分页 + + + + + 名称 + + + + + 编码 + + + + + 输出 + + + + + 主键 + + + + + 名 称 : + 创 建 人 :yangxiao + 创建时间 : 2023/7/20 18:25:18 + 描 述 : + + + + + 产线Id + + + + + 产线设备 + + + + + 产线设备不分页 + + + + + 名称 + + + + + 产线Id + + + + + 物料Id + + + + + 产线设备分页 + + + + + 名称 + + + + + 产线Id + + + + + 删除产线设备 + + + + + 主键 + + + + + 产线设备关联信息 + + + + + 主键 + + + + + 产线名称 + + + + + 名称 + + 设备名称 + + + + 编码 + + + + + 物料信息 + + + + + 物料名称 + + + + + 名 称 :分组信息 + 创 建 人 :yangxiao + 创建时间 :2023/3/10 14:03:06 + 描 述 : + + + + + 增加 + + + + + + + 删除 + + + + + + + + 详情 + + + + + + + + 列表 + + + + + + + 分页 + + + + + + + 下拉 + + + + + + 更新 + + + + + + + + 名 称 :分组信息 + 创 建 人 :yangxiao + 创建时间 :2023/3/10 14:03:21 + 描 述 : + + + + + 增加 + + + + + + 移除 + + + + + + 更新 + + + + + + 不分页列表 + + + + + + 下拉列表 + + + + + + 分页列表 + + + + + + 查询单条 + + + + + + + 名 称 :产线管理 + 创 建 人 :yangxiao + 创建时间 :2023/7/18 14:05:16 + 描 述 : + + + + + 增加 + + + + + + 移除 + + + + + + 更新 + + + + + + 不分页列表 + + + + + + 分页列表 + + + + + + 下拉列表 + + + + + + 查询单条 + + + + + + + 产线添加设备 + + + + + + 产线删除设备 + + + + + + 产线设备不分页 + + + + + + 产线设备分页 + + + + + + 产线添加料仓 + + + + + + 产线删除料仓 + + + + + + 产线料仓不分页 + + + + + + 产线料仓分页 + + + + + + 名 称 :产线服务 + 创 建 人 :yangxiao + 创建时间 :2023/3/2 16:11:04 + 描 述 :基础数据管理 + + + + + 增加 + + + + + + + 删除 + + + + + + + + 详情 + + + + + + + + 列表 + + + + + + + 分页 + + + + + + + 下拉 + + + + + + + 更新 + + + + + + + + 产线添加设备 + + + + + + 产线删除设备 + + + + + + 产线设备不分页 + + + + + + 产线设备分页 + + + + + + 产线添加料仓 + + + + + + 产线删除料仓 + + + + + + 产线料仓不分页 + + + + + + 产线料仓分页 + + + + + + 名 称 :配方物料Dto类 + 创 建 人 :yangxiao + 创建时间 :2023/3/2 16:12:06 + 描 述 : + + + + + 物料Id + + + + + 配方Id + + + + + 重量 + + + + + 描述 + + + + + 误差 + + + + + 增加 + + + + + 更新 + + + + + 主键 + + + + + 删除 + + + + + 主键 + + + + + 不分页 + + + + + 配方Id + + + + + 分页 + + + + + 输出 + + + + + 主键 + + + + + 配方名称 + + + + + 物料名称 + + + + + 物料编码 + + + + + 名 称 :配方Dto类 + 创 建 人 :yangxiao + 创建时间 :2023/3/2 16:12:06 + 描 述 : + + + + + 名称 + + + + + 自定义编码 + + + + + 增加 + + + + + 更新 + + + + + 主键 + + + + + 删除 + + + + + 主键 + + + + + 分页 + + + + + 名称 + + + + + 分组id + + + + + 输出 + + + + + 主键 + + + + + 分组Id + + + + + 主键 + + + + + + 名 称 :配方物料服务 + 创 建 人 :yangxiao + 创建时间 :2023/3/2 18:33:18 + 描 述 : + + + + + 增加 + + + + + + 批量增加 + + + + + + + 移除 + + + + + + 更新 + + + + + + 不分页列表 + + + + + + 分页列表 + + + + + + 查询单条 + + + + + + + 名 称 :配方服务 + 创 建 人 :yangxiao + 创建时间 :2023/3/2 18:33:18 + 描 述 : + + + + + 增加 + + + + + + 移除 + + + + + + 更新 + + + + + + 不分页列表 + + + + + + 分页列表 + + + + + + 下拉列表 + + + + + + 查询单条 + + + + + + + 更改物料分组 + + + + + + + 名 称 :配方物料服务 + 创 建 人 :yangxiao + 创建时间 :2023/3/2 16:11:04 + 描 述 :配方物料数据维护 + + + + + 增加 + + + + + + + 批量增加 + + + + + + + + 删除 + + + + + + + + 详情 + + + + + + + + 列表 + + + + + + + 分页 + + + + + + + 更新 + + + + + + + + 名 称 :配方管理 + 创 建 人 :yangxiao + 创建时间 :2023/3/2 16:11:04 + 描 述 :店铺数据维护 + + + + + 增加 + + + + + + + 删除 + + + + + + + + 详情 + + + + + + + + 列表 + + + + + + + 分页 + + + + + + + 下拉 + + + + + + + 更新 + + + + + + + + 获取产品生产统计 + + + + + + + 获取物料统计 + + + + + + + 获取成品生产统计 + + + + + + + 获取物料统计 + + + + + + + 名 称 : 料仓服务 + 创 建 人 :yangxiao + 创建时间 : 2023/7/17 15:27:20 + 描 述 : + + + + + 料仓编码 + + + + + 料仓名称 + + + + + 物料Id + + + + + 料仓容积 + + + + + 增加 + + + + + 更新 + + + + + 主键 + + + + + 删除 + + + + + 主键 + + + + + 分页 + + + + + 名称 + + + + + 编码 + + + + + 输出 + + + + + 主键 + + + + + 物料Name + + + + + 名 称 :料仓服务 + 创 建 人 :yangxiao + 创建时间 : 2023/7/17 15:32:17 + 描 述 : + + + + + 增加 + + + + + + 移除 + + + + + + 更新 + + + + + + 不分页列表 + + + + + + 分页列表 + + + + + + 下拉列表 + + + + + + 查询单条 + + + + + + + 名 称 :料仓服务 + 创 建 人 :yangxiao + 创建时间 :2023/3/2 16:11:04 + 描 述 :基础数据管理 + + + + + 增加 + + + + + + + 删除 + + + + + + + + 详情 + + + + + + + + 列表 + + + + + + + 分页 + + + + + + + 下拉 + + + + + + + 更新 + + + + + + + + 名 称 : + 创 建 人 :yangxiao + 创建时间 : 2024/4/8 15:46:52 + 描 述 : + + + + + 批次名词 + + + + + 创建时间 + + + + + 状态 + + + + + 增加 + + + + + 更新 + + + + + 主键 + + + + + 删除 + + + + + 主键 + + + + + 不分页 + + + + + 分页 + + + + + 创建时间 + + + + + 起始时间 + + + + + 结束时间 + + + + + 输出 + + + + + 主键 + + + + + 个数 + + + + + 名 称 : + 创 建 人 :yangxiao + 创建时间 : 2023/8/10 14:19:47 + 描 述 : + + + + + 工艺Id + + + + + 工艺名称 + + + + + 工艺步骤 + + + + + 工艺步骤名称 + + + + + 执行状态 + + + + + 更新状态 + + + + + 增加 + + + + + 更新 + + + + + 工单工艺步骤Id + + + + + 工单Id + + + + + 锅数 + + + + + 状态 + + + + + 删除 + + + + + 主键 + + + + + 分页 + + + + + 输出 + + + + + 主键 + + + + + 名 称 : + 创 建 人 :yangxiao + 创建时间 : 2023/7/20 14:29:09 + 描 述 : + + + + + 工单名称 + + + + + 产线Id + + + + + 成品Id + + + + + 产量 + + + + + 批次号 + + + + + 设备id + + + + + 创建时间 + + + + + 增加 + + + + + 更新 + + + + + 主键 + + + + + 删除 + + + + + 主键 + + + + + 不分页查询条件 + + + + + 名称 + + + + + 主键 + + + + + 工单状态 + + + + + 起始时间 + + + + + 结束时间 + + + + + 批次计划Id + + + + + 分页 + + + + + 名称 + + + + + 编码 + + + + + 工单状态 + + + + + 批次计划Id + + + + + 起始时间 + + + + + 结束时间 + + + + + 工单下发 + + + + + 输出 + + + + + 主键 + + + + + 产品名称 + + + + + 线名称 + + + + + 设备编码 + + + + + 设备名称 + + + + + 工单状态 + + + + + 详情输出 + + + + + 工艺状态 + + + + + 配方状态 + + + + + 工艺步骤 + + + + + 物料信息 + + + + + 名 称 :工单产量 + 创 建 人 :yangxiao + 创建时间 : 2023/7/20 14:29:25 + 描 述 : + + + + + 工单名称 + + + + + 产量 + + + + + 增加 + + + + + 更新 + + + + + 主键 + + + + + 删除 + + + + + 主键 + + + + + 分页 + + + + + 名称 + + + + + 编码 + + + + + 输出 + + + + + 主键 + + + + + 名 称 : + 创 建 人 :yangxiao + 创建时间 : 2023/8/10 9:48:30 + 描 述 : + + + + + 物料名称 + + + + + 物料id + + + + + 工单id + + + + + 重量 + + + + + 第几锅 + + + + + 配方Id + + + + + 配方名称 + + + + + 物料状态 + + + + + 更新时间 + + + + + 误差重量 + + + + + 增加 + + + + + 更新 + + + + + 工单物料Id + + + + + 状态 + + + + + 删除 + + + + + 主键 + + + + + 分页 + + + + + 输出 + + + + + 主键 + + + + + 物料类型 + + + + + 物料类型名称 + + + + + 每升重量 + + + + + 名 称 :工单状态 + 创 建 人 :yangxiao + 创建时间 :2023/7/20 14:29:39 + 描 述 : + + + + + 工单Id + + + + + 工单状态 + + + + + 创建时间 + + + + + 备注 + + + + + 增加 + + + + + 更新 + + + + + 工单Id + + + + + 状态 + + + + + 备注 + + + + + 删除 + + + + + 主键 + + + + + 分页 + + + + + 批次下发 + + + + + 下发 + + + + + 工单ID + + + + + 设备ID + + + + + 输出 + + + + + 主键 + + + + + 状态名称 + + + + + 名 称 : + 创 建 人 :yangxiao + 创建时间 : 2024/4/8 15:41:42 + 描 述 : + + + + + 增加 + + + + + + 移除 + + + + + + 更新 + + + + + + 不分页列表 + + + + + + 分页列表 + + + + + + 名 称 :工单服务 + 创 建 人 :yangxiao + 创建时间 : 2023/7/20 14:39:28 + 描 述 : + + + + + 增加 + + + + + + 移除 + + + + + + 更新 + + + + + + 不分页列表 + + + + + + 分页列表 + + + + + + 下拉列表 + + + + + + 查询单条 + + + + + + + 更改状态 + + + + + + 工单下发 + + 工单Id + + + + + 批次工单下发 + + + + + + + 强制结束 + + 工单Id + + + + + 工单状态记录 + + + + + + + 修改工单步骤状态 + + + + + + + 修改工单物料状态 + + + + + + + 名 称 : + 创 建 人 :yangxiao + 创建时间 : 2023/7/21 14:54:31 + 描 述 : + + + + + 名 称 :工单服务 + 创 建 人 :yangxiao + 创建时间 :2023/7/20 14:39:41 + 描 述 : + + + + + 名 称 :工单服务 + 创 建 人 :yangxiao + 创建时间 :2023/7/20 14:39:41 + 描 述 : + + + + + 增加 + + + + + + + 删除 + + + + + + + + 详情 + + + + + + + + 列表 + + + + + + + 分页 + + + + + + + 分页 + + + + + + + 工单下发 + + 工单id + + + + + + 工单下发 + + 工单id + + + + + + 下拉 + + + + + + + 更新 + + + + + + + + 修改工单状态 + + + + + + + + 修改工单物料状态 + + + + + + + 修改工单步骤状态 + + + + + + + 强制结束工单 + + + + + + + 工单状态变更记录 + + + + + + + 名 称 : + 创 建 人 :yangxiao + 创建时间 : 2023/7/21 14:54:42 + 描 述 : + + + + + 系统缓存服务 + + + + + 获取所有缓存关键字 + + + + + + 删除指定关键字缓存 + + + + + + + 删除某特征关键字缓存 + + + + + + + 设置缓存 + + + + + + + + 设置缓存 + + + + + + + + 获取缓存 + + + + + + + 获取缓存 + + + + + + + + 检查给定 key 是否存在 + + 键 + + + + + 增加缓存Key + + + + + + + + + + + + + + [账号信息]入参基础 + + + + + 账号 + + admin + + + + 密码 + + e10adc3949ba59abbe56e057f20f883e + + + + [账号信息]添加入参 + + + + + 员工编号 + + + + + [账号信息]修改入参 + + + + + 主键 + + + + + 员工编号 + + + + + [账号信息]修改密码 + + + + + 旧密码 + + + + + 新密码 + + + + + [账号信息]删除入参 + + + + + 主键 + + + + + [账号信息]普通查询入参 + + + + + 主键 + + + + + [账号信息]分页查询入参 + + + + + 主键 + + + + + 账号名称 + + + + + 名 称 :[账号信息]输出实体 + 创 建 人 :yangxiao + 创建时间 : 2023/1/3 10:22:37 + 描 述 : + + + + + 主键 + + + + + 账号 + + + + + 密码 + + + + + 员工id + + + + + [授权信息]入参基础 + + + + + 关键字 + + + + + 模板Id + + + + + 授权类型 1:用户,2:角色 + + + + + 授权对象 + + + + + [授权信息]添加入参 + + + + + [授权信息]角色授权入参 + + + + + 模板编号 + + + + + 授权类型 1用户 2角色 + + + + + 授权对象 + + + + + [授权信息]修改入参 + + + + + 主键 + + + + + [授权信息]删除入参 + + + + + 主键 + + + + + [授权信息]普通查询入参 + + + + + 主键 + + + + + [授权信息]分页查询入参 + + + + + 主键 + + + + + 名 称 :授权信息输出 + 创 建 人 :yangxiao + 创建时间 : 2023/1/4 17:24:21 + 描 述 : + + + + + 编号 + + + + + 名称 + + + + + 已授权 + + + + + 名 称 : + 创 建 人 :yangxiao + 创建时间 : 2023/1/5 15:15:50 + 描 述 : + + + + + 员工姓名 + + + + + 0男1女 + + + + + 0启用 1禁用 + + + + + 角色Id + + + + + 是否存在账号 + + + + + 账号 + + + + + [授权信息]添加入参 + + + + + [授权信息]修改入参 + + + + + 主键 + + + + + [授权信息]删除入参 + + + + + 主键 + + + + + [授权信息]普通查询入参 + + + + + 主键 + + + + + [授权信息]分页查询入参 + + + + + 主键 + + + + + 关键字 + + + + + 状态 + + + + + 性别 + + + + + 入职时间 + + + + + 名 称 :[员工信息] + 创 建 人 :yangxiao + 创建时间 : 2023/1/5 15:18:02 + 描 述 : + + + + + 主键 + + + + + 排序 + + + + + 员工姓名 + + + + + 0男1女 + + + + + 0启用 1禁用 + + + + + 角色Id + + + + + 是否存在账号 + + + + + 账号 + + + + + [模块信息]入参基础 + + + + + 类别 1:菜单,2:视图,3:功能 + + + + + 菜单打开方式 0:框架内嵌,1:新开页面 + + + + + 父级编号 + + + + + 名称 + + + + + 图标 + + + + + 地址 + + + + + 排序码 + + + + + 启用禁用 + + + + + [模块信息]添加入参 + + + + + [模块信息]修改入参 + + + + + 主键 + + + + + [模块信息]删除入参 + + + + + 主键 + + + + + [模块信息]普通查询入参 + + + + + 主键 + + + + + [模块信息]分页查询入参 + + + + + 主键 + + + + + 名 称 : + 创 建 人 :yangxiao + 创建时间 : 2023/1/4 9:48:24 + 描 述 : + + + + + 主键 + + + + + 类别 1:菜单,2:视图,3:功能 + + + + + 菜单打开方式 0:框架内嵌,1:新开页面 + + + + + 父级编号 + + + + + 名称 + + + + + 图标 + + + + + 地址 + + + + + 排序码 + + + + + 启用禁用 + + + + + [菜单模块树]入参基础 + + + + + 类别 1:菜单,2:视图,3:功能 + + + + + 菜单打开方式 0:框架内嵌,1:新开页面 + + + + + 父级编号 + + + + + 名称 + + + + + 图标 + + + + + 地址 + + + + + 排序码 + + + + + 启用禁用 + + + + + 子集 + + + + + [菜单模块树]添加入参 + + + + + [菜单模块树]修改入参 + + + + + 主键 + + + + + [菜单模块树]删除入参 + + + + + 主键 + + + + + [菜单模块树]普通查询入参 + + + + + 主键 + + + + + 名称 + + + + + [菜单模块树]分页查询入参 + + + + + 主键 + + + + + 名 称 :[菜单模块树]输出 + 创 建 人 :yangxiao + 创建时间 : 2023/1/4 16:14:43 + 描 述 : + + + + + 模块编号 + + + + + 类别 1:菜单,2:视图,3:功能 + + + + + 菜单打开方式 0:框架内嵌,1:新开页面 + + + + + 父级编号 + + + + + 名称 + + + + + 图标 + + + + + 地址 + + + + + 排序码 + + + + + 启用禁用 + + + + + 子集 + + + + + 名 称 :[角色信息] + 创 建 人 :yangxiao + 创建时间 : 2023/1/4 9:43:25 + 描 述 : + + + + + 角色名称 + + + + + 角色描述 + + + + + [角色信息]添加入参 + + + + + [角色信息]修改入参 + + + + + 主键 + + + + + [角色信息]删除入参 + + + + + 主键 + + + + + [角色信息]普通查询入参 + + + + + 主键 + + + + + [角色信息]分页查询入参 + + + + + 主键 + + + + + 关键字 + + + + + 名 称 : + 创 建 人 :yangxiao + 创建时间 : 2023/8/31 15:58:31 + 描 述 : + + + + + 角色Id + + + + + 模块Id + + + + + 父级Id + + + + + 角色Id + + + + + 角色Id + + + + + 模块Id + + + + + 角色Id + + + + + 名 称 :角色信息 + 创 建 人 :yangxiao + 创建时间 : 2023/1/4 9:43:42 + 描 述 : + + + + + 主键 + + + + + 角色名称 + + + + + 角色描述 + + + + + 名 称 :个人角色信息 + 创 建 人 :yangxiao + 创建时间 : 2023/1/4 17:46:47 + 描 述 : + + + + + 个人菜单信息 + + + + + 主键 + + + + + 菜单名称 + + + + + 菜单地址 + + + + + 菜单图标 + + + + + 菜单子项 + + + + + 父级Id + + + + + 分页信息 + + + + + 打开类型 + + + + + 类别 + + + + + 名 称 :授权服务 + 创 建 人 :yangxiao + 创建时间 :2023/3/2 16:11:04 + 描 述 :授权服务数据维护 + + + + + 登录 + + + + + + + 获取个人信息 + + + + + + 获取用户权限 + + + + + + 获取账户信息 + + + + + + + 添加账户 + + + + + + + 修改账户信息 + + + + + + + 删除账户 + + + + + + + 编辑员工 + + + + + + + 查询员工 + + + + + + + 删除员工 + + + + + + + 分配角色权限 + + + + + + + 根据角色获取权限模块 + + + + + + + 名 称 : + 创 建 人 :yangxiao + 创建时间 : 2023/7/20 15:09:49 + 描 述 : + + + + diff --git a/backend/BPA.MES.Base.Application/Const/ClaimConst.cs b/backend/BPA.MES.Base.Application/Const/ClaimConst.cs new file mode 100644 index 0000000..67d1454 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Const/ClaimConst.cs @@ -0,0 +1,88 @@ +namespace BPA.MES.Base.Application +{ + /// + /// 名 称 : + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/3/4 10:15:54 + /// 描 述 : + /// + public class ClaimConst + { + /// + /// 用户Id + /// + public const string CLAINM_USERID = "UserId"; + /// + /// 账号 + /// + public const string CLAINM_ACCOUNT = "Account"; + /// + /// 名称 + /// + public const string CLAINM_NAME = "Name"; + /// + /// 头像 + /// + public const string CLAINM_AVATARURL = "AvatarUrl"; + /// + /// 电话 + /// + public const string CLAINM_PHONE = "Phone"; + /// + /// 性别 + /// + public const string CLAINM_SEX = "0"; + /// + /// 是否授权 + /// + public const string CLAINM_ISAUTH = "0"; + /// + /// 角色Id + /// + public const string CLAINM_ROLEID = ""; + /// + /// 微信session_key + /// + public const string SESSION_KEY = "session_key"; + /// + /// 是否超级管理 + /// + public const string CLAINM_SUPERADMIN = "SuperAdmin"; + /// + /// 租户Id + /// + public const string TENANT_ID = "TenantId"; + /// + /// 用户组织机构Id + /// + public const string CLAINM_ORGID = "OrgId"; + /// + /// 用户组织机构名称 + /// + public const string CLAINM_ORGNAME = "OrgName"; + /// + /// 是否是管理员 + /// + public const bool ISADMIN = false; + /// + /// 所有缓存关键字集合 + /// + public const string CACHE_KEY_ALL = "allkey"; + } + + public class MQTTConfig + { + /// + /// 地址 + /// + public static string Address { get; set; } + /// + /// 密码 + /// + public static string Pwd { get; set; } + /// + /// 账号 + /// + public static string Account { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Const/DeviceTypeEnum.cs b/backend/BPA.MES.Base.Application/Const/DeviceTypeEnum.cs new file mode 100644 index 0000000..e30fa7c --- /dev/null +++ b/backend/BPA.MES.Base.Application/Const/DeviceTypeEnum.cs @@ -0,0 +1,40 @@ +namespace BPA.MES.Base.Application +{ + /// + /// 名 称 :产线设备类型 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/7/24 16:56:13 + /// 描 述 : + /// + public enum DeviceTypeEnum + { + /// + /// 锅 + /// + Pot, + /// + /// 釜 + /// + Kettle + } + /// + /// 配料状态 + /// + public enum EBatchingStatus + { + None = 0, + 等待配料 = 1, + 正在配料 = 2, + 配料完成 = 3 + } + /// + /// 工艺状态 + /// + public enum RecipeStatus + { + None = 0, + 等待执行 = 1, + 正在执行 = 2, + 执行完成 = 3 + } +} diff --git a/backend/BPA.MES.Base.Application/Const/ELogType.cs b/backend/BPA.MES.Base.Application/Const/ELogType.cs new file mode 100644 index 0000000..c1f6e52 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Const/ELogType.cs @@ -0,0 +1,10 @@ +namespace BPA.MES.Base.Application +{ + public enum ELogType + { + Error, + Info, + Warn, + + } +} diff --git a/backend/BPA.MES.Base.Application/Const/OrderStatusEnum.cs b/backend/BPA.MES.Base.Application/Const/OrderStatusEnum.cs new file mode 100644 index 0000000..16d256a --- /dev/null +++ b/backend/BPA.MES.Base.Application/Const/OrderStatusEnum.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BPA.MES.Base.Application.Const +{ + public enum OrderStatusEnum + { + /// + /// 未开始 + /// + NotStarted = 0, + /// + /// 进行中 + /// + Ongoing = 1, + /// + /// 完成 + /// + Completed = 2, + + + } +} diff --git a/backend/BPA.MES.Base.Application/Const/WorkOrderStatusEnum.cs b/backend/BPA.MES.Base.Application/Const/WorkOrderStatusEnum.cs new file mode 100644 index 0000000..83fc83e --- /dev/null +++ b/backend/BPA.MES.Base.Application/Const/WorkOrderStatusEnum.cs @@ -0,0 +1,40 @@ +namespace BPA.MES.Base.Application +{ + /// + /// 名 称 :工单枚举 + /// 创 建 人 :yangxiao + /// 创建时间 :2023/7/21 15:04:24 + /// 描 述 : + /// + public enum WorkOrderStatusEnum + { + /// + /// 未知 + /// + Unkown = -1, + /// + /// 草稿 + /// + Draft = 0, + /// + /// 已下发 + /// + Issued = 1, + /// + /// 已接受 + /// + Receive = 2, + /// + /// 已启动 + /// + Started = 3, + /// + /// 已完成 + /// + Completed = 4, + /// + /// 废弃 + /// + Obsolete = 5, + } +} diff --git a/backend/BPA.MES.Base.Application/Entitys/Agv/AgvLineEntity.cs b/backend/BPA.MES.Base.Application/Entitys/Agv/AgvLineEntity.cs new file mode 100644 index 0000000..711f75a --- /dev/null +++ b/backend/BPA.MES.Base.Application/Entitys/Agv/AgvLineEntity.cs @@ -0,0 +1,33 @@ +namespace BPA.MES.Base.Application.Entitys +{ + /// + /// 名 称 : + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/7/27 9:35:27 + /// 描 述 : + /// + [SugarTable("agv_line")] + public class AgvLineEntity : DEntityBase + { + /// + /// 自定义编码 + /// + public string Code { get; set; } + /// + /// 线路名称 + /// + public string Name { get; set; } + /// + /// 开始点位 + /// + public string StartPointId { get; set; } + /// + /// 结束点位 + /// + public string EndPointId { get; set; } + /// + /// 描述 + /// + public string Description { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Entitys/Agv/AgvPointEntity.cs b/backend/BPA.MES.Base.Application/Entitys/Agv/AgvPointEntity.cs new file mode 100644 index 0000000..03551ef --- /dev/null +++ b/backend/BPA.MES.Base.Application/Entitys/Agv/AgvPointEntity.cs @@ -0,0 +1,21 @@ +namespace BPA.MES.Base.Application.Entitys +{ + /// + /// 名 称 : + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/7/27 9:36:07 + /// 描 述 : + /// + [SugarTable("agv_point")] + public class AgvPointEntity : DEntityBase + { + /// + /// 点位名称 + /// + public string Name { get; set; } + /// + /// 点位编码 + /// + public string Code { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Entitys/App/Pztj_BucketInfoEntity.cs b/backend/BPA.MES.Base.Application/Entitys/App/Pztj_BucketInfoEntity.cs new file mode 100644 index 0000000..79ade8f --- /dev/null +++ b/backend/BPA.MES.Base.Application/Entitys/App/Pztj_BucketInfoEntity.cs @@ -0,0 +1,22 @@ +namespace BPA.MES.Base.Application.Entitys +{ + /// + /// 名 称 :胖子天骄桶管理 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/7/14 11:33:10 + /// 描 述 : + /// + [SugarTable("bucket_info")] + public class Pztj_BucketInfoEntity : DEntityBase + { + /// + /// 桶名称 + /// + public string Name { get; set; } + /// + /// 桶编号 + /// + public string Code { get; set; } + + } +} diff --git a/backend/BPA.MES.Base.Application/Entitys/App/Pztj_BucketMaterialsRecordEntity.cs b/backend/BPA.MES.Base.Application/Entitys/App/Pztj_BucketMaterialsRecordEntity.cs new file mode 100644 index 0000000..3332257 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Entitys/App/Pztj_BucketMaterialsRecordEntity.cs @@ -0,0 +1,38 @@ +namespace BPA.MES.Base.Application.Entitys +{ + /// + /// 名 称 :桶原料记录 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/7/14 11:47:33 + /// 描 述 : + /// + [SugarTable("bucket_material_record")] + public class Pztj_BucketMaterialsRecordEntity : DEntityBase + { + /// + /// 桶Id + /// + [SugarColumn(IsNullable = true)] + public string BucketId { get; set; } + /// + /// 物料Id + /// + [SugarColumn(IsNullable = true)] + public string MaterialId { get; set; } + /// + /// 添加时间 + /// + [SugarColumn(IsNullable = true)] + public DateTime? CreateTime { get; set; } + /// + /// 重量 + /// + [SugarColumn(IsNullable = true)] + public string Weight { get; set; } + /// + /// 工单Id + /// + [SugarColumn(IsNullable = true)] + public string WorkId { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Entitys/App/Pztj_CraftStepsEntity.cs b/backend/BPA.MES.Base.Application/Entitys/App/Pztj_CraftStepsEntity.cs new file mode 100644 index 0000000..b91e35e --- /dev/null +++ b/backend/BPA.MES.Base.Application/Entitys/App/Pztj_CraftStepsEntity.cs @@ -0,0 +1,36 @@ +namespace BPA.MES.Base.Application.Entitys +{ + /// + /// 名 称 :工艺路线 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/7/17 17:01:26 + /// 描 述 : + /// + [SugarTable("craft_Steps")] + public class Pztj_CraftStepsEntity : DEntityBase + { + /// + /// 工艺Id + /// + public string CraftId { get; set; } + /// + /// 步骤 + /// + public int Step { get; set; } + /// + /// 功能描述 + /// + [SugarColumn(IsNullable = true)] + public string Description { get; set; } + /// + /// 设备产品功能Id + /// + [SugarColumn(IsNullable = true)] + public string DeviceProductFunctionId { get; set; } + /// + /// 功能参数 + /// + [SugarColumn(IsNullable = true, ColumnDataType= "longtext")] + public string Params { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Entitys/App/Pztj_CraftsInfoEntity.cs b/backend/BPA.MES.Base.Application/Entitys/App/Pztj_CraftsInfoEntity.cs new file mode 100644 index 0000000..9c7df8b --- /dev/null +++ b/backend/BPA.MES.Base.Application/Entitys/App/Pztj_CraftsInfoEntity.cs @@ -0,0 +1,25 @@ +namespace BPA.MES.Base.Application.Entitys +{ + /// + /// 名 称 :胖子天骄工艺基础信息 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/7/14 14:43:37 + /// 描 述 : + /// + [SugarTable("craft_info")] + public class Pztj_CraftsInfoEntity : DEntityBase + { + /// + /// 工艺名称 + /// + public string Name { get; set; } + /// + /// 设备产品Id + /// + public string DeviceProductId { get; set; } + /// + /// 工艺描述 + /// + public string Description { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Entitys/App/Pztj_DevicesInfoEntity.cs b/backend/BPA.MES.Base.Application/Entitys/App/Pztj_DevicesInfoEntity.cs new file mode 100644 index 0000000..d80f4a1 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Entitys/App/Pztj_DevicesInfoEntity.cs @@ -0,0 +1,43 @@ +namespace BPA.MES.Base.Application.Entitys +{ + /// + /// 名 称 :胖子天骄设备基础表 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/7/14 11:26:34 + /// 描 述 : + /// + [SugarTable("device_info")] + public class Pztj_DevicesInfoEntity: DEntityBase + { + /// + /// 名称 + /// + [Required(ErrorMessage = "名称不能为空")] + public string Name { get; set; } + /// + /// 编码 + /// + [Required(ErrorMessage = "编码不能为空")] + public string Code { get; set; } + /// + /// 设备类型 + /// + [SugarColumn(IsNullable = true)] + public string DeviceType { get; set; } + /// + /// 设备描述 + /// + [SugarColumn(IsNullable = true)] + public string Describe { get; set; } + /// + /// 设备维保时间 + /// + [SugarColumn(IsNullable = true)] + public string RepairDate { get; set; } + /// + /// 设备创建时间 + /// + [SugarColumn(IsNullable = true)] + public string CreateTime { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Entitys/App/Pztj_FinalsInfoEntity.cs b/backend/BPA.MES.Base.Application/Entitys/App/Pztj_FinalsInfoEntity.cs new file mode 100644 index 0000000..bfbc782 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Entitys/App/Pztj_FinalsInfoEntity.cs @@ -0,0 +1,33 @@ +namespace BPA.MES.Base.Application.Entitys +{ + /// + /// 名 称 :胖子天骄成品基础信息管理 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/7/14 14:07:56 + /// 描 述 : + /// + [SugarTable("final_info")] + public class Pztj_FinalsInfoEntity : DEntityBase + { + /// + /// 成品编号 + /// + public string Code { get; set; } + /// + /// 成品名称 + /// + public string Name { get; set; } + /// + /// 配方Id + /// + public string RecipeId { get; set; } + /// + /// 工艺Id + /// + public string CraftId { get; set; } + /// + /// 添加时间 + /// + public DateTime? CreateTime { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Entitys/App/Pztj_LineDevicesEntity.cs b/backend/BPA.MES.Base.Application/Entitys/App/Pztj_LineDevicesEntity.cs new file mode 100644 index 0000000..d93c88b --- /dev/null +++ b/backend/BPA.MES.Base.Application/Entitys/App/Pztj_LineDevicesEntity.cs @@ -0,0 +1,21 @@ +namespace BPA.MES.Base.Application.Entitys +{ + /// + /// 名 称 :产线设备 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/7/20 16:45:05 + /// 描 述 : + /// + [SugarTable("productline_devices")] + public class Pztj_LineDevicesEntity : DEntityBase + { + /// + /// 产线Id + /// + public string LineId { get; set; } + /// + /// 产线设备 + /// + public string DeviceId { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Entitys/App/Pztj_LineStocksEntity.cs b/backend/BPA.MES.Base.Application/Entitys/App/Pztj_LineStocksEntity.cs new file mode 100644 index 0000000..ed6f78b --- /dev/null +++ b/backend/BPA.MES.Base.Application/Entitys/App/Pztj_LineStocksEntity.cs @@ -0,0 +1,21 @@ +namespace BPA.MES.Base.Application.Entitys +{ + /// + /// 名 称 :产线料仓 + /// 创 建 人 :yangxiao + /// 创建时间 :2023/7/20 16:45:40 + /// 描 述 : + /// + [SugarTable("productline_stocks")] + public class Pztj_LineStocksEntity : DEntityBase + { + /// + /// 产线Id + /// + public string LineId { get; set; } + /// + /// 产线料仓 + /// + public string StockId { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Entitys/App/Pztj_MaterialsInfoEntity.cs b/backend/BPA.MES.Base.Application/Entitys/App/Pztj_MaterialsInfoEntity.cs new file mode 100644 index 0000000..c80edb4 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Entitys/App/Pztj_MaterialsInfoEntity.cs @@ -0,0 +1,34 @@ +namespace BPA.MES.Base.Application.Entitys +{ + /// + /// 名 称 :胖子天骄原料管理 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/7/14 11:32:06 + /// 描 述 : + /// + [SugarTable("material_Info")] + public class Pztj_MaterialsInfoEntity : DEntityBase + { + /// + /// 原料名称 + /// + public string Name { get; set; } + /// + /// 原料编号 + /// + public string Code { get; set; } + /// + /// 原料单位 + /// + public string Unit { get; set; } + /// + /// 原料分组 + /// + public string Type { get; set; } + /// + /// 每升重量 + /// + [SugarColumn(IsNullable = true)] + public string WeightPerLiter { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Entitys/App/Pztj_StockInfoEntity.cs b/backend/BPA.MES.Base.Application/Entitys/App/Pztj_StockInfoEntity.cs new file mode 100644 index 0000000..60338a1 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Entitys/App/Pztj_StockInfoEntity.cs @@ -0,0 +1,30 @@ +namespace BPA.MES.Base.Application.Entitys +{ + /// + /// 名 称 :胖子天骄料仓管理 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/7/14 11:31:34 + /// 描 述 : + /// + [SugarTable("stock_info")] + public class Pztj_StockInfoEntity : DEntityBase + { + /// + /// 料仓编码 + /// + public string Code { get; set; } + /// + /// 料仓名称 + /// + public string Name { get; set; } + /// + /// 物料Id + /// + public string MaterialId { get; set; } + /// + /// 料仓容积 + /// + public string Volume { get; set; } + + } +} diff --git a/backend/BPA.MES.Base.Application/Entitys/App/Pztj_WorkInfoEntity.cs b/backend/BPA.MES.Base.Application/Entitys/App/Pztj_WorkInfoEntity.cs new file mode 100644 index 0000000..d43dbd6 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Entitys/App/Pztj_WorkInfoEntity.cs @@ -0,0 +1,48 @@ +namespace BPA.MES.Base.Application.Entitys +{ + /// + /// 名 称 :工单基础信息 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/7/18 17:54:43 + /// 描 述 : + /// + [SugarTable("work_info")] + public class Pztj_WorkInfoEntity : DEntityBase + { + /// + /// 工单名称 + /// + [SugarColumn(IsNullable = true)] + public string Name { get; set; } + /// + /// 产线Id + /// + public string LineId { get; set; } + /// + /// 成品Id + /// + public string FinalId { get; set; } + /// + /// 指定设备Id + /// + [SugarColumn(IsNullable = true)] + public string DeviceId { get; set; } + /// + /// 产量 + /// + public string Number { get;set; } + /// + /// 批次号 + /// + public string BatchId { get; set; } + /// + /// 工单当前状态 + /// + [SugarColumn(IsNullable = true)] + public WorkOrderStatusEnum? Status { get; set; } + /// + /// 创建时间 + /// + public DateTime CreateTime { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Entitys/App/Pztj_WorkInfoItemEntity.cs b/backend/BPA.MES.Base.Application/Entitys/App/Pztj_WorkInfoItemEntity.cs new file mode 100644 index 0000000..eceb6c2 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Entitys/App/Pztj_WorkInfoItemEntity.cs @@ -0,0 +1,21 @@ +namespace BPA.MES.Base.Application.Entitys +{ + /// + /// 名 称 :工单拆分 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/7/18 18:12:55 + /// 描 述 : + /// + [SugarTable("work_info_item")] + public class Pztj_WorkInfoItemEntity : DEntityBase + { + /// + /// 工单名称 + /// + public string Name { get; set; } + /// + /// 产量 + /// + public string Number { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Entitys/App/Pztj_WorkInfoStatusEntity.cs b/backend/BPA.MES.Base.Application/Entitys/App/Pztj_WorkInfoStatusEntity.cs new file mode 100644 index 0000000..ab8d0ff --- /dev/null +++ b/backend/BPA.MES.Base.Application/Entitys/App/Pztj_WorkInfoStatusEntity.cs @@ -0,0 +1,33 @@ +namespace BPA.MES.Base.Application.Entitys +{ + /// + /// 名 称 :工单状态 + /// 创 建 人 :yangxiao + /// 创建时间 :2023/7/18 18:07:21 + /// 描 述 : + /// + [SugarTable("work_info_status")] + public class Pztj_WorkInfoStatusEntity : DEntityBase + { + /// + /// 工单Id + /// + [SugarColumn(IsNullable = true)] + public string WorkId { get; set; } + /// + /// 工单状态 + /// + [SugarColumn(IsNullable = true)] + public WorkOrderStatusEnum? Status { get; set; } + /// + /// 创建时间 + /// + [SugarColumn(IsNullable = true)] + public DateTime CreateTime { get; set; } + /// + /// 备注 + /// + [SugarColumn(IsNullable = true)] + public string Remark { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Entitys/App/WorkBatchEntity.cs b/backend/BPA.MES.Base.Application/Entitys/App/WorkBatchEntity.cs new file mode 100644 index 0000000..7e31bd5 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Entitys/App/WorkBatchEntity.cs @@ -0,0 +1,26 @@ +namespace BPA.MES.Base.Application.Entitys +{ + /// + /// 名 称 : + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/8/9 18:22:42 + /// 描 述 : + /// + [SugarTable("work_batch")] + public class WorkBatchEntity : DEntityBase + { + /// + /// 批次名词 + /// + public string Name { get; set; } + /// + /// 创建时间 + /// + public DateTime CreateTime { get; set; } + /// + /// 状态 + /// + public WorkOrderStatusEnum? Status { get; set; } + + } +} diff --git a/backend/BPA.MES.Base.Application/Entitys/App/WorkInfoCraftstepRecordEntity.cs b/backend/BPA.MES.Base.Application/Entitys/App/WorkInfoCraftstepRecordEntity.cs new file mode 100644 index 0000000..41b2192 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Entitys/App/WorkInfoCraftstepRecordEntity.cs @@ -0,0 +1,67 @@ +namespace BPA.MES.Base.Application.Entitys +{ + /// + /// 名 称 : + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/8/10 10:03:15 + /// 描 述 : + /// + [SugarTable("work_info_craftstep_record")] + public class WorkInfoCraftstepRecordEntity : DEntityBase + { + /// + /// 工单Id + /// + public string WorkId { get; set; } + /// + /// 工艺Id + /// + public string CraftId { get; set; } + /// + /// 工艺名称 + /// + public string CraftName { get; set; } + /// + /// 工艺步骤Id + /// + public string CraftstepId { get; set; } + /// + /// 步骤 + /// + public int Step { get; set; } + /// + /// 工艺步骤名称 + /// + [SugarColumn(IsNullable = true)] + public string CraftstepName { get; set; } + /// + /// 工艺参数 + /// + [SugarColumn(IsNullable = true)] + public string CraftstepParms { get; set; } + /// + /// 设备类型功能Id + /// + [SugarColumn(IsNullable = true)] + public string DeviceProductFunctionId { get; set; } + /// + /// 设备类型功能名称 + /// + [SugarColumn(IsNullable = true)] + public string DeviceProductFunctionName { get; set; } + /// + /// 执行状态 + /// + [SugarColumn(IsNullable = true)] + public RecipeStatus Status { get; set; } + /// + /// 更新时间 + /// + [SugarColumn(IsNullable = true)] + public DateTime? UpdateTime{ get;set;} + /// + /// 第几锅 + /// + public string PotNum { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Entitys/App/WorkInfoMaterialsRecordEntity.cs b/backend/BPA.MES.Base.Application/Entitys/App/WorkInfoMaterialsRecordEntity.cs new file mode 100644 index 0000000..b94c2a0 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Entitys/App/WorkInfoMaterialsRecordEntity.cs @@ -0,0 +1,63 @@ +namespace BPA.MES.Base.Application.Entitys +{ + /// + /// 名 称 : + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/8/9 18:22:42 + /// 描 述 : + /// + [SugarTable("work_info_materials_record")] + public class WorkInfoMaterialsRecordEntity : DEntityBase + { + /// + /// 物料名称 + /// + [SugarColumn(IsNullable = true)] + public string MaterialName { get; set; } + /// + /// 物料id + /// + [SugarColumn(IsNullable = true)] + public string MaterialId { get; set; } + /// + /// 工单id + /// + [SugarColumn(IsNullable = true)] + public string WorkId { get; set; } + /// + /// 重量 + /// + [SugarColumn(IsNullable = true)] + public string Weight { get; set; } + /// + /// 第几锅 + /// + [SugarColumn(IsNullable = true)] + public string PotNum { get; set; } + /// + /// 配方Id + /// + [SugarColumn(IsNullable = true)] + public string RecipeId { get; set; } + /// + /// 配方名称 + /// + [SugarColumn(IsNullable = true)] + public string RecipeName { get; set; } + /// + /// 物料状态 + /// + [SugarColumn(IsNullable = true)] + public EBatchingStatus MaterialStatus { get; set; } + /// + /// 更新时间 + /// + [SugarColumn(IsNullable = true)] + public DateTime? UpdateTime { get; set; } + /// + /// 误差 + /// + [SugarColumn(IsNullable = true)] + public string ErrorWeight { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Entitys/Base/DeviceProductEntity.cs b/backend/BPA.MES.Base.Application/Entitys/Base/DeviceProductEntity.cs new file mode 100644 index 0000000..62ce072 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Entitys/Base/DeviceProductEntity.cs @@ -0,0 +1,26 @@ +namespace BPA.MES.Base.Application.Entitys +{ + /// + /// 名 称 :设备产品 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/8/1 16:34:53 + /// 描 述 : + /// + [SugarTable("devices_product")] + public class DeviceProductEntity : DEntityBase + { + /// + /// 设备产品名称 + /// + public string Name { get; set; } + /// + /// 设备产品编码 + /// + public string Code { get; set; } + /// + /// 设备产品描述 + /// + [SugarColumn(IsNullable = true)] + public string Description { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Entitys/Base/DeviceProductFunctionEntity.cs b/backend/BPA.MES.Base.Application/Entitys/Base/DeviceProductFunctionEntity.cs new file mode 100644 index 0000000..aaa58d6 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Entitys/Base/DeviceProductFunctionEntity.cs @@ -0,0 +1,38 @@ +namespace BPA.MES.Base.Application.Entitys +{ + /// + /// 名 称 :设备功能 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/8/2 16:03:10 + /// 描 述 : + /// + [SugarTable("devices_product_function")] + public class DeviceProductFunctionEntity : DEntityBase + { + /// + /// 设备产品Id + /// + [SugarColumn(IsNullable = true)] + public string DeviceProductId { get; set; } + /// + /// 功能名称 + /// + [SugarColumn(IsNullable = true)] + public string Name { get; set; } + /// + /// 功能编码 + /// + [SugarColumn(IsNullable = true)] + public string Code { get; set; } + /// + /// 描述 + /// + [SugarColumn(IsNullable = true)] + public string Description { get; set; } + /// + /// 方法参数 + /// + [SugarColumn(IsNullable = true, ColumnDataType = "longtext")] + public string Params { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Entitys/Base/DeviceProductParmEntity.cs b/backend/BPA.MES.Base.Application/Entitys/Base/DeviceProductParmEntity.cs new file mode 100644 index 0000000..dd527fd --- /dev/null +++ b/backend/BPA.MES.Base.Application/Entitys/Base/DeviceProductParmEntity.cs @@ -0,0 +1,30 @@ +namespace BPA.MES.Base.Application.Entitys +{ + /// + /// 名 称 :设备属性 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/7/31 15:06:00 + /// 描 述 : + /// + [SugarTable("devices_product_parm")] + public class DeviceProductParmEntity : DEntityBase + { + /// + /// 设备产品Id + /// + public string DeviceProductId { get; set; } + /// + /// 名称 + /// + public string Name { get; set; } + /// + /// 编码 + /// + public string Code { get; set; } + /// + /// 描述 + /// + [SugarColumn(IsNullable = true)] + public string Description { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Entitys/Base/DeviceRecipeEntity.cs b/backend/BPA.MES.Base.Application/Entitys/Base/DeviceRecipeEntity.cs new file mode 100644 index 0000000..a7d7750 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Entitys/Base/DeviceRecipeEntity.cs @@ -0,0 +1,22 @@ +namespace BPA.MES.Base.Application.Entitys +{ + /// + /// 名 称 :设备配方表 + /// 创 建 人 :yangxiao + /// 创建时间 :2023/3/2 13:57:00 + /// 描 述 : + /// + [SugarTable("devices_recipes")] + public class DeviceRecipeEntity : DEntityBase + { + /// + /// 设备Id + /// + public string DeviceId { get; set; } + /// + /// 配方Id + /// + public string RecipesId { get; set; } + + } +} diff --git a/backend/BPA.MES.Base.Application/Entitys/Base/DictDataEntity.cs b/backend/BPA.MES.Base.Application/Entitys/Base/DictDataEntity.cs new file mode 100644 index 0000000..0c2a890 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Entitys/Base/DictDataEntity.cs @@ -0,0 +1,33 @@ +namespace BPA.MES.Base.Application.Entitys +{ + /// + /// 名 称 :码表数据 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/8/9 9:47:53 + /// 描 述 : + /// + [SugarTable("dict_data")] + public class DictDataEntity : DEntityBase + { + /// + /// 类型id + /// + public string TypeId { get; set; } + /// + /// 值 + /// + public string Value { get; set; } + /// + /// 编码 + /// + public string Code { get; set; } + /// + /// 排序 + /// + public int Sort { get; set; } + /// + /// 添加时间 + /// + public DateTime CreateTime { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Entitys/Base/DictTypeEntity.cs b/backend/BPA.MES.Base.Application/Entitys/Base/DictTypeEntity.cs new file mode 100644 index 0000000..7feed45 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Entitys/Base/DictTypeEntity.cs @@ -0,0 +1,26 @@ +namespace BPA.MES.Base.Application.Entitys +{ + /// + /// 名 称 :数据码表 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/8/9 9:48:05 + /// 描 述 : + /// + [SugarTable("dict_type")] + public class DictTypeEntity : DEntityBase + { + /// + /// 名称 + /// + public string Name { get; set; } + /// + /// 编码 + /// + public string Code { get; set; } + /// + /// 排序 + /// + public int Sort { get; set; } + + } +} diff --git a/backend/BPA.MES.Base.Application/Entitys/Base/GroupInfoEntity.cs b/backend/BPA.MES.Base.Application/Entitys/Base/GroupInfoEntity.cs new file mode 100644 index 0000000..2bbf3b3 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Entitys/Base/GroupInfoEntity.cs @@ -0,0 +1,21 @@ +namespace BPA.MES.Base.Application.Entitys +{ + /// + /// 名 称 :分组信息 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/3/10 14:01:15 + /// 描 述 : + /// + [SugarTable("group_info")] + public class GroupInfoEntity: DEntityBase + { + /// + /// 名称 + /// + public string Name { get; set; } + /// + /// 介绍 + /// + public string Des { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Entitys/Base/MQTTInfoEntity.cs b/backend/BPA.MES.Base.Application/Entitys/Base/MQTTInfoEntity.cs new file mode 100644 index 0000000..c7ed338 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Entitys/Base/MQTTInfoEntity.cs @@ -0,0 +1,29 @@ +namespace BPA.MES.Base.Application.Entitys +{ + /// + /// 名 称 : + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/7/24 17:28:56 + /// 描 述 : + /// + [SugarTable("mqtt")] + public class MQTTInfoEntity + { + /// + /// 地址 + /// + public string Address { get; set; } + /// + /// 密码 + /// + public string Pwd { get; set; } + /// + /// 账号 + /// + public string Account { get; set; } + /// + /// 消息发布路由 4.0和5.0不一样 + /// + public string MsgPublishRoute { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Entitys/Base/OperLogEntity.cs b/backend/BPA.MES.Base.Application/Entitys/Base/OperLogEntity.cs new file mode 100644 index 0000000..0eca510 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Entitys/Base/OperLogEntity.cs @@ -0,0 +1,31 @@ +namespace BPA.MES.Base.Application.Entitys +{ + /// + /// 名 称 :操作日志 + /// 创 建 人 :yangxiao + /// 创建时间 :2023/7/20 15:10:59 + /// 描 述 : + /// + [SugarTable("oper_log")] + public class OperLogEntity : DEntityBase + { + /// + /// 操作标题 + /// + public string Name { get; set; } + /// + /// 内容 + /// + public string Context { get; set; } + /// + /// 返回值 + /// + [SugarColumn(IsNullable = true)] + public string Result { get; set; } + /// + /// 创建时间 + /// + [SugarColumn(IsNullable = true)] + public DateTime? CreateTime { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Entitys/Base/OrderInfoEntity.cs b/backend/BPA.MES.Base.Application/Entitys/Base/OrderInfoEntity.cs new file mode 100644 index 0000000..20e31fa --- /dev/null +++ b/backend/BPA.MES.Base.Application/Entitys/Base/OrderInfoEntity.cs @@ -0,0 +1,13 @@ +namespace BPA.MES.Base.Application.Entitys.Base +{ + /// + /// 名 称 :订单服务 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/7/18 18:11:48 + /// 描 述 : + /// + public class OrderInfoEntity + { + + } +} diff --git a/backend/BPA.MES.Base.Application/Entitys/Base/ProductLineEntity.cs b/backend/BPA.MES.Base.Application/Entitys/Base/ProductLineEntity.cs new file mode 100644 index 0000000..366b19f --- /dev/null +++ b/backend/BPA.MES.Base.Application/Entitys/Base/ProductLineEntity.cs @@ -0,0 +1,25 @@ +namespace BPA.MES.Base.Application.Entitys +{ + /// + /// 名 称 :产线管理 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/7/18 10:42:35 + /// 描 述 : + /// + [SugarTable("product_line")] + public class ProductLineEntity : DEntityBase + { + /// + /// 产线名称 + /// + public string Name { get; set; } + /// + /// 产线编码 + /// + public string Code { get; set; } + /// + /// 产线描述 + /// + public string Describe { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Entitys/Base/RecipeMaterialEntity.cs b/backend/BPA.MES.Base.Application/Entitys/Base/RecipeMaterialEntity.cs new file mode 100644 index 0000000..9f1512c --- /dev/null +++ b/backend/BPA.MES.Base.Application/Entitys/Base/RecipeMaterialEntity.cs @@ -0,0 +1,36 @@ +namespace BPA.MES.Base.Application.Entitys +{ + /// + /// 名 称 :配方物料信息 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/3/2 13:58:19 + /// 描 述 : + /// + [SugarTable("recipes_material")] + public class RecipeMaterialEntity : DEntityBase + { + /// + /// 物料Id + /// + public string MaterialId { get; set; } + /// + /// 配方Id + /// + public string RecipesId { get; set; } + /// + /// 重量 + /// + [SugarColumn(IsNullable = true)] + public string Weight { get; set; } + /// + /// 描述 + /// + [SugarColumn(IsNullable = true)] + public string Describe { get; set; } + /// + /// 误差 + /// + [SugarColumn(IsNullable = true)] + public string ErrorWeight { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Entitys/Base/RecipesGroupEntity.cs b/backend/BPA.MES.Base.Application/Entitys/Base/RecipesGroupEntity.cs new file mode 100644 index 0000000..1518fdd --- /dev/null +++ b/backend/BPA.MES.Base.Application/Entitys/Base/RecipesGroupEntity.cs @@ -0,0 +1,21 @@ +namespace BPA.MES.Base.Application.Entitys +{ + /// + /// 名 称 :配方分组 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/3/10 14:56:03 + /// 描 述 : + /// + [SugarTable("recipes_group")] + public class RecipesGroupEntity + { + /// + /// 组Id + /// + public string GroupId { get; set; } + /// + /// 产品Id + /// + public string RecipesId { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Entitys/Base/RecipesInfoEntity.cs b/backend/BPA.MES.Base.Application/Entitys/Base/RecipesInfoEntity.cs new file mode 100644 index 0000000..b9b63f6 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Entitys/Base/RecipesInfoEntity.cs @@ -0,0 +1,22 @@ +namespace BPA.MES.Base.Application.Entitys +{ + /// + /// 名 称 :配方信息 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/3/2 13:57:15 + /// 描 述 : + /// + [SugarTable("recipes_info")] + public class RecipesInfoEntity : DEntityBase + { + /// + /// 名称 + /// + public string Name { get; set; } + /// + /// 自定义编码 + /// + public string Code { get; set; } + + } +} diff --git a/backend/BPA.MES.Base.Application/Entitys/Base/StoreInfoEntity.cs b/backend/BPA.MES.Base.Application/Entitys/Base/StoreInfoEntity.cs new file mode 100644 index 0000000..6a5c6ef --- /dev/null +++ b/backend/BPA.MES.Base.Application/Entitys/Base/StoreInfoEntity.cs @@ -0,0 +1,30 @@ +namespace BPA.MES.Base.Application.Entitys +{ + /// + /// 名 称 :店铺信息 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/3/2 13:52:13 + /// 描 述 : + /// + [SugarTable("store_info")] + public class StoreInfoEntity : DEntityBase + { + /// + /// 名称 + /// + [Required(ErrorMessage = "名称不能为空")] + public string Name { get; set; } + /// + /// 地址 + /// + public string Address { get; set; } + /// + /// 联系电话 + /// + public string Phone { get; set; } + /// + /// 负责人 + /// + public string Directors { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Entitys/KepData/AlarmLog.cs b/backend/BPA.MES.Base.Application/Entitys/KepData/AlarmLog.cs new file mode 100644 index 0000000..a8da614 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Entitys/KepData/AlarmLog.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BPA.MES.Base.Application.Entitys.KepData +{ + [SugarTable("DataVAlarmLog")] + public class AlarmLog: DEntityBase + { + public string Name { get; set; } + + /// + /// 当前值 + /// + public string Value { get; set; } + + /// + /// 报警信息 + /// + public string ValueStr{ get; set; } + + + public DateTime CreateTime { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Entitys/KepData/DataVAlarmLimit.cs b/backend/BPA.MES.Base.Application/Entitys/KepData/DataVAlarmLimit.cs new file mode 100644 index 0000000..97ce0cd --- /dev/null +++ b/backend/BPA.MES.Base.Application/Entitys/KepData/DataVAlarmLimit.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BPA.MES.Base.Application.Entitys.KepData +{ + /// + /// 大屏报警限制 + /// + [SugarTable("DataVAlarmLimit")] + public class DataVAlarmLimit: DEntityBase + { + /// + /// 限制名称 + /// + public string Name { get; set; } + + public string Code { get; set; } + + /// + /// 最小限制值 + /// + public decimal MinLimitValue { get; set; } + + /// + /// 最大限制值 + /// + public decimal MaxLimitValue { get; set; } + + } +} diff --git a/backend/BPA.MES.Base.Application/Entitys/KepData/ch1_device1.cs b/backend/BPA.MES.Base.Application/Entitys/KepData/ch1_device1.cs new file mode 100644 index 0000000..7459fe0 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Entitys/KepData/ch1_device1.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BPA.MES.Base.Application.Entitys.KepData +{ + // [SugarTable("ch1_device1")] + public class ch1_device1 + { + [SugarColumn(IsPrimaryKey = true)] + public int id { get; set; } + public string _NAME { get; set; } + public int _NUMERICID { get; set; } + public string _VALUE { get; set; } + public DateTime _TIMESTAMP { get; set; } + public int _QUALITY { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Entitys/Logs/AlarmLogEntity.cs b/backend/BPA.MES.Base.Application/Entitys/Logs/AlarmLogEntity.cs new file mode 100644 index 0000000..eb9a200 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Entitys/Logs/AlarmLogEntity.cs @@ -0,0 +1,54 @@ +namespace BPA.MES.Base.Application.Entitys +{ + /// + /// 名 称 :报警日志 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/8/21 10:17:57 + /// 描 述 : + /// + [SugarTable("alarm")] + public class AlarmLogEntity : DEntityBase + { + /// + /// 报警信息 + /// + [SugarColumn(IsNullable = true)] + public string MsgInfo { get; set; } + /// + /// 报警值 + /// + [SugarColumn(IsNullable = true)] + public string Value { get; set; } + /// + /// 报警等级 + /// + [SugarColumn(IsNullable = true)] + public string Grade { get; set; } + /// + /// 设备名称 + /// + [SugarColumn(IsNullable = true)] + public string DeviceName { get; set; } + /// + /// 日期 + /// + [SugarColumn(IsNullable = true)] + public string Date { get; set; } + /// + /// 时间 + /// + [SugarColumn(IsNullable = true)] + public string Time { get; set; } + /// + /// 创建时间 + /// + [SugarColumn(IsNullable = true)] + public DateTime CreateDate { get; set; } + /// + /// 类型 + /// + [SugarColumn(IsNullable = true)] + public string LogType { get; set; } + + } +} diff --git a/backend/BPA.MES.Base.Application/Entitys/Logs/ProgramLogEntity.cs b/backend/BPA.MES.Base.Application/Entitys/Logs/ProgramLogEntity.cs new file mode 100644 index 0000000..c117ec6 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Entitys/Logs/ProgramLogEntity.cs @@ -0,0 +1,39 @@ +namespace BPA.MES.Base.Application.Entitys +{ + /// + /// 名 称 :程序日志 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/8/21 10:18:13 + /// 描 述 : + /// + [SugarTable("programlog")] + public class ProgramLogEntity : DEntityBase + { + /// + /// 日志类型 + /// + [SugarColumn(IsNullable = true, ColumnDataType = "varchar",Length = 200)] + public string LogType { get; set; } + /// + /// 日志消息 + /// + [SugarColumn(IsNullable = true, ColumnDataType = "longtext")] + public string MsgInfo { get; set; } + /// + /// 日期 + /// + [SugarColumn(IsNullable = true)] + public string Date { get; set; } + /// + /// 时间 + /// + [SugarColumn(IsNullable = true)] + public string Time { get; set; } + /// + /// 日志消息 + /// + [SugarColumn(IsNullable = true)] + public DateTime CreateDate { get; set; } + + } +} diff --git a/backend/BPA.MES.Base.Application/Entitys/Logs/RunLogEntity.cs b/backend/BPA.MES.Base.Application/Entitys/Logs/RunLogEntity.cs new file mode 100644 index 0000000..9317b17 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Entitys/Logs/RunLogEntity.cs @@ -0,0 +1,45 @@ +namespace BPA.MES.Base.Application.Entitys +{ + /// + /// 名 称 :运行日志 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/8/21 10:18:34 + /// 描 述 : + /// + [SplitTable(SplitType.Month)] + //[SugarTable("runlog_{year}{month}{day}")] + [SugarTable("runlog")] + public class RunLogEntity : DEntityBase + { + /// + /// 日志类别 + /// + [SugarColumn(IsNullable = true)] + public string LogType { get; set; } + /// + /// 日志消息 + /// + [SugarColumn(IsNullable = true, ColumnDataType = "longtext")] + public string MsgInfo { get; set; } + /// + /// 日期 + /// + [SugarColumn(IsNullable = true)] + public string Date { get; set; } + /// + /// 时间 + /// + [SugarColumn(IsNullable = true)] + public string Time { get; set; } + /// + /// 日志消息 + /// + [SugarColumn(IsNullable = true),SplitField] + public DateTime CreateDate { get; set; } + /// + /// 更新时间 + /// + [SugarColumn(IsNullable = true)]//设置为可空字段 + public DateTime UpdateTime { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Entitys/Logs/UserLogEntity.cs b/backend/BPA.MES.Base.Application/Entitys/Logs/UserLogEntity.cs new file mode 100644 index 0000000..06f9db3 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Entitys/Logs/UserLogEntity.cs @@ -0,0 +1,36 @@ +namespace BPA.MES.Base.Application.Entitys +{ + /// + /// 名 称 :用户日志 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/8/21 10:18:50 + /// 描 述 : + /// + [SugarTable("user_log")] + public class UserLogEntity : DEntityBase + { + /// + /// 权限 + /// + [SugarColumn(IsNullable = true)] + public string Permission { get; set; } + + /// + /// 用户名 + /// + [SugarColumn(IsNullable = true)] + public string UserName { get; set; } + + /// + /// 日志消息 + /// + [SugarColumn(IsNullable = true)] + public string MsgInfo { get; set; } + + /// + /// 日志时间 + /// + [SugarColumn(IsNullable = true)] + public DateTime CreateDate { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Entitys/Order/OrderEntity.cs b/backend/BPA.MES.Base.Application/Entitys/Order/OrderEntity.cs new file mode 100644 index 0000000..4fee717 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Entitys/Order/OrderEntity.cs @@ -0,0 +1,24 @@ +using BPA.MES.Base.Application.Const; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BPA.MES.Base.Application.Entitys.Order +{ + + [SugarTable("order")] + public class OrderEntity: DEntityBase + { + + /// + /// 状态 + /// + public OrderStatusEnum Status { get; set; } + + + + public DateTime CreateTime { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Entitys/Order/OrderInfoEntity.cs b/backend/BPA.MES.Base.Application/Entitys/Order/OrderInfoEntity.cs new file mode 100644 index 0000000..a3b0f39 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Entitys/Order/OrderInfoEntity.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BPA.MES.Base.Application.Entitys.Order +{ + + [SugarTable("order_info")] + public class OrderInfoEntity : DEntityBase + { + /// + /// 订单ID + /// + public string OrderId { get; set; } + + /// + /// 成品Id + /// + public string FinalslId { get; set; } + + /// + /// 数量 + /// + public decimal Number { get; set; } + + public DateTime CreateTime { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Entitys/Order/OrderWorkEntity.cs b/backend/BPA.MES.Base.Application/Entitys/Order/OrderWorkEntity.cs new file mode 100644 index 0000000..c4e0537 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Entitys/Order/OrderWorkEntity.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BPA.MES.Base.Application.Entitys.Order +{ + /// + /// 订单关联工单 + /// + [SugarTable("order_work")] + public class OrderWorkEntity: DEntityBase + { + public string OrderId { get; set; } + public string WorkId { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Entitys/Sys/AccountEntity.cs b/backend/BPA.MES.Base.Application/Entitys/Sys/AccountEntity.cs new file mode 100644 index 0000000..8c0955b --- /dev/null +++ b/backend/BPA.MES.Base.Application/Entitys/Sys/AccountEntity.cs @@ -0,0 +1,29 @@ + +namespace BPA.MES.Base.Application.Entitys +{ + /// + /// 名 称 :账户信息 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/1/3 10:18:43 + /// 描 述 : + /// + [SugarTable("sys_account")] + public class AccountEntity : DEntityBase + { + /// + /// 账号 + /// + [SugarColumn(IsNullable = false)] + public string Account { get; set; } + /// + /// 密码 + /// + [SugarColumn(IsNullable = false)] + public string Pwd { get; set; } + /// + /// 员工表Id + /// + [SugarColumn(IsNullable = false)] + public string EmployeeId { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Entitys/Sys/EmployeeEntity.cs b/backend/BPA.MES.Base.Application/Entitys/Sys/EmployeeEntity.cs new file mode 100644 index 0000000..66b70f5 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Entitys/Sys/EmployeeEntity.cs @@ -0,0 +1,38 @@ +namespace BPA.MES.Base.Application.Entitys +{ + /// + /// 名 称 :员工信息 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/1/4 17:44:31 + /// 描 述 : + /// + [SugarTable("sys_employee")] + public class EmployeeEntity : DEntityBase + { + /// + /// 员工姓名 + /// + [SugarColumn(IsNullable = false)] + public string Name { get; set; } + /// + /// 1男2女 + /// + [SugarColumn(IsNullable = true)] + public int Gender { get; set; } + /// + /// 1启用 2禁用 + /// + [SugarColumn(IsNullable = false)] + public int Status { get; set; } + /// + /// 超管 + /// + [SugarColumn(IsNullable = false)] + public bool IsAdmin { get; set; } + /// + /// 角色Id + /// + public string RoleId { get; set; } + + } +} diff --git a/backend/BPA.MES.Base.Application/Entitys/Sys/ModuleEntity.cs b/backend/BPA.MES.Base.Application/Entitys/Sys/ModuleEntity.cs new file mode 100644 index 0000000..b9ef298 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Entitys/Sys/ModuleEntity.cs @@ -0,0 +1,46 @@ +namespace BPA.MES.Base.Application.Entitys +{ + /// + /// 名 称 :模块菜单表 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/1/4 17:32:15 + /// 描 述 : + /// + [SugarTable("sys_module")] + public class ModuleEntity : DEntityBase + { + /// + /// 类别 1:菜单,2:视图,3:功能 + /// + public int Category { get; set; } + + /// + /// 菜单打开方式 0:框架内嵌,1:新开页面 + /// + public int OpenType { get; set; } + + /// + /// 父级编号 + /// + public string ParentId { get; set; } + + /// + /// 名称 + /// + public string Name { set; get; } + + /// + /// 图标 + /// + public string Icon { set; get; } + + /// + /// 地址 + /// + public string Url { set; get; } + /// + /// 状态 + /// + public bool IsDisabled { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Entitys/Sys/RoleEntity.cs b/backend/BPA.MES.Base.Application/Entitys/Sys/RoleEntity.cs new file mode 100644 index 0000000..43522ff --- /dev/null +++ b/backend/BPA.MES.Base.Application/Entitys/Sys/RoleEntity.cs @@ -0,0 +1,32 @@ +namespace BPA.MES.Base.Application.Entitys +{ + /// + /// 名 称 :角色信息 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/1/4 17:32:32 + /// 描 述 : + /// + [SugarTable("sys_role")] + public class RoleEntity : DEntityBase + { + /// + /// 角色名称 + /// + public string Name { get; set; } + + /// + /// 角色类型 1超级管理员,2其他 + /// + public int? RoleType { get; set; } + + /// + /// 角色描述 + /// + public string Description { get; set; } + + /// + /// 是否删除 + /// + public bool IsDeleted { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Entitys/Sys/RoleModuleEntity.cs b/backend/BPA.MES.Base.Application/Entitys/Sys/RoleModuleEntity.cs new file mode 100644 index 0000000..bec361f --- /dev/null +++ b/backend/BPA.MES.Base.Application/Entitys/Sys/RoleModuleEntity.cs @@ -0,0 +1,26 @@ +namespace BPA.MES.Base.Application.Entitys +{ + /// + /// 名 称 :角色权限表 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/8/31 15:56:02 + /// 描 述 : + /// + [SugarTable("sys_role_module")] + public class RoleModuleEntity : DEntityBase + { + /// + /// 角色Id + /// + public string RoleId { get; set; } + /// + /// 模块Id + /// + public string ModuleId { get; set; } + /// + /// 父级模块 + /// + [SugarColumn(IsNullable =true)] + public string ParentId { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Filters/AGVAttribute.cs b/backend/BPA.MES.Base.Application/Filters/AGVAttribute.cs new file mode 100644 index 0000000..dfdff3e --- /dev/null +++ b/backend/BPA.MES.Base.Application/Filters/AGVAttribute.cs @@ -0,0 +1,39 @@ +using BPA.MES.Base.Application.Services; +using BPA.MES.Base.Application.Services.AGVService.Dtos; +using Furion.JsonSerialization; +using Microsoft.AspNetCore.Mvc.Filters; +using System.Diagnostics; + +namespace BPA.MES.Base.Application +{ + public class AGVAttribute : ActionFilterAttribute + { + /// + /// 执行操作前后 + /// + /// + /// + /// + public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) + { + // 获取 HttpContext 和 HttpRequest 对象 + var httpContext = context.HttpContext; + var httpRequest = httpContext.Request; + var sw = new Stopwatch(); + sw.Start(); + var actionContext = await next(); + sw.Stop(); + var server = App.GetService(); + var contentstring = JSON.Serialize(context.ActionArguments["input"]); + AGVLoadAndUnloadRequest input = JSON.Deserialize(contentstring); + Roller_JobRequest roller_Job = new() + { + AgvCode = input.Body.Event.agvCode, + Complete = true, + JobId = input.Body.Event.jobId, + MsgId = input.Body.Event.msgId + }; + await server.RollerJobExecute(roller_Job); + } + } +} diff --git a/backend/BPA.MES.Base.Application/Filters/OperLogAttribute.cs b/backend/BPA.MES.Base.Application/Filters/OperLogAttribute.cs new file mode 100644 index 0000000..779615b --- /dev/null +++ b/backend/BPA.MES.Base.Application/Filters/OperLogAttribute.cs @@ -0,0 +1,46 @@ +using Furion.EventBus; +using Furion.JsonSerialization; +using Microsoft.AspNetCore.Mvc.Filters; +using System.Diagnostics; +using System.Security.Claims; + +namespace BPA.MES.Base.Application +{ + /// + /// 名 称 :接口AOP + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/7/20 15:04:06 + /// 描 述 : + /// + public class OperLogAttribute : ActionFilterAttribute + { + public string _name; + public OperLogAttribute(string name) + { + _name = name; + } + /// + /// 执行操作前后 + /// + /// + /// + /// + public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) + { + // 获取 HttpContext 和 HttpRequest 对象 + var httpContext = context.HttpContext; + var httpRequest = httpContext.Request; + var sw = new Stopwatch(); + sw.Start(); + var actionContext = await next(); + sw.Stop(); + var userName = httpContext.User?.FindFirstValue(ClaimConst.CLAINM_NAME); + await MessageCenter.PublishAsync("ToDo:OperLog", new OperLogEntity() + { + Context = context.ActionArguments.Count < 1 ? string.Empty : JSON.Serialize(context.ActionArguments), + Name = $"[{userName}]{_name}", + Result = actionContext.Exception == null? "true" : EnhancedStackTrace.Current().ToString() + }); + } + } +} diff --git a/backend/BPA.MES.Base.Application/GlobalUsings.cs b/backend/BPA.MES.Base.Application/GlobalUsings.cs new file mode 100644 index 0000000..d3511cb --- /dev/null +++ b/backend/BPA.MES.Base.Application/GlobalUsings.cs @@ -0,0 +1,19 @@ +global using Furion; +global using Furion.DataEncryption; +global using Furion.DataValidation; +global using Furion.DependencyInjection; +global using Furion.DynamicApiController; +global using Furion.Extensions; +global using Furion.FriendlyException; +global using Furion.Logging; +global using Mapster; +global using Microsoft.AspNetCore.Authorization; +global using Microsoft.AspNetCore.Http; +global using Microsoft.AspNetCore.Mvc; +global using Microsoft.CodeAnalysis; +global using BPA.MES.Base.Core; +global using static BPA.MES.Base.Core.TreeExtensions; +global using System.ComponentModel.DataAnnotations; +global using BPA.MES.Base.Application.Entitys; +global using Furion.DataEncryption.Extensions; +global using SqlSugar; \ No newline at end of file diff --git a/backend/BPA.MES.Base.Application/MQTT/IMessage.cs b/backend/BPA.MES.Base.Application/MQTT/IMessage.cs new file mode 100644 index 0000000..f8f5d28 --- /dev/null +++ b/backend/BPA.MES.Base.Application/MQTT/IMessage.cs @@ -0,0 +1,21 @@ +namespace BPA.MES.Base.Application +{ + /// + /// 名 称 :MQTT消息基类 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/7/21 10:24:24 + /// 描 述 : + /// + public interface IMessage + { + /// + /// 消息ID + /// + public int MessageId { get; set; } + + /// + /// 消息版本 + /// + public Version MsgVersion { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/MQTT/MQTTService.cs b/backend/BPA.MES.Base.Application/MQTT/MQTTService.cs new file mode 100644 index 0000000..0f8776b --- /dev/null +++ b/backend/BPA.MES.Base.Application/MQTT/MQTTService.cs @@ -0,0 +1,145 @@ +using Furion.JsonSerialization; +using Furion.RemoteRequest.Extensions; +using Newtonsoft.Json; +using System.Text; + +namespace BPA.MES.Base.Application +{ + /// + /// 名 称 :MQTT通信库 + /// 创 建 人 :yangxiao + /// 创建时间 : 2022/11/18 15:38:40 + /// 描 述 : + /// + public class MQTTService : IMQTTService, ITransient, IDynamicApiController + { + private readonly ISqlSugarClient _dbContext; + ISysCacheService _sysCacheService; + public MQTTService(ISqlSugarClient db, ISysCacheService sysCacheService) + { + _dbContext = db; + _sysCacheService = sysCacheService; + } + public async Task GetMQTTConfig() + { + var entity = await _dbContext.Queryable().FirstAsync(); + if (entity != null) + { + MQTTConfig.Address = entity.Address; + MQTTConfig.Account = entity.Account; + MQTTConfig.Pwd = entity.Pwd; + await _sysCacheService.SetAsync("mqtt", entity); + } + } + /// + /// Mqtt通用服务 + /// + public async Task MqttPublish(MqttPublishDto input) + { + bool result = false; + MQTTInfoEntity mqttentity = new(); + mqttentity = await _sysCacheService.GetAsync("mqtt"); + if (mqttentity==null) + { + mqttentity = await _dbContext.Queryable().FirstAsync(); + await _sysCacheService.SetAsync("mqtt", mqttentity); + } + try + { + input.Payload.MessageId = input.MessageId; + input.Payload.MsgVersion = new Version(1, 0, 0, 0); + MsgPackage mp = new() + { + Message = input.Payload, + MessageLen = JSON.Serialize(input.Payload).Length + }; + //组装MQTT消息 + var tem = await $"http://{mqttentity.Address}{mqttentity.MsgPublishRoute}".SetHeaders(new + { + Authorization = "Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes($"{mqttentity.Account}:{mqttentity.Pwd}")) + }).SetBody(new + { + input.Topic, + payload = JsonConvert.SerializeObject(mp), + qos = 2, + retain = false, + clientid = "pztj_service" + }).PostAsStringAsync(); + var res = JSON.Deserialize(tem); + if (res.Code == 0 || res.Reason_code<100 || !string.IsNullOrEmpty(res.Id)) + { + result = true; + } + Console.WriteLine($"_____________________MQTT发消息:{JsonConvert.SerializeObject(mp)}"); + } + catch + { + + } + + return result; + } + [AllowAnonymous] + public async Task MqttTestPublish(string topic, string msg) + { + bool result = false; + var mqttentity = await _dbContext.Queryable().FirstAsync(); + string mqttAddress = mqttentity.Address; + try + { + //组装MQTT消息 + var tem = await $"http://{mqttAddress}/api/v5/publish".SetHeaders(new + { + Authorization = "Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes($"{mqttentity.Account}:{mqttentity.Pwd}")) + }).SetBody(new + { + topic, + payload = msg, + qos = 2, + retain = false, + clientid = "pztj_service" + }).PostAsStringAsync(); + var res = JSON.Deserialize(tem); + if (res.Code == 0 || res.Reason_code < 100 || !string.IsNullOrEmpty(res.Id)) + { + result = true; + } + } + catch + { + + } + return result; + } + + } + + public class MqttResult + { + /// + /// code + /// + public int Code { get; set; } + /// + /// reason_code + /// + public int Reason_code { get; set; } + /// + /// + /// + public string Id { get; set; } + } + + public class MqttPublishDto + { + public IMessage Payload { get; set; } + public string Topic { get; set; } + public int MessageId { get; set; } + } + public interface IMQTTService + { + Task MqttPublish(MqttPublishDto input); + + Task GetMQTTConfig(); + } +} diff --git a/backend/BPA.MES.Base.Application/MQTT/MessageID.cs b/backend/BPA.MES.Base.Application/MQTT/MessageID.cs new file mode 100644 index 0000000..e96980f --- /dev/null +++ b/backend/BPA.MES.Base.Application/MQTT/MessageID.cs @@ -0,0 +1,14 @@ +namespace BPA.MES.Base.Application +{ + public class MessageID + { + public const int DevcieControl = 1;//设备控制ID + public const int WorkOrderIssued = 2;//工单下发ID + public const int DeviceData = 3;//设备上报数据 + public const int TaskState = 4;//AGV任务状态上报 + public const int LoadAndUnload = 8;//AGV上下料上报 + public const int PowerId = 12;// 权限验证 + public const int StateChange = 13;//状态改变 + } +} + diff --git a/backend/BPA.MES.Base.Application/MQTT/MsgPackage.cs b/backend/BPA.MES.Base.Application/MQTT/MsgPackage.cs new file mode 100644 index 0000000..ed8e173 --- /dev/null +++ b/backend/BPA.MES.Base.Application/MQTT/MsgPackage.cs @@ -0,0 +1,18 @@ +using Newtonsoft.Json; + +namespace BPA.MES.Base.Application +{ + public class MsgPackage + { + /// + /// 消息内容 + /// + [JsonProperty(TypeNameHandling = TypeNameHandling.Auto)] + public IMessage Message { get; set; } + /// + /// 消息长度 + /// + public int MessageLen { get; set; } + + } +} diff --git a/backend/BPA.MES.Base.Application/MQTT/Topics.cs b/backend/BPA.MES.Base.Application/MQTT/Topics.cs new file mode 100644 index 0000000..5144bdc --- /dev/null +++ b/backend/BPA.MES.Base.Application/MQTT/Topics.cs @@ -0,0 +1,42 @@ +namespace BPA.MES.Base.Application +{ + /// + /// 名 称 : + /// 创 建 人 :yangxiao + /// 创建时间 : 2022/11/18 15:37:07 + /// 描 述 : + /// + public class Topics + { + /// + /// 设备控制主题,前端通过消息控制设备动作(客户端/前端 --> 设备) + /// + public const string DeviceControl = "BPAProline/Client/Device/Control"; + + /// + /// 工单推送主题,中控将创建的工单推送到对应的产线 (中控系统 --> 产线) + /// + public const string WorkOrderPush = "BPAPROLINE/MES/SERVER/WORKORDER/DOWN"; + + /// + /// 前端展示数据推送,数据服务将设备数据推送到前端界面展示 (数据中心服务 --> 客户端/前端) + /// + public const string DeviceDataPush = "BPAProline/DataServer/Client/Data"; + /// + /// 工单状态(信息系统 --> 中控系统) + /// + public const string STWorkState = "BPAProline/CentralControl/Proline/WorkState"; + + /// + /// 任务下发成功 回调 + /// + public const string ExecuteReplyTopic = "robotjob.report"; + + /// + /// 上下料回调 + /// + public const string LoadAndUnloadTopic = "rollerjob.upstreamrequest"; + + + } +} diff --git a/backend/BPA.MES.Base.Application/Services/AGVService/Dtos/AGVThirdPartyDto.cs b/backend/BPA.MES.Base.Application/Services/AGVService/Dtos/AGVThirdPartyDto.cs new file mode 100644 index 0000000..3ed7710 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/AGVService/Dtos/AGVThirdPartyDto.cs @@ -0,0 +1,473 @@ +using BPA.AGV; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BPA.MES.Base.Application.Services.AGVService.Dtos +{ + + public class Roller_JobRequest + { + public string Url { get; set; } + + [Required(ErrorMessage = "[{0}]不能为空")] + [MaxLength(64, ErrorMessage = "[{0}]不能超过64字符")] + public string AgvCode { get; set; } + + [Required(ErrorMessage = "[{0}]不能为空")] + [MaxLength(64, ErrorMessage = "[{0}]不能超过64字符")] + public string JobId { get; set; } + + [Required(ErrorMessage = "[{0}]不能为空")] + [MaxLength(64, ErrorMessage = "[{0}]不能超过64字符")] + public string MsgId { get; set; } + + public bool? Complete { get; set; } + } + + public class AGVExecuteReplyRequest + { + public AgvHeader Header { get; set; } + public AgvReplyBody Body { get; set; } + } + + public class AgvReplyBody + { + public AGVExecuteReplyDto Event { get; set; } + } + + + public class AGVExecuteReplyMQTT: IMessage + { + public AGVExecuteReplyDto Event { get; set; } + public int MessageId { get; set; } + public Version MsgVersion { get; set; } + } + + public class AGVLoadAndUnloadRequest + { + public AgvHeader Header { get; set; } + public AGVLoadAndUnloadBody Body { get; set; } + } + + public class AGVLoadAndUnloadBody + { + public AGVLoadAndUnloadDto Event { get; set; } + } + + public class AGVLoadAndUnloadMQTT : IMessage + { + public AGVLoadAndUnloadDto Event { get; set; } + public int MessageId { get; set; } + public Version MsgVersion { get; set; } + } + + public class AgvBody + { + public AgvHeader Header { get; set; } + public AgvRetrun Body { get; set; } + } + public class AgvHeader + { + public string RequestId { get; set; } + public string Timestamp { get; set; } + public string Version { get; set; } + } + public class AgvRetrun + { + public string Code { get; set; } + + public bool Success { get; set; } + + public string Message { get; set; } + + public object? Data { get; set; } + } + + /// + /// 任务完成回报Dto + /// + public class AGVExecuteReplyDto + { + /// + /// 上游系统任务号,全局唯一 + /// + public string robotJobId { get; set; } + + /// + /// 仓库编号 + /// + public long warehouseId { get; set; } + + /// + /// 任务快仓系统编号 + /// + public string jobId { get; set; } + + /// + /// 任务状态 + /// + public string state { get; set; } + + /// + /// 内部任务类型 + /// + public string jobType { get; set; } + + /// + /// 数据字段 + /// + public PointToPoint jobData { get; set; } + + } + + /// + /// 上下料交互请求DTO + /// + public class AGVLoadAndUnloadDto + { + /// + /// AGV编号 + /// + public string agvCode { get; set; } + + /// + /// 容器编号,如果一次上/下多个容器,则多个容器用英文逗号分隔 + /// + public string containerCode { get; set; } + + /// + /// 上游设备ID + /// + public long equipmentId { get; set; } + + /// + /// 上游设备ID,多个用英文逗号分隔 + /// + public string equipmentIds { get; set; } + + /// + /// 快仓任务编号 + /// + public string jobId { get; set; } + + /// + /// 消息ID + /// + public string msgId { get; set; } + + /// + /// 交互阶段LOAD:上料阶段 UNLOAD:下料阶段 + /// + public string command { get; set; } + + /// + /// 上游任务号 + /// + public string robotJobId { get; set; } + + } + + + /// + /// 货到货 + /// + public class GoodsToGoods + { + /// + /// AGV编号 + /// + public string agvCode { get; set; } + + /// + /// 容器编号 + /// + public string containerCode { get; set; } + + /// + /// 上料点位 + /// + public string startPointCode { get; set; } + + /// + /// 上料货位编号 + /// + public string startSlotCode { get; set; } + + /// + /// 下料点位 + /// + public string targetPointCode { get; set; } + + /// + /// 下料货位编号 + /// + public string targetSlotCode { get; set; } + + /// + /// 是否需要上料交互 + /// + public bool loadInteractive { get; set; } + } + + /// + /// 点到点 + /// + public class PointToPoint + { + /// + /// AGV编号 + /// + public string agvCode { get; set; } + + /// + /// 容器编号 + /// + public string containerCode { get; set; } + + /// + /// 上料点位 + /// + public string startPointCode { get; set; } + + /// + /// 下料点位 + /// + public string targetPointCode { get; set; } + + /// + /// 是否需要上料交互 + /// + public bool loadInteractive { get; set; } + } + + public enum AGVState + { + + //任务状态: + //1)货架/货位/点到点货架搬运任务枚举: + //LIFT_UP_DONE:顶升完成 + //MOVE_BEGIN:开始移动 + //PUT_DOWN_DONE:放下完成 + //DONE:任务完成 + //CANCEL:任务取消 + //ABNORMAL_CANCEL:任务异常取消 + //ABNORMAL_COMPLETED:任务异常完成 + //2)货位到货位/点到点辊筒料箱搬运任务枚举: + //ROLLER_LOAD_DOING:正在上料 + //ROLLER_LOAD_FINISH:上料完成 + //ROLLER_UNLOAD_DOING:正在下料 + //DONE:下料完成 + //ABNORMAL_CANCEL:任务异常取消 + //ABNORMAL_COMPLETED:任务异常完成 + //3)AGV移动任务枚举: + //DONE:任务完成 + //CANCEL:任务取消 + //ABNORMAL_CANCEL:任务异常取消 + //ABNORMAL_COMPLETED:任务异常完成 + //4) 纯料箱任务枚举: + //MOVE_BEGIN:开始移动(仅单插臂或单夹报,2.8.1后) + //ENTER_STATION:到站 + //DONE:任务完成 + //LOAD_COMPLETED:取料完成 + //UNLOAD_COMPLETED:放料完成 + //ABNORMAL_CANCEL:任务异常取消ABNORMAL_COMPLETED:任务异常完成 + //5) 小皮带任务枚举: + //DONE:任务完成 + //6) QuickPick任务枚举: + //ENTER_STATION:到站 + //DONE:任务完成 + //CANCEL:任务取消 + //LEAVE_STATION离站 + //ROLLBACK 回滚(有其他任务,当前任务可不执行) + + + /// + /// 顶升完成 + /// + LIFT_UP_DONE = 1, + + /// + /// 开始移动 + /// + MOVE_BEGIN = 2, + + /// + /// 放下完成 + /// + PUT_DOWN_DONE = 3, + + /// + /// 任务完成 + /// + DONE = 4, + + + /// + /// 任务取消 + /// + CANCEL = 5, + + /// + /// 任务异常取消 + /// + ABNORMAL_CANCEL = 6, + + /// + /// 任务异常完成 + /// + ABNORMAL_COMPLETED = 7 + + } + + public enum jobType + { + /// + /// 1) 辊筒货位到货位搬运 + /// + SLOT_ROLLER_MOVE = 1, + POINT_ROLLER_MOVE=2 + } + + public class KC_Response + { + public KC_Response() + { + Data = new(); + } + /// + /// 是否成功 + /// + public bool Success { get; set; } + /// + /// 状态码 + /// + public string Code { get; set; } + /// + /// 消息 + /// + public string Message { get; set; } + /// + /// 返回数据数组 + /// + public List Data { get; set; } + } + public class KC_Response_Data + { + /// + /// 状态码 + /// + public string Code { get; set; } + /// + /// 消息体 + /// + public string Message { get; set; } + /// + /// 任务编号 + /// + public string RobotJobId { get; set; } + } + /// + /// AGV请求 + /// + public class KC_ExecuteRequest + { + /// + /// 快仓api地址 + /// + public string Url { get; set; } + /// + /// 任务编码 + /// + public string RobotJobId { get; set; } + /// + /// 仓库编码 默认值1 + /// + public long WarehouseId { get; set; } = 1; + + public string RobotJobGroupId { get; set; } + + public int? Sequence { get; set; } + + public string RobotJobGroupNum { get; set; } + /// + /// 优先级 0-99 越高越先执行 + /// + public int? JobPriority { get; set; } + + public int? JobPriorityType { get; set; } + + public string Deadline { get; set; } + + public string AgvType { get; set; } + + public string AgvEndPoint { get; set; } + + public bool NeedOperation { get; set; } + + public string AgvCode { get; set; } + + public int? TaskCountDown { get; set; } = 0; + public string BusinessType { get; set; } + [Required(ErrorMessage = "[{0}]不能为空")] + [MaxLength(64, ErrorMessage = "[{0}]不能超过64字符")] + //任务类型 用来滚筒点对点 POINT_ROLLER_MOVE n8H7jX + public string JobType { get; set; } = "POINT_ROLLER_MOVE"; + [Required(ErrorMessage = "[{0}]不能为空")] + public KC_JobDataRequest? JobData { get; set; } + } + /// + /// 任务下发起止点信息 + /// + public class KC_JobDataRequest + { + /// + /// 用户自定义信息编号 + /// + public string ContainerCode { get; set; } + /// + /// 起点点位 + /// + [Required(ErrorMessage = "[{0}]不能为空")] + [MaxLength(64, ErrorMessage = "[{0}]不能超过64字符")] + public string StartPoint { get; set; } + /// + /// 终点点位 + /// + [Required(ErrorMessage = "[{0}]不能为空")] + [MaxLength(64, ErrorMessage = "[{0}]不能超过64字符")] + public string EndPoint { get; set; } + /// + /// 上料方式 自动/人工 + /// + public bool? AutoLoad { get; set; } + /// + /// 上料交互方式 //接口对接 false + /// + public bool? EnableIOLoad { get; set; } = false; + /// + /// 下料方式 true自动/false人工 + /// + public bool? AutoUnload { get; set; } + /// + /// 接口对接 false + /// + public bool? EnableIOUnload { get; set; } = false; + /// + /// 起点设备ID + /// + public long LoadEquipmentId { get; set; } + /// + /// 目标设备ID + /// + public long UnloadEquipmentId { get; set; } + + public long LoadInteractive { get; set; } + + public long LoadHeight { get; set; } + + public long UnloadHeight { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Services/AGVService/Dtos/AgvLineDto.cs b/backend/BPA.MES.Base.Application/Services/AGVService/Dtos/AgvLineDto.cs new file mode 100644 index 0000000..2539232 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/AGVService/Dtos/AgvLineDto.cs @@ -0,0 +1,95 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 : + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/8/7 9:59:47 + /// 描 述 : + /// + public class AgvLineDto + { + /// + /// 自定义编码 + /// + public string Code { get; set; } + /// + /// 线路名称 + /// + public string Name { get; set; } + /// + /// 开始点位 + /// + public string StartPointId { get; set; } + /// + /// 结束点位 + /// + public string EndPointId { get; set; } + /// + /// 描述 + /// + public string Description { get; set; } + } + /// + /// 增加 + /// + public class AgvLineAddInput : AgvLineDto + { + + } + /// + /// 修改 + /// + public class AgvLineUpdateInput : AgvLineDto + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 刪除 + /// + public class AgvLineDelInput + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 普通查询条件 + /// + public class AgvLineQueryInput + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 分页查询条件 + /// + public class AgvLineQueryPageInput : RequestPage + { + + /// + /// 名称 + /// + public string Name { get; set; } + /// + /// 编码 + /// + public string Code { get; set; } + } + /// + /// 输出 + /// + public class AgvLineOutput : AgvLineDto + { + /// + /// 主键 + /// + public string Id { get; set; } + //下面增加多的数据 + } +} \ No newline at end of file diff --git a/backend/BPA.MES.Base.Application/Services/AGVService/Dtos/AgvPointDto.cs b/backend/BPA.MES.Base.Application/Services/AGVService/Dtos/AgvPointDto.cs new file mode 100644 index 0000000..1d3299d --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/AGVService/Dtos/AgvPointDto.cs @@ -0,0 +1,83 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 : + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/8/7 10:00:01 + /// 描 述 : + /// + public class AgvPointDto + { + /// + /// 点位名称 + /// + public string Name { get; set; } + /// + /// 点位编码 + /// + public string Code { get; set; } + } + /// + /// 增加 + /// + public class AgvPointAddInput : AgvPointDto + { + + } + /// + /// 修改 + /// + public class AgvPointUpdateInput : AgvPointDto + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 刪除 + /// + public class AgvPointDelInput + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 普通查询条件 + /// + public class AgvPointQueryInput + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 分页查询条件 + /// + public class AgvPointQueryPageInput : RequestPage + { + + /// + /// 名称 + /// + public string Name { get; set; } + /// + /// 编码 + /// + public string Code { get; set; } + } + /// + /// 输出 + /// + public class AgvPointOutput : AgvPointDto + { + /// + /// 主键 + /// + public string Id { get; set; } + //下面增加多的数据 + } +} \ No newline at end of file diff --git a/backend/BPA.MES.Base.Application/Services/AGVService/Services/AGVThirdPartyService.cs b/backend/BPA.MES.Base.Application/Services/AGVService/Services/AGVThirdPartyService.cs new file mode 100644 index 0000000..7777e04 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/AGVService/Services/AGVThirdPartyService.cs @@ -0,0 +1,170 @@ +using BPA.AGV; +using BPA.MES.Base.Application.Services.AGVService.Dtos; +using Furion.EventBus; +using Furion.JsonSerialization; +using Furion.RemoteRequest.Extensions; + +namespace BPA.MES.Base.Application.Services +{ + /// + /// AGV第三方api + /// + [AllowAnonymous, NonUnify] + [ApiDescriptionSettings("AGV管理", Name = "AgvThirdParty", Tag = "AGV第三方api", KeepName = true, SplitCamelCase = true, KeepVerb = true)] + public class AGVThirdPartyService : IAGVThirdPartyService, ITransient, IDynamicApiController + { + private readonly AGVHandler _aGVHandler; + private readonly IMQTTService _MQTTService; + public AGVThirdPartyService(AGVHandler aGVHandler, IMQTTService MQTTService) + { + _aGVHandler = aGVHandler; + _MQTTService = MQTTService; + } + + /// + /// 下发任务 + /// + /// + /// + [HttpPost] + public async Task Execute(KC_ExecuteRequest input) + { + List cExecuteRequests = new(); + if (string.IsNullOrEmpty(input.RobotJobId)) + { + throw Oops.Bah("任务编号不能为空"); + } + if (input.JobData != null) + input = new KC_ExecuteRequest + { + Url = string.IsNullOrEmpty(input.Url) ? App.GetConfig("AGVUrl")+"/api/quicktron/wcs/standardized.robot.job.submit": input.Url + "/api/quicktron/wcs/standardized.robot.job.submit", + RobotJobId = input.RobotJobId,//任务号 + WarehouseId = input.WarehouseId,//仓库编码 默认值1 + JobPriority = input.JobPriority, //优先级 0-99 越高越先执行 + JobPriorityType = input.JobPriorityType, //优先级类型 0 普通和1 强制. + JobType = input.JobType,//任务类型 用来滚筒点对点 POINT_ROLLER_MOVE n8H7jX + JobData = new KC_JobDataRequest + { + StartPoint = input.JobData.StartPoint, //起点 + EndPoint = input.JobData.EndPoint,//终点 + ContainerCode = input.JobData.ContainerCode,//桶号 + AutoLoad = input.JobData.AutoLoad,//上料方式 自动/人工 + EnableIOLoad = input.JobData.EnableIOLoad,//上料交互方式 //接口对接 false + AutoUnload = input.JobData.AutoUnload,//下料方式 true自动/false人工 + EnableIOUnload = input.JobData.EnableIOUnload,//接口对接 false + LoadEquipmentId = input.JobData.LoadEquipmentId,//起点设备ID + UnloadEquipmentId = input.JobData.UnloadEquipmentId,//目标设备ID + } + }; + cExecuteRequests.Add(input); + try + { + Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}:{input.RobotJobId}接收到下发任务!"); + var res = await input.Url.SetBody(cExecuteRequests).PostAsStringAsync(); + return JSON.Deserialize(res); + } + catch (Exception ex) + { + throw Oops.Bah(ex.Message); + } + } + /// + /// 取消任务 + /// + /// + /// + [HttpPost] + public async Task Cancel(KCCancelRequest kCCancelRequest) + { + kCCancelRequest.Url = string.IsNullOrEmpty(kCCancelRequest.Url) ? App.GetConfig("AGVUrl") + "/api/quicktron/wcs/standardized.robot.job.cancel" : kCCancelRequest.Url + "/api/quicktron/wcs/standardized.robot.job.cancel"; + return await _aGVHandler.CancelAsync(kCCancelRequest); + } + /// + /// 上下料反馈给AGV接口 + /// + /// + /// + public async Task RollerJobExecute(Roller_JobRequest input) + { + //http://[IP:Port]/api/quicktron/wcs/standardized.roller.job.upstream.response + input.Url = string.IsNullOrEmpty(input.Url) ? App.GetConfig("AGVUrl") + "/api/quicktron/wcs/standardized.roller.job.upstream.response": input.Url+ "/api/quicktron/wcs/standardized.roller.job.upstream.response"; + try + { + var res = await input.Url.SetBody(input).PostAsStringAsync(); + Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}:{input.JobId}上下料反馈给AGV接口!{res}"); + return JSON.Deserialize(res); + } + catch (Exception ex) + { + return new RollerJobResponse() { Success = false }; + } + } + /// + /// 任务反馈(暴露给AGV厂商) + /// + /// + /// + [HttpPost] + public async Task ExecuteReply(AGVExecuteReplyRequest input) + { + try + { + var data = new AGVExecuteReplyMQTT() + { + Event = input.Body.Event, + }; + bool res = await _MQTTService.MqttPublish(new MqttPublishDto(){ Payload= data, Topic = Topics.ExecuteReplyTopic, MessageId = MessageID.TaskState }); + Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}:接收到AGV反馈请求!", res.ToString()); + AgvBody agvBody = new() + { + Header = input.Header, + Body = new AgvRetrun { Code = "SUCCESS", Success = res, Message = "SUCCESS", Data = null } + }; + Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}:AGV反馈消息!{JSON.Serialize(agvBody)}"); + return agvBody; + } + catch (Exception ex) + { + AgvBody agvBody = new() + { + Header = input.Header, + Body = new AgvRetrun { Code = "SUCCESS", Success = false, Message = ex.Message, Data = null } + }; + return agvBody; + } + } + /// + /// AGV上下料交互请求 (暴露给AGV厂商) + /// + /// + /// + [HttpPost, AGV] + public async Task LoadAndUnload(AGVLoadAndUnloadRequest input) + { + try + { + var data = new AGVLoadAndUnloadMQTT() + { + Event = input.Body.Event, + }; + bool res = await _MQTTService.MqttPublish(new MqttPublishDto() { Payload= data, Topic = Topics.LoadAndUnloadTopic, MessageId = MessageID.LoadAndUnload }); + Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}:接收到AGV上下料交互请求!{res.ToString()}"); + AgvBody agvBody = new() + { + Header = input.Header, + Body = new AgvRetrun { Code = "SUCCESS", Success = res, Message = "SUCCESS", Data = null } + }; + return agvBody; + } + catch (Exception ex) + { + AgvBody agvBody = new() + { + Header = input.Header, + Body = new AgvRetrun { Code = "SUCCESS", Success = false, Message = ex.Message, Data = null } + }; + return agvBody; + } + } + } +} diff --git a/backend/BPA.MES.Base.Application/Services/AGVService/Services/AgvLineService.cs b/backend/BPA.MES.Base.Application/Services/AGVService/Services/AgvLineService.cs new file mode 100644 index 0000000..7a53431 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/AGVService/Services/AgvLineService.cs @@ -0,0 +1,115 @@ +namespace BPA.MES.Base.Application.Services.AGVService.Services +{ + /// + /// 名 称 :AGV线路管理 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/8/7 10:03:21 + /// 描 述 : + /// + [ApiDescriptionSettings("AGV管理", Name = "AgvLine", Tag = "AGV线路", KeepName = true, SplitCamelCase = true, KeepVerb = true)] + public class AgvLineService : IAgvLineService, ITransient, IDynamicApiController + { + private readonly ISqlSugarClient _dbContext; + public AgvLineService(ISqlSugarClient db) + { + _dbContext = db; + } + /// + /// 增加 + /// + /// + /// + [HttpPost] + public async Task Add(AgvLineAddInput input) + { + var r_entity = await _dbContext.Queryable().FirstAsync(x => x.Name == input.Name); + if (r_entity != null) + { + throw Oops.Bah("名称已存在!"); + } + AgvLineEntity entity = input.Adapt(); + return await _dbContext.Insertable(entity).IgnoreColumns(ignoreNullColumn: true).ExecuteCommandIdentityIntoEntityAsync(); + } + /// + /// 删除 + /// + /// + /// + /// + [HttpPost] + public async Task Del(AgvLineDelInput input) + { + var res = await _dbContext.Deleteable().Where(x => x.Id == input.Id).ExecuteCommandHasChangeAsync(); + return res; + } + /// + /// 详情 + /// + /// + /// + /// + [HttpGet] + public async Task Detail(string Id) + { + var entity = await _dbContext.Queryable().FirstAsync(x => x.Id == Id); + AgvLineOutput output = entity.Adapt(); + return output; + } + /// + /// 列表 + /// + /// + /// + [HttpPost] + public async Task> List(AgvLineQueryInput input) + { + var entity = await _dbContext.Queryable().ToListAsync(); + List output = entity.Adapt>(); + return output; + } + /// + /// 分页 + /// + /// + /// + [HttpPost] + public async Task> PagedList(AgvLineQueryPageInput input) + { + var entity = await _dbContext.Queryable() + .WhereIF(!string.IsNullOrEmpty(input.Name), x => x.Name.Contains(input.Name)) + .WhereIF(!string.IsNullOrEmpty(input.Code), x => x.Code.Contains(input.Code)) + .ToPagedListAsync(input.PageIndex, input.PageSize); + SqlSugarPagedList output = entity.Adapt>(); + return output; + } + /// + /// 下拉 + /// + /// + /// + [HttpGet] + public async Task SelectList() + { + var entity = await _dbContext.Queryable().Select(x => new + { + key = x.Id, + value = x.Name + }).ToListAsync(); + return entity; + } + /// + /// 更新 + /// + /// + /// + /// + [HttpPost] + public async Task Update(AgvLineUpdateInput input) + { + var entity = await _dbContext.Queryable().Where(x => x.Id == input.Id).FirstAsync(); + entity = input.Adapt(); + var res = await _dbContext.Updateable(entity).IgnoreColumns(true).ExecuteCommandHasChangeAsync(); + return res; + } + } +} \ No newline at end of file diff --git a/backend/BPA.MES.Base.Application/Services/AGVService/Services/AgvPointService.cs b/backend/BPA.MES.Base.Application/Services/AGVService/Services/AgvPointService.cs new file mode 100644 index 0000000..5975935 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/AGVService/Services/AgvPointService.cs @@ -0,0 +1,115 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :AGV点位管理 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/8/7 10:03:37 + /// 描 述 : + /// + [ApiDescriptionSettings("AGV管理", Name = "AgvPoint", Tag = "AGV点位", KeepName = true, SplitCamelCase = true, KeepVerb = true)] + public class AgvPointService : IAgvPointService, ITransient, IDynamicApiController + { + private readonly ISqlSugarClient _dbContext; + public AgvPointService(ISqlSugarClient db) + { + _dbContext = db; + } + /// + /// 增加 + /// + /// + /// + [HttpPost] + public async Task Add(AgvPointAddInput input) + { + var r_entity = await _dbContext.Queryable().FirstAsync(x => x.Name == input.Name); + if (r_entity != null) + { + throw Oops.Bah("名称已存在!"); + } + AgvPointEntity entity = input.Adapt(); + return await _dbContext.Insertable(entity).IgnoreColumns(ignoreNullColumn: true).ExecuteCommandIdentityIntoEntityAsync(); + } + /// + /// 删除 + /// + /// + /// + /// + [HttpPost] + public async Task Del(AgvPointDelInput input) + { + var res = await _dbContext.Deleteable().Where(x => x.Id == input.Id).ExecuteCommandHasChangeAsync(); + return res; + } + /// + /// 详情 + /// + /// + /// + /// + [HttpGet] + public async Task Detail(string Id) + { + var entity = await _dbContext.Queryable().FirstAsync(x => x.Id == Id); + AgvPointOutput output = entity.Adapt(); + return output; + } + /// + /// 列表 + /// + /// + /// + [HttpPost] + public async Task> List(AgvPointQueryInput input) + { + var entity = await _dbContext.Queryable().ToListAsync(); + List output = entity.Adapt>(); + return output; + } + /// + /// 分页 + /// + /// + /// + [HttpPost] + public async Task> PagedList(AgvPointQueryPageInput input) + { + var entity = await _dbContext.Queryable() + .WhereIF(!string.IsNullOrEmpty(input.Name), x => x.Name.Contains(input.Name)) + .WhereIF(!string.IsNullOrEmpty(input.Code), x => x.Code.Contains(input.Code)) + .ToPagedListAsync(input.PageIndex, input.PageSize); + SqlSugarPagedList output = entity.Adapt>(); + return output; + } + /// + /// 下拉 + /// + /// + /// + [HttpGet] + public async Task SelectList() + { + var entity = await _dbContext.Queryable().Select(x => new + { + key = x.Id, + value = x.Name + }).ToListAsync(); + return entity; + } + /// + /// 更新 + /// + /// + /// + /// + [HttpPost] + public async Task Update(AgvPointUpdateInput input) + { + var entity = await _dbContext.Queryable().Where(x => x.Id == input.Id).FirstAsync(); + entity = input.Adapt(); + var res = await _dbContext.Updateable(entity).IgnoreColumns(true).ExecuteCommandHasChangeAsync(); + return res; + } + } +} \ No newline at end of file diff --git a/backend/BPA.MES.Base.Application/Services/AGVService/Services/IAGVThirdPartyService.cs b/backend/BPA.MES.Base.Application/Services/AGVService/Services/IAGVThirdPartyService.cs new file mode 100644 index 0000000..4849af8 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/AGVService/Services/IAGVThirdPartyService.cs @@ -0,0 +1,40 @@ +using BPA.AGV; +using BPA.MES.Base.Application.Services.AGVService.Dtos; + +namespace BPA.MES.Base.Application.Services +{ + public interface IAGVThirdPartyService + { + + /// + /// 下发任务 + /// + /// + /// + Task Execute(KC_ExecuteRequest input); + /// + /// 取消任务 + /// + /// + /// + Task Cancel(KCCancelRequest kCCancelRequest); + /// + /// 任务回调 + /// + /// + /// + Task ExecuteReply(AGVExecuteReplyRequest input); + /// + /// AGV上下料交互请求 + /// + /// + /// + Task LoadAndUnload(AGVLoadAndUnloadRequest input); + /// + /// 上下料反馈给AGV接口 + /// + /// + /// + Task RollerJobExecute(Roller_JobRequest input); + } +} diff --git a/backend/BPA.MES.Base.Application/Services/AGVService/Services/IAgvLineService.cs b/backend/BPA.MES.Base.Application/Services/AGVService/Services/IAgvLineService.cs new file mode 100644 index 0000000..1065d50 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/AGVService/Services/IAgvLineService.cs @@ -0,0 +1,43 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 : + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/8/7 10:02:54 + /// 描 述 : + /// + public interface IAgvLineService + { + /// + /// 增加 + /// + /// + Task Add(AgvLineAddInput input); + /// + /// 移除 + /// + /// + Task Del(AgvLineDelInput input); + /// + /// 更新 + /// + /// + Task Update(AgvLineUpdateInput input); + /// + /// 不分页列表 + /// + /// + Task> List(AgvLineQueryInput input); + /// + /// 分页列表 + /// + /// + Task> PagedList(AgvLineQueryPageInput input); + /// + /// 查询单条 + /// + /// + /// + Task Detail(string Id); + } +} diff --git a/backend/BPA.MES.Base.Application/Services/AGVService/Services/IAgvPointService.cs b/backend/BPA.MES.Base.Application/Services/AGVService/Services/IAgvPointService.cs new file mode 100644 index 0000000..353cbeb --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/AGVService/Services/IAgvPointService.cs @@ -0,0 +1,43 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :AVG点位 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/8/7 10:03:06 + /// 描 述 : + /// + public interface IAgvPointService + { + /// + /// 增加 + /// + /// + Task Add(AgvPointAddInput input); + /// + /// 移除 + /// + /// + Task Del(AgvPointDelInput input); + /// + /// 更新 + /// + /// + Task Update(AgvPointUpdateInput input); + /// + /// 不分页列表 + /// + /// + Task> List(AgvPointQueryInput input); + /// + /// 分页列表 + /// + /// + Task> PagedList(AgvPointQueryPageInput input); + /// + /// 查询单条 + /// + /// + /// + Task Detail(string Id); + } +} diff --git a/backend/BPA.MES.Base.Application/Services/BaseService.cs b/backend/BPA.MES.Base.Application/Services/BaseService.cs new file mode 100644 index 0000000..7f8fc14 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/BaseService.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 : + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/7/17 16:13:10 + /// 描 述 : + /// + public class BaseService: ITransient, IDynamicApiController + { + private readonly ISqlSugarClient _dbContext; + public BaseService(ISqlSugarClient db) + { + _dbContext = db; + } + /// + /// 初始化数据库 + /// + /// + public string CreateDB() + { + var types = Assembly.Load("BPA.MES.Base.Application").GetTypes() + .Where(x => x.GetCustomAttribute() != null + && x.Namespace == "BPA.MES.Base.Application.Entitys").ToArray(); + _dbContext.CodeFirst.InitTables(types); + return "成功"; + } + /// + /// 测试 + /// + [AllowAnonymous] + public void Test() + { + //Type personType = Type.GetType("BPA.MES.Base.Application, DictDataAddInput"); + //object person = Activator.CreateInstance(personType); + Type type = Type.GetType("BPA.MES.Base.Application.Services.DictService.Dtos"); + string fullName = "BPA.MES.Base.Application.Services.DictDataAddInput"; + Type? instanceClass = Assembly.Load("BPA.MES.Base.Application").GetType(fullName); + var myInstance = instanceClass?.Assembly.CreateInstance(fullName); + + } + } +} diff --git a/backend/BPA.MES.Base.Application/Services/BucketInfoService/Dtos/BucketInfoDto.cs b/backend/BPA.MES.Base.Application/Services/BucketInfoService/Dtos/BucketInfoDto.cs new file mode 100644 index 0000000..c3da2f5 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/BucketInfoService/Dtos/BucketInfoDto.cs @@ -0,0 +1,75 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 : + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/7/17 15:43:00 + /// 描 述 : + /// + public class BucketInfoDto + { + /// + /// 桶名称 + /// + public string Name { get; set; } + /// + /// 桶编号 + /// + public string Code { get; set; } + } + /// + /// 增加 + /// + public class BucketInfoAddInput : BucketInfoDto + { + + } + /// + /// 更新 + /// + public class BucketInfoUpdateInput : BucketInfoDto + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 删除 + /// + public class BucketInfoDelInput + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 分页 + /// + public class BucketInfoQueryPageInput : RequestPage + { + /// + /// 名称 + /// + public string Name { get; set; } + /// + /// 编码 + /// + public string Code { get; set; } + } + /// + /// 输出 + /// + public class BucketInfoOutput : BucketInfoDto + { + /// + /// 主键 + /// + public string Id { get; set; } + /// + /// 当前原料名称 + /// + public string MaterialName { get; set; } + } +} \ No newline at end of file diff --git a/backend/BPA.MES.Base.Application/Services/BucketInfoService/Dtos/BucketMaterialsRecordDto.cs b/backend/BPA.MES.Base.Application/Services/BucketInfoService/Dtos/BucketMaterialsRecordDto.cs new file mode 100644 index 0000000..7482a75 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/BucketInfoService/Dtos/BucketMaterialsRecordDto.cs @@ -0,0 +1,135 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 : + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/7/17 17:29:52 + /// 描 述 : + /// + public class BucketMaterialsRecordDto + { + /// + /// 桶Id + /// + public string BucketId { get; set; } + /// + /// 物料Id + /// + public string MaterialId { get; set; } + /// + /// 添加时间 + /// + public DateTime? CreateTime { get; set; } + /// + /// 物料重量 + /// + public string Weight { get; set; } + /// + /// 工单Id + /// + public string WorkId { get; set; } + } + public class BucketMaterialsRecordAddInput : BucketMaterialsRecordDto + { + + } + /// + /// 更新 + /// + public class BucketMaterialsRecordUpdateInput : BucketMaterialsRecordDto + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 删除 + /// + public class BucketMaterialsRecordDelInput + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 不分页 + /// + public class BucketMaterialsRecordQueryInput + { + /// + /// 工单Id + /// + public string WorkId { get; set; } + /// + /// 桶Id + /// + public string BucketId { get; set; } + /// + /// 桶编号 + /// + public string BucketCode { get; set; } + } + /// + /// 分页 + /// + public class BucketMaterialsRecordQueryPageInput : RequestPage + { + /// + /// 名称 + /// + public string Name { get; set; } + /// + /// 编码 + /// + public string Code { get; set; } + /// + /// 桶Id + /// + public string BucketId { get; set; } + } + + /// + /// 清空桶 + /// + public class BucketClearInput + { + public string BucketId { get; set; } + } + + /// + /// 输出 + /// + public class BucketMaterialsRecordOutput : BucketMaterialsRecordDto + { + /// + /// 主键 + /// + public string Id { get; set; } + /// + /// 原料名称 + /// + public string MaterialName { get; set; } + /// + /// 桶名称 + /// + public string BucketName { get; set; } + /// + /// 工单名称 + /// + public string WorkName { get; set; } + /// + /// 桶编码 + /// + public string BucketCode { get; set; } + /// + /// 计划重量 + /// + public string SchemeWeight { get; set; } + /// + /// 第几锅 + /// + public string PotNum { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Services/BucketInfoService/Services/BucketInfoService.cs b/backend/BPA.MES.Base.Application/Services/BucketInfoService/Services/BucketInfoService.cs new file mode 100644 index 0000000..b75c69b --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/BucketInfoService/Services/BucketInfoService.cs @@ -0,0 +1,168 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :桶服务 + /// 创 建 人 :yangxiao + /// 创建时间 :2023/3/2 16:11:04 + /// 描 述 :基础数据管理 + /// + [ApiDescriptionSettings("基础数据管理", Order = 3, Tag = "桶服务", Name = "BucketInfo", KeepName = true, SplitCamelCase = true, KeepVerb = true)] + public class BucketInfoService : IBucketInfoService, ITransient, IDynamicApiController + { + private readonly ISqlSugarClient _dbContext; + public BucketInfoService(ISqlSugarClient db) + { + _dbContext = db; + } + /// + /// 增加 + /// + /// + /// + [HttpPost] + public async Task Add(BucketInfoAddInput input) + { + var r_entity = await _dbContext.Queryable().FirstAsync(x => x.Name == input.Name || x.Code == input.Code); + if (r_entity != null) + { + throw Oops.Bah("名称已存在!"); + } + Pztj_BucketInfoEntity entity = input.Adapt(); + return await _dbContext.Insertable(entity).IgnoreColumns(ignoreNullColumn: true).ExecuteCommandIdentityIntoEntityAsync(); + } + /// + /// 新增并返回 + /// + /// + /// + [HttpPost] + public async Task AddRetrun(BucketInfoAddInput input) + { + var r_entity = await _dbContext.Queryable().FirstAsync(x => x.Name == input.Name || x.Code == input.Code); + if (r_entity != null) + { + throw Oops.Bah("名称已存在!"); + } + Pztj_BucketInfoEntity entity = input.Adapt(); + var res = await _dbContext.Insertable(entity).IgnoreColumns(ignoreNullColumn: true).ExecuteCommandIdentityIntoEntityAsync(); + if (!res) + { + throw Oops.Bah("新增桶失败!"); + } + return entity; + } + /// + /// 删除 + /// + /// + /// + /// + [HttpPost] + public async Task Del(BucketInfoDelInput input) + { + var res = await _dbContext.Deleteable().Where(x => x.Id == input.Id).ExecuteCommandHasChangeAsync(); + return res; + } + /// + /// 详情 + /// + /// + /// + /// + [HttpGet] + public async Task Detail(string Id) + { + var entity = await _dbContext.Queryable().FirstAsync(x => x.Id == Id); + BucketInfoOutput output = entity.Adapt(); + return output; + } + /// + /// 列表 + /// + /// + /// + [HttpGet] + public async Task> List() + { + var entity = await _dbContext.Queryable().ToListAsync(); + List output = entity.Adapt>(); + return output; + } + /// + /// 分页 + /// + /// + /// + [HttpPost] + public async Task> PagedList(BucketInfoQueryPageInput input) + { + var entity = await _dbContext.Queryable() + .LeftJoin((a,b)=>a.Id==b.BucketId && b.Id == SqlFunc.Subqueryable().Where(s => s.BucketId == a.Id).OrderByDesc(s => s.CreateTime).Select(s => s.Id)) + .LeftJoin((a,b,c)=>b.MaterialId==c.Id) + .Select((a,b,c)=>new BucketInfoOutput + { + Id = a.Id.SelectAll(), + MaterialName = c.Name + }) + .ToPagedListAsync(input.PageIndex, input.PageSize); + SqlSugarPagedList output = entity.Adapt>(); + return output; + } + + + + + /// + /// 下拉 + /// + /// + /// + [HttpGet] + public async Task SelectList() + { + var entity = await _dbContext.Queryable().Select(x => new + { + key = x.Id, + value = x.Name + }).ToListAsync(); + return entity; + } + /// + /// 更新 + /// + /// + /// + /// + [HttpPost] + public async Task Update(BucketInfoUpdateInput input) + { + var isExit =await _dbContext.Queryable().Where(x => x.Id != input.Id && (x.Name == input.Name || x.Code == input.Code)).FirstAsync(); + if (isExit != null) + { + throw Oops.Bah("名称或编码已存在!"); + } + Pztj_BucketInfoEntity entity = input.Adapt(); + var res = await _dbContext.Updateable(entity).IgnoreColumns(true).ExecuteCommandHasChangeAsync(); + return res; + } + ///// + ///// 根据桶Id查询记录 + ///// + ///// + ///// + //public async Task RecordList(string bucketId) + //{ + // var entity = await _dbContext.Queryable() + // .LeftJoin((a, b) => a.MaterialId == b.Id) + // .Select((a, b) => new BucketMaterialsRecordOutput + // { + // Id = a.Id.SelectAll(), + // MaterialName = b.Name + // }) + // .ToListAsync(); + // SqlSugarPagedList output = entity.Adapt>(); + // return output; + //} + } +} + diff --git a/backend/BPA.MES.Base.Application/Services/BucketInfoService/Services/BucketMaterialsRecordServcie.cs b/backend/BPA.MES.Base.Application/Services/BucketInfoService/Services/BucketMaterialsRecordServcie.cs new file mode 100644 index 0000000..ed1ce37 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/BucketInfoService/Services/BucketMaterialsRecordServcie.cs @@ -0,0 +1,140 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :桶记录 + /// 创 建 人 :yangxiao + /// 创建时间 :2023/3/2 16:11:04 + /// 描 述 :基础数据管理 + /// + [ApiDescriptionSettings("基础数据管理", Order = 3, Tag = "桶服务", Name = "BucketMaterialsRecord", KeepName = true, SplitCamelCase = true, KeepVerb = true)] + public class BucketMaterialsRecordServcie : IBucketMaterialsRecordService, ITransient, IDynamicApiController + { + private readonly ISqlSugarClient _dbContext; + public BucketMaterialsRecordServcie(ISqlSugarClient db) + { + _dbContext = db; + } + /// + /// 增加 + /// + /// + /// + [HttpPost] + public async Task Add(BucketMaterialsRecordAddInput input) + { + Pztj_BucketMaterialsRecordEntity entity = input.Adapt(); + var work_entity =await _dbContext.Queryable().FirstAsync(x => x.Id == input.MaterialId); + if (work_entity==null) + { + throw Oops.Bah("没有找到此物料信息!"); + } + entity.WorkId = work_entity.WorkId; + return await _dbContext.Insertable(entity).IgnoreColumns(ignoreNullColumn: true).ExecuteCommandIdentityIntoEntityAsync(); + } + /// + /// 删除 + /// + /// + /// + /// + [HttpPost] + public async Task Del(BucketMaterialsRecordDelInput input) + { + var res = await _dbContext.Deleteable().Where(x => x.Id == input.Id).ExecuteCommandHasChangeAsync(); + return res; + } + /// + /// 详情 + /// + /// + /// + /// + [HttpGet] + public async Task Detail(string Id) + { + var entity = await _dbContext.Queryable().FirstAsync(x => x.Id == Id); + BucketMaterialsRecordOutput output = entity.Adapt(); + return output; + } + /// + /// 列表 + /// + /// + /// + [HttpPost] + public async Task> List(BucketMaterialsRecordQueryInput input) + { + var output = await _dbContext.Queryable() + .LeftJoin((a, b) => a.MaterialId == b.Id) + .LeftJoin((a, b, c) => a.BucketId == c.Id) + .LeftJoin((a,b,c,d)=>b.WorkId==d.Id) + .WhereIF(!string.IsNullOrEmpty(input.BucketId), (a, b, c) => a.BucketId == input.BucketId) + .WhereIF(!string.IsNullOrEmpty(input.WorkId), (a, b, c) => b.WorkId == b.WorkId) + .WhereIF(!string.IsNullOrEmpty(input.BucketCode),(a,b,c)=>c.Code==input.BucketCode) + .Select((a, b, c, d) => new BucketMaterialsRecordOutput + { + Id = a.Id, + MaterialId = a.MaterialId, + BucketId = a.BucketId, + Weight = a.Weight, + CreateTime = a.CreateTime, + SchemeWeight = b.Weight, + WorkId = d.Id, + MaterialName = b.MaterialName, + BucketName = c.Name, + WorkName = b.RecipeName, + PotNum = b.PotNum, + BucketCode = c.Code + }) + .ToListAsync(); + return output; + } + /// + /// 分页 + /// + /// + /// + [HttpPost] + public async Task> PagedList(BucketMaterialsRecordQueryPageInput input) + { + var entity = await _dbContext.Queryable() + .LeftJoin((a,b)=>a.BucketId==b.Id) + .LeftJoin((a,b,c)=>a.MaterialId==c.Id) + .WhereIF(!string.IsNullOrEmpty(input.BucketId),(a,b,c)=>a.BucketId==input.BucketId) + .OrderByDescending((a,b,c)=>a.CreateTime) + .Select((a,b,c)=>new BucketMaterialsRecordOutput + { + Id = a.Id.SelectAll(), + MaterialName = c.Name, + BucketName = b.Name + }) + .ToPagedListAsync(input.PageIndex, input.PageSize); + SqlSugarPagedList output = entity.Adapt>(); + return output; + } + /// + /// 更新 + /// + /// + /// + /// + [HttpPost] + public async Task Update(BucketMaterialsRecordUpdateInput input) + { + Pztj_BucketMaterialsRecordEntity entity = input.Adapt(); + var res = await _dbContext.Updateable(entity).IgnoreColumns(true).ExecuteCommandHasChangeAsync(); + return res; + } + /// + /// 清空桶 + /// + /// + /// + [HttpPost] + public async Task Clear(BucketClearInput input) + { + var res = await _dbContext.Deleteable().Where(x => x.BucketId == input.BucketId).ExecuteCommandHasChangeAsync(); + return res; + } + } +} diff --git a/backend/BPA.MES.Base.Application/Services/BucketInfoService/Services/IBucketInfoService.cs b/backend/BPA.MES.Base.Application/Services/BucketInfoService/Services/IBucketInfoService.cs new file mode 100644 index 0000000..3d54bd1 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/BucketInfoService/Services/IBucketInfoService.cs @@ -0,0 +1,53 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 : + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/7/17 15:43:10 + /// 描 述 : + /// + public interface IBucketInfoService + { + /// + /// 增加 + /// + /// + Task Add(BucketInfoAddInput input); + /// + /// 增加并返回数据 + /// + /// + Task AddRetrun(BucketInfoAddInput input); + /// + /// 移除 + /// + /// + Task Del(BucketInfoDelInput input); + /// + /// 更新 + /// + /// + Task Update(BucketInfoUpdateInput input); + /// + /// 不分页列表 + /// + /// + Task> List(); + /// + /// 分页列表 + /// + /// + Task> PagedList(BucketInfoQueryPageInput input); + /// + /// 下拉列表 + /// + /// + Task SelectList(); + /// + /// 查询单条 + /// + /// + /// + Task Detail(string Id); + } +} diff --git a/backend/BPA.MES.Base.Application/Services/BucketInfoService/Services/IBucketMaterialsRecordService.cs b/backend/BPA.MES.Base.Application/Services/BucketInfoService/Services/IBucketMaterialsRecordService.cs new file mode 100644 index 0000000..2bfe66d --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/BucketInfoService/Services/IBucketMaterialsRecordService.cs @@ -0,0 +1,49 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :桶记录 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/7/17 17:37:03 + /// 描 述 : + /// + public interface IBucketMaterialsRecordService + { + /// + /// 增加 + /// + /// + Task Add(BucketMaterialsRecordAddInput input); + /// + /// 移除 + /// + /// + Task Del(BucketMaterialsRecordDelInput input); + /// + /// 更新 + /// + /// + Task Update(BucketMaterialsRecordUpdateInput input); + /// + /// 不分页列表 + /// + /// + Task> List(BucketMaterialsRecordQueryInput input); + /// + /// 分页列表 + /// + /// + Task> PagedList(BucketMaterialsRecordQueryPageInput input); + /// + /// 查询单条 + /// + /// + /// + Task Detail(string Id); + /// + /// 清空桶 + /// + /// + /// + Task Clear(BucketClearInput input); + } +} diff --git a/backend/BPA.MES.Base.Application/Services/CraftsInfoService/Dtos/CraftsInfoDto.cs b/backend/BPA.MES.Base.Application/Services/CraftsInfoService/Dtos/CraftsInfoDto.cs new file mode 100644 index 0000000..794556c --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/CraftsInfoService/Dtos/CraftsInfoDto.cs @@ -0,0 +1,83 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :产品分组 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/3/10 13:59:43 + /// 描 述 : + /// + public class CraftsInfoDto + { + /// + /// 工艺名称 + /// + public string Name { get; set; } + /// + /// 设备类型 0:炒锅 1:反应釜 + /// + public string DeviceProductId { get; set; } + /// + /// 工艺描述 + /// + public string Description { get; set; } + } + /// + /// 增加 + /// + public class CraftsInfoAddInput : CraftsInfoDto + { + + } + /// + /// 更新 + /// + public class CraftsInfoUpdateInput : CraftsInfoDto + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 删除 + /// + public class CraftsInfoDelInput + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 分页 + /// + public class CraftsInfoQueryPageInput : RequestPage + { + /// + /// 名称 + /// + public string Name { get; set; } + /// + /// 设备类型 0:炒锅 1:反应釜 + /// + public string DeviceProductId { get; set; } + } + /// + /// 不分页 + /// + public class CraftsInfoQueryInput + { + + } + /// + /// 输出 + /// + public class CraftsInfoOutput : CraftsInfoDto + { + /// + /// 主键 + /// + /// + public string Id { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Services/CraftsInfoService/Dtos/CraftsStepsDto.cs b/backend/BPA.MES.Base.Application/Services/CraftsInfoService/Dtos/CraftsStepsDto.cs new file mode 100644 index 0000000..4364319 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/CraftsInfoService/Dtos/CraftsStepsDto.cs @@ -0,0 +1,100 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :产线管理 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/7/18 14:03:27 + /// 描 述 : + /// + public class CraftsStepsDto + { + /// + /// 工艺Id + /// + public string CraftId { get; set; } + /// + /// 步骤 + /// + public int Step { get; set; } + /// + /// 功能描述 + /// + public string Description { get; set; } + /// + /// 设备产品功能Id + /// + public string DeviceProductFunctionId { get; set; } + + /// + /// 功能参数 + /// + public string Params { get; set; } + } + /// + /// 增加 + /// + public class CraftsStepsAddInput : CraftsStepsDto + { + + } + /// + /// 更新 + /// + public class CraftsStepsUpdateInput : CraftsStepsDto + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 删除 + /// + public class CraftsStepsDelInput + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 分页 + /// + public class CraftsStepsQueryPageInput : RequestPage + { + /// + /// 名称 + /// + public string Name { get; set; } + /// + /// 编码 + /// + public string Code { get; set; } + /// + /// 工艺Id + /// + public string CraftId { get; set; } + } + /// + /// 输出 + /// + public class CraftsStepsOutput : CraftsStepsDto + { + /// + /// 主键 + /// + public string Id { get; set; } + /// + /// 工艺名称 + /// + public string CraftName { get; set; } + /// + /// 设备产品功能名称 + /// + public string DeviceProductFunctionName { get; set; } + /// + /// 设备产品Id + /// + public string DeviceProductId { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Services/CraftsInfoService/Services/CraftsInfoService.cs b/backend/BPA.MES.Base.Application/Services/CraftsInfoService/Services/CraftsInfoService.cs new file mode 100644 index 0000000..1e8301f --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/CraftsInfoService/Services/CraftsInfoService.cs @@ -0,0 +1,130 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :工艺信息 + /// 创 建 人 :yangxiao + /// 创建时间 :2023/3/10 14:03:06 + /// 描 述 :配方工艺管理 + /// + [ApiDescriptionSettings("配方工艺管理", Order = 0, Tag = "工艺服务", Name = "CraftsInfo", KeepName = true, SplitCamelCase = true, KeepVerb = true)] + public class CraftsInfoService : ICraftsInfoService, ITransient, IDynamicApiController + { + private readonly ISqlSugarClient _dbContext; + public CraftsInfoService(ISqlSugarClient db) + { + _dbContext = db; + } + /// + /// 增加 + /// + /// + /// + [HttpPost] + public async Task Add(CraftsInfoAddInput input) + { + Pztj_CraftsInfoEntity entity = await _dbContext.Queryable().FirstAsync(x => x.Name ==input.Name); + if (entity != null) + { + throw Oops.Bah("名称已存在!"); + } + entity = input.Adapt(); + return await _dbContext.Insertable(entity).IgnoreColumns(ignoreNullColumn: true).ExecuteCommandIdentityIntoEntityAsync(); + } + /// + /// 删除 + /// + /// + /// + /// + [HttpPost] + public async Task Del(CraftsInfoDelInput input) + { + //事务,删除所有子表 + try + { + _dbContext.Ado.BeginTran(); + await _dbContext.Deleteable().Where(x => x.Id == input.Id).ExecuteCommandAsync(); + await _dbContext.Deleteable().Where(x => x.CraftId == input.Id).ExecuteCommandAsync(); + _dbContext.Ado.CommitTran(); + } + catch (Exception ex) + { + _dbContext.Ado.RollbackTran(); + throw Oops.Bah("删除失败!"); + } + return true; + } + /// + /// 详情 + /// + /// + /// + /// + [HttpGet] + public async Task Detail(string Id) + { + var entity = await _dbContext.Queryable().FirstAsync(); + CraftsInfoOutput output = entity.Adapt(); + return output; + } + /// + /// 列表 + /// + /// + /// + [HttpPost, AllowAnonymous] + public async Task> List(CraftsInfoQueryInput input) + { + var entity = await _dbContext.Queryable().ToListAsync(); + List output = entity.Adapt>(); + return output; + } + /// + /// 分页 + /// + /// + /// + [HttpPost] + public async Task> PagedList(CraftsInfoQueryPageInput input) + { + var entity = await _dbContext.Queryable() + .WhereIF(!string.IsNullOrEmpty(input.DeviceProductId), x => x.DeviceProductId == input.DeviceProductId) + .WhereIF(!string.IsNullOrEmpty(input.Name),x=>x.Name.Contains(input.Name)) + .ToPagedListAsync(input.PageIndex, input.PageSize); + SqlSugarPagedList output = entity.Adapt>(); + return output; + } + /// + /// 下拉 + /// + /// + [HttpGet] + public async Task SelectList() + { + var entity = await _dbContext.Queryable().Select(x => new + { + key = x.Id, + value = x.Name + }).ToListAsync(); + return entity; + } + /// + /// 更新 + /// + /// + /// + /// + [HttpPost] + public async Task Update(CraftsInfoUpdateInput input) + { + var entity = await _dbContext.Queryable().FirstAsync(x => x.Id != input.Id && x.Name == input.Name); + if (entity != null) + { + throw Oops.Bah("名称已存在!"); + } + entity = input.Adapt(); + var res = await _dbContext.Updateable(entity).IgnoreColumns(true).ExecuteCommandHasChangeAsync(); + return res; + } + } +} diff --git a/backend/BPA.MES.Base.Application/Services/CraftsInfoService/Services/CraftsStepsService.cs b/backend/BPA.MES.Base.Application/Services/CraftsInfoService/Services/CraftsStepsService.cs new file mode 100644 index 0000000..a3d908b --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/CraftsInfoService/Services/CraftsStepsService.cs @@ -0,0 +1,144 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :工艺路线服务 + /// 创 建 人 :yangxiao + /// 创建时间 :2023/3/2 16:11:04 + /// 描 述 :CraftsInfo 工艺管理 CraftsSteps工艺步骤管理 + /// + [ApiDescriptionSettings("配方工艺管理", Order = 0, Tag = "工艺服务", Name = "CraftsSteps", KeepName = true, SplitCamelCase = true, KeepVerb = true)] + public class CraftsStepsService : ICraftsStepsService, ITransient, IDynamicApiController + { + private readonly ISqlSugarClient _dbContext; + public CraftsStepsService(ISqlSugarClient db) + { + _dbContext = db; + } + /// + /// 增加 + /// + /// + /// + [HttpPost] + public async Task Add(CraftsStepsAddInput input) + { + + var step = await _dbContext.Queryable().Where(x=>x.CraftId==input.CraftId).MaxAsync(x => x.Step); + Pztj_CraftStepsEntity entity = input.Adapt(); + entity.Step = step+1; + return await _dbContext.Insertable(entity).IgnoreColumns(ignoreNullColumn: true).ExecuteCommandIdentityIntoEntityAsync(); + } + /// + /// 删除 + /// + /// + /// + /// + [HttpPost] + public async Task Del(CraftsStepsDelInput input) + { + var stepItem = await _dbContext.Queryable().Where(x => x.Id == input.Id).FirstAsync(); + string craftsId = stepItem.CraftId; + int step = stepItem.Step; + var res = await _dbContext.Deleteable().Where(x => x.Id == input.Id).ExecuteCommandHasChangeAsync(); + if (res) + { + var stepList = await _dbContext.Queryable().Where(x => x.CraftId == craftsId).OrderBy(x=>x.Step).ToListAsync(); + for (int i = 0; i < stepList.Count; i++) + { + stepList[i].Step = i + 1; + } + await _dbContext.Updateable(stepList).ExecuteCommandAsync(); + } + return res; + } + /// + /// 详情 + /// + /// + /// + /// + [HttpGet] + public async Task Detail(string Id) + { + var entity = await _dbContext.Queryable().FirstAsync(x => x.Id == Id); + CraftsStepsOutput output = entity.Adapt(); + return output; + } + /// + /// 列表 + /// + /// + /// + [HttpGet] + public async Task> List() + { + var entity = await _dbContext.Queryable().ToListAsync(); + List output = entity.Adapt>(); + return output; + } + /// + /// 分页 + /// + /// + /// + [HttpPost] + public async Task> PagedList(CraftsStepsQueryPageInput input) + { + var output = await _dbContext.Queryable() + .LeftJoin((a,b)=>a.DeviceProductFunctionId==b.Id) + .WhereIF(!string.IsNullOrEmpty(input.CraftId), (a, b) => a.CraftId == input.CraftId) + .OrderBy((a, b) => a.Step) + .Select((a,b)=>new CraftsStepsOutput + { + Id = a.Id.SelectAll(), + DeviceProductFunctionName = b.Name, + DeviceProductFunctionId = a.DeviceProductFunctionId, + DeviceProductId = b.DeviceProductId + }) + .ToPagedListAsync(input.PageIndex, input.PageSize); + return output; + } + /// + /// 下拉 + /// + /// + /// + [HttpGet] + public async Task SelectList() + { + var entity = await _dbContext.Queryable().Select(x => new + { + key = x.Id, + value = x.Description + }).ToListAsync(); + return entity; + } + /// + /// 更新 + /// + /// + /// + /// + [HttpPost] + public async Task Update(CraftsStepsUpdateInput input) + { + Pztj_CraftStepsEntity entity = input.Adapt(); + var res = await _dbContext.Updateable(entity).IgnoreColumns(it => it.Step).IgnoreColumns(true).ExecuteCommandHasChangeAsync(); + return res; + } + /// + /// 批量更新 + /// + /// + /// + [HttpPost] + public async Task BatchUpdate(List inputs) + { + List entity = inputs.Adapt>(); + var res = await _dbContext.Updateable(entity).ExecuteCommandHasChangeAsync(); + return res; + } + } +} + diff --git a/backend/BPA.MES.Base.Application/Services/CraftsInfoService/Services/ICraftsInfoService.cs b/backend/BPA.MES.Base.Application/Services/CraftsInfoService/Services/ICraftsInfoService.cs new file mode 100644 index 0000000..130be32 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/CraftsInfoService/Services/ICraftsInfoService.cs @@ -0,0 +1,48 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :工艺信息 + /// 创 建 人 :yangxiao + /// 创建时间 :2023/3/10 14:03:21 + /// 描 述 : + /// + public interface ICraftsInfoService + { + /// + /// 增加 + /// + /// + Task Add(CraftsInfoAddInput input); + /// + /// 移除 + /// + /// + Task Del(CraftsInfoDelInput input); + /// + /// 更新 + /// + /// + Task Update(CraftsInfoUpdateInput input); + /// + /// 不分页列表 + /// + /// + Task> List(CraftsInfoQueryInput Input); + /// + /// 分页列表 + /// + /// + Task> PagedList(CraftsInfoQueryPageInput input); + /// + /// 下拉列表 + /// + /// + Task SelectList(); + /// + /// 查询单条 + /// + /// + /// + Task Detail(string Id); + } +} diff --git a/backend/BPA.MES.Base.Application/Services/CraftsInfoService/Services/ICraftsStepsService.cs b/backend/BPA.MES.Base.Application/Services/CraftsInfoService/Services/ICraftsStepsService.cs new file mode 100644 index 0000000..880101a --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/CraftsInfoService/Services/ICraftsStepsService.cs @@ -0,0 +1,54 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :产线管理 + /// 创 建 人 :yangxiao + /// 创建时间 :2023/7/18 14:05:16 + /// 描 述 : + /// + public interface ICraftsStepsService + { + /// + /// 增加 + /// + /// + Task Add(CraftsStepsAddInput input); + /// + /// 移除 + /// + /// + Task Del(CraftsStepsDelInput input); + /// + /// 更新 + /// + /// + Task Update(CraftsStepsUpdateInput input); + /// + /// 批量更新 + /// + /// + /// + Task BatchUpdate(List inputs); + /// + /// 不分页列表 + /// + /// + Task> List(); + /// + /// 分页列表 + /// + /// + Task> PagedList(CraftsStepsQueryPageInput input); + /// + /// 下拉列表 + /// + /// + Task SelectList(); + /// + /// 查询单条 + /// + /// + /// + Task Detail(string Id); + } +} diff --git a/backend/BPA.MES.Base.Application/Services/DeviceProductService/Dtos/DeviceProductDto.cs b/backend/BPA.MES.Base.Application/Services/DeviceProductService/Dtos/DeviceProductDto.cs new file mode 100644 index 0000000..30ae841 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/DeviceProductService/Dtos/DeviceProductDto.cs @@ -0,0 +1,87 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :设备产品信息 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/8/2 16:19:15 + /// 描 述 : + /// + public class DeviceProductDto + { + /// + /// 设备产品名称 + /// + public string Name { get; set; } + /// + /// 设备产品编码 + /// + public string Code { get; set; } + /// + /// 设备产品描述 + /// + public string Description { get; set; } + } + /// + /// 增加 + /// + public class DeviceProductAddInput : DeviceProductDto + { + + } + /// + /// 修改 + /// + public class DeviceProductUpdateInput : DeviceProductDto + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 刪除 + /// + public class DeviceProductDelInput + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 普通查询条件 + /// + public class DeviceProductQueryInput + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 分页查询条件 + /// + public class DeviceProductQueryPageInput : RequestPage + { + + /// + /// 名称 + /// + public string Name { get; set; } + /// + /// 编码 + /// + public string Code { get; set; } + } + /// + /// 输出 + /// + public class DeviceProductOutput : DeviceProductDto + { + /// + /// 主键 + /// + public string Id { get; set; } + //下面增加多的数据 + } +} diff --git a/backend/BPA.MES.Base.Application/Services/DeviceProductService/Dtos/DeviceProductFunctionDto.cs b/backend/BPA.MES.Base.Application/Services/DeviceProductService/Dtos/DeviceProductFunctionDto.cs new file mode 100644 index 0000000..ecd4b0c --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/DeviceProductService/Dtos/DeviceProductFunctionDto.cs @@ -0,0 +1,111 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :设备产品模型功能 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/7/31 18:04:53 + /// 描 述 : + /// + public class DeviceProductFunctionDto + { + /// + /// 设备产品Id + /// + public string DeviceProductId { get; set; } + /// + /// 功能名称 + /// + public string Name { get; set; } + /// + /// 功能编码 + /// + public string Code { get; set; } + /// + /// 描述 + /// + public string Description { get; set; } + /// + /// 方法参数 + /// + public string Params { get; set; } + } + /// + /// 增加 + /// + public class DeviceProductFunctionAddInput : DeviceProductFunctionDto + { + + } + /// + /// 修改 + /// + public class DeviceProductFunctionUpdateInput : DeviceProductFunctionDto + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 刪除 + /// + public class DeviceProductFunctionDelInput + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 普通查询条件 + /// + public class DeviceProductFunctionQueryInput + { + /// + /// 主键 + /// + public string Id { get; set; } + /// + /// 设备产品Id + /// + public string DeviceProductId { get; set; } + /// + /// 设备产品名称 + /// + public string Name { get; set; } + /// + /// 设备产品编号 + /// + public string Code { get; set; } + } + /// + /// 分页查询条件 + /// + public class DeviceProductFunctionQueryPageInput : RequestPage + { + + /// + /// 名称 + /// + public string Name { get; set; } + /// + /// 编码 + /// + public string Code { get; set; } + /// + /// 设备产品Id + /// + public string DeviceProductId { get; set; } + } + /// + /// 输出 + /// + public class DeviceProductFunctionOutput : DeviceProductFunctionDto + { + /// + /// 主键 + /// + public string Id { get; set; } + //下面增加多的数据 + } +} diff --git a/backend/BPA.MES.Base.Application/Services/DeviceProductService/Dtos/DeviceProductParmDto.cs b/backend/BPA.MES.Base.Application/Services/DeviceProductService/Dtos/DeviceProductParmDto.cs new file mode 100644 index 0000000..1ba3d1f --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/DeviceProductService/Dtos/DeviceProductParmDto.cs @@ -0,0 +1,91 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :设备产品参数 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/7/31 18:04:53 + /// 描 述 : + /// + public class DeviceProductParmDto + { + /// + /// 设备产品Id + /// + public string DeviceProductId { get; set; } + /// + /// 名称 + /// + public string Name { get; set; } + /// + /// 编码 + /// + public string Code { get; set; } + /// + /// 描述 + /// + public string Description { get; set; } + } + /// + /// 增加 + /// + public class DeviceProductParmAddInput : DeviceProductParmDto + { + + } + /// + /// 修改 + /// + public class DeviceProductParmUpdateInput : DeviceProductParmDto + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 刪除 + /// + public class DeviceProductParmDelInput + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 普通查询条件 + /// + public class DeviceProductParmQueryInput + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 分页查询条件 + /// + public class DeviceProductParmQueryPageInput : RequestPage + { + + /// + /// 名称 + /// + public string Name { get; set; } + /// + /// 编码 + /// + public string Code { get; set; } + } + /// + /// 输出 + /// + public class DeviceProductParmOutput : DeviceProductParmDto + { + /// + /// 主键 + /// + public string Id { get; set; } + //下面增加多的数据 + } +} diff --git a/backend/BPA.MES.Base.Application/Services/DeviceProductService/Services/DeviceProductFunctionService.cs b/backend/BPA.MES.Base.Application/Services/DeviceProductService/Services/DeviceProductFunctionService.cs new file mode 100644 index 0000000..a95ba3e --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/DeviceProductService/Services/DeviceProductFunctionService.cs @@ -0,0 +1,128 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :设备产品功能服务 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/7/31 18:03:25 + /// 描 述 : + /// + [ApiDescriptionSettings("设备产品模型", Name = "DeviceProductFunction", Tag = "设备产品功能", KeepName = true, SplitCamelCase = true, KeepVerb = true)] + public class DeviceProductFunctionService : IDeviceProductFunctionService, ITransient, IDynamicApiController + { + private readonly ISqlSugarClient _dbContext; + public DeviceProductFunctionService(ISqlSugarClient db) + { + _dbContext = db; + } + /// + /// 增加 + /// + /// + /// + [HttpPost] + public async Task Add(DeviceProductFunctionAddInput input) + { + var r_entity = await _dbContext.Queryable().Where(x=>x.DeviceProductId==input.DeviceProductId && x.Name == input.Name).FirstAsync(); + if (r_entity != null) + { + throw Oops.Bah("名称已存在!"); + } + DeviceProductFunctionEntity entity = input.Adapt(); + return await _dbContext.Insertable(entity).IgnoreColumns(ignoreNullColumn: true).ExecuteCommandIdentityIntoEntityAsync(); + } + /// + /// 删除 + /// + /// + /// + /// + [HttpPost] + public async Task Del(DeviceProductFunctionDelInput input) + { + var res = await _dbContext.Deleteable().Where(x => x.Id == input.Id).ExecuteCommandHasChangeAsync(); + return res; + } + /// + /// 详情 + /// + /// + /// + /// + [HttpGet] + public async Task Detail(string Id) + { + var entity = await _dbContext.Queryable().FirstAsync(x => x.Id == Id); + DeviceProductFunctionOutput output = entity.Adapt(); + return output; + } + /// + /// 列表 + /// + /// + /// + [HttpPost] + public async Task> List(DeviceProductFunctionQueryInput input) + { + var entity = await _dbContext.Queryable() + .WhereIF(!string.IsNullOrEmpty(input.DeviceProductId), x => x.DeviceProductId==input.DeviceProductId) + .WhereIF(!string.IsNullOrEmpty(input.Name), x => x.Name.Contains(input.Name)) + .WhereIF(!string.IsNullOrEmpty(input.Code), x => x.Code.Contains(input.Code)) + .ToListAsync(); + List output = entity.Adapt>(); + return output; + } + /// + /// 分页 + /// + /// + /// + [HttpPost] + public async Task> PagedList(DeviceProductFunctionQueryPageInput input) + { + var entity = await _dbContext.Queryable() + .WhereIF(!string.IsNullOrEmpty(input.Name), x => x.Name.Contains(input.Name)) + .WhereIF(!string.IsNullOrEmpty(input.Code), x => x.Code.Contains(input.Code)) + .WhereIF(!string.IsNullOrEmpty(input.DeviceProductId),x=>x.DeviceProductId==input.DeviceProductId) + .ToPagedListAsync(input.PageIndex, input.PageSize); + SqlSugarPagedList output = entity.Adapt>(); + return output; + } + /// + /// 下拉 + /// + /// + /// + [HttpGet] + public async Task SelectList() + { + var entity = await _dbContext.Queryable().Select(x => new + { + key = x.Id, + value = x.Name + }).ToListAsync(); + return entity; + } + /// + /// 更新 + /// + /// + /// + /// + [HttpPost] + public async Task Update(DeviceProductFunctionUpdateInput input) + { + + var isEntity = await _dbContext.Queryable() + .Where(x =>x.Id != input.Id && x.DeviceProductId == input.DeviceProductId && x.Name == input.Name).FirstAsync(); + if (isEntity != null) + { + throw Oops.Bah("名称已存在!"); + } + var entity = await _dbContext.Queryable().Where(x => x.Id == input.Id).FirstAsync(); + entity = input.Adapt(); + + var res = await _dbContext.Updateable(entity).IgnoreColumns(true).ExecuteCommandHasChangeAsync(); + return res; + } + } +} diff --git a/backend/BPA.MES.Base.Application/Services/DeviceProductService/Services/DeviceProductParmService.cs b/backend/BPA.MES.Base.Application/Services/DeviceProductService/Services/DeviceProductParmService.cs new file mode 100644 index 0000000..1c0499b --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/DeviceProductService/Services/DeviceProductParmService.cs @@ -0,0 +1,115 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :设备参数 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/7/31 18:03:25 + /// 描 述 : + /// + [ApiDescriptionSettings("设备产品模型", Name = "DeviceProductParm", Tag = "设备产品参数", KeepName = true, SplitCamelCase = true, KeepVerb = true)] + public class DeviceProductParmService : IDeviceProductParmService, ITransient, IDynamicApiController + { + private readonly ISqlSugarClient _dbContext; + public DeviceProductParmService(ISqlSugarClient db) + { + _dbContext = db; + } + /// + /// 增加 + /// + /// + /// + [HttpPost] + public async Task Add(DeviceProductParmAddInput input) + { + var r_entity = await _dbContext.Queryable().FirstAsync(x => x.Name == input.Name); + if (r_entity != null) + { + throw Oops.Bah("名称已存在!"); + } + DeviceProductParmEntity entity = input.Adapt(); + return await _dbContext.Insertable(entity).IgnoreColumns(ignoreNullColumn: true).ExecuteCommandIdentityIntoEntityAsync(); + } + /// + /// 删除 + /// + /// + /// + /// + [HttpPost] + public async Task Del(DeviceProductParmDelInput input) + { + var res = await _dbContext.Deleteable().Where(x => x.Id == input.Id).ExecuteCommandHasChangeAsync(); + return res; + } + /// + /// 详情 + /// + /// + /// + /// + [HttpGet] + public async Task Detail(string Id) + { + var entity = await _dbContext.Queryable().FirstAsync(x => x.Id == Id); + DeviceProductParmOutput output = entity.Adapt(); + return output; + } + /// + /// 列表 + /// + /// + /// + [HttpPost] + public async Task> List(DeviceProductParmQueryInput input) + { + var entity = await _dbContext.Queryable().ToListAsync(); + List output = entity.Adapt>(); + return output; + } + /// + /// 分页 + /// + /// + /// + [HttpPost] + public async Task> PagedList(DeviceProductParmQueryPageInput input) + { + var entity = await _dbContext.Queryable() + .WhereIF(!string.IsNullOrEmpty(input.Name), x => x.Name.Contains(input.Name)) + .WhereIF(!string.IsNullOrEmpty(input.Code), x => x.Code.Contains(input.Code)) + .ToPagedListAsync(input.PageIndex, input.PageSize); + SqlSugarPagedList output = entity.Adapt>(); + return output; + } + /// + /// 下拉 + /// + /// + /// + [HttpGet] + public async Task SelectList() + { + var entity = await _dbContext.Queryable().Select(x => new + { + key = x.Id, + value = x.Name + }).ToListAsync(); + return entity; + } + /// + /// 更新 + /// + /// + /// + /// + [HttpPost] + public async Task Update(DeviceProductParmUpdateInput input) + { + var entity = await _dbContext.Queryable().Where(x => x.Id == input.Id).FirstAsync(); + entity = input.Adapt(); + var res = await _dbContext.Updateable(entity).IgnoreColumns(true).ExecuteCommandHasChangeAsync(); + return res; + } + } +} diff --git a/backend/BPA.MES.Base.Application/Services/DeviceProductService/Services/DeviceProductService.cs b/backend/BPA.MES.Base.Application/Services/DeviceProductService/Services/DeviceProductService.cs new file mode 100644 index 0000000..fcbc849 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/DeviceProductService/Services/DeviceProductService.cs @@ -0,0 +1,127 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :设备产品 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/7/31 18:03:25 + /// 描 述 : + /// + [ApiDescriptionSettings("设备产品模型", Name = "DeviceProduct", Tag = "设备产品管理", KeepName = true, SplitCamelCase = true, KeepVerb = true)] + public class DeviceProductService : IDeviceProductService, ITransient, IDynamicApiController + { + private readonly ISqlSugarClient _dbContext; + public DeviceProductService(ISqlSugarClient db) + { + _dbContext = db; + } + /// + /// 增加 + /// + /// + /// + [HttpPost] + public async Task Add(DeviceProductAddInput input) + { + var r_entity = await _dbContext.Queryable().FirstAsync(x => x.Name == input.Name); + if (r_entity != null) + { + throw Oops.Bah("名称已存在!"); + } + DeviceProductEntity entity = input.Adapt(); + return await _dbContext.Insertable(entity).IgnoreColumns(ignoreNullColumn: true).ExecuteCommandIdentityIntoEntityAsync(); + } + /// + /// 删除 + /// + /// + /// + /// + [HttpPost] + public async Task Del(DeviceProductDelInput input) + { + //事务,删除所有子表 + try + { + _dbContext.Ado.BeginTran(); + await _dbContext.Deleteable().Where(x => x.Id == input.Id).ExecuteCommandAsync(); + await _dbContext.Deleteable().Where(x => x.DeviceProductId == input.Id).ExecuteCommandAsync(); + _dbContext.Ado.CommitTran(); + } + catch (Exception ex) + { + _dbContext.Ado.RollbackTran(); + throw Oops.Bah("删除失败!"); + } + return true; + } + /// + /// 详情 + /// + /// + /// + /// + [HttpGet] + public async Task Detail(string Id) + { + var entity = await _dbContext.Queryable().FirstAsync(x => x.Id == Id); + DeviceProductOutput output = entity.Adapt(); + return output; + } + /// + /// 列表 + /// + /// + /// + [HttpPost] + public async Task> List(DeviceProductQueryInput input) + { + var entity = await _dbContext.Queryable().ToListAsync(); + List output = entity.Adapt>(); + return output; + } + /// + /// 分页 + /// + /// + /// + [HttpPost] + public async Task> PagedList(DeviceProductQueryPageInput input) + { + var entity = await _dbContext.Queryable() + .WhereIF(!string.IsNullOrEmpty(input.Name), x => x.Name.Contains(input.Name)) + .WhereIF(!string.IsNullOrEmpty(input.Code), x => x.Code.Contains(input.Code)) + .ToPagedListAsync(input.PageIndex, input.PageSize); + SqlSugarPagedList output = entity.Adapt>(); + return output; + } + /// + /// 下拉 + /// + /// + /// + [HttpGet] + public async Task SelectList() + { + var entity = await _dbContext.Queryable().Select(x => new + { + key = x.Id, + value = x.Name + }).ToListAsync(); + return entity; + } + /// + /// 更新 + /// + /// + /// + /// + [HttpPost] + public async Task Update(DeviceProductUpdateInput input) + { + var entity = await _dbContext.Queryable().Where(x => x.Id == input.Id).FirstAsync(); + entity = input.Adapt(); + var res = await _dbContext.Updateable(entity).IgnoreColumns(true).ExecuteCommandHasChangeAsync(); + return res; + } + } +} diff --git a/backend/BPA.MES.Base.Application/Services/DeviceProductService/Services/IDeviceProductFunctionService.cs b/backend/BPA.MES.Base.Application/Services/DeviceProductService/Services/IDeviceProductFunctionService.cs new file mode 100644 index 0000000..6d26ba2 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/DeviceProductService/Services/IDeviceProductFunctionService.cs @@ -0,0 +1,48 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :设备产品功能 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/7/31 18:02:57 + /// 描 述 : + /// + public interface IDeviceProductFunctionService + { + /// + /// 增加 + /// + /// + Task Add(DeviceProductFunctionAddInput input); + /// + /// 删除 + /// + /// + Task Del(DeviceProductFunctionDelInput input); + /// + /// 更新 + /// + /// + Task Update(DeviceProductFunctionUpdateInput input); + /// + /// 不分页列表 + /// + /// + Task> List(DeviceProductFunctionQueryInput input); + /// + /// 分页列表 + /// + /// + Task> PagedList(DeviceProductFunctionQueryPageInput input); + /// + /// 下拉列表 + /// + /// + Task SelectList(); + /// + /// 查询单条 + /// + /// + /// + Task Detail(string Id); + } +} diff --git a/backend/BPA.MES.Base.Application/Services/DeviceProductService/Services/IDeviceProductParmService.cs b/backend/BPA.MES.Base.Application/Services/DeviceProductService/Services/IDeviceProductParmService.cs new file mode 100644 index 0000000..6a2866e --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/DeviceProductService/Services/IDeviceProductParmService.cs @@ -0,0 +1,48 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :设备产品参数 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/7/31 18:02:57 + /// 描 述 : + /// + public interface IDeviceProductParmService + { + /// + /// 增加 + /// + /// + Task Add(DeviceProductParmAddInput input); + /// + /// 删除 + /// + /// + Task Del(DeviceProductParmDelInput input); + /// + /// 更新 + /// + /// + Task Update(DeviceProductParmUpdateInput input); + /// + /// 不分页列表 + /// + /// + Task> List(DeviceProductParmQueryInput input); + /// + /// 分页列表 + /// + /// + Task> PagedList(DeviceProductParmQueryPageInput input); + /// + /// 下拉列表 + /// + /// + Task SelectList(); + /// + /// 查询单条 + /// + /// + /// + Task Detail(string Id); + } +} diff --git a/backend/BPA.MES.Base.Application/Services/DeviceProductService/Services/IDeviceProductService.cs b/backend/BPA.MES.Base.Application/Services/DeviceProductService/Services/IDeviceProductService.cs new file mode 100644 index 0000000..b759a85 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/DeviceProductService/Services/IDeviceProductService.cs @@ -0,0 +1,48 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :设备产品基础信息 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/8/2 16:19:35 + /// 描 述 : + /// + public interface IDeviceProductService + { + /// + /// 增加 + /// + /// + Task Add(DeviceProductAddInput input); + /// + /// 删除 + /// + /// + Task Del(DeviceProductDelInput input); + /// + /// 更新 + /// + /// + Task Update(DeviceProductUpdateInput input); + /// + /// 不分页列表 + /// + /// + Task> List(DeviceProductQueryInput input); + /// + /// 分页列表 + /// + /// + Task> PagedList(DeviceProductQueryPageInput input); + /// + /// 下拉列表 + /// + /// + Task SelectList(); + /// + /// 查询单条 + /// + /// + /// + Task Detail(string Id); + } +} diff --git a/backend/BPA.MES.Base.Application/Services/DeviceService/Dtos/DeviceRecipeDto.cs b/backend/BPA.MES.Base.Application/Services/DeviceService/Dtos/DeviceRecipeDto.cs new file mode 100644 index 0000000..167f13b --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/DeviceService/Dtos/DeviceRecipeDto.cs @@ -0,0 +1,99 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :设备Dto类 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/3/2 16:12:06 + /// 描 述 : + /// + public class DeviceRecipeDto : DeviceRecipeEntity + { + + } + /// + /// 增加 + /// + public class DeviceRecipeAddInput : DeviceRecipeDto + { + + } + /// + /// 更新 + /// + public class DeviceRecipeUpdateInput : DeviceRecipeDto + { + + } + /// + /// 删除 + /// + public class DeviceRecipeDelInput + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 不分页 + /// + public class DeviceRecipeQueryInput + { + /// + /// 设备Id + /// + public string DeviceId { get; set; } + + } + /// + /// 分页 + /// + public class DeviceRecipeQueryPageInput : RequestPage + { + + } + + public class DeviceRecipeBatchAddInput + { + /// + /// 设备Id + /// + public string DeviceId { get; set; } + /// + /// 配方数组 + /// + public List RecipesIds { get; set; } = new(); + } + + + /// + /// 输出 + /// + public class DeviceRecipeOutput : DeviceRecipeDto + { + /// + /// 设备名称 + /// + public string DeviceName { get; set; } + /// + /// 配方名称 + /// + public string RecipeName { get; set; } + /// + /// 配方代码 + /// + public string RecipeCode { get; set; } + /// + /// 分组Id + /// + public string GroupId { get; set; } + /// + /// 分组名称 + /// + public string GroupName { get; set; } + /// + /// 配方图片地址 + /// + public string RecipesPic { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Services/DeviceService/Dtos/DevicesInfoDto.cs b/backend/BPA.MES.Base.Application/Services/DeviceService/Dtos/DevicesInfoDto.cs new file mode 100644 index 0000000..c95b597 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/DeviceService/Dtos/DevicesInfoDto.cs @@ -0,0 +1,88 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :设备Dto类 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/3/2 16:12:06 + /// 描 述 : + /// + public class DevicesInfoDto + { + /// + /// 名称 + /// + /// 设备名称 + [Required(ErrorMessage = "名称不能为空")] + public string Name { get; set; } + /// + /// 编码 + /// + [Required(ErrorMessage = "编码不能为空")] + public string Code { get; set; } + /// + /// 设备类型 + /// + public string DeviceType { get; set; } + /// + /// 设备描述 + /// + /// 设备描述 + public string Describe { get; set; } + /// + /// 设备维保时间 + /// + /// 2023-7-17 + public string RepairDate { get; set; } + } + /// + /// 增加 + /// + public class DevicesInfoAddInput : DevicesInfoDto + { + + } + /// + /// 更新 + /// + public class DevicesInfoUpdateInput : DevicesInfoDto + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 删除 + /// + public class DevicesInfoDelInput + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 分页 + /// + public class DevicesInfoQueryPageInput : RequestPage + { + /// + /// 名称 + /// + public string Name { get; set; } + /// + /// 编码 + /// + public string Code { get; set; } + } + /// + /// 输出 + /// + public class DevicesInfoOutput : DevicesInfoDto + { + /// + /// 主键 + /// + public string Id { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Services/DeviceService/Services/DeviceRecipeService.cs b/backend/BPA.MES.Base.Application/Services/DeviceService/Services/DeviceRecipeService.cs new file mode 100644 index 0000000..26c0f83 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/DeviceService/Services/DeviceRecipeService.cs @@ -0,0 +1,144 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :设备服务 + /// 创 建 人 :yangxiao + /// 创建时间 :2023/3/2 16:11:04 + /// 描 述 :基础信息管理 + /// + [ApiDescriptionSettings("基础数据管理", Name = "DeviceRecipe", Tag = "设备服务", KeepName = true, SplitCamelCase = true, KeepVerb = true)] + public class DeviceRecipeService : IDeviceRecipeService, ITransient, IDynamicApiController + { + private readonly ISqlSugarClient _dbContext; + public DeviceRecipeService(ISqlSugarClient db) + { + _dbContext = db; + } + /// + /// 增加 + /// + /// + /// + [HttpPost] + public async Task Add(DeviceRecipeAddInput input) + { + var r_entity = await _dbContext.Queryable().FirstAsync(x => x.DeviceId == input.DeviceId && x.RecipesId==input.RecipesId); + if (r_entity != null) + { + throw Oops.Bah("名称已存在!"); + } + DeviceRecipeEntity entity = input.Adapt(); + return await _dbContext.Insertable(entity).IgnoreColumns(ignoreNullColumn: true).ExecuteCommandIdentityIntoEntityAsync(); + } + /// + /// 批量下发配方 + /// + /// + /// + /// + + public async Task BatchUpdate(DeviceRecipeBatchAddInput input) + { + bool result = false; + List dr_entitys = new(); + foreach (var item in input.RecipesIds) + { + DeviceRecipeEntity entity = new(); + entity.RecipesId = item; + entity.DeviceId = input.DeviceId; + dr_entitys.Add(entity); + } + try + { + _dbContext.Ado.BeginTran(); + await _dbContext.Deleteable().Where(x => x.DeviceId == input.DeviceId).ExecuteCommandAsync(); + if (input.RecipesIds.Any()) + { + await _dbContext.Insertable(dr_entitys).ExecuteCommandAsync(); + } + _dbContext.Ado.CommitTran(); + result = true; + } + catch (Exception ex) + { + throw Oops.Bah("更新失败!"); + } + return result; + } + /// + /// 删除 + /// + /// + /// + /// + [HttpPost] + public async Task Del(DeviceRecipeDelInput input) + { + var res = await _dbContext.Deleteable().Where(x => x.Id == input.Id).ExecuteCommandHasChangeAsync(); + return res; + } + /// + /// 详情 + /// + /// + /// + /// + [HttpGet] + public async Task Detail(string Id) + { + var entity = await _dbContext.Queryable().FirstAsync(x => x.Id == Id); + DeviceRecipeOutput output = entity.Adapt(); + return output; + } + /// + /// 列表 + /// + /// + /// + [HttpPost,AllowAnonymous] + public async Task> List(DeviceRecipeQueryInput input) + { + var output = await _dbContext.Queryable() + .LeftJoin((a,b)=>a.RecipesId==b.Id) + .LeftJoin((a,b,c)=>a.RecipesId==c.RecipesId) + .LeftJoin((a, b, c,d)=>c.GroupId==d.Id) + .WhereIF(!string.IsNullOrEmpty(input.DeviceId),a=>a.DeviceId==input.DeviceId) + .Select((a, b, c,d) => new DeviceRecipeOutput + { + DeviceId = a.DeviceId, + RecipeName = b.Name, + RecipeCode = b.Code, + RecipesId = a.RecipesId, + GroupId = c.GroupId, + GroupName = d.Name + }) + .ToListAsync(); + return output; + } + /// + /// 分页 + /// + /// + /// + [HttpPost] + public async Task> PagedList(DeviceRecipeQueryPageInput input) + { + var entity = await _dbContext.Queryable() + .ToPagedListAsync(input.PageIndex, input.PageSize); + SqlSugarPagedList output = entity.Adapt>(); + return output; + } + /// + /// 更新 + /// + /// + /// + /// + [HttpPost] + public async Task Update(DeviceRecipeUpdateInput input) + { + var res = await _dbContext.Updateable().ExecuteCommandHasChangeAsync(); + return res; + } + } +} diff --git a/backend/BPA.MES.Base.Application/Services/DeviceService/Services/DevicesInfoService.cs b/backend/BPA.MES.Base.Application/Services/DeviceService/Services/DevicesInfoService.cs new file mode 100644 index 0000000..77b066d --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/DeviceService/Services/DevicesInfoService.cs @@ -0,0 +1,119 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :设备服务 + /// 创 建 人 :yangxiao + /// 创建时间 :2023/3/2 16:11:04 + /// 描 述 :基础数据管理 + /// + [ApiDescriptionSettings("基础数据管理",Order = 0, Tag = "设备服务", Name = "DevicesInfo", KeepName = true, SplitCamelCase = true, KeepVerb = true)] + public class DevicesInfoService : IDevicesInfoService, ITransient, IDynamicApiController + { + private readonly ISqlSugarClient _dbContext; + public DevicesInfoService(ISqlSugarClient db) + { + _dbContext = db; + } + /// + /// 增加 + /// + /// + /// + [HttpPost] + public async Task Add(DevicesInfoAddInput input) + { + var r_entity = await _dbContext.Queryable().FirstAsync(x => x.Name == input.Name || x.Code == input.Code); + if (r_entity != null) + { + throw Oops.Bah("名称或编码已存在!"); + } + Pztj_DevicesInfoEntity entity = input.Adapt(); + return await _dbContext.Insertable(entity).IgnoreColumns(ignoreNullColumn: true).ExecuteCommandIdentityIntoEntityAsync(); + } + /// + /// 删除 + /// + /// + /// + /// + [HttpPost] + public async Task Del(DevicesInfoDelInput input) + { + var res = await _dbContext.Deleteable().Where(x => x.Id == input.Id).ExecuteCommandHasChangeAsync(); + return res; + } + /// + /// 详情 + /// + /// + /// + /// + [HttpGet] + public async Task Detail(string Id) + { + var entity = await _dbContext.Queryable().FirstAsync(x => x.Id == Id); + DevicesInfoOutput output = entity.Adapt(); + return output; + } + /// + /// 列表 + /// + /// + /// + [HttpGet] + public async Task> List() + { + var entity = await _dbContext.Queryable().ToListAsync(); + List output = entity.Adapt>(); + return output; + } + /// + /// 分页 + /// + /// + /// + [HttpPost] + public async Task> PagedList(DevicesInfoQueryPageInput input) + { + var entity = await _dbContext.Queryable() + .WhereIF(!string.IsNullOrEmpty(input.Name),x=>x.Name.Contains(input.Name)) + .WhereIF(!string.IsNullOrEmpty(input.Code), x => x.Name.Contains(input.Code)) + .ToPagedListAsync(input.PageIndex, input.PageSize); + SqlSugarPagedList output = entity.Adapt>(); + return output; + } + /// + /// 下拉 + /// + /// + /// + [HttpGet] + public async Task SelectList() + { + var entity = await _dbContext.Queryable().Select(x => new + { + key = x.Id, + value = x.Name + }).ToListAsync(); + return entity; + } + /// + /// 更新 + /// + /// + /// + /// + [HttpPost] + public async Task Update(DevicesInfoUpdateInput input) + { + var isExit =await _dbContext.Queryable().Where(x => x.Id != input.Id && (x.Name == input.Name || x.Code == input.Code)).FirstAsync(); + if (isExit != null) + { + throw Oops.Bah("名称或编码已存在!"); + } + Pztj_DevicesInfoEntity entity = input.Adapt(); + var res = await _dbContext.Updateable(entity).IgnoreColumns(true).ExecuteCommandHasChangeAsync(); + return res; + } + } +} diff --git a/backend/BPA.MES.Base.Application/Services/DeviceService/Services/IDeviceRecipeService.cs b/backend/BPA.MES.Base.Application/Services/DeviceService/Services/IDeviceRecipeService.cs new file mode 100644 index 0000000..3c74b75 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/DeviceService/Services/IDeviceRecipeService.cs @@ -0,0 +1,49 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :设备配方服务 + /// 创 建 人 :yangxiao + /// 创建时间 :2023/3/2 18:30:58 + /// 描 述 : + /// + public interface IDeviceRecipeService + { + /// + /// 增加 + /// + /// + Task Add(DeviceRecipeAddInput input); + /// + /// 移除 + /// + /// + Task Del(DeviceRecipeDelInput input); + /// + /// 更新 + /// + /// + Task Update(DeviceRecipeUpdateInput input); + /// + /// 不分页列表 + /// + /// + Task> List(DeviceRecipeQueryInput input); + /// + /// 分页列表 + /// + /// + Task> PagedList(DeviceRecipeQueryPageInput input); + /// + /// 查询单条 + /// + /// + /// + Task Detail(string Id); + /// + /// 批量下发配方 + /// + /// + /// + Task BatchUpdate(DeviceRecipeBatchAddInput input); + } +} diff --git a/backend/BPA.MES.Base.Application/Services/DeviceService/Services/IDevicesInfoService.cs b/backend/BPA.MES.Base.Application/Services/DeviceService/Services/IDevicesInfoService.cs new file mode 100644 index 0000000..31386c0 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/DeviceService/Services/IDevicesInfoService.cs @@ -0,0 +1,48 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :设备服务 + /// 创 建 人 :yangxiao + /// 创建时间 :2023/3/2 18:30:58 + /// 描 述 : + /// + public interface IDevicesInfoService + { + /// + /// 增加 + /// + /// + Task Add(DevicesInfoAddInput input); + /// + /// 移除 + /// + /// + Task Del(DevicesInfoDelInput input); + /// + /// 更新 + /// + /// + Task Update(DevicesInfoUpdateInput input); + /// + /// 不分页列表 + /// + /// + Task> List(); + /// + /// 分页列表 + /// + /// + Task> PagedList(DevicesInfoQueryPageInput input); + /// + /// 下拉列表 + /// + /// + Task SelectList(); + /// + /// 查询单条 + /// + /// + /// + Task Detail(string Id); + } +} diff --git a/backend/BPA.MES.Base.Application/Services/DictService/Dtos/DictDataDto.cs b/backend/BPA.MES.Base.Application/Services/DictService/Dtos/DictDataDto.cs new file mode 100644 index 0000000..6bd555e --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/DictService/Dtos/DictDataDto.cs @@ -0,0 +1,102 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :码表数据 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/8/9 9:56:11 + /// 描 述 : + /// + public class DictDataDto + { + /// + /// 类型id + /// + public string TypeId { get; set; } + /// + /// 值 + /// + public string Value { get; set; } + /// + /// 编码 + /// + public string Code { get; set; } + /// + /// 排序 + /// + public int Sort { get; set; } + } + /// + /// 增加 + /// + public class DictDataAddInput : DictDataDto + { + + } + /// + /// 修改 + /// + public class DictDataUpdateInput : DictDataDto + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 刪除 + /// + public class DictDataDelInput + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 普通查询条件 + /// + public class DictDataQueryInput + { + /// + /// 码表类型Id + /// + public string TypeId { get; set; } + /// + /// 码表类型编码 + /// + public string TypeCode { get; set; } + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 分页查询条件 + /// + public class DictDataQueryPageInput : RequestPage + { + /// + /// 名称 + /// + public string Value { get; set; } + /// + /// 编码 + /// + public string Code { get; set; } + /// + /// 码表类型Id + /// + public string TypeId { get; set; } + } + /// + /// 输出 + /// + public class DictDataOutput : DictDataDto + { + /// + /// 主键 + /// + public string Id { get; set; } + //下面增加多的数据 + } +} diff --git a/backend/BPA.MES.Base.Application/Services/DictService/Dtos/DictTypeDto.cs b/backend/BPA.MES.Base.Application/Services/DictService/Dtos/DictTypeDto.cs new file mode 100644 index 0000000..dd9ebb4 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/DictService/Dtos/DictTypeDto.cs @@ -0,0 +1,86 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :码表类型 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/8/9 9:56:00 + /// 描 述 : + /// + public class DictTypeDto + { + /// + /// 名称 + /// + public string Name { get; set; } + /// + /// 编码 + /// + public string Code { get; set; } + /// + /// 排序 + /// + public int Sort { get; set; } + } + /// + /// 增加 + /// + public class DictTypeAddInput : DictTypeDto + { + + } + /// + /// 修改 + /// + public class DictTypeUpdateInput : DictTypeDto + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 刪除 + /// + public class DictTypeDelInput + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 普通查询条件 + /// + public class DictTypeQueryInput + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 分页查询条件 + /// + public class DictTypeQueryPageInput : RequestPage + { + /// + /// 名称 + /// + public string Name { get; set; } + /// + /// 编码 + /// + public string Code { get; set; } + } + /// + /// 输出 + /// + public class DictTypeOutput : DictTypeDto + { + /// + /// 主键 + /// + public string Id { get; set; } + //下面增加多的数据 + } +} diff --git a/backend/BPA.MES.Base.Application/Services/DictService/Services/DictDataService.cs b/backend/BPA.MES.Base.Application/Services/DictService/Services/DictDataService.cs new file mode 100644 index 0000000..3830f83 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/DictService/Services/DictDataService.cs @@ -0,0 +1,123 @@ +using System.Reflection; + +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :码表管理 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/8/9 10:01:19 + /// 描 述 : + /// + [ApiDescriptionSettings("数据字典", Name = "DictData", Tag = "字典数据", KeepName = true, SplitCamelCase = true, KeepVerb = true)] + public class DictDataService: IDictDataService, ITransient, IDynamicApiController + { + private readonly ISqlSugarClient _dbContext; + public DictDataService(ISqlSugarClient db) + { + _dbContext = db; + + + } + /// + /// 增加 + /// + /// + /// + [HttpPost] + public async Task Add(DictDataAddInput input) + { + DictDataEntity entity = input.Adapt(); + return await _dbContext.Insertable(entity).IgnoreColumns(ignoreNullColumn: true).ExecuteCommandIdentityIntoEntityAsync(); + } + /// + /// 删除 + /// + /// + /// + /// + [HttpPost] + public async Task Del(DictDataDelInput input) + { + var res = await _dbContext.Deleteable().Where(x => x.Id == input.Id).ExecuteCommandHasChangeAsync(); + return res; + } + /// + /// 详情 + /// + /// + /// + /// + [HttpGet] + public async Task Detail(string Id) + { + var entity = await _dbContext.Queryable().FirstAsync(x => x.Id == Id); + DictDataOutput output = entity.Adapt(); + return output; + } + /// + /// 列表 + /// + /// + /// + [HttpPost] + public async Task> List(DictDataQueryInput input) + { + if (!string.IsNullOrEmpty(input.TypeCode)) + { + var typeentity = await _dbContext.Queryable().Where(x => x.Code == input.TypeCode).FirstAsync(); + if (typeentity != null) + { + input.TypeId = typeentity.Id; + } + } + var entity = await _dbContext.Queryable().WhereIF(!string.IsNullOrEmpty(input.TypeId), x => x.TypeId == input.TypeId).ToListAsync(); + List output = entity.Adapt>(); + return output; + } + /// + /// 分页 + /// + /// + /// + [HttpPost] + public async Task> PagedList(DictDataQueryPageInput input) + { + var entity = await _dbContext.Queryable() + .WhereIF(!string.IsNullOrEmpty(input.Value), x => x.Value.Contains(input.Value)) + .WhereIF(!string.IsNullOrEmpty(input.Code), x => x.Code.Contains(input.Code)) + .WhereIF(!string.IsNullOrEmpty(input.TypeId),x=>x.TypeId==input.TypeId) + .ToPagedListAsync(input.PageIndex, input.PageSize); + SqlSugarPagedList output = entity.Adapt>(); + return output; + } + /// + /// 下拉 + /// + /// + /// + [HttpGet] + public async Task SelectList() + { + var entity = await _dbContext.Queryable().Select(x => new + { + key = x.Id, + value = x.Value + }).ToListAsync(); + return entity; + } + /// + /// 更新 + /// + /// + /// + /// + [HttpPost] + public async Task Update(DictDataUpdateInput input) + { + var entity = await _dbContext.Queryable().Where(x => x.Id == input.Id).FirstAsync(); + entity = input.Adapt(); + var res = await _dbContext.Updateable(entity).IgnoreColumns(true).ExecuteCommandHasChangeAsync(); + return res; + } + } +} diff --git a/backend/BPA.MES.Base.Application/Services/DictService/Services/DictTypeService.cs b/backend/BPA.MES.Base.Application/Services/DictService/Services/DictTypeService.cs new file mode 100644 index 0000000..9179b73 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/DictService/Services/DictTypeService.cs @@ -0,0 +1,110 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :码表类型管理 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/8/9 10:01:35 + /// 描 述 : + /// + [ApiDescriptionSettings("数据字典", Name = "DictType", Tag = "字典类型", KeepName = true, SplitCamelCase = true, KeepVerb = true)] + public class DictTypeService : IDictTypeService, ITransient, IDynamicApiController + { + private readonly ISqlSugarClient _dbContext; + public DictTypeService(ISqlSugarClient db) + { + _dbContext = db; + } + /// + /// 增加 + /// + /// + /// + [HttpPost] + public async Task Add(DictTypeAddInput input) + { + DictTypeEntity entity = input.Adapt(); + return await _dbContext.Insertable(entity).IgnoreColumns(ignoreNullColumn: true).ExecuteCommandIdentityIntoEntityAsync(); + } + /// + /// 删除 + /// + /// + /// + /// + [HttpPost] + public async Task Del(DictTypeDelInput input) + { + var res = await _dbContext.Deleteable().Where(x => x.Id == input.Id).ExecuteCommandHasChangeAsync(); + return res; + } + /// + /// 详情 + /// + /// + /// + /// + [HttpGet] + public async Task Detail(string Id) + { + var entity = await _dbContext.Queryable().FirstAsync(x => x.Id == Id); + DictTypeOutput output = entity.Adapt(); + return output; + } + /// + /// 列表 + /// + /// + /// + [HttpPost] + public async Task> List(DictTypeQueryInput input) + { + var entity = await _dbContext.Queryable().ToListAsync(); + List output = entity.Adapt>(); + return output; + } + /// + /// 分页 + /// + /// + /// + [HttpPost] + public async Task> PagedList(DictTypeQueryPageInput input) + { + var entity = await _dbContext.Queryable() + .WhereIF(!string.IsNullOrEmpty(input.Code), x => x.Code.Contains(input.Code)) + .WhereIF(!string.IsNullOrEmpty(input.Name), x => x.Name.Contains(input.Name)) + .ToPagedListAsync(input.PageIndex, input.PageSize); + SqlSugarPagedList output = entity.Adapt>(); + return output; + } + /// + /// 下拉 + /// + /// + /// + [HttpGet] + public async Task SelectList() + { + var entity = await _dbContext.Queryable().Select(x => new + { + key = x.Id, + value = x.Name + }).ToListAsync(); + return entity; + } + /// + /// 更新 + /// + /// + /// + /// + [HttpPost] + public async Task Update(DictTypeUpdateInput input) + { + var entity = await _dbContext.Queryable().Where(x => x.Id == input.Id).FirstAsync(); + entity = input.Adapt(); + var res = await _dbContext.Updateable(entity).IgnoreColumns(true).ExecuteCommandHasChangeAsync(); + return res; + } + } + } \ No newline at end of file diff --git a/backend/BPA.MES.Base.Application/Services/DictService/Services/IDictDataService.cs b/backend/BPA.MES.Base.Application/Services/DictService/Services/IDictDataService.cs new file mode 100644 index 0000000..fc989fd --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/DictService/Services/IDictDataService.cs @@ -0,0 +1,43 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :码表数据 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/8/9 10:00:06 + /// 描 述 : + /// + public interface IDictDataService + { + /// + /// 增加 + /// + /// + Task Add(DictDataAddInput input); + /// + /// 移除 + /// + /// + Task Del(DictDataDelInput input); + /// + /// 更新 + /// + /// + Task Update(DictDataUpdateInput input); + /// + /// 不分页列表 + /// + /// + Task> List(DictDataQueryInput input); + /// + /// 分页列表 + /// + /// + Task> PagedList(DictDataQueryPageInput input); + /// + /// 查询单条 + /// + /// + /// + Task Detail(string Id); + } +} diff --git a/backend/BPA.MES.Base.Application/Services/DictService/Services/IDictTypeService.cs b/backend/BPA.MES.Base.Application/Services/DictService/Services/IDictTypeService.cs new file mode 100644 index 0000000..be8b79d --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/DictService/Services/IDictTypeService.cs @@ -0,0 +1,44 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 : + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/8/9 10:00:23 + /// 描 述 : + /// + public interface IDictTypeService + { + /// + /// 增加 + /// + /// + Task Add(DictTypeAddInput input); + /// + /// 移除 + /// + /// + Task Del(DictTypeDelInput input); + /// + /// 更新 + /// + /// + Task Update(DictTypeUpdateInput input); + /// + /// 不分页列表 + /// + /// + Task> List(DictTypeQueryInput input); + /// + /// 分页列表 + /// + /// + Task> PagedList(DictTypeQueryPageInput input); + /// + /// 查询单条 + /// + /// + /// + Task Detail(string Id); + } +} + diff --git a/backend/BPA.MES.Base.Application/Services/FinalsInfoService/Dtos/FinalsInfoDto.cs b/backend/BPA.MES.Base.Application/Services/FinalsInfoService/Dtos/FinalsInfoDto.cs new file mode 100644 index 0000000..055da75 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/FinalsInfoService/Dtos/FinalsInfoDto.cs @@ -0,0 +1,87 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :成品管理 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/7/17 15:59:39 + /// 描 述 : + /// + public class FinalsInfoDto + { + /// + /// 成品编号 + /// + public string Code { get; set; } + /// + /// 成品名称 + /// + public string Name { get; set; } + /// + /// 配方Id + /// + public string RecipeId { get; set; } + /// + /// 工艺Id + /// + public string CraftId { get; set; } + } + /// + /// 增加 + /// + public class FinalsInfoAddInput : FinalsInfoDto + { + + } + /// + /// 更新 + /// + public class FinalsInfoUpdateInput : FinalsInfoDto + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 删除 + /// + public class FinalsInfoDelInput + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 分页 + /// + public class FinalsInfoQueryPageInput : RequestPage + { + /// + /// 名称 + /// + public string Name { get; set; } + /// + /// 编码 + /// + public string Code { get; set; } + } + /// + /// 输出 + /// + public class FinalsInfoOutput : FinalsInfoDto + { + /// + /// 主键 + /// + public string Id { get; set; } + /// + /// 配方名称 + /// + public string RecipeName { get; set; } + /// + /// 工艺名称 + /// + public string CraftName { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Services/FinalsInfoService/Services/FinalsInfoService.cs b/backend/BPA.MES.Base.Application/Services/FinalsInfoService/Services/FinalsInfoService.cs new file mode 100644 index 0000000..b258d0c --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/FinalsInfoService/Services/FinalsInfoService.cs @@ -0,0 +1,123 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :成品管理服务 + /// 创 建 人 :yangxiao + /// 创建时间 :2023/3/2 16:11:04 + /// 描 述 :基础数据管理 + /// + [ApiDescriptionSettings("基础数据管理", Order = 4, Name = "FinalsInfo", Tag = "成品管理服务", KeepName = true, SplitCamelCase = true, KeepVerb = true)] + public class FinalsInfoService : IFinalsInfoService, ITransient, IDynamicApiController + { + private readonly ISqlSugarClient _dbContext; + public FinalsInfoService(ISqlSugarClient db) + { + _dbContext = db; + } + /// + /// 增加 + /// + /// + /// + [HttpPost] + public async Task Add(FinalsInfoAddInput input) + { + var r_entity = await _dbContext.Queryable().FirstAsync(x => x.Name == input.Name); + if (r_entity != null) + { + throw Oops.Bah("名称已存在!"); + } + Pztj_FinalsInfoEntity entity = input.Adapt(); + return await _dbContext.Insertable(entity).IgnoreColumns(ignoreNullColumn: true).ExecuteCommandIdentityIntoEntityAsync(); + } + /// + /// 删除 + /// + /// + /// + /// + [HttpPost] + public async Task Del(FinalsInfoDelInput input) + { + var res = await _dbContext.Deleteable().Where(x => x.Id == input.Id).ExecuteCommandHasChangeAsync(); + return res; + } + /// + /// 详情 + /// + /// + /// + /// + [HttpGet] + public async Task Detail(string Id) + { + var entity = await _dbContext.Queryable().FirstAsync(x => x.Id == Id); + FinalsInfoOutput output = entity.Adapt(); + return output; + } + /// + /// 列表 + /// + /// + /// + [HttpGet] + public async Task> List() + { + var entity = await _dbContext.Queryable().ToListAsync(); + List output = entity.Adapt>(); + return output; + } + /// + /// 分页 + /// + /// + /// + [HttpPost] + public async Task> PagedList(FinalsInfoQueryPageInput input) + { + var entity = await _dbContext.Queryable() + .LeftJoin((a,b)=>a.CraftId==b.Id) + .LeftJoin((a, b, c) => a.RecipeId == c.Id) + .WhereIF(!string.IsNullOrEmpty(input.Name),a=>a.Name.Contains(input.Name)) + .WhereIF(!string.IsNullOrEmpty(input.Code), a => a.Name.Contains(input.Code)) + .Select((a,b,c)=> new FinalsInfoOutput + { + Id = a.Id.SelectAll(), + RecipeName = c.Name, + CraftName = b.Name + }) + .ToPagedListAsync(input.PageIndex, input.PageSize); + SqlSugarPagedList output = entity.Adapt>(); + return output; + } + /// + /// 下拉 + /// + /// + /// + [HttpGet] + public async Task SelectList() + { + var entity = await _dbContext.Queryable().Select(x => new + { + key = x.Id, + value = x.Name + }).ToListAsync(); + return entity; + } + /// + /// 更新 + /// + /// + /// + /// + [HttpPost] + public async Task Update(FinalsInfoUpdateInput input) + { + Pztj_FinalsInfoEntity entity = input.Adapt(); + var res = await _dbContext.Updateable(entity).IgnoreColumns(true).ExecuteCommandHasChangeAsync(); + return res; + } + } +} + diff --git a/backend/BPA.MES.Base.Application/Services/FinalsInfoService/Services/IFinalsInfoService.cs b/backend/BPA.MES.Base.Application/Services/FinalsInfoService/Services/IFinalsInfoService.cs new file mode 100644 index 0000000..2830188 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/FinalsInfoService/Services/IFinalsInfoService.cs @@ -0,0 +1,49 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :成品信息管理 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/7/17 16:02:25 + /// 描 述 : + /// + public interface IFinalsInfoService + { + /// + /// 增加 + /// + /// + Task Add(FinalsInfoAddInput input); + /// + /// 移除 + /// + /// + Task Del(FinalsInfoDelInput input); + /// + /// 更新 + /// + /// + Task Update(FinalsInfoUpdateInput input); + /// + /// 不分页列表 + /// + /// + Task> List(); + /// + /// 分页列表 + /// + /// + Task> PagedList(FinalsInfoQueryPageInput input); + /// + /// 下拉列表 + /// + /// + Task SelectList(); + /// + /// 查询单条 + /// + /// + /// + Task Detail(string Id); + } +} + diff --git a/backend/BPA.MES.Base.Application/Services/ICRUDService.cs b/backend/BPA.MES.Base.Application/Services/ICRUDService.cs new file mode 100644 index 0000000..5413cda --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/ICRUDService.cs @@ -0,0 +1,43 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 : + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/8/21 10:59:30 + /// 描 述 : + /// + public interface ICRUDService + { + /// + /// 增加 + /// + /// + Task Add(T input); + /// + /// 移除 + /// + /// + Task Del(T input); + /// + /// 更新 + /// + /// + Task Update(T input); + /// + /// 不分页列表 + /// + /// + Task> List(T input); + /// + /// 分页列表 + /// + /// + Task> PagedList(T input); + /// + /// 查询单条 + /// + /// + /// + Task Detail(string Id); + } +} diff --git a/backend/BPA.MES.Base.Application/Services/KepServerDataService/Dto/DataVDataDto.cs b/backend/BPA.MES.Base.Application/Services/KepServerDataService/Dto/DataVDataDto.cs new file mode 100644 index 0000000..faf4fe2 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/KepServerDataService/Dto/DataVDataDto.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BPA.MES.Base.Application.Services.KepServerDataService.Dto +{ + public class DataVDataDto + { + public string Key { get; set; } + + public string Value { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Services/KepServerDataService/Services/IKepDataService.cs b/backend/BPA.MES.Base.Application/Services/KepServerDataService/Services/IKepDataService.cs new file mode 100644 index 0000000..6971bf4 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/KepServerDataService/Services/IKepDataService.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BPA.MES.Base.Application.Services.KepServerDataService.Services +{ + + public interface IKepDataService + { + Task> GetList(); + } +} diff --git a/backend/BPA.MES.Base.Application/Services/KepServerDataService/Services/KepDataService.cs b/backend/BPA.MES.Base.Application/Services/KepServerDataService/Services/KepDataService.cs new file mode 100644 index 0000000..51e2e59 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/KepServerDataService/Services/KepDataService.cs @@ -0,0 +1,224 @@ +using BPA.MES.Base.Application.Entitys.KepData; +using FreeRedis; +using Furion.ClayObject.Extensions; +using Furion.RemoteRequest; +using Newtonsoft.Json; +//using ServiceStack.Redis; +using SqlSugar; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using Yitter.IdGenerator; +using static ServiceStack.Diagnostics.Events; + +namespace BPA.MES.Base.Application.Services.KepServerDataService.Services +{ + [AllowAnonymous] + [ApiDescriptionSettings("大屏数据", Order = 4, Name = "KepData", Tag = "大屏数据", KeepName = true, SplitCamelCase = true, KeepVerb = true)] + public class KepDataService: KepServerSqlsugar, IKepDataService,ITransient, IDynamicApiController + { + public KepDataService() + { + + } + [HttpPost] + public async Task> GetList() + { + //to_days(now()) - to_days(o._TIMESTAMP) = 1 + // to_days(o._TIMESTAMP) = to_days(now()) + var list = KepDb.Queryable().AS("ch01_device1", "o").Where(" to_days(o._TIMESTAMP) = to_days(now())").ToList(); + //var data =await KepDb.Queryable().Where(x=> SqlFunc.DateIsSame(x._TIMESTAMP, DateTime.Now)).Take(1000).ToListAsync(); + //var dicdatass = KepDb.Queryable().GroupBy(x => x._NAME).Where(x => SqlFunc.DateIsSame(x._TIMESTAMP, DateTime.Now)).Select(x => x._NAME).ToArray(); + //var dicdata = KepDb.Queryable().GroupBy(x => x._NAME).Where(x => SqlFunc.DateIsSame(x._TIMESTAMP, DateTime.Now)).Select(x=>x._NAME).ToDictionary(); + Dictionary dic = new Dictionary(); + //DataTable table = new DataTable(); + //foreach (var item in dicdatass) + //{ + // var key = item.ToString(); + // var values = data.Where(x => x._NAME == key).Select(x=>x._VALUE).ToList(); + // dic.Add(key, values); + //} + //var JsonString = JsonConvert.SerializeObject(dic); + return list; + } + [HttpGet] + [AllowAnonymous] + public async Task DeleteKep() + { + var sql = "delete from ch01_device1 where 1=1 order by id limit 1000;"; + var list = KepDb.Ado.ExecuteCommand(sql); + return true; + } + + public async Task GetA1() + { + //await using (RedisClient client = new RedisClient("10.2.1.21", 6379, "1178661552398188544", 0)) + //{ + // if (client == null) return string.Empty; + // string configData = client.Get("ns=2;s=CH1.Device1.A1"); + // return configData; + + //} + return ""; + } + + + [HttpGet] + [AllowAnonymous] + public Task CodeFirst() + { + var types = Assembly.Load("BPA.MES.Base.Application").GetTypes() + .Where(x => x.GetCustomAttribute() != null + && x.Namespace == "BPA.MES.Base.Application.Entitys.KepData").ToArray(); + KepDb.CodeFirst.InitTables(types); + return Task.FromResult(true); + } + + + /// + /// 添加报警限制 + /// + /// + /// + [HttpPost] + [AllowAnonymous] + public async Task AddDataVAlarmLimit(DataVAlarmLimit inputDto) + { + inputDto.Id = YitIdHelper.NextId().ToString(); + var res = await KepDb.Insertable(inputDto).ExecuteCommandAsync(); + return res > 0; + } + + /// + /// 修改报警限制 + /// + /// + /// + [HttpPost] + [AllowAnonymous] + public async Task UpdateDataVAlarmLimit(DataVAlarmLimit inputDto) + { + var res = await KepDb.Updateable(inputDto).ExecuteCommandAsync(); + return res > 0; + } + + /// + /// 获取报警限制 + /// + /// + [HttpPost] + [AllowAnonymous] + public async Task> GetDataVAlarmLimitList(RequestPage input) + { + var entity = await KepDb.Queryable() + .ToPagedListAsync(input.PageIndex, input.PageSize); + SqlSugarPagedList output = entity.Adapt>(); + return output; + } + + /// + /// 删除报警限制 + /// + /// + [HttpPost] + [AllowAnonymous] + public async Task DelDataVAlarmLimitList(string id) + { + var res = await KepDb.Deleteable().Where(x=>x.Id==id).ExecuteCommandAsync(); + return res>0; + } + + [HttpGet] + [AllowAnonymous] + public Dictionary GetDataVList() + { + + // var client = new ServiceStack.Redis.RedisClient("10.2.1.21", 6379, "1178661552398188544"); + + //var client = new RedisClient("10.2.1.21:6379,password=1178661552398188544,defaultDatabase=13"); + + + try + { + var client = new FreeRedis.RedisClient("10.2.1.21:6379,password=1178661552398188544,defaultDatabase=0"); + var res = new Dictionary(); + + for (int i = 1; i <= 28; i++) + { + var str = "ns=2;WFZ.Device1.A" + i; + var value = client.Get(str); + if (!string.IsNullOrEmpty(value)&&i!=4) + { + if (value.Length>=4) + { + value = value.Substring(0, 2); + } + } + res.Add("Device1.A" + i, value); + } + for (int i = 1; i <=31; i++) + { + var str = "ns=2;WFZ.Device2.A" + i; + var value = client.Get(str); + if (!string.IsNullOrEmpty(value) ) + { + if (value.Length >= 4) + { + value = value.Substring(0, 2); + } + } + res.Add("Device2.A" + i, value); + } + for (int i = 1; i <=7; i++) + { + var str = "ns=2;WFZ.Device3.A" + i; + var value = client.Get(str); + res.Add("Device3.A" + i, value); + } + for (int i = 1; i <= 1; i++) + { + var str = "ns=2;WFZ.Device4.A" + i; + var value = client.Get(str); + res.Add("Device4.A" + i, value); + } + return res; + } + catch (Exception e) + { + var res = new Dictionary(); + return res; + + } + + } + + [HttpGet] + [AllowAnonymous] + public async Task>> GetLogsAsync() + { + var result = new List>(); + var entity = await KepDb.Queryable().Where(x=>x.CreateTime.Date==DateTime.Now.Date).ToListAsync(); + + foreach (var item in entity) + { + var data = new List(); + var thisData = new object(); + + thisData = item.GetType().GetProperty("Name").GetValue(item, null); + data.Add(thisData == null ? "" : thisData.ToString()); + thisData = item.GetType().GetProperty("ValueStr").GetValue(item, null); + data.Add(thisData == null ? "" : thisData.ToString()); + thisData = item.GetType().GetProperty("CreateTime").GetValue(item, null); + data.Add(thisData == null ? "" : thisData.ToString()); + + result.Add(data); + } + return result; + } + } +} diff --git a/backend/BPA.MES.Base.Application/Services/LogService/Dtos/AlarmLogDto.cs b/backend/BPA.MES.Base.Application/Services/LogService/Dtos/AlarmLogDto.cs new file mode 100644 index 0000000..66420fd --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/LogService/Dtos/AlarmLogDto.cs @@ -0,0 +1,123 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 : + /// 创 建 人 :yangxiao + /// 创建时间 :2023/8/21 10:20:37 + /// 描 述 : + /// + public class AlarmLogDto + { + /// + /// 报警信息 + /// + public string MsgInfo { get; set; } + /// + /// 报警值 + /// + public string Value { get; set; } + /// + /// 报警等级 + /// + public string Grade { get; set; } + /// + /// 类型 + /// + public string LogType { get; set; } + /// + /// 设备名称 + /// + public string DeviceName { get; set; } + /// + /// 日期 + /// + public string Date { get; set; } + /// + /// 时间 + /// + public string Time { get; set; } + /// + /// 日志消息 + /// + public DateTime CreateDate { get; set; } + + } + /// + /// 增加 + /// + public class AlarmLogAddInput : AlarmLogDto + { + + } + /// + /// 更新 + /// + public class AlarmLogUpdateInput : AlarmLogDto + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 删除 + /// + public class AlarmLogDelInput + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 不分页 + /// + public class AlarmLogQueryInput + { + + } + /// + /// 分页 + /// + public class AlarmLogQueryPageInput : RequestPage + { + /// + /// 报警信息 + /// + public string MsgInfo { get; set; } + + /// + /// 报警值 + /// + public string Value { get; set; } + + /// + /// 报警等级 + /// + public string Grade { get; set; } + + /// + /// 设备名称 + /// + public string DeviceName { get; set; } + /// + /// 开始时间 + /// + public DateTime? StartTime { get; set; } + /// + /// 结束时间 + /// + public DateTime? EndTime { get; set; } + } + /// + /// 输出 + /// + public class AlarmLogOutput : AlarmLogDto + { + /// + /// 主键 + /// + public string Id { get; set; } + + } +} diff --git a/backend/BPA.MES.Base.Application/Services/LogService/Dtos/ProgramLogDto.cs b/backend/BPA.MES.Base.Application/Services/LogService/Dtos/ProgramLogDto.cs new file mode 100644 index 0000000..b39966a --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/LogService/Dtos/ProgramLogDto.cs @@ -0,0 +1,101 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 : + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/8/21 10:20:55 + /// 描 述 : + /// + public class ProgramLogDto + { + /// + /// 日志类型 + /// + public string LogType { get; set; } + + /// + /// 日志消息 + /// + public string MsgInfo { get; set; } + /// + /// 日期 + /// + public string Date { get; set; } + /// + /// 时间 + /// + public string Time { get; set; } + /// + /// 日志消息 + /// + public DateTime CreateDate { get; set; } + } + /// + /// 增加 + /// + public class ProgramLogAddInput : ProgramLogDto + { + + } + /// + /// 更新 + /// + public class ProgramLogUpdateInput : ProgramLogDto + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 删除 + /// + public class ProgramLogDelInput + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 不分页 + /// + public class ProgramLogQueryInput + { + + } + /// + /// 分页 + /// + public class ProgramLogQueryPageInput : RequestPage + { + /// + /// 日志类型 + /// + public string LogType { get; set; } + + /// + /// 日志消息 + /// + public string MsgInfo { get; set; } + /// + /// 开始时间 + /// + public DateTime? StartTime { get; set; } + /// + /// 结束时间 + /// + public DateTime? EndTime { get; set; } + } + /// + /// 输出 + /// + public class ProgramLogOutput : ProgramLogDto + { + /// + /// 主键 + /// + public string Id { get; set; } + + } +} diff --git a/backend/BPA.MES.Base.Application/Services/LogService/Dtos/RunLogDto.cs b/backend/BPA.MES.Base.Application/Services/LogService/Dtos/RunLogDto.cs new file mode 100644 index 0000000..da4598b --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/LogService/Dtos/RunLogDto.cs @@ -0,0 +1,99 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 : + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/8/21 10:21:11 + /// 描 述 : + /// + public class RunLogDto + { + /// + /// 日志类别 + /// + public string LogType { get; set; } + /// + /// 日志消息 + /// + public string MsgInfo { get; set; } + /// + /// 日期 + /// + public string Date { get; set; } + /// + /// 时间 + /// + public string Time { get; set; } + /// + /// 日志消息 + /// + public DateTime CreateDate { get; set; } + } + /// + /// 增加 + /// + public class RunLogAddInput : RunLogDto + { + + } + /// + /// 更新 + /// + public class RunLogUpdateInput : RunLogDto + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 删除 + /// + public class RunLogDelInput + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 不分页 + /// + public class RunLogQueryInput + { + + } + /// + /// 分页 + /// + public class RunLogQueryPageInput : RequestPage + { + /// + /// 日志类别 + /// + public string LogType { get; set; } + /// + /// 日志消息 + /// + public string MsgInfo { get; set; } + /// + /// 开始时间 + /// + public DateTime? StartTime { get; set; } + /// + /// 结束时间 + /// + public DateTime? EndTime { get; set; } + } + /// + /// 输出 + /// + public class RunLogOutput : RunLogDto + { + /// + /// 主键 + /// + public string Id { get; set; } + + } +} diff --git a/backend/BPA.MES.Base.Application/Services/LogService/Dtos/UserLogDto.cs b/backend/BPA.MES.Base.Application/Services/LogService/Dtos/UserLogDto.cs new file mode 100644 index 0000000..7216d5b --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/LogService/Dtos/UserLogDto.cs @@ -0,0 +1,91 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :用户权限 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/8/21 10:21:40 + /// 描 述 : + /// + public class UserLogDto + { + /// + /// 权限 + /// + public string Permission { get; set; } + + /// + /// 用户名 + /// + public string UserName { get; set; } + + /// + /// 日志消息 + /// + public string MsgInfo { get; set; } + /// + /// 日志时间 + /// + public DateTime CreateDate { get; set; } + } + /// + /// 增加 + /// + public class UserLogAddInput : UserLogDto + { + + } + /// + /// 更新 + /// + public class UserLogUpdateInput : UserLogDto + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 删除 + /// + public class UserLogDelInput + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 不分页 + /// + public class UserLogQueryInput + { + + } + /// + /// 分页 + /// + public class UserLogQueryPageInput : RequestPage + { + + /// + /// 用户名 + /// + public string UserName { get; set; } + + /// + /// 日志消息 + /// + public string MsgInfo { get; set; } + } + /// + /// 输出 + /// + public class UserLogOutput : UserLogDto + { + /// + /// 主键 + /// + public string Id { get; set; } + + } +} diff --git a/backend/BPA.MES.Base.Application/Services/LogService/Services/AlarmLogService.cs b/backend/BPA.MES.Base.Application/Services/LogService/Services/AlarmLogService.cs new file mode 100644 index 0000000..4b27e13 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/LogService/Services/AlarmLogService.cs @@ -0,0 +1,100 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :报警日志 + /// 创 建 人 :yangxiao + /// 创建时间 :2023/8/21 11:02:36 + /// 描 述 : + /// + [ApiDescriptionSettings("数据日志", Name = "AlarmLog", Tag = "报警日志", KeepName = true, SplitCamelCase = true, KeepVerb = true)] + public class AlarmLogService : IAlarmLogService, ITransient, IDynamicApiController + { + private readonly ISqlSugarClient _dbContext; + public AlarmLogService(ISqlSugarClient db) + { + _dbContext = db; + } + /// + /// 增加 + /// + /// + /// + [HttpPost] + public async Task Add(AlarmLogAddInput input) + { + AlarmLogEntity entity = input.Adapt(); + return await _dbContext.Insertable(entity).IgnoreColumns(ignoreNullColumn: true).ExecuteCommandIdentityIntoEntityAsync(); + } + /// + /// 删除 + /// + /// + /// + /// + [HttpPost] + public async Task Del(AlarmLogDelInput input) + { + var res = await _dbContext.Deleteable().Where(x => x.Id == input.Id).ExecuteCommandHasChangeAsync(); + return res; + } + /// + /// 详情 + /// + /// + /// + /// + [HttpGet] + public async Task Detail(string Id) + { + var entity = await _dbContext.Queryable().FirstAsync(x => x.Id == Id); + AlarmLogOutput output = entity.Adapt(); + return output; + } + /// + /// 列表 + /// + /// + /// + [HttpPost] + public async Task> List(AlarmLogQueryInput input) + { + var entity = await _dbContext.Queryable().ToListAsync(); + List output = entity.Adapt>(); + return output; + } + /// + /// 分页 + /// + /// + /// + [HttpPost] + public async Task> PagedList(AlarmLogQueryPageInput input) + { + var entity = await _dbContext.Queryable() + .WhereIF(!string.IsNullOrEmpty(input.DeviceName), x => x.DeviceName.Contains(input.DeviceName)) + .WhereIF(!string.IsNullOrEmpty(input.Grade), x => x.Grade.Contains(input.Grade)) + .WhereIF(!string.IsNullOrEmpty(input.MsgInfo), x => x.MsgInfo.Contains(input.MsgInfo)) + .WhereIF(!string.IsNullOrEmpty(input.Value), x => x.Value.Contains(input.Value)) + .WhereIF(input.StartTime.HasVal(), x => x.CreateDate >= input.StartTime.Value) + .WhereIF(input.EndTime.HasVal(), x => x.CreateDate <= input.EndTime.Value) + .OrderByDescending(x=>x.CreateDate) + .ToPagedListAsync(input.PageIndex, input.PageSize); + SqlSugarPagedList output = entity.Adapt>(); + return output; + } + /// + /// 更新 + /// + /// + /// + /// + [HttpPost] + public async Task Update(AlarmLogUpdateInput input) + { + var entity = await _dbContext.Queryable().Where(x => x.Id == input.Id).FirstAsync(); + entity = input.Adapt(); + var res = await _dbContext.Updateable(entity).IgnoreColumns(true).ExecuteCommandHasChangeAsync(); + return res; + } + } +} \ No newline at end of file diff --git a/backend/BPA.MES.Base.Application/Services/LogService/Services/IAlarmLogService.cs b/backend/BPA.MES.Base.Application/Services/LogService/Services/IAlarmLogService.cs new file mode 100644 index 0000000..a6c9d1b --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/LogService/Services/IAlarmLogService.cs @@ -0,0 +1,43 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 : + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/8/21 10:30:26 + /// 描 述 : + /// + public interface IAlarmLogService + { + /// + /// 增加 + /// + /// + Task Add(AlarmLogAddInput input); + /// + /// 移除 + /// + /// + Task Del(AlarmLogDelInput input); + /// + /// 更新 + /// + /// + Task Update(AlarmLogUpdateInput input); + /// + /// 不分页列表 + /// + /// + Task> List(AlarmLogQueryInput input); + /// + /// 分页列表 + /// + /// + Task> PagedList(AlarmLogQueryPageInput input); + /// + /// 查询单条 + /// + /// + /// + Task Detail(string Id); + } +} diff --git a/backend/BPA.MES.Base.Application/Services/LogService/Services/IProgramLogService.cs b/backend/BPA.MES.Base.Application/Services/LogService/Services/IProgramLogService.cs new file mode 100644 index 0000000..b8e5ae3 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/LogService/Services/IProgramLogService.cs @@ -0,0 +1,43 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 : + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/8/21 10:30:39 + /// 描 述 : + /// + public interface IProgramLogService + { + /// + /// 增加 + /// + /// + Task Add(ProgramLogAddInput input); + /// + /// 移除 + /// + /// + Task Del(ProgramLogDelInput input); + /// + /// 更新 + /// + /// + Task Update(ProgramLogUpdateInput input); + /// + /// 不分页列表 + /// + /// + Task> List(ProgramLogQueryInput input); + /// + /// 分页列表 + /// + /// + Task> PagedList(ProgramLogQueryPageInput input); + /// + /// 查询单条 + /// + /// + /// + Task Detail(string Id); + } +} diff --git a/backend/BPA.MES.Base.Application/Services/LogService/Services/IRunLogService.cs b/backend/BPA.MES.Base.Application/Services/LogService/Services/IRunLogService.cs new file mode 100644 index 0000000..13687cd --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/LogService/Services/IRunLogService.cs @@ -0,0 +1,43 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 : + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/8/21 10:30:53 + /// 描 述 : + /// + public interface IRunLogService + { + /// + /// 增加 + /// + /// + Task Add(RunLogAddInput input); + /// + /// 移除 + /// + /// + Task Del(RunLogDelInput input); + /// + /// 更新 + /// + /// + Task Update(RunLogUpdateInput input); + /// + /// 不分页列表 + /// + /// + Task> List(RunLogQueryInput input); + /// + /// 分页列表 + /// + /// + Task> PagedList(RunLogQueryPageInput input); + /// + /// 查询单条 + /// + /// + /// + Task Detail(string Id); + } +} diff --git a/backend/BPA.MES.Base.Application/Services/LogService/Services/IUserLogService.cs b/backend/BPA.MES.Base.Application/Services/LogService/Services/IUserLogService.cs new file mode 100644 index 0000000..e53ad63 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/LogService/Services/IUserLogService.cs @@ -0,0 +1,43 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 : + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/8/21 10:31:05 + /// 描 述 : + /// + public interface IUserLogService + { + /// + /// 增加 + /// + /// + Task Add(UserLogAddInput input); + /// + /// 移除 + /// + /// + Task Del(UserLogDelInput input); + /// + /// 更新 + /// + /// + Task Update(UserLogUpdateInput input); + /// + /// 不分页列表 + /// + /// + Task> List(UserLogQueryInput input); + /// + /// 分页列表 + /// + /// + Task> PagedList(UserLogQueryPageInput input); + /// + /// 查询单条 + /// + /// + /// + Task Detail(string Id); + } +} diff --git a/backend/BPA.MES.Base.Application/Services/LogService/Services/ProgramLogService.cs b/backend/BPA.MES.Base.Application/Services/LogService/Services/ProgramLogService.cs new file mode 100644 index 0000000..c169424 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/LogService/Services/ProgramLogService.cs @@ -0,0 +1,98 @@ +namespace BPA.MES.Base.Application.Services.LogService.Services +{ + /// + /// 名 称 :系统日志 + /// 创 建 人 :yangxiao + /// 创建时间 :2023/8/21 11:16:20 + /// 描 述 : + /// + [ApiDescriptionSettings("数据日志", Name = "ProgramLog", Tag = "系统日志", KeepName = true, SplitCamelCase = true, KeepVerb = true)] + public class ProgramLogService : IProgramLogService, ITransient, IDynamicApiController + { + private readonly ISqlSugarClient _dbContext; + public ProgramLogService(ISqlSugarClient db) + { + _dbContext = db; + } + /// + /// 增加 + /// + /// + /// + [HttpPost] + public async Task Add(ProgramLogAddInput input) + { + ProgramLogEntity entity = input.Adapt(); + return await _dbContext.Insertable(entity).IgnoreColumns(ignoreNullColumn: true).ExecuteCommandIdentityIntoEntityAsync(); + } + /// + /// 删除 + /// + /// + /// + /// + [HttpPost] + public async Task Del(ProgramLogDelInput input) + { + var res = await _dbContext.Deleteable().Where(x => x.Id == input.Id).ExecuteCommandHasChangeAsync(); + return res; + } + /// + /// 详情 + /// + /// + /// + /// + [HttpGet] + public async Task Detail(string Id) + { + var entity = await _dbContext.Queryable().FirstAsync(x => x.Id == Id); + ProgramLogOutput output = entity.Adapt(); + return output; + } + /// + /// 列表 + /// + /// + /// + [HttpPost] + public async Task> List(ProgramLogQueryInput input) + { + var entity = await _dbContext.Queryable().ToListAsync(); + List output = entity.Adapt>(); + return output; + } + /// + /// 分页 + /// + /// + /// + [HttpPost] + public async Task> PagedList(ProgramLogQueryPageInput input) + { + var entity = await _dbContext.Queryable() + .WhereIF(input.LogType != null, x => x.LogType == input.LogType) + .WhereIF(!string.IsNullOrEmpty(input.MsgInfo), x => x.MsgInfo.Contains(input.MsgInfo)) + .WhereIF(input.StartTime.HasVal(), x => x.CreateDate >= input.StartTime.Value) + .WhereIF(input.EndTime.HasVal(), x => x.CreateDate <= input.EndTime.Value) + .OrderByDescending(x => x.CreateDate) + .ToPagedListAsync(input.PageIndex, input.PageSize); + SqlSugarPagedList output = entity.Adapt>(); + return output; + } + /// + /// 更新 + /// + /// + /// + /// + [HttpPost] + public async Task Update(ProgramLogUpdateInput input) + { + var entity = await _dbContext.Queryable().Where(x => x.Id == input.Id).FirstAsync(); + entity = input.Adapt(); + var res = await _dbContext.Updateable(entity).IgnoreColumns(true).ExecuteCommandHasChangeAsync(); + return res; + } + } +} diff --git a/backend/BPA.MES.Base.Application/Services/LogService/Services/RunLogService.cs b/backend/BPA.MES.Base.Application/Services/LogService/Services/RunLogService.cs new file mode 100644 index 0000000..759ef34 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/LogService/Services/RunLogService.cs @@ -0,0 +1,99 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :运行日志 + /// 创 建 人 :yangxiao + /// 创建时间 :2023/8/21 11:16:32 + /// 描 述 : + /// + [ApiDescriptionSettings("数据日志", Name = "RunLog", Tag = "运行日志", KeepName = true, SplitCamelCase = true, KeepVerb = true)] + public class RunLogService : IRunLogService, ITransient, IDynamicApiController + { + private readonly ISqlSugarClient _dbContext; + public RunLogService(ISqlSugarClient db) + { + _dbContext = db; + } + /// + /// 增加 + /// + /// + /// + [HttpPost] + public async Task Add(RunLogAddInput input) + { + RunLogEntity entity = input.Adapt(); + return await _dbContext.Insertable(entity).IgnoreColumns(ignoreNullColumn: true).ExecuteCommandIdentityIntoEntityAsync(); + } + /// + /// 删除 + /// + /// + /// + /// + [HttpPost] + public async Task Del(RunLogDelInput input) + { + var res = await _dbContext.Deleteable().Where(x => x.Id == input.Id).ExecuteCommandHasChangeAsync(); + return res; + } + /// + /// 详情 + /// + /// + /// + /// + [HttpGet] + public async Task Detail(string Id) + { + var entity = await _dbContext.Queryable().FirstAsync(x => x.Id == Id); + RunLogOutput output = entity.Adapt(); + return output; + } + /// + /// 列表 + /// + /// + /// + [HttpPost] + public async Task> List(RunLogQueryInput input) + { + var entity = await _dbContext.Queryable().ToListAsync(); + List output = entity.Adapt>(); + return output; + } + /// + /// 分页 + /// + /// + /// + [HttpPost] + public async Task> PagedList(RunLogQueryPageInput input) + { + var entity = await _dbContext.Queryable() + .WhereIF(!string.IsNullOrEmpty(input.LogType), x => x.LogType.Contains(input.LogType)) + .WhereIF(!string.IsNullOrEmpty(input.MsgInfo), x => x.MsgInfo.Contains(input.MsgInfo)) + .WhereIF(input.StartTime.HasVal(), x => x.CreateDate >= input.StartTime.Value) + .WhereIF(input.EndTime.HasVal(), x => x.CreateDate <= input.EndTime.Value) + //.SplitTable(input.StartTime.Value, input.EndTime.Value) + .OrderByDescending(x => x.CreateDate) + .ToPagedListAsync(input.PageIndex, input.PageSize); + SqlSugarPagedList output = entity.Adapt>(); + return output; + } + /// + /// 更新 + /// + /// + /// + /// + [HttpPost] + public async Task Update(RunLogUpdateInput input) + { + var entity = await _dbContext.Queryable().Where(x => x.Id == input.Id).FirstAsync(); + entity = input.Adapt(); + var res = await _dbContext.Updateable(entity).IgnoreColumns(true).ExecuteCommandHasChangeAsync(); + return res; + } + } +} \ No newline at end of file diff --git a/backend/BPA.MES.Base.Application/Services/LogService/Services/UserLogService.cs b/backend/BPA.MES.Base.Application/Services/LogService/Services/UserLogService.cs new file mode 100644 index 0000000..af24f2a --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/LogService/Services/UserLogService.cs @@ -0,0 +1,95 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :用户操作日志 + /// 创 建 人 :yangxiao + /// 创建时间 :2023/8/21 11:16:44 + /// 描 述 : + /// + [ApiDescriptionSettings("数据日志", Name = "UserLog", Tag = "用户操作日志", KeepName = true, SplitCamelCase = true, KeepVerb = true)] + public class UserLogService : IUserLogService, ITransient, IDynamicApiController + { + private readonly ISqlSugarClient _dbContext; + public UserLogService(ISqlSugarClient db) + { + _dbContext = db; + } + /// + /// 增加 + /// + /// + /// + [HttpPost] + public async Task Add(UserLogAddInput input) + { + UserLogEntity entity = input.Adapt(); + return await _dbContext.Insertable(entity).IgnoreColumns(ignoreNullColumn: true).ExecuteCommandIdentityIntoEntityAsync(); + } + /// + /// 删除 + /// + /// + /// + /// + [HttpPost] + public async Task Del(UserLogDelInput input) + { + var res = await _dbContext.Deleteable().Where(x => x.Id == input.Id).ExecuteCommandHasChangeAsync(); + return res; + } + /// + /// 详情 + /// + /// + /// + /// + [HttpGet] + public async Task Detail(string Id) + { + var entity = await _dbContext.Queryable().FirstAsync(x => x.Id == Id); + UserLogOutput output = entity.Adapt(); + return output; + } + /// + /// 列表 + /// + /// + /// + [HttpPost] + public async Task> List(UserLogQueryInput input) + { + var entity = await _dbContext.Queryable().ToListAsync(); + List output = entity.Adapt>(); + return output; + } + /// + /// 分页 + /// + /// + /// + [HttpPost] + public async Task> PagedList(UserLogQueryPageInput input) + { + var entity = await _dbContext.Queryable() + .WhereIF(!string.IsNullOrEmpty(input.UserName), x => x.UserName.Contains(input.UserName)) + .WhereIF(!string.IsNullOrEmpty(input.MsgInfo), x => x.MsgInfo.Contains(input.MsgInfo)) + .ToPagedListAsync(input.PageIndex, input.PageSize); + SqlSugarPagedList output = entity.Adapt>(); + return output; + } + /// + /// 更新 + /// + /// + /// + /// + [HttpPost] + public async Task Update(UserLogUpdateInput input) + { + var entity = await _dbContext.Queryable().Where(x => x.Id == input.Id).FirstAsync(); + entity = input.Adapt(); + var res = await _dbContext.Updateable(entity).IgnoreColumns(true).ExecuteCommandHasChangeAsync(); + return res; + } + } +} diff --git a/backend/BPA.MES.Base.Application/Services/MaterialService/Dtos/MaterialsInfoDto.cs b/backend/BPA.MES.Base.Application/Services/MaterialService/Dtos/MaterialsInfoDto.cs new file mode 100644 index 0000000..1404191 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/MaterialService/Dtos/MaterialsInfoDto.cs @@ -0,0 +1,97 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :设备Dto类 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/3/2 16:12:06 + /// 描 述 : + /// + public class MaterialsInfoDto + { + /// + /// 原料名称 + /// + /// + public string Name { get; set; } + /// + /// 原料编号 + /// + /// + public string Code { get; set; } + /// + /// 原料单位 + /// + /// + public string Unit { get; set; } + /// + /// 原料分组 + /// + /// + public string Type { get; set; } + /// + /// 每升重量 + /// + + public string WeightPerLiter { get; set; } + } + /// + /// 增加 + /// + public class MaterialsInfoAddInput : MaterialsInfoDto + { + + } + /// + /// 更新 + /// + public class MaterialsInfoUpdateInput : MaterialsInfoDto + { + /// + /// 主键 + /// + /// + public string Id { get; set; } + } + /// + /// 删除 + /// + public class MaterialsInfoDelInput + { + /// + /// 主键 + /// + /// + public string Id { get; set; } + } + /// + /// 分页 + /// + public class MaterialsInfoQueryPageInput : RequestPage + { + /// + /// 名称 + /// + /// + public string Name { get; set; } + /// + /// 编码 + /// + /// + public string Code { get; set; } + } + /// + /// 输出 + /// + public class MaterialsInfoOutput : MaterialsInfoDto + { + /// + /// 主键 + /// + /// + public string Id { get; set; } + /// + /// 类型名称 + /// + public string TypeName { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Services/MaterialService/Services/IMaterialsInfoService.cs b/backend/BPA.MES.Base.Application/Services/MaterialService/Services/IMaterialsInfoService.cs new file mode 100644 index 0000000..d38613d --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/MaterialService/Services/IMaterialsInfoService.cs @@ -0,0 +1,48 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :物料服务 + /// 创 建 人 :yangxiao + /// 创建时间 :2023/3/2 18:31:53 + /// 描 述 : + /// + public interface IMaterialsInfoService + { + /// + /// 增加 + /// + /// + Task Add(MaterialsInfoAddInput input); + /// + /// 移除 + /// + /// + Task Del(MaterialsInfoDelInput input); + /// + /// 更新 + /// + /// + Task Update(MaterialsInfoUpdateInput input); + /// + /// 不分页列表 + /// + /// + Task> List(); + /// + /// 分页列表 + /// + /// + Task> PagedList(MaterialsInfoQueryPageInput input); + /// + /// 下拉列表 + /// + /// + Task SelectList(); + /// + /// 查询单条 + /// + /// + /// + Task Detail(string Id); + } +} diff --git a/backend/BPA.MES.Base.Application/Services/MaterialService/Services/MaterialsInfoService.cs b/backend/BPA.MES.Base.Application/Services/MaterialService/Services/MaterialsInfoService.cs new file mode 100644 index 0000000..269dfae --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/MaterialService/Services/MaterialsInfoService.cs @@ -0,0 +1,133 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :原料服务 + /// 创 建 人 :yangxiao + /// 创建时间 :2023年7月17日15:41:09 + /// 描 述 :基础数据管理 + /// + [ApiDescriptionSettings("基础数据管理", Order = 2, Name = "MaterialsInfo", Tag = "原料服务", KeepName = true, SplitCamelCase = true, KeepVerb = true)] + public class MaterialsInfoService : IMaterialsInfoService, ITransient, IDynamicApiController + { + private readonly ISqlSugarClient _dbContext; + public MaterialsInfoService(ISqlSugarClient db) + { + _dbContext = db; + } + /// + /// 增加 + /// + /// + /// + [HttpPost] + public async Task Add(MaterialsInfoAddInput input) + { + var r_entity = await _dbContext.Queryable().FirstAsync(x => x.Name == input.Name); + if (r_entity != null) + { + throw Oops.Bah("名称已存在!"); + } + Pztj_MaterialsInfoEntity entity = input.Adapt(); + return await _dbContext.Insertable(entity).IgnoreColumns(ignoreNullColumn: true).ExecuteCommandIdentityIntoEntityAsync(); + } + /// + /// 删除 + /// + /// + /// + /// + [HttpPost] + public async Task Del(MaterialsInfoDelInput input) + { + var res = await _dbContext.Deleteable().Where(x => x.Id == input.Id).ExecuteCommandHasChangeAsync(); + return res; + } + /// + /// 详情 + /// + /// + /// + /// + [HttpGet] + public async Task Detail(string Id) + { + var output = await _dbContext.Queryable() + .LeftJoin((a,b)=>a.Type==b.Id) + .Where((a,b)=> a.Id == Id) + .Select((a,b)=>new MaterialsInfoOutput + { + Id=a.Id.SelectAll(), + TypeName = b.Value + }) + .FirstAsync(); + return output; + } + /// + /// 列表 + /// + /// + /// + [HttpGet] + public async Task> List() + { + var output = await _dbContext.Queryable() + .LeftJoin((a, b) => a.Type == b.Id) + .Select((a, b) => new MaterialsInfoOutput + { + Id = a.Id.SelectAll(), + TypeName = b.Value + }) + .ToListAsync(); + return output; + } + /// + /// 分页 + /// + /// + /// + [HttpPost] + public async Task> PagedList(MaterialsInfoQueryPageInput input) + { + var output = await _dbContext.Queryable() + .LeftJoin((a, b) => a.Type == b.Id) + .WhereIF(!string.IsNullOrEmpty(input.Name), (a, b) => a.Name.Contains(input.Name)) + .WhereIF(!string.IsNullOrEmpty(input.Code), (a, b) => a.Code.Contains(input.Code)) + .Select((a, b) => new MaterialsInfoOutput + { + Id = a.Id.SelectAll(), + TypeName = b.Value + }) + .ToPagedListAsync(input.PageIndex, input.PageSize); + return output; + } + /// + /// 下拉 + /// + /// + /// + [HttpGet] + public async Task SelectList() + { + var entity = await _dbContext.Queryable().Select(x => new + { + key = x.Id, + value = x.Name + }).ToListAsync(); + return entity; + } + /// + /// 更新 + /// + /// + /// + /// + [HttpPost] + public async Task Update(MaterialsInfoUpdateInput input) + { + var entity = await _dbContext.Queryable().Where(x => x.Id == input.Id).FirstAsync(); + entity = input.Adapt(); + var res = await _dbContext.Updateable(entity).IgnoreColumns(true).ExecuteCommandHasChangeAsync(); + return res; + } + } +} diff --git a/backend/BPA.MES.Base.Application/Services/OperLogService/Dtos/OperLogDto.cs b/backend/BPA.MES.Base.Application/Services/OperLogService/Dtos/OperLogDto.cs new file mode 100644 index 0000000..2c61f9f --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/OperLogService/Dtos/OperLogDto.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 : + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/7/20 15:15:48 + /// 描 述 : + /// + public class OperLogDto + { + /// + /// 操作标题 + /// + public string Name { get; set; } + /// + /// 内容 + /// + public string Context { get; set; } + /// + /// 创建时间 + /// + public DateTime CreateTime { get; set; } + } + /// + /// 增加 + /// + public class OperLogAddInput: OperLogDto + { + } + +} diff --git a/backend/BPA.MES.Base.Application/Services/OperLogService/Services/IOperLogService.cs b/backend/BPA.MES.Base.Application/Services/OperLogService/Services/IOperLogService.cs new file mode 100644 index 0000000..5156141 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/OperLogService/Services/IOperLogService.cs @@ -0,0 +1,17 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :日志服务 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/7/20 15:17:58 + /// 描 述 : + /// + public interface IOperLogService + { + /// + /// 增加 + /// + /// + Task Add(WorkInfoAddInput input); + } +} diff --git a/backend/BPA.MES.Base.Application/Services/OperLogService/Services/OperLogService.cs b/backend/BPA.MES.Base.Application/Services/OperLogService/Services/OperLogService.cs new file mode 100644 index 0000000..7f2e3c0 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/OperLogService/Services/OperLogService.cs @@ -0,0 +1,12 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :操作日志 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/7/20 15:17:24 + /// 描 述 : + /// + public class OperLogService + { + } +} diff --git a/backend/BPA.MES.Base.Application/Services/OrderService/Dtos/OrderBaseDto.cs b/backend/BPA.MES.Base.Application/Services/OrderService/Dtos/OrderBaseDto.cs new file mode 100644 index 0000000..6724fbe --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/OrderService/Dtos/OrderBaseDto.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BPA.MES.Base.Application.Services.OrderService.Dtos +{ + public class OrderBaseDto + { + public string Id { get; set; } + + + /// + /// 状态 + /// + public int Status { get; set; } + + /// + /// 分配进度 + /// + public decimal AllocationRate { get; set; } + + /// + /// 生产进度 + /// + public decimal ProduceRate { get; set; } + + public decimal ProduceSum { get; set; } + + public DateTime CreateTime { get; set; } + + public List OrderInfos { get; set; } + } + + public class OrderInfoBaseDto + { + public string Id { get; set; } + + public string OrderId { get; set; } + + /// + /// 成品 + /// + public string FinalslId { get; set; } + + public string FinalslName { get; set; } + + /// + /// 产线 + /// + public string ProductionLineId { get; set; } + + public string ProductionLineName { get; set; } + + public string CreateTime { get; set; } + + /// + /// 数量 + /// + public decimal Number { get; set; } + public WorkOrderStatusEnum? Status { get; set; } + } + + /// + /// 成品数量限制 + /// + public class OrderWorkLimit + { + /// + /// 成品 + /// + public string FinalslId { get; set; } + + public decimal Limit { get; set; } + + } +} diff --git a/backend/BPA.MES.Base.Application/Services/OrderService/Dtos/OrderQueryPageInput.cs b/backend/BPA.MES.Base.Application/Services/OrderService/Dtos/OrderQueryPageInput.cs new file mode 100644 index 0000000..fda408d --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/OrderService/Dtos/OrderQueryPageInput.cs @@ -0,0 +1,16 @@ +using BPA.MES.Base.Application.Const; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BPA.MES.Base.Application.Services.OrderService.Dtos +{ + public class OrderQueryPageInput: RequestPage + { + public string Id { get; set; } + + public string Status { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Services/OrderService/Service/IOrderService.cs b/backend/BPA.MES.Base.Application/Services/OrderService/Service/IOrderService.cs new file mode 100644 index 0000000..c06f8ca --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/OrderService/Service/IOrderService.cs @@ -0,0 +1,57 @@ +using BPA.MES.Base.Application.Services.OrderService.Dtos; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BPA.MES.Base.Application.Services.OrderService.Service +{ + public interface IOrderService + { + /// + /// 分页列表 + /// + /// + Task> PagedList(OrderQueryPageInput input); + + /// + /// 新增 + /// + /// + /// + Task Add(List inputDto); + + /// + /// 修改 + /// + /// + /// + + Task Update(List inputDto); + + /// + /// 获取订单的商品 + /// + /// + /// + Task> GetOrderMaterial(string OrderId); + + + /// + /// 添加工单 并绑定订单 + /// + /// + /// + Task OrderAssociationWork(List inputDto); + + /// + /// 获取成品剩余制作数量 + /// + /// + /// + Task> GetFinalslLImit(string OrderId); + + Task CodeFirst(); + } +} diff --git a/backend/BPA.MES.Base.Application/Services/OrderService/Service/OrderService.cs b/backend/BPA.MES.Base.Application/Services/OrderService/Service/OrderService.cs new file mode 100644 index 0000000..a3c725d --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/OrderService/Service/OrderService.cs @@ -0,0 +1,374 @@ +using BPA.MES.Base.Application.Const; +using BPA.MES.Base.Application.Entitys.Order; +using BPA.MES.Base.Application.Services.OrderService.Dtos; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using Yitter.IdGenerator; + +namespace BPA.MES.Base.Application.Services.OrderService.Service +{ + [ApiDescriptionSettings("订单管理", Order = 2, Name = "Order", Tag = "订单信息", KeepName = true, SplitCamelCase = true, KeepVerb = true)] + public class OrderService : IOrderService, ITransient, IDynamicApiController + { + private readonly ISqlSugarClient _dbContext; + public OrderService(ISqlSugarClient db) + { + _dbContext = db; + } + + /// + /// 分页列表 + /// + /// + [HttpPost] + public async Task> PagedList(OrderQueryPageInput input) + { + var entity = await _dbContext.Queryable() + .WhereIF(!string.IsNullOrEmpty(input.Id), a => a.Id.Contains(input.Id)) + .WhereIF(!string.IsNullOrEmpty(input.Status), a => ((int)a.Status).ToString()==input.Status) + .Select((x) => new OrderBaseDto + { + Id = x.Id.SelectAll(), + }) + .ToPagedListAsync(input.PageIndex, input.PageSize); + + + var orderIds= entity.Items.Select(x => x.Id); + + var itemList = await _dbContext.Queryable() + .Where(x => orderIds.Contains(x.OrderId)) + .ToListAsync(); + + var list = await _dbContext.Queryable() + .LeftJoin((a, b) => a.FinalId == b.Id) + .LeftJoin((a, b, c) => a.LineId == c.Id) + .LeftJoin((a, b, c, d) => d.Id == SqlFunc.Subqueryable().Where(s => s.WorkId == a.Id).OrderByDesc(s => s.CreateTime).Select(s => s.Id)) + .LeftJoin((a, b, c, d,e) =>a.Id==e.WorkId ) + .Where((a, b, c, d, e)=> orderIds.Contains(e.OrderId)) + .Select((a, b, c, d,e) => new OrderInfoBaseDto + { + FinalslId=a.FinalId, + FinalslName=b.Name, + Number=string.IsNullOrEmpty(a.Number)?0:Convert.ToInt32(a.Number), + OrderId=e.OrderId, + ProductionLineId=a.LineId, + ProductionLineName=c.Name, + Id = a.Id, + CreateTime=a.CreateTime.ToString(), + Status = d.Status == null ? WorkOrderStatusEnum.Draft : d.Status + }).ToListAsync(); + + SqlSugarPagedList output = entity.Adapt>(); + foreach (var item in output.Items) + { + item.OrderInfos= list.Where(x=>x.OrderId==item.Id).ToList(); + item.ProduceRate= list.Where(x => x.OrderId == item.Id&&x.Status== WorkOrderStatusEnum.Completed).Count(); + item.ProduceSum = itemList.Where(x => x.OrderId == item.Id).Sum(x => x.Number); + } + return output; + } + + /// + /// 新增 + /// + /// + /// + [HttpPost] + public async Task Add(List inputDto) + { + + try + { + + _dbContext.Ado.BeginTran(); + OrderEntity order = new OrderEntity(); + var res = await _dbContext.Insertable(order) + .IgnoreColumns(ignoreNullColumn: true) + .ExecuteCommandIdentityIntoEntityAsync(); + if (res) + { + List orderInfo = inputDto.Adapt>(); + orderInfo = orderInfo.GroupBy(x => x.FinalslId).Select(x => new OrderInfoEntity() + { + CreateTime = DateTime.Now, + FinalslId = x.Key, + Number = x.Sum(y => y.Number), + }).ToList(); + foreach (var item in orderInfo) + { + item.Id = YitIdHelper.NextId().ToString(); + item.OrderId = order.Id; + } + res = await _dbContext.Insertable(orderInfo) + .ExecuteCommandIdentityIntoEntityAsync(); + } + + _dbContext.Ado.CommitTran(); + return res; + } + catch (Exception ex) + { + _dbContext.Ado.RollbackTran(); + return false; + } + } + + /// + /// 修改 + /// + /// + /// + [HttpPost] + public async Task Update(List inputDto) + { + try + { + + _dbContext.Ado.BeginTran(); + var orderId = inputDto.Select(x => x.OrderId).First(); + + //删除原来的所有 + var res = await _dbContext.Deleteable(x => x.OrderId == orderId).ExecuteCommandHasChangeAsync(); + + List orderInfo = inputDto.Adapt>(); + orderInfo = orderInfo.GroupBy(x => x.FinalslId).Select(x => new OrderInfoEntity() + { + CreateTime = DateTime.Now, + FinalslId = x.Key, + Number = x.Sum(y => y.Number), + }).ToList(); + foreach (var item in orderInfo) + { + item.Id = YitIdHelper.NextId().ToString(); + item.OrderId = orderId; + } + res = await _dbContext.Insertable(orderInfo) + .ExecuteCommandIdentityIntoEntityAsync(); + + + _dbContext.Ado.CommitTran(); + return res; + } + catch (Exception ex) + { + _dbContext.Ado.RollbackTran(); + return false; + } + } + + /// + /// 删除 + /// + /// + /// + [HttpPost] + public async Task Del(string Id) + { + + try + { + _dbContext.Ado.BeginTran(); + + var res = await _dbContext.Deleteable().Where(x => x.Id == Id).ExecuteCommandHasChangeAsync(); + if (res) + { + res = await _dbContext.Deleteable().Where(x => x.OrderId == Id).ExecuteCommandHasChangeAsync(); + } + _dbContext.Ado.CommitTran(); + return res; + } + catch (Exception ex) + { + _dbContext.Ado.RollbackTran(); + return false; + } + } + + /// + /// 获取订单的商品 + /// + /// + /// + [HttpGet] + public async Task> GetOrderMaterial(string OrderId) + { + + var res = await _dbContext.Queryable().Where(x => x.OrderId == OrderId) + .Select(x => new OrderInfoBaseDto() + { + + Id = x.Id, + FinalslId = x.FinalslId, + Number = x.Number, + OrderId = x.OrderId, + }) + .ToListAsync(); + return res; + } + + + /// + /// 添加工单 并绑定订单 + /// + /// + /// + public async Task OrderAssociationWork(List inputDto) + { + var result = false; + var orderId = inputDto.Select(x => x.OrderId).First(); + //验证 + VerifyOrderProduct(inputDto); + _dbContext.Ado.BeginTran(); + + try + { + foreach (var item in inputDto) + { + Pztj_WorkInfoEntity entity = new Pztj_WorkInfoEntity() + { + CreateTime = DateTime.Now, + FinalId = item.FinalslId, + LineId = item.ProductionLineId, + Name = "", + Number = item.Number.ToString(), + + }; + var res= await _dbContext.Insertable(entity).IgnoreColumns(ignoreNullColumn: true).ExecuteCommandAsync(); + Pztj_WorkInfoStatusEntity pztj_WorkInfoStatusEntity = new() + { + Status = WorkOrderStatusEnum.Draft, + WorkId = entity.Id + }; + if (res >0) + { + res= await _dbContext.Insertable(pztj_WorkInfoStatusEntity).IgnoreColumns(true).ExecuteCommandAsync(); + if (res>0) + { + res = await _dbContext.Insertable(new OrderWorkEntity() + { + OrderId = orderId, + WorkId=entity.Id + }).IgnoreColumns(true).ExecuteCommandAsync(); + if (res>0) + { + var order=_dbContext.Queryable< OrderEntity >().First(x=>x.Id==orderId); + order.Status = OrderStatusEnum.Ongoing; + //修改订单状态 + res =await _dbContext.Updateable(order).ExecuteCommandAsync(); + if (res<=0) + { + _dbContext.Ado.RollbackTran(); + return false; + } + + } + else + { + _dbContext.Ado.RollbackTran(); + return false; + } + } + else + { + _dbContext.Ado.RollbackTran(); + return false; + } + } + else + { + _dbContext.Ado.RollbackTran(); + return false; + } + } + } + catch + { + _dbContext.Ado.RollbackTran(); + throw Oops.Bah("添加失败!"); + } + _dbContext.Ado.CommitTran(); + return true; + } + + /// + /// 生成工单时验证成品数量 + /// + /// + private void VerifyOrderProduct(List inputDto) + { + var orderId = inputDto.Select(x => x.OrderId).First(); + var data=_dbContext.Queryable((a,b)=>new JoinQueryInfos( + JoinType.Left,a.FinalslId==b.Id + )).Where((a,b)=>a.OrderId==orderId). + Select((a,b)=>new + { + orderId = a.OrderId, + ProductId = a.FinalslId, + productName = b.Name, + a.Number + }).ToList(); + foreach (var item in data) + { + var productCount = inputDto.Where(x => x.FinalslId == item.ProductId).Sum(x => x.Number); + var count= item.Number - productCount; + if (count<0) + { + throw Oops.Bah($"{item.productName}成品生成工单数量大于订单数量,多【{System.Math.Abs(count)}】"); + } + + if (count>0) + { + throw Oops.Bah($"{item.productName}成品生成工单数量小于订单数量,差【{count}】"); + } + + } + } + + /// + /// 获取成品剩余制作数量 + /// + /// + /// + public async Task> GetFinalslLImit(string OrderId) + { + var result = new List(); + var orderInfo=_dbContext.Queryable().Where(x=>x.OrderId==OrderId).ToList(); + + var list=_dbContext.Queryable((a,b)=>new JoinQueryInfos( + JoinType.Left,a.WorkId==b.Id)) + .Where((a, b) => a.OrderId==OrderId) + .Select((a,b)=>new OrderWorkLimit() + { + FinalslId=b.FinalId, + Limit=0 + }).ToList(); + + foreach (var item in orderInfo) + { + var data=list.Where(x=>x.FinalslId==item.FinalslId).ToList(); + + result.Add(new OrderWorkLimit() + { + FinalslId=item.FinalslId, + Limit=item.Number-data.Sum(x=>x.Limit), + }); + } + return result; + + } + + [HttpGet] + public Task CodeFirst() + { + var types = Assembly.Load("BPA.MES.Base.Application").GetTypes() + .Where(x => x.GetCustomAttribute() != null + && x.Namespace == "BPA.MES.Base.Application.Entitys.Order").ToArray(); + _dbContext.CodeFirst.InitTables(types); + return Task.FromResult(true); + } + } +} diff --git a/backend/BPA.MES.Base.Application/Services/ProductLineService/Dtos/GroupInfoDto.cs b/backend/BPA.MES.Base.Application/Services/ProductLineService/Dtos/GroupInfoDto.cs new file mode 100644 index 0000000..408f415 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/ProductLineService/Dtos/GroupInfoDto.cs @@ -0,0 +1,68 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :产品分组 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/3/10 13:59:43 + /// 描 述 : + /// + public class GroupInfoDto + { + /// + /// 名称 + /// + public string Name { get; set; } + /// + /// 介绍 + /// + public string Des { get; set; } + } + /// + /// 增加 + /// + public class GroupInfoAddInput : GroupInfoDto + { + + } + /// + /// 更新 + /// + public class GroupInfoUpdateInput : GroupInfoDto + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 删除 + /// + public class GroupInfoDelInput + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 分页 + /// + public class GroupInfoQueryPageInput : RequestPage + { + /// + /// 名称 + /// + public string Name { get; set; } + } + /// + /// 输出 + /// + public class GroupInfoOutput : GroupInfoDto + { + /// + /// 主键 + /// + /// + public string Id { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Services/ProductLineService/Dtos/ProductLineDeviceDto.cs b/backend/BPA.MES.Base.Application/Services/ProductLineService/Dtos/ProductLineDeviceDto.cs new file mode 100644 index 0000000..e8e6c26 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/ProductLineService/Dtos/ProductLineDeviceDto.cs @@ -0,0 +1,90 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :产线设备 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/7/20 17:00:32 + /// 描 述 : + /// + public class ProductLineDeviceDto + { + /// + /// 产线Id + /// + public string LineId { get; set; } + /// + /// 产线设备 + /// + public string DeviceId { get; set; } + } + public class ProductLineDeviceAddInput: ProductLineDeviceDto { + + + } + /// + /// 产线设备不分页 + /// + public class ProductLineDeviceQueryInput + { + /// + /// 名称 + /// + public string Name { get; set; } + /// + /// 产线Id + /// + public string LineId { get; set; } + } + /// + /// 产线设备分页 + /// + public class ProductLineDeviceQueryPageInput : RequestPage + { + /// + /// 名称 + /// + public string Name { get; set; } + /// + /// 产线Id + /// + public string LineId { get; set; } + } + /// + /// 删除产线设备 + /// + public class ProductLineDeviceDelInput: ProductLineDeviceDto + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 产线设备关联信息 + /// + public class ProductLineDeviceOutput: ProductLineDeviceDto + { + /// + /// 主键 + /// + public string Id { get; set; } + /// + /// 名称 + /// + /// 设备名称 + public string DeviceName { get; set; } + /// + /// 编码 + /// + public string DeviceCode { get; set; } + /// + /// 设备类型 + /// + public string DeviceType { get; set; } + /// + /// 设备描述 + /// + /// 设备描述 + public string Describe { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Services/ProductLineService/Dtos/ProductLineDto.cs b/backend/BPA.MES.Base.Application/Services/ProductLineService/Dtos/ProductLineDto.cs new file mode 100644 index 0000000..f7215bf --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/ProductLineService/Dtos/ProductLineDto.cs @@ -0,0 +1,76 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :产线管理 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/7/18 14:03:27 + /// 描 述 : + /// + public class ProductLineDto + { + /// + /// 产线名称 + /// + public string Name { get; set; } + /// + /// 产线编码 + /// + public string Code { get; set; } + /// + /// 产线描述 + /// + public string Describe { get; set; } + } + /// + /// 增加 + /// + public class ProductLineAddInput : ProductLineDto + { + + } + /// + /// 更新 + /// + public class ProductLineUpdateInput : ProductLineDto + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 删除 + /// + public class ProductLineDelInput + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 分页 + /// + public class ProductLineQueryPageInput : RequestPage + { + /// + /// 名称 + /// + public string Name { get; set; } + /// + /// 编码 + /// + public string Code { get; set; } + } + /// + /// 输出 + /// + public class ProductLineOutput : ProductLineDto + { + /// + /// 主键 + /// + public string Id { get; set; } + } + +} diff --git a/backend/BPA.MES.Base.Application/Services/ProductLineService/Dtos/ProductLineStockDto.cs b/backend/BPA.MES.Base.Application/Services/ProductLineService/Dtos/ProductLineStockDto.cs new file mode 100644 index 0000000..6876119 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/ProductLineService/Dtos/ProductLineStockDto.cs @@ -0,0 +1,99 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 : + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/7/20 18:25:18 + /// 描 述 : + /// + public class ProductLineStockDto + { + /// + /// 产线Id + /// + public string LineId { get; set; } + /// + /// 产线设备 + /// + public string StockId { get; set; } + } + public class ProductLineStockAddInput : ProductLineStockDto + { + + + } + /// + /// 产线设备不分页 + /// + public class ProductLineStockQueryInput + { + /// + /// 名称 + /// + public string Name { get; set; } + /// + /// 产线Id + /// + public string LineId { get; set; } + /// + /// 物料Id + /// + public string MaterialId { get; set; } + } + /// + /// 产线设备分页 + /// + public class ProductLineStockQueryPageInput : RequestPage + { + /// + /// 名称 + /// + public string Name { get; set; } + /// + /// 产线Id + /// + public string LineId { get; set; } + } + /// + /// 删除产线设备 + /// + public class ProductLineStockDelInput : ProductLineStockDto + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 产线设备关联信息 + /// + public class ProductLineStockOutput : ProductLineStockDto + { + /// + /// 主键 + /// + public string Id { get; set; } + /// + /// 产线名称 + /// + public string LineName { get; set; } + /// + /// 名称 + /// + /// 设备名称 + public string StockName { get; set; } + /// + /// 编码 + /// + public string StockCode { get; set; } + /// + /// 物料信息 + /// + public string MaterialId { get; set; } + /// + /// 物料名称 + /// + public string MateriaName { get; set; } + } +} + diff --git a/backend/BPA.MES.Base.Application/Services/ProductLineService/Services/GroupInfoService.cs b/backend/BPA.MES.Base.Application/Services/ProductLineService/Services/GroupInfoService.cs new file mode 100644 index 0000000..fcbcc6c --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/ProductLineService/Services/GroupInfoService.cs @@ -0,0 +1,116 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :分组信息 + /// 创 建 人 :yangxiao + /// 创建时间 :2023/3/10 14:03:06 + /// 描 述 : + /// + [ApiDescriptionSettings("产线管理", Order = 0, Name = "GroupInfo", Tag = "分组服务", KeepName = true, SplitCamelCase = true, KeepVerb = true)] + public class GroupInfoService : IGroupInfoService, ITransient, IDynamicApiController + { + private readonly ISqlSugarClient _dbContext; + public GroupInfoService(ISqlSugarClient db) + { + _dbContext = db; + } + /// + /// 增加 + /// + /// + /// + [HttpPost] + public async Task Add(GroupInfoAddInput input) + { + GroupInfoEntity entity = await _dbContext.Queryable().FirstAsync(x => x.Name == input.Name); + if (entity != null) + { + throw Oops.Bah("名称已存在!"); + } + entity = input.Adapt(); + return await _dbContext.Insertable(entity).IgnoreColumns(ignoreNullColumn: true).ExecuteCommandIdentityIntoEntityAsync(); + } + /// + /// 删除 + /// + /// + /// + /// + [HttpPost] + public async Task Del(GroupInfoDelInput input) + { + var res = await _dbContext.Deleteable().Where(x=>x.Id==input.Id).ExecuteCommandHasChangeAsync(); + return res; + } + /// + /// 详情 + /// + /// + /// + /// + [HttpGet] + public async Task Detail(string Id) + { + var entity = await _dbContext.Queryable().FirstAsync(); + GroupInfoOutput output = entity.Adapt(); + return output; + } + /// + /// 列表 + /// + /// + /// + [HttpPost, AllowAnonymous] + public async Task> List() + { + var entity = await _dbContext.Queryable().ToListAsync(); + List output = entity.Adapt>(); + return output; + } + /// + /// 分页 + /// + /// + /// + [HttpPost] + public async Task> PagedList(GroupInfoQueryPageInput input) + { + var entity = await _dbContext.Queryable() + .ToPagedListAsync(input.PageIndex, input.PageSize); + SqlSugarPagedList output = entity.Adapt>(); + return output; + } + /// + /// 下拉 + /// + /// + [HttpGet] + public async Task SelectList() + { + var entity = await _dbContext.Queryable().Select(x => new + { + key = x.Id, + value = x.Name + }).ToListAsync(); + return entity; + } + /// + /// 更新 + /// + /// + /// + /// + [HttpPost] + public async Task Update(GroupInfoUpdateInput input) + { + var entity = await _dbContext.Queryable().FirstAsync(x => x.Id != input.Id && x.Name == input.Name); + if (entity != null) + { + throw Oops.Bah("名称已存在!"); + } + entity = input.Adapt(); + var res = await _dbContext.Updateable(entity).IgnoreColumns(true).ExecuteCommandHasChangeAsync(); + return res; + } + } +} diff --git a/backend/BPA.MES.Base.Application/Services/ProductLineService/Services/IGroupInfoService.cs b/backend/BPA.MES.Base.Application/Services/ProductLineService/Services/IGroupInfoService.cs new file mode 100644 index 0000000..ed44933 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/ProductLineService/Services/IGroupInfoService.cs @@ -0,0 +1,48 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :分组信息 + /// 创 建 人 :yangxiao + /// 创建时间 :2023/3/10 14:03:21 + /// 描 述 : + /// + public interface IGroupInfoService + { + /// + /// 增加 + /// + /// + Task Add(GroupInfoAddInput input); + /// + /// 移除 + /// + /// + Task Del(GroupInfoDelInput input); + /// + /// 更新 + /// + /// + Task Update(GroupInfoUpdateInput input); + /// + /// 不分页列表 + /// + /// + Task> List(); + /// + /// 下拉列表 + /// + /// + Task SelectList(); + /// + /// 分页列表 + /// + /// + Task> PagedList(GroupInfoQueryPageInput input); + /// + /// 查询单条 + /// + /// + /// + Task Detail(string Id); + } +} diff --git a/backend/BPA.MES.Base.Application/Services/ProductLineService/Services/IProductLineService.cs b/backend/BPA.MES.Base.Application/Services/ProductLineService/Services/IProductLineService.cs new file mode 100644 index 0000000..e352cc8 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/ProductLineService/Services/IProductLineService.cs @@ -0,0 +1,100 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :产线管理 + /// 创 建 人 :yangxiao + /// 创建时间 :2023/7/18 14:05:16 + /// 描 述 : + /// + public interface IProductLineService + { + /// + /// 增加 + /// + /// + Task Add(ProductLineAddInput input); + /// + /// 移除 + /// + /// + Task Del(ProductLineDelInput input); + /// + /// 更新 + /// + /// + Task Update(ProductLineUpdateInput input); + /// + /// 不分页列表 + /// + /// + Task> List(); + /// + /// 分页列表 + /// + /// + Task> PagedList(ProductLineQueryPageInput input); + /// + /// 下拉列表 + /// + /// + Task SelectList(); + /// + /// 查询单条 + /// + /// + /// + Task Detail(string Id); + /// + /// 产线添加设备 + /// + /// + Task AddDevice(ProductLineDeviceAddInput input); + /// + /// 产线删除设备 + /// + /// + Task DeleteDevice(ProductLineDeviceDelInput input); + ///// + ///// 产线更新设备 + ///// + ///// + //Task UpdateDevice(string DeviceId); + /// + /// 产线设备不分页 + /// + /// + Task> DeviceList(ProductLineDeviceQueryInput input); + /// + /// 产线设备分页 + /// + /// + Task> DevicePageList(ProductLineDeviceQueryPageInput input); + + + /// + /// 产线添加料仓 + /// + /// + Task AddStock(ProductLineStockAddInput input); + /// + /// 产线删除料仓 + /// + /// + Task DeleteStock(ProductLineStockDelInput input); + ///// + ///// 产线更新料仓 + ///// + ///// + //Task UpdateStock(string StockId); + /// + /// 产线料仓不分页 + /// + /// + Task> StockList(ProductLineStockQueryInput input); + /// + /// 产线料仓分页 + /// + /// + Task> StockPageList(ProductLineStockQueryPageInput input); + } +} diff --git a/backend/BPA.MES.Base.Application/Services/ProductLineService/Services/ProductLineService.cs b/backend/BPA.MES.Base.Application/Services/ProductLineService/Services/ProductLineService.cs new file mode 100644 index 0000000..2a64b93 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/ProductLineService/Services/ProductLineService.cs @@ -0,0 +1,268 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :产线服务 + /// 创 建 人 :yangxiao + /// 创建时间 :2023/3/2 16:11:04 + /// 描 述 :基础数据管理 + /// + [ApiDescriptionSettings("产线管理", Order = 0, Name = "ProductLine", Tag = "产线服务", KeepName = true, SplitCamelCase = true, KeepVerb = true)] + public class ProductLineService : IProductLineService, ITransient, IDynamicApiController + { + private readonly ISqlSugarClient _dbContext; + public ProductLineService(ISqlSugarClient db) + { + _dbContext = db; + } + /// + /// 增加 + /// + /// + /// + [HttpPost] + public async Task Add(ProductLineAddInput input) + { + var r_entity = await _dbContext.Queryable().FirstAsync(x => x.Name == input.Name); + if (r_entity != null) + { + throw Oops.Bah("名称已存在!"); + } + ProductLineEntity entity = input.Adapt(); + return await _dbContext.Insertable(entity).IgnoreColumns(ignoreNullColumn: true).ExecuteCommandIdentityIntoEntityAsync(); + } + /// + /// 删除 + /// + /// + /// + /// + [HttpPost] + public async Task Del(ProductLineDelInput input) + { + var res = await _dbContext.Deleteable().Where(x => x.Id == input.Id).ExecuteCommandHasChangeAsync(); + return res; + } + /// + /// 详情 + /// + /// + /// + /// + [HttpGet] + public async Task Detail(string Id) + { + var entity = await _dbContext.Queryable().FirstAsync(x => x.Id == Id); + ProductLineOutput output = entity.Adapt(); + return output; + } + + /// + /// 列表 + /// + /// + /// + [HttpGet] + public async Task> List() + { + var entity = await _dbContext.Queryable().ToListAsync(); + List output = entity.Adapt>(); + return output; + } + /// + /// 分页 + /// + /// + /// + [HttpPost] + public async Task> PagedList(ProductLineQueryPageInput input) + { + var entity = await _dbContext.Queryable() + .WhereIF(!string.IsNullOrEmpty(input.Name), x => x.Name.Contains(input.Name)) + .WhereIF(!string.IsNullOrEmpty(input.Code), x => x.Name.Contains(input.Code)) + .ToPagedListAsync(input.PageIndex, input.PageSize); + SqlSugarPagedList output = entity.Adapt>(); + return output; + } + /// + /// 下拉 + /// + /// + /// + [HttpGet] + public async Task SelectList() + { + var entity = await _dbContext.Queryable().Select(x => new + { + key = x.Id, + value = x.Name + }).ToListAsync(); + return entity; + } + /// + /// 更新 + /// + /// + /// + /// + [HttpPost] + public async Task Update(ProductLineUpdateInput input) + { + var isExit =await _dbContext.Queryable().Where(x => x.Id != input.Id && (x.Name == input.Name || x.Code == input.Code)).FirstAsync(); + if (isExit != null) + { + throw Oops.Bah("名称或编码已存在!"); + } + ProductLineEntity entity = input.Adapt(); + var res = await _dbContext.Updateable(entity).IgnoreColumns(true).ExecuteCommandHasChangeAsync(); + return res; + } + /// + /// 产线添加设备 + /// + /// + [HttpPost] + public async Task AddDevice(ProductLineDeviceAddInput input) + { + var r_entity = await _dbContext.Queryable().FirstAsync(x => x.DeviceId == input.DeviceId); + if (r_entity != null) + { + throw Oops.Bah("设备已存在!"); + } + Pztj_LineDevicesEntity entity = input.Adapt(); + return await _dbContext.Insertable(entity).IgnoreColumns(ignoreNullColumn: true).ExecuteCommandIdentityIntoEntityAsync(); + } + /// + /// 产线删除设备 + /// + /// + [HttpPost] + public async Task DeleteDevice(ProductLineDeviceDelInput input) + { + var res = await _dbContext.Deleteable().Where(x => x.Id == input.Id).ExecuteCommandHasChangeAsync(); + return res; + } + /// + /// 产线设备不分页 + /// + /// + [HttpPost] + public async Task> DeviceList(ProductLineDeviceQueryInput input) + { + var output = await _dbContext.Queryable() + .LeftJoin((a, b) => a.DeviceId == b.Id) + .WhereIF(!string.IsNullOrEmpty(input.Name), (a, b) => b.Name.Contains(input.Name)) + .WhereIF(!string.IsNullOrEmpty(input.LineId), (a, b) => a.LineId == input.LineId) + .Select((a, b) => new ProductLineDeviceOutput + { + DeviceId = a.DeviceId, + DeviceCode = b.Code, + DeviceName = b.Name, + Describe = b.Describe, + DeviceType = b.DeviceType, + Id = a.Id, + LineId = a.LineId + }). + ToListAsync(); + return output; + } + /// + /// 产线设备分页 + /// + /// + [HttpPost] + public async Task> DevicePageList(ProductLineDeviceQueryPageInput input) + { + var entity = await _dbContext.Queryable() + .LeftJoin((a,b)=>a.DeviceId==b.Id) + .WhereIF(!string.IsNullOrEmpty(input.Name), (a, b) => b.Name.Contains(input.Name)) + .WhereIF(!string.IsNullOrEmpty(input.LineId), (a, b) => a.LineId == input.LineId) + .Select((a,b)=>new ProductLineDeviceOutput + { + DeviceId = a.DeviceId, + DeviceCode = b.Code, + DeviceName = b.Name, + Describe = b.Describe, + DeviceType = b.DeviceType, + Id = a.Id, + LineId = a.LineId + }) + .ToPagedListAsync(input.PageIndex, input.PageSize); + return entity; + } + + + /// + /// 产线添加料仓 + /// + /// + [HttpPost] + public async Task AddStock(ProductLineStockAddInput input) + { + var r_entity = await _dbContext.Queryable().FirstAsync(x => x.StockId == input.StockId); + if (r_entity != null) + { + throw Oops.Bah("设备已存在!"); + } + Pztj_LineStocksEntity entity = input.Adapt(); + return await _dbContext.Insertable(entity).IgnoreColumns(ignoreNullColumn: true).ExecuteCommandIdentityIntoEntityAsync(); + } + /// + /// 产线删除料仓 + /// + /// + [HttpPost] + public async Task DeleteStock(ProductLineStockDelInput input) + { + var res = await _dbContext.Deleteable().Where(x => x.Id == input.Id).ExecuteCommandHasChangeAsync(); + return res; + } + /// + /// 产线料仓不分页 + /// + /// + [HttpPost] + public async Task> StockList(ProductLineStockQueryInput input) + { + var entity = await _dbContext.Queryable() + .LeftJoin((a, b) => a.StockId == b.Id) + .LeftJoin((a, b,c) => b.MaterialId == c.Id) + .WhereIF(!string.IsNullOrEmpty(input.MaterialId), (a, b) => b.MaterialId == input.MaterialId) + .WhereIF(!string.IsNullOrEmpty(input.LineId), (a, b) => a.LineId == input.LineId) + .Select((a, b,c) => new ProductLineStockOutput + { + Id = a.Id, + LineId = a.LineId, + StockCode = b.Code, + StockId = b.Id, + StockName = b.Name, + MaterialId = b.MaterialId, + MateriaName = c.Name + }) + .ToListAsync(); + return entity; + } + /// + /// 产线料仓分页 + /// + /// + [HttpPost] + public async Task> StockPageList(ProductLineStockQueryPageInput input) + { + var entity = await _dbContext.Queryable() + .LeftJoin((a, b) => a.StockId == b.Id) + .WhereIF(!string.IsNullOrEmpty(input.Name), (a, b) => b.Name.Contains(input.Name)) + .WhereIF(!string.IsNullOrEmpty(input.LineId), (a, b) => a.LineId == input.LineId) + .Select((a, b) => new ProductLineStockOutput + { + StockId = a.StockId, + StockCode = b.Code, + StockName = b.Name, + Id = a.Id, + LineId = a.LineId + }) + .ToPagedListAsync(input.PageIndex, input.PageSize); + return entity; + } + } +} + diff --git a/backend/BPA.MES.Base.Application/Services/RecipesService/Dtos/RecipeMaterialDto.cs b/backend/BPA.MES.Base.Application/Services/RecipesService/Dtos/RecipeMaterialDto.cs new file mode 100644 index 0000000..f9a0713 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/RecipesService/Dtos/RecipeMaterialDto.cs @@ -0,0 +1,98 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :配方物料Dto类 + /// 创 建 人 :yangxiao + /// 创建时间 :2023/3/2 16:12:06 + /// 描 述 : + /// + public class RecipeMaterialDto + { + /// + /// 物料Id + /// + public string MaterialId { get; set; } + /// + /// 配方Id + /// + public string RecipesId { get; set; } + /// + /// 重量 + /// + public string Weight { get; set; } + /// + /// 描述 + /// + public string Describe { get; set; } + /// + /// 误差 + /// + public string ErrorWeight { get; set; } + } + /// + /// 增加 + /// + public class RecipeMaterialAddInput: RecipeMaterialDto + { + + } + /// + /// 更新 + /// + public class RecipeMaterialUpdateInput : RecipeMaterialDto + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 删除 + /// + public class RecipeMaterialDelInput + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 不分页 + /// + public class RecipeMaterialQueryInput + { + /// + /// 配方Id + /// + public string RecipesId { get; set; } + } + /// + /// 分页 + /// + public class RecipeMaterialQueryPageInput : RequestPage + { + + } + /// + /// 输出 + /// + public class RecipeMaterialOutput : RecipeMaterialDto + { + /// + /// 主键 + /// + public string Id { get; set; } + /// + /// 配方名称 + /// + public string RecipesName { get; set; } + /// + /// 物料名称 + /// + public string MaterialName { get; set; } + /// + /// 物料编码 + /// + public string MaterialCode { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Services/RecipesService/Dtos/RecipesInfoDto.cs b/backend/BPA.MES.Base.Application/Services/RecipesService/Dtos/RecipesInfoDto.cs new file mode 100644 index 0000000..83adee8 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/RecipesService/Dtos/RecipesInfoDto.cs @@ -0,0 +1,84 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :配方Dto类 + /// 创 建 人 :yangxiao + /// 创建时间 :2023/3/2 16:12:06 + /// 描 述 : + /// + public class RecipesInfoDto + { + /// + /// 名称 + /// + public string Name { get; set; } + /// + /// 自定义编码 + /// + public string Code { get; set; } + } + /// + /// 增加 + /// + public class RecipesInfoAddInput : RecipesInfoDto + { + + } + /// + /// 更新 + /// + public class RecipesInfoUpdateInput : RecipesInfoDto + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 删除 + /// + public class RecipesInfoDelInput + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 分页 + /// + public class RecipesInfoQueryPageInput : RequestPage + { + /// + /// 名称 + /// + public string Name { get; set; } + /// + /// 分组id + /// + public string GroupId { get; set; } + } + /// + /// 输出 + /// + public class RecipesInfoOutput : RecipesInfoDto + { + /// + /// 主键 + /// + public string Id { get; set; } + /// + /// 分组Id + /// + public string GroupId { get; set; } + } + + public class RecipesGroupInput : RecipesGroupEntity + { + /// + /// 主键 + /// + /// + public string Id { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Services/RecipesService/Services/IRecipeMaterialService.cs b/backend/BPA.MES.Base.Application/Services/RecipesService/Services/IRecipeMaterialService.cs new file mode 100644 index 0000000..ad1ee62 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/RecipesService/Services/IRecipeMaterialService.cs @@ -0,0 +1,49 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :配方物料服务 + /// 创 建 人 :yangxiao + /// 创建时间 :2023/3/2 18:33:18 + /// 描 述 : + /// + public interface IRecipeMaterialService + { + /// + /// 增加 + /// + /// + Task Add(RecipeMaterialAddInput input); + /// + /// 批量增加 + /// + /// + /// + Task BatchAdd(List inputs); + /// + /// 移除 + /// + /// + Task Del(RecipeMaterialDelInput input); + /// + /// 更新 + /// + /// + Task Update(RecipeMaterialUpdateInput input); + /// + /// 不分页列表 + /// + /// + Task> List(RecipeMaterialQueryInput input); + /// + /// 分页列表 + /// + /// + Task> PagedList(RecipeMaterialQueryPageInput input); + /// + /// 查询单条 + /// + /// + /// + Task Detail(string Id); + } +} diff --git a/backend/BPA.MES.Base.Application/Services/RecipesService/Services/IRecipesInfoService.cs b/backend/BPA.MES.Base.Application/Services/RecipesService/Services/IRecipesInfoService.cs new file mode 100644 index 0000000..d1f07bb --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/RecipesService/Services/IRecipesInfoService.cs @@ -0,0 +1,54 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :配方服务 + /// 创 建 人 :yangxiao + /// 创建时间 :2023/3/2 18:33:18 + /// 描 述 : + /// + public interface IRecipesInfoService + { + /// + /// 增加 + /// + /// + Task Add(RecipesInfoAddInput input); + /// + /// 移除 + /// + /// + Task Del(RecipesInfoDelInput input); + /// + /// 更新 + /// + /// + Task Update(RecipesInfoUpdateInput input); + /// + /// 不分页列表 + /// + /// + Task> List(); + /// + /// 分页列表 + /// + /// + Task> PagedList(RecipesInfoQueryPageInput input); + /// + /// 下拉列表 + /// + /// + Task SelectList(); + /// + /// 查询单条 + /// + /// + /// + Task Detail(string Id); + /// + /// 更改物料分组 + /// + /// + /// + Task ChangeGroup(RecipesGroupInput input); + } +} diff --git a/backend/BPA.MES.Base.Application/Services/RecipesService/Services/RecipeMaterialService.cs b/backend/BPA.MES.Base.Application/Services/RecipesService/Services/RecipeMaterialService.cs new file mode 100644 index 0000000..f20b767 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/RecipesService/Services/RecipeMaterialService.cs @@ -0,0 +1,130 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :配方物料服务 + /// 创 建 人 :yangxiao + /// 创建时间 :2023/3/2 16:11:04 + /// 描 述 :配方物料数据维护 + /// + [ApiDescriptionSettings("配方工艺管理", Name = "RecipeMaterial", Tag = "配方物料服务", KeepName = true, SplitCamelCase = true, KeepVerb = true)] + public class RecipeMaterialService : IRecipeMaterialService, ITransient, IDynamicApiController + { + private readonly ISqlSugarClient _dbContext; + public RecipeMaterialService(ISqlSugarClient db) + { + _dbContext = db; + } + /// + /// 增加 + /// + /// + /// + [HttpPost] + public async Task Add(RecipeMaterialAddInput input) + { + RecipeMaterialEntity entity = input.Adapt(); + return await _dbContext.Insertable(entity).IgnoreColumns(ignoreNullColumn: true).ExecuteCommandIdentityIntoEntityAsync(); + } + /// + /// 批量增加 + /// + /// + /// + /// + public async Task BatchAdd(List inputs) + { + bool result = false; + List entitys = inputs.Adapt>(); + try + { + _dbContext.Ado.BeginTran(); + await _dbContext.Deleteable().Where(x => x.RecipesId == inputs[0].RecipesId).ExecuteCommandAsync(); + await _dbContext.Insertable(entitys).ExecuteCommandAsync(); + _dbContext.Ado.CommitTran(); + result = true; + } + catch (Exception ex) + { + _dbContext.Ado.RollbackTran(); + throw Oops.Bah("保存失败!"); + } + return result; + } + + /// + /// 删除 + /// + /// + /// + /// + [HttpPost] + public async Task Del(RecipeMaterialDelInput input) + { + var res = await _dbContext.Deleteable().Where(x => x.Id == input.Id).ExecuteCommandHasChangeAsync(); + return res; + } + /// + /// 详情 + /// + /// + /// + /// + [HttpGet] + public async Task Detail(string Id) + { + var entity = await _dbContext.Queryable().FirstAsync(x => x.Id == Id); + RecipeMaterialOutput output = entity.Adapt(); + return output; + } + /// + /// 列表 + /// + /// + /// + [HttpPost,AllowAnonymous] + public async Task> List(RecipeMaterialQueryInput input) + { + var output = await _dbContext.Queryable() + .LeftJoin((a,b)=>a.RecipesId==b.Id) + .LeftJoin((a,b,c)=>a.MaterialId==c.Id) + .WhereIF(!string.IsNullOrEmpty(input.RecipesId),(a,b,c)=>a.RecipesId==input.RecipesId) + .Select((a,b,c)=>new RecipeMaterialOutput + { + Id = a.Id, + MaterialName = c.Name, + MaterialCode = c.Code, + MaterialId = c.Id, + RecipesId = a.RecipesId, + RecipesName = b.Name, + Weight = a.Weight + }) + .ToListAsync(); + return output; + } + /// + /// 分页 + /// + /// + /// + [HttpPost] + public async Task> PagedList(RecipeMaterialQueryPageInput input) + { + var entity = await _dbContext.Queryable() + .ToPagedListAsync(input.PageIndex, input.PageSize); + SqlSugarPagedList output = entity.Adapt>(); + return output; + } + /// + /// 更新 + /// + /// + /// + /// + [HttpPost] + public async Task Update(RecipeMaterialUpdateInput input) + { + var res = await _dbContext.Updateable().ExecuteCommandHasChangeAsync(); + return res; + } + } +} diff --git a/backend/BPA.MES.Base.Application/Services/RecipesService/Services/RecipesInfoService.cs b/backend/BPA.MES.Base.Application/Services/RecipesService/Services/RecipesInfoService.cs new file mode 100644 index 0000000..b535ab2 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/RecipesService/Services/RecipesInfoService.cs @@ -0,0 +1,136 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :配方管理 + /// 创 建 人 :yangxiao + /// 创建时间 :2023/3/2 16:11:04 + /// 描 述 :店铺数据维护 + /// + [ApiDescriptionSettings("配方工艺管理", Name = "RecipesInfo", Tag = "配方服务", KeepName = true, SplitCamelCase = true, KeepVerb = true)] + public class RecipesInfoService : IRecipesInfoService, ITransient, IDynamicApiController + { + private readonly ISqlSugarClient _dbContext; + public RecipesInfoService(ISqlSugarClient db) + { + _dbContext = db; + } + /// + /// 增加 + /// + /// + /// + [HttpPost] + public async Task Add(RecipesInfoAddInput input) + { + var r_entity = await _dbContext.Queryable().FirstAsync(x => x.Name == input.Name || x.Code==input.Code); + if (r_entity != null) + { + throw Oops.Bah("名称或者编码已存在!"); + } + RecipesInfoEntity entity = input.Adapt(); + return await _dbContext.Insertable(entity).IgnoreColumns(ignoreNullColumn: true).ExecuteCommandIdentityIntoEntityAsync(); + } + /// + /// 删除 + /// + /// + /// + /// + [HttpPost] + public async Task Del(RecipesInfoDelInput input) + { + var res = await _dbContext.Deleteable().Where(x => x.Id == input.Id).ExecuteCommandHasChangeAsync(); + return res; + } + /// + /// 详情 + /// + /// + /// + /// + [HttpGet] + public async Task Detail(string Id) + { + var entity = await _dbContext.Queryable().FirstAsync(x => x.Id == Id); + RecipesInfoOutput output = entity.Adapt(); + return output; + } + /// + /// 列表 + /// + /// + /// + [HttpGet] + public async Task> List() + { + var entity = await _dbContext.Queryable().ToListAsync(); + List output = entity.Adapt>(); + return output; + } + /// + /// 分页 + /// + /// + /// + [HttpPost] + public async Task> PagedList(RecipesInfoQueryPageInput input) + { + var entity = await _dbContext.Queryable() + .LeftJoin((a,b)=>a.Id==b.RecipesId) + .WhereIF(!string.IsNullOrEmpty(input.Name), (a, b) => a.Name.Contains(input.Name)) + .WhereIF(!string.IsNullOrEmpty(input.GroupId), (a, b) => b.GroupId==input.GroupId) + .Select() + .ToPagedListAsync(input.PageIndex, input.PageSize); + SqlSugarPagedList output = entity.Adapt>(); + return output; + } + /// + /// 下拉 + /// + /// + /// + [HttpGet] + public async Task SelectList() + { + var entity = await _dbContext.Queryable().Select(x => new + { + key = x.Id, + value = x.Name + }).ToListAsync(); + return entity; + } + /// + /// 更新 + /// + /// + /// + /// + [HttpPost] + public async Task Update(RecipesInfoUpdateInput input) + { + RecipesInfoEntity entity = await _dbContext.Queryable().FirstAsync(x => x.Id != input.Id && (x.Name == input.Name || x.Code == input.Code)); + if (entity != null) + { + throw Oops.Bah("名称或者编码已存在!"); + } + entity = input.Adapt(); + var res = await _dbContext.Updateable(entity).IgnoreColumns(true).ExecuteCommandHasChangeAsync(); + return res; + } + [HttpPost] + public async Task ChangeGroup(RecipesGroupInput input) + { + var isExit =await _dbContext.Queryable().FirstAsync(x=>x.RecipesId==input.RecipesId); + var entity = input.Adapt(); + if (isExit==null) + { + return await _dbContext.Insertable(entity).ExecuteCommandIdentityIntoEntityAsync(); + } + else + { + return await _dbContext.Updateable(entity).IgnoreColumns(true).Where(x => x.RecipesId == input.RecipesId).ExecuteCommandHasChangeAsync(); + } + + } + } +} diff --git a/backend/BPA.MES.Base.Application/Services/ReportService/Dtos/MaterialsInputDto.cs b/backend/BPA.MES.Base.Application/Services/ReportService/Dtos/MaterialsInputDto.cs new file mode 100644 index 0000000..23067f6 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/ReportService/Dtos/MaterialsInputDto.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BPA.MES.Base.Application.Services.ReportService.Dtos +{ + public class MaterialsInputDto: RequestPage + { + public DateTime? StartTime { get; set; } + public DateTime? EndTime { get; set; } + public string MaterialName { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Services/ReportService/Dtos/MaterialsOutDto.cs b/backend/BPA.MES.Base.Application/Services/ReportService/Dtos/MaterialsOutDto.cs new file mode 100644 index 0000000..bc12347 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/ReportService/Dtos/MaterialsOutDto.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BPA.MES.Base.Application.Services.ReportService.Dtos +{ + public class MaterialsOutDto + { + public string MaterialId { get; set; } + public string MaterialName { get; set; } + public decimal Count { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Services/ReportService/Dtos/ProductInputDto.cs b/backend/BPA.MES.Base.Application/Services/ReportService/Dtos/ProductInputDto.cs new file mode 100644 index 0000000..b5b26bf --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/ReportService/Dtos/ProductInputDto.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BPA.MES.Base.Application.Services.ReportService.Dtos +{ + public class ProductInputDto : RequestPage + { + public DateTime? StartTime { get; set; } + public DateTime? EndTime { get; set; } + public string ProductName { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Services/ReportService/Dtos/ProductOutDto.cs b/backend/BPA.MES.Base.Application/Services/ReportService/Dtos/ProductOutDto.cs new file mode 100644 index 0000000..fdaf4bd --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/ReportService/Dtos/ProductOutDto.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BPA.MES.Base.Application.Services.ReportService.Dtos +{ + public class ProductOutDto + { + public string ProductId { get; set; } + public string ProductName { get; set; } + public decimal Count { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Services/ReportService/IReportService.cs b/backend/BPA.MES.Base.Application/Services/ReportService/IReportService.cs new file mode 100644 index 0000000..18816d6 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/ReportService/IReportService.cs @@ -0,0 +1,26 @@ +using BPA.MES.Base.Application.Services.ReportService.Dtos; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BPA.MES.Base.Application.Services.ReportService +{ + public interface IReportService + { + /// + /// 获取产品生产统计 + /// + /// + /// + Task> GetProductReport(ProductInputDto input); + + /// + /// 获取物料统计 + /// + /// + /// + Task> GetMaterialsReport(MaterialsInputDto inputDto); + } +} diff --git a/backend/BPA.MES.Base.Application/Services/ReportService/ReportService.cs b/backend/BPA.MES.Base.Application/Services/ReportService/ReportService.cs new file mode 100644 index 0000000..7fb128b --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/ReportService/ReportService.cs @@ -0,0 +1,69 @@ +using BPA.MES.Base.Application.Services.ReportService.Dtos; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BPA.MES.Base.Application.Services.ReportService +{ + + [ApiDescriptionSettings("统计报表管理", Order = 2, Name = "Report", Tag = "报表信息", KeepName = true, SplitCamelCase = true, KeepVerb = true)] + public class ReportService : IReportService, ITransient, IDynamicApiController + { + private readonly ISqlSugarClient _dbContext; + public ReportService(ISqlSugarClient db) + { + _dbContext = db; + } + + /// + /// 获取成品生产统计 + /// + /// + /// + [HttpPost] + public async Task> GetProductReport(ProductInputDto input) + { + var res = await _dbContext.Queryable().LeftJoin((a, b) => a.FinalId == b.Id) + .WhereIF(!string.IsNullOrEmpty(input.ProductName), (a, b) => b.Name.Contains(input.ProductName)) + .WhereIF(input.StartTime.HasVal(), (a, b) => a.CreateTime >= input.StartTime.Value) + .WhereIF(input.EndTime.HasVal(), (a, b) => a.CreateTime <= input.EndTime.Value) + .Where((a, b) => a.Status == WorkOrderStatusEnum.Completed) + .GroupBy((a, b) => b.Name) + .Select((a, b) => new ProductOutDto + { + ProductName = b.Name, + Count = SqlFunc.AggregateSum(Convert.ToDecimal(a.Number)), + + }).ToPagedListAsync(input.PageIndex, input.PageSize); + + return res; + } + + + /// + /// 获取物料统计 + /// + /// + /// + [HttpPost] + public async Task> GetMaterialsReport(MaterialsInputDto input) + { + var result = await _dbContext.Queryable() + .LeftJoin((a, b) => a.WorkId == b.Id) + .Where((a, b) => b.Status == WorkOrderStatusEnum.Completed) + .WhereIF(!string.IsNullOrEmpty(input.MaterialName), (a, b) => a.MaterialName.Contains(input.MaterialName)) + .WhereIF(input.StartTime.HasVal(), (a, b) => b.CreateTime >= input.StartTime.Value) + .WhereIF(input.EndTime.HasVal(), (a, b) => b.CreateTime <= input.EndTime.Value) + .GroupBy((a, b) => a.MaterialName) + .Select((a, b) => new MaterialsOutDto + { + Count = SqlFunc.AggregateSumNoNull(Convert.ToDecimal(a.Weight)), + MaterialName = a.MaterialName, + }).ToPagedListAsync(input.PageIndex, input.PageSize); + + return result; + } + } +} diff --git a/backend/BPA.MES.Base.Application/Services/StockInfoService/Dtos/StockInfoDto.cs b/backend/BPA.MES.Base.Application/Services/StockInfoService/Dtos/StockInfoDto.cs new file mode 100644 index 0000000..35c5b20 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/StockInfoService/Dtos/StockInfoDto.cs @@ -0,0 +1,83 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 : 料仓服务 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/7/17 15:27:20 + /// 描 述 : + /// + public class StockInfoDto + { + /// + /// 料仓编码 + /// + public string Code { get; set; } + /// + /// 料仓名称 + /// + public string Name { get; set; } + /// + /// 物料Id + /// + public string MaterialId { get; set; } + /// + /// 料仓容积 + /// + public string Volume { get; set; } + } + /// + /// 增加 + /// + public class StockInfoAddInput : StockInfoDto + { + + } + /// + /// 更新 + /// + public class StockInfoUpdateInput : StockInfoDto + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 删除 + /// + public class StockInfoDelInput + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 分页 + /// + public class StockInfoQueryPageInput : RequestPage + { + /// + /// 名称 + /// + public string Name { get; set; } + /// + /// 编码 + /// + public string Code { get; set; } + } + /// + /// 输出 + /// + public class StockInfoOutput : StockInfoDto + { + /// + /// 主键 + /// + public string Id { get; set; } + /// + /// 物料Name + /// + public string MaterialName { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Services/StockInfoService/Services/IStockInfoService.cs b/backend/BPA.MES.Base.Application/Services/StockInfoService/Services/IStockInfoService.cs new file mode 100644 index 0000000..46e5196 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/StockInfoService/Services/IStockInfoService.cs @@ -0,0 +1,49 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :料仓服务 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/7/17 15:32:17 + /// 描 述 : + /// + public interface IStockInfoService + { + /// + /// 增加 + /// + /// + Task Add(StockInfoAddInput input); + /// + /// 移除 + /// + /// + Task Del(StockInfoDelInput input); + /// + /// 更新 + /// + /// + Task Update(StockInfoUpdateInput input); + /// + /// 不分页列表 + /// + /// + Task> List(); + /// + /// 分页列表 + /// + /// + Task> PagedList(StockInfoQueryPageInput input); + /// + /// 下拉列表 + /// + /// + Task SelectList(); + /// + /// 查询单条 + /// + /// + /// + Task Detail(string Id); + + } +} diff --git a/backend/BPA.MES.Base.Application/Services/StockInfoService/Services/StockInfoService.cs b/backend/BPA.MES.Base.Application/Services/StockInfoService/Services/StockInfoService.cs new file mode 100644 index 0000000..26ec87c --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/StockInfoService/Services/StockInfoService.cs @@ -0,0 +1,123 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :料仓服务 + /// 创 建 人 :yangxiao + /// 创建时间 :2023/3/2 16:11:04 + /// 描 述 :基础数据管理 + /// + [ApiDescriptionSettings("基础数据管理", Order = 1, Name = "StockInfo", Tag = "料仓服务", KeepName = true, SplitCamelCase = true, KeepVerb = true)] + public class StockInfoService : IStockInfoService, ITransient, IDynamicApiController + { + private readonly ISqlSugarClient _dbContext; + public StockInfoService(ISqlSugarClient db) + { + _dbContext = db; + } + /// + /// 增加 + /// + /// + /// + [HttpPost] + public async Task Add(StockInfoAddInput input) + { + var r_entity = await _dbContext.Queryable().FirstAsync(x => x.Name == input.Name || x.Code==input.Code); + if (r_entity != null) + { + throw Oops.Bah("名称或编码已存在!"); + } + Pztj_StockInfoEntity entity = input.Adapt(); + return await _dbContext.Insertable(entity).IgnoreColumns(ignoreNullColumn: true).ExecuteCommandIdentityIntoEntityAsync(); + } + /// + /// 删除 + /// + /// + /// + /// + [HttpPost] + public async Task Del(StockInfoDelInput input) + { + var res = await _dbContext.Deleteable().Where(x => x.Id == input.Id).ExecuteCommandHasChangeAsync(); + return res; + } + /// + /// 详情 + /// + /// + /// + /// + [HttpGet] + public async Task Detail(string Id) + { + var entity = await _dbContext.Queryable().FirstAsync(x => x.Id == Id); + StockInfoOutput output = entity.Adapt(); + return output; + } + /// + /// 列表 + /// + /// + /// + [HttpGet] + public async Task> List() + { + var entity = await _dbContext.Queryable().ToListAsync(); + List output = entity.Adapt>(); + return output; + } + /// + /// 分页 + /// + /// + /// + [HttpPost] + public async Task> PagedList(StockInfoQueryPageInput input) + { + var entity = await _dbContext.Queryable() + .LeftJoin((a,b)=>a.MaterialId==b.Id) + .Select((a,b)=>new StockInfoOutput + { + Id=a.Id.SelectAll(), + MaterialName= b.Name + }) + .ToPagedListAsync(input.PageIndex, input.PageSize); + SqlSugarPagedList output = entity.Adapt>(); + return output; + } + /// + /// 下拉 + /// + /// + /// + [HttpGet] + public async Task SelectList() + { + var entity = await _dbContext.Queryable().Select(x => new + { + key = x.Id, + value = x.Name + }).ToListAsync(); + return entity; + } + /// + /// 更新 + /// + /// + /// + /// + [HttpPost] + public async Task Update(StockInfoUpdateInput input) + { + var isExit =await _dbContext.Queryable().Where(x => x.Id != input.Id && (x.Name==input.Name || x.Code==input.Code)).FirstAsync(); + if (isExit != null) + { + throw Oops.Bah("名称或编码已存在!"); + } + Pztj_StockInfoEntity entity = input.Adapt(); + var res = await _dbContext.Updateable(entity).IgnoreColumns(true).ExecuteCommandHasChangeAsync(); + return res; + } + } +} diff --git a/backend/BPA.MES.Base.Application/Services/SysCacheService/ISysCacheService.cs b/backend/BPA.MES.Base.Application/Services/SysCacheService/ISysCacheService.cs new file mode 100644 index 0000000..f070ad9 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/SysCacheService/ISysCacheService.cs @@ -0,0 +1,15 @@ +namespace BPA.MES.Base.Application +{ + public interface ISysCacheService + { + Task AddCacheKey(string cacheKey); + Task DelCacheKey(string cacheKey); + bool Exists(string cacheKey); + Task> GetAllCacheKeys(); + Task GetAsync(string cacheKey); + Task GetStringAsync(string cacheKey); + Task RemoveAsync(string key); + Task SetAsync(string cacheKey, object value); + Task SetStringAsync(string cacheKey, string value); + } +} diff --git a/backend/BPA.MES.Base.Application/Services/SysCacheService/SysCacheService.cs b/backend/BPA.MES.Base.Application/Services/SysCacheService/SysCacheService.cs new file mode 100644 index 0000000..bc6de78 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/SysCacheService/SysCacheService.cs @@ -0,0 +1,163 @@ +using Furion.JsonSerialization; +using Microsoft.Extensions.Caching.Distributed; +using System.Text; + +namespace BPA.MES.Base.Application +{ + /// + /// 系统缓存服务 + /// + [ApiDescriptionSettings(Name = "Cache", Order = 100)] + public class SysCacheService : ISysCacheService, IDynamicApiController, ISingleton + { + private readonly IDistributedCache _cache; + + public SysCacheService(IDistributedCache cache) + { + _cache = cache; + } + + /// + /// 获取所有缓存关键字 + /// + /// + [HttpGet("sysCache/keyList")] + public async Task> GetAllCacheKeys() + { + var res = await _cache.GetStringAsync(ClaimConst.CACHE_KEY_ALL); + return string.IsNullOrWhiteSpace(res) ? null : JSON.Deserialize>(res); + } + + /// + /// 删除指定关键字缓存 + /// + /// + /// + [HttpGet("sysCache/remove")] + public async Task RemoveAsync(string key) + { + await _cache.RemoveAsync(key); + + await DelCacheKey(key); + } + + /// + /// 删除某特征关键字缓存 + /// + /// + /// + [NonAction] + public async Task DelByPatternAsync(string key) + { + var allkeys = await GetAllCacheKeys(); + var delAllkeys = allkeys.Where(u => u.Contains(key)).ToList(); + + // 删除相应的缓存 + delAllkeys.ForEach(u => + { + _cache.Remove(u); + }); + + // 更新所有缓存键 + allkeys = allkeys.Where(u => !u.Contains(key)).ToList(); + await _cache.SetStringAsync(ClaimConst.CACHE_KEY_ALL, JSON.Serialize(allkeys)); + } + + /// + /// 设置缓存 + /// + /// + /// + /// + [NonAction] + public async Task SetAsync(string cacheKey, object value) + { + await _cache.SetAsync(cacheKey, Encoding.UTF8.GetBytes(JSON.Serialize(value))); + + await AddCacheKey(cacheKey); + } + + /// + /// 设置缓存 + /// + /// + /// + /// + [NonAction] + public async Task SetStringAsync(string cacheKey, string value) + { + await _cache.SetStringAsync(cacheKey, value); + + await AddCacheKey(cacheKey); + } + + /// + /// 获取缓存 + /// + /// + /// + [HttpGet("sysCache/detail")] + public async Task GetStringAsync(string cacheKey) + { + return await _cache.GetStringAsync(cacheKey); + } + + /// + /// 获取缓存 + /// + /// + /// + /// + [NonAction] + public async Task GetAsync(string cacheKey) + { + var res = await _cache.GetAsync(cacheKey); + return res == null ? default : JSON.Deserialize(Encoding.UTF8.GetString(res)); + } + + /// + /// 检查给定 key 是否存在 + /// + /// 键 + /// + [NonAction] + public bool Exists(string cacheKey) + { + return _cache.Equals(cacheKey); + } + + /// + /// 增加缓存Key + /// + /// + /// + [NonAction] + public async Task AddCacheKey(string cacheKey) + { + var res = await _cache.GetStringAsync(ClaimConst.CACHE_KEY_ALL); + var allkeys = string.IsNullOrWhiteSpace(res) ? new List() : JSON.Deserialize>(res); + if (!allkeys.Any(m => m == cacheKey)) + { + allkeys.Add(cacheKey); + await _cache.SetStringAsync(ClaimConst.CACHE_KEY_ALL, JSON.Serialize(allkeys)); + } + } + + /// + /// + /// + /// + /// + [NonAction] + public async Task DelCacheKey(string cacheKey) + { + var res = await _cache.GetStringAsync(ClaimConst.CACHE_KEY_ALL); + var allkeys = string.IsNullOrWhiteSpace(res) ? new List() : JSON.Deserialize>(res); + if (allkeys.Any(m => m == cacheKey)) + { + allkeys.Remove(cacheKey); + await _cache.SetStringAsync(ClaimConst.CACHE_KEY_ALL, JSON.Serialize(allkeys)); + } + } + } +} diff --git a/backend/BPA.MES.Base.Application/Services/SystemService/Dtos/AccountInput.cs b/backend/BPA.MES.Base.Application/Services/SystemService/Dtos/AccountInput.cs new file mode 100644 index 0000000..5f26c29 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/SystemService/Dtos/AccountInput.cs @@ -0,0 +1,98 @@ +/// +/// 名 称 :[账号信息]实体基础 +/// 创 建 人 :yangxiao +/// 创建时间 : 2023/1/3 10:21:42 +/// 描 述 : +/// +namespace BPA.MES.Base.Application +{ + /// + /// [账号信息]入参基础 + /// + public class AccountInput + { + /// + /// 账号 + /// + /// admin + public string Account { get; set; } + /// + /// 密码 + /// + /// e10adc3949ba59abbe56e057f20f883e + public string Pwd { get; set; } + + } + /// + /// [账号信息]添加入参 + /// + public class AccountAddInput : AccountInput + { + /// + /// 员工编号 + /// + public string TB_Employee_Id { get; set; } + } + /// + /// [账号信息]修改入参 + /// + public class AccountUpdateInput : AccountInput + { + /// + /// 主键 + /// + public string? Id { get; set; } + /// + /// 员工编号 + /// + public string TB_Employee_Id { get; set; } + } + /// + /// [账号信息]修改密码 + /// + public class AccountUpdatePwdInput + { + /// + /// 旧密码 + /// + public string OldPwd { get; set; } + /// + /// 新密码 + /// + public string NewPwd { get; set; } + } + /// + /// [账号信息]删除入参 + /// + public class AccountDelInput + { + /// + /// 主键 + /// + public string? Id { get; set; } + } + /// + /// [账号信息]普通查询入参 + /// + public class AccountQueryInput + { + /// + /// 主键 + /// + public string? Id { get; set; } + } + /// + /// [账号信息]分页查询入参 + /// + public class AccountQueryPageInput : RequestPage + { + /// + /// 主键 + /// + public string? Id { get; set; } + /// + /// 账号名称 + /// + public string Account { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Services/SystemService/Dtos/AccountOutput.cs b/backend/BPA.MES.Base.Application/Services/SystemService/Dtos/AccountOutput.cs new file mode 100644 index 0000000..ea06298 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/SystemService/Dtos/AccountOutput.cs @@ -0,0 +1,29 @@ +namespace BPA.MES.Base.Application +{ + /// + /// 名 称 :[账号信息]输出实体 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/1/3 10:22:37 + /// 描 述 : + /// + public class AccountOutput + { + /// + /// 主键 + /// + public string Id { get;set; } + /// + /// 账号 + /// + public string Account { get; set; } + /// + /// 密码 + /// + public string Pwd { get; set; } + /// + /// 员工id + /// + public string TB_Employee_Id { get; set; } + + } +} diff --git a/backend/BPA.MES.Base.Application/Services/SystemService/Dtos/AuthorizeInput.cs b/backend/BPA.MES.Base.Application/Services/SystemService/Dtos/AuthorizeInput.cs new file mode 100644 index 0000000..4562531 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/SystemService/Dtos/AuthorizeInput.cs @@ -0,0 +1,97 @@ +/// +/// 名 称 :[授权信息]实体基础 +/// 创 建 人 :yangxiao +/// 创建时间 : 2023/1/3 10:21:42 +/// 描 述 +/// +namespace BPA.MES.Base.Application +{ + /// + /// [授权信息]入参基础 + /// + public class AuthorizeInput + { + /// + /// 关键字 + /// + public string Keyword { get; set; } + /// + /// 模板Id + /// + public string TemplateId { get; set; } + /// + /// 授权类型 1:用户,2:角色 + /// + public int Type { get; set; } + /// + /// 授权对象 + /// + public List? ObjectIds { get; set; } + } + /// + /// [授权信息]添加入参 + /// + public class AuthorizeAddInput : AuthorizeInput + { + + } + /// + /// [授权信息]角色授权入参 + /// + public class AuthorMapAddInput + { + /// + /// 模板编号 + /// + public List TemplateIds { get; set; } + /// + /// 授权类型 1用户 2角色 + /// + + public int AuthorizeType { get; set; } + /// + /// 授权对象 + /// + public string ObjectId { get; set; } + } + /// + /// [授权信息]修改入参 + /// + public class AuthorizeUpdateInput : AuthorizeInput + { + /// + /// 主键 + /// + public string? Id { get; set; } + } + /// + /// [授权信息]删除入参 + /// + public class AuthorizeDelInput + { + /// + /// 主键 + /// + public string? Id { get; set; } + } + /// + /// [授权信息]普通查询入参 + /// + public class AuthorizeQueryInput + { + /// + /// 主键 + /// + public string? Id { get; set; } + } + /// + /// [授权信息]分页查询入参 + /// + public class AuthorizeQueryPageInput : RequestPage + { + /// + /// 主键 + /// + public string? Id { get; set; } + } +} \ No newline at end of file diff --git a/backend/BPA.MES.Base.Application/Services/SystemService/Dtos/AuthorizeOutput.cs b/backend/BPA.MES.Base.Application/Services/SystemService/Dtos/AuthorizeOutput.cs new file mode 100644 index 0000000..7ef3dc9 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/SystemService/Dtos/AuthorizeOutput.cs @@ -0,0 +1,27 @@ +namespace BPA.MES.Base.Application +{ + /// + /// 名 称 :授权信息输出 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/1/4 17:24:21 + /// 描 述 : + /// + public class AuthorizeOutput + { + /// + /// 编号 + /// + public string Id { get; set; } + + /// + /// 名称 + /// + public string Name { get; set; } + + /// + /// 已授权 + /// + public bool IsAuthorized { get; set; } + } + +} diff --git a/backend/BPA.MES.Base.Application/Services/SystemService/Dtos/EmployeeInput.cs b/backend/BPA.MES.Base.Application/Services/SystemService/Dtos/EmployeeInput.cs new file mode 100644 index 0000000..baaa41f --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/SystemService/Dtos/EmployeeInput.cs @@ -0,0 +1,101 @@ +namespace BPA.MES.Base.Application +{ + /// + /// 名 称 : + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/1/5 15:15:50 + /// 描 述 : + /// + public class EmployeeInput + { + /// + /// 员工姓名 + /// + + public string Name { get; set; } + /// + /// 0男1女 + /// + public int Gender { get; set; } + /// + /// 0启用 1禁用 + /// + public int Status { get; set; } + /// + /// 角色Id + /// + public string RoleId { get; set; } + /// + /// 是否存在账号 + /// + public bool IsAccount { get; set; } + /// + /// 账号 + /// + public string Account { get; set; } + } + + /// + /// [授权信息]添加入参 + /// + public class EmployeeAddInput : EmployeeInput + { + + } + /// + /// [授权信息]修改入参 + /// + public class EmployeeUpdateInput : EmployeeInput + { + /// + /// 主键 + /// + public string? Id { get; set; } + } + /// + /// [授权信息]删除入参 + /// + public class EmployeeDelInput + { + /// + /// 主键 + /// + public string? Id { get; set; } + } + /// + /// [授权信息]普通查询入参 + /// + public class EmployeeQueryInput + { + /// + /// 主键 + /// + public string? Id { get; set; } + } + /// + /// [授权信息]分页查询入参 + /// + public class EmployeeQueryPageInput : RequestPage + { + /// + /// 主键 + /// + public string? Id { get; set; } + /// + /// 关键字 + /// + public string name { get; set; } + /// + /// 状态 + /// + public int Status { get; set; } + /// + /// 性别 + /// + public int Gender { get; set; } + /// + /// 入职时间 + /// + public DateTime? JoinDate { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Services/SystemService/Dtos/EmployeeOutput.cs b/backend/BPA.MES.Base.Application/Services/SystemService/Dtos/EmployeeOutput.cs new file mode 100644 index 0000000..3373c3a --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/SystemService/Dtos/EmployeeOutput.cs @@ -0,0 +1,45 @@ +namespace BPA.MES.Base.Application +{ + /// + /// 名 称 :[员工信息] + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/1/5 15:18:02 + /// 描 述 : + /// + public class EmployeeOutput + { + /// + /// 主键 + /// + public string Id { get; set; } + /// + /// 排序 + /// + public int Sort { get; set; } + /// + /// 员工姓名 + /// + public string Name { get; set; } + /// + /// 0男1女 + /// + + public int Gender { get; set; } + /// + /// 0启用 1禁用 + /// + public int Status { get; set; } + /// + /// 角色Id + /// + public string RoleId { get; set; } + /// + /// 是否存在账号 + /// + public bool IsAccount { get; set; } + /// + /// 账号 + /// + public string Account { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Services/SystemService/Dtos/Mapper.cs b/backend/BPA.MES.Base.Application/Services/SystemService/Dtos/Mapper.cs new file mode 100644 index 0000000..8487bf4 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/SystemService/Dtos/Mapper.cs @@ -0,0 +1,8 @@ +namespace BPA.MES.Base.Application; + +public class Mapper : IRegister +{ + public void Register(TypeAdapterConfig config) + { + } +} diff --git a/backend/BPA.MES.Base.Application/Services/SystemService/Dtos/ModuleInput.cs b/backend/BPA.MES.Base.Application/Services/SystemService/Dtos/ModuleInput.cs new file mode 100644 index 0000000..102ed2b --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/SystemService/Dtos/ModuleInput.cs @@ -0,0 +1,94 @@ +/// +/// 名 称 :[模块信息]实体基础 +/// 创 建 人 :yangxiao +/// 创建时间 : 2023/1/3 10:21:42 +/// 描 述 +/// +namespace BPA.MES.Base.Application +{ + /// + /// [模块信息]入参基础 + /// + public class ModuleInput + { + /// + /// 类别 1:菜单,2:视图,3:功能 + /// + public int Category { get; set; } + /// + /// 菜单打开方式 0:框架内嵌,1:新开页面 + /// + public int OpenType { get; set; } + /// + /// 父级编号 + /// + public string ParentId { get; set; } + /// + /// 名称 + /// + public string Name { set; get; } + /// + /// 图标 + /// + public string Icon { set; get; } + /// + /// 地址 + /// + public string Url { set; get; } + /// + /// 排序码 + /// + public int Sort { set; get; } + /// + /// 启用禁用 + /// + public bool IsDisabled { get; set; } + } + /// + /// [模块信息]添加入参 + /// + public class ModuleAddInput : ModuleInput + { + + } + /// + /// [模块信息]修改入参 + /// + public class ModuleUpdateInput : ModuleInput + { + /// + /// 主键 + /// + public string? Id { get; set; } + } + /// + /// [模块信息]删除入参 + /// + public class ModuleDelInput + { + /// + /// 主键 + /// + public string? Id { get; set; } + } + /// + /// [模块信息]普通查询入参 + /// + public class ModuleQueryInput + { + /// + /// 主键 + /// + public string? Id { get; set; } + } + /// + /// [模块信息]分页查询入参 + /// + public class ModuleQueryPageInput : RequestPage + { + /// + /// 主键 + /// + public string? Id { get; set; } + } +} \ No newline at end of file diff --git a/backend/BPA.MES.Base.Application/Services/SystemService/Dtos/ModuleOutput.cs b/backend/BPA.MES.Base.Application/Services/SystemService/Dtos/ModuleOutput.cs new file mode 100644 index 0000000..ae5b46b --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/SystemService/Dtos/ModuleOutput.cs @@ -0,0 +1,48 @@ +namespace BPA.MES.Base.Application +{ + /// + /// 名 称 : + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/1/4 9:48:24 + /// 描 述 : + /// + public class ModuleOutput + { + /// + /// 主键 + /// + public string Id { get; set; } + /// + /// 类别 1:菜单,2:视图,3:功能 + /// + public int Category { get; set; } + /// + /// 菜单打开方式 0:框架内嵌,1:新开页面 + /// + public int OpenType { get; set; } + /// + /// 父级编号 + /// + public string ParentId { get; set; } + /// + /// 名称 + /// + public string Name { set; get; } + /// + /// 图标 + /// + public string Icon { set; get; } + /// + /// 地址 + /// + public string Url { set; get; } + /// + /// 排序码 + /// + public int Sort { set; get; } + /// + /// 启用禁用 + /// + public bool IsDisabled { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Services/SystemService/Dtos/ModuleTreeInput.cs b/backend/BPA.MES.Base.Application/Services/SystemService/Dtos/ModuleTreeInput.cs new file mode 100644 index 0000000..9113544 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/SystemService/Dtos/ModuleTreeInput.cs @@ -0,0 +1,108 @@ +/// +/// 名 称 :[菜单模块树]实体基础 +/// 创 建 人 :yangxiao +/// 创建时间 : 2023/1/3 10:21:42 +/// 描 述 +/// +namespace BPA.MES.Base.Application +{ + /// + /// [菜单模块树]入参基础 + /// + public class ModuleTreeInput + { + /// + /// 类别 1:菜单,2:视图,3:功能 + /// + public int Category { get; set; } + + /// + /// 菜单打开方式 0:框架内嵌,1:新开页面 + /// + public int OpenType { get; set; } + + /// + /// 父级编号 + /// + public string ParentId { get; set; } + + /// + /// 名称 + /// + public string Name { set; get; } + + /// + /// 图标 + /// + public string Icon { set; get; } + + /// + /// 地址 + /// + public string Url { set; get; } + /// + /// 排序码 + /// + public int Sort { set; get; } + /// + /// 启用禁用 + /// + public bool IsDisabled { get; set; } + + /// + /// 子集 + /// + public List Children { get; set; } + } + /// + /// [菜单模块树]添加入参 + /// + public class ModuleTreeAddInput : ModuleTreeInput + { + + } + /// + /// [菜单模块树]修改入参 + /// + public class ModuleTreeUpdateInput : ModuleTreeInput + { + /// + /// 主键 + /// + public string? Id { get; set; } + } + /// + /// [菜单模块树]删除入参 + /// + public class ModuleTreeDelInput + { + /// + /// 主键 + /// + public string? Id { get; set; } + } + /// + /// [菜单模块树]普通查询入参 + /// + public class ModuleTreeQueryInput + { + /// + /// 主键 + /// + public string? Id { get; set; } + /// + /// 名称 + /// + public string Name { get; set; } + } + /// + /// [菜单模块树]分页查询入参 + /// + public class ModuleTreeQueryPageInput : RequestPage + { + /// + /// 主键 + /// + public string? Id { get; set; } + } +} \ No newline at end of file diff --git a/backend/BPA.MES.Base.Application/Services/SystemService/Dtos/ModuleTreeOutput.cs b/backend/BPA.MES.Base.Application/Services/SystemService/Dtos/ModuleTreeOutput.cs new file mode 100644 index 0000000..a8771bd --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/SystemService/Dtos/ModuleTreeOutput.cs @@ -0,0 +1,59 @@ +namespace BPA.MES.Base.Application +{ + /// + /// 名 称 :[菜单模块树]输出 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/1/4 16:14:43 + /// 描 述 : + /// + public class ModuleTreeOutput + { + /// + /// 模块编号 + /// + public string Id { get; set; } + + /// + /// 类别 1:菜单,2:视图,3:功能 + /// + public int Category { get; set; } + + /// + /// 菜单打开方式 0:框架内嵌,1:新开页面 + /// + public int OpenType { get; set; } + + /// + /// 父级编号 + /// + public string ParentId { get; set; } + + /// + /// 名称 + /// + public string Name { set; get; } + + /// + /// 图标 + /// + public string Icon { set; get; } + + /// + /// 地址 + /// + public string Url { set; get; } + /// + /// 排序码 + /// + public int Sort { set; get; } + /// + /// 启用禁用 + /// + public bool IsDisabled { get; set; } + + /// + /// 子集 + /// + public List Children { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Services/SystemService/Dtos/RoleInput.cs b/backend/BPA.MES.Base.Application/Services/SystemService/Dtos/RoleInput.cs new file mode 100644 index 0000000..69e5a12 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/SystemService/Dtos/RoleInput.cs @@ -0,0 +1,71 @@ +namespace BPA.MES.Base.Application +{ + /// + /// 名 称 :[角色信息] + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/1/4 9:43:25 + /// 描 述 : + /// + public class RoleInput + { + /// + /// 角色名称 + /// + public string Name { get; set; } + /// + /// 角色描述 + /// + public string Description { get; set; } + } + /// + /// [角色信息]添加入参 + /// + public class RoleAddInput : RoleInput + { + + } + /// + /// [角色信息]修改入参 + /// + public class RoleUpdateInput : RoleInput + { + /// + /// 主键 + /// + public string? Id { get; set; } + } + /// + /// [角色信息]删除入参 + /// + public class RoleDelInput + { + /// + /// 主键 + /// + public string? Id { get; set; } + } + /// + /// [角色信息]普通查询入参 + /// + public class RoleQueryInput + { + /// + /// 主键 + /// + public string? Id { get; set; } + } + /// + /// [角色信息]分页查询入参 + /// + public class RoleQueryPageInput : RequestPage + { + /// + /// 主键 + /// + public string? Id { get; set; } + /// + /// 关键字 + /// + public string Keyword { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Services/SystemService/Dtos/RoleModuleDto.cs b/backend/BPA.MES.Base.Application/Services/SystemService/Dtos/RoleModuleDto.cs new file mode 100644 index 0000000..dbb6a2c --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/SystemService/Dtos/RoleModuleDto.cs @@ -0,0 +1,50 @@ +namespace BPA.MES.Base.Application +{ + /// + /// 名 称 : + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/8/31 15:58:31 + /// 描 述 : + /// + public class RoleModuleDto + { + /// + /// 角色Id + /// + public string RoleId { get; set; } + /// + /// 模块Id + /// + public string ModuleId { get; set; } + /// + /// 父级Id + /// + public string ParentId { get; set; } + } + public class RoleModuleAddInput + { + public List ModuleIds { get; set; } + /// + /// 角色Id + /// + public string RoleId { get; set; } + } + public class RoleModuleOutput + { + /// + /// 角色Id + /// + public string RoleId { get; set; } + /// + /// 模块Id + /// + public string ModuleId { get; set; } + } + public class RoleModuleQuery + { + /// + /// 角色Id + /// + public string RoleId { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Services/SystemService/Dtos/RoleOutput.cs b/backend/BPA.MES.Base.Application/Services/SystemService/Dtos/RoleOutput.cs new file mode 100644 index 0000000..423080d --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/SystemService/Dtos/RoleOutput.cs @@ -0,0 +1,24 @@ +namespace BPA.MES.Base.Application +{ + /// + /// 名 称 :角色信息 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/1/4 9:43:42 + /// 描 述 : + /// + public class RoleOutput + { + /// + /// 主键 + /// + public string Id { get; set; } + /// + /// 角色名称 + /// + public string Name { get; set; } + /// + /// 角色描述 + /// + public string Description { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Services/SystemService/Dtos/UserRoleCacheDto.cs b/backend/BPA.MES.Base.Application/Services/SystemService/Dtos/UserRoleCacheDto.cs new file mode 100644 index 0000000..112a260 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/SystemService/Dtos/UserRoleCacheDto.cs @@ -0,0 +1,62 @@ + + + + + +namespace BPA.MES.Base.Application +{ + /// + /// 名 称 :个人角色信息 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/1/4 17:46:47 + /// 描 述 : + /// + public class UserRoleCacheDto + { + public List AuthorizationCodes { get; set; } + public List Menus { get; set; } + } + +/// +/// 个人菜单信息 +/// +public class UserMenu : ITree + { + /// + /// 主键 + /// + public string Id { get; set; } + /// + /// 菜单名称 + /// + public string Name { get; set; } + /// + /// 菜单地址 + /// + public string Url { get; set; } + /// + /// 菜单图标 + /// + public string Icon { get; set; } + /// + /// 菜单子项 + /// + public List Children { get; set; } + /// + /// 父级Id + /// + public string ParentId { get; set; } + /// + /// 分页信息 + /// + public string Sort { get; set; } + /// + /// 打开类型 + /// + public int OpenType { get; set; } + /// + /// 类别 + /// + public int Category { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Services/SystemService/Services/AuthorizeService.cs b/backend/BPA.MES.Base.Application/Services/SystemService/Services/AuthorizeService.cs new file mode 100644 index 0000000..8359ee2 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/SystemService/Services/AuthorizeService.cs @@ -0,0 +1,467 @@ +namespace BPA.MES.Base.Application +{ + /// + /// 名 称 :授权服务 + /// 创 建 人 :yangxiao + /// 创建时间 :2023/3/2 16:11:04 + /// 描 述 :授权服务数据维护 + /// + [ApiDescriptionSettings(Name = "Authorize", KeepName = true, SplitCamelCase = true, KeepVerb = true)] + public class AuthorizeService : IAuthorizeService, ITransient, IDynamicApiController + { + private readonly IHttpContextAccessor _httpContextAccessor; + private readonly ISqlSugarClient db; + private readonly ISqlSugarClient _dbContext; + public AuthorizeService(ISqlSugarClient db, IHttpContextAccessor httpContextAccessor) + { + this.db = db; + _dbContext = db; + _httpContextAccessor = httpContextAccessor; + } + #region 当前用户 + /// + /// 登录 + /// + /// + /// + + [AllowAnonymous] + public async Task Login(AccountInput input) + { + var Info = await db.Queryable().FirstAsync(t => t.Account == input.Account && t.Pwd == input.Pwd); + if (Info == null) + throw Oops.Bah("请输入正确的账号和密码"); + var User = await db.Queryable().FirstAsync(t => t.Id == Info.EmployeeId); + if (User == null) + { + throw Oops.Bah("账号没有权限"); + } + //return ResolveService().CreateAccessToken(new UserIdentity + //{ + // Id = User.Id, + // UserName = User.Name, + // IsAdmin = User.IsAdmin, + //}); + + // 生成Token令牌 + //var accessToken = await _jwtBearerManager.CreateTokenAdmin(user); + var accessToken = JWTEncryption.Encrypt(new Dictionary + { + {ClaimConst.CLAINM_USERID, User.Id}, + {ClaimConst.CLAINM_NAME,User.Name}, + {ClaimConst.CLAINM_ACCOUNT,Info.Account }, + {ClaimConst.CLAINM_ISAUTH,User.IsAdmin}, + {ClaimConst.CLAINM_ROLEID,User.RoleId } + }, 43200); + // 设置Swagger自动登录 + _httpContextAccessor.HttpContext.SigninToSwagger(accessToken); + // 生成刷新Token令牌 + var refreshToken = + JWTEncryption.GenerateRefreshToken(accessToken, int.MaxValue); + + _httpContextAccessor.HttpContext.Response.Headers["access-token"] = accessToken; + // 设置刷新Token令牌 + _httpContextAccessor.HttpContext.Response.Headers["x-access-token"] = refreshToken; + return true; + } + /// + /// 获取个人信息 + /// + /// + public async Task GetUserInfo() + { + string userId = App.User?.FindFirst(ClaimConst.CLAINM_USERID)?.Value; + var user = await db.Queryable().LeftJoin((t, x) => t.RoleId == x.Id) + .Where((t, x) => t.Id == userId).Select((t, x) => new + { + RoleName = x.Name, + RoleType = x.RoleType, + Id = t.Id, + UserName = t.Name + }).FirstAsync(); + + + var menus = (await GetJurisdictionItemsAsync())?.Menus; + return new + { + Menus = menus, + UserInfo = new + { + UserId = user?.Id, + user?.RoleName, + user?.UserName + } + }; + } + [HttpGet] + public async Task> MultipleModuleAuthorityAsync() + { + return (await GetJurisdictionItemsAsync())?.AuthorizationCodes; + } + /// + /// 获取用户权限 + /// + /// + [HttpGet] + async Task GetJurisdictionItemsAsync() + { + + string userId = App.User?.FindFirst(ClaimConst.CLAINM_USERID)?.Value; + string roleId = App.User?.FindFirst(ClaimConst.CLAINM_ROLEID)?.Value; + var result = new UserRoleCacheDto(); + //根据角色获取权限Id + var rolemodules = await db.Queryable().Where(x => x.RoleId == roleId).ToListAsync(); + result.AuthorizationCodes = rolemodules.Select(t => t.ModuleId).ToList(); + if (result.AuthorizationCodes.HasVal()) + { + var temp = await db.Queryable().Where(t => result.AuthorizationCodes.Contains(t.Id) && !t.IsDisabled).OrderBy(t => t.ParentId) + .ToListAsync(); + + result.Menus = temp.Adapt>().BuildTree(); + } + result.Menus ??= new List(); + + return result; + } + /// + /// 获取账户信息 + /// + /// + /// + [HttpPost] + public async Task> AccountPageList(AccountQueryPageInput input) + { + var entity = await _dbContext.Queryable() + .WhereIF(!string.IsNullOrEmpty(input.Account),x=>x.Account==input.Account) + .ToPagedListAsync(input.PageIndex,input.PageSize); + SqlSugarPagedList output = entity.Adapt>(); + return output; + } + + /// + /// 添加账户 + /// + /// + /// + public async Task AddAccount(AccountAddInput input) + { + var entity = input.Adapt(); + return await _dbContext.Insertable(entity).ExecuteCommandIdentityIntoEntityAsync(); + } + /// + /// 修改账户信息 + /// + /// + /// + public async Task UpdateAccount(AccountUpdateInput input) { + var entity = input.Adapt(); + return await _dbContext.Updateable(entity).IgnoreColumns(true).ExecuteCommandHasChangeAsync(); + } + /// + /// 删除账户 + /// + /// + /// + public async Task DelAccount(AccountDelInput input) { + var entity = input.Adapt(); + return await _dbContext.Deleteable(entity).Where(x=>x.Id==input.Id).ExecuteCommandHasChangeAsync(); + } + #endregion + #region 角色 + [HttpPost] + public async Task AddRole(RoleAddInput input) + { + var check = await db.Queryable().FirstAsync(t => t.Name == input.Name); + if (check != null) throw Oops.Bah ("角色名称不能重复"); + var model = input.Adapt(); + model.RoleType = 2; + return await db.Insertable(model).ExecuteCommandAsync() > 0; + } + [HttpPost] + public async Task EditRole(RoleUpdateInput input) + { + if (!await db.Queryable().Where(it => it.Id == input.Id).AnyAsync()) + throw Oops.Bah("角色不存在或已被删除"); + if (await _dbContext.Queryable().Where(it => it.Id != input.Id && it.Name == input.Name).AnyAsync()) + throw Oops.Bah("角色名称已经存在"); + return await _dbContext.Updateable(input).Where(a => a.Id == input.Id).ExecuteCommandHasChangeAsync(); + } + [HttpGet] + public async Task RemoveRole(string input) + { + return await db.Deleteable().Where(t => t.Id == input).ExecuteCommandHasChangeAsync(); + } + [HttpGet] + public async Task GetRole(string input) + { + var entity = await db.Queryable().FirstAsync(t => t.Id == input); + return entity.Adapt(); + } + [HttpGet] + public async Task> GetRoleList() + { + var entity = await db.Queryable().Where(t => t.RoleType != 1).ToListAsync(); + return entity.Adapt>(); + } + [HttpPost] + public async Task> QueryRole(RoleQueryPageInput input) + { + var eneity = await db.Queryable() + .WhereIF(!string.IsNullOrEmpty(input.Keyword), t => t.Name.Contains(input.Keyword)) + .Select() + .ToPagedListAsync(input.PageIndex, input.PageSize); + return eneity; + } + #endregion + + #region 模块 + [HttpPost] + public async Task AddModule(ModuleAddInput input) + { + input.ParentId = input.ParentId ?? string.Empty; + var entity = input.Adapt(); + await db.Insertable(entity).IgnoreColumns(true).ExecuteCommandAsync(); + return true; + } + [HttpPost] + + public async Task EditModule(ModuleUpdateInput input) + { + if (!await db.Queryable().Where(it => it.Id == input.Id ).AnyAsync()) + { + throw Oops.Bah("模块不存在或已被删除"); + } + input.ParentId = input.ParentId ?? string.Empty; + return await db.Updateable(input).Where(a => a.Id == input.Id).ExecuteCommandHasChangeAsync(); + } + [HttpGet] + + public async Task RemoveModule(string input) + { + var list = await db.Queryable().Where(it => it.ParentId == input).ToListAsync(); + if (list.HasVal()) + { + foreach (var item in list) + { + await RemoveModule(item.Id); + } + } + await _dbContext.Deleteable().Where(it => it.Id == input).ExecuteCommandAsync(); + } + [HttpPost] + public async Task> GetTreeGrid(ModuleTreeQueryInput input) + { + var list = new List(); + + var datas = await db.Queryable() + .WhereIF(!string.IsNullOrEmpty(input.Name), t => t.Name.Contains(input.Name)) + .OrderBy(it => it.ParentId) + .OrderBy(it => it.Name) + .ToListAsync(); + + var modules = datas.Adapt>(); + + if (modules.HasVal()) + { + foreach (var item in modules.Where(it=>it.ParentId=="").ToList()) + { + item.Children = modules.Where(it => it.ParentId == item.Id ).OrderBy(it => it.Sort).ToList(); + foreach (var view in item.Children) + { + view.Children = modules.Where(it => it.ParentId == view.Id ).OrderBy(it => it.Sort).ToList(); + } + + list.Add(item); + } + } + return list; + } + #endregion + + #region 授权模板详情 + [HttpGet] + public async Task RestoreAccountByUser(string input) + { + var Demo = "123456".ToMD5Encrypt(); + return await db.Updateable().SetColumns(t => t.Pwd == Demo) + .Where(t => t.EmployeeId == input).ExecuteCommandHasChangeAsync(); + } + [HttpPost] + public async Task AddAccountByUser(AccountAddInput input) + { + var temp = await db.Queryable().FirstAsync(t => t.EmployeeId == input.TB_Employee_Id); + if (temp != null) + { + //throw new BusinessException("该员工已绑定账户,请勿重复绑定"); + temp.Account = input.Account; + return await db.Updateable(temp).ExecuteCommandAsync() > 0; + } + else + { + var model = input.Adapt(); + //默认123456 + model.Pwd = "123456".ToMD5Encrypt(); + model.EmployeeId = input.TB_Employee_Id; + return await db.Insertable(model).ExecuteCommandAsync() > 0; + } + } + [HttpPost] + public async Task EditAccountPwd(AccountUpdatePwdInput input) + { + var Account = App.User?.FindFirst(ClaimConst.CLAINM_ACCOUNT)?.Value; + var model = db.Queryable().First(t => t.Account == Account && t.Pwd == input.OldPwd); + if (model == null) throw Oops.Bah("原密码不正确"); + model.Pwd = input.NewPwd; + return await db.Updateable(model).ExecuteCommandAsync() > 0; + } + [HttpGet] + public async Task GetAccountByUser(string input) + { + var data = await db.Queryable().FirstAsync(t => t.EmployeeId == input); + return data.Adapt(); + } + + [HttpPost] + public async Task AddEmployee(EmployeeAddInput input) + { + var model = input.Adapt(); + model.IsAdmin = false; + return await db.Insertable(model).IgnoreColumns(true).ExecuteCommandAsync() > 0; + } + /// + /// 编辑员工 + /// + /// + /// + [HttpPost] + public async Task EditEmployee(EmployeeUpdateInput input) + { + var temp = await db.Queryable().FirstAsync(t => t.Id == input.Id); + temp.Name = input.Name; + temp.Status = input.Status; + return await db.Updateable(temp).ExecuteCommandHasChangeAsync(); + } + /// + /// 查询员工 + /// + /// + /// + [HttpPost] + public async Task> QueryEmployee(EmployeeQueryPageInput input) + { + + var entity = await db.Queryable() + + .WhereIF(!string.IsNullOrEmpty(input.name), t => t.Name.Contains(input.name)) + .WhereIF(input.Status > 0, t => t.Status == input.Status). + WhereIF(input.Gender > 0, t => t.Gender == input.Gender) + .Where(t => t.IsAdmin == false) + + .Select(t => new EmployeeOutput() + { + Id = t.Id.SelectAll(), + IsAccount = SqlFunc.Subqueryable().Where(s => s.EmployeeId == t.Id).Any(), + Account = SqlFunc.Subqueryable().Where(s => s.EmployeeId == t.Id).Select(s => s.Account) + }) + .ToPagedListAsync(input.PageIndex, input.PageSize); + return entity; + } + /// + /// 删除员工 + /// + /// + /// + [HttpGet] + public async Task RemoveEmployee([FromQuery] string employeeId) + { + try + { + db.Ado.BeginTran(); + await db.Deleteable().Where(t => t.Id == employeeId).ExecuteCommandAsync(); + await db.Deleteable().Where(t => t.EmployeeId == employeeId).ExecuteCommandAsync(); + db.Ado.CommitTran(); + return true; + } + catch (Exception ex) + { + db.Ado.RollbackTran(); + throw Oops.Bah("删除失败!"); + } + } + [HttpGet] + public async Task> EmployeeList() + { + var data = await db.Queryable().Where(t => t.IsAdmin == false).ToListAsync(); + return data.Adapt>(); + } + /// + /// 分配角色权限 + /// + /// + /// + [HttpPost] + public async Task AddRoleModule(RoleModuleAddInput input) + { + List entitys = new(); + var moduleList =await _dbContext.Queryable().ToListAsync(); + var parentId = input.ModuleIds.Where(x=>x.ParentId!="").GroupBy(x => x.ParentId).ToList(); + foreach (var item in parentId) + { + if (input.ModuleIds.FirstOrDefault(x=>x.ModuleId==item.Key && x.ParentId=="")==null) + { + input.ModuleIds.Add(new RoleModuleDto { ModuleId = item.Key, ParentId = "", RoleId = input.RoleId }); + } + } + foreach (var item in input.ModuleIds) + { + + RoleModuleEntity entity = new() + { + ModuleId = item.ModuleId, + ParentId = item.ParentId, + RoleId = input.RoleId + }; + entitys.Add(entity); + } + try + { + _dbContext.Ado.BeginTran(); + await _dbContext.Deleteable().Where(x => x.RoleId == input.RoleId).ExecuteCommandAsync(); + await _dbContext.Insertable(entitys).ExecuteCommandAsync(); + _dbContext.Ado.CommitTran(); + return true; + } + catch (Exception ex) + { + throw Oops.Bah(ex.Message); + } + } + /// + /// 根据角色获取权限模块 + /// + /// + /// + [HttpGet] + public async Task> RoleModuleList(string RoleId) + { + var entitys = await _dbContext.Queryable().Where(x => x.RoleId == RoleId).ToListAsync(); + var tementity = entitys.Where(x => x.ParentId == "").ToList();//查询出主菜单 + var delentity = new List(); + foreach (var item in tementity)//查询出主菜单是否有多个 + { + var v = entitys.Where(x=>x.ParentId==item.ModuleId).ToList(); + if (v.Count>0)//如果只有一个,就不删除 + { + delentity.Add(item); + } + } + foreach (var item in delentity) + { + entitys.Remove(item); + } + var output = entitys.Adapt>(); + return output; + } + #endregion + } +} diff --git a/backend/BPA.MES.Base.Application/Services/SystemService/Services/IAuthorizeService.cs b/backend/BPA.MES.Base.Application/Services/SystemService/Services/IAuthorizeService.cs new file mode 100644 index 0000000..2cd96d5 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/SystemService/Services/IAuthorizeService.cs @@ -0,0 +1,50 @@ +namespace BPA.MES.Base.Application; + +public interface IAuthorizeService +{ + + #region 账户 + Task RestoreAccountByUser(string input); + Task AddAccountByUser(AccountAddInput input); + Task EditAccountPwd(AccountUpdatePwdInput input); + Task GetAccountByUser(string input); + Task> AccountPageList(AccountQueryPageInput input); + Task AddAccount(AccountAddInput input); + Task UpdateAccount(AccountUpdateInput input); + Task DelAccount(AccountDelInput input); + Task Login(AccountInput input); + + #endregion + + #region 员工 + Task AddEmployee(EmployeeAddInput input); + Task EditEmployee(EmployeeUpdateInput input); + Task> QueryEmployee(EmployeeQueryPageInput input); + Task RemoveEmployee(string input); + Task> EmployeeList(); + #endregion + + + Task GetUserInfo(); + Task> MultipleModuleAuthorityAsync(); + + #region 角色 + Task AddRole(RoleAddInput input); + Task EditRole(RoleUpdateInput input); + Task RemoveRole(string input); + Task GetRole(string input); + Task> GetRoleList(); + Task> QueryRole(RoleQueryPageInput input); + + Task AddRoleModule(RoleModuleAddInput input); + #endregion + + #region 模块 + Task AddModule(ModuleAddInput input); + Task EditModule(ModuleUpdateInput input); + Task RemoveModule(string input); + Task> GetTreeGrid(ModuleTreeQueryInput input); + #endregion + + +} diff --git a/backend/BPA.MES.Base.Application/Services/WorkInfoService/Dtos/WorkBatchDto.cs b/backend/BPA.MES.Base.Application/Services/WorkInfoService/Dtos/WorkBatchDto.cs new file mode 100644 index 0000000..5a4e905 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/WorkInfoService/Dtos/WorkBatchDto.cs @@ -0,0 +1,98 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 : + /// 创 建 人 :yangxiao + /// 创建时间 : 2024/4/8 15:46:52 + /// 描 述 : + /// + public class WorkBatchDto + { + /// + /// 批次名词 + /// + public string Name { get; set; } + /// + /// 创建时间 + /// + public DateTime CreateTime { get; set; } + /// + /// 状态 + /// + public WorkOrderStatusEnum? Status { get; set; } + + } + + /// + /// 增加 + /// + public class WorkBatchAddInput : WorkBatchDto + { + + } + /// + /// 更新 + /// + public class WorkBatchUpdateInput : WorkBatchDto + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 删除 + /// + public class WorkBatchDelInput + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 不分页 + /// + public class WorkBatchQueryInput + { + + } + /// + /// 分页 + /// + public class WorkBatchQueryPageInput : RequestPage + { + /// + /// 创建时间 + /// + public DateTime CreateTime { get; set; } + + public string Id { get; set; } + + /// + /// 起始时间 + /// + public DateTime? StartTime { get; set; } + /// + /// 结束时间 + /// + public DateTime? EndTime { get; set; } + } + /// + /// 输出 + /// + public class WorkBatchOutput : WorkBatchDto + { + /// + /// 主键 + /// + public string Id { get; set; } + /// + /// 个数 + /// + public int Count { get; set; } + + public List WorkList { get; set; } = new(); + + } +} \ No newline at end of file diff --git a/backend/BPA.MES.Base.Application/Services/WorkInfoService/Dtos/WorkInfoCraftstepRecordDto.cs b/backend/BPA.MES.Base.Application/Services/WorkInfoService/Dtos/WorkInfoCraftstepRecordDto.cs new file mode 100644 index 0000000..710c7f1 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/WorkInfoService/Dtos/WorkInfoCraftstepRecordDto.cs @@ -0,0 +1,91 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 : + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/8/10 14:19:47 + /// 描 述 : + /// + public class WorkInfoCraftstepRecordDto + { + /// + /// 工艺Id + /// + public string CraftsId { get; set; } + /// + /// 工艺名称 + /// + public string CraftsName { get; set; } + /// + /// 工艺步骤 + /// + public string CraftstepId { get; set; } + /// + /// 工艺步骤名称 + /// + public string CraftstepName { get; set; } + /// + /// 执行状态 + /// + public RecipeStatus Status { get; set; } + /// + /// 更新状态 + /// + public DateTime UpdateTime { get; set; } + } /// + /// 增加 + /// + public class WorkInfoCraftstepRecordAddInput : WorkInfoCraftstepRecordDto + { + + } + /// + /// 更新 + /// + public class WorkInfoCraftstepRecordUpdateInput + { + /// + /// 工单工艺步骤Id + /// + public string WorkCraftstepId { get; set; } + /// + /// 工单Id + /// + public string WorkId { get; set; } + /// + /// 锅数 + /// + public string PotNum { get; set; } + /// + /// 状态 + /// + public RecipeStatus Status { get; set; } + } + /// + /// 删除 + /// + public class WorkInfoCraftstepRecordDelInput + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 分页 + /// + public class WorkInfoCraftstepRecordQueryPageInput : RequestPage + { + + } + /// + /// 输出 + /// + public class WorkInfoCraftstepRecordOutput : WorkInfoCraftstepRecordDto + { + /// + /// 主键 + /// + public string Id { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Services/WorkInfoService/Dtos/WorkInfoDto.cs b/backend/BPA.MES.Base.Application/Services/WorkInfoService/Dtos/WorkInfoDto.cs new file mode 100644 index 0000000..8504f49 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/WorkInfoService/Dtos/WorkInfoDto.cs @@ -0,0 +1,203 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 : + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/7/20 14:29:09 + /// 描 述 : + /// + public class WorkInfoDto : IMessage + { + /// + /// 工单名称 + /// + public string Name { get; set; } + /// + /// 产线Id + /// + public string LineId { get; set; } + /// + /// 成品Id + /// + public string FinalId { get; set; } + /// + /// 产量 + /// + public string Number { get; set; } + /// + /// 批次号 + /// + public string BatchId { get; set; } + /// + /// 设备id + /// + public string DeviceId { get; set; } + /// + /// 创建时间 + /// + public string CreateTime { get; set; } + public int MessageId { get; set; } + + public Version MsgVersion { get; set; } + } + /// + /// 增加 + /// + public class WorkInfoAddInput : WorkInfoDto + { + + } + /// + /// 更新 + /// + public class WorkInfoUpdateInput : WorkInfoDto + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 删除 + /// + public class WorkInfoDelInput + { + /// + /// 主键 + /// + public string Id { get; set; } + } + + /// + /// 不分页查询条件 + /// + public class WorkInfoQueryInput + { + /// + /// 名称 + /// + public string Name { get; set; } + /// + /// 主键 + /// + public string Id { get; set; } + /// + /// 工单状态 + /// + public WorkOrderStatusEnum?[] Status { get; set; } + /// + /// 起始时间 + /// + public DateTime? StartTime { get; set; } + /// + /// 结束时间 + /// + public DateTime? EndTime { get; set; } + /// + /// 批次计划Id + /// + public string BatchId { get; set; } + } + /// + /// 分页 + /// + public class WorkInfoQueryPageInput : RequestPage + { + /// + /// 名称 + /// + public string Name { get; set; } + /// + /// 编码 + /// + public string Id { get; set; } + /// + /// 工单状态 + /// + public WorkOrderStatusEnum?[] Status { get; set; } + /// + /// 批次计划Id + /// + + public string BatchId { get; set; } + /// + /// 起始时间 + /// + public DateTime? StartTime { get; set; } + /// + /// 结束时间 + /// + public DateTime? EndTime { get; set; } + } + /// + /// 工单下发 + /// + public class WorkPublishInput + { + + } + /// + /// 输出 + /// + public class WorkInfoOutput : WorkInfoDto + { + /// + /// 主键 + /// + public string Id { get; set; } + /// + /// 产品名称 + /// + public string FinalName { get; set; } + /// + /// 线名称 + /// + public string LineName { get; set; } + /// + /// 设备编码 + /// + public string DeviceCode { get; set; } + /// + /// 设备名称 + /// + public string DeviceName { get; set; } + /// + /// 工单状态 + /// + public WorkOrderStatusEnum? Status { get; set; } + + + + } + /// + /// 详情输出 + /// + public class WorkInfoDetailOutput : WorkInfoOutput + { + public WorkInfoDetailOutput() + { + + CraftList = new(); + MaterialList = new(); + } + /// + /// 工艺状态 + /// + public RecipeStatus? CraftStatus { get; set; } + /// + /// 配方状态 + /// + public EBatchingStatus? MaterialStatus { get; set; } + /// + /// 工艺步骤 + /// + public List CraftList { get; set; } + /// + /// 物料信息 + /// + public List MaterialList { get; set; } + } + + + +} diff --git a/backend/BPA.MES.Base.Application/Services/WorkInfoService/Dtos/WorkInfoItemDto.cs b/backend/BPA.MES.Base.Application/Services/WorkInfoService/Dtos/WorkInfoItemDto.cs new file mode 100644 index 0000000..516d1a8 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/WorkInfoService/Dtos/WorkInfoItemDto.cs @@ -0,0 +1,71 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :工单产量 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/7/20 14:29:25 + /// 描 述 : + /// + public class WorkInfoItemDto + { + /// + /// 工单名称 + /// + public string Name { get; set; } + /// + /// 产量 + /// + public string Number { get; set; } + } + /// + /// 增加 + /// + public class WorkInfoItemAddInput : WorkInfoItemDto + { + + } + /// + /// 更新 + /// + public class WorkInfoItemUpdateInput : WorkInfoItemDto + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 删除 + /// + public class WorkInfoItemDelInput + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 分页 + /// + public class WorkInfoItemQueryPageInput : RequestPage + { + /// + /// 名称 + /// + public string Name { get; set; } + /// + /// 编码 + /// + public string Code { get; set; } + } + /// + /// 输出 + /// + public class WorkInfoItemOutput : WorkInfoItemDto + { + /// + /// 主键 + /// + public string Id { get; set; } + } +} \ No newline at end of file diff --git a/backend/BPA.MES.Base.Application/Services/WorkInfoService/Dtos/WorkInfoMaterialsRecordDto.cs b/backend/BPA.MES.Base.Application/Services/WorkInfoService/Dtos/WorkInfoMaterialsRecordDto.cs new file mode 100644 index 0000000..6147858 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/WorkInfoService/Dtos/WorkInfoMaterialsRecordDto.cs @@ -0,0 +1,112 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 : + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/8/10 9:48:30 + /// 描 述 : + /// + public class WorkInfoMaterialsRecordDto + { + /// + /// 物料名称 + /// + public string MaterialName { get; set; } + /// + /// 物料id + /// + public string MaterialId { get; set; } + /// + /// 工单id + /// + public string WorkId { get; set; } + /// + /// 重量 + /// + public string Weight { get; set; } + /// + /// 第几锅 + /// + public string PotNum { get; set; } + /// + /// 配方Id + /// + public string RecipeId { get; set; } + /// + /// 配方名称 + /// + public string RecipeName { get; set; } + /// + /// 物料状态 + /// + public EBatchingStatus MaterialStatus { get; set; } + /// + /// 更新时间 + /// + public DateTime? UpdateTime { get; set; } + /// + /// 误差重量 + /// + public string ErrorWeight { get; set; } + } + /// + /// 增加 + /// + public class WorkInfoMaterialsRecordAddInput : WorkInfoMaterialsRecordDto + { + + } + /// + /// 更新 + /// + public class WorkInfoMaterialsRecordUpdateInput + { + /// + /// 工单物料Id + /// + public string WorkMaterialId { get; set; } + /// + /// 状态 + /// + public EBatchingStatus Status { get; set; } + } + /// + /// 删除 + /// + public class WorkInfoMaterialsRecordDelInput + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 分页 + /// + public class WorkInfoMaterialsRecordQueryPageInput : RequestPage + { + + } + /// + /// 输出 + /// + public class WorkInfoMaterialsRecordOutput : WorkInfoMaterialsRecordDto + { + /// + /// 主键 + /// + public string Id { get; set; } + /// + /// 物料类型 + /// + public string MaterialType { get; set; } + /// + /// 物料类型名称 + /// + public string MaterialTypeName { get; set; } + /// + /// 每升重量 + /// + public string WeightPerLiter { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Application/Services/WorkInfoService/Dtos/WorkInfoStatusDto.cs b/backend/BPA.MES.Base.Application/Services/WorkInfoService/Dtos/WorkInfoStatusDto.cs new file mode 100644 index 0000000..9c6a5a4 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/WorkInfoService/Dtos/WorkInfoStatusDto.cs @@ -0,0 +1,130 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :工单状态 + /// 创 建 人 :yangxiao + /// 创建时间 :2023/7/20 14:29:39 + /// 描 述 : + /// + public class WorkInfoStatusDto + { + /// + /// 工单Id + /// + public string WorkId { get; set; } + /// + /// 工单状态 + /// + public WorkOrderStatusEnum Status { get; set; } + /// + /// 创建时间 + /// + public DateTime CreateTime { get; set; } + /// + /// 备注 + /// + + public string Remark { get; set; } + } + /// + /// 增加 + /// + public class WorkInfoStatusAddInput : WorkInfoStatusDto + { + + } + /// + /// 更新 + /// + public class WorkInfoStatusUpdateInput + { + /// + /// 工单Id + /// + public string WorkId { get; set; } + /// + /// 状态 + /// + public WorkOrderStatusEnum Status { get; set; } + /// + /// 备注 + /// + + public string Remark { get; set; } + } + /// + /// 删除 + /// + public class WorkInfoStatusDelInput + { + /// + /// 主键 + /// + public string Id { get; set; } + } + /// + /// 分页 + /// + public class WorkInfoStatusQueryPageInput : RequestPage + { + + } + + /// + /// 批次下发 + /// + public class BatchInput + { + public string BatchId { get; set; } + } + + /// + /// 下发 + /// + public class PublishInput + { + /// + /// 工单ID + /// + public string WorkId { get; set; } + /// + /// 设备ID + /// + public string? DeviceId { get; set; } + } + /// + /// 输出 + /// + public class WorkInfoStatusOutput : WorkInfoStatusDto + { + /// + /// 主键 + /// + public string Id { get; set; } + /// + /// 状态名称 + /// + public string StatusName { get { + + switch (Status) + { + case WorkOrderStatusEnum.Unkown: + return "未知"; + case WorkOrderStatusEnum.Draft: + return "草稿"; + case WorkOrderStatusEnum.Issued: + return "已下发"; + case WorkOrderStatusEnum.Receive: + return "已接受"; + case WorkOrderStatusEnum.Started: + return "已启动"; + case WorkOrderStatusEnum.Completed: + return "已完成"; + case WorkOrderStatusEnum.Obsolete: + return "废弃"; + default: + return "错误"; + } + } } + } +} diff --git a/backend/BPA.MES.Base.Application/Services/WorkInfoService/Services/IWorkBatchService.cs b/backend/BPA.MES.Base.Application/Services/WorkInfoService/Services/IWorkBatchService.cs new file mode 100644 index 0000000..0933a6d --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/WorkInfoService/Services/IWorkBatchService.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 : + /// 创 建 人 :yangxiao + /// 创建时间 : 2024/4/8 15:41:42 + /// 描 述 : + /// + public interface IWorkBatchService + { + /// + /// 增加 + /// + /// + Task Add(WorkBatchAddInput input); + /// + /// 移除 + /// + /// + Task Del(WorkBatchDelInput input); + /// + /// 更新 + /// + /// + Task Update(WorkBatchUpdateInput input); + /// + /// 不分页列表 + /// + /// + Task> List(WorkBatchQueryInput input); + /// + /// 分页列表 + /// + /// + Task> PagedList(WorkBatchQueryPageInput input); + } +} diff --git a/backend/BPA.MES.Base.Application/Services/WorkInfoService/Services/IWorkInfoService.cs b/backend/BPA.MES.Base.Application/Services/WorkInfoService/Services/IWorkInfoService.cs new file mode 100644 index 0000000..4fbedd3 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/WorkInfoService/Services/IWorkInfoService.cs @@ -0,0 +1,90 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :工单服务 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/7/20 14:39:28 + /// 描 述 : + /// + public interface IWorkInfoService + { + /// + /// 增加 + /// + /// + Task Add(WorkInfoAddInput input); + /// + /// 移除 + /// + /// + Task Del(WorkInfoDelInput input); + /// + /// 更新 + /// + /// + Task Update(WorkInfoUpdateInput input); + /// + /// 不分页列表 + /// + /// + Task> List(WorkInfoQueryInput input); + /// + /// 分页列表 + /// + /// + Task> PagedList(WorkInfoQueryPageInput input); + /// + /// 下拉列表 + /// + /// + Task SelectList(); + /// + /// 查询单条 + /// + /// + /// + Task Detail(string Id); + /// + /// 更改状态 + /// + /// + Task UpdateStatus(WorkInfoStatusUpdateInput input); + + /// + /// 工单下发 + /// + /// 工单Id + /// + Task Publish(PublishInput input); + /// + /// 批次工单下发 + /// + /// + /// + Task Publishs(BatchInput input); + /// + /// 强制结束 + /// + /// 工单Id + /// + Task ForcedEnd(string workId); + /// + /// 工单状态记录 + /// + /// + /// + Task> StatusList(string workId); + /// + /// 修改工单步骤状态 + /// + /// + /// + Task UpdateWorkCraftStepsStatus(WorkInfoCraftstepRecordUpdateInput input); + /// + /// 修改工单物料状态 + /// + /// + /// + Task UpdateWorkMaterialStatus(WorkInfoMaterialsRecordUpdateInput input); + } +} diff --git a/backend/BPA.MES.Base.Application/Services/WorkInfoService/Services/IWorkInfoStatusService.cs b/backend/BPA.MES.Base.Application/Services/WorkInfoService/Services/IWorkInfoStatusService.cs new file mode 100644 index 0000000..4eb624f --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/WorkInfoService/Services/IWorkInfoStatusService.cs @@ -0,0 +1,13 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 : + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/7/21 14:54:31 + /// 描 述 : + /// + public class IWorkInfoStatusService + { + + } +} diff --git a/backend/BPA.MES.Base.Application/Services/WorkInfoService/Services/WorkBatchService.cs b/backend/BPA.MES.Base.Application/Services/WorkInfoService/Services/WorkBatchService.cs new file mode 100644 index 0000000..cfec498 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/WorkInfoService/Services/WorkBatchService.cs @@ -0,0 +1,81 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 :工单服务 + /// 创 建 人 :yangxiao + /// 创建时间 :2023/7/20 14:39:41 + /// 描 述 : + /// + [ApiDescriptionSettings("工单批次服务", Order = 0, Tag = "工单服务", Name = "WorkBatch", KeepName = true, SplitCamelCase = true, KeepVerb = true)] + public class WorkBatchService : IWorkBatchService, ITransient, IDynamicApiController + { + private readonly ISqlSugarClient _dbContext; + private readonly IMQTTService _MQTTService; + private readonly IWorkInfoService _workInfoService; + public WorkBatchService(ISqlSugarClient db, IMQTTService MQTTService, IWorkInfoService WorkInfoService) + { + _dbContext = db; + _MQTTService = MQTTService; + _workInfoService = WorkInfoService; + } + public async Task Add(WorkBatchAddInput input) + { + WorkBatchEntity entity = input.Adapt(); + entity.Status = WorkOrderStatusEnum.Draft; + return await _dbContext.Insertable(entity).IgnoreColumns(ignoreNullColumn: true).ExecuteCommandIdentityIntoEntityAsync(); + } + + public async Task Del(WorkBatchDelInput input) + { + var res = false; + try + { + _dbContext.Ado.BeginTran(); + await _dbContext.Deleteable().Where(x => x.Id == input.Id).ExecuteCommandHasChangeAsync(); + await _dbContext.Deleteable().Where(x => x.BatchId == input.Id).ExecuteCommandAsync(); + _dbContext.Ado.CommitTran(); + res = true; + } + catch (Exception) + { + _dbContext.Ado.RollbackTran(); + } + return res; + } + + public async Task> List(WorkBatchQueryInput input) + { + var entity = await _dbContext.Queryable().ToListAsync(); + List output = entity.Adapt>(); + return output; + } + + public async Task> PagedList(WorkBatchQueryPageInput input) + { + var entity = await _dbContext.Queryable() + .WhereIF(!string.IsNullOrEmpty(input.Id),x=>x.Id.Contains(input.Id)) + .WhereIF(input.StartTime != null, x => input.StartTime <= Convert.ToDateTime(x.CreateTime)) + .WhereIF(input.EndTime != null, x => input.EndTime.Value.AddHours(23).AddMinutes(59).AddSeconds(59) >= Convert.ToDateTime(x.CreateTime)) + .OrderByDescending(x => x.CreateTime) + .Select((x)=>new WorkBatchOutput + { + Id = x.Id.SelectAll(), + Count = SqlFunc.Subqueryable().Where(d=>d.BatchId==x.Id).Count() + }) + .ToPagedListAsync(input.PageIndex, input.PageSize); + foreach (var item in entity.Items) + { + item.WorkList = await _workInfoService.List(new WorkInfoQueryInput { BatchId = item.Id }); + } + return entity; + } + + public async Task Update(WorkBatchUpdateInput input) + { + var entity = await _dbContext.Queryable().Where(x => x.Id == input.Id).FirstAsync(); + entity = input.Adapt(); + var res = await _dbContext.Updateable(entity).IgnoreColumns(true).ExecuteCommandHasChangeAsync(); + return res; + } + } +} diff --git a/backend/BPA.MES.Base.Application/Services/WorkInfoService/Services/WorkInfoService.cs b/backend/BPA.MES.Base.Application/Services/WorkInfoService/Services/WorkInfoService.cs new file mode 100644 index 0000000..da77b4e --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/WorkInfoService/Services/WorkInfoService.cs @@ -0,0 +1,670 @@ +using Furion.EventBus; +using Yitter.IdGenerator; + +namespace BPA.MES.Base.Application.Services.WorkInfoService.Services +{ + /// + /// 名 称 :工单服务 + /// 创 建 人 :yangxiao + /// 创建时间 :2023/7/20 14:39:41 + /// 描 述 : + /// + [ApiDescriptionSettings("工单服务", Order = 0, Tag = "工单服务", Name = "WorkInfo", KeepName = true, SplitCamelCase = true, KeepVerb = true)] + public class WorkInfoService : IWorkInfoService, ITransient, IDynamicApiController + { + private readonly ISqlSugarClient _dbContext; + private readonly IMQTTService _MQTTService; + public WorkInfoService(ISqlSugarClient db, IEventPublisher eventPublisher, IMQTTService MQTTService) + { + _dbContext = db; + _MQTTService = MQTTService; + } + /// + /// 增加 + /// + /// + /// + [HttpPost, OperLog("增加工单")] + public async Task Add(WorkInfoAddInput input) + { + bool result = false; + Pztj_WorkInfoEntity entity = input.Adapt(); + try + { + _dbContext.Ado.BeginTran(); + await _dbContext.Insertable(entity).IgnoreColumns(ignoreNullColumn: true).ExecuteCommandAsync(); + Pztj_WorkInfoStatusEntity pztj_WorkInfoStatusEntity = new() + { + Status = WorkOrderStatusEnum.Draft, + WorkId = entity.Id + }; + await _dbContext.Insertable(pztj_WorkInfoStatusEntity).IgnoreColumns(true).ExecuteCommandAsync(); + _dbContext.Ado.CommitTran(); + result = true; + } + catch + { + _dbContext.Ado.RollbackTran(); + throw Oops.Bah("添加失败!"); + } + return result; + } + /// + /// 删除 + /// + /// + /// + /// + [HttpPost] + public async Task Del(WorkInfoDelInput input) + { + var res = await _dbContext.Deleteable().Where(x => x.Id == input.Id).ExecuteCommandHasChangeAsync(); + return res; + } + /// + /// 详情 + /// + /// + /// + /// + [HttpGet] + public async Task Detail(string Id) + { + var entity = await _dbContext.Queryable() + .LeftJoin((a, b) => a.FinalId == b.Id) + .LeftJoin((a, b, c) => a.LineId == c.Id) + .LeftJoin((a, b, c, d) => d.Id == SqlFunc.Subqueryable().Where(s => s.WorkId == a.Id).OrderByDesc(s => s.CreateTime).Select(s => s.Id)) + .LeftJoin((a,b,c,d,e)=>a.DeviceId==e.Id) + .Where((a, b, c, d) => a.Id == Id) + .Select((a, b, c, d, e) => new WorkInfoDetailOutput + { + Id = a.Id.SelectAll(), + DeviceCode = e.Code, + DeviceName=e.Name, + DeviceId = e.Id, + FinalName = b.Name, + LineName = c.Name, + Status = d.Status == null ? WorkOrderStatusEnum.Draft : d.Status + }).FirstAsync(); + if (entity == null) + { + throw Oops.Bah("没有找到工单信息!"); + } + //获取成品信息 + var finainfo = await _dbContext.Queryable().FirstAsync(x => x.Id == entity.FinalId); + if (finainfo == null) + { + throw Oops.Bah("没有找到成品信息!"); + } + //获取工艺步骤 + var craftlist = await _dbContext.Queryable().Where(x => x.WorkId == Id).ToListAsync(); + //获取物料信息 + var materiallist = await _dbContext.Queryable() + .LeftJoin((a,b)=>a.MaterialId==b.Id) + .LeftJoin((a,b,c) => b.Type == c.Id) + .Where((a, b) => a.WorkId == Id) + .Select((a, b,c) => + new WorkInfoMaterialsRecordOutput + { + Id = a.Id.SelectAll(), + MaterialType = c.Id, + MaterialTypeName = c.Value, + WeightPerLiter = b.WeightPerLiter + }) + .ToListAsync(); + entity.CraftList = craftlist; + entity.MaterialList = materiallist; + if (craftlist.Max(x => x.Status) == RecipeStatus.执行完成 && craftlist.Max(x => x.Status) == craftlist.Min(x => x.Status)) + { + entity.CraftStatus = RecipeStatus.执行完成; + } + else + if (craftlist.Max(x => x.Status) == RecipeStatus.等待执行 && craftlist.Max(x => x.Status) == craftlist.Min(x => x.Status)) + { + entity.CraftStatus = RecipeStatus.等待执行; + } + else + { + entity.CraftStatus = RecipeStatus.正在执行; + } + + if (materiallist.Max(x => x.MaterialStatus) == EBatchingStatus.配料完成 && materiallist.Max(x => x.MaterialStatus) == materiallist.Min(x => x.MaterialStatus)) + { + entity.MaterialStatus = EBatchingStatus.配料完成; + } + else + if (materiallist.Max(x => x.MaterialStatus) == EBatchingStatus.等待配料 && materiallist.Max(x => x.MaterialStatus) == materiallist.Min(x => x.MaterialStatus)) + { + entity.MaterialStatus = EBatchingStatus.等待配料; + } + else + { + entity.MaterialStatus = EBatchingStatus.正在配料; + } + return entity; + } + /// + /// 列表 + /// + /// + /// + [HttpPost] + public async Task> List(WorkInfoQueryInput input) + { + var entity = await _dbContext.Queryable() + .LeftJoin((a, b) => a.FinalId == b.Id) + .LeftJoin((a, b, c) => a.LineId == c.Id) + .LeftJoin((a, b, c, d) =>a.DeviceId==d.Id) + .WhereIF(!string.IsNullOrEmpty(input.Name), (a, b, c, d) => b.Name.Contains(input.Name)) + .WhereIF(!string.IsNullOrEmpty(input.Id), (a, b, c, d) => a.Id.Contains(input.Id)) + .WhereIF(!string.IsNullOrEmpty(input.BatchId), (a, b, c, d) => a.BatchId == input.BatchId) + .WhereIF(input.Status != null, (a, b, c, d) => input.Status.Contains(a.Status)) + .WhereIF(input.StartTime != null, (a, b, c, d) => input.StartTime <= Convert.ToDateTime(a.CreateTime)) + .WhereIF(input.EndTime != null, (a, b, c, d) => input.EndTime.Value.AddHours(23).AddMinutes(59).AddSeconds(59) >= Convert.ToDateTime(a.CreateTime)) + .OrderByDescending((a, b, c, d) => a.CreateTime) + .Select((a, b, c, d) => new WorkInfoOutput + { + Id = a.Id, + FinalName = b.Name, + LineName = c.Name, + DeviceId = a.DeviceId == null ? "" : a.DeviceId, + DeviceName =d.Name, + Status = a.Status == null ? WorkOrderStatusEnum.Draft : a.Status, + BatchId = a.BatchId, + Number = a.Number, + FinalId = a.FinalId, + LineId = a.LineId, + DeviceCode = a.DeviceId + }).ToListAsync(); + return entity; + } + /// + /// 分页 + /// + /// + /// + [HttpPost] + public async Task> PagedList(WorkInfoQueryPageInput input) + { + var entity = await _dbContext.Queryable() + .LeftJoin((a, b) => a.FinalId == b.Id) + .LeftJoin((a, b, c) => a.LineId == c.Id) + .WhereIF(!string.IsNullOrEmpty(input.Name), (a, b, c) => b.Name.Contains(input.Name)) + .WhereIF(!string.IsNullOrEmpty(input.Id), (a, b, c) => a.Id.Contains(input.Id)) + .WhereIF(!string.IsNullOrEmpty(input.BatchId), (a, b, c) => a.BatchId==input.BatchId) + .WhereIF(input.Status != null, (a, b, c) => input.Status.Contains(a.Status)) + .WhereIF(input.StartTime != null, (a, b, c) => input.StartTime <= Convert.ToDateTime(a.CreateTime)) + .WhereIF(input.EndTime != null, (a, b, c) => input.EndTime.Value.AddHours(23).AddMinutes(59).AddSeconds(59) >= Convert.ToDateTime(a.CreateTime)) + .OrderByDescending((a, b, c) => a.CreateTime) + .Select((a, b, c) => new WorkInfoOutput + { + Id = a.Id.SelectAll(), + FinalName = b.Name, + LineName = c.Name, + DeviceId = a.DeviceId ?? "", + Status = a.Status == null ? WorkOrderStatusEnum.Draft : a.Status + }) + .ToPagedListAsync(input.PageIndex, input.PageSize); + return entity; + } + /// + /// 分页 + /// + /// + /// + [HttpPost] + public async Task> BatchPagedList(WorkInfoQueryPageInput input) + { + var entity = await _dbContext.Queryable() + .LeftJoin((a, b) => a.FinalId == b.Id) + .LeftJoin((a, b, c) => a.LineId == c.Id) + .WhereIF(!string.IsNullOrEmpty(input.Name), (a, b, c) => b.Name.Contains(input.Name)) + .WhereIF(!string.IsNullOrEmpty(input.Id), (a, b, c) => a.Id.Contains(input.Id)) + .WhereIF(input.Status != null, (a, b, c) => input.Status.Contains(a.Status)) + .WhereIF(input.StartTime != null, (a, b, c) => input.StartTime <= Convert.ToDateTime(a.CreateTime)) + .WhereIF(input.EndTime != null, (a, b, c) => input.EndTime.Value.AddHours(23).AddMinutes(59).AddSeconds(59) >= Convert.ToDateTime(a.CreateTime)) + .OrderByDescending((a, b, c) => a.CreateTime) + .Select((a, b, c) => new WorkInfoOutput + { + Id = a.Id.SelectAll(), + FinalName = b.Name, + LineName = c.Name, + Status = a.Status == null ? WorkOrderStatusEnum.Draft : a.Status + }) + .ToPagedListAsync(input.PageIndex, input.PageSize); + return entity; + } + + /// + /// 工单下发 + /// + /// 工单id + /// + /// + [HttpPost] + public async Task Publishs(BatchInput input) + { + string userId = App.User?.FindFirst(ClaimConst.CLAINM_USERID)?.Value; + string userName = App.User?.FindFirst(ClaimConst.CLAINM_NAME)?.Value; + var workentitys = await _dbContext.Queryable().Where(x => x.BatchId == input.BatchId).ToListAsync(); + + foreach (var item in workentitys) + { + var res = await UpdateStatus( + new WorkInfoStatusUpdateInput + { + WorkId = item.Id, + Status = WorkOrderStatusEnum.Issued, + Remark = $"[{userId}]{userName}" + }); + var workentity = await _dbContext.Queryable() + .LeftJoin((a, b) => a.DeviceId == b.Id) + .Where((a, b) => a.Id == item.Id) + .Select((a, b) => new WorkInfoOutput + { + Id = a.Id.SelectAll(), + DeviceCode = b.Code, + DeviceName = b.Name + }) + .FirstAsync(); + if (res) + { + WorkInfoMaterialsRecordEntity workInfoMaterialsRecordEntity = new() + { + MaterialId = item.Id, + }; + //获取成品信息 + var finainfo = await _dbContext.Queryable().FirstAsync(x => x.Id == workentity.FinalId); + if (finainfo == null) + { + throw Oops.Bah("没有找到成品信息!"); + } + + var materiallist = await _dbContext.Queryable() + .LeftJoin((a, b) => a.MaterialId == b.Id) + .LeftJoin((a, b, c) => a.RecipesId == c.Id) + .Where((a, b, c) => a.RecipesId == finainfo.RecipeId) + .Select((a, b, c) => new WorkInfoMaterialsRecordEntity + { + MaterialId = a.MaterialId, + MaterialName = b.Name, + MaterialStatus = EBatchingStatus.等待配料, + WorkId = item.Id, + Weight = a.Weight, + RecipeId = a.RecipesId, + RecipeName = c.Name + }) + .ToListAsync(); + + //获取物料信息 + + var craftsteplist = await _dbContext.Queryable() + .LeftJoin((a, b) => a.CraftId == b.Id) + .LeftJoin((a, b, c) => a.DeviceProductFunctionId == c.Id) + .Where((a, b) => a.CraftId == finainfo.CraftId) + .Select((a, b, c) => new WorkInfoCraftstepRecordEntity + { + CraftId = a.CraftId, + CraftName = b.Name, + CraftstepId = a.Id, + DeviceProductFunctionId = c.Id, + DeviceProductFunctionName = c.Name, + CraftstepParms = a.Params, + Status = RecipeStatus.等待执行, + Step = a.Step, + WorkId = item.Id + }) + .ToListAsync(); + List newmateriallist = new(); + List newcraftslist = new(); + for (int i = 1; i <= Convert.ToInt32(workentity.Number); i++) + { + foreach (var materiaItem in materiallist) + { + WorkInfoMaterialsRecordEntity itementity = new() + { + PotNum = i.ToString(), + MaterialId = materiaItem.MaterialId, + MaterialName = materiaItem.MaterialName, + MaterialStatus = materiaItem.MaterialStatus, + WorkId = materiaItem.WorkId, + Weight = materiaItem.Weight, + RecipeId = materiaItem.RecipeId, + RecipeName = materiaItem.RecipeName, + }; + newmateriallist.Add(itementity); + } + foreach (var craftstepitem in craftsteplist) + { + WorkInfoCraftstepRecordEntity itementity = new() + { + CraftId = craftstepitem.CraftId, + CraftName = craftstepitem.CraftName, + CraftstepId = craftstepitem.CraftstepId, + DeviceProductFunctionId = craftstepitem.DeviceProductFunctionId, + DeviceProductFunctionName = craftstepitem.DeviceProductFunctionName, + CraftstepParms = craftstepitem.CraftstepParms, + Status = craftstepitem.Status, + Step = craftstepitem.Step, + WorkId = craftstepitem.WorkId, + PotNum = i.ToString(), + }; + newcraftslist.Add(itementity); + } + } + try + { + _dbContext.Ado.BeginTran(); + await _dbContext.Deleteable().Where(x => x.WorkId == item.Id).ExecuteCommandAsync(); + await _dbContext.Deleteable().Where(x => x.WorkId == item.Id).ExecuteCommandAsync(); + + await _dbContext.Insertable(newcraftslist).ExecuteCommandAsync(); + await _dbContext.Insertable(newmateriallist).ExecuteCommandAsync(); + _dbContext.Ado.CommitTran(); + } + catch (Exception ex) + { + _dbContext.Ado.RollbackTran(); + throw Oops.Oh("下发失败!"); + } + await _MQTTService.MqttPublish(new MqttPublishDto() { Payload = workentity, Topic = Topics.WorkOrderPush, MessageId = MessageID.WorkOrderIssued }); + } + } + await _dbContext.Updateable().SetColumns(x => x.Status == WorkOrderStatusEnum.Issued).Where(x => x.Id == input.BatchId).ExecuteCommandAsync(); + return true; + } + + /// + /// 工单下发 + /// + /// 工单id + /// + /// + [HttpPost] + public async Task Publish(PublishInput input) + { + string userId = App.User?.FindFirst(ClaimConst.CLAINM_USERID)?.Value; + string userName = App.User?.FindFirst(ClaimConst.CLAINM_NAME)?.Value; + if (!string.IsNullOrEmpty(input.DeviceId)) + { + await _dbContext.Updateable().SetColumns(x => x.DeviceId == input.DeviceId).Where(x => x.Id == input.WorkId).ExecuteCommandAsync(); + } + var res = await UpdateStatus( + new WorkInfoStatusUpdateInput + { + WorkId = input.WorkId, + Status = WorkOrderStatusEnum.Issued, + Remark = $"[{userId}]{userName}" + }); + var workentity = await _dbContext.Queryable() + .LeftJoin((a,b)=>a.DeviceId==b.Id) + .Where((a, b) => a.Id == input.WorkId) + .Select((a,b)=>new WorkInfoOutput + { + Id=a.Id.SelectAll(), + DeviceCode = b.Code, + DeviceName = b.Name + }) + .FirstAsync(); + if (res) + { + WorkInfoMaterialsRecordEntity workInfoMaterialsRecordEntity = new() + { + MaterialId = input.WorkId, + }; + //获取成品信息 + var finainfo = await _dbContext.Queryable().FirstAsync(x => x.Id == workentity.FinalId); + if (finainfo == null) + { + throw Oops.Bah("没有找到成品信息!"); + } + + var materiallist = await _dbContext.Queryable() + .LeftJoin((a, b) => a.MaterialId == b.Id) + .LeftJoin((a,b,c)=>a.RecipesId==c.Id) + .Where((a, b, c) => a.RecipesId == finainfo.RecipeId) + .Select((a, b, c) => new WorkInfoMaterialsRecordEntity + { + MaterialId = a.MaterialId, + MaterialName = b.Name, + MaterialStatus = EBatchingStatus.等待配料, + WorkId = input.WorkId, + Weight = a.Weight, + RecipeId = a.RecipesId, + RecipeName = c.Name, + ErrorWeight = a.ErrorWeight, + }) + .ToListAsync(); + + //获取物料信息 + + var craftsteplist = await _dbContext.Queryable() + .LeftJoin((a, b) => a.CraftId == b.Id) + .LeftJoin((a, b, c) => a.DeviceProductFunctionId == c.Id) + .Where((a, b) => a.CraftId == finainfo.CraftId) + .Select((a, b, c) => new WorkInfoCraftstepRecordEntity + { + CraftId = a.CraftId, + CraftName = b.Name, + CraftstepId = a.Id, + DeviceProductFunctionId = c.Id, + DeviceProductFunctionName = c.Name, + CraftstepParms = a.Params, + Status = RecipeStatus.等待执行, + Step = a.Step, + WorkId = input.WorkId + }) + .ToListAsync(); + List newmateriallist = new(); + List newcraftslist = new(); + for (int i = 1; i <= Convert.ToInt32(workentity.Number); i++) + { + foreach (var item in materiallist) + { + WorkInfoMaterialsRecordEntity itementity = new() + { + PotNum = i.ToString(), + MaterialId = item.MaterialId, + MaterialName = item.MaterialName, + MaterialStatus = item.MaterialStatus, + WorkId = item.WorkId, + Weight = item.Weight, + RecipeId = item.RecipeId, + RecipeName = item.RecipeName, + ErrorWeight = item.ErrorWeight + }; + newmateriallist.Add(itementity); + } + foreach (var item in craftsteplist) + { + WorkInfoCraftstepRecordEntity itementity = new() + { + CraftId = item.CraftId, + CraftName = item.CraftName, + CraftstepId = item.CraftstepId, + DeviceProductFunctionId = item.DeviceProductFunctionId, + DeviceProductFunctionName = item.DeviceProductFunctionName, + CraftstepParms = item.CraftstepParms, + Status = item.Status, + Step = item.Step, + WorkId = item.WorkId, + PotNum = i.ToString(), + }; + newcraftslist.Add(itementity); + } + } + try + { + _dbContext.Ado.BeginTran(); + await _dbContext.Deleteable().Where(x => x.WorkId == input.WorkId).ExecuteCommandAsync(); + await _dbContext.Deleteable().Where(x => x.WorkId == input.WorkId).ExecuteCommandAsync(); + + await _dbContext.Insertable(newcraftslist).ExecuteCommandAsync(); + await _dbContext.Insertable(newmateriallist).ExecuteCommandAsync(); + _dbContext.Ado.CommitTran(); + } + catch (Exception ex) + { + _dbContext.Ado.RollbackTran(); + throw Oops.Oh("下发失败!"); + } + await _MQTTService.MqttPublish(new MqttPublishDto() { Payload = workentity, Topic = Topics.WorkOrderPush, MessageId = MessageID.WorkOrderIssued }); + } + return true; + } + /// + /// 下拉 + /// + /// + /// + [HttpGet] + public async Task SelectList() + { + var entity = await _dbContext.Queryable().Select(x => new + { + key = x.Id, + value = x.Name + }).ToListAsync(); + return entity; + } + /// + /// 更新 + /// + /// + /// + /// + [HttpPost] + public async Task Update(WorkInfoUpdateInput input) + { + Pztj_WorkInfoEntity entity = input.Adapt(); + entity.CreateTime = DateTime.Now; + var res = await _dbContext.Updateable(entity).IgnoreColumns(true).ExecuteCommandHasChangeAsync(); + return res; + } + /// + /// 修改工单状态 + /// + /// + /// + /// + [HttpPost] + public async Task UpdateStatus(WorkInfoStatusUpdateInput input) + { + var entitys = await _dbContext.Queryable().Where(x => x.Id == input.WorkId) + .FirstAsync(); + Pztj_WorkInfoStatusEntity entity = input.Adapt(); + try + { + _dbContext.Ado.BeginTran(); + await _dbContext.Insertable(entity).IgnoreColumns(true).ExecuteCommandIdentityIntoEntityAsync(); + await _dbContext.Updateable().SetColumns(x => x.Status == input.Status).Where(x => x.Id == input.WorkId).ExecuteCommandAsync(); + _dbContext.Ado.CommitTran(); + } + catch (Exception ex) + { + _dbContext.Ado.RollbackTran(); + throw Oops.Bah("更新失败"); + } + var workItems = await _dbContext.Queryable().LeftJoin((a, b) => a.Id == b.WorkId).Where(a => a.BatchId == entitys.BatchId) + .Select((a, b) => new WorkInfoOutput + { + Id = a.Id.SelectAll(), + Status = b.Status, + }) + .ToListAsync(); + if (workItems.Max(x => x.Status) == WorkOrderStatusEnum.Completed && workItems.Min(x => x.Status) == WorkOrderStatusEnum.Completed) + { + await _dbContext.Updateable().SetColumns(x => x.Status == WorkOrderStatusEnum.Completed).Where(x => x.Id == entitys.BatchId).ExecuteCommandAsync(); + } + else + { + await _dbContext.Updateable().SetColumns(x => x.Status == workItems.Max(x => x.Status)).Where(x => x.Id == entitys.BatchId).ExecuteCommandAsync(); + } + return true; + } + /// + /// 修改工单物料状态 + /// + /// + /// + [HttpPost] + public async Task UpdateWorkMaterialStatus(WorkInfoMaterialsRecordUpdateInput input) + { + WorkInfoMaterialsRecordEntity entity = new() + { + Id = input.WorkMaterialId, + MaterialStatus = input.Status, + UpdateTime = DateTime.Now + }; + bool res = await _dbContext.Updateable(entity).IgnoreColumns(true).ExecuteCommandHasChangeAsync(); + return res; + } + /// + /// 修改工单步骤状态 + /// + /// + /// + [HttpPost] + public async Task UpdateWorkCraftStepsStatus(WorkInfoCraftstepRecordUpdateInput input) + { + + + var entityFrist = await _dbContext.Queryable().Where(x => x.Id == input.WorkCraftstepId).FirstAsync(); + if (entityFrist==null) + { + throw Oops.Bah("未查询到工单信息!"); + } + if (!string.IsNullOrEmpty(input.WorkId)) + { + bool res = await _dbContext.Updateable() + .SetColumns(x => x.Status == input.Status) + .SetColumns(x => x.UpdateTime == DateTime.Now).IgnoreColumns(true).Where(x => x.WorkId == input.WorkId && x.PotNum == input.PotNum).ExecuteCommandHasChangeAsync(); + return res; + } + else + { + WorkInfoCraftstepRecordEntity entity = new() + { + Id = input.WorkCraftstepId, + Status = input.Status, + UpdateTime = DateTime.Now, + Step = entityFrist.Step + }; + bool res = await _dbContext.Updateable(entity).IgnoreColumns(true).ExecuteCommandHasChangeAsync(); + return res; + } + } + + /// + /// 强制结束工单 + /// + /// + /// + [HttpPost] + public async Task ForcedEnd(string workId) + { + string userId = App.User?.FindFirst(ClaimConst.CLAINM_USERID)?.Value; + string userName = App.User?.FindFirst(ClaimConst.CLAINM_NAME)?.Value; + await UpdateStatus(new WorkInfoStatusUpdateInput + { + WorkId = workId, + Status = WorkOrderStatusEnum.Completed, + Remark = $"{userName}[{userId}]点击了强制结束" + }); + return true; + } + /// + /// 工单状态变更记录 + /// + /// + /// + [HttpGet] + public async Task> StatusList(string workId) + { + var entitys = await _dbContext.Queryable().Where(x => x.WorkId == workId).OrderByDescending(x=>x.CreateTime).ToListAsync(); + List list = entitys.Adapt>(); + + return list; + } + } +} diff --git a/backend/BPA.MES.Base.Application/Services/WorkInfoService/Services/WorkInfoStatusService.cs b/backend/BPA.MES.Base.Application/Services/WorkInfoService/Services/WorkInfoStatusService.cs new file mode 100644 index 0000000..4178e27 --- /dev/null +++ b/backend/BPA.MES.Base.Application/Services/WorkInfoService/Services/WorkInfoStatusService.cs @@ -0,0 +1,12 @@ +namespace BPA.MES.Base.Application.Services +{ + /// + /// 名 称 : + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/7/21 14:54:42 + /// 描 述 : + /// + public class WorkInfoStatusService + { + } +} diff --git a/backend/BPA.MES.Base.Application/Subscriber/ToDoEventSubscriber.cs b/backend/BPA.MES.Base.Application/Subscriber/ToDoEventSubscriber.cs new file mode 100644 index 0000000..4b4d8fd --- /dev/null +++ b/backend/BPA.MES.Base.Application/Subscriber/ToDoEventSubscriber.cs @@ -0,0 +1,28 @@ +using Furion.EventBus; + +namespace BPA.MES.Base.Application.Subscriber +{ + /// + /// 名 称 : + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/7/20 15:09:49 + /// 描 述 : + /// + public class ToDoEventSubscriber : IEventSubscriber + { + private readonly ISqlSugarClient _dbContext; + public ToDoEventSubscriber(ISqlSugarClient db) + { + _dbContext = db; + } + + [EventSubscribe("ToDo:OperLog")] + public async Task CreateToDo(EventHandlerExecutingContext context) + { + var todo = context.Source; + OperLogEntity entity =(OperLogEntity)todo.Payload; + await _dbContext.Insertable(entity).ExecuteCommandAsync(); + await Task.CompletedTask; + } + } +} diff --git a/backend/BPA.MES.Base.Application/applicationsettings.json b/backend/BPA.MES.Base.Application/applicationsettings.json new file mode 100644 index 0000000..56080bc --- /dev/null +++ b/backend/BPA.MES.Base.Application/applicationsettings.json @@ -0,0 +1,12 @@ +{ + "SpecificationDocumentSettings": { + "DocumentTitle": "MES数据接口" + }, + "CorsAccessorSettings": { + "WithExposedHeaders": [ + "access-token", + "x-access-token", + "environment" + ] + } +} \ No newline at end of file diff --git a/backend/BPA.MES.Base.Core/BPA.MES.Base.Core.csproj b/backend/BPA.MES.Base.Core/BPA.MES.Base.Core.csproj new file mode 100644 index 0000000..c91d436 --- /dev/null +++ b/backend/BPA.MES.Base.Core/BPA.MES.Base.Core.csproj @@ -0,0 +1,26 @@ + + + + + net6.0 + 1701;1702;1591 + BPA.MES.Base.Core.xml + + + + + + + + + + + + + + + + + + + diff --git a/backend/BPA.MES.Base.Core/BPA.MES.Base.Core.xml b/backend/BPA.MES.Base.Core/BPA.MES.Base.Core.xml new file mode 100644 index 0000000..5776893 --- /dev/null +++ b/backend/BPA.MES.Base.Core/BPA.MES.Base.Core.xml @@ -0,0 +1,136 @@ + + + + BPA.MES.Base.Core + + + + + 名 称 :主键 + 创 建 人 :yangxiao + 创建时间 :2023/3/2 13:59:33 + 描 述 : + + + + + 主键 + + + + + 名 称 : + 创 建 人 :yangxiao + 创建时间 : 2023/3/4 9:51:33 + 描 述 : + + + + + 获基础信息库对象 (用IOC这块代码不能写到IOC里面) + + + + + 名 称 :分页基础类 + 创 建 人 :yangxiao + 创建时间 : 2023/3/2 16:15:41 + 描 述 : + + + + + 页码 + + 1 + + + + 页大小 + + 10 + + + + 名 称 :分页泛型集合 + 创 建 人 :yangxiao + 创建时间 : 2023/3/2 16:21:27 + 描 述 : + + + + + 页码 + + + + + 页容量 + + + + + 总条数 + + + + + 总页数 + + + + + 当前页集合 + + + + + 是否有上一页 + + + + + 是否有下一页 + + + + + 分页拓展类 + + + + + 分页拓展 + + + + + + + + + 分页拓展 + + + + + + + + + 名 称 :数据库启动类 + 创 建 人 :yangxiao + 创建时间 : 2023/3/23 14:09:30 + 描 述 : + + + + + 名 称 : + 创 建 人 :yangxiao + 创建时间 : 2023/3/4 9:50:52 + 描 述 : + + + + diff --git a/backend/BPA.MES.Base.Core/DEntityBase.cs b/backend/BPA.MES.Base.Core/DEntityBase.cs new file mode 100644 index 0000000..39a7fb6 --- /dev/null +++ b/backend/BPA.MES.Base.Core/DEntityBase.cs @@ -0,0 +1,27 @@ +using SqlSugar; +using System.ComponentModel; +using Yitter.IdGenerator; + +namespace BPA.MES.Base.Core +{ + /// + /// 名 称 :主键 + /// 创 建 人 :yangxiao + /// 创建时间 :2023/3/2 13:59:33 + /// 描 述 : + /// + public class DEntityBase + { + /// + /// 主键 + /// + [Description("主键")] + [SugarColumn(IsPrimaryKey = true)] + public string Id { get; set; } + public DEntityBase() + { + var b = YitIdHelper.NextId(); + Id = b.ToString(); + } + } +} diff --git a/backend/BPA.MES.Base.Core/EmptyExtensions.cs b/backend/BPA.MES.Base.Core/EmptyExtensions.cs new file mode 100644 index 0000000..fe0750a --- /dev/null +++ b/backend/BPA.MES.Base.Core/EmptyExtensions.cs @@ -0,0 +1,21 @@ +namespace BPA.MES.Base.Core +{ + /// + /// 名 称 : + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/3/4 9:51:33 + /// 描 述 : + /// + public static class EmptyExtensions + { + public static bool HasVal(this T obj) + { + if (obj != null) + { + return !obj.Equals(default(T)); + } + + return false; + } + } +} diff --git a/backend/BPA.MES.Base.Core/KepServerSqlsugar.cs b/backend/BPA.MES.Base.Core/KepServerSqlsugar.cs new file mode 100644 index 0000000..e71d119 --- /dev/null +++ b/backend/BPA.MES.Base.Core/KepServerSqlsugar.cs @@ -0,0 +1,64 @@ +using Furion; +using Microsoft.Extensions.Caching.Distributed; +using Newtonsoft.Json; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BPA.MES.Base.Core +{ + public class KepServerSqlsugar + { + /// + /// 获基础信息库对象 (用IOC这块代码不能写到IOC里面) + /// + public static ISqlSugarClient KepDb + { + get + { + //如果是跨服务器分库,也需要动态配置的,因为库的IP会变 + //参考业务库用法 + string configId = "configId"; + var dbs = App.GetConfig>("ConnectionConfigs")[0]; + if (!Db.IsAnyConnection(configId)) + { //用非默认ConfigId进行测试 + //添加业务库只在当前上下文有效(原理:SqlSugarScope模式入门文档去看) + Db.AddConnection(new ConnectionConfig() + { + ConfigId = configId, + ConnectionString = dbs.ConnectionString, + DbType = DbType.MySql, + IsAutoCloseConnection = true, + InitKeyType = InitKeyType.Attribute + }); + } + //原理说明 + //IsAnyConnection、AddConnection和GetConnection 都是Scope周期不同请求不会有影响 + + var result = Db.GetConnection(configId); + + //可以给业务库result设置AOP和过滤滤器 + + return result; + } + } + + + //通过IOC获取注入的Db对象 + public static SqlSugarScope Db + { + get + { + //如果用Furion就是 App.GetService(); + //IOC不会可以看文档: https://www.donet5.com/Doc/27/2563 + //var ihttp=你存储的Services.BuildServiceProvider().GetService(); + var obj = App.GetService(); + return (SqlSugarScope)obj; + } + } + + } +} diff --git a/backend/BPA.MES.Base.Core/RequestPage.cs b/backend/BPA.MES.Base.Core/RequestPage.cs new file mode 100644 index 0000000..15ea1e6 --- /dev/null +++ b/backend/BPA.MES.Base.Core/RequestPage.cs @@ -0,0 +1,22 @@ +namespace BPA.MES.Base.Core +{ + /// + /// 名 称 :分页基础类 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/3/2 16:15:41 + /// 描 述 : + /// + public class RequestPage + { + /// + /// 页码 + /// + /// 1 + public int PageIndex { get; set; } + /// + /// 页大小 + /// + /// 10 + public int PageSize { get; set; } + } +} diff --git a/backend/BPA.MES.Base.Core/SqlSugarPagedList.cs b/backend/BPA.MES.Base.Core/SqlSugarPagedList.cs new file mode 100644 index 0000000..2f67754 --- /dev/null +++ b/backend/BPA.MES.Base.Core/SqlSugarPagedList.cs @@ -0,0 +1,109 @@ +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace BPA.MES.Base.Core +{ + /// + /// 名 称 :分页泛型集合 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/3/2 16:21:27 + /// 描 述 : + /// + public class SqlSugarPagedList + where TEntity : new() + { + /// + /// 页码 + /// + public int Page { get; set; } + + /// + /// 页容量 + /// + public int PageSize { get; set; } + + /// + /// 总条数 + /// + public int Total { get; set; } + + /// + /// 总页数 + /// + public int TotalPages { get; set; } + + /// + /// 当前页集合 + /// + public IEnumerable Items { get; set; } + + /// + /// 是否有上一页 + /// + public bool HasPrevPage { get; set; } + + /// + /// 是否有下一页 + /// + public bool HasNextPage { get; set; } + } + + /// + /// 分页拓展类 + /// + public static class SqlSugarPagedExtensions + { + /// + /// 分页拓展 + /// + /// + /// + /// + /// + public static SqlSugarPagedList ToPagedList(this ISugarQueryable entity, int pageIndex, int pageSize) + where TEntity : new() + { + var total = 0; + var items = entity.ToPageList(pageIndex, pageSize, ref total); + var totalPages = (int)Math.Ceiling(total / (double)pageSize); + return new SqlSugarPagedList + { + Page = pageIndex, + PageSize = pageSize, + Items = items, + Total = total, + TotalPages = totalPages, + HasNextPage = pageIndex < totalPages, + HasPrevPage = pageIndex - 1 > 0 + }; + } + + /// + /// 分页拓展 + /// + /// + /// + /// + /// + public static async Task> ToPagedListAsync(this ISugarQueryable entity, int pageIndex, int pageSize) + where TEntity : new() + { + RefAsync total = 0; + var items = await entity.ToPageListAsync(pageIndex, pageSize, total); + var totalPages = (int)Math.Ceiling(total / (double)pageSize); + return new SqlSugarPagedList + { + Page = pageIndex, + PageSize = pageSize, + Items = items, + Total = total, + TotalPages = totalPages, + HasNextPage = pageIndex < totalPages, + HasPrevPage = pageIndex - 1 > 0 + }; + } + + } +} \ No newline at end of file diff --git a/backend/BPA.MES.Base.Core/SqlsugarSetup.cs b/backend/BPA.MES.Base.Core/SqlsugarSetup.cs new file mode 100644 index 0000000..35195bd --- /dev/null +++ b/backend/BPA.MES.Base.Core/SqlsugarSetup.cs @@ -0,0 +1,52 @@ +using Furion; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using SqlSugar; +using System; +using System.Collections.Generic; + +namespace BPA.MES.Base.Core +{ + /// + /// 名 称 :数据库启动类 + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/3/23 14:09:30 + /// 描 述 : + /// + public static class SqlsugarSetup + { + public static void AddSqlsugarSetup(this IServiceCollection services, IConfiguration configuration, string dbName = "ConnectionString") + { + //如果多个数数据库传 List + var dbs = App.GetConfig>("ConnectionConfigs")[0]; + var configConnection = new ConnectionConfig() + { + DbType = dbs.DbType, + ConnectionString = dbs.ConnectionString, + IsAutoCloseConnection = dbs.IsAutoCloseConnection, + }; + SqlSugarScope sqlSugar = new SqlSugarScope(configConnection, + db => + { + //单例参数配置,所有上下文生效 + db.Aop.OnLogExecuting = (sql, pars) => + { + Console.WriteLine(sql);//输出sql + }; + db.Aop.DataExecuting = (oldValue, entityInfo) => + { + if (entityInfo.PropertyName == "CreateTime" && entityInfo.OperationType == DataFilterType.InsertByObject) + { + entityInfo.SetValue(DateTime.Now); + }; + if (entityInfo.PropertyName == "CreateDate" && entityInfo.OperationType == DataFilterType.InsertByObject) + { + entityInfo.SetValue(DateTime.Now); + }; + }; + } + ); + services.AddSingleton(sqlSugar);//这边是SqlSugarScope用AddSingleton + } + } +} diff --git a/backend/BPA.MES.Base.Core/TreeExtensions.cs b/backend/BPA.MES.Base.Core/TreeExtensions.cs new file mode 100644 index 0000000..1659049 --- /dev/null +++ b/backend/BPA.MES.Base.Core/TreeExtensions.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace BPA.MES.Base.Core +{ + /// + /// 名 称 : + /// 创 建 人 :yangxiao + /// 创建时间 : 2023/3/4 9:50:52 + /// 描 述 : + /// + public static class TreeExtensions + { + public static List BuildTree(this List list, string rootId = "") where T : class, ITree + { + string rootId2 = rootId; + List list2 = list; + List resul = null; + if (list2.HasVal()) + { + List list3 = list2.Where((T e) => e.ParentId == rootId2).ToList(); + if (list3.HasVal()) + { + resul = new List(); + list3.ForEach(delegate (T it) + { + it.Children = list2.BuildTree(it.Id); + resul.Add(it); + }); + } + } + + return resul; + } + public interface ITree where T : class + { + string Id { get; set; } + + string ParentId { get; set; } + + List Children { get; set; } + } + public static List DeleteTreeNodes(this List list, Func condition) where T : class, ITree + { + if (list.HasVal()) + { + for (int i = 0; i < list.Count; i++) + { + T val = list[i]; + if (condition(val)) + { + list.Remove(val); + } + else if (val.Children.HasVal()) + { + val.Children.DeleteTreeNodes(condition); + } + } + } + + return list; + } + } +} diff --git a/backend/BPA.MES.Base.Web.Core/BPA.MES.Base.Web.Core.csproj b/backend/BPA.MES.Base.Web.Core/BPA.MES.Base.Web.Core.csproj new file mode 100644 index 0000000..56a5220 --- /dev/null +++ b/backend/BPA.MES.Base.Web.Core/BPA.MES.Base.Web.Core.csproj @@ -0,0 +1,19 @@ + + + + + net6.0 + 1701;1702;1591 + BPA.MES.Base.Web.Core.xml + + + + + + + + + + + + diff --git a/backend/BPA.MES.Base.Web.Core/BPA.MES.Base.Web.Core.xml b/backend/BPA.MES.Base.Web.Core/BPA.MES.Base.Web.Core.xml new file mode 100644 index 0000000..0956092 --- /dev/null +++ b/backend/BPA.MES.Base.Web.Core/BPA.MES.Base.Web.Core.xml @@ -0,0 +1,22 @@ + + + + BPA.MES.Base.Web.Core + + + + + 重写 Handler 添加自动刷新收取逻辑 + + + + + + + 检查权限 + + + + + + diff --git a/backend/BPA.MES.Base.Web.Core/Handlers/JwtHandler.cs b/backend/BPA.MES.Base.Web.Core/Handlers/JwtHandler.cs new file mode 100644 index 0000000..7d69122 --- /dev/null +++ b/backend/BPA.MES.Base.Web.Core/Handlers/JwtHandler.cs @@ -0,0 +1,72 @@ +using Furion; +using Furion.Authorization; +using Furion.DataEncryption; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using System.Threading.Tasks; + +namespace BPA.MES.Base.Web.Core; + +public class JwtHandler : AppAuthorizeHandler +{ + /// + /// 重写 Handler 添加自动刷新收取逻辑 + /// + /// + /// + public override async Task HandleAsync(AuthorizationHandlerContext context) + { + var IsClient = App.HttpContext.Request.Headers["IsClient"].ToString(); + if (IsClient == "true") + { + //获取所有未成功验证的需求 + var pendingRequirements = context.PendingRequirements; + // 通过授权验证 + foreach (var requirement in pendingRequirements) + { + context.Succeed(requirement); + } + } + else + { + // 自动刷新 token + if (JWTEncryption.AutoRefreshToken(context, context.GetCurrentHttpContext(), expiredTime: 43200, refreshTokenExpiredTime: 43225)) + { + await AuthorizeHandleAsync(context); + } + else + { + context.Fail(); // 授权失败 + } + } + } + public override Task PipelineAsync(AuthorizationHandlerContext context, DefaultHttpContext httpContext) + { + // 这里写您的授权判断逻辑,授权通过返回 true,否则返回 false + + return Task.FromResult(CheckAuthorzie(httpContext)); + } + /// + /// 检查权限 + /// + /// + /// + private static bool CheckAuthorzie(DefaultHttpContext httpContext) + { + // 获取权限特性 + var IsClient = App.HttpContext.Request.Headers["IsClient"].ToString(); + if (IsClient == "true") + { + return true; + } + var securityDefineAttribute = httpContext.GetMetadata(); + if (securityDefineAttribute == null) + { + return true; + } + else + { + return false; + } + } +} diff --git a/backend/BPA.MES.Base.Web.Core/Startup.cs b/backend/BPA.MES.Base.Web.Core/Startup.cs new file mode 100644 index 0000000..cbfc3b5 --- /dev/null +++ b/backend/BPA.MES.Base.Web.Core/Startup.cs @@ -0,0 +1,87 @@ +using System; +using System.Threading.Tasks; +using BPA.AGV; +using BPA.ApiClient; +using BPA.MES.Base.Application; +using BPA.MES.Base.Application.Subscriber; +using BPA.MES.Base.Core; +using BPA.MQTTClient; +using Furion; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using MQTTnet.Client; +using MQTTnet.Client.Connecting; +using MQTTnet.Client.Disconnecting; +using MQTTnet.Client.Options; +using Newtonsoft.Json.Linq; +using Yitter.IdGenerator; + +namespace BPA.MES.Base.Web.Core; + +public class Startup : AppStartup +{ + public void ConfigureServices(IServiceCollection services) + { + + services.AddConsoleFormatter(); + services.AddJwt(enableGlobalAuthorize: true); + services.AddCorsAccessor(); + services.AddSqlsugarSetup(App.Configuration); + // 配置雪花Id算法机器码 + YitIdHelper.SetIdGenerator(new IdGeneratorOptions + { + WorkerId = 5 + }); + // 注册 EventBus 服务 + services.AddEventBus(builder => + { + // 通过类型注册 + builder.AddSubscriber(typeof(ToDoEventSubscriber)); + }); + services.AddRemoteRequest(); + + services.AddWebApiClient(); + services.AddAGV(op => + { + op.Header = new KCOption() + { + AppKey = "43", + AppSecret = "12", + RequestId = "43", + Timestamp = "2234234324", + Version = "2.9" + }; + op.Sign = "123456"; + }); + + services.AddControllers() + .AddInjectWithUnifyResult(); + + } + + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + app.UseHttpsRedirection(); + app.UseStaticFiles(); + app.UseRouting(); + + app.UseCorsAccessor(); + + app.UseAuthentication(); + app.UseAuthorization(); + + app.UseInject("swagger"); + + app.UseEndpoints(endpoints => + { + endpoints.MapControllers(); + }); + } +} diff --git a/backend/BPA.MES.Base.Web.Entry/.config/dotnet-tools.json b/backend/BPA.MES.Base.Web.Entry/.config/dotnet-tools.json new file mode 100644 index 0000000..b0e38ab --- /dev/null +++ b/backend/BPA.MES.Base.Web.Entry/.config/dotnet-tools.json @@ -0,0 +1,5 @@ +{ + "version": 1, + "isRoot": true, + "tools": {} +} \ No newline at end of file diff --git a/backend/BPA.MES.Base.Web.Entry/BPA.MES.Base.Web.Entry.csproj b/backend/BPA.MES.Base.Web.Entry/BPA.MES.Base.Web.Entry.csproj new file mode 100644 index 0000000..4f228e6 --- /dev/null +++ b/backend/BPA.MES.Base.Web.Entry/BPA.MES.Base.Web.Entry.csproj @@ -0,0 +1,33 @@ + + + + + net6.0 + enable + en-US + true + 2cf25418-ba37-42f6-94c4-df8b11a33318 + Linux + + + + + + + + + + + + + + + + + + + + + + + diff --git a/backend/BPA.MES.Base.Web.Entry/BPA.MES.Base.Web.Entry.csproj.user b/backend/BPA.MES.Base.Web.Entry/BPA.MES.Base.Web.Entry.csproj.user new file mode 100644 index 0000000..ace091a --- /dev/null +++ b/backend/BPA.MES.Base.Web.Entry/BPA.MES.Base.Web.Entry.csproj.user @@ -0,0 +1,10 @@ + + + + ProjectDebugger + + + BPA.MES.Base.Web.Entry + E:\PZTJ.MES\backend\BPA.MES.Base.Web.Entry\Properties\PublishProfiles\FolderProfile.pubxml + + \ No newline at end of file diff --git a/backend/BPA.MES.Base.Web.Entry/Dockerfile b/backend/BPA.MES.Base.Web.Entry/Dockerfile new file mode 100644 index 0000000..122e207 --- /dev/null +++ b/backend/BPA.MES.Base.Web.Entry/Dockerfile @@ -0,0 +1,25 @@ +#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging. + +FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base +WORKDIR /app +EXPOSE 80 +EXPOSE 443 + +FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build +WORKDIR /src +COPY ["BPA.MES.Base.Web.Entry/BPA.MES.Base.Web.Entry.csproj", "BPA.MES.Base.Web.Entry/"] +COPY ["BPA.MES.Base.Web.Core/BPA.MES.Base.Web.Core.csproj", "BPA.MES.Base.Web.Core/"] +COPY ["BPA.MES.Base.Application/BPA.MES.Base.Application.csproj", "BPA.MES.Base.Application/"] +COPY ["BPA.MES.Base.Core/BPA.MES.Base.Core.csproj", "BPA.MES.Base.Core/"] +RUN dotnet restore "BPA.MES.Base.Web.Entry/BPA.MES.Base.Web.Entry.csproj" +COPY . . +WORKDIR "/src/BPA.MES.Base.Web.Entry" +RUN dotnet build "BPA.MES.Base.Web.Entry.csproj" -c Release -o /app/build + +FROM build AS publish +RUN dotnet publish "BPA.MES.Base.Web.Entry.csproj" -c Release -o /app/publish + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "BPA.MES.Base.Web.Entry.dll"] \ No newline at end of file diff --git a/backend/BPA.MES.Base.Web.Entry/Program.cs b/backend/BPA.MES.Base.Web.Entry/Program.cs new file mode 100644 index 0000000..65ae485 --- /dev/null +++ b/backend/BPA.MES.Base.Web.Entry/Program.cs @@ -0,0 +1 @@ +Serve.Run(RunOptions.Default.WithArgs(args)); diff --git a/backend/BPA.MES.Base.Web.Entry/SingleFilePublish.cs b/backend/BPA.MES.Base.Web.Entry/SingleFilePublish.cs new file mode 100644 index 0000000..8f9d8ec --- /dev/null +++ b/backend/BPA.MES.Base.Web.Entry/SingleFilePublish.cs @@ -0,0 +1,22 @@ +using Furion; +using System.Reflection; + +namespace BPA.MES.Base.Web.Entry; + +public class SingleFilePublish : ISingleFilePublish +{ + public Assembly[] IncludeAssemblies() + { + return Array.Empty(); + } + + public string[] IncludeAssemblyNames() + { + return new[] + { + "BPA.MES.Base.Application", + "BPA.MES.Base.Core", + "BPA.MES.Base.Web.Core" + }; + } +} \ No newline at end of file diff --git a/backend/BPA.MES.Base.Web.Entry/appsettings.Development.json b/backend/BPA.MES.Base.Web.Entry/appsettings.Development.json new file mode 100644 index 0000000..5f187ae --- /dev/null +++ b/backend/BPA.MES.Base.Web.Entry/appsettings.Development.json @@ -0,0 +1,10 @@ +{ + "$schema": "https://gitee.com/dotnetchina/Furion/raw/v4/schemas/v4/furion-schema.json", + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning", + "Microsoft.EntityFrameworkCore": "Information" + } + } +} \ No newline at end of file diff --git a/backend/BPA.MES.Base.Web.Entry/appsettings.json b/backend/BPA.MES.Base.Web.Entry/appsettings.json new file mode 100644 index 0000000..c8ad527 --- /dev/null +++ b/backend/BPA.MES.Base.Web.Entry/appsettings.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://gitee.com/dotnetchina/Furion/raw/v4/schemas/v4/furion-schema.json", + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning", + "Microsoft.EntityFrameworkCore": "Information" + } + }, + "AllowedHosts": "*", + "ConnectionConfigs": [ + { + "ConnectionString": "server=10.2.1.254;Port=3306;Database=bpa_pztj_mes;Uid=root;Pwd=BapAdmin123456.;", + //"ConnectionString": "server=192.168.1.231;Port=3306;Database=bpa_pztj_mes;Uid=root;Pwd=pztj8127;", + "DbType": "MySql", + "IsAutoCloseConnection": true + } + ], + "AGVUrl": "http://172.16.12.206:10080" +} \ No newline at end of file diff --git a/backend/BPA.MES.Base.sln b/backend/BPA.MES.Base.sln new file mode 100644 index 0000000..4571ecc --- /dev/null +++ b/backend/BPA.MES.Base.sln @@ -0,0 +1,43 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.3.32519.111 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BPA.MES.Base.Application", "BPA.MES.Base.Application\BPA.MES.Base.Application.csproj", "{AB699EE9-43A8-46F2-A855-04A26DE63372}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BPA.MES.Base.Web.Core", "BPA.MES.Base.Web.Core\BPA.MES.Base.Web.Core.csproj", "{9D14BB78-DA2A-4040-B9DB-5A515B599181}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BPA.MES.Base.Core", "BPA.MES.Base.Core\BPA.MES.Base.Core.csproj", "{4FB30091-15C7-4FD9-AB7D-266814F360F5}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BPA.MES.Base.Web.Entry", "BPA.MES.Base.Web.Entry\BPA.MES.Base.Web.Entry.csproj", "{C8D99F52-EDC7-411F-8300-6DB14BF59E8C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {AB699EE9-43A8-46F2-A855-04A26DE63372}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AB699EE9-43A8-46F2-A855-04A26DE63372}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AB699EE9-43A8-46F2-A855-04A26DE63372}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AB699EE9-43A8-46F2-A855-04A26DE63372}.Release|Any CPU.Build.0 = Release|Any CPU + {9D14BB78-DA2A-4040-B9DB-5A515B599181}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9D14BB78-DA2A-4040-B9DB-5A515B599181}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9D14BB78-DA2A-4040-B9DB-5A515B599181}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9D14BB78-DA2A-4040-B9DB-5A515B599181}.Release|Any CPU.Build.0 = Release|Any CPU + {4FB30091-15C7-4FD9-AB7D-266814F360F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4FB30091-15C7-4FD9-AB7D-266814F360F5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4FB30091-15C7-4FD9-AB7D-266814F360F5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4FB30091-15C7-4FD9-AB7D-266814F360F5}.Release|Any CPU.Build.0 = Release|Any CPU + {C8D99F52-EDC7-411F-8300-6DB14BF59E8C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C8D99F52-EDC7-411F-8300-6DB14BF59E8C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C8D99F52-EDC7-411F-8300-6DB14BF59E8C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C8D99F52-EDC7-411F-8300-6DB14BF59E8C}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {B2073C2C-0FD3-452B-8047-8134D68E12CE} + EndGlobalSection +EndGlobal diff --git a/backend/NuGet.config b/backend/NuGet.config new file mode 100644 index 0000000..b149801 --- /dev/null +++ b/backend/NuGet.config @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/backend/dockerfile b/backend/dockerfile new file mode 100644 index 0000000..3076cfe --- /dev/null +++ b/backend/dockerfile @@ -0,0 +1,30 @@ +#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging. + +FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base +WORKDIR /app +EXPOSE 80 +EXPOSE 443 + +FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build +WORKDIR /src +COPY ["NuGet.config", "."] +COPY ["BPA.MES.Base.Web.Entry/BPA.MES.Base.Web.Entry.csproj", "BPA.MES.Base.Web.Entry/"] +COPY ["BPA.MES.Base.Web.Core/BPA.MES.Base.Web.Core.csproj", "BPA.MES.Base.Web.Core/"] +COPY ["BPA.MES.Base.Application/BPA.MES.Base.Application.csproj", "BPA.MES.Base.Application/"] +COPY ["BPA.MES.Base.Core/BPA.MES.Base.Core.csproj", "BPA.MES.Base.Core/"] + + + +RUN dotnet restore "BPA.MES.Base.Web.Entry/BPA.MES.Base.Web.Entry.csproj" --configfile "NuGet.config" + +COPY . . +WORKDIR "/src/BPA.MES.Base.Web.Entry" +RUN dotnet build "BPA.MES.Base.Web.Entry.csproj" -c Release -o /app/build + +FROM build AS publish +RUN dotnet publish "BPA.MES.Base.Web.Entry.csproj" -c Release -o /app/publish + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "BPA.MES.Base.Web.Entry.dll"] \ No newline at end of file diff --git a/frontend/.editorconfig b/frontend/.editorconfig new file mode 100644 index 0000000..7e3649a --- /dev/null +++ b/frontend/.editorconfig @@ -0,0 +1,16 @@ +# http://editorconfig.org +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false + +[Makefile] +indent_style = tab diff --git a/frontend/.eslintignore b/frontend/.eslintignore new file mode 100644 index 0000000..8336e93 --- /dev/null +++ b/frontend/.eslintignore @@ -0,0 +1,8 @@ +/lambda/ +/scripts +/config +.history +public +dist +.umi +mock \ No newline at end of file diff --git a/frontend/.eslintrc.js b/frontend/.eslintrc.js new file mode 100644 index 0000000..3ac39ef --- /dev/null +++ b/frontend/.eslintrc.js @@ -0,0 +1,7 @@ +module.exports = { + extends: [require.resolve('@umijs/lint/dist/config/eslint')], + globals: { + page: true, + REACT_APP_ENV: true, + }, +}; diff --git a/frontend/.gitignore b/frontend/.gitignore new file mode 100644 index 0000000..0fb3670 --- /dev/null +++ b/frontend/.gitignore @@ -0,0 +1,41 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +**/node_modules +# roadhog-api-doc ignore +/src/utils/request-temp.js +_roadhog-api-doc + +# production +/dist + +# misc +.DS_Store +npm-debug.log* +yarn-error.log + +/coverage +.idea +yarn.lock +package-lock.json +*bak +.vscode + + +# visual studio code +.history +*.log +functions/* +.temp/** + +# umi +.umi +.umi-production +.umi-test + +# screenshot +screenshot +.firebase +.eslintcache + +build diff --git a/frontend/.prettierignore b/frontend/.prettierignore new file mode 100644 index 0000000..7999ccd --- /dev/null +++ b/frontend/.prettierignore @@ -0,0 +1,22 @@ +**/*.svg +.umi +.umi-production +/dist +.dockerignore +.DS_Store +.eslintignore +*.png +*.toml +docker +.editorconfig +Dockerfile* +.gitignore +.prettierignore +LICENSE +.eslintcache +*.lock +yarn-error.log +.history +CNAME +/build +/public diff --git a/frontend/.prettierrc.js b/frontend/.prettierrc.js new file mode 100644 index 0000000..3447a1a --- /dev/null +++ b/frontend/.prettierrc.js @@ -0,0 +1,21 @@ +module.exports = { + singleQuote: true, + trailingComma: 'all', + printWidth: 100, + proseWrap: 'never', + endOfLine: 'lf', + overrides: [ + { + files: '.prettierrc', + options: { + parser: 'json', + }, + }, + { + files: 'document.ejs', + options: { + parser: 'html', + }, + }, + ], +}; diff --git a/frontend/README.md b/frontend/README.md new file mode 100644 index 0000000..4c89a72 --- /dev/null +++ b/frontend/README.md @@ -0,0 +1,57 @@ +# Ant Design Pro + +This project is initialized with [Ant Design Pro](https://pro.ant.design). Follow is the quick guide for how to use. + +## Environment Prepare + +Install `node_modules`: + +```bash +npm install +``` + +or + +```bash +yarn +``` + +## Provided Scripts + +Ant Design Pro provides some useful script to help you quick start and build with web project, code style check and test. + +Scripts provided in `package.json`. It's safe to modify or add additional script: + +### Start project + +```bash +npm start +``` + +### Build project + +```bash +npm run build +``` + +### Check code style + +```bash +npm run lint +``` + +You can also use script to auto fix some lint error: + +```bash +npm run lint:fix +``` + +### Test code + +```bash +npm test +``` + +## More + +You can view full document on our [official website](https://pro.ant.design). And welcome any feedback in our [github](https://github.com/ant-design/ant-design-pro). diff --git a/frontend/config/config.ts b/frontend/config/config.ts new file mode 100644 index 0000000..f4cdc2e --- /dev/null +++ b/frontend/config/config.ts @@ -0,0 +1,132 @@ +// https://umijs.org/config/ +import { defineConfig } from '@umijs/max'; +import { join } from 'path'; +import defaultSettings from './defaultSettings'; +import proxy from './proxy'; +import routes from './routes'; + +const { REACT_APP_ENV = 'dev' } = process.env; + +export default defineConfig({ + /** + * @name 开启 hash 模式 + * @description 让 build 之后的产物包含 hash 后缀。通常用于增量发布和避免浏览器加载缓存。 + * @doc https://umijs.org/docs/api/config#hash + */ + history: { type: 'hash' }, + + // 更改为history模式 + // history:{type:'browser'} + hash: true, + esbuildMinifyIIFE: true, + /** + * @name 兼容性设置 + * @description 设置 ie11 不一定完美兼容,需要检查自己使用的所有依赖 + * @doc https://umijs.org/docs/api/config#targets + */ + // targets: { + // ie: 11, + // }, + /** + * @name 路由的配置,不在路由中引入的文件不会编译 + * @description 只支持 path,component,routes,redirect,wrappers,title 的配置 + * @doc https://umijs.org/docs/guides/routes + */ + // umi routes: https://umijs.org/docs/routing + routes, + /** + * @name 主题的配置 + * @description 虽然叫主题,但是其实只是 less 的变量设置 + * @doc antd的主题设置 https://ant.design/docs/react/customize-theme-cn + * @doc umi 的theme 配置 https://umijs.org/docs/api/config#theme + */ + theme: { + // 如果不想要 configProvide 动态设置主题需要把这个设置为 default + // 只有设置为 variable, 才能使用 configProvide 动态设置主色调 + 'root-entry-name': 'variable', + }, + /** + * @name moment 的国际化配置 + * @description 如果对国际化没有要求,打开之后能减少js的包大小 + * @doc https://umijs.org/docs/api/config#ignoremomentlocale + */ + ignoreMomentLocale: false, + /** + * @name 代理配置 + * @description 可以让你的本地服务器代理到你的服务器上,这样你就可以访问服务器的数据了 + * @see 要注意以下 代理只能在本地开发时使用,build 之后就无法使用了。 + * @doc 代理介绍 https://umijs.org/docs/guides/proxy + * @doc 代理配置 https://umijs.org/docs/api/config#proxy + */ + proxy: proxy[REACT_APP_ENV as keyof typeof proxy], + /** + * @name 快速热更新配置 + * @description 一个不错的热更新组件,更新时可以保留 state + */ + fastRefresh: true, + //============== 以下都是max的插件配置 =============== + /** + * @name 数据流插件 + * @@doc https://umijs.org/docs/max/data-flow + */ + model: {}, + /** + * 一个全局的初始数据流,可以用它在插件之间共享数据 + * @description 可以用来存放一些全局的数据,比如用户信息,或者一些全局的状态,全局初始状态在整个 Umi 项目的最开始创建。 + * @doc https://umijs.org/docs/max/data-flow#%E5%85%A8%E5%B1%80%E5%88%9D%E5%A7%8B%E7%8A%B6%E6%80%81 + */ + initialState: {}, + /** + * @name layout 插件 + * @doc https://umijs.org/docs/max/layout-menu + */ + layout: { + locale: false, + ...defaultSettings, + }, + // /** + // * @name 国际化插件 + // * @doc https://umijs.org/docs/max/i18n + // */ + // locale: { + // default: '' + // }, + /** + * @name antd 插件 + * @description 内置了 babel import 插件 + * @doc https://umijs.org/docs/max/antd#antd + */ + antd: { + configProvider: {}, + appConfig: {}, + }, + /** + * @name moment2dayjs 插件 + * @description 将项目中的 moment 替换为 dayjs + * @doc https://umijs.org/docs/max/moment2dayjs + */ + moment2dayjs: { + preset: 'antd', + plugins: ['duration'], + }, + /** + * @name 网络请求配置 + * @description 它基于 axios 和 ahooks 的 useRequest 提供了一套统一的网络请求和错误处理方案。 + * @doc https://umijs.org/docs/max/request + */ + request: {}, + /** + * @name 权限插件 + * @description 基于 initialState 的权限插件,必须先打开 initialState + * @doc https://umijs.org/docs/max/access + */ + access: {}, + //================ pro 插件配置 ================= + presets: ['umi-presets-pro'], + keepalive: [/./], + tabsLayout: { hasFixedHeader: false }, + mfsu: { + strategy: 'normal', + }, + requestRecord: {}, +}); diff --git a/frontend/config/defaultSettings.ts b/frontend/config/defaultSettings.ts new file mode 100644 index 0000000..2f6f1a4 --- /dev/null +++ b/frontend/config/defaultSettings.ts @@ -0,0 +1,28 @@ +import { Settings as LayoutSettings } from '@ant-design/pro-components'; + +/** + * @name + */ +const Settings: LayoutSettings & { + pwa?: boolean; + logo?: string; + title?:any +} = { + navTheme: 'light', + colorPrimary: '#13C2C2', + layout: 'mix', + contentWidth: 'Fluid', + fixedHeader: false, + fixSiderbar: true, + colorWeak: false, + title: "中控管理系统", + menu: { + locale: false, // 禁用多语言功能 + }, + pwa: false, + splitMenus:false, + + iconfontUrl: '', +}; + +export default Settings; diff --git a/frontend/config/proxy.ts b/frontend/config/proxy.ts new file mode 100644 index 0000000..ff1230b --- /dev/null +++ b/frontend/config/proxy.ts @@ -0,0 +1,26 @@ +/** + * @name 代理的配置 + * @see 在生产环境 代理是无法生效的,所以这里没有生产环境的配置 + * @doc https://umijs.org/docs/guides/proxy + */ +export default { + dev: { + '/api/': { + target: 'http://localhost:5502', + pathRewrite: { + '/api': '/api' + }, + changeOrigin: true, + } + }, + pre: { + '/api/': { + target: 'http://localhost:5000', + changeOrigin: true, + secure: false, + pathRewrite: { + '/api': '' + }, + }, + }, +}; diff --git a/frontend/config/routes.ts b/frontend/config/routes.ts new file mode 100644 index 0000000..bea4387 --- /dev/null +++ b/frontend/config/routes.ts @@ -0,0 +1,75 @@ +export default [ + { path: '/user', layout: false, routes: [{ path: '/user/login', component: './user/login' }] }, + { path: '/', icon: 'SmileOutlined', component: './welcome', name: '欢迎页' }, + { + icon: 'SettingOutlined', + path: '/system', + name: '系统管理', + routes: [ + { path: '/system/user', name: '人员管理', component: './system/user' }, + { path: '/system/role', name: '角色管理', component: './system/role' }, + { path: '/system/module', name: '模块管理', component: './system/module' }, + ], + }, + { + path: '/wmx', icon: 'SettingOutlined', name: '设备模型管理', + routes: [{ + name: '设备建模', + path: '/wmx/deviceProduct', + component: './deviceProductInfo/index', + }, + { path: '/wmx/deviceinfo', name: '设备管理', component: './deviceInfo/index' }, + ] + }, + { + path: '/base', icon: 'SettingOutlined', name: '工厂数据管理', + routes: [ + // { path: '/base/stock', name: '料仓管理', component: './stock/index' }, + { path: '/base/materials', name: '原料管理', component: './materials/index' }, + { path: '/base/final', name: '成品管理', component: './final/index' }, + { path: '/base/manufacturing', name: '产线管理', component: './manufacturing/index' }, + // { path: '/base/dict', name: '数据字典', component: './dict/index' }, + ] + }, + + // { + // path: '/line', icon: 'SettingOutlined', name: '产线管理', + // routes: [ + // { path: '/line/manufacturing', name: '产线设备管理', component: './manufacturing/index' }, + // ] + // }, + { + path: '/recipeCraft', icon: 'SettingOutlined', name: '配方工艺管理', + routes: [ + { path: '/recipeCraft/recipe', name: '配方管理', component: './recipe/index' }, + { path: '/recipeCraft/pot', name: '设备工艺', component: './craftInfo/pot' } + ] + }, + { path: '/work', icon: 'SettingOutlined', name: '工单管理', component: './workInfo/index' }, + // { + // path: '/data', icon: 'SettingOutlined', name: '数据服务', + // routes: [ + // { path: '/data/userlog', name: '操作日志', component: './logs/userlog' }, + // { path: '/data/runlog', name: '运行日志', component: './logs/runlog' }, + // { path: '/data/alarmlog', name: '报警日志', component: './logs/alarmlog' }, + // { path: '/data/programlog', name: '系统日志', component: './logs/programlog' } + // ] + // }, + // { + // path: '/agv', icon: 'SettingOutlined', name: 'agv管理', + // routes: [ + // { path: '/agv/agvbasic', name: 'agv基础数据', component: './agvbasic/index' }, + // { path: '/agv/agvline', name: 'agv线路管理', component: './agvline/index' } + // ] + // }, + // { + // path: '/report', icon: 'SettingOutlined', name: '统计报表', + // routes: [ + // { path: '/report/product', name: '成品统计', component: './report/product' }, + // { path: '/report/material', name: '原料统计', component: './report/material' }, + // ] + // }, + + { path: '*', layout: false, component: './404' }, + +]; diff --git a/frontend/default.conf b/frontend/default.conf new file mode 100644 index 0000000..ad50602 --- /dev/null +++ b/frontend/default.conf @@ -0,0 +1,13 @@ +server { + listen 80; + server_name localhost; + + location / { + root /usr/share/nginx/html; + index index.html index.htm; + try_files $uri $uri/ /index.html; + } +} + + + diff --git a/frontend/dockerfile b/frontend/dockerfile new file mode 100644 index 0000000..dfe1554 --- /dev/null +++ b/frontend/dockerfile @@ -0,0 +1,4 @@ +FROM nginx:latest +COPY ./frontend/dist /usr/share/nginx/html/ +COPY ./frontend/default.conf /etc/nginx/conf.d/ +EXPOSE 80 diff --git a/frontend/jest.config.ts b/frontend/jest.config.ts new file mode 100644 index 0000000..1de2a1a --- /dev/null +++ b/frontend/jest.config.ts @@ -0,0 +1,23 @@ +import { configUmiAlias, createConfig } from '@umijs/max/test'; + +export default async () => { + const config = await configUmiAlias({ + ...createConfig({ + target: 'browser', + }), + }); + + console.log(); + return { + ...config, + testEnvironmentOptions: { + ...(config?.testEnvironmentOptions || {}), + url: 'http://localhost:8000', + }, + setupFiles: [...(config.setupFiles || []), './tests/setupTests.jsx'], + globals: { + ...config.globals, + localStorage: null, + }, + }; +}; diff --git a/frontend/jsconfig.json b/frontend/jsconfig.json new file mode 100644 index 0000000..197bee5 --- /dev/null +++ b/frontend/jsconfig.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "jsx": "react-jsx", + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/frontend/package.json b/frontend/package.json new file mode 100644 index 0000000..e9834e6 --- /dev/null +++ b/frontend/package.json @@ -0,0 +1,106 @@ +{ + "name": "ant-design-pro", + "version": "6.0.0", + "license": "ISC", + "private": true, + "description": "An out-of-box UI solution for enterprise applications", + "scripts": { + "analyze": "cross-env ANALYZE=1 max build", + "build": "max build", + "deploy": "npm run build && npm run gh-pages", + "dev": "npm run start:dev", + "gh-pages": "gh-pages -d dist", + "i18n-remove": "pro i18n-remove --write", + "postinstall": "max setup", + "jest": "jest", + "lint": "npm run lint:js && npm run lint:prettier && npm run tsc", + "lint-staged": "lint-staged", + "lint-staged:js": "eslint --ext .js,.jsx,.ts,.tsx ", + "lint:fix": "eslint --fix --cache --ext .js,.jsx,.ts,.tsx --format=pretty ./src ", + "lint:js": "eslint --cache --ext .js,.jsx,.ts,.tsx --format=pretty ./src", + "lint:prettier": "prettier -c --write \"**/**.{js,jsx,tsx,ts,less,md,json}\" --end-of-line auto", + "openapi": "max openapi", + "prepare": "cd ../.. && husky install frontend/.husky", + "prettier": "prettier -c --write \"**/**.{js,jsx,tsx,ts,less,md,json}\"", + "preview": "npm run build && max preview --port 8000", + "record": "cross-env NODE_ENV=development REACT_APP_ENV=test max record --scene=login", + "serve": "umi-serve", + "start:mock": "cross-env UMI_ENV=dev max dev", + "start": "cross-env UMI_ENV=dev max dev", + "start:dev": "cross-env REACT_APP_ENV=dev MOCK=none UMI_ENV=dev max dev", + "start:no-mock": "cross-env MOCK=none UMI_ENV=dev max dev", + "start:pre": "cross-env REACT_APP_ENV=pre UMI_ENV=dev max dev", + "start:test": "cross-env REACT_APP_ENV=test MOCK=none UMI_ENV=dev max dev", + "test": "jest", + "test:coverage": "npm run jest -- --coverage", + "test:update": "npm run jest -- -u", + "tsc": "tsc --noEmit" + }, + "lint-staged": { + "**/*.{js,jsx,ts,tsx}": "npm run lint-staged:js", + "**/*.{js,jsx,tsx,ts,less,md,json}": [ + "prettier --write" + ] + }, + "browserslist": [ + "> 1%", + "last 2 versions", + "not ie <= 10" + ], + "dependencies": { + "@ant-design/charts": "^1.4.2", + "@ant-design/icons": "^4.8.0", + "@ant-design/pro-components": "^2.3.44", + "@ant-design/pro-layout": "^7.8.3", + "@ant-design/use-emotion-css": "1.0.4", + "@jiaminghi/data-view-react": "^1.2.5", + "@umijs/route-utils": "^2.2.2", + "antd": "^5.2.3", + "classnames": "^2.3.2", + "eslint-config-prettier": "^8.6.0", + "eslint-plugin-unicorn": "^46.0.0", + "js-md5": "^0.7.3", + "lodash": "^4.17.21", + "moment": "^2.29.4", + "omit.js": "^2.0.2", + "rc-menu": "^9.8.1", + "rc-util": "^5.25.2", + "react": "^18.2.0", + "react-dev-inspector": "^1.8.3", + "react-dom": "^18.2.0", + "react-helmet-async": "^1.3.0", + "uuid": "^9.0.0" + }, + "devDependencies": { + "@ant-design/pro-cli": "^2.1.5", + "@testing-library/react": "^13.4.0", + "@types/classnames": "^2.3.1", + "@types/express": "^4.17.14", + "@types/history": "^4.7.11", + "@types/jest": "^29.2.4", + "@types/js-md5": "^0.7.0", + "@types/lodash": "^4.14.191", + "@types/react": "^17.0.52", + "@types/react-dom": "^17.0.18", + "@types/react-helmet": "^6.1.6", + "@umijs/lint": "^4.0.35", + "@umijs/max": "^4.0.55", + "cross-env": "^7.0.3", + "eslint": "^8.29.0", + "express": "^4.18.2", + "gh-pages": "^3.2.3", + "husky": "^7.0.4", + "jest": "^29.3.1", + "jest-environment-jsdom": "^29.3.1", + "lint-staged": "^10.5.4", + "mockjs": "^1.1.0", + "prettier": "^2.8.1", + "swagger-ui-dist": "^4.15.5", + "ts-node": "^10.9.1", + "typescript": "^4.9.4", + "umi-presets-pro": "^2.0.0" + }, + "engines": { + "node": ">=12.0.0" + } +} diff --git a/frontend/playwright.config.ts b/frontend/playwright.config.ts new file mode 100644 index 0000000..ec1b31d --- /dev/null +++ b/frontend/playwright.config.ts @@ -0,0 +1,22 @@ +// playwright.config.ts +import type { PlaywrightTestConfig } from '@playwright/test'; +import { devices } from '@playwright/test'; + +const config: PlaywrightTestConfig = { + forbidOnly: !!process.env.CI, + retries: process.env.CI ? 2 : 0, + use: { + trace: 'on-first-retry', + }, + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] }, + }, + { + name: 'firefox', + use: { ...devices['Desktop Firefox'] }, + }, + ], +}; +export default config; diff --git a/frontend/public/CNAME b/frontend/public/CNAME new file mode 100644 index 0000000..30c2d4d --- /dev/null +++ b/frontend/public/CNAME @@ -0,0 +1 @@ +preview.pro.ant.design \ No newline at end of file diff --git a/frontend/public/favicon.ico b/frontend/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..e2e93252988b5bed120ddeb168eb577bf0caa881 GIT binary patch literal 4286 zcmeHLO(?8k6#ga#Gs=ufvobTd=q@y~nOLdYlqL%nQY4WqC`)z}3y~cqOAAF4VkQd~ z^3$wrC}~D1l%!eMp!|gA&U5sN?~b{2>)yNg-s#Lc-+9k_p7Y<=XqqYcDJs(Vt%dBG z=F~Lpdy*pd!Y zozZT}udJ-#| zqiAVq0sT@kAMMobbULxOw+F6{j*egO8CQ?TgTuo^+}_@zrlv;l$*-)e#PRVl?(Xgo zi9`?zg>ZFsh0DuJ)Ya9!von7LPN@OfP9IfH_4tet&&I~a#O{TK1<3*LO-xJ( zZ*Fc5%v&m4#Z&mZySs8{XJ-fV^Yh@{p`ju8d_J)w6+U%`!(qAC+uJK~qg_o+O|QC` zTVg0Y{jSHqzP^^&G0t4^cwF+$`egj?@9$AtTMLuPB>7!lUKY8&zP?xd=H_PM(U;HS ztNi!(_oJes0<5X6tu4{BxVR{FO)_x3UauFkv$I%RTSHe@7dAIHF+4mhc?|>t(!XbCXVQZk z8yje7Xh2R*&WCwdw&?N4$H!4$Uyq)i9_;V$3;y)^-LKhmkv{Z#(CP^-7Wn# zI5-H>z`y`nTU%u=f7Tbh-mg5fPT0G8`Wx6^vD1(>-r0;AFlyjWYC!!D@UQlt)%}4^ literal 0 HcmV?d00001 diff --git a/frontend/public/icons/icon-128x128.png b/frontend/public/icons/icon-128x128.png new file mode 100644 index 0000000000000000000000000000000000000000..48d0e2339a60a637b94319c65e8654289b4f4b6c GIT binary patch literal 1329 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

*C7T$?5!b= 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

s5~Kru5_G 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 literal 0 HcmV?d00001 diff --git a/frontend/public/logo.svg b/frontend/public/logo.svg new file mode 100644 index 0000000..239bf69 --- /dev/null +++ b/frontend/public/logo.svg @@ -0,0 +1 @@ +Group 28 Copy 5Created with Sketch. \ No newline at end of file diff --git a/frontend/public/nc.png b/frontend/public/nc.png new file mode 100644 index 0000000000000000000000000000000000000000..2dcd41028bd3c9601bcb55c3eb66cc0f2a686f4c GIT binary patch literal 366817 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

?f7Kl~9@%P=q zQR*(bE_mjf@$F3c+;-*&wk@G8=>{IRg192hD7lDqd=0rhM`G3oQT#ZN>U+BgRVSG* zA$FeYIy~Kf0+U&Easz%07FGI%Ev3M?Wu?vrXp31Yw!#O;@2_*|005h$m#^bS{W_2? zV%N8B&_#5!amplH+^7JNpo+XL2q6DWsa3o@^GASgyOkJWIm9W8!$eP3hWAZ}JJp0T z^!pn9+)Om_%MU&+O^lzxG8m?)2}!PHRM<}ne6!&pxQ$$n_dN)v@}LzJ%K z)54n7%O={M%Gh(5CB;!G{e_5C({7TN)XS4F*h$7l#?W%H8frT% z^`p$%-**?cayN24|Hsr@1~dVF?Zcx75*r}{K~e-nx^uv2DP@FG(v7rq3ZuJIP=wJX zUD7ogq)}3dNjLoW{GNE{$uegtuezZgg~kYP7iVAZi{r^$ zC9lS%m#Ut<#YwK@AUvJEoR`*=@9|)ptSxUVa=wk6ZDIJEgb#CJlX7E{Mvc!7ikU%w#XoPaAK;R2T%0>H{?naxjI4%P)d8 z%J@Mk{gr#y9r3o1f%kO%cTPM8a_ogC0$p0oznGELfH~2K1Ji9&Ug$EC`>#=Wr~06e>Im=7x#@_b9atfglyDQ7F$X$vRtmX0BL2QLw4jXBnY4ywKL%Q z#-Sm}XZu^l{(si;k6;ZJ0KA#gTKS}(`)i6DibKz`Ib)nUTERdUk>ZB2BH&6-*IOFf z{(EfK-eH%;)(-@XR+dv&vip}9f)hf(QD(Ye1->!t1)Y>2!U-mUY7tXxrFDd4qB(Kg z%H&@M>34GqMvvkDK6x=|{W5w_2E+EH(y47w=~dENc^o2Pi4Wy6Gr;|NxUv@ z|LE?qK&&1Eec!=8uBlsR_TB$-9d*%ZQrZGBisFvrB_%H!EP-HAm|0PgGl|VWMh$AQ zGB`3qXtNU8BZEo{1D*;Vxo2o#-k=X}B>oFL2W)3uG9n1UW-;omdpE`~ow_LR9jS;M z%eDRQO9ugK4vnp4Wh0pQ?r0Wc3X~nEy&?TDwI#g3X@*17oMLXjp<)%=#C^`4H-x0r#iWs zJo@8M<0=ip+Zh2Nk;q8H`3s|^GP{4Ildeyxzm4=w+UbtdyNqVRJ|Fx#c0F0WQJ>}> z=5^B;c)v@VNC&J6_$YIR!z()8&&Y0OpdM+U0EP^0g*j$pMa}-*UGeH%^HkTK+1Z)j zuA2~A5_I=4uz5Vrtwl&w0tE(_Aft??Gj=__8tlJ!aB7aHDb;NuOV(}g2U_U{&XQ z;keXGr$7brW4At0kjnNosd)s@7%SyNypb0IumS{e;1rWRJ+H=yb)aLfx>95bY4{*b z#A#egbS(Waj>!yO+DEmegc;;P^7v5KfL08aMFnT4j?~pXac(<$)Oob+EOl`ky?5r> zzA)=ygdsK%Fa-luGc_mer$!Re7tp1$Xu4@-|Y>-!!3_LbQ)hF_N57*>mo;HAMHSoKh!sySZ|`Q~ zs_eTC^i2*wK-3d+N5kQ>7~}(|O6cke($Q8>=o;%oycd*LR0@D_yl_O$QZGKc$STtWUPgYECPgTsF?D?iRD1JFdn%j#GJZb5@tp z*<+q%#W7tmt92Vttq{=>JF{*Vs=CC%j!Y{!V8|r~3M1x-SDz-n z)4%*}!3SnaX3C0;f*_iZeq~C_NWQ=Z@JhF% z<4sL9&1u*)X30auO@1kKx5FJjov&x=ON$}ZN>Czo>9e@CjMOzv;>4m(cfOl}uyvo6ei z1x@N}Jn#^~rNNvTnY4g};4GjsB?rlzviDR{x+n%(tk0fv@f74bl|u}WW!lR4ouQD?oHZXL8PncRJi6|Gh)Hx_H4uHZO{07H zT!(K=e$B+lutIkv6h&Q!$+wdLfH(NjVnv~az#ho_9tmSUT|Ot1uSNVOh<^R^x{yol zE0_S0kPrRq>H2KJ!((3DAkMZUHW`6lwWEe0HC8DJJYq#%Xh2-xwjSn zM32k}!ul_SB|W=j`5(OXUwN!3FC#8Y%P$M@$`qK^udJ-_OYWb|M8nEf-^M`vQ)$0{ z1&-%pafp6p+$=M?i0(v&h$iQj$~{SMd>$SS-)Y#huR4qcjf2yJ49VgX+^iuGD-db)L^JygPpp>%66BQa^29)%MZc3AF zMj^Av%me&t{zOay<22K_P1)(aB~mWsO)YfZ@N?kVyJLx}7!Mqp{amxH{9tU@>U}ro z*4X(#9k@lY&tPb5l6z+Rk=$?ox%OqxMnO#=C0fE=2>d%mQ}XEI`r(bxyv6^m?MM7! zdC>VE2?>3zuJSyrF5dH{15baC2IH#6CG~j^BxjaRZDfcQTq@%$l|p81aSq8K)z_2m ziRaqSc%Wc*TDF21o6QvVNJtP379fO=mYJWwt8Rk#sXHwl?FGx9e$|peD6w)_-VhVs zrksDK5g7C7u7m#u#nvJbvzAvs+%RnC-?E48i-4WEgH#T|m&7=RhEAP#xy}#281B*O zdht9}+&Th$QEbo?g%7Lo=6_o&(LOkqW^kH;_lQupFo1zOosTjho%E44ibk7gAdHiv zUl2RQx^uH6U`DR1jryqRGLCmxQueCwh zW;%ll$vE4>17{OX8@x7$Zhi-;dXf{ZfoF5%YV?J?oLQwIw8+W#ujva*|JDJHrZX^g z!wJli^8F`{KJ|bz7rO2A;n4ie)czXhCC_$av}dc}xs@WUTMVW)WJaezfg}DKgbl{x z7oeaX#J4kei3P*OdQKc-S6)c;u_UkfZ=w!UJX;sEc$nbqMknuqy(g8l`;joNycQ#) zE&#?R|60!Ueg03S9i?pqm*zcO*?jPIBv;S=i=Fwk%i(#!9#1k-rbiAJHy5jc52*H5 zK5LaCdb;UX=C3rcGNBcfdzcQKQb(_1A7Epg|48@v-f@EF)CGpZkq9?^N(FjVv=nocobYac+g^*K$bPuX;A1R`=8=qxaF*uHkjvN6FuN8uMb&L;2ne5L<}F77o1{ z5Y>enrKWCTXswzRCvY&Kfmv{J`5bOmT%s>3^XFGUck$67RUSPr9&zu^<3OQb-29^&3}d(Fl%# zj!wVZro7qgV%yep3zyqRCO7>i0edoiqDTT+EFrjpZxVBGSaCQk%zZFj^h+#DBF8`U z1KGp*^A^2(7hezm5bv^l!oXq8Y`w)Vk%7WDzm&Fit~WY(uj&G%zoUEIJ1)5@(GT{) zflG>aMb|4mDGi|n4@`$6qqZ@o{jgVGm>s7j18)EQ3cbmy-Q*H0#=Howv}9Jc3I@DI z=I5*F9TuJj?xRWkf;|&4VoZb)2tn+#{Z_4QA1C-r1;Vq@*+)bTNlM4aU4XW%`T6c6 z*9{OAl=OZuF85;e70hm8pd5Fd=-+CSmaD1;J1ggf>QcEBLGJj-#`M*nh2NW(iw)DW zZ5`j=j?%Ze2VAe+kE{h;rP`-oc=l-@**FHCGTiqpId}T|)nnSJSFcu!l*m9>G+i*+ z1P~$V>gZnC+0lO?=t*8u$7yT`(!}7XWM0H?H z@&I0!1v_dh1#dJe!hAkkxz5o!XYJ$FNY(A^+U?HRy{j%&Qc{$T!lZ}Mn%DDz0X_wo zs9{h>rc_;n?#9}~UEodW)Z;h)wH&Kgc=Nr}_X2!;v5jv61H$fd+%Va!e{qZ(YD4sC zg|5|{$BJj2LDl@y!S}tlk%WMmV|^r|;}nsIktIVkfDe7jJ#hM)&JIt!odf7g@y|YMmIrqN{(QDN3ot>_8$@pjmMk0N??? z@RuR>H_){N8m)O6G34OLPsT)WL=_i?B*F0_6F>*+gbvV%6dQ5K6piduicl#bKS<7W zTmG?%FdV>&Bb30k!G!&CDDCX{(ndC}8|tB>BbuSbSb&JcWmf0&zki`j1#?~AEuRNxpq;kne%Uka&+AQ>^RGj|33`vZ?_Q#;U@!p{p`%EzB|iI z2k%=~&W#$E4qE&vHcYJ$yBThAfUcld5oDKI(^!LmprFXXpx3k!4*sf+DgG$OkWHXG z$0mOQ#Ku6(M06*rP*hsH-Nnps#yvEVAe=o>eRlWQu8cUYsobjD*8(Ju z*SdVjj{DD&?P*vNR#QPo&{d&+xrV0ZI0{uspG(K^QV%Y4;;z%G01z`6qhFPF$y%?q z-wS>?Z4JENHM_X{{T}%1?_aaJ=9afIq}^MrHcOl7zxqz>oZqC78ziF#M;YZC$;A@0a~Ygz)pPR8(_9)NrYM1_lO`R?ma$ zt5|#Mosq3JU|%`=ydK8&WCu*2xgEn6-m4(H+6?+BA*af0K5P`TD-|&;mpDo2&1F4% zTp}qheKVDga$fWM(?@L_aDRTXW8J8`6)R>^_J>#C6E1_Fx;bpc8aA6Y(o^|UN~ko-AJE7_csHKgKctHK#Gt)o*jp-lJpH84tVVyX z!5pAgEonS=lF37dlw;O zH?m{g(*72O(u~uzF9C+g@v;N-0YJO37+&_X+}rgCGECOk`Lp63`VpJ5%kEpe3Fd?^ zSlVD*vT%#=@Q=J-qs8VuUWTYomxOQG1^5J1{ArEo@n;p#g0tY6u}7IFo*IF?V$GjrqIBTYHe|y$DVWXfjnn*5__1ju@N}iI zyujo}sR|H8^p$;|m@Ylq?y<$LxyI3Xg}{^Kkgc&w=ZpUWDk)Qssygl$?W+tOxzQ`F zdNZjP%kGXq+5LoPX1J!Nra?hOUt|;xd*fT3Zd}|tF_pLfgfz$YNpmJi&xD83w4mcs zKSVucqHAAeNE~Km#XUMIMi7DR1VD^COr{LdCmHl+XX}#d zre}})ii#G+OmNS;sZkP89Blv&H60aKXjE^`5@0t)ha4bgqGPGg^*DOAEo;1qox#W< zyxf2I@2#tg-@$owqlw?u?f#|Tuk>eJb|oOKZc5%4*oA*wQ9S_D54FI+t9gd|wTJn@ z{l>@zmaNkK3;!iKjF`yiiLV@vBxRZ~qW~NRsMcyqNkWM3AZ&J7z$BQ1xU$GNTX+vt?>&JQP_?CZLEE#DU-Xe3<~r%N91j9mAh%zKF$+vZ(3&MPhM zA9h@_#O30cpVb=RKKmD0tm7 z-GF>?`2~|_Md{-EL;51O%^?ckCE5W7{!c?1081alOmn@L=-zbvumff z^lz}|_toQxLpkNhT>L)3u+E-kEz+SySdZ~RvLyY2{h|mq0SPhj11huEI*XEYYuBhH zvNivbFm$o%&OLsc5Z0VQx<6_NT#-v$Y%rBCK!VW=;`z8wYoW878@ivRH-g zm^Okn4k{uKeRfX<$&TB(#)s*vs)y+fF`zv5Fk4&?$`2hfAQ*j-| zNEO+qULbf1T@=yLKHv49=I7<)=PesQ9&zk66%OBI{fpp6V+34IH{ecI-Pq(saY_me)2_1uU!t=#s{8?RMVRSNH2xoTg6+{6W+ z0!9-^X?B309*(jui-sK^>aYIXf9bqQ-j2Hcvi6{oE-?1>#-012XfaT_bYm+z?dH^W z1nZ{$?BQDl=9_cB<<6UjYD@x^W;yS%h7mKkMTm6fl=0i||HYCQ0SL<$JYi+cN_r{4 zrH#W8_2t!Yt@@N8hoZjc&uap@a~V^KAGfArA;fRKa14@j@B_&KSmd&1HU*O>I}@vaWDGzqyt`-<)RO`P{$S zyD~MvRX)0hpkHP*mOlwNV|J*xUN;Br7-khSg(W8^FF5E@;t7tmtM^0L4P1rg5dhOc z#;oajz%w`=vjP@xlw1%XBt%u%6g!-e(y}DVNBdI?Hj*QfTVZM3cVn`D8`b~8erAcc z#o$w&_urs2d@CZMu9#moaE<5DMH>x6!snho9KJ|B!^%GD7$muZS=zIe`;0`ZJy-ff z$LBOoxy>K{3~!CJKH*h0H7#IaVy?(-7RIS;Ew}r&a;c?5tkq*=<%DR@2|f68b-TZ*V8a@!x}Jr98c8zbe%!`0 z`K;$?dzk#mlaaq48&)NEK?_LZvv8^UJz6Qt@2KgblF3W56OF1$WD6I5t^<0s$rxq5WjIsiwDvYw((l9J-+pC3gS4+6D4YVm zFnrlha5$KRX5u`?NbNr{;zdig-5xthwN@A-4^)4Q%ZvmHh~y4&F}clIaEI~AWMbZ@ zTCU8@j_stW5;LeQ3?K`G!C4(yF&-Aof*a=80QhU2$M4C(T3Y}u932b0dLgT4UuXV! z5Nu4^)JyFixF=Pl^oJh7Vq1Zg%o_|iv(SStQD z5xLNJyWbQYoo^|vwKq36*J1ULo`PKgJMx&Uw|Chn;!m#cbgS1_Lk0&&=h$;$01$#vFjfqC0*1kXfx&oKy^Ux;RuyvC z0jAA^&y%qam{sR=-; z>^43sZCMZjNMFjWuVv1Gu&uCO*vP%zDX^`**~7}MXiF$voVVg|D&0e74k7C!DxS+7VvJxNh{G$d|T)%b_2d7YP2j~boVqDH;HVN8h(f5Vi` zZ~=I_AT9rDLHw*hUZxNbQz48=H20T?wN_hs&-83E>4gynVILgc_+fK?>@dCP47;7t>! zA3Wm9AuDXPyH9Ngm0MP6Y!s0o{+y{FqA*Jf1Eh5^(OU065LB(4KWQ?`|L=cBM&dM0 z`)Fyfma88kXM_Bs@opOw*5fCgt?{jF_HTfFuB~L1i5>+74M6N}iC}E1D-2&7-Ygb3 z*Y@Te?w)=KY+H4o?jNj1nBJrP@S|HjW~YlS(^>RT`e?kd&?=v(1k4ea6=qTI^ckyq_jT#l#^2G>;l#hQ@_h@_a zc(EO$s9E^6B9U2l<}<4~9l>MV=6dvMK(-m1s_FWA&)K*=9B~)0=0=%#|DohH=bJi$ zi9w|L=O;M8V1OJ;P$DJXTCrx&7EGFaNrC%OcsvM2xAQqR9_Nv`JY=X-x_)HvZJG*!-!p^P(2u)39Jx;^)k&& zrk8Cw1n_5%$pbNy9BlCceEn75BC&!f!CgQ`W^&2FbdbEF?CHH27qi{+H<(tqeku1X z7vsAGxX7#4_Q~zl^L|segxJ@+?*>&U5=sP1O{v}+>z>T|h)I;{j-;52xZ&*honngj zsqm8acr4(hJLCBabn!Q)c${QB9jC(;??i@Ob6F!jiceFKZ_~qQgAx!ie1(cIWrY+%T+M-Q z>@NlCa(uL`a5yC%oOzb*JERaO@D8&U5k;|u<>oP~H(})4kRrCy1NU0vDhh={1QFTy zM(VO!$-J2UrDiqK_~+zjH=StTfa{%rdy4$K<<9$FGz9@x#`v!uO-C~0l@BOU+_QCT zQLGp+XTCF<^bI=?Pr#m6AbR;c-tmG2EDID?H*%kQ`-ZTN{6k(wfXK?y0{7m;P*Mw* zRrJ-C(o_H4-=Bu|EsXF&Z7Se%gN4HgHWhOC-S@G`CCLp>|F{2%4g(|-JE;Hl^2`UW zo#hD@Xb*!MwU%`{V_d3Qq?p|I7lWr3<<9>W=rv!xvrj3>XUT8cTHCr4a z$nKdm^>u3#P!@KB=ns-uq-jktz6FdHX+$4ebm-@eMr|$gN|+zMstk<>LBOAg#iHl5 z(zwjS>Lnn=sNAK%-KqOk&u@EB8m_LXliZ?(Scz$o!&lBvUs`=CL2P&k$%wVK-wZZ~ z9vlr~e;|22y`a}|`wHlh#2Q>wwE*ei9GQ(uNM(uGZ6~XV^PpOIQOAd`1q6-V9bixT z(}y4xVTU{j>4}%X5QJ?ODSjxDU0$@?O07GX#>njY&Ix2(NhDN^=HYOE}GEu83bk;M8BXCv23Icj0%dj-`WNln?9?(3y=v5LX<5Kf*F$#2{pMI19iCC zx?H+1poLs7qRk#|Kjq)npq{>W_lSBt zx0QEMW=SmuPx&Qe#wMr1W;#y&nQQ&(d`D=5C~qjxqEtx!KKCl_gi8;Oma2o8=hlreUY&Nl z=(sy96MSl*#i{^+V^INsOn}dP;pHsZL6{!;V6n>I?>XMY<5`)tcvrQyib;2_ER4N> z5&9XctT0IS{o5bymj3qN+q~V~-O(B~IkxbmszJTYc5s{r{A!T^4e!n@UqU;@)ZMSI zn?6iNpmNvtJn8!(YU7q+)W)4>KW3MBI(#;^bBnh2zZjz|geK40(EBCRcX?!O4>d2c zJ8;iOyVsfm9L>!gDu!AYRx{gU$4Kle)TUy`5-{$;ti0%t&R63aYNbHcmCXR|Gw~@^c3d zr-4@jGAGjy3V#_>_@BQ2&8Xgr_P^NJ8Q(u?K}G6DC@r^&68wd zq_cb0IyrB0`C}*F=Pw~P6uPZNtx%JtXW6}41_aD$x2~-IngnBWrK_2bBDqlcGJ$t< zFTsS;QA9MM7BInnMA-Se+=y$9t;>MA`3I|pzD6JVj@jnHhrrp|gQo>w{iXbN9_VbY zqR(1<298s^{Z?e+`J^W_P0Woh7gY}K!j10m15BW)+m%vanjKK0yv4RgUe)~Gm0yP; zw>&&l*^Gqw69~bsUf0jR)btdDl?aFHJiYD7Rwdn`6HwdS4XtG?O$UBP#6m$MFjy>;ffE1R$KHR(gn z)XpJ4OuhrpuyZM!C3Ml$v%+i;T2IA0FaF8j+$@y>adE8=+zr|>tkJm4&GCzQr%#-$ zVO#EUvwjjH&3yXQn*OIndfX-mD)%>9Liqax`F=7P({DnN5QR*!YJ{>jrIONx@yGjS z-$v(Ik3TsLY)5dgJXNUf*TU}JuNX9wE2+Z&dhK*Mkq`S@kr&vzdh7!#5)q$RPVekA ztKiL_8?N=ldJmLho@FiJ{q41ph7}SBlR0}Ma~9osDKM%v-y%@3wTQzeMS%0^8$&Dq z57s}YhpQ5A%hR4$bxJq6+WMBg(e*gk6Fm69x?|XUO4#%Q?QhnRaeG|#FsFI{kIaXG z&a7&>^jM?8IJzpdiW#D&f^hY;Zmk?~dj9e+=g3r_`?b{CS#W&d@9B08YweWHBzO&J zu;Xt)&6!61e@C0S;Fh&BRYxoroA~TNprUph0@cj+6mwlMtCo+{I=K27!e{LokVsWI zT+wzMr$HuWCUCn)WhoO30QD(@QUe_A0>E96&|>X>-@Z*S18Vt0u%qO;F0V(M`!Td#Xrf}Nz;fNGbqU47FSZ#GOC|-F2utY z*8>&z{o?j|^F`IlWml@(<5yDef?nILaL$Z!mB3I2g91zAbxv6`9%CNxinQGKuJ_CL zvwI>Gdw;c_nDcKGR`V6l_P+e@KtssB?BI;e==;VBIaBmL97?bvN``^Z5*sbJpV1tg zFO%*QNDe*#`K(=Ef|wDU61vVv$a);t==a!>`_fdJK7>5+8E-#?A5c&Nn0ST2G0-*Z z&hnu8K;uF~vbpeqSF}z{`X_BZ&DRY|aR@~$1d2G45qp%S&1Jvycq(?slTlo&zVwaQLT- zv$xZ27ZaaO=AD=M@#ih8Rie0mAt@7eDH{Lpa0R?E*EoAKT|Rkx?J;{I0(tTR&<~Ln zQX#i@G@75rl%$fAx9x_PKe8SMGBZm$+B!+|gmCf##M7f-+Ll(^6PJ7dKn-|0NI7;A z8;Cp6k}?@$rt<_>mycVDT9(SOQ{?9oE!sK86MsnbQyvz}k8)X$Umh)$Xzt&+-roH0 zQu_EGJ$gb^E){Odj8l!|XSB2(`;5;wM|#s!cjHSoupVe^U2*2qnU4t_!aPaz~3MyHooxc5qMDI&-S@4 z&2M*MZQNJncmRIYZFz=(>%iOm`yEKp$W#lqNzWq_@B68*xm*Wx9tDC|z2ENtUD|l> zVDzePb5T^u%`u$DdQ`2rv7aGftgf(Ucu>Uyrx>{!4|AW>+h`tt^v#;RV^ULjZz>RI zXXN`h-(tO-=G^zm#(V8l$#mJ~qqA<1E$mTSu437kmIMWn5pAkS#Gt{_CTj^J&HO2k zpa;XnH0yfzP&FuI5T^=H9Aoc^lw{wAvNEzjW5R>=ZK=Es`ru)};&G;jN(# zHqVq^0TD?aRGfXbTWIc{gQ7pb9JDJ{splhk97=fc%`lq)0$>RV;x4rQQsHv3{`*Ra z+gMt(b#~C6UpE4bfWZ%HqTEQf~?~Mv*alwNZThZgo{qD_J&N+-DAE&vdk~Fw>uE9rj;f z&IH?His72qk7Z|U!5|t7>a;@@L%d=;1p30iSnmwf*jrphM!%xzbYh6=T&aTA`@M?|+Q3PCJTc zAQ3_XGp2!UF6ZmF>3RN#w{zQ0GG5$NSk}|3!{Q%JYv&}AJ!{=1cdO?1YD-46W-M#o zqN)sA{6xiurpt9nJaRoHD)RpqJmgaLZcC$b;~)w!)+mIHpVlC8AilYaTaQ0Jm^)m_HV9-I|DR`5cUGT z$AfX<*<>bdep|;1mfUJ2OqaVAS_$js)pNoR+`2k&FudD}T=E^|sxSBm)193-BR&OT zh0PWtakMasQJ}IJCE6d;=hJNUwmd49L=pZ+u=L>m9zU3}6xtfjlKf2PZ>z<<--r;HE zUtU~@t}S}UEz3+En&|@MYf$Vi3qh8OeMoUK^BO-ixf#~Oa1ybrEa?@T0^e*~j328L z=k_x8i_6~`dx=6uclIm|2+-7ZSNDAp;XPP7mJM%9k$i0Za}twN|A}MN5o5_CKzRch zrEBM!HKF>B!8F1&0Rxen_s{+}pJ26JrvSH>mQGZ{Ip$aD}GH zUcln!q3{420hs(?bDfVlngB*l8m!lX#FQDs;^lvL@gzdKKbqTnIr~~KuZ=Q3SJuf5 z7Vnbm(*E3Nb(Vdx9g*x^^VZGiwc)cGRk;tNT?J8vg9Qz$crA}rBHG(ec6g**x0XM- zg^~tED3IvQ|J%|#Y(M>B|J=)Y$?WfKQnV#PAst^a$3u`exVU4rA3sp;Y(x_TEPK zNA8p9_=kJ+-R=0DTvc)g;AH65OZqAz@OV^@Q+45I5g^%D>50wremaGx?sf0;Vnhja ztrIDPmAQVDL)i<3)a=GSjij&oos8YR4>bR&&6r(0%L>vyHM~)UPq$60)M^^^0PI~of__{;Iiv_mc{=%aZ;I8!rsCkV z4kB+fAEj8Z4Wa}qFt8G=JyZ$v5y6^rcu2{}Mrz$H#BJG_x9oB)Gm*?eVzYI)098c@ z9wns?6&pGVUrG$#yTez# zav(fKuu~i)@2_t)ag1rT0SuQH0OYK05Igno@)T6&5{jUf<$y7<_F9=>0TDsO2tZs6 zqMFRZXvY8sQ&R-;afXru%7TQ0pK=o0Ch2$>UGwjGh6~eFj9j$sv<93q+|cV6=Z6dCGWRcDKO@k_Dw?e;j-NXjjima(kY~PCV$U zlLfm}eGw_~RjI(E?Uh#CjICVpk7_oZv&|W6e+^fiQ|vEepFU`8fdb1;EIW;wQER)` zfs+zEZ{K!M$pm)H){FHX>}^V1?R{f&*3Y^Z!DdvzWdwyHRBdA3GsAmi6Wa+`<+9x+ zR7A%7jOHzyBx>*q&d5GCWd8w^)Y7E~|SPl3y8wjvqktqqT{ZJa+K z8Q;&7YUNwzhik_2af8Zf9%B`!qWt_e#>z%!v2~NbyiM@=7DEIS{s5Q&alWsw)Fa5K zxt3g!z*wyJ?Buuj-K#zy$BkoYs|}fV=IOjt3WV<2iah@DwYJgLtb*iKSSjo^kBXh= zcSX&B3ko}brmSx?Zmg87j{tM}_6|BiKXEBT0YHQ-HcR;{a-}_& zivj*9)W)O2noN+zj*)g3Ur~IF^N5)_t9RjTh(Nf3*hd{@hacr0KxN%ouN$K(I(;6a zfD4&xC7H(7#sT8d3H5ci{5v|llinigXZ-Ax0{12ljSnZYdd6>9Jn@Y}bMFsnf3LWH zZbt!2D0gQhDHr#@92v?_&9ri^Lp`19_!nFt6(@tS|bjhm1pN{BVa1fTjsM++? zw<`JYL7AD9S}FCBkRnBI5in69?Tm_>Rb^&66PU9Q6wFDage5gQZb8Bs#LR@bRkWFa zbtQBgN1Wim5>$6fU$sW!h1v#N0BIVfTmMc+gL6p$B{W;d8g@IzTBk^y15Re314FCu%u|^{94owYE z0s8}izmK<0`n!Cdy_3J5dER-tz2|&;N%qitYttY$%+fUwaIz-(aIE%xFIiFmhrFWv zC+=r5v5JWZEz2Y~GlxS)CO%U)Ygs~KjskLQY-FJi`S|^>=N)_ToyW@&48FZhf-adR zl|Kncg#clK`qbrWwOkk`a%I783x^YGQQC93J-4zESz8_Ue>mn=Oxq!hI^;)bmRwst z7Cv)GRCyG__$Q<&q#qJ$THz6{V`S%`T^>>eYaj~1Bv|qB)F)!n|48x!n3?KPVm5`* zkqISyWCCgyR$5SbWo0OCv6!fm1(bz1XYLgMoG5EvZll8-%4(N@)dggF^5(KIY7{qD zqqc@`agElQ%r*m>2Il0GH|jx#Eci)@iMRNEY|6@GPv69;{Sfn89vB>|WJZpwp6XCd z_)cQ+(5TJ*T%JtE&(^o+Yqg-e*XOELF`tcvox^~uOsDp6J1YOr-O)a9ZCN~Q%e@%& z(SkE{kLM0H;_tQxjN8xnBNn1~`8q10*;fx(7kgn1(Zpnm8~G zGvgM;n)>U1wE!i;!L+W(r6(s%4MXPf?R#~d4@+du&gk>&zN0VAJK#{@hjM@SNOe}t z>Gy#X=$CtaQ#yPz@PlEu8-lv4T4LkD`>)fz2kn=h^#5T%R?OxuigWR*|9kJRg?9~@IgZWrd2WxUHK4vJaCK<8?#IAYdLKtrsT7!Bb)km zzGb@2J6v*HE3L3Dtr^Mu^ywkLfLiwS7o>?9O!!B#ZRvv`8o*!i&B{G-9N6>7gUt`s zooBs0J5~Em30;vtvep~=uHASfeNXy$yygbdid-#Isqk>MgFz}ak=BQ2K4_o$Rv#%z z1MlPvadxE;0)IN9(E=g_h$aS$xyhNF%_(+wS@6&KeS2xSxJXJ4XJtz7{ zIMYb&*qHi`AypxeF^HT^MGnTNN{KJG0UQLG9eCSYKRDk{ka@HSW><+stf>CVf0*jL z?V`|>KHu%Bd8?A=mJo=sU&csG_k^mt6#va)%d3|Idzy4Qm0N~Z6+Mqex4Rd9ZFhOn z=~G$f;5z1cfaG9!ww|Q9#_3Fl`#Ii!w)D=WFD;TR=2%f*5gsu$l~T0M9Pjk@3U-n*xz#DGEsqWlYO3M_R3 z0;`TxKOPl}z{e;H*ZY<69O403u=1*MdEJjT6LJLOiVQ zLQl)cY)(>OyZ;!e3gbcsg(F_!tFGQC!1ZL40=y)jIy=XR;I9PW8(~MUvjpMsRCC{2 zh)YO|8}pRpS9+i>zdJz8N@qu z{z!oImspx1KE5Uj&+Qr-Is4@f?zB(w1QkwW3A{RCDs_nSG+)l!>st*nIv;QSOa(sS zAp^oO{IAm3mE&S5UUMmy7vziGi>2e)pN95CA3yrE=M`j(9 z#k{I7_tQ2E*hzI{8A((q!$X|Ck|zKGl%*I67`V)O@b6~#KfHBVX=|E#H+GDy$Qr;2 ziQ~9xgCq~hPP2nwG8>sIWEp9k={3VgCc=gNr? z5BTyqBvdAF|HTJyy~EURSU0+)1gxUY`^Se2>r?zMR}p!&)E!U1+tUqaQ6%($&1g5P z%}-$P+Zk_V#rKH(LwLmHXR`e5f_pV0^m-7 zL20;>vnL`q^CnA62gX=N)ht^ZlLU6zGyL7wxiFKGG}3R6!DIcF`_XQv)7qa*@iWHg zrWS@m^3gVmW&|0;swqT%4DgTRGkn8MWEmCCiiwH2+#A1r^p#*L`}0^5E-q`yfI)(& zQXQI>zn?_m_pkj-Ow;om)EK(LE^^tw_i`8a^0M|Q%n$^sE%1kL`gUF}b$%D-;5_%j zjsTFV$=v9$Xx`e#vKh9-@5P>a{&vvJq;I*y9x5M9I{R{w5$=D&+Xq{5xRjup934s}OG-@zcr=mZ<+qEG*q;a6~ zf9IYVVT2h=m$%HL9g7OZx5aER3LEurv^r(pa&vQlOJQVEImrcIIo=j&r?{ggZMBx| zlvgU4nM1>X;gNqvCP+8{gc+h15E=lDF^UY_@Iojlt-@2_V0CNh^A?Dz8UY%FSTOO} z#2yV62DO-42rQD?Wgf(QBz0q@K^4z6$A)zj-Pa1Fu@Xg@L6bK>aM_&GWd5Q#a(&3M zFP^I5QvD2qV|$-tnlP+|EwYz1BD#bU@y{s22SHZE-raM9^liDsUJ{e&75m%ub#ZmL$y8U} z%?JVF96?AJ8B`G2YH`!?TJ?c2B#V3aTR%qU)&1Vu^I##f=8f|khc?cYcMeZt6pt(U z`QF+xOZlfm$mMxX5mnY9;j&&_VxIRiFRiQY3pR}Y;CW+kZ6t;I=rqOrCVZYi{Qi?M=O65qjghkGc<$F556yjd&Rf* z&CYUt(MLTxA&dDa%wr@blUg=eibH0>8~r=Osq7!>o3vyXbKS6{N!2a2Q;s6bYB9UX z#ck3vzYtXS!(~ybl7L&PP|9xQxHzIZs}cpnR5xfm9bS7LcvE*2zgQU)<~D0q3L7)8 z%g@ix%7Q=ASSCq3wdY*Sn%^knowiwm!og`zrNy1@-VT@mG9!0<|E)POvFu9!ZHHG` z{R+Fqm6esd`6}P1m@sT%;tW zWz{fdd<6hOJ)IPf3?mb=IpSzt+do>)8`ONCYNwOaNowM;c__V8R%BabFNrU7uEP}= z!I{M}R7X?O%hYFG)8yWmTFB^oscq}8>g?I6FW7N5?FOH#j-5?kJ}Om=8xkzmMX;`+ zS2a1L4wPQ&`FhXoEj7I0cmY;*23dd@IU&f%rl3))zet%!gt*4_UQN30HJZBt?nLS&bZ z@ZQuvYyG!RjXlz)W$*ehMf$XQ=J(Y3>hN0H(7!N3cK4T?-G8^v-}PiS=G5btPBz2- zw~rLUB5mGh`zm#@C$|f9I&WOPI^pDAxLSI@pHIvW!$>JB{LE+qu{nbME96(lLH*(8 zObOuR>r1+K_MVUF&Y)>MA8ZwUMe}$3>M&REj#7#Z9onqJrrt1jRLVpPFIO&khVV4Q z{@^aRx*Yv&eqQ?MzWD$9$Ud?L=Os!|A|nAFh(OWdhA}{!#ShcID^Zkuq%8%Akum@h zaq&74-u@pnC$3&o2L4=WEasOx&dqfVHqlhHXTH!1D6g_`mXe10<>#=zXKV||G#yHjN85L{_di^Z?5It=Mw+2Zi!&%ck@ly zK`$mrs!lY>7?z8S5X|QiUx=Pt_GeHPL0_97xZrm6_Cvx>v!V(>avj$giguQNTT?oS zsuGc)K7_lv#>A0rFAmA6Jc1J_v{-z!gTkqdR8;NBsxu&sQ}e=j(!r?l@o6!f`IDC3 z-b*C#G7hu3JZXSrJWIH^f3?M(xEuw%bv%~V9{2RU`0q4Gyj())oV@d<%5UG{B}T*r zI59Lz?(o+CkQ<)0^k|&}P-W@^JG;g{P}7sq^oo2=4YJVko+5w!%l>=@_neYrhFMzb zt50fCAc1vk&|~62*8RN!ed*n%Spn+IQ0v6*lFoLQ=kxu|u`aXb@|2+MM3(+v2JGHN z4%32pEH&Dj8c;;`~Q}3R`<8(Mr1KKblo8Vs6d4D7jDGD-P~ICQwIQ1SCizvZu{nwlj=H0)Z8PgsAtx)7Qp zb4!kJZSt*t{yMp^T&CFe6g|CaO*^5TrGywNE1AzZtaxtqulydeJ^Y5IyP~@1OU%}8 z;h;?A70}${GUw3w^z`OZn7?)>N^Pt;ZgZ*VS_R2v;=?S*EP5TZ7nJ2 zgH_iDtNiV({lGLWJqpgrgLU=f#9%E52A34)T49W|8B`Td9SmLlVw%gbRY8ZSs}p9t z6^2+vBjt(1z4_vayL>}l!7sZvL_l}|?C;-FJapqN`IG&%7`IAFut5Xk)g#fDj)B`- z8AKHilBvvdrS#v6}_Jqk;4+NTdnAsB`YF= zrxB1o&8@&mZ-S3m%Krb(UV6nChVgh<=cNCRJ_aNrd^9cWN|;wcGz(EO*H9(3q+KM9 zZerK#cvvPLx5v>hMw)ekCe%?)5ASddsb$dh!)vl_&-7_1A@eS-RD070d)|xAup0x< z|N2AALf3A_!UKTF;Xu?$%D>ruYd%X39dtiWPR{CzE{LcjnJ_RC;d)AU2(OFW>cL5K z{o2`_wCBm;OiSf(Eu>dOZb%&72?o1O%tvF9@&LjMx)x<`WN^vhb_T@{dRWx}OmXeR zE3fC37stA!o3|t=5F<3OiVKUNdPCKb5HDR_<(eXYXozJk&1jYzFjsF}sVM9=*5TcI zgH9J$cP{q)P@Zw2ySvuPw!Od7dtVCw2bT6NJ>vbl@9vg~9efVH zrE+q&XT3}gO@BOgm-!i0o@5`(2d@gzHdFCZ%|LTIa0>7P&d(QSW&dqz{@6H;nj#U! zOP^c#I?89Lk%pndMn3U+7ZZVabUN&&w4pGv!QOTE_;q+S<9YF`zJ;Gj^g_A$neWYk z{aSS~jart~a4li$pLis4s8axp5<5seK++(Q((}*fmoTqEDHZW}e=1oNY$h{JTdfa; zY8FF@3~IJ)Lrd9y?qwM+v7G;^Zv@-g3K{;x0M}2R!Evh_c7xyY1Vy{OXT*dCj zRwpm!AIce0%bKCk9kzPAC6BXqCs7yaw4Lv|;^ZdBExXIJIT2{6|2=-8=?PTgZ!Bj6 zdyn$Yt$6RIg)jK<`=qSN=OQtcns8@C-y;(K1LMn4MLN2!>eOys$f!n(CYwdwKRNn4 zh-NqG+f`hwS}goR$BGZiT@^%l-V{YdkTgN4$ooFPdQNc3srlzrVBer22pS2_6tuR(4KvdqUiswV{-xOSCp88l{0p2UQz z6wP0s^C=!#QN)88yDx0{vd1eJ0UV8>kQfP*63u4RF7J$;RV|2`stW4v{I^q6Q857l z*|#dBs!%O_xT21ClU0KPMNuKZokS#w0w<fW{;PL)6<*lOU>b|6EpkM(YUo=E;e7`X)GUZDV~QcUM6p_MJDxqFIG3Ul#fGE zA>H2F$cY4?iVM)Ms9gJn7>w|V{vQs}#&fKKpBml2R>Bc4XASi1rw<~;eSEII!e=eo zo@YbCCLH6wDQ2@8`l*YJD=To)p7K)$#cVR>f6fz<%vu8Rq~=#p46d3Xho~Dwq*uo&a z^sbA;AOd9wz>OGoZ|vtGlKqZ?;&i3e-QjG%gvc5>n8Ze3+g$mBv!DBKI^o8 z%`KcN@=GMa5z}dR@jH4qDi!>NMoC6PS-#ZBFp#I7oR8zbolnfJZyX>J_MC4Ghe^=L zBL^fW)-lLnVc_X-m`(_1Xe0H2doaVvBukEFd_={Bgf@Suqo_j?WhK=_u==QJ5yE>G zZ^J%I_rmPT8}cWCn1#vZ4Z6Czh+ZBdOY@7%?T&u+?oDsw#4aL~MILhp%8<#41iNov zUuJMMvhU`LKL@F%RWRKxbv`dDR6XTjkIvrQxVj$Hz|D1&^rDCX*&a94No~t-V@{Bj zSdJSU{m*g)1s}ZccrLpB z=O}CR--#n$=U?%2NnRQ=c3V3#MP55@hapz)J!unGPX`!cJA7~ z)c_b=d!u>@i)f4DgPZcvcXUnPpe0KYXhBzwO`V*%;LE9^%VIy?QNaI3h@k&+x9IH+k%J9Wnns6XJj!EVsr=yv+l{qp>KD<29CgjuRV)y2hm z0*pd1shL#OA|ZjzNSHZOla?kTi|=CS1ho+4a&jW)8|}bUQu)Rroc84^bmF0G5-Y9) zXt%d#D`FyAZ{NP7c>jKE_ak09+t*{RuhU%NoWx%ne|m0SxMT>=wqmbaVzc|ahQSq2 z$5JcJM>3+`tVFZzWIQI0H+dMJ6O@l;FebGWh}kl|4-Z`Q5h1eZr)!;6h`PGu`nIa= zZUHhe@IfCKArYZEpoGe8#0(ErQ9n|DuEB1JM-fQX4`gvnuc8M>%#Z||f&!+w7~*;R zwYHl0ifZ1#=lso=HPK+}ifhk-x3@TYKmD(^DArcfF~meO6D>#aAxCT z5Cg(1XV?x)m5Qb!YufDMimhAyV?#=EfF(H$Ibf?5yL=ptH*#S2RUHV}q%|ZEKQHT4 zZ)LvShf5d++c6d`J0hbARFwjTX5P9HxAxj9f|p=&A+wVvQ!y1HORUv{fut}%yAD^n z;^3zkH)M@21_pqzfbIHe)^l*`%gg>t)&ke)kv*aDcDT;?p-Gl)**nef)~OSVN<+Vg zzl6F*^b@pN%gw%fI}R+T?cpb%4r!f2dfkqrBQq#LiGi5Dx+YrP%?IDwNJ#fy&$+Yz zysM8%HhFlYXcPUTQ0v#B6^|6F_;*pRh{@(NMgl_!$q}}`s9+|ATj}bLWc|677Pq7R z7;-oLCMXgkI=2fl)Lf2{^a!L1A;FEGz}4QnH0B`_G)(#PI zt8PTU#iN2oK<9im^uD`{pO`*M>@IlRRFF%O^6rqhlZx~yU+e`Q)9d;0aLr073!=l8 zL5{-c>N-Jr+qAOr&s1ZS{p480#m#*xKt>>3MR^&%o$=hd*Lf`xa=6>n`LFY->NM_k z={5JAqCRJ2I9lD#^Y8p5>+kBK4>fV$V4@Z)Up3xVr8I|*s+N8_AN{WKT+j(o0BV$yNS1`T z>^Rwdl^={k;@!uzu0HIt7faq(I7T*HYXR2|%;^viQ9$A-c?PW149A(RDzO9klco(i zJZ>{Q(5VK+@;_LVsb*{rX@^4fh<*LLeWM5VyL=UlSh(WivcLdX$j`RAeaxI7X_b)1 zVCf8lc295rv)Rqn_P)s%*d%noO*T_#y6{3Pf41~`%0-i+-S2w2Ip%E!Fv3Xmjr*#H znWqQwR*(FVM0hs<1QL?%DX~VDXkcliQR7mB&RB>&K5AC!ZvwTI1_pBNbX5*5;Dw2t zx@`DQxK|j03jj&uGqY+aoH4i*!Cd{E+nSo(Jv;<5Mj4Q0Rq>*@FmBOO!quTeBsn3G z#<&S^Y?5w4?MNL9e!`C*2)!Pt1m7-GtCF{du0OIrViFO4qThXKf7nSi_~m!9I5y_N z7fi<`csZC9Cvrbo%x<{CqCgqI7sTO;cwGxmf#^6NCC1J;&tKvfvhu(EJpSQ&kQXfn z6aCA=#a_qD)8*RJ!)li91Y7rh2D{H0`|HE&Xw?VNg%vB(Sj{psazyTGTf+=*$?~JF zP2@bM($7Qy=eA~DiZlElT1{JRdLc&tL>k_Hcq9qv!WB?JF+(XNy!^lNew9)8VtOeD za5Ux^;wxnaMt;7C-N^2dd+N}(Sqob{h`&BL zSCAl$6^bAP+s~Uzs+`uK^Vjp$l(Jr%W9gs~;{>wD)+qmf$Qr+&k?e)Bx)Jf#wT)_n z7#PZ6vfAd1c`j`1k;?uLQ?0F26M+=nHvBh>d;naA2=VA;+LWm+Dj1AuBz!P>ge9V# zIhvCyWNT|HI5>F0c6K%<0`yCPF%aXR<*E_}1|UOB;jJ@#n~3ky$dV^Lc}E~H5_ZC` z;Wh>rtdBE=4b6S&C4aDAp^4oYq)l>Dc-g9phjWppl{g-3-VYHqf{?oau88~&@8F(G zW_|(lO`FW-qGZk4d#`yXD!`QGKn=`nC3kg0_78~DLdTuc79J?U`cV?7(~ zkA^Rqp60Kc*B{AeJX7bjDBsB4*sm@xu7*+)&XAjdd<}RJsDuWRV(c{L&-OZ>jD@jl(~^KUa=U30`lZQGhI3;3F~Y z3lpBl4b#7H2HKuAAf9Dm<&B%x47QN@YMhmq4X3PI|35E4zm{`9L0`$>ze!7;h52aC z_ajQXQ2mM&xs(2WSChwOQy1!{c#C~pISE1_06u|FnKg_Q|NId&*&FtFYrpo($>*}) zhd0|TDn;0=i^L8WPtls7R;iotzQHE7%CMD(41rW7Fh6PcV^y2a(QL&$?_ZS4!=74a zNjU~^?N=luD$=O%9gk$Q1$xo@q2akou3*Y~*38UI8uNO#eiAiX6In)38rrvzpLDVX z$v~>QG2OZ86YGv2*&~umCDzfPA10V!Ng&Z&ZMya(84U`rWq368UgjvSqQ>^Dpi-vU zDlyy|K787o#p1r#cr1tFi9H4Kxfg4L!wK&`c0Mnkj+NM%iGbZ4c~TFO%Y&D@pHbRw z`kzw`J$D-B3|igK45oODpCyeZL(4R)UWY7R@2HjSqk3vl#R9kTAD9jA|J}Zxp55(} z#Lu$AT+kkyJoCd1>L&XkH4;;$DBbzG{0gb6h)Ox=Iyi~HMoJv5tltcNq(=+;HX5#8 zvqJ(k1`;5O%k-PAYV9RmT28HJ{ZF+<;-Nq!b}j}0s1X1tdpjh{>raJm3G@&#|@=Oc?K;yyK;hF%lvuB^c`cLxknsD~UT-2GU8!-pSKou#$6G(ZoC=F&l5Zkh9aCSQB$(fsMZHL5EwKo%3F8X+o08GLvA@#p>iXJt7w z)h{MUI-%^oC&Px1i*xn%IR})SW*UbWMffFg>vZe|g6`K|+Min3B*m)*X(EL8xLr9n z-U^vWK$AR9B^9~eJ7g_;<_`|H=zC^=#MV&!q)!}?NSjKkFdJAS9_+rE+OIq&%VRnfuGMk|*n+zzliPMoi7*6^TW2OYF znC%)6?P-6B-uQ92W6ddS1tTmD_){zT62bt-6tk4WEcJ~M)VU6aJkKf`EE$+(M416K zXDO*_#xwAXB}<7;Ftgl4gb(q2)WNTgW!NIymnfW?CP^51P~lI!P{6qVhOVL4%Tbg4 zn)l^RRuPu8VB>75kz@DIrFOraO?t7L3m0-+9RYq6l)GJbc%;syVYC11Y4gDqaEpe$jzZ3h1LAOO0+w^j|mx!Bc;nBHw{X!H|;ya|GNNI>yU3hDa{Q)Wn*7f^q;A2_>ZZd7r=- zPf<@3YS{{dEf&F!Ztjd;;R4xL=YW$;+FF93a87``5vc7%5A}ZgUtgKBf$w&YB@cW{ z2aW!Gvy6SE?OujB{S!R$C)&xB)d^1tJ0Y`SEYN+QMGMWSi^TcHUG%v%Ulkh&b9C_U zfGrvG$n=tYo^s6-x5TH1s>8vrHu2>Ms!)LHOddmdLxc&G{b+{ERZ(8z@hfqAxXiJ) z6Ei8u$x`cE8hWM++c4K&Cg+%iv<3kL!U&a5c|w^wM{;B}4i$3d?rKT@#D zi}Qwrl9C0mb!WBzKJ&RnGxT}6|DEp%EFICe&9LXaCHhLY<>S8hzW69k)OlxTVt6w3vbz1Zb8woh zhgwbZtFs*L9%vU3m5eCh)L>?=Imd1ZKWAQ;%w z(xC(y0RzHA%c=IFufsgGhLcw_+T4J^Ypnw80<TtMl?KQE#UFmRYW>MD(#{I5MNjokl7ZF}Awa4kQi&Pe|Rz<%- zoaIt}_V_d5MZW*uZ*7nNgW){|S#X$zK-_NuF^_?bz3UekCLkOYL}DIvKV1la7nF94F2!YgD&zx8wLdgk_m)Gr63jmPxHgDZ6MF zZBWt((JY3p;tK;R@jy?8o=pXBiQk2(SA~B`?jFrRGkl%BG<=%Xv~Ty5S|loivK^zl z^A#(?*NEx0yr6pHhLVZUca|FoGSuWL^Z`E))6P=#B~fkqyO~M}+`0;jPke$uP6af? zeMe{j>dytb>8Bn-HDfDoXLSbKNDq6F{^y*FFAx$cIaE<2-~t%iXsy;}X3m+5Q#b1k zFn$qTQKk^Wa~>oh;y?f)?sr-~#(Gw8UTp|29CxymqVic@-x4PD?%gpQy~(fG$CNZ0 zvuj%9784Q9qb=_#C)`@k+x~B!T60XF1(`uo<(Ge($JT1ba>HLJuI}$i27H(lM<~s= z+PA?qW(gGNHo1cfJAgk^3|KOzf3#lmmPv|a}nvFN-UWw zNdW+GqAK^*@&8tvTFm;$P?gDs7h0PM%F5K)>qPvANar=3En=~PFyn|dB%9eS&i<^^<+-O()+^6za76|KX48x45DMYB5h&vfG_5%?)D1!_$z82jw8;ZnGW$ zaag{8A3TwG+r4KE(UXsgvg0{xNLYo$zCRv zMMV>v)KN<^SOHI-mF% zbzor`mCMfwIVKeXtNTpvl50&Gbeg(VwH{1JD^Q zo1yd~8$4io`4y3b&Ww@oNZU}qurS=Wu=Z{*2MamW`y;(Wo0Ey3E5`}bp*6AaW-JX; zWDo`h8B7um8OO+No0orU5-^-v<-0FM!6s8UY}6dIbbHFDultFwe0UMp#K@cwKx5;J z3iyK_Flx1i1+I?$Co;}8K635s=ImUnH=<@K@eLQKh>Tk3ce(1lJPnefEQeXSaLgS8V*2T_dxkbU-$aB_LN-(SAv{ee}J^&D=Tp& zIMKM2zF}79=JZhYReo>GiY>mh)^5l`;~>L$lc0{?eALE-iyS+vWw;GbyH$MGjB^Cw zKoyYur1lvw8kNuxzbI5rls4LBmYJ8RnLyVsZ=}@nAx(w`L=`WZs6-t?*^Tj$6T5;s zFIP!~m&yRduiqmgx;bwwTfk*J$zCOOR>o(b1+5$ys6OjLusH%e*0!sig;(KL6(R9rX z>a0E4FGCh=25mq9#PRXw1P(5ZmdO`o$g4c!b4@_$#?_WofJmAKuzooskxon3M@fTCp<;jS=!?RqUI>4YtYor3hh1E8t-M+u!YChjqUx1?28V7Eq}Gs zh~}|s$Jm*t?usGjfB8>L$oDh_nNYdBAJMLOCINxR-$msKw6{_FbQ5*BXe2k zp?sR+&-(MPgV1o{pV3xPmO|I zsrI&0%IwcARX_D+R_5c7QrEG5c zk4m5bStwzQTgt>-S>MggY4gg;q$P45*!k!tBP?tH_9-zEJxIzGg#cgEUXkys=+ofV zRF8BZ?#67n-}Tr^QtkR}fr zf1ZAnUq4#&+K4iI`NJ&c#aJH8$uqB^1|<=)h`{50!`YwH07S*2x-ZC8SafrGYcixJ zr4EuFVO7kmfhF{D&?9~N%Z_r@uk>-J4IbYn-phci8kUzBz&QQgsX27sRi92)QUc+v zw9;&=hCsX`ji;bIx2hbI9Q0dYQhy2F+#BrC{}Uf`&b|fC^9SyaHXN~k$5oM7uP8wi z|J!kS$=)I|U96RPUF=aM#0i6uiK`<_4eO~O)0Dw1-boeUi~?x55Yt1T(}`4E1vy=w z+Lh@#pW8eR{`$WdKHZ=B?%s;M-jDlVGmi_K+?+1kE~fOGq<=F0xtD)plS_r2Ad|Mo^o|2x$W0<4euJvo?vDa55IO-Lkg|2a=je{u2JxD|UwBOc2>^0r)S zaq}0=_CAYXaQ9Q40UJjTRn)P$bU1pNS5Wu-4dgb(gzFVevN}~McJ0w`VKde>TIw@g zg&{bK>d62P-}kvVM$|l}g93YPw{Qx4rn@#F$)K&Boqn5#lh8YANnoa@Nd)dBfTJr4 zzR3+wHcDl0fBGYH+MF)eT7auyI`WsC!>;vzBPV0p0-pX1c8Q?Snm@@)S?psgcl*2HXHBp zqF+s`96c{%>!KxW%}Ry4&Kl30P!)m0eDHtOr#mZPyqY47!Tyz}9EmEVPnzsu3C0-+Q>ZEwA9tmxBSQkt}eCG}gj*t3%r z{ShS&8DOA5JSvKe3gV6%x7gKv$&+J2p|)u7Sn(TedLh5p6S15+FKB|MryI^?6MqA2NIyskChy+^}m9K$N} zFqy@6;ilo~g0Fp4LVI3OC<&}}5#a!ChU|C#Us6aUmvT|mzV`ysLAlpMIy8})Br`&B zvnuKU)cDB~EjOrj9v!NQ>|C~P3G=?rmhe6YLfDLj3Ig40HDMUw#yuKKi#O`m?+4qWkX2UuEF3?7`=y<@xcx zjBI@U`r%r{9=Vuk1MNHel^dMF2tDa@VkbvO7$VtN78rQ^WGK$IJs3 zXOFYg9Y;rJzAHWx?c-nJ8ujtax$aFxO4D0N9DI(O z<4*M!5YRdbTD`r|>he7sTIw5;9BkjRXhej=pC)2$gI(=}d$3Eh`|M&RzYH~*iX!K? zq6(s#QrP{mC0roe20~*vIguwJkiYKEsQZPSiD1Ma&_uHFuFJo)0FWJ;E(BZJ~7q06;!OB?p^BBf*d10PR5fD#uX6P(F|86EJnPQ=sRQc zzg~HNp>N>d`T1LRF7x{!3631(fSe;DngYj^!ix#zM8rz|oTjr}G0_r?0Mr1lN2|F) zXA!@fq;We#?@g0V@4bRjzOU@I-}^Msp+Ru-JpY=9+gHbNg=)Zwaf6v6bQ~+kMTs!A zjy9JYm#0?NIGib$^ey9~FK$(z zNybai8U^;{2*Foa2|-^FaCtCf7!jCMxlk|P3aVwqe^U}G2+Fg}8ciH+ep3<&w8mAJ zAQ4cVQ)$Sn%p>4bkc%tJmHmsk72DV@*InK}QbJiIkZvIK)L0`(O7Anig5r z3`fVc4?M&iZElDvk19U|Cvq&?*lcM$32o+FxZzB>ZRKiW&_D7S9S`9~+w^L^GOZcM zI>)Wd(#*VmjKNe;@`^Zn^F+z1aP7nAlTpiyWjnz3S%XMiMAY{FUqMkc|>n*Ds6&7QGqig-z*Xsj0QC~gf@0Kf_r_9%W*X)yjF()>MuZ&uBf(c8Fl(z1gThH1dMRa*p|Wom z=@u4w?a~loh`>C=+^d$gc(SW4C*N`y)AKW$9-4}*F)r0ZSgP`q#OU+8f6@OnC%$iE zdHN;o=mm=yXQK!Q8cmRiKm$9&kH)-{{V3G-a9SAsy!2mG+~czEf-Nxaas#u>NV4s! zXL~WOVOTEcB@yA#HLIpTa=~e$)aG%}UzmML)N=aY$E2;`nsF>M#ih{7vB=E9G2*g{ ztV`(9r=qlg``==BA2C#7ZI^nomTqI?;y{z|;KOizi0gUMeFg@^9#4!^qbH;Tj9LNCHK5OT#q!2e)EdJ?r z_;kvL&>Ne@Jr;!M_(>nLE-Bc$K}CtGe_|GygXy1i>psq$_UBWBKgG!p<_yoP5#dRp zxW>_pg;Pm=#d|&5o~v%!bMx?g1UwMwXY$FsAr$9tskorro+KvnBgfv1mtJ{ik4e7Z{Xg~7T3xr zdg<`ByTi+<`w_<`9p3zk80XA4KZ;<+@0?TP=rTrrn0;dsdAx`ddzqe6Oe)Iw>a+}x zb*MXPVPS?FtPZy*#rYhTj4H5lu@uWVOCU;A4T?){ZpX;UCgGex7%rG@(3vO|O{)4M z42I%WDIZvvavW3IizBm&!M0I(!`FIFMw!BfuO=p2PknFTG-MZKmH?(P5@gGkUzy|I zw~o(q3`V3r+t{|k5()Bx!YTg-cY8ih_YCTmFo9?lsX~$^4QWK(VCB+v|B=Pde1RLR z!yblAbX%Eqvk*Gp_3a98QTN=kviZirp%P#uB`&y(=DX5@gVKWVaWq$T9sq-Z{>v_W z;WUfHudy?GJb>uf=JJ{7x zR%hEiJWinM^>EF9!{OD-B6BnrCpMPY^Ji)jD@cMed&iBi2=1p!&3-=ij|Pg?>7zY9 zKGwl^SMp)>AH#-Q6fpACd9h%jxROh9n12uioG=nTPaykJ@wvh<5+ya=-DaklcS|^{ zY2sHAYQIvpoiOAgKu{n@1i&Go)aLTR;mO&XQ+PrKYc67mWP)&10H7>s!P!&KOOqW= z({*as(;^5Cpe&O{u^iVh`DtY=N?Yi9lPd}NBFC7ekt}^}H)FO}%fj4J8O4cMzJ$+I z9f>EAV#eq+Ag2mIhae1r3n#vL5gy7*qNNv%f8-?jCM@^8dLh$smxqMFR8wFtC&u-_4%zdjya-M+^wN0AY94Zb=c*f3%`HH}85^EKDZ0v5KyZ=k}^QG9U#p{9L z^UUkzZ{m*EKML%PcEdq10>nA}6I&%y_oAV0^OTlNT}&s0K(b0ZTYCGuha#OG`P z>Rc@Go^i8`Mk!{kt*yjtdh^T6>fe$B0GS8?Ef!d%fk4PS-*N+))Zt-#p5s+`35&et zh!lP0Ej~V|Z$1t_@2%jv66{_MGumI=S>jLoZ1O3^Y|PAtwgR~e9Q2v~$Hf2h0^|YL zxygg<76BvcEa8-7h{%K`WsN$jb4Hl*A%mura<-q#IX6su(*_80N#ItBzK$PR0A!=V z{~39b+=T_Mx0bBBy|M5SpxDeMJ7ibH`i*p8i!-#Dy=PQ?=6%cNFfSYtAq&ykww1>P zgbWJ&Gdpc3L^ii4n@rZ*P|dZ;NbV_M`6#`>GwOfO{&EDbI?jCe&N{C8*gNhvqwJP; z?@21Ccom7WJ#X^0QyNqef7eHR;@hTHEkTMwe?L0Kogy}Nxr8A zngAh`;1M}#07MPGPc0QH+g%F?M8P#zj8Lqyn{&rhNtgxsnASNb@1Vqw4o}|0HS}yT z!(AFg${Y-qu86WeJv`<9zLh11qIp3iM%S_(z0U+nvud)%mzcgb_vVI7N{pn#y972= zrI~Jlo+`LyFd((@nsNGIB+b5*qN9XyV`%_E>cBwF0pFj5kV++x(jL*X zal^HwkU6w^_TPbgtHEwh={N}>WmsA}<+;C~1WFf#JMW!sVV1({rq9icKxSgRL~4S| z**jsO4N*A4iBBx(kl-G@ITd}FjB{OV+Sy$g8ZvchIx=?MrTOaT5{%=sAp>J9O{}I4 z3umOA!mP>XF5MFxv;F5*@I{lu}jv=|5)W zyVrT|DLT2zBl+`X?=_d(@WF~3LMHDhl`Cz;e5$_WdlWz-8Q_GV89%R8g7OWvOx^R`?tSLt0ZK^F%>@u3 z6YUS+MU0fl;`on$pdN2MTXylf+MnEF4fo9YLF@;`MwEd3Ang%7t8n1}$*2Eb*^<4# z2`^kM%lr9eF3QY3=>KEtD+8MR-uDrZP`U)A1(A^MZfWU~j?v8s>246o!A6LHw19Ls z$VPWJNQ@Fk@4wHte*eQ8UhK`zvvWW9eVr?8O}Ucw3R1GE=oZe_6o6e!`a~k<94(&& zrDE;_2^s&a;BIU#ediMp#!Zt>D@liPME4`t#^1$j#U3RV1**pLB!^ntA{JJq= zpUcE~8P1n~vrA{vA_~!{Xw{$H&kJz1^IhgRg*#U#V=?lAG?p64i8tT6Pw!MKM4~lN zJpf;O#^ivG#1F@xzmi-aMH@EdxuiO`G6VG6$`3yIJTXI3k?taF95nR$R6GD6>_ChW zZV?jSao*oCGOau&Sg9m%a&nTP%(-H!hl+)KIvS^As)E=B?f%lw&?NH32FZmn+JYed zEq~A*a{vofYAmL?B|BsC<%?e&ekG`*`C1G4y0hx#T2WL&-U7j1HV96;dgUx%e*9>R zuiYvo!?I@L?4i7UH94e+M=XhdcDHDVP%62pEaSb(EzcgWRSsV-=|F?;eOt)I^A2O< z_V1)z>4c@qpcL+;*B?GMiV0tUZ3_oH*t)#WJ;CC(59Y7)eViHYg>>XBO-)bVQjy!BL>;9ztw{nBb5zw+tu zGpXv|blI~N=C|sv-PB8qdO}%aYukjMsF7icdxakz_5WudKavbs7JPon@rQ&7o!bkg zWxjsm3QR1*RAJYfRxbJ730BY0T;BBWPtZi8a~g<-Wm?weL{ddeF`K z<1+G*-8|%Qk}G(#_I=m4GN&9zYwJFa_0FI+r{zzY#jcLr*{^0GDhi~bwqElh6 zo>i9g4smD+w5)!I`4f1R%EtA;_#HSqZI^mR%#Bso<(Js>Z#f{%Tg(?t#}=8xBrgKU zf*{TBQ)p3p>Q_;}O%-XBx!szKIowg+b;mN7VIHA35KcW9X3)@$1!Z;)a_6Zr5%H~T=IG5fFn#}h zdmAtRGG(%aO!m5;Me^c2C3wddIeU7)n~z+~e^}hlL+SM_BfItV1oRptK%sl@BCtzs zb?XlHb{7Y}wQ!-FA9IL=MOt)-HO~THVlpXu1FW}$P6O7(=={4w(}~gRw*StJ!Ts7L zUlKJtd3~moU07OLT3>&WO5`+aiv$>FLO9IBcJGs;sGklU|IN%&9KCNoJ5@%BASyDM zdeVXC5yd4g$zR6ylfho|Sg?u2YB|WeRCnDg$nOOqEUmAaXvTJh^o-~rP~8=9>z@rn zmC7n;%>Hj`C=WM`#zrPM+rBeezwLD=DNFQt2crs2ZLInWZEU@Ff@lfWv<`i}rZFP< zB@n~!@lP;_!O1@kTO8zSXYi}`aVXyB`OG*BkQq(b<^rtZah~y7`(j~J;Ki_yfmY}> zXwh)`7KQW;T-Vxd`(GW|je+Atti=cHpJs8H-})lq>-R??4*?%g_+5T5TnhQH9^&sC zz*3qVr;_rmZK<~&YVw_XNPCL�y>6sHHO-u>h-#U&ZmlAYmttRzt&z=!ps0Lp7S~ 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�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%0A#5Jucs=?Ns`aw5rT#LP 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

t z1e9%k1HecZz+jxwkws^~*wdtrS43bky4r5FOeq%x;`G^!w$@JdGPw3@*I`+_VMN;G zvD3yKbx#4AU@-bVAKVBsh4&j9sEOkLCd@ihfW-k7((5zX_nP+@-`R)meQ9wb9h>yH z6jr(I^kGo-)#hHB8JY(9K{{R^uMfx;UtyrXz?-RZD6Y28|$#E4Er|o~tEj85j82WKKoH3TqEQnUjcXlL$=JticLy-9+;O&~C4)0y960I&@PD`H zurix9Qnwz#-j?zihmxrRmN}oybF(OiJ7qL}blq5%9UdNz^M4s(Bz_CCU;hV&f)xxf z!i(1Sk4tQPJ`rXNHb`=Qh{L=s+s{{prx7sxjv|=|^Ly7yV4g_NUddKToyHGO)3e7SE*%;Xo;!^VXZKAnBtkl-7zL#~ z)Qp+PbTr>O$%1Y!>aG7qdOYZKjT$GZ-O9D|D|H!J-8rJC=rVEUAl(IoGiS5r8SCj?=Z^}oU!o6vP*0m*^B$D-Zb+!f(dgI= zAkMt(><++*hfKsX;Z!7Vy1j-ZUJBK_wEu_n4ws7NlH05tz!EVt)WVfi!L4-k^t8&+ zuU!JVMBTSG-M0`2f9TeEehpM`8ZZCsaoh2FO5ne&%-5k;2>~jzZ;xYvUK$P0} zp;Wcyu%t%2y_1YGVIx%{{Jmo9@CuMy3W|@U2g~9=+>G-@CZI4DNvP6rEb>F6wjEi= z<<2_KI%$&INwN3fYu3BK@>3V>iDM^E@8SPW9aw&kWZl_1RJ*eGdiN~P&Q59Y|M42Y zjmQ`rU@l<1+<3h4UhuG+# z%c1VAmB885?ytY3V!F<4mgA;@n|Ka*Ry$@yPgLDJjPBB@G}-uQlq2;+rIxz>e9 z;4td+a6Nf23;1`bC;FB$kg%|`b2PtF8BYu4hbamvFNYik`_M>Y2rMXJ)^!o7&9-K~ z(JqiNzqpDUhg^BBui&k-Y?`|Ht$v1X+{*W>t(cmSj6`X$f)?h zW7q9OC(0ZRu(TG8wBCkGYM183OkU179%r!yxZhqcj~+RzH@Ie?n4`ouaV9r2Z_1c`W+>io-Qg#MO@bF@2 z5Z5#278E%1rUL-+n4s^SW1Sv#f#W7@D7~H;7Y}$!!P;B{e;$87{;YvEL)*G6v7zb{5#3F$Aj=QR%=(Av9)ta=E;TBq0BJ%C}nO^f}S zAg^FKQjs8QQUziX#b@nQORrNsi`Y-P=66Hs)T6CncQTf>(gC|;XCq`B9@C6fKm2b| z(o!5ll;j{B+TStK8rYS_6%q=o(`i+MChNCipy0r9=VWv9PrSTsN6cRkC3yve4f67m zQG&}QjA*617>6tdPkbCs$@FY8{hPG3ZK9du6O;eFS8karBWX@g04ulHUbxTw+V*30 z?r(oyMfAVpvwUh88qi#c1Zp8*Z7mNDL{+rEjc{Af&dIseCooCRn-1^ac5Vfj5EmDt zPJ4f|uL`mzE#j;?^_Z-dniZBx@u~Ub7Gq(zF_Zjcv2M~DDM;pCXHz7p^<=MqLw1Li zf_{!%b=ir>6izU+%bq1yvZ2V4`4O}=Loe$`>ifXpWvq?YIv1khUpf$Bue%7onk;Td z`pe7nEk}+uEOzfilth{@n0;^(7Q+o$Jg5HG7oW$FTQ=@@1PmYVH=l=J=gkJ7VGqrA znG4R^(`f}Zob~3ZuWOoJ-aw1PW~pXX@GB^bPjhdIFESV9p=NcHMCwdxR}ABWXhyP2 zZMkUSi&~&II6>QkYx*>HB^=%s(>t^6v$#Z-Co`ouIAk<1O5H?z|HS#_S>$;aE8wXJ z+_uK2;(z{k8JWzlL+?}aC;~W7(5p?SR;uVi6EMH+bwr4ukkDx2W{N7TL>gb_;OeZ$ zL@L_89>EN!n6@cSZtlDtBKhud%B%sU!^*qWACa#ihjyvNN~oFJ3o=)6&;^4{Q`7Vh zGiEX=IVG>37PA~)=>pEq-bzia6x!|jh&;{w7hHeiCxw(J?4y^eI8YTz=m%^Mpu)at z5NSw#`Ol~x4fr;(pmZarC~d`6Bxx|c7s*$CJu7UKKsAcG>7Sp3KbglT_|BfqIJ{u%9{;Jdk2VZe0gblJ zv8}M?!XxY~;GW44$PuT6?~~MC>+sq=@euX^?(mFNab;pyLbXeVOX_hr#Rj7uw*i#F zKLe$C9RV*0f+FOGnN*U2LXKmny%)`hK+PdzW6n|tw?JMOuYzp{%q;TRJL9AG|Lt8f zGcjSa4}ExVz*Gqj&JMY8_Ivuv9>Lg956sEowE>(c<=}T3jr^U*vf+ODXo5Job;8FX zJLoWl`vlBnhq|41XT;^%`eg^67OAs5=WZE5(9ad@>@O*9VT!^e!&eRowI|)`(5o^( z{a1HCMQrhNb#=z*hSR&{=TC&HsoH7rbYJn`Qs8PEvxI)w@IORfs@e2>EsBpP6GAIs9X8d#Bz-4> zUwHOVW1rPrwKRF@$_@Rj#hT`~si{sBjI|-+fBBo=!{41dYf|%Og^)lUg@s&wxkqQ! zYx6c1Xa1y3yY{O3yeS@A`DEGm=-I;w zI|vpDy|PZ*_tAjP0OEmNgCO_IwBK~dOoFLxdmE#RCBrRCB|k#+Wx(sk>%}fvr)DZ5 zO3|2Y>q9b`zoYA;A|L7VGHmm)*XK+D3$y#>#sL_x8QxOVWHnc`TeJNF7~nHaBxd@X zh^mc7D9lW^Vmg6FIeX^pIUn2oxz=9=x-WDMpI2C)?&CKDu6N1a*1lg{M^pK{nqLpc z-ZP~d6BPEn2({qNpuPH8d|CIiE?}(g;46t8aen7{@6!!?jQ=2V)Yc3bGtP`&6m`{x zg}4pDgy4j|F6UdT9UckAR}_msW1If%Brqm#G>a`k=m+@jKdzn_UFO^i^*@$51)#6DkG5ncrpF`9>M;=x{ulhkly;v*N$=G&cZ?tY1#C8L^r(a>%AsNg~S##Qn3vkpPa0> z!-k$8VGf(EE>{PW`zDe@5o{DGlETE8Nb1_SlB-Q1YjDJGFwtj(e8$Cuy1nd4jx@_D za8Q&4Lp0-iMMMhmN zL!Be2IsR~W^wqLD5Z>5G?>pflFcb%NyaAzpJwQtYG4YV9XC5+p(;~m|c77zSvA?cv`#%|A*0F z*{n98^(KNnbisOotLe;#a<7NtVcGX%pVU%K`$UtSCF)zsr~^q_Pz}9?-PxFRV*ptF z2Pu)ItwoI6BL8PU667Dzy&YFmhyF)tU0tUuB7k{koehEtp13YdfkZuqf*KcTGW1g$;3(!|ed_^8zs&Sv3%A%nU+ z_GTGxdr8zHX9%grC_7XH150blA}EOyQ&=-)4ev+anU@RL%iea86l~M~ajE+X>afuUm* z&`WhoB~x%2{6zNPi&A@J1X1=d{Qfu+T~IB(;}-dRTuIh^T3@JM%F{La>qFY#K$S zIAJlt=&SC-XMv;GqFo8*5r>zJBl|E?kOv6v6p}( z_$<40S=EP#5${g_yYp=+k^51AhP(*_8C6f#Gmmo|>hZ%@-8k22RWI3qMy^P)HLDhY ze^_#psmU?d)=rgFQB(hMcpnR0>V9T=ooea2VL4o*!y?Pg%Nri)!w7_(u0O5`I zh4BTldh9H@a-rTiWw95u4QuUz-6;yBx z{;W6B%{%dv?^?-|!U=8$&Ua$;`^Kj0SPg_tJs5gA&l3XJX*Zr>|H~w@Y<~MDf--ZT zFFL=^q!|Iv6qu|td%L^qr0(}_V{_8+QPqWZeKrjP=oOm3{9bcBx~}&d_W2{)s*Uz1 z{upcHP7VF0+WQz%dK4bg`(G*sw8dV?^V*X=@3WbsJ=+I!?Pi_Y#X~x`rC)0~d6U}Y z*M3V25!NVh)YEIdFOAIOySuyJvB==awMn#b!HM?kt$xodiJyjuzhW|`;W6{mOL?)= z>my1>*9hpc@b*K$`&=AjWVVg1WwkhLcKH`MP7x8mMJ|Mw02-NsE-0jwoX8RWT-Ej) zzqYea+7)>#>9Ge0)sit?O{c1VZyXYp*W%QVXrmO8O@no^1_^VTB<=aU zu|IOil?Pk`6ozeNvVkpiBCy33(1lMXX*uOid^zgAI~@inwF|ZW`#i6mo4@>^7P?FN zOY0q8&o8<#VEr9f3EomHD$G5KE^_&isA;M7lJmpcR8VJCq!Tt-PFDUqVGTGU>3;a} zEC8EU|KNMq+hij(+4dnG8RYDI=^DU);)7+D!@`lJ^kuG+zU$?*Jpjh@!Yzf@w>x(b z@c8}p@&0}}N1z43!P&sTLv~w{0yhjWIwuqHdT`~=YWVBDPDpt$LfUz@bn`mAk>xh* zW^Nhmledk@j%)$m0)eUNWs6lm%kuFfTb8af3alShxn9!{r8cm*_mB*59IT4;WJ}Ckm1K z^~1>DARfM{(ZAmG2*>nkfAZqS1e zDXe;Cg(O~-C-0(zdmU+4vpKHF!fk_=Jn9OU;zqjAm}FN#Z|_kHjcB^9T+q>~U@Qsw z$?@rvkch|ef~KLD#f@I4!RGSv^2Q3|WyeqMsKN#&%QU4tU~3?tzw7`7a(GJ0I{miP z@E6TpGzQ=0+P7rV#j)n{H8^`8&F}4nrUqvKK0(oxnyT~G3l>ENwd!v+uLQ$-;6*`2 zqD|cpaybJnv`F!z*)?$n8X-tfMT#v|F#QD$Ir)`m#SJfyB8bw25XlVkNwRAFFpb5j%bQZE+A@1~$Ze66a7-h~1KcWx7z#~#qY8( z4$Pqh<PBJ6EhXYyEjup3GBTm+t~pQ7&da;e0UODdMjLu3?%`X0&$*fO=%fpk+y2 z_92%iijwl5yHD(w&SmQ#XyTe?x!{2~I2TIQ-0FGOj;G~!OjRCa)n#5PcJmEfrn;WN zRY8=Ngl3wblMv$eAG9Oi9)kXNf!@?V!+{o6Fa0SW))4k-v5vwLf+%HnH5xf2 z(N2TNpUf#BXok|mcACSqddRG8LGQ(S7~>*g7O6KH$bWcC@h;A%D*eZ8RN=W_$q#B% zL7G3UCzDblPup3XUz7W{!PwPJP!ioq3%UDk!>5HTpUxM~!zsVR)$YqRPRpVfa-z2u zWwalKVQXgX6~$~ryf)asuKVb1ja$`T^wa!t?>@X|Tb44br z5Dz<%mK4#;e9psTa_Z_ zx?kFmQlB#2C)FV6*zH%l_S~}gLrK64=_y4mEf1GYFeoxoI7!-r@LjS?d=u9$f&hq~ zXKdKQQs-X?Z;T%zrbuF;2VvqI-T8o$T=Wbdz8Tj3}-00+_M;C&{y>q{dgR#+gwMtToyVy(365&K`^lKMr>F5p*4-|6+ zy>2HmbRg_PLi;`+1T4`_A$SowmEKMGslH8zKB}mq&2b}0U52v1avG-iOvFWzQsEJ0 z8OAU>pV=vTWI!siE5kXtIAP%6$Y641S(!+~`!P*su|(aI=zLX&=?V3$N&igRp?&eU z7+QEk`6h2#-{1#VGbAM9<~&$s%#8j1L`5Y65Go*>aD#HpiAp^nY z^DwP@Sq_1pt!3uFtq-*8d5%*RE(V2%<>IjPS{VJ6;iJe=qTmDnEEi_ijpewSxyn!R zQKX2f*Y{2B1L=psh4g~c4T}$5N)i%5hXtzQ3_%D)7DMTR1bfcpREVeU&9!=6$6f}w zl8dd(<3P@f8(4PwHCf~_fEyNW`0|g(|E9?y$AI5FY3AvAU`MS1=Rs11u%EhB{X*~) z5z+^Nw0)TdgExuT6o-0jyp+%peqziAQni>8D?$%gxVAN|Zly-v(-`aP%ILeY*E`tD z8-kCf4NGS^{LPL5elDfTEL1Cygk|3sm+`~tJh|CIohxp#)2^40v)IDiv+wKc?-?>O zoEw)XMUTqS*SDvl0=++LHHYfV3Ez|d!0AfUIaD2Fzl{-?H-%yS)n7)2 zDxz#>FR!dTY=vL}Nf8^+8&R}PSk`3eBLDQ&jMe-ZY~1&NS|*~7v~zJ~JAG!D90gd5 zV1$VBCVMVoCMG6=k9xc=-eEDZ;r(LWd8OZys8z>GOwoaFBQG-(a4-3mnc5d~xg*UG z%U-U`5C%^J4hGb#TlbYItcPATp%~Bk1`vv!3{Fd+1qu+89}W(trW9LNV+-kdBr{8; zsUt)K%Y+y{OPGQ8|Ml_K@5jCUN#iJA&lPBt8mM)^NtFbq9s_j&hjNu;B_xvq)(Z`jRmEJ1SnM}r0()31LF=veA2 zlTkuPN;+jwo5nj_;G-j?anh{>X@_a)o(SWGKY+x03I=EWjfSO6t&9S0UK(v~L`pv& zpu8hnP5$}j6smLZ|o zFJ92_A*ga5Nqd6`1G)1B9YY5`;r+3jd%kjRu5hRKRsZ|_wbpchXyH#bZ_&(2sFclbbG)UT4 z#kT#uiDl@S3)G7#9AB!Hx5_I_$%cL@k_cItg*}5@!SqV^29Qdfros<_q8YzL=}j*u z%tn}-M$i@QRAdF;^O@v7uf0VW4g4WnlARt*o`8aqLj9;lR`;eKp^uM=loAbszzB$f z`v|{s)BYgOr$;;d!`GZDIDN&1rXKz$kp+YQOFq5gBH%K&v_x`~ImtPFRkPl)pKbH7 zZ3tKvE>7LD`knx!jRjV}(;w5^jJ;D2Zxr94F2bk}hhU*}ZxAv6w2CTl_fa~?5b+Ir zsTTibb_q8_AaXrvm8=rP3oUmg_e)HcF2Lr_;*6G?eI>J`eZ7Xg^xq0NMD?_LJ-(Rv zSo`_#u>4L4aK6~faG92$uFRR7zuH>4VbT=#tTk|8RA-19z!LmQZT{s;?jd0BqN6Y5 zWc_V_f-~ST`MpfbWC=V zN`+zq^Q#1cL7lEB;e0;p2p`nPnZqYkevqBAU4aWhY^!?_O znlKlS+8W+T<&6skcbzenAmjrMA!XR&2)W($zTW2MB_o&i-7PIGOJtZ!r|Z#kTyeX+ z3bw{5goG%g%i{THf-Ftq5^~B~UwP4))3sBG4e$XDfebmlJ3Ms|y-NuZH7AH3Hx6jv z;Mw~;&qUrgml^*hm)(JFcDn7%0|5)yVYi6D{3ot6n|S4D*!GzIyj;J6Ug-fYE72(o zH;{TfQKN6?;*MdG3M7{=7!EO!|8Rzt9v{;~mvCw<`XqChHxi5#*zIt-uF`x3EK?P~ z%yDAXv4&EVH=CKZ-qsqRGVzIti4!-08*iZ~%0nw_>r6Q7Act_DMI9p)#wPir0e(7M z>-Y1z@!ZWEHn{a_%G5JfM$%gvYXWYk+7wqWj;pYLi}=r7Hr&=zK`wz{(k#P=rEdR! zK!1j$=oi`B@EphqvJGq_;Ptu5$K!jyKi6@5_)HF#1I48yul#Js-Ym6`F(JO1D2*D1 zOcJ#dX{Ax&OlGz<@8(?B5(?v-!NMCAt*ithI6fq?y`VP|pK&d}iAio(&r?pzM~dk! zZw1$1`z5I^T7TM{n^2S+osxx{IvJ-x0sUc5Ie3joFRcTchO6p)gM1odC`q5W>Y()S z(n#^?5bIHmX2S>-w}D7B(grj(13$DS%ne069{kU}M&8~Bizn?ZXSIG;y1;Lm|Ix(d z(U-qPlhK}Fw-&iU7nbwl#UYe27hOV>M!Qd3Xl(LChe1rC=G!5L?{31Yxv9eV2-l&h)P1~$37G1Sx7 zF_7W--L-UtQDe|)63r#|bI0e#`&}KbE`e$^^HhD|U#WiUPXE(2m$|RQ8{OBZE6)P` z#v-yiu2h>xwlWM=#w8k6A6Z!tgOYF{m1J&QhSth|yoKUp+8DgQXMP&7t3SC0If&s{+4MNS|JZ+X_?!H0?^wbMK8J z%62((k$^D@BWKK#?moN7a>@4yTGn);2ssk|4a2Hl!d_BQB0?M1mygmepgBmBL~~lq ze+Uv*2B2>0v0(wzh25$Pw>5RsUr`)=oEAH^!0Pn(}7bp%uQ7m!X@B5@Ca{TmBO)i z8}`xk&fwp#h=}U(SQe_kzMJUqfV?`9GZnj0&4sf8xDcND!lH|)Pu<%E+S@xjJJ;8X1?^Vi%BAgwGoir`K_;61z* z_iBYqzdP^osY1c#t@S;915VwCI6W1+MZW~MisD@ruD@~N!RRHO#nOe_Y%*WzK+73i zta=|q>EGKEiBZ&3Q{ouGNu!h_2C0rEV)r1{tLoUqlA|i~TD~XyQ^j6C%E^E$hbkMC zB3bEs|UYccQL3tdi zgt1!R>`$XYE(O2{E%Tj;2Tzt2f{hJUp+U<62G0k(Vy6yIYjd`!%!Pa%)IVZ*lAV0L z)IufVO5G17tkr@I4*@TauL^R+7(MJ%CdMq5e5m(}t7mFeH}38F4qS{sq6m<>YW-N4 za#eA{l+C+p!QzxM_&thXX~Kqv&_FBYJ7X<3{E?uBjKB##Dw>C`Gh_oWLX!?;#)^wL z*1OZ-0r)I$E!@Lxw?h-?!GzgV4A<%35qsr9g$Q&AF?rdCPY6SZq=%m9W=JN~qQPY; z1Uq#?WcZ7z5kw_mP)#EzQY!tgYYs8d@XKNPfG|`Md*pJ74TPQ;AXSAI-S!N!-tGSU zu-=3$8+lZry}2}1=LAH*wJ)u*IO|qv0;vX3lyd0cA$Ams#zk=y8wh7yAY zXQS)O+P}W1?4-i>)#a5x6Acq)6{;I+Pfw90`-^)i^DB5^XOH4Cy6LsTv;Yd;;a?AJHXYCUfoyrZiU&d!1qq-2bPfC$snp@h^7Nxw&+v|bFS23ge8$=8sIudjiY=a_N%|!_$Wkb zmBR%1E$t*!f0dNxSKl+5ut>idW8zu*=zp}(K)~8@k@xC*y|tYYW~%V{+m-`hk`3QrLlbQTdd-!-3#^0v-#WU;j`(P`0( z-^e+Yl#eOYag0|Ng<<(h@D@=ke*!;ulxaw#|EINWK}x1|3sUFy!g!i{vxiO7msImk z0|&d4-n!l4B_3{je@`C(v8HuBG|gE~Gw1M|Up{TDJl`}udXXZ2VpY-`nnL#zu`T8! z3YK*%B&0Umtq9{>U2tvq#WU}QS>mjitq1?icXzzuawEB-^OU z$-WirULAkLI_;YC`|0LhQE>F<9-Ze*5cFL#v-nrb!{wzMtD!s&N*{UjHe@Lv38Tnz zy2gm#_g7QXT#l--(Db`)LR4%2bs{0cy&&-V)WKd~#n8as;9=gnL9MXwFX1ScFBHW} z;_T&-k&-yGY9t;-yyVqT<wsvPU8D6hBFoyt7*gzk9@)vW~ z?z2Z78|2`KMAsF!0?o)>D{qU!k=?1&)4m<9WRhDSeNE|5*^*h?W?hIzyU?-~*Oz`3 zFv1FY%5Palnv^DdV9Gko`-Bl0nJ)Vzdo24#7@qOuGvS{)M9|JKM;QBBo!97NoKk8% zn&WL<=$nj-o~S>GOo=sbK8T=!5G*JWC;|f!W5}>HnkP=T+=C(l^(^jCDU|b#P3xRo7qNvX z3^J2M1Fa;3_6-Ez2n=I_lml_4cd1XF+q1zX?Hh38{=ZA;o04?+XpI8v5P4H{;Xsa; zcTQi-4mcdmfc-Ivclt`P%#;Q1KMlAFZpkJJTnHV43Cb+YZ=oFN#2cbg>(%RQQyMJG zu)o0APCMH3rHHwDp_1jbbvoc=d$Y@hsf^@IzcmB5`+k4AyX{!%!HAWa2+zR#@!w-h zyCt0`t@LV8lUkrTrKE%^XJE>{v)u1rXPA*=xpHct9&?0U-gqUDfCL5T4>6ESiOGh^ zO#lKhi@3*u^Ah$ixGJ6oVqE4;J^n)guK|ToVIaneWT&h4qz_(uKHHaL%V*E~0bM}y z8P-R`L~)W`#g8m!W&%zDyzA*~RA=AMHg6ewW3fa8Ul&;AKNw~k8mydP85>i?&c!rj zBww}n7szlNQV0H={WEV?G}E(*H&!)Yxq|)#WLz?KofXYT&}*fPcEW=Z&o+AQkuKEB+huoVe%_>gePfvfwbtAD=BZz$uGJ};!P9mcJ0gUo?bEV$}LATd^w{ISrskvgQQN3yi(%mT5=BjU_j2TpnO=MkhR*+|?pb{|`Cm0nG z^b<#Xbaqh(jY11viJOF261S{~m&`ou4NE7ugU#}qWU}PlxMC%|(aXT-Rjt3VyO-pz zr}=^79ll@wyA&IGWcaX6Z8M z1GerNuS0siN;Eb!)pfRR*te9?T4tUcX;kS~@yIQNF6uny*7{OXf_skB6Y}MSm^!zI za%~@bVBb0iOmo=V*^Q8p%tXc6ZySWy4q=UE%W&~Lw=kLB%ZsBcoDTv^9~y7q-hl7L z5(thQd9RC6d;=UT&wFo3a@O@lFjkY@C?qmVff9;0YL?4Ik9LRepnlgeuPs%FLFq2x zu$2LgvQpF9#l^+&bxczPwyb$zQHC7S3nYwf*bnb#BrR}F--_E2-lwG7(b@eF}IW*BCk5+sY4t##i+> z(NrUC%Pl``+F~+PpuHjaD|~+C_P}WJ!9VrNPf;oM4z>ZWu{`<#_dA0n%gaL-Tx+W? zx*=7%{U@W0Xm3;A%_V1H?7oe>6gsK$AI^xz=+V=8+m|kHfe`AXA^3uO3p2gn3ZRzp z4ULTd2ehWY#zkt&(!#4esG^qOq8Xw9$P4JO^Bu!TZXRNxn$sP(wZu){%CJjW`~idG zi{p#dll9Iiw#N-!2j7=y!#fB6tCo%DPLW^lXbA8v^t+RfF`_6dB8;*Pq1i4UCpiNt z;25U~R3E#}5b-u)O=mU`#7gUuVDhFE^A1)x6wq+Y#J;Ot zzMfja^y}V){8S2^T_T@N25B#^*=bKX^rA8JyEHbqN3U&%NlETRj^TYW6+C5%EQ$mL zHt2nWsL9XZ*q>H#q~tM=HEY6Ie!tfT153i|pWti_$P22}ko+3DUL1Kz=l|h--2bp?9jBFMM1y`sb! ztCCl&KDl{0o+RsXGJUHvm-oDrhOarT-}QR#5dibpU56`19NAjFIy7wc+#b*CHhRlL zd~^1+((<~)+Vyx#;?Qxv&)R*<)cx?X0OPLdXmP*l*VLHip)Ct{%G6yw0*Vy@&IU-i zrD4ET?8%88#`{1XPR>spt^roDRNbcy>(_eF0Q{X`iK~R6?oNLR~gne4s zhKVFe^{n)b_cW+P47S$JwJV-4_m-M@0%V?G0{?ttt8EBO_?Pc)&DXB$e_=8sl(?hp;EM*Ia?``#NvB#QvP9weSvZ z6ga>1A&vLAD-rHB+$pO8kVVyNu$R2 zrj!J0QOfDEHsC00EC1v6eM4EL2nHG?I*~|l#bSs<%^#qB1vHvlQ6%`j zQE~pLxlpAq$Tk)AzGrE_k>-y8xCKNg85C!UQNc4e{8GoRG=|o}!GYR7$hJxZ0aj*R$o4<$= z<;A$FW6vlWND1O8dU_e8Qi2+qv@-Q%Hd_(p2z`6ZF%w z&nO)rd|3ua)1g-wjnohyoft@(*HIpx0TgORk&`le(A=2Aq7v7HAH))T=tV>Ok)n_H zcQ2oXd;_miveoa;y;B)4M!!$on--l&JsvwpM~~*lEvEoMoUapmthG3uHh`6PCi2i9@Y?+XWbNcQ1RO2}?9b3XO`SbWz2-g-14OIo`pvuBfA`Uy z8wPFeue}F~KJIZ+PHU^WK6hLFSPnuyFB8aQfF$-i*@0In7mR8Z4ai*0h>Nz%wo)o| zL@QAfwwPs%HBXS!`J;Yg}buL?ldHvm~Xpk>L<%(dgr$~}DS!lEBOsAY36 zB$tXe%@DC>cLG^s#Zbx0W5}aCh1v|j1>A=Q4ANzQUvbUkO@Ciu??NsSi|ECBCoNnY zYF+Lx_W_zWk!f5GuLfl4N)SkGU)k9BxC_N>_xO?MeD3L!)3`XKoJ1XT2KZsz0*poi zU>>XP?hednH_uK_PS~|U^p6D7BCxgV2@GsJNjOkRV1X;oYwOx3X3ZBFEHW!3S*q6l z+s^$}*2`=$dVKn@@3Mhrqd3aE|1c=C?M2pn??PZ3SkGe)3)15*{t#P@o)2fD9+8y+c@5YuPEY0XZ&wUmh^8F8HN~yz}&`TzglfL66tin$i%Y9b%nihF|f@CdO zmeSVf`M+M}y><{C{OOS`5!XQn8{<{p7#U1FrJcPR)sh7qakAFTL&6Ul;ISJc0{77-x|YCL-!6^ADW3lS}G`I}KREgA&kL_pT#i%5Ll1cKp} z^F=9&=}HigkuL#1lppQC2fPgG2fxTN{P@WJRRwoS$D-NmBee}{#IBW(kAN(t5;E4= zCV{yAFGpiHH#ZB5R8$9p?hUWIo+WzdO48^|6ggNt_|4aW8MfL`xM0|66BO_r?QUB> ztLeHPbKC>$UYdV-?#wp;hgP>cblpSjPRoI(|DRdIhdb;0`8p5Q&hEO_+s)^p+Ki67 zlg*ct0FT{+o7X4(ho*q0hbK9Kg@>W6fCeoHcUh?&KHYOCl&98@>V6UG&?Ov!6oFCP z_8hcizo>h{K+?9}g&C^6&w)}bal$mMY5HA%_{3eHLDCFaZEwg-GB<<1{#&Xm%tS6{ zBjL8$4B~ZsXS)zm0j37sIr@;i9OTIL&vVgQ@Q$J(M>XMg!IvOXg4lz9<19peI6Ml4?05lJ!@YH{BA;Cm;3Ymq_diDf}l4kz-W zb713{H^#SAV#}t4knM9ow0zd(!61{gYz4^wSi5?wIrB}(t%!w-rk3GjTY9Bt3Nit2Rll0iPG>XBGBeEn z8c|KQT-*a*_#+4yC9V#~SF(EHdzVsl;r%#h{MG-Dsk01fvkSX*fS{!iq`14aKykO= z?pi4B(&Fy!uE8CG2e(qBMTh}gd zPM*Qb0CH`=?x*YSXQ;NVa>X)c)UCC@EZhZfw6uQY8ZqtJut|Zt=dN4U*4J_W#IW^V zZ9#R7{eJGZG<@B^%ymB2_ub!?9x{7;LBeil0q4v7v*G6vYwqrbdlv6yrE@Cut0f^; zRRly@r1&kRGx0IC$O;Xl4D$9?b?bJ6&*VpWmE6UqbE|6{wkZd;DVUGGkZ;Ctr~`G? zdL^eI5LZLGWNX8z;)iP_LbMOU2CSxS<6%0n%U47~d>BR2_A_=_#>}E5h}6{RohP$y%$Q(i-o$}6!14Jv+=a(I z(WHddGE5UB&fFNc!(bKJP#|%qo_`O(3!GC!1Pq(4RHTobr&+GzQQcch4lAJ=k6FsN z{R@#!jx^1(JcQXVelY1Jlb#+N9Ne87|4iiWA(We&E1#0qIx(JC&U_phD*P>s-+5W2 zWF>Q%%VCMS_rfyKuM`i{EgV2Ktk8RC8 z?_&!D#T&*^g41yg>{VHzr74JcQp5h(B^O2rQDI6-k?y`_4)}V264C-TYHp-t7q`zTpqT*FZ}{3>RlQ;9|Qnm!L|s1{3d(9_N`_w}3yJ z6$>l!@h*4@ePW&)9?m%USK$3J1g{8$t)2*Tc{**Lp132T0~tIQn%*%9S0ST&=s~$r zT;BiRKy0NpB1SeO>V@1iZR@pEquYZ8(S$BEI0h^WJtS zN46i@jjP{n{MT_<73~A%jfv2O4`c%N{>HOrI&F5tJno#VU1?+Sa?5y?f9%c(Fk$kW zG3H5+;A(06KEO<#hnorW)k(;|$LD%(!oPPvzmyr=g@Qn(`13Ml)7A3ti`)BF506hy z<05cyyn7c6xKf!f+2Vh83XkQv866f${oB{|70h%OY%!M8;i&Pxc@~hI_B1QMrsV}6brz$&JrsiF|4EEw;*Sb>* zU0FC6z(QZA+>sJR2{p<@-c%{T$Mzq5xD6pR@lr4RajB&+edu;6%!qr?byDACDdmWust8_rnVvN*64tRR zL6?cj=5l7;1(xFPS?vz*204vKn&>Y8hZy~gUvtOIsdtwW5etv~mI5cuF`wO1u150y z`I?!5g$Mp;pm=k*7cD`hKn)7(|5%ZQj+35r<8yPmF4TJ~vT5IzlkjJ9{n0yT>izg4 z!xKNbmgH7Rmn-L4OPS;3XNWI6dc#jBu)kA zC1;eWv%V`^L0m%Q?7vqB&*!H2LxwCnb4 zbSw_ejEzdANPcrkE8V4od~X>!Ov(7N?GOZsIP3ZpBsih`8kizUaqdWuDK5?*CFAPX z{}EnJMq;5`6%mzW=`Bp+E(o#Vzw{6E_c#CYj?V|3hGP~3GdIcG);5@Otk;h;><1D1IPt?H zKsbq|G)OCmX%YjAkpzm4{nHXXnG{nN7X8zpXL{WrvA8|RrCvsu*bg4wl1$IfR`}AA0`U#eD+eNX_v$PXIJ2$ z3)6S!?l7kKq`SaU#u9CiguDRno~8y%w4?x?OwG;e-I?F(w-dbj-ZXD&VqvkJG0dEI zMD(Fm3VWuTPv^I^2jNNk=?3$IBJ`GROfvetK4#vwylbB}Nlt~Uk!;GpvpIXSmGX7l(1{y!?0~*AG_6^z^06XQugIFMyS-68(Zj zaKA%#)Q@=bCZ;sHI27rWG<^n z*Z5jMCsP%chHDyEJ=&p)PJkwz4{uBmo`PG~SYa#QWwF02?2RvTRj7PGmS})aYnNAK z0EkCn(nIA9d4?xI{6B1HVq~D_7n6XyEgQGfd0oP(T5iS)NZHt#$;)(Nz(*qb1RNO3 zI}l5(q<8QPN%l`-x>(-t#lMb!&A{&&Q=*R!kN4Zy&YKbHeot#1-}W=)@GL(jDswOK zl>8a2D$^;U*DspuNY(JhZC}Wnl%ChK30o;Gal_y2@I8aeaCT)g>qd7^E@`nL9L(E; z``Pa?42i6xY{fo@Bqx&tjR6rxISZi*+Agg4?+y{^EMsXBA|NMjzmQYsh3Rox)Pjh# zaPM|$vYZ#d_$-dO7++G&@Er4mjkY^wtnsakquHD52}? zJ#_NIQ}v6awmJLo@lglou)t9iC@VN!C+PPNVogvg2#rGpnX&bGIPhpJHlr*$0~aBMpLc<&jO^To`>#irnD^t!u@|ay_V!^_NJu^> zBYCX%jMhvYUq6G`e3+Bij4YeF?Ao6a5F=aw$$ps#d~`MmIHb47*t4zL{mj9%GrGf{ zAqf$1y?tt)TKF5^%{2Nu_PMn$k^lD#SBL6=Ea@ax7#=Dg6Jrt}N)htz4M>40&A90L z?De-VWt`YA=FH)$-Hz?eJA-mTkRIUhRiGlWJd; z6OnH6PD!p4d%EA^LXDe8yc>QY&wW6$8SlW|crvSmp>KwGkzt0BLmZLyKew)~)rHce zAbyl4lN}`#UH`={9<;vOGl>wR0S0?@%aIlo_*PT7TwU+ZHdfbGs&wFUpxnJs`?fmI z;z)LpKqqf27EH+|7Qi&b)ef}zbK6U3do`Ajawd)Jb z3W}GB)e?RvZw{^1Pb2gvpPn2S9AE%Zgru!`Y4tpSiM&n!M|Qn>+9-RJ2%rANG^9d!8jUA}4DHQ{Ko(;wDo!4SJB>0uZzE zEE#ww1;-Y!qL>t8CniqP)8Cb)!QlQNE+MdmN7krJ^CyPNbkHu~Y+wXMf{TnHy+DTa zm8e?}vBat;*^(J2-1JWtoM4w?9d&=|d-fIuY4eU;)A^U`Y>QGk6AV}uP+0m^(NT&h z0)FEeuXAphzN9aYnAb;5?0={}r1y{pCVukW%Px0>{Pw zI4$iIk3+TnFxWo2mg$JKdKHV2IYOOxhtzy$>b(rRN^GE{a!s+Zc-1VpoKbQXlGvze zVA@fwby{cj1=dOt8ViDMu}u!d@3XhnTIIhou9%CLM!LL~(q4A5or0v2jU$u3qQ~Iq zf$%ceC(O+vh=`FX14f34rmjAkXD{CksHb@a2fhrr9_Z>G%_k{^MH$%sjLOFg61RCL zr_V(Dk@byr+|T94wX;1WKn5-j3|AuvG$4SQ01yYow^e7;p_yYg{77|!>tyGw>iAqc zPivCDbyF;~@QDpkd^=mz1Up#F84IuZeZy0ZO`W?=c z9JQr#4M5M3r zC;qtVmg!+Jf=9#*CIs<~bG~wqtN(-Ey1Dw~eC=618vY<fD`^lsSKolC$N{aSJ??s_aqQfDGrnNR>7*A!Q zj4w5T@;2`eKFwSXD6$t2UB_A}dwO(=y-Z_wbr~KT{a(bu6c}+>dS^MxiAzh(NrRE5 z5lq$E(J1ZAp@0GPOgmFnRaNC)9bCBnYVVle=Jp%O45TGICH3JBt@4@|VPncKAa6lP z=TLas_l}$D<&kDbN*uMBZ9cyxV~0+XT3FS+^8yZV;p1zIl4Hs~_{XHchQ~=VQa0W; zI8ydfM5izon1Ko3?)$sj+wVum3jF_t6O!K88C#TX7t7(1R=&DSOkIPj- zVSq|CN!!;;_I8``-!Un-geb)Kua;*MIc!4p#|=Gqe0f_50=kw9L6X|0Q~)!kre!(_ zZr_wuk2VW=Q-J~M<$%Ugm#~84^ZH+6E=#Jd^x?wc_%Xj?>1uM7J@_Jd<%2BDD?7eU zcJE~OnmUW+W&448AE5>U7Y%Vk(xPs7iwkT{^^H=%`PFx9D+7)(98q<^p` zcK`NJVnyoKi(JhR8q3E!`5^_*a`WU2=^iH&YuMAG<1m+K{aP`Xp7xa>_#HlroY%sh zt|50~?qp&XoJtc3LMwuI!e2=eMcW8dI6FCc2$G9`7}K!-sDOh&JJK)L&ncrrq6OCG z5*8$Rh5wcWw08Sl?dfK)J8T4=|9NiP?6`Y5;b+Z2RUF|&lu42!E7Jb-UEaO`L{M^O z1L96%P@_xjk-ge^p5Fo)eaf&zCxQb%vZ6Ry#!>>>X3spOI05NRllKl>YV41MT(MA5iGo^aTC`WL=DV|16^R5G%-LL{lHW#2XbiO2 zkkTsF9(7{4uY=DJIRR>B*B5RE=R|JCg4i((sXgnEuIJBvm*Rp{^TnD5XE=^x&ImP7@8Ou z8s;X-ev1UF=UB(sQ~oq~Gd_)ugT}0(V6RLf5xgMCU6jtl#WlRd5Q-3_0}KLyG1aT2 z4-CR+bLSEgu*+v{+g73We8f}6zRx-!>;!f3sx&!#ga$m&J06+1aS2;GU#)q{W6BK? z!CsG}`B+0;fgcc0XR%KI%?U+}jdbLFdDdH-#F`X>H|&3^!x_1gX_Nrm;&rye6Bm=T zuJlNbah$2&Y0L0aKvDAwd$xVK2eyLsp;6Z;>rBDFing8D`)n4rD|3#g7;@3%Z(&P|jOC<9Jd>+9<<10QA!2(E}_7f;-*ufAkR zq8W1p0e_>h;p)RHA9lP(u|85&@m3%)&f2#7W=cC5^=+KpnO`@5b!slXc>j{h8@7kp zac=?oF6(NVA7lTDsC8jJ{yuN-=k7fkj06)UQnrNh={IWI*}Cei78njiaWF`l9w#&U zjsqTy1TdNu$PCulL)7EgB!)J%aq=jQOctW`O{XQ9Aj{HP8w>%9WSDW3I&U`#2 zN>kv6ei3_V%)orHi#~sd`L=8RJ@efk_%bg@y)sfE`)!zWQz{vyU|ZG_%ZZ4otD}_S zdFgjH+10h0*gazG4B@I8!!SF(i@dU{!?l0Z2V5)9xdS9=w$&lJCJ#h&K<_+Yr z$0DYxaC97m7A;OlGQJo&Uct-gd)jfY5PxJMLai^Pc`gqfqO+>_;!eq5St*dI!Q)p? zD=>TAdSiF@64+a1>M)ua?zdoPytm0c4Q4d>^)RymDg{&XZYe^1p@Ws->qGoET(tdW z#i$K?8)k7NI5esiv&EG&bYdhYG-maSZ>XbiYu+*c!pIJF5yzQll3J0ypu;*pou2NQ zE+W3J7rQgFx_rbw6Z3nW-2KgjJZ&IgQbNZR)NjB+Gkn{**%Szf3qive1lZEOsby}O znJo!@Sz*v?7AB$)U7@Ba;jSu-Utmz3rF;0LmG1fyiYn$0FSqYGKj!M$gPmYVBcHuJ zYQKV@_Rh%fN|dCR|zuT^J|_V)4MizU7PUu z5x>g0@9c*fFY@px{w4||>|h^Y5dd@2SmxH=9LGab9>s7QOvn5WcX|GT3&^duTHN zsGz_gWTenHwa~xp?@0$N%kXrBN{H>X&3DInaX}Cj@g-9?bS8{qJDr?3<&wFO3Q?R` z_Cj9X1T7)pqA?^o7+D=X*oCx1!fP8FRWj&&`n`w*o>=sWDlOjR>3%c6Ip06AmQqbtI#Ai zAV`6^3_wTYvI|nLS$3d693eWm`sel$Zfd}wwvhrCa??o0iGm}?b%-4#Q_4gmFwD^> zx=_1DHa7kKr9+`Lva%zdfe$ZU2SH;p`VhM4X>M6+d^;qJGUYdP65DW~iR5$`3MVxh zXj!{TCy3+EO=5I)^?uVia&(Ph{%OKfl_PHC@e2 z1`Sd>40KBuP9GaPnU55exaR{j)6K5Rw79ip!n*zG^^gga?{#JgSNc7KcTqw7cFL=J zbc2GO#f~I$QJhUc2?AU*aSfO1R~fw)dLkeijAya~&ShaKt2650{&N#c6M=?St$Z?h zB|P@AYz_|#m$IUef9y%*9sE#|a?dT)$#&2qEF>rjA6o>#z4xseEXwonIzI2 zIL@%bGz|sc&Aeb8FTsapQRsg+*ERS${?CK8u%N^Gn5|qfyilb$5$kHv zBG(}u8!meoZ6@6CI^2hRr)0{Vv_thqiRmBf_mD6HN*IlEiUsgZ)ha_jAc}nxXi!rF z1gu406H}Yx2>kDXq#jTF$*ZGvK}UPfyd-VLK-LsZ0t6?&6|ItcPzrZ;^@u=}92PV) z#?00Z%WwQb#v{dQAx!90~Z5T+#b<9C6@lUwT{x+yr`S2Xa;RZ1+TpeZAcCI0|I(qJ`P8(zK}d-=Ur)II!^F@2i*^qtyl*#ImRGjb8@dP`96~dfuL{scWxGNUIB@ zy$ul;$nr_`PE)w7t-l zB>|$NQL9O@-sPfTwtjb|`p>4-`Xe=D$qF?J@t9gN?K9NBz4>|Lv5nI4Oa?@kr)>53 z_*lw=!=tRt;~oc(pOwgQ!Y6zP!HjbDh}*tr5;on?%u{~M zJVBJkzH?g=c{#)$$1pNgS4Wy)=>5RDSpPCz(CxZQ9D|XO0RV)o>WvC@I1i`4@Y{^i z0Q+&!lA=Lq#0X+OI)0KtkNO;gj?XjJ9(j+K`HOwn2UF~in~xoSeFQAV{j=->>UXV3 z)-j+W*juY8r5qB<*?>Sxe`p^!RY-MKNAVmuMjD-&dxdU+L<>Ol6JU=31agKMFb^!? zFX6RrIX2$dA%R4HmP>;^6WFesA51}L z7(oWPJJP(w1s)94VEs?4_kVLYK{KU}fNJ4WvZ>Coqck^iJqXrtx^-%d3gY3pUVNdP zy*VyWLQ=yfP9<(S#=uHVJvNkBoF8RzPI>(vL^R=Mys^0<-|Xk>$tXWN58E?_C!cOx zbfTyR5KGf!%ChKTR^0jOE6gN*XQ2?;ky%n_|M!N(oh5MO=f4Y^J9SmlMD^lvs1tW- z3=gN>yZ9ShR6+7dABS2FGm9hh{ZIQf+`Q120d+o+w|sUSGB! z!i5{FC(KQy!w7GKTO z{Gv*&G1BDT7=z=epf8^tt?!m(EvPB=NXexDXx}mwq|=g!;_507n!obK)bU2?m|wep zQsMOZaSpO}W$VgDb^5Qu1~Gdl%0$s)mMs3qev<#>7+-X#fK93cs5qK7u(O2#cDD&J=5d7;1HO zs2h00+IO|u_dK4?8m&#mIS0pUTka4~hgZh+xb2O`ALNt5>FXbH5lm}D5Yl+NaKuDt zTLX2E8j^5JqkaLR7|Py_{Q0|YxcN_taa#T}+V9Yd8(cHhX~>=E{of;#H8QKcYa7@i zv5jOy$>Gy!dzLi7lDcS6dBN*N>4N|tOQ+^Gg6aXYIJjLTA}Az?DlYcd{g7ZhP&_D> zbS3F zr_%tY_bywF=pQ#kz9C*byx9=YAD&586hvj7JF|w7MA)lWA#e7cIWnX2NX-JA z6m{91yQIV%Unxg#BkvZ#{iVmLoXNA$U6vMXl_Wj~D54bMogk=y9SWv_YzY#IxLc{Py12u477iKZVE{cFLzC6QIEpl@x||GS z&$pS|mLNZVN>#1%?V7EJuK**TTdU;vuGY3KeOJ1#3!8pBy2ewOE=dw20C5Me*4IA; z@Rpa6z?Zg{<~R0)m%{e(e$tTfuhI=baVkV~NjvQnwi{R9Mk66%k~4~g%i8AVK<@m^ zt0oV`FXx)~-SR(|{T8 zCG{r*VwU2cf0jB77{=4fh-62<*&fxj z^_3Uy7>wc<6eXKtHBaYAv-|>|c!cgu*Jk;iL0o75)!OE0E^~58S?K8{G)R6b zI7k2xYqU61Z7@OGY`+C4J_$@N@HT-&uH|D+s@n7B>w%chsq^cEVy14)g`2mzH!WA- z$>Qe2GxiH-7zSp)+uY4Om!VW`qLDrwr6PV?oOoA!)SL#8&fxbUt|?A1{q5w1 zY6=&^M1<8jP?t%cqgIo~orI{B&&-51@Rm7o4vYc94?)qI27bkYdpN}}o1+fkxwX~w?!d8mz_d~OgliiWMOujfvTF|ia9 zl-bcOFxVNI4I7}Y$Cs13vwQ{vXzXJQgoh%`N|tP+BJ@f;$Yxbu2Q=;`OLhoR^gHg< zbSJtmc~;!`m2`DDjxyr|UoICmU)K8`W+K!93hW<-KAgYai#<+WC@A^a_69}?tMV~Bc~N>St*8%Z zrHsWe+j;lrTVVyvD(DAPIV=HT!}km+JjDQ+h~2Ty)h&~~j#0<+icL|&9>190Qoiwy z22BBt1Ig` zQO`oKTO^w-cSWM_p^RNLQOj~^Z*aE3^ok7R31rA9> z$~1E|PUGT*;KL+-@hUetdAEpk`EOcCEpP7Vn<`n8oUANx&Hh=|t*Z<;;Co#m4{qc?-*`Us`Y1p#HD-4T5~q@h5+*&NE1ZeH5k9g}Ua1^T zpA%<4o9wROjyEu3j9$UY$TaqQjyLJ@xKQo*_wBAP(9LCS!dGr^RPh9eTc(F!SgaE< z8U`3BG<>(9YZrmYK|x!>`~@#{VxJOX*S2M>X9$Gd*;+Qgc&g&vJM z!-HUO-SJbm*MCWSP%`h)=~a6-PHYm0hHIwSGrSTljsdF1s)R!pW6h}i9+1h$PN6#d zdLHlWg-yF| zy|}Li&7Se`#Nv4azFI!Qo69DxkN?}2kGd&z^)psT%->>!{WgmmKm^o~9j;&<_7 zw*aN_oEu%8AEaqqsAiOBx$7i<{|N=F#Gw#iB_~URB^{D+aNx2thZ;C%;bxHMEwn!e4VFPn%H_KwQd}UX`Uix#evKu-dFK=`hCY^c`HFJ8U zu_wj9^|L_VyPiiTTLlBFp}&92HiqdBYtzPm;n(+h?eJ~1&meGM(FJ#))@(uAHlHJ3 z?+cz5;k5s{S}0=39RPsQ=$>!??gJRDFe=LQ%g!$!jWA&FKl= zUfq{2f}0fNCyr-uT;XqGVj33j_Zk`y)b}bIs4>n8nyxIvX?7SaT_NHKsa&0NkiaJZ zAnrDQu}p-h68z3m(KFWpG9}KEsc;n?xZ_B-z+kRjU0rZ;RK5~JWtwYU9lUA-;yT$e zTYE@=SFl3Y7L*l*_QQbGoaw;Ts<*}cFrLr&@iNm{-yXTKj`d6gr)UOT3ol){t~c)S zIh>(~y2Ggwsdvi_iBqidn293OYRu_+5T;9@f~~WNV1!=io8}VPBT`b-9Z28>`|Esz znAZu6kN3e1)5R6J_hRkcM#r7QrtzW0L}(91^}mZO%%_f#)5iFp=nMfEH(lc6lpha; z-qcP#M~lHF^tH@8_=0Bl<_uC!DGJv>e>D> z40hU*oaM62rR&N|N?4W2LIu~WvmQmr-oMS@W3LrT?Eq>bV&Levj5gn}E~c8E4Zv#H zPmfQI;T7P7CGxHuut#{)~>_a_LA z%XXiA6N}%>yXEU`MyV=0rPye4CWWFf(91!kc;#8C5?qRj!!^a61Vk_q`+-V9&^O^x z4K8tH=J+y;VQ3$-l_*XeC@IKv-SLwDHdTMpTy+1$K3S|Y{|j;ZR&(}LU>+1nltP!S zaiy;F$mI3msNR3tz&`F`gHL&<$GImae3|I#=?%M4yI12xo75n;GD2ZBi~0D0 zN4k_+A%K8-9z#9J$J^RrxEukR6wmO5Em?omZkxgDXkPd9W%=ZFFYsAbaf~!HvtBKX zmE3vCTz<5Tt*&HnqAK*U_BndWd;3bT9{x9C z33cqoR>qT5!+U2y7Qbe;b5>|#PI!} z^?N*;7*)!*CBMy_P>9VQV_U|PG%%t;jkY;XfoNb+VA!vd(pNzV-Id3C+ zinHL3;6t|n;hbwY3di}^(T$*fXVcn*2E;NOrc;8f!7@#Uu*?i{RKB)wo1u9JcAMl; zeplk0!xHw(N*tsfS3&kG`YBC9yjV`l?$jup!-%+v=caoBrv#8BBaQWqnZ8O{yST@y ztYk(<0&&{KJWLtWpxYxIEB-6&o@G!k+FD%QF2Qa=OXn|?f_z>yOrPC^qShg3RAVl5 zuKVVJmHk=+-V-8GXj|xZvAX%M z;5u{ErCSVQflUEV@5aOC-w=La!;Z8mnpMrLayi@jpANKdNO}f`V`cMW ztf2vBIos!^vsg_ryqZpa7fL! zm+b7EoSeYNRUjhuzr(8Kni;=)#BPWpQZW-eu=7h}3%mh!RRY8Fd+CcNkK6E-{Ke4` z3b%FzbX{-)btJ+X#q?IX{SGhp##UBzf{I{Hcu=ts#4(*A-%bL^hAt*bPYJDI20e8N zHN7Ar%hsDrz76lYP{AYNyW^XGEl<|3*9Ds$&zFmvPYQE|6_L6rUS2L?@w@%~c^0;S zyPtun$Y=r8`S((lcT#KTn*ZM-R_$X*jh0UloSv<0wHWmIriiMo4=;YO+Yq9f|O$zq`nBM=99l@!j(e=stV*C6k} z=|8Ofg|f6bIluAP^r8Gp-%}7yxbV);)NY&o3GWB5Uz|t*Gi#(#5nn_J;sU{R=0RzN zhyyy;#Nj=6)Lf|aGb+<}>Nqqh zE-^UY^rJJTeROb{7X(o%6{3v&@Va+EWFs-b@_RLe+cw48du6txC8Mi1HM)Fl9}=x@ zn)&MWc%E-`O%4G>Cc&fMnm@wNQ9YD?XOHaN_fJ<-pJV_B)Qtc@GPR6O_4B6&o;TAu z6pYx2h#b?~pBR&7$4!BBi1aR1*fsKJ8VCQr&!@{C`C?Nzimfb@D_cK~q)t2NMEw55 zOn&nJbsi8_(}#y_V@p*u+r(#LAm}N)ze3y$F;ZJ zaet|fvSb2Ceg>58m6^pu+3Vt{{ zB|knrQy$i&I+67D^7_+r=9c=;W`&~Hqxe)y#%~2hKkw&zDuN#~E$`_2u4fe6oYoCY zOq|`n!z(E9rP{XG;7Kj^-g}J{E71rYDK;ASPqbzkmK%>#zKX|E>!rqRxq3Ac;!C(G zI_iUfgwu`Z6-AS!b@C}YJ;TkfmN3_|jlMjxwA4_&sZX4|qWfv!wDnNglcs-!!G{HN zp4-jJ4ThkDzT=m{0+OCf#naV?v(+y`V)+L*uUxMe%);nFyb+*mBv+%njgavHDs?@; zJ7#dqICV_abr)ona?ME_?;EPQ(k%DF%FtOek&B^MBVrJP9s9|NcK19yYZoqZgKaNn zU6GqQa#C@4!PVBAH!k7A`O9qpxe;xUNXo)|mTs)h$h&;@MBpqMq?Q6sA9AyPe0lb5 zvz}GYFgUA@Iu5y-e*7bOt#0=F&nL}vcYPkXQWbA+6a`SwPo?`d!Zro^!NgUd?CI%= zLybWeU%qo_1c)s@r*`x0iOtO&8)F@3LZd;8Ds7oTkw-67NhLYl@M7qZ_=6=`m^+q> zn&^RbFjBb$2-V?Kl`|Y;q3ubtX1*6*_=KStLN(MTG%Y5VybcZDn{b*QCX^FV%xLV!h4S`=v~=Mv6Wg_ne}(=hfxTFz`Myll{{R zbo1$k8-^jl3NrSJvmGF~#N8VBgh_GW2B*eDd)ywS(JFk=zzF(5N)l7se+ykry&XF? zPlzD;%H!*7@=z6+0;r=(N*jR2dfiJv$swb=IOL#{9$tSmy+!@e{CYZEg3pk+|J%l{ z(B|_ks!$?7(yF?5U023ew2rH47Fl0k`1JJqyrrby%gRmP1?9^|xG+v|$Y;KOv40h> zK4)ItJ%Ki}b3~8>eQiQ@zqq%GNVvcrIoifxDg!W{4KAXL?G1ih|3GpHUNnsaf7ow- z7v;DQ_r;af)dUO(B#GsBr(*5!9Gb;P$kf=O!wR?ZQN%C)10(V$N%=KnQ3Jia18-jm zbp;Uut*}CT71jhKZ@u$fw~4&x^`$pcZ)RQ1$a`<`rfY`&;2VSy1rwxy|k$rP_8Elzkq zoMbtX-hUF$( zqO0Y#lpzYy zf*V7N#f%n}>Pzsa^L`>^;;3N!Z0@6liL616FTT_E@+J!yX}9X)#ATZ5IccWm4t*t9 z+>&!t;z=baWkP9mHovAcpm?#z3ViR4J{5U|R?@OUoVmRIQ8V3*ikGe5_Tv3o zx}5eajiJ%l-oef$MtDM$h%z4KIoAHDc|B4nu{H1kUaIB!8jzaf-aKz|l>N`IRqQ?G zM!|`L;*Oa%(l@`?!d&Hlm==E64MZGl|DKCcekOwXV>6r^Pwwwh=e-lp2X_WeY`O3kOu-fu zs(xC09cA114%iw9SIqq2-nCv`H-DhZ_vGf|RphpHTTUEIlm)n~&Hc}P#p0OeFwLgRbswVe)vx1nRIPYxu16O#`cHky1WK;k}#nF-RQ&0M;w@ zK0mbaILa}CQ;+dCe6>(;Qsy$|-5mW7{}I+bW3k=7rAU3Q_xi4PXX8h==vE9L{pwkY@*gc(v?{*J z#7Fgq^jo|oqz_S;6+XejzGb{U5v?%RLzL$VeLUI z^4Pqc5X;kR9igtrNPBEgic<&YGs;s6^0?vIj@XHA4bi50b4?i<%NBgseEJWHNkin; zR}kOS(9qShK0d)E)R`kv!plgZp?k06{k;qItT-i3K2g!;MgiyQo#`yzoLs|P-4ATG zK}`|fSYj{BkCeh|C${6MZpV3powZbB$`N@W*IhMT(V)AHT$y0L(N+Z`fh+i~2%|x@ zvH~VAg?zG9Qcs_i=cG`@zLiCdlx^1EleCFsM=p-yaEVLqc{9z~JTNp;I=^TGU3D7A z)j;{{1e=f|=#>HCu?k?JI zQy=lf+{OF`E4B|xwr&@W$nXjl|1&Q^ied^{pW8JQ-m|ldwfj!_CPu-}r*A>i#ADR_ zCu@-Q%F#$=Z853MXpdnmeS8J9BDS$*hixOszK*SBnvR0LJzN`km{DZ!c|7eJk(FIH zu5hH5L1&ueqz1^Kf3UGMkHg$Hv+-ksu(M>A%cHIRbQDufrBi3%v&H_&^1d|n#~-t} zAe;sdBVU|Sx|94h-Ih;Az#t$(d}}h$8q#t%zCVBVd?8lT=f%2D(9+Z|pr^=`gZP)J zn2xUZve{ODBDpNL3=*)p0%o?HU9$Ybhx!3r3+tzpW6kkKAlWC@Ts+^EYcj(cj9s*CQ?G!Ki4vXy` z*1qCd&*CwH5ak^9h%l+>fTf?!p{ee(ry9;zmn$377vE)t?kF88$>LG3%4?synX1b@ z@`p@qa+(S;EZzC9C!VYmDNaS&M>sKkA;uX?olMxbts^6|%bfg~c7KV?xdjfuhn>|4 zci0r`eFgqkHCX-oF0Z1S0k5BQbvYGDuo|nv%*d<3V;s$_klIutL?_9(|HIQ;hDG&< z+usAyB`w`8N;lHoHNb#`4Ba7}(kb03?a&|%0@B?LgS0e=bUpj`Kj%DLT)dnY%--Kv z_gbHIoGt7@(2qgK!)Dvg;&3A(%u&^egbR?oaJV?#2u{Vk&VN5&+v|D_x}OB2%Gi^= z21O#06!zifyjK0Ewh4`#6;>vJ8k{&`CZ=k=3&R3I@;a{UoE(kT><@MrY(AJDdekRp zK0G}G_A(CRjwL|l6;qvMc}%x+ArMZRY{q9}L~1zic>12dUMRw7iJ0O+Mv(v>!Op)$%^e0d3SkHaC%Jj47@&#?|S&)^h$w& zPL~!&Vq{Le)G$p9vd=31X5~LeyFfdqTDx#hg4$_3d!v}tqQHOj_5`V;sWtxNqG}|a z#QQ#&OCzRD*{Ut-JgX;8G*R$?7@Ln*!r{)|uGLZJQ?HL$S;FTestPd|rouvAu8Bg- zp7|oYa3<+g_xererIVXVMN;%Q>_mE8JU(}xym4~sq&@{g-EdZc^&dPfraC4O8QPD( zcamZYc z|J-2igzq=8BTzWI~p%s`WuCI^kB(c|2zjJUj?)cFP1fmano~=EdM6-2$Q6nM- z*}DDkC*N_P2j|SQ`=U}5v)kp&6}f<} zo?cNTCIXr!9@6t@(@)wVMT(p6D-lCW&!&n&p@bk-hc96%IECLEOLT&NU+jochk*#` zFvR3b6!+dsf#;y zB!r^^7M&_Luk6#yVDhD$aAdFc<#@r>=-6b5Vs6}z+fD4A`tjn%sqk)b^c4v-Br6kFk9;(=3^;pQMU@|{SZty?jSsx;J!_kuuIEE7@=r5W)F;44DVXV> z?)dt}hkra(wX%`SzcK~HRglDj6^e#I7+pi@w*7Ir#amOADS6mjH@zPoB4Y5#OzRyX zl#*OdXMxNVAr^!W{RfZuO;fLc^@*0AiLOM)SA5x^tT9CUo!P|YCm3{2Nl@D;c-{M)Uo_GI{JwC(hfJ~DAK(Zfi^m`&F6ERq#Hx*n}1!@7w zkfDLxX~H7O5E$wDkR{oXOi9qfaPb83IX@wRkgj47x8i;3dN@wi9~FbHCgpp}IwRdw z{D7p$OWlp7Y7*mO=9180dV61*;fb=Io;&#L1JauyP~T?kCpp4!rYvKY%slh@I|8Ur z+CO^pBGh4XZr51e@ks8k_Eap@B=~)DxDrLv*8dEYPf1se)}C^TBFIToQ&YizsvYqu zxYe4&WZ|*VK=pCy!+w6?{)28KjCqob5*zU~I_`(MSMQS|t^NIFETa^>o( zzu?><{rWiOqbDL=VE9idOzP%VEw~A(dTa#SNuImr;puqdsv<1iwnKc41SXaGtGVmB)0n@-8vwAA7)~9P&2pbSH4)EWjNq7c^uyynGJT}077Q_nG=w;E z*+m|lWESMJ5Vx1d>-EchAiegLX}hztGo&~7Vp=RYnD(r5(}TPJ=_vjGyZ}P>rKnNl zJg%y_SQXrne1~oy$=jxBVwv3);xxXtc=A5=ia)Fbx*v7j#W)4{H@S&B8RReL+O8el zbTovnoMF3~(0n53DYsUcUa7QD<|Z)@QcRRkmC`}xL<(9Jd2rbBo*mn}^5Umf2VM{M z1)f3M*iX~AhM!yq?$~(-iuq{@A{A693>5KFurX-Hpy4S> zox87WV?Q+Gc1O^UDbM&IO0N+Ht~%t6gz(3RezP!N=3~TCK-w*M9Ue608re+5PSwvFG4DY#G_*Xi{SGu_@WV0W$YRG%+u{0^F*e{T$P ziVIUTC)dT6$r5ox1r`N3OvFrLQS5euq_J`chXjw};vB43m|V4>K|)QM2td4?i$d4! zr8CPIHaNjH% zz-P3w3k>L|yX1*{{Yt4{Bg4co(UCsU@r6nX%J>V~!1ii@Lf)80<3{ThakqX;K!5Xa zP0f|S!bnI+$a-%lYRNL|Katflr)$g!Q@_tGUCpx-R*<}#$^3Sc#zwC9y^YTU)|V7j zRVC9BzTSaQdU_ECU$2**RdK(|z=x9!?>ptL$42od1AD6kGVt5WqUZ9@EMsdoPuw@< z5(=?XpyIiS)dKvcGQ7B;y5JNLDc;nVZ~Vnf;V|IGb`MM`rGv+C<`c?*g*J5rkh_b! zXAcA$)M%pmSXeO{f)75kl66jY+~lg5gd+D8^1*Gk?)*+W12^}oIQ%a#)889ser4`$ zylQe7m?b4OOta9AsAR8R_d1=(6>*=XprZ0Q^X)WVZNd+}p^|wLtEmK>(2* zUZIFh+FB+O578H3BqM-ibu@$$Z@$bdpL`Py(KlmdG_cPQ&Ft|<3EWB^yeP{=%RR8D z`^)@n(=j>{c;mF|Q(ZlF=yuocLQCBHL(K2kb(89W8l+L>Nh^2s7~y$_sI}fy94#|= z7=fAICA`wNlCmbA&x?Hwf z4Fx7mx`Yj=i6MKr%?k;%2-p;R-(XVf#pOs~tS|HsXeD+IKF@vOmGs4K?c&Bz1N%fo zN_ACw?=NRCDJOpIklf4Q%k!!?yz6Nz=FR(j=~y-u^QpEljF0mWJ6sJ}A!jUnas>pf z3ViKVrN{!Qf+?d5HI3=-BSeIf={jN_&8yrCuXH3+WW)ZD*iZEih%%aodSj9wwKNKK zxa|Jo42k`9({;7~gcTd^!=E=<$|c7+(UPRv+PN;}@jMaJb$)4bKhnQi!`GBknEWh^ zwdmq-(#YX|*Y%wK^7rk_)}mo};Dg8uKR>N2qn4WpHF2h{TjnHcrpXzRY#!+=iC=Qa z+TBaGvl26vXiabYIf(pEYmQcktMfw|<3?7Vyg%5iBy4&4@RFWM+jeN7luVBmcrwug z(f8C`fy4?1+5zFxZuVT6>LF4c~Pyr*Gr9J{XX$!U>zLqiJ-*>Yuw|52~q#twQKFR~!4OA&Ipj5HkQ zdIo$1yM;)|LG5{*5{oqX3*_(+5aK*2i6es$yMrnd(%!EPehp=woTl-hA!%nuLjmC_ zAfz+(l|4qic|MAH*VxaGkGEMjcgXr?Gm$@d*6HafAnScm$xA&t$`%pvz4Wd^%mw{$ zSbexT12CtTy_>ZTtM6IKKxmX>NGeUb{}%2)NFPdW033D!z%2?uLpkska>#`a4WWEe z(G&zp+^;H-)KsGrweh182!$u-`pcTnL6QVSqplizYEm&XSiTTTcQMlBW_$`zY`mE0 zO8$D=rC9VpNZKMHJ zzOBeT>5IA|p`#)3-yz2Jx@{#RKBvN^X?6zkP?sxrfiGtP?fGBks@|=wWi5YR<7GX2 zeaIB>?^*tIE0^OrIq-Rx<7vc{b47&AN*=Xn`EysbL525p;2HcH^<~eq;^gF@6ZN7z zukq3qo082PMyg53scJm{-gD&*9SEl7l?g)8=q^8Dcl_gVz#>4pv6ET5NMoZ#LJxf)is&%%05uh5SI9pkj zv5#g?8g&6vhSqWS5W;LG=d9*o3y6}9F<(f}?}aKuy&98>)jjm{3--dlXHT#f_G?1C zoCxq*jh!)?pFVv~PLl@07pjwGI>5bWc7kVDhN z>)crL)XGf#-->W?a^2j^?g6EosLY>N{L_M=mGD#mVB@`u65cuTlacUr#UL7mEGb&QlEa zyU#QvZZ9fJbV21#OOAG{X2Hm}a4=0QP699}U+8Ed&?6XePe9GhJ-O540Pw5#^KWX$ zqHk@3T^zCop3z=Sv~#Q?!b;OgWHS@6FzL=e{&9Bl-0!&#@ojJSRYkK1)F2c}tXtq! z^*vc>#08c#$JOwQTWjH5m#y4~)hj<7v?s|L@jt$Hz$=)aON|vFb|#`n0>zcVFB_tB zS5W;eTq+zoM24&{iAUhJU$kbVg(oS&i4$GFNNtY7Hz#yhJ0|KZl8-m!u8}Sa2WjK6jIsX7kc z5QtO~AN&a?%5aYay7~zMKA~W$Y+T3~Ywe>gk(p>4d!>K|peX=qL`~=8h%yJ96g!;4 z%-%pz5j@@I4Yq)IJY1h-3pnk0!x`ZpmQT;AiFJ*${voozTPB94auH_jb>3_s6XU(_ z0CsvZpe1*6E;+*FJr2I;m@_}Ku?jOhN_crHb0tdc%(>F1yToYHY;;%i4k-ssO4uJ3 zA10np237ah(-Xb;Z`}g>lW`Y?05$ARoFo*KQ~;+WgW%z~g||dp64e8(F&U4;duw;h ze}wiAY5A6RUaoS=ngvB4$!e2@WmswM2t%m`*d221n_Br_Az0U+@3!_U-BH~g*CR(Y z9e-E4?)6@J^BmGrk;ma)c6pStnW))9*HVZRF_}kN zTv%{TS+i1>H}mG_pPO!dr6~VznXmHQ-{lt5nD+=bhJKB83lB=+LqV66o*Mp!Fe3ej z@!dQYOFWt`D2I&+35jU4oPt+2k%bij4Z$5zLwX>AmX0AZ5rKw>sYD+P-g{iQi!*sH znKb$7=eUz32|vbJMKdVJ4QLhyj@1Kudwcf$%B)1Pc+ij7y6T3?G3Eb}OllUh zc_YpFjF@8l5o8w>eV|Ex=)eq4@ZnY84OR%Y|O*b&z6IQ3Mc*K{5DoGiiC*_;%+cNDQF zS3cxLU)-jUtPL&qHXg@K^2Y-m#43*3;37-FZLhiO<>@T&-}L%x@q25r{6+T<`RdZv zdzS~((~=yM+)i3510*K@GBRn8u6!nd0_(j?AI?ZUAa?D%DV1gcR4XriG@Qh#gLNkNB)&UYujqD;b-lpVf8O?UEV%D3%B^~e|GC0wB74%7U8 zUz%a6d^JcHECGWh>2O6m(@D^?A|y7Z6}t1gO^|L+;R=^A>ncU&j?NS8+gl-kP@ewA zzjTS;Zf1*<#K~py$ji$o5AT@1)K;%dTkBxSRkJ{M?w)DMPn;b1`MN~>J$(Y>t*+#p z9C)a;DpfN@5;XMK>qt_h3-*eZsD!ba+MJ&wu8=U72Ae zV1zQ%rIv2Bg-=~0{BUsF%qvluf8}jb*dN5Fp#{dXj2eq#jHckQ8p6fkMxY2SIE z8w&PtYQ7V5aXTHF^y>Q;gmd|(z z0NiAAS~D-*0&@KjHmSM}3L>;vIC`_sVc+SsA664^wTP>lwhTiDQpU5x?4g|blUD8) zi39Qv06(y(h;bN*_oOYXH1oQ`jN1u@D}|3s0HGb8o(PC` zSZ$&W%Uacyk}-!$BO&WRu}L))D=TL#_Gm}ULUh4|X!Cf2jzOH-1%$NxSq75Wa_|0} zY8nZ$QOq~c)RCT1=^I%o516httq=R2HLxG0Ft0xccy_!RG>Y$pfe<}Ed@hHvbW4&3 z;p5>mF3O$dxLN0nW75d*Di5@_yKk`AymGjf(w(R4p#%<7a3%?a`k!DI~G!gBD zOY+fo!QU>*?eNqskeVU!@qeS0C__RlL;*!Y@RjX(o5*Z2_`)P8!eyPP4!;Qq8}L|1 z4lS|U#0()y>fkf)4gG@6IGB76R9aYh&o7Bgl%f3>PHP4RXL`QjF!tS^Uj*7)bFFYv zq<2W@dER2Od7n+1w0+**1M+k4qZDR&z4Hh(XL(V!*NbT?{OR}_p9@hnf-!d|_B&E~b1r@7=l$F|X=Na1eSJ@-9ZN@d`!T`u;>J~{tkOl&yOj=(-AIvmTyY`sDa)-SF1abRl z%}!atnYIT~7Jwju)SiC59K9TQqMHj+Aar|)QmL2G-QOR*SRbv0F&*@5;*se!)ACl$ z^3n*fyRyeLIUY6Yi^| z1?C9`GnpS_-c#NzC90amx*GxH9zWiZ9O&NE+yDfm`b|t7 zb!PLN@f^?0X7gA##F>RL*7+y|2|P3MHXfCnLKxqG2=mxNMnFxv8GDQwcV3jjpnkK% zDxVrxa}F#;D%%W;0%De}g%ORv+C5gOs4?}q2^mA`eKSjVrVwzy5>=zbh8>ipRf3CeWg+l2ktmZh5vW9(t=?Ol4 zM1qvUMA%)&DItyb1Xumdai_jA>kmrrwdnzg7~*eD4kFz8vie#|Us%f-$)Wq&bsB8# zvBK1*2-_@-2r^I&f>2za64YNCcLH5T<^f{4)?J>Ld*d&=CNDLU07_?nVszK}Uu*tL zzpu!{#$CnP*Ro6Bn^PO3nj%)L!f)R8nMv;K#I({IJXe)!d{$|=xp7;hSVGQwf6lv8 z9Q6gQD^ixyN@z1<2Tdsp(N&dH`xvNVwNuh~q=mjmm!@EqaW}|Xc9iIwHw=pw6Mqb! z;H90P(aOLSFfwyP4Xbh=AR*FsJy~Z|F4V+NDy*f|HzEJ|`5{aI?&SdW_xJPKsjOH@ z%cRVlcx?`~yBrwb2W$u|XzoU@B&^OCcdIG~Uh<=*D;qB_c7BCn+S%F3Z->;gOQTJ! zXwMygU#}W8SZnhX@wb>z(OcLKgJ&+@ZI%v4U7RcS!iQ(Q%ww>K>EXl4CINT19ATEJ zC;zjjn+0r7T=^KMEaEa5J@2QWyqU5{0-uJ`op01L#IsjkCKZ5`mqo` z5nQz$FG4DPTIIH;+M7!yfiApNH9HEV;b?-a5leLhBv=N@-HtnzC1d5GQ9~JP_;qY- z`j{vmSRT)PHvr5tYqS~gU*#q9-!|OvJ19y2dEU=q(((CjVzj2Vdtk5ia)0uSnqq8! zzWMo|T}xL!K{VsP3{m=Q1*Cx=HgM{H5~`8tNGJpJzs&s-zI^RyrX6cOGdw~LDkI=R z(FluW!)Q=E9R6pYXvoacCshd-+Lte2?HA_j5&XX20Lv8MVu&QOk7Vs@`-jK^lESn? zJgiP~$5H!H=rM`@ZL9$X8>#oZ+I?f1da(fx`n=G@m5TaE8IU9e zCAl`FdPikS8CjXk{^;@oj91LRi*qDMBy~#IN9USCmzo?B_9jkN1!_#P>;va?w-v2r z2+<g$!(180pGj=-bkCut1PM$Z}8;_Re!=Och zW*AIZl;UM1@VX-Z<#GSAkOBu4hMW9RuxtLuMXo0tP+66;4d-@f=x0$8aU^w+F-=Mf z<{1>|W%>U>HX`IclWkWzlk#ff40s2cCa(0EmgjpjX@S5J$m&^&CmDEckAmmnv5a8z zIn&y>y0~wunwqjDinP%QL|{f_Wd;!10Etx`J>8kBC9$fq0WKbzgw|pD9dKBMdjY*> zdez1J^X@0HM0l^3Fqk)cOg}#jT&C9;pS_lI$EuJ#Acc|l3H!g?-`_u>dI~Y_=LC2x zFH&ASuwGmw`$bZ}oDO>9#Jg`t4PpG>_wPouV2}`2BCSaXJn|y1o2akMdLvf0w3GXa zY&_y4R{i%fTIgLw^gn{Jc?{(xSk_KdF#zxeLkuYTHx}945XKl=R+cUrW8Yqje?sKc z(pOYjPV;mo3t~Jl2n+HfIOYY5gb^7}fTj$_UpBj);( z@O)W5S)o61g)nJ>8pCY`QfTaG`PWm$G>i2%GevSwniklQP_hLCH71?X3;s|NvO04} zB0MQ}QY{qB@X4xBvfdmx8(TmyXy}B+Z7r`voVpsjy1H6hh4Lq5cYqu)N9W&_n3|5Y zvzyC86$iUZy8abkJM8Bx&#w7}RC-fFE`>a9y@K1JC<4M1E>n2=g2eja=JRxAbRyq? zb&jbDB+Z24Yh+`V?u3qS0eb_<4YaOv?g?on@hYEPdP8^N6XBBo#y? zK^MFOm$a3PLPL88d;}R(xCkB0_#=|#7b`MYQp;vrxu)ZyHUFU%XpGVjpwNCpkPKPm zRsGFNf|Kw2JkXdeFcJ_5ul6~}>lD7EIC~rz2n=R~4Nzqn1-|B!V8Jjx)tf{Sw}GnzjR^W%WV0gd)RV*br**VX$Zx&yygtRO|{SSyi^eF_!Nl{z!Zv zMSa1N6x_Ovv$B*>cPrnT{iv3^?xz3q0!%NP@t#}cdGD*t>iixExdgjDUG&ffUuMJ& zZU=BW7`{ej{QOKLvtY2VlI~0nm516XNu}g$lPr@k*a3`77lmW!U%2n&!b(cvz=8iS;P2*j`^~AN`cZUL z$pmW?>r!#{Li{~_^cLwzy}h=*6uB%#A)^d8(3V9GPLewj^R`3gjb3nXaC7z&%+z&v zi2Y<5^$sE7EH+1EWQ_!h?G7Uki5!qfpTZ6A`|l%>?v~+Ciei0M z+=J@k0i_nJ|FKQ8$+IK?h7TH~qwL|7& zm$Iih+EQYtzO;1n+XUUA)(RPk=nSO_G6j`rY~^UhXqKBkp-Dj+sTr-a*yP)|waQ$? zM7UGPpT?LUFfW$AU_lx~nvkSurVw1bTNH5X3g`|=6*L9wm;i(KVLfxfk-g6Tnl)!7 z%y#WZ(R4ZcsGZ(>lP)hfuD+fBsc+{m{Yu#KXJLQmv!8CKA^9DvO%9d8tT-bb33CJY z8iJpf+6+-BZoYijiA|U52X09gtR>aEHE!j9ZnyskJ3&`%)QGDG3ebXCkctP>TngA> zENqny+7BvG*89)@if%T@)o~UV7CbyXQ9^oprZ=ySCf(!WWxHO3IyX7z8abkYE(Gz1 zS@G%jj%o-9Iw=`(Bvw<)Ih9-xxq*#!c;J3f{MVERfod|Srzf? z3y*2CEgelw0%9cU%veSq4RrVu&3X%@>9mUL42HcZ!LRx$b2eqN%(qXnG$! zfI|UH_lmXFQg1@Y5s?N5B_u8`?!f#nQt36X-NP+|Oa1sC9(%h= zrI6`j8j3_@I95R<2*}U}#@S&kaqZwKAxv#~u4Fw|;Yw8>DVt$jAGWv1)j#B{9 zG#zLCVrsNPQYkzRA?ZCML{c)02%@@Q&V)4vGu5dA!AjM#F_mc0%p`hf*u3n}ez1=M z%#tC|m&frpCVm&YA{^mOwRy-$N!RgK5U&P2FP818p^ zPSo<5br;}6cuQk`9Fd(1vLU)y(-)Qp0GeJqwg2y-P+TdMcHf6zKAXQvo~_4ku@ZPu zek|asy?*`k`Ay*SbNd;gEP^ICZ+WhoVQi^NZTdGpI8Y9Mda|}5@+Wtd#3&GFB6kB^ zE1%AM_Q*%E;>_Err-~~7kX~)v+ENEr9bj@}+99(;K%OBfvUX02#em|6Bual!MNPiz zd=LR1j!3!0j>$MCM9v*7^k5deBwFqTFX%_++5<<>9t&L|7U(J9W##IvfRm^v0ISdd zJAg?UKuDi(8_oSRKX&?D4aAX$Oh+Olp}kvE2-5ZUm<-j$LkDNHE&`HdXX_1@+->YY zK92=-a*Uvt;4vy+Rp0OLZzc8ry)2kjzLC`g)tb{GmZx>XO@EY1U{p#($Hci9+}5K9 z38BYO%XjAEpkn^2YcSkj@r{*Bk3CjAah>I*L~q-XY@DZ_|JEP?pDDXWMN)8PVrH@xwB2kYj18uvSX(3ev*k}wOz2-9XXJft55 zXd|%VU<@=RjNBxW?v}A}CO10=%XPb&j_diF0Cxw@W1qwJMoCJkc@(>-O4?*u6g1I4 zM05#Px7V$h@ZO#Cp<#{*W?vBzk#^u+i->3#{sDvGW-Z%?2ca$bx1fN~2~)Bqkn9~8 zxCfA+g>C}{&XXhrz@x!8U|JV6)C1V*k8jjRkd#by7d z$*ojA_%1fOaD=Y#*TU}=Yv;?>Bk`M+ih1*`SlO^r8#5Id^Bkh^|9nFouI_?lb#$0k zVtS!%)t!ctS?Z!@p953V62Pg``;ffU6pN&cyrl29kl#>Q4J0?$rF)xKj?K{l7$)aq z3;pYO?SBoQGHWJv7hleLt|0zjUu=wCCJ!(F4j?jzG&w-iyZG!@Vt|sQ5bDlcDWtDM zN=W5FF?}WoDL54GnUEPkwF@4m>XNekxU`Y93KVH=>znFY zS`ukCA+cgGz5B?Nmc`G{#gy8i*XI!%ZSuU8-gU0r)l$bV6-Hu^8m5{j$w)`o%@P!h zAwzgX405#+3ezq4bH$E5GQD@dyI%vI|13;NP37R^L``)%$&`HOCq@~++JsE_N)F#_ zXXcxN0w{MK2`}o#dy`qd%I&=y+?P7{5FQbZ40nLJR3M!`F8}r!^}?i@U#r@dM|^t z;N*8=*Zx|}Tq(9vuJn>$EhVMn;wzTI&t@JG;Wm*>)m5g_6wzQFLhWE&Bz*+JIxr2d z0>7IDJ`J?~*DDD$N!hBR6hzVl5}ldGx9R^~YmW4)UDth%r0mT;{;Or$tQOI0~_Z5CXiK!%RycOQ`Cd82k1%`ElmNn&Ez4%(pf2J z?4}BM#N^@X3a(;TyG2Gb)Da5C9br<76Hk zlEfJmDH$Sh2>}!KpJX=&Z0?JBJ{>kTIcVEHJOxBv+z#Sh0a5mJWIS8cS$_j= zkgq1p{m=gPI6pn!DeD1{;}Bm@;IFx#V5Ulztu7e&`R<@a{x0$c?pwbQQw+TC)+6;u znif$GfByAB(jfV%vKxX<1WSE8m5RqX07Zi?Bk|+7jZ@-x4uYo9yW~n<<@ZHwlp4W`E3g(Tg}S|`jo`-{SyurNOe}H z!F!!QN#7;0J6%glidV+y<7HjEd*+SK8wptk(lg-@ar+VnHt6q}{{POy?st#K@+7N4 zNUSn=f2=KK8@x{+Pga|ezxNuxc8O0yBrn+}cLL`Zq-D#}AUF59H8AfXl==`Aq~41B;eEfa z&(C%3%CFP{vZn?;8Lcr)#z3QdFvkI_#)G!aRl~<*wMQ*46eTg%vVab?PRqneW;XV* z=+Ff+%@4vk|3Q)6@*mcKyiu;3QSCCT>rtY~;WYIMYZrK4L@HG6aSdTP01_)#gt^}Y zIF#Yf696jY_S_nH3HG%eS2@Ko#yilt&c~KxvGncmY=kR_tGovEmEjKz$6B#mWJkGf z{Fe(t+qpNbjVb#=bY$H{y-%JS{+@z=cE#EQ1KYo|CAT;BIJ^1x(t#UVuZ9KleedC( zU6&ze{>=`CXR%ED3L}ULwBbm99KONaKR5}I%Ck1j+h1R2iQQt;F=J2QbEBZBQU7k@HwjLRy0#$BSx=s!PG?h zWc4f2`>b=^Z}Fq`&^u9eGh96RaI7Gu=;_4el{LSM3BYlXceF2?{;{0B&?_e{DYxBg z^Z%KpjB~-8v6NIF5IYqO-K(lYM-5v8?W#e4BmE9AIEMXv^XCpVS4* z<9DWK|Guu>3*c539;kN&GpXV;%hBlmYB&E?du7&bbzUI&iqvjU`iS+WIYaAB6_EL6 z{&A8r__wa}UVP%CVK#Uw>HaMH=K zhEn99Y3r6&p~t-lCu)@nEG5T+-J8M4gGbAFoxzBoCXVJmca}!iTiuTIn)wL?1UT}^ zo9E%5+X8vTR@%Fo-2?+_#Yxp8j_46kkmy1v8SSy~g!ZR2tX9`Dd5icWhiops(4pZ$ ziSMSnRlQpLJG>B$T3&!qW@|RLYL~!wSQF4jt7$3u!*K5mJQC zVd{A{pE$O1j&d5>iD!VD$7=wlXC>O57Z$YXG?P#Ax&MEKt1^mq^#XH{M3`}n09hRD zLZ|hll;Skp)UUYW_y_YvlpL?1W31uV?a{i21640&eq`#CA+g<~RzH8VZ#G#0T^q~8 z{uH>6gn?5HHYxo_S7VF$eig|yw>zHsNHI|?B@Bo%#S&j2NZ_l>u7Ap&r)#7*5x|U_ zmC>&1rrKdOS?^)4|9Ij&#i!kd4$uA6G=@hKsSt(^*=w4Jf1jbL-SgaY3UK~!&rP%T ze;%h6#gSw!{g?&7joD#SvEi@iF>-XkyvSIvXbcNu5@lAI?Ml1cQNJ>6Pz4yTSR>#+G2%{aipz;c9>IfR1nR7 z8Qf%R+sjQ>^`=PD*-~T2VfAahF;9L!%;(ZDuE6^_=_UQMhB{e6NDZSay9KtPv@yN6T^qTMOU%BGU3rHl-?S)Nk$ipm#Fr7Wmi(c zOp!KkW6kIJZokH)EAOGwfm{^}W@Jl)YYD0IeqIAgXPTQP=rc&j?LLUj#d=sY|z7Ujt99sQl1CbTLTX4_SGH81vZj^l?*#9?W zF`o;XEBPpD`@tpn0iyfn(F5bHr(+M799V*m7@c;<+v!KsH9&{j|8GW@w+~+i#FVKM zoZd{a@9~O|wjW&yGrj7YeP{3KxVQ@&i7Ug#}?SzKCx3DIX^fTh*|NDi6hb*A=I zD@|3B$RP%ZR+T)MJZw_V)3s67(*{lu-;c6V0Qq1&UhMEj`RtPJ zEo$edQ&(^;(vZ!I^J9^~MrG;jn4t7hsWoU?UkkKPSRSV-6W-b5ENCxyBD!>9;hikd zTF=&AAL!IUJ>Xl|qdExx}S)#l`+TWQO$;^ zAYnaJfWRG2%vV%*Xfk`r)ZGPF>%>YM|JPRTPKQ{ z{zoo22zT;R5klx516(@!6jX8X*J!NagwSJb6nAZZ3XPc8$;lVRv6~DcfBzkvxSaH5 z(ySU}YuT>ym!w!MYl&TOCEg4Yss;VZ^vx{`Wu`3k#%B*7 z^ZDLcFqR7#XYaSVRXZ4dx`yZPCj0o{7$cfNu^3NP{-rRMAPw?Q4rK5Tv^gMj8yXTW zJCDEe8gZPoZ0PNM8osR+6=WYVUY#rc`|K;ew-jEA&Wg?qjN_o_TI3}2Bt^vof&@dY z3&QDuM)EQV&%RPhVze@|^dR<(f2#I&a!fS@Tey3=zs_b)QvGU4qtz!G$$|Joq8kmj zV1qN{4ildyNL(rb9_o$zPr?NxrU6p?5pK>gdu$0_OiMj7g1XcUx2BOkp-v6dZ$e|Q*a_qnTPmSR3g*(**ZXmJ82_w@x+phzJ zM3>Sv4Asd(5Ri#Bf9Gh=baQbUp4smmwNa%4n~4tb(zu_$pkp?FLG>;_#o3_#%EhOy z#gSjJWfrFjU*gMpqoLDhsKm%J+{B%lz3ku2$I*BhEilNWkrsUH&{HcJ&s@)90Za!C z3mHTzwvn4&soc`tsHUdIWPRBia6ydSkrZ)On2qC`;fAU;H?;ci0s#^`@@!Bz5uP?{ zPjZfqmPXis(^ic9NTZQbv~MT;Vlgyo6QA1bHt8u!@<&gfD(|!mLCq`D8ktxZ&Ogm< zxjT}?ctw$Jjs{|Htc`<3#Pf?ujJMtnWRO77BxNRA2)h#4#JVat=mI7@yecwo|79sZ z3|)4%MADRG4Nv<9ULDS#1-?8K9WYF~X_X&k;nuVBAX%l*PBxrnX!mD`Zl?*4GGKv% z0ACY7jmu;MTMAEPx$J85LubbGo*Ntg_4N&NktQ0gPNOW{ zTvIbjN@gk{*OGPSvRwA=>C@`~1RAbzkM^fOo5_yNuOk5?h10J0s0g!WiUqIe{lB8u z*yYIc8ZnYq4zReKU2medpE!YjRA{Vxvdj0iktbd?kER-`uh1G6Ci-QT=!j(LSiU&< zS5n&Jc^~}OMjo@B;Oo>>AN=l*%h^f0Gb)E-(wue^`q}0HXb>L@8LCVuO=Q~fN1ji^ zf=4-Zp=ddC(m@zOQYat=F!t8o{k_P|*&9fn%1tbnd*ti^p=Lwj{K$it`%Gck4 z%dE1~fqy~qJd-ITRva@tt(^Zx=##!h>L=A%+fz30nqIWMn(**6+A)LVYS^LogA z2>d4>D4MC_mxcgBFtCeLjHt4ib2(MZNdKq_CNj4Dl*}68CdSI19?_vg)SwVqheOL9 z!wbg5NRSaE1pD*{Sqc+_7u9;Bw zm&4PE>s%3_lCnt$iHNYc`sl)(Ldc_S9helo9Ou7`cFcb*lo=o)r<1qb|EOf}q18?U zJrXx?*7ev}?_n=T`L!TmgNx%TnjXUS|2z5`G-r^F@?~LV*}lo3?_$i6om=-nrtx)! z+F=DofX;jv-<|DL>vo~+c8GINJM(hgz6XkN<4z=3>1I^6bzv0K&+b}>C>%Xq{E`&! zl{I*lTA8mp)gt&L=M|!*+K=tR&C)lAF5&{J-u8s@c%#E*f8BF~GEOer&=8Ep(Tkc-JFF|R z^5Zo+c7A@f(YydX2~!+{lBE{D(ErENd$_Y5w*AAQMyL{d7pYBctvy32HA<{nwTarB z+I#O+tD$J@RkhVtL{U)`MM+V+_IkhfeLug~ACSY5>&SJT=VxjV6PKxBu97BpWhS3J zi`j4%aq&LxgnPBe1YSLRM!4aO8%hJwv0~nVR6nxkW=lEr%cbq+ukc?+Z5!)SHO=#n z#kUjBjE);gNl5%ySqVA%J?baMA0PfLmHIwSZy4Y(qVeW=>@7&!U%Ui5S1YCOU|M}%7lCPN@qk?g2T@38+ z+6&mfoJH6OtHv=bjV%*CfGKj^AoRLmIYGLglk zA@;k@%;CO1K6@cM(&5e3gXaZ~d7RyrLdP$kW^F1Lc<%ZvO42Ih(>l_b^HE+CPp?jX zA?(+4)l`C-^Y;XSzIynSv_G#j=A8)873SWQvLm)6%SoLs7 zFfL-%gLd^dS*lGVPZdua6&LL%QE_R3>0fIo>LI?vmlYmcTG%Wu6YR#xz}T(y&=04U zy_KF2Ky-8HXIE2WB~gkrmz}gX5`a^ygBf$SWAQmj6Z-LBFX4G}U@=r5Z`=XFYZ%UN z?tFwmtU4=OT317!EA^s^8M?d+NGRLHoT6ujwdF4UmD*1hjjQ&DI)O5bE%aYUM6WxD zF{BJHx%8l%5N{LR>z9ir>~;`{jQPyi&NCo{Zbn=F?a@J#4x9!jQQQhX7z(9>RvlYs za)(xrdxomRXvFos?F#Kn*?t=rQD&~|#?&tgj8M=`f&gbP;+3>vtyvEMwaQR|>2 zf-dwaMzz9>B&MJKnSI+#+(sF+Jpq$2;vq2Q*6TE9QgH{&KpstNxI zAUhpP4d;!ot>FnTnsjvYj-|Wd?AjM9cwF!?y-NoXr9HU6@o@Q1J>UXm9r;L*|qc=%+z!b zn>`OM(3>KqiP&#K8iNOt)}N`Ff=D0qZ}>R#nABjFzZ`a~T`e1WWJ5+x{6AsgPUB>QJ30>6W-`1baiB=iaT{u|30! zk&IED(i{>s=xX-MER06+plxp!T9eEr0l zpCF7@>o~QXUWsto8cypa0l^Hp5)aDX6tBCYE?Wf)JkdrDcmO)A0Lb8RY7XtgCOEVMxw(5P?0%n zQNg&4sH1oKp*UE4oKz6EB%IZ1x;PZfX0q;qja7qN*=WIY-|*U``L;)#B)w?V8ci(E zXcS1(SKMjO*W}!A-tOcYkP(dTKfJtbKhBHwlJ0^y*^zp`4e~nwJ-Y5>V3%hbM@$@A zo&WveRvDuP2_!0O7K|HC5wGa2Z+Oy6ovrKi9_eQ=A$Rk4hEK)a+PA{)P^F=v%kyq= zMHgn5M>5jtWbds2s{ro+QF@Xa^EO`~VZHc5HF?Gk)<)pN7x+H>=%Qmb5aUlv51 ziYs7IxrKu`(locPPA149Yhhz}_;-JQpChv%`trU!lazd7$onF{qHpym#wQ6@XMDuJ zHaZgIwX$;p)@D_=`r;3B-rnL{;5hrOapnULqTq*js}Or8**vYDx&5=V)6^pzXVt@ZIGy2qTBAussd(m^g40Ng`HZ1M}akofrIw}Ljr)#DYLCNmg zi|VD}9IP~HlI>;}orypvs9+QI6l=u|IpnSAI1A)U#zT;X=H}%m^e_d!=KSPQ z0$5cct2ABF8}~OjiD62GLj?|Mk~rit|2{;Q?EW9Ey2;XV8EOnNaPjWdq773CFQRG@ zRo+y3$n8qobG3Z7-|f94e|wX}a@VgdcR3&P?5ecAn&NyF!l4R(k#7k}>*b|@=jKUD z*rVE22Y|6{-z!JS2lQiU>FqJVw0-s-3$#djhKhIiJlb%JVyJ>MNQjdYxC6}+ffjIT z@+gRb{6+hp*M4ua@&sSq9o-H@ez*MJ5lzyE=X^S8cjHwX5gBWAX=PMmR;olvdCTy; z2!TI8WE#0j&-0-Le#^Y1pL~cq9;AB;L>~N^dW86oCTsGW3hi_+?e|WTB%YBP&6Ip3G}V}X(ILphv2%9Rj#h-9sh>ChBtcDypAKA` z9m!k5AGWhmKEn9ACX(FSQ8FCHXz24|@7MsdeKMzkVXL04gfJ3+BI`VGn(w_WI;c!D&g{^n@mxO0-AG95En zp{H?GZl)+fi4GYCgF@jdP=6cQMMmkvK32@QXTRIO+jD(;w&Z(vTX(z15^{N5eEZk_ zSq8b}E1P76XTvcz+^U;&5~>e`zk4Ub!C^W_KYjlbR+S`-p^MO`y0{#|Ebjm8@!4Gv z)1TQAL$t>CX_a%#YldYbZ#F2O@;)(b>Rx&Q5d9 zAc8^84+H*y@plu)Vxra0yOzX!sF*H4pZUL=W3i|f2j+da0GBs83=gMZ3?d#+oafU@ zxzk=<&f6zkmQoS^S^aO|bUv5HW00+>=2aC61m^y-fls`NrT{5`ksy&X24x7IelIMB zLFhMxoG!?qzW27e+AiZ27~#OA6QwwQOnY~gm#({4&D3sBr{e1?l(Y#cPs>4&xByZ2(mEDQZorG> zffmu(u=BT-7-B~hcnS~NOmM^^LjwS(S3!+c;y8){GG&6NLrzoq*pBhtt1k1pk)!tf zq~zo($0$tdDmVLY(&%STU8=RK8b@B0A!mp-CFuZi6Xj$;l{ePNYryJ^o2D&3fTQA7 zG@N()2xb{sCanX9h=*2lm;7!Z^)5(Wv?=_+TCky#ZM*pD6~+YjC7$iawzd2S*wL@f zvuw3-mb=jq_cKi4ZebzI&EMga;@vFMSzGG1y)z7Jv{4Kl@5fwa_y^k>-&*IIH_mPR zbx?auOFQt7o&kp7?y)8lef%(Iurq(aekmxt;HS`wAa(1js3$z)WE!usI+uho_ZaY} zHB?9H@E`QBpJ?!ggDmywr*OfcVHwiD#{(1~`0WQV=sHFGD8U}PXL^s?<5qrOVZAr8 zPv$lZ1=T3~-m!G?-+og;8`u!_8h7aZn|ml1tZ(F;##iv5u#>mn86dT&mEF({m7yRI z15ANBmD{G;BmXN5q$C959fz(JXo#L0XMbpCl$#9412jcqK&r;#E(#Y$PeL%Wg-4w# zCVmr3+za~Mm<@h=eX#YTt+bE%H2${1iFwD=DL#21&aRr*h)sxsB2=iIjOB@I^z+Yb;nvOoaRFdk_38+3V^mmQve}A@2S1^t;sLC?FI#?|Qh}V!T+9e-* zo#+55o&=tIF5)?bXfx^~uWZZc6aw`g$pwu-w&OQC(Hm9g^4~I;tNM9l}3;E-xFu zT6wZ8svvCCbB2}%TCwhhftSH3m&E7R$AsWk{i+3S(t@pu*VFph6gAA-v#r+bcnIe zM~KH!lWOD#inM>V;pv*t#PqK|7oj_I9b69R^I4gyT5XK1mdXL)Dt*AVEbB|*- z%jj0;w-f=*MntLdj+y!I8^sWzKR60zSs>8Y(0IqMOmvDw)YR~$vdw4fhiq{@4W71v zzNPH6pS^h5%bZor@Lt*sGz*S>{Chmqm9x>!&zr~pmp)sDuUyLuCso%wENS&$rbD8z zZ9Pt?w;Xlp^76d@+0x4P>0D6uM-WsB3sT8_z$Q>~fTYw1i6?YfJb#p}gfCIJ^jSf) z`EQ-}ER8YpF2no^FU!oXHb@nNL;-1dvELnA7I&+;+q*}Il5iXTqy%4QxVY*xn_LAF z8v6J?dD>br!-E33RqsIhu7eeXhS)_Caj1Lgb~?|NUtz-vpc9@&VCorvkOn*dkTC)L z*Q%dib5AQ~w>dr$ELyzO7P!CA!dRj(#BFs{Ov#Rqhc_tpvzOa+uBFo1qU{Jc{r#Wq zyVZb`LZzsJ*av*PGri>nz~y^;aD~KiU^ts-UB1M$_H=okpc)Kv{A`2298mpzBeLCH zzL_|pWj{kmCZ|Ugr^LA=_k1ha#649XIoO<7^!0;ujx`})o~KyItzp>F{8whK{d*Q#qVy5BP`;6 zWssvi?=o&X;MHyPE2`sCgwT&ubf2W#B5E+U^6QW#(8|S~!2cgd>fBXVhp)>`OwW19 zSL2(6Gxt2C`=t%6=)s3@J`PhrDz%w8a zYXzuR=(!&2Vfrt3)-<1(mn2-MRk7sKx>yL5tu!@x0tf+OuJ%I#T5M@*pw7|=0eCQh z=*{I@$^?g+4Jo?guLakG0*;<>2RVDn*U!gJ5r0L^e;Pdb&xu_JSgpa!a)sPm7n$e! z2WnGsV9I4fNaBDVgSnGt)EJ6a^1JW=>$v8KlaBaowjPKN3iX_YDTT!;x6q8WU;b^H z1YVJUTf@bPL&L_|4+tU<($fA##i#d*q-DUBpxsHkEB;!CH~*e&>l(lN^fX()8kdI^ z2?d8)zWh-1RpZs;&YoleXM*D^R{=?U~$=QTB(kTR>e0#DYCRM?q91+`FLR zW#~4zYm%NJO#9asitP}kWlc?A{PfcAJ>_xKee7Jt@eGd%jiXdy_H6TvldG%i(r0(i zH*X$K9#>2j-SmW<7^a+&R+-eUv@dSg$e#b}_puj}TA&0WI%Bzy8l#m^y5X@7Ne${0 zR{FYvQeGges@aez|7p@toh5s6$lJGXjej0? zN*-2$*7Onu3yMU;?(_B*AAOLtaJ!8fKdh>~lR`-U?_3UFBzw%2<@Z%6 zqHJvOSi|2+U#D;E$;+tJH1*LaAOxqQJTGIi`t%9o(&{dPXpvqttc`?_NW#k!SozQ&#@yW8Qf-Z=p>y8A zn!eM|sxXBpuX$y)ZL@0eSd=ikZd8jw zFQ1dy-1CpMgbd1PV{GpHARYA&>0<6yy!SKMOohI*il@fGF@6n)UqbEI^w_^?5bzwN|9l}2f5@T z>Y0B36(RwthHaX4ih@vxXd$MFfW{tm|IPw6^)x1x{B!ty#2aI$j{iLK&jPQ;6Nga5 zzkqPd{*CYZ{y(p;cRLSia*Xf1FSTSU3}z7X=sL5N3qFb-r~K>{vD=bWjc$6Zq9-V2h`5rG+4Zp-EhV>0JX~F@_dt;QxBAfcxbm;ftT_1)oI<|8P%lNa$4w@*pNj9?}#DoBvQM zYOuLw8pNL|QGvS$T zCgUu4pKSE9_rs%>p)Bu_V;KUR+;@0_&si0uisN2HMjc6X8N+9{3$x{V$H)FvQ^qXV zP~AL8s;iQJYt}P1USog|Vdyy=V(dBBmf!L6*uVCZ(L6fKoXOiH$J65#dd!uYEzV~c z5@O3D2A`Ddsi;G}2p_YL6v%j7nDeqA^AHg*{9oj=j`OJ6w$M;yoGFSLL_(21dAhGZLXA8=U`*P%zvWg^NRYO79Xf1F z*Qi%o{hD&4(0`<$qxK>0fr$pXn$EvyKU6SNyVFU{#ui8SB`ZGA(n8ZMAtkl#)6u%$ z?O0)9csnerVk;CP=pAhoJNTdiED|izriG6 z;(N&FBwwc}INPbzYaV4&{^C9+ei<6;ZKk(uA}B?rl;!Rw#*jpMcGh3QtV6A+pE<~C z%>KQJ!^e%BN|jXtH3 zi~M0`j;@YiCcKlE-yCEGg;Eog{39(3=Pg0C^NTV|#>Y}HG@^g(2c31KjX}0Y4=fGf z45fpT7fI?7uStw6qVa^Nk0dT?G8$*oUsABh24pr0&9JM2SJ7Rq@jex#{3x3TsW=>2 zDkt5destQz*e8cciDFD&8>{DbYU=9b15Yb!cjg=@JXFoShiuny>*6#p7M1XOpePMY z-GW6ydFngH_Wyj3YgJ$sH)GvqDdVXp7$OKH-ig}D;B^-FIB#F?M*}*6&#$fj{ z2?}4#K@b*?ZSBmjK1C_s*R%N^HJt;8TW6k3Bmt>1wRNtk?kM6&2e9B*HfakKu>tYi zs^h1?JZs;F#Kli}qYcGurO9Ho%N_KhS&DAireM@fcsi>1kWEM%DaAd{`sI}n?BdFm zeb3Tv-HS1XDT$r2M$-v~0$Q?}Hh&BSgp0eAU(dtM4NzY<&c_P_E$4vTrLd40=yPGT zCZA9tIrQ-2n4r92#7#&NR?)4ltExZ}lnGb6n{@$T`0k)dFA+-NPgWhOpe6f%^-8Z^>2o_dc%X{SpN zp+!LmhbLDa>!aG%M0NRz9l!nk3vxfYADf0TMwXUG;3US-{{KnaKj z`lAEL9siHjspHO_wNFALnZ0B4XIc-+65yfbZ>PBAx-HiW;miyxQWD?wMg9j@IQ&IWVd z*|wO=*$MO@mspNA|BHv|1ZJ@4{@2FY0RQb@RB^({$oSN?o4k~rBbsg4eUJ9AV0}>4 z@H#1Zc52;H$e{&D-jdjte0iH=A1luy8#JHISoHb7ze_%%5Ba6O-BFKILm39s8rSKR zD)r%bVTyP(ar3;qCE=FoQA+7JT(8U#hBh??RcKH%mn+bT{DT7Cd?-v=p zPWEuZvyN3ROgKHd{?Zh))RKHA=N8m?=KQ8&g|9#nj~tid1s+=;^3Djq1p6_6GSB+y z8Cc_T+eY4bbiQ>tfbYY3@6ViMBjHF(gCF1EMx7(liS|ajv-(XRwELpUj%>S5umpHm zzEO^723F>Ms~`8${|!LA@aj}-QE?bk*?vIqEOJw0b6?K{k{KX0ypagN0hii%D|sgjG>@Ywz$4;2HS zKZO7U?SE?xt2k#M;r?$=NoX%0SeSI|X<#U;ocbxB{&y4LNTpN63#~qGbI)^M#;Ppu zH7_tDx>}a$lnEfzVKevHQM|l@cV^=!g4cNbC}K~lG@BXAPUUr61Q-Vd78^1$Y(f=a zHp+@7`kY^8WeB~C^oTU^CVna<)7kC0v2GFE`PSBVAg$@|A3q~)4a(X2a5b16uDGY6 z8I@N1G&a`P0*~dy<~fz^g%koEijmkc^|{%60k5$-SboGyZi9~0!TBn4gCM=x)N6+w zdnv&2Y2Z&{H^oA(JJY`lK0~~fGwMXO8&Ii-(qSvCcsxL%Hqwv#DnTV9FSUkVKY5ot zlyO+Sw7uMQcDgtFimB%PPaQ1>2uUi6+y_?+fV->|Mv;f4H6K+f;KuNitchLosnHQ1 z=^LMrgQ0h>Sro!)e^P^1tvu>2NfQuHo~jV2fN(#k${kLS>Z*t-#5$Pl`c%ydV?_8s zg=4CL^x{#~L7D~}Ta!&$y@Oo3=083a1lHP4k=COGg3V|ME5>|tc0zXj*IZG>hjsbd z2Y}fnWX37)M*y%y?qd1O1Y0oKwp%1L{uM=8SAp6!Q#B_i<1JRz%Hma3B9?;* zNP?kPG{5MKkq$2(&?zAj@9E5@+SbmZWBP%L;xSM8g1nZA8nWOEb-EOviCGj%wN!Ug zGgc8Rk_a0>#f#*Qt8u5Sgxs;*jfLFEUtfe=cZ6IHa=G4}x&mwLdBV|`Ci#m(Eoo3A z!7q2Sg_9E<0|RJWB{4B{oZd=FM`N6c9*B?ECf6bV{43~a)L2g{3wrNYO$#P@m{KJI zjWfMGbr^EBa&wj`sdOI}8Xn853-1zzNnmGiz`|d&ps{erM0Xpchz6blHpt*NoF2rz z`UWInR(B61^mwPwR`CQMu!>{W)pJ6=7Kq=Bi#Up`0u6WMDz-0}>d{{+QEPqp+Hmpb zyw=hzvaIXgDX%7PuTmjS`K$5i>OQe2Rsvy%lDSF6 za`TIS-_*8XWPTiarPCJrc3+wOp`xZ&5QE_obA$} zt`Ehj`d+^H|7ih^y)9{&y)IjqKc5}n{X6!VQdFCWj#{1Gj5cbv5*&3j;+#&hzH~lt^Up#>a4KhJ01S$?jWTbbGc5_8-oCwN%qCU zw5xu}sRJkJQk3J_rgR>+{jUM#$$1Bmg7Dqu%5BHyLdd=IzW3WAMRN#L7iPi2KGu66B&n{&MSt&rqaqyzlf> z)%=__(PkS0`GyLAzNSOV08-Pt)0l}=IgWBXxgWOvahXpE{6)&X(OIN$!+$5`?zi?g zI^`$2y&u0(33!9~x|zhDeo+9Gv`HvttME-st@+2MO@*Zha?l6#pL#ry^tLkE%mmOv4cjpY|e0&KO-<2L#=SS5# zN=}qsQat|MCb-Zf^><(P9qBNAUW@q(gH3XxlW1`Zu^3g=k0VI|;s>Zo6a_aMf9~5t zz6C5FMcA3RPScCKbLvRkSZ-Du43Q|V5%SRO^VwheO3rCoB9PwubFWrNLAJix6MZcc zUyvr{6SdTZM6uk$SC#A6QO)O+Xol3f>$Y>ubXT zD7;L|7*7E{57+}Xt?~?=IXE*6ifjO~I;xMGD-}4Q2EGDE{9~fjuk=|l zj+(KS>(9@aJuehWDO6{6S4K}=Jk@ZqQl$>bOU$<=c)+9?l$RHwsEmGL5ARrHOyXR* zuwUu87kwTc~MvKET%?Xw-U9i<4(WX40B+Eb2pjmEDYmK6sfNtqu-6ktvQ<{Kg$UAt;gFF77?XH3UB@!?WO(> z$W&ZKI0+OK+=k-8!>L$fRBg71ds+? z9?$f#HxCpFp7bn)Je0fEgo+M3GEWaj_piE%p*>c1P8JFU64Dh#2(U07R(e*T{<)a> zK?O_j^{>4yU!S_=&z}2_Riqx0MI2$!2FqX7Tii%@e#II2eZeo@h@&m>oS(1usutYt z&%Qq-Wk-}&x_yd9?{}V=C;n|DNp(xx?$&v*BXagOi%Y9VEw%Bxt?|F#GMsWfTy_01 zMuN)MV{1Gb5~LcRBpz@oq>DDx$JWP&#>U6O$PMgtb*U8wdm*?Ucv-PB@IAAohZPLlV+_9N3^|#IG&TN~ zJ4Ta3$FrzBN%xsv0l1*69H%N27jKqMX;XIi{Ge%4sTv41h!nf`s03>D%``gB(EB-G zgtF!kpS^j#kd5(MB5u=v{yO-DWD|x4=;4i=>X_M919{++2>v_XSCeo9<4;o_s&La$xKkzCrZT?jbEudk6W%?i* zuzuU-1UK!ddGVWd!)YTNR&waD8cf5=Pl5s139)3?rl+B}@klQsPPvd>18kr`M|G9e z#)a|&zu+6sd@4U8p6_{C|NreojsITVpyy*HZuw@R!<+ieF2jNLWN&IK8+;`s3I!$n zhIjFDifE_c4D(T~sAGV}KJV^dX-eT41{)JoiZnAq49_?k!_zp%60|Bbh8PeJ=tVGe z>rFp_opUF#D_~$&^-W>L&=|7xi=izX?lbSPsDGDF%vGws;G zC4nhbf>+heDQUX8NQH>$9@K9~be~99CH>i=>56|JO~@M+>HOQnDk5E0WIL+B6Qe^i z6%Yd=V+rPD;wIzYVg=2dk`G~T3d)A6D1P66;$bIS zblq|JI*N0+_P=JK0mD<%suzAE#`^^t>hMsb*%sg0MMfYyp|Q5sA0Q;lMM1G_81G7D z8(rwXWm=WhLdvwxk#uXr*2SAa`CIE{r;M>8nMK!@`};Qz|1sObE02*sek?!{g`OC| zWO0nP_b>t5poNBt*#9%RSqv9;0~F{oEoA2N#AMpnH69Kx9B^2W#Fe zOZU9orl735{pT4k8RDWD6fAB3{Lcs36#g;O-ZGA&SDJ3WIMji6K7AsV7?cnWQVWH! zH^zsP#ynCsrvBbK=exHw{N=L0_u0d<54V42Qi_7k$!9mR3=lf!B-CjMT2tFJ0)j^R z;S54ihiH?WD@ecdll2kfY^=&^f%1T@-4eZ3-IswCKTYRE9{VOFcY(Mq+%E4aI{4uB zN`1MMH?qF7p*SUOMmFTR5n0903Bjt^HdAdkRQjgv?H@r?^BR@L_7YT&doG=YaChy^ zMR^gnJnJHfdHu%ZCz-`*Fz@(;gbF-Tg+q}9E2{f?N(OO4xN{S{(ypn%an#gh-vtaj z$ zhKK;b5zCsTA4Y^xOMHf|KRXAj@BZCh4SRdvoYvS66UyI?rUakQg>=dOX*EiKB(N^| zkn0SL%W~L|{*86e?Z9!w2Sdp}3YppzWTu)c#S`%Zl1B`A=$|Fu9^aik+5KY(9#Nd8 zlwc6CmF#$n*6Cz&(UQd)c%2;4dvg+0y8T>fX_No(9;`zt2pRd7% z8$1>)3}y%LJS!!KB%dU+4dp9C;&^fS>F}uOIFPXT#BeD0H}9GNQ(Avt)TV3jVFF9= z<>H9 zjt;}8n7O2uJU+}EW}(oaW678i05I#$2xaRx50{%luIIJqS^-(FKcH{NoV2uvBbp$d zvqo7{;lB#*nWqj$#u8BqN@Jpy7V%{copx=_xLGz?DdO;bYt2H|F@;*Klkq_I^N7`6 z5k${~4a%xEEnUP%%7t=DjU9mq#LHAvi<|vxqFoQgQVj=eX;fhmvjT|c#W=*E-k?5+ zpqrZ}4dpo7RDWD5CAkfoDkzpcktvNji>kVWD4ZN$Q{@!=dZkZq%(~{M^8#tZV;MJ} ziTPU5-SN#lwuDjDgjAg*U1fz(im<7dD4`dj=qvuQWBv$^dp(`8eCw&4-ED7XQOOoL zHM9&t|Ncz*i8!|2w|-$}AdH9DRbThX4>9B2nxtrschl-@4hlz4_a?Mp)mM&H2i@ZS zo{!fR_&*Gx^#7lFxsDG{S9b<6CHV)}IGvjnS&0h_)wau!-TnQP;hFYiWQhXGsX$sv zj)rEZGjxcq8YqzPYL5V9o;9v6Dw{X`_pF^O=B#H+SL+M13SI8LqW3m84eDlgKXm|M z4qq&50GLmO%QoZz2J^}Hlkr-AMGA}D`FCPJjLg@G7VpWaK{_S;<%8$@5ed`o8k(Jb zgcWcPwhMcp3C2f*y%q&!SlR9dbVk5P{yr3GS*WLIz#$Tw8DOi#p4-v+UidRq+}!Uf z;=_RaWZ=&ab@Z$?Yl}I$6g}yEbc&N+*BY8`(FIx!BjtM8U{3{L6LRlo>VvKb#0!BJ z!C(fpM?|Gya9qHUQq42LaB53uYz*DQ%;62^?~Ew{w)6P(5`U$gq`!7OCa!~)fx%_b zp=wFE+?5K@P2I?y_ITmnDh;2WYXR&C;8@ z9#B5A`lkhJ{L^I!w_d6N3ZpyEzF11|$}(b8V^ykK_z22l9YCx!>a6JvNnVj|@9j7- zvpdx-YW!(F!$e(m>4uk!!q%Op-1T4M0%z5K4m79``cOr~oA)*?1=sSr)GSX?xU48E zJdy}rAw>l{8~pmjY;oO;AJzYstCR#~A7i!2im8X6^^Z2U8hND=qE8D(N!UsCb~5R4 zlAt`5=}<6em{XcuNk6iY|LumfzrDml?|C^}^+uAySlmi*-e;HZpCuYWisTds>7}4H z)4d+QZc~9qF>g$5r@CQ>w?)tKwD3`RASOi-@8!3r%taP%SlS;S1emiPbGb|*RT5Sh zxuQ+jRL$n3lwLsIkmM+cU?g|=A&+SXr=|{rx(g;Y1%dIN4B+j^H1_j8tn9ZB6ise6 zU6{hc5*y;k8k?F#f6#Ty$S`ShsV}Qf^W*v7UJq`K&YvuGU7hV=9R>K+1cW}bH^u4N zL@BU4u6>H`-+y~h*sX46*MZ{facGWBpzam zgoJz6&aniY1%`ZT>q>B7Z>Pgo0;?A_5Mv^O6k2?ha9BOoyn|^ZUs*Aev;8s2XcFss zbzocS-P58Uw8dcg_Qr5dlj23fLtgHFUgPk*h)77n4lGx)a_Fl)KAcKevxGqhP{u1{ zQK{+jK5_VpA}PV>Hb}?^Uf`yrxDd=|3O!%q*7l6C`OXRfiKK?>0`A$YES7$T(k~In z76W}{uzEh=4zqQ1wyvb72)DYXGBLOw?u%=A@*5X)uCrmx%ipxs%zs~B$M_XE*X&bp>W@cvjx0e^%A*W3@5wu|u zY^A_$nj-=Fd!kA_0$rT*Y4!Cj?((}mAI08G4Ov<%D`;z>&G+`X&`TX5A--5CLbePP zE`kRFyT4CsO7pwl&R0lN>Rn+se^ut6%?a6@iuJ7@>5d{`gZ8ob_*(akXg5sxm#U-C z(!AVQsN};W)xcJuB`;4tP-wT3 z!kl)w1uxM4c;kA+12vs8Y2EX6ep253g&X=l+02?|lC56f`ww0d_@3KOW}P&prIcP) z)N>HGLO6;-p7L3y(Q~78D@lITV%$=r&ky${mwa{_UBxfB48Y_Izu-vc5lr6bRxGrHJr+M|hAf@Nn{~ZWB#Xa1TPKMgJ&|lRFqcGgB z#QY3K;bcQbFc~Q+QnoTj19;ZitcP(y;lsNz!H^3w`HRsetoGD5%Wuc;18&z;>O^6z zplvdOchZY$Vsi4ug0yIk{?*h_^KL))gEa`~s>?jRTz%o}Z_Y+1iDw%099i&UZ0n-b zA~@)14aE1@t|?ApqrjfM zeD$k;*>a4q9+M`#ObBvQAL946_9Ss4sO+MwYCE_4B;&2U2KjW*m-$4cp>2cX2W9%w`a+H3l5vtsEqiLd+)o}GkiNM7`_W~%4(Jn)nX7? z*h2LFL*s)`Q1WSd&AN*bqrAXa@Z( zt)k+Bf^j>nt+6Jj9=^~JKh0R5;mqhoMX~JdsQm4EMM_bOg?`CyB~6(m|sRfr3Q+EqZ*lti&&Tn3JM>~ z-Av*|g=d)W+@hdyRtx1)g z8&0bom)m^rz67$|jyBrRyf`k1%}!`*5zxr+X!D8|qA|Y5P5i!=s0m0pj#rEIPL29_ zQug^VxWq55Jn_I*AXe}}iJvFa55Ars`bnnKaf~LWWV08&Z1vS(;o(1VC1G$QAi*4+ zgsTt3(W%^>B94!@`N*%K1j@4N9)Vn;6?H*|iZTh{+4~bTBe)dL2=Q>)N_oReAfeRy z<toqWzTmi#pN0Qp-g$YctJ&e=+utl9 zwU%A>IF|67GRORr%ZQZjV=glJw*&lRjY4Qr-zPJ{*cp56+sV6g!%{7)GNuOvu)TAy zqx0j^XOmjR#pA(;qZz3-+9@eC6vP%U?6LbjcXB)fv9$|XeC`_Jm&ZC``il6a>WWd@ zl{z3>a!$C8Do90q$e<`plY{ulRR+uTd<0p~(>!YRbVlo_hgbBtuqd22 zMFa^Nr_Sys{9hOvlT&qKVP6PO!oc^y5qP$$gCki}sUDgMHCc}A>?G!mogH0WjJSlG z>=P0~;a^;f-<^})TpzvJQLp^5IKZGRr_bhh-yu#Xcg!gev2$*D2f)8ghkh>w5}FRh z@ODpI?QH=H&A{}0>wi6j%$2|DDZcdI;ZQ%xRN2UuM_-o_nmjj}BD&)T|f)+g1 zfS-Qz`H|<)Q?9OG3o8}}5-RwcsT^@`xdlnIO>JzrO5_iqMQz+~buW>`Sy)y&yx`NB zV!42$-@pD;9=!(^MnYu-Q&rGij68Sz+Ta*%LL&%PhZ`ATe&%|691`$vba?XgY#7^Q z+dGO3Y7eARA@D(ArypOd0Kc2qBpQ`x(|C%9j$qI$rHL~~4yjNt)jcac* zL$(m&+97*(rF3nQy|S{dWRo4TU3>eTKHtyhcOLf-xc8p(exLX2IX~Tvw}#`hk}($w zu_@!)qbu~rso0O_$KOfYe5W3MY5ldno)kpp==_}*OhBkOBM@1Oe299IDGd2Ej&!=i zh5vCJVSDxmXP>|#&%YW2uH%YcsF`8n?emEGpnvaJ!q61_5b+}na{4{his20*i6~rw z0G~Ca4JgiVx6`75Rd|y>;t_NJ(Toj9DLLwyWX|>Qd@|UKA=MpgYboJo!L+e$43xYf zpN6XG@!(gVy}EgM)71}zHOaaBcT2yP#7$TZftz-{rMuIooPlUTH0T~)v8y-*oA0jj z-rQ$3f8W5vy?=2Er+*Kf$wLYTOPwZ8qN^JGHjj_7uDbe&b%_Y3E3^5umAKj2E)QIc z`OWzg`Rj6d0EUx)jq_+Q^c^l3N&cQ@i|}rg;x@Dgwz|j6uc+QbpQlHe|eTDWjlrBIZRGGkquLWz+xlb8&LKT`_za0n@Kl zcJrOBk;$51N3Wl5^|`o8(_|WLAzb?2DwG{*hN1jw8=I@|UJxW|kbJoAO1;}U z#%i68)Q=S!Pp^wCcI50oIXMYF5@-!P+qZ4v=I^g6Nrel^Gv@_*2l~@lyjq*BhOg7e zq{7miF&6CaNFBmUtY4C$N{UP(_eN7>&;ZQF1yins2$F<&tSo={^>V&0XWYoJ#yUdm zbfJKf^!bq-EIcBRHX5C+F{B-@O_87-AD=LU?H*aLR~-58Vode0veYuQ0t`7_Rzg{W zeVAy!<~vzY;oXs7C9c;gYdM2)!)I34{pMHw^H*2EoEZ;VoSSV_OZr{szTA9k_tOji zS1)x^$4Z-$NK|5U{fdJ<>TcKM2D4cMWrfJT>389b>mRVG_IJ6qd3jD+}IF-pZL zaG$QItYE`O8o2oBZsY!1RU4C)F!yy}#m!$Vgw5r%G+8`L_{L8=(vb0iZLVhMXGwz~ z%1S*FudBw=vu^a!RblQ|i4^f*xLwJ2F|jAkj@j1Vx@id>zfs=%j)U!3?}U38YToK| z40SEN%hVDWkf}jwJ#ZQ5|3WN#oLei?wCHU1)U_2GmCW1dy`5R3rHJ?F3ZuIDKP^Cb z#jiyptxNF^Lmmj(QyA+;Gd%^W2$JyNvH$5F5VV`iK?<0`m5Q)HCvVKzXU=3H8>ZdB zQx9293??s=%+5KCQBSx~DF1yWhu2Tm(dS$y+jGU#tCOJbjA769VdN!7q0ePJ!%wcM z)y?>R2!f5Qdl?a>p?LzU)l<&WIk~Yz6qE_T2aDx^>xLxNj8Aud%k%$tatf5OEH!-( zPl7TTXU&YvUKMm;0Gu3K4=B`h@>F9!kF39}aF>>wk(U$hUPW?}+yGtM6E_n#2RGL% z=D_EY^5*IZ%WIed(74j!v-|k;&q(CW;Ygm@OrtJM*JtyDG9a?PR}-ckSTd z?2KG-G*T-wdx!&3^a~ngLb`FCc$?e%#h$G##c=xPH>juiA()RChrfZs&7LRiku0x) zFY(^?g~s=RR9=%@?Fk+Mtvv+W@%OU5r$4F9GL$cANpWtkZ&J#lyu_Kuc!8piIJ+o= z11|lKmPhX2bez^m1BITs(Zw&0p<<6_23N)2zusodpPT;s?1eaIDrU5`&L1;I{w$`J z&Rv@oI#yTvR6_^o(L0Nw7odxID-?l(LDi^JVPnV7(v*Bs6U@?ggrNOtL$<1Z^3ad> zw>y*Wf#9T21(@DvlZk*7R))8I)w-;28Pu`(8n}&Vw3(}&YYX1e%HMN@`FgXk0b*T> z23~K-OBVxQEOw~XQ4|*UxrY{JCG-55dbieL7~NG%6|K;%Z%Yb#k?9I3egWGR-EBJ# zG;crumx=E5YFs!yE&mW$eqI_tU8eDx`WV7H0QtTI4^!2lB8nGl@T%)%N?JBc`zql6TcxO_PRGy7 zx%e!_Yl9bZB%;7fH)>bJ^1S*IH*05yJ{EkPRVm#24#fa*;(J+y*#KOAk&%&Nw03k< zPA*AMTRgSQJA)N{5|mHhT(5HW$Wz2r+*T8K1T=LhHxRy-_A2M?HK za#lQ~?j^+45bho1U2OrG1-rjQoBa+}9Ym=^(A?Ub%hkP;x9~#12mBwp zyXP);n`E|p?rzqV6xDX;l^IDS1TA?Le(`JK!Y2WJaj*a^wI{oC%}hg1!^}#s!M#bQ z4NHMmX3uQ|YSFcZ^H^zt@HF$D+>Lx8kU2<3@Wks5siKv2-e_>havq2o1`W@rHcU6D zxzCDbt)q4ksGJj+%vG6>3$F><7c**|6P|r}a%$Ga;ao84|r3usyS%pIG* z!Vmu7B~gUjo>S4LDz0Lq0}GQWgoK8`@ zKmZV?^ykk-i&o$bpE*E z(dAh|Paf{G&7ERGJJzsqZV^=?*!xe7wXQomJI-#dNBdY-%}1(5WTp5)ME+Ac#S^>q zP&~lMxZ8AbeY~@S=1St#*3f%DCl&cLEoddC`7Ulc-|`J4)S|`0VrNr$x!kXnffac* z>73F+%F3+>6^u*?WwtuWjmvpBX;Wf$^=mV*)?Krtm1!?C(faCf)964XiuyC#gm4N| z<8ecmRVnJ@N~ha}m=wAq9IUqqvJlULPY{aOzpyLi)2A9XVhY`)tc}*w!%OE|y(Iv2 zeHtf9sTgN#az)1Bt)RZ-vy)_UC3#r9XJrH`th!q$E>h0UDEgoK!r@Sb{YZ&!i|9DJK}aOLA-C-r?vA2 zE#ql+F~?Uo;!Tv>7soTrc{fIT%s|VVa{o%zzFhwSuuiP^GZ5IqbKANeJKLO^31_Pnj_tczK@!N zuO?bY5tpBa8ziYNha=j`B*@e#Rb;AK zQs>nhlcb;dx7jifGGAn-f?L$WWhU&_o^+i~^3lzDOp#g&M0O&z-j%}lqCCf^I(m^l zo+Ax^{{H>j-h7c;=ICj;iG?GM?M9rvEu4#CR>K-YQtX0|H{F;+Q1j zDJh1q*nf>k>I(-42T-+t(P}R}vc0Ml%Y&ECkEWc1fR4k#Roluy++`t`6PPN#Bq0Rs z?rHreyT6KesM@tvg83MDE)LAh_-Cw`dx`N3#_-tMPFH;kHjh|^qwSBV5$ zkHP#%FPTBovFisOU}tBY0&>jEhdXa_gj5u!Zf!b0d~Eh$IzUq-!ocM%&stf~qusLx zjlX^NzE@g=By6I?cQ((ybf+Kf>6_L}ei6114TLp@E=(-CY)(1WXvCvX?)RqxcC!Q6 z9bHzMU7ORM9#8mr zdI$XEMdORw?^elcmS)>8(q;Wl7s4o6u5C)Dig=G+32m<Q4(r}^rNYf|s(ApF^SeOGC`<4qZY?2?cP(bLVSs&LK<<@H4uxGoyG}~; z+KNYuA;l;oBGE}XC-2tB4=%d`=Y z$c1~#&s0JrUIH{yNta$We2W&q5}0w`B4JQ^InLk&7J6yH0u@9>S9Q0L)7d7r_3=cL zlap|lfIvKnOs#)c%;qZ?p3ts`V))bgyR38(DY{5)RshwMLW^a|Rp&5hM%i*V;IAx7g`?Rbb zd~|(tnMNspP0v?sTQ7^$de*un6E>ZU749{m7Yk=4j;qFRC~119tNs8QQbb0|C0N1r zsDdQ3PWr1M?=R6f8OLe~@qI;2&p09MqcNJP(nnobDTuHt5YdZ+l%kLRdt##-H$vDh z{;+#$E@cgH5w9=42@%sikPkAUfqxz$Wz+aP@-d5;7RbSobw~bUc@@ArXTZxC{-#S^ z2k{)PC+M*JXwXQQ4ljIVX$v1#<6nO+l9A&Uq1oqA^u$<$`91Qa+H5)q=7p_PKn*(?)-vFWq&Uetm1jGVqnv4o~<3|7kbC> zE#{uP^(xoLW?_ofJ}YY+qtj>WL}8P;X`XK^<&#ZbHR-7Tc!%M-Fs-|flmg4gBa+Jm z1D{m={^9H{Q|jrL3plF(e$i>>LcG9@E5oc#3oyCa*|Ndcft7}T{P+VCOO)v84QP~p zlvIB4%<$~M3Jk@6NjGh6_5m0~ahdXc(hDJoALX?y536?6y-B8INtUnsbGBc+zI3{A z{Ty2?@rtY_UdtA;lgpD(M{EXo@qvt;N@>R;?l#8ci$g|5HFY;lXDygt>cDiI{|_Pv zG**PAoRlz5oLaqkM)INL5{uP34}$_31qpe;zz{dZaEH50ClO8p%`JAe(iif|@5AS! z))&fk*J0y*{i-wxFS=7rHzgI0=RkwkUIZ5;#3$~&faFH=b5_BD_|H)n-aFko|F&b= z!n^@&`E1kCbtKClzXwVRRSqaHC?q3sw1n`-(dXu*58by!k$2-Xcp*Z`zOw=sL~~K| zM%+QO-po>!>b!3-9wc)YNm8H?A^p_K=Bda9Ws-q6Q`HryBH}M2sKuks`N?T2FKdN* zSkJ_if(b8i2$~C+4@lTFpMm0DjK|?MSW<6N2OPAbz8gd7hH=>|SHlj#`-e&>lBf4o zOf4<8zKZuEEcfKPH<|O+ty?(mW}L8?+8?n<3ft5=Sv6+~ZPR14(Sz$%`rY4kVrQ}^ zmWG7EM*LOzwtLNv(YaH{cQUzsUx|~5EacA+C>PTu{QXS@V$;DV#UN9|!LjWaZWJUf z?qf!jpqlfa&Ta+;Wsa!M2}WnhN;U;60%C=zchAEa6lSpT|3T!wMT>&KoZb3(tU<%- z7P@i2tO4m0urr?L?AYhM7QdH(Hws~6Ttl_PGB~;4&jlFP2WMBm!6Fo5_;-Pec8g5F}9jRL!YN?X6BjeX5nwzsG%6I*UgvHCS z#TY_5DnjFO?NdZ+-JSX6=2=@LZ8+ZTvay5M>_faID>9~IW7J}R}Q~M3w;a} zQleiu{^W6-q(AUIzbRMQ9mj3p;%Jgf{BGjrk)2)X-K9Fq@p_fl<`O2|v};GTD`NvP z&U3wHQmLP~n0 z$)iI@rarD}eC$SQ#MY$7(n5*wS&1H6z^OpGrD0DI)-?ib@L6g8QZpUVW>!P@Zfrog z&F=4dpvPEqnfcZ?@fJcxC?pQ6Z(^OXx3SGJX?b<|1V$}+9x)Nveb^OyTzq#)!1pqx zohC6x;!r}4qXk~B?^SZ8S~vH@YcZL)x$gp(>28&?imw1@#Mai}x}7JS;R^b0)Ftna zc>6PbqwTiJEstspA~R62m1;>q`N-_7DV1WPI;2u4g8l2Qb>mnJrV7ZO>Y-$j%huq) zZTPrUAj}^_pla;`*hjMp$#tdIH8gW$9^T*Nr|LN|C%syT1(d5-d>)oeQA74XQ7MvLp~#nEq2Vc zy}IN#VEJ=k{tjOvtiX>U9tM4XN(N%+a;rlVvS&WBeiPA2@%y|qE}^tw3W9vp?@?*! zyDMUk_v1n@JH|LBA{%&NocK5M_G@WrF^&h}Zj@llhGO9h%(loRuZCI0R*B!~8XR0` z9->xKrPX7u*Tt3DL*Hs^^KyXH@ym>=KggwiZcjDQv!+!Yy)e5L-X_cB2CZDTayDzPacYY3Fmo7_Gc?lx`H$!gtrsKCM~K! z*rt#v4N{}teEotiiVzkT!wIwCvyCEx=yzrQ#fLCJg+sVfK_F=)F&FNK60C$$Sun~) z3MUck#(fKyweS3TX2~OHVrFDj=h||cGWc)a#IFCv-Q^I3;{B<*>>`j2A2)CFEl`CD zC~!{=$PioTVDfPVaM(-0>gKQz{=WNAgEA*ZUg$?m2{nGQ=DQGm zHC-4@qN1wrJ7}t*Qtv{ETC6*S+yRdkj0h}AdONzgX(G z5|TM-@9BEu5UA4mdzF7MzGqFQapGZ3F0C>s{a4l{bu|c}(a)bPg3wXw&O7)50j3gJDLqey0LVrC??J5I6TpX%Tpy=s z00#+qO?lL7fJ=l*|iqgy^MVFvTb-VL?8 zv-7{_q~zq}eCvZfJoExw4Q>ncBV z+Ls+VklhHhMaGNQrr9D9h}!v9&)vCkY`i?_;izO1rxTgfXmo1Kak&FfB>In7Y@i4a1KzL)#+5Ax|agY`RAE5ArF z?4;S}|56ve>hJ#CtF9dPZU9{1vw+M3nDo}CP7nWdf*>En;!(U~e%U5`REhbyzsowJ zNZ=d$BzihUSx|DF%uiQA@`O@Z*#;(tSq!&x_yS}T1@q?*{y zk`!l-FQRTis;gM0=;kfn8YGV|DXgfpkl%-E2Kdkn?IGnNeL_VA9mRKTjMlLaoh%V0 z3(W~p&#}^W@sCmN-p@!Cg@l)R`+*t#W~Xr%NaJ1gnF-tEQ{lCVqGfQmVmp7OOfr=F zSVmUXnRz2(!_~&2>ALtK#4Mu+@qo&5h>LJs%D&9S&F^ibz_I-GTHgG{UgJ&A&2{VJ z%geKb;7iKc((SbtUJ8mxrnA3P(aun~zQuSOgTf%!%%Jm0 zk?iA1d97rv)>`*hFJ-sfRDWtsult;5^e>$lTIDEusKtJ=1hW&MfVK@Fypu2Fp-21= zECv+IBtE8iToK4Rr{@4y$YEMsH94xTk*yq3HU#Ig6G(+BOws)|A>!I?k! zghMPySOw99B`*Z=$ykL1$%HD%sPvL1WrzBzl63rz$CIk#;YvkI?=JI1MsT=ws-3uvOA9Rinyeajx@)c8Gu#i!A*25E9Nwx zqy|h9&Q<(Dffj-<3T!d*%yX^5H&-X~^OKXPyfn|UFZ@op=S#Hl#Tbkb{p#LXKkziJ zcuZ}3KLm&=0DbV({VH`14hsXP9Hn<>W5{W|p|T$FuWu4gC05 zb1F-Eq`*-E$a)@SKY~39sbol}q9Tn2!nuL!JsVP$0xBv=>(T;*qY&FhlhL>T-j@ej z&UdrCJZv-Q)h*UvH5Lpz0LgJ4{>MvQF&$xHy*AW+m_u4(uXwQaU2} z0e!=uNjuqlp!K-`17Xvj;~Yn_5)#3oa0HkRj~Ge|5#7o0VR3fZ;az>(ua{gW*^3n# zxV_}&=-d%)`qH547e{dI14{GR`dqwPIir(7tDN+u;_$i;R5hH6cyJvWI9!0x(l*L8 zBqW+ynVnz!s#v{?O+VjC;SLp>peI)hhL2U2P7$wA(&U3J zRO2Q|ED3`!G&Vm5ltFWiyDc(|ahXYL&!It^RMm{jp$eBjqf|v@{SO`F@_LF}z)G^9 z{;IF4nj%YGU3>~)6=>Lzs6*^q-4sBLM}g%S3v8KU8GgCP# zUII(#!E5n=OD=QluFDoL4)wT#<^i|BfR?k>$j3CB`(*%v>ML#>v=){?x3*H+Y`g?F zJP=hk4F!#Nj&Tw>!D;!V*Q%fZct}l6Rpfkl3$2KR;is9ncP)iIr3(D7gsl`D05VNt zeL?duPUtBiS;`4A*Ja0ft$AlKO9CL;dV70^hlkHznVdak7ZvkJjb+qfM~Fo$Ifl^C zhUlk&fEU1ic*ck*Acq&w)hEpv)Q9W7uXF{`(fk_T83(XI=^QMOyltO_IOWOOcz&j3 zFj`+)oJ)U?!tJGIU>I|m&{H$J?iz+n9>Cc8-`QRL+7-Thd2!y_ z9I)oU@qNpA^`))`M^_z2(pMqNJ0Qo>O@vVDac*{w*7?=7g`lj|KXv56nH0VaGF39N zC`0{W6z3DQ^00`KnkcVvj-%sSa*xf)JWceH+t7*xw`i-7|Gh(eZ-nfSDNA8B;zOPg zOkb4|9bA`v+$$h#aB$mcKxP^DcfrELUsy`Ygx~JqOqL9;DU!Vwf=aw4rq&c9Mz5ha zv*`mR#zlOW?5C#xD}=#XSbb6PznLRg*87UJ^+UX6VC@@F6@nX%pYIK@M>oYEX)M+B zHN=otu3EO<`XV{U8ZAT)kkJ?ng-O_tw*tRAnDNV}r9K2!U~0H-86IJz%ySyE8s_lodAI-R*GO0L>cc ziF?A=vf^-@;o$N#=^tR7tSy%@XxD8eJHEthwxXN_Wop$SDuQ4#UIcNS+-p6$7Y{2Pj-EfLQ zZtFQ#h2#45{x`2(*l3i2+Doqn&*d}}1ou{-8E$2Vyp3#Z=sg>Z&DIa$`cyf-9X8jK zvU5%fPYkiL{f5p*v!$Gpqewz&?lS|~sX17nDiY}VEH`Zw{|!uMD%}V+)QP6w6Ps?F zcfiZ$*@<5uR$g7&_;!lC;A_9%<>+YUfZSrt#*zPr5`NS2@zQ(U{<{R#4uY!PtZ%sg zTKUI!L)9Dud%43W*?)W3F+?XHj64|eDVx8n24XC?u}xD{-d27NY8?RWjWoc*Z(m!wS2AYDuL zP~VxAlzI3RI-9=_O@07Jq^>yEbM@;57DZZRC`}zt)|@W4u^7AJBvS0BmMCvy*;yCZ z`9qAXK{S|O6ZUdxFuzoTUt2pzP6dOD!0+!_#sOR3`ue(!@M2+SSI^Pws0_qtfB=NJ zo!a|A)aw&(KdTiUQGN-TwTR%Vv+zBao$D-?%SThtTK(t1X(V+GW%xWrJt;-pWcO3? zWw7pB74rB+9bAv7rsWE%w7(RsOrYs0-?S=y8hUlvC*3e{|8~ukwM&wKwrcVqmFN(|)0EhS5p-ay{!-eQMu;($po6ChFW6>2i!FUUJR zS`+9mWM#0AgK!slm^4<5gF?>xZn?QwWe;jpy_lWVi6cp}dND+S5!Jmtxk*Uy?vwbS zNs8-X1XG7oE91?+LF@UHRnT<-%T3YD?jiAPg8bEKd)TcknXDI?xjD?Q0R>*gc!*HE zbaK~zpg6D}*#4_uk5mf9C$Xz^( z7A~(Xvc~)dCF!IF!*Z+YMZ`hSu1u%&XHUVyNy-1bG@jk2!k;kH#OgF2e?Quk;Bk|p+Wkfkn7 z|H?0^TcEj%szZLYf5~!enOtiZX#A%NvOr5I;9{?7-UK$Nx!+S}ymY|NMn=Hq0&L^w zC|Mm73Tht|Z}$49#nb!3byXMAg*<@E+nY|Qt=PMtClb%Bb%F4GOy?dVl7cOikc2G1 zY=H?I3y$%Sl9Rl|ak2zA2u(No1o*nxSNIH0mdtP7?zpxek`MlR6O(tfx^ghY^Gw6u z{zayo@1BKcz$gnvwx@%GtT7pv2t6E-Z*?!@Y=n{gY1(;m8GO-a-vxLKeNEo$R8VO| zgZO)^c8Y3;g}N(FU+9KgvDpIK?mzU`Hz34Zg`Vjy4_m&_(@rvCuFY3I+4o(YBXvw? z9?QxDYV7Q|p3nWZU*7N;ISKkwMR0L^DO})L1Tz5D1yCOEZzZyuH96Z%wL3O`L$^U6 z@Iln$4HYKn?=;26w4k>?+A}A-XO)|+x0mh-YLIXU9le`pnuE1Q9h?%H<_{H};3&l0u3zC&+LmE5e&Uo2h^Ydt;x3kv(HEAX(N{+f4N8sZ;JzdEb3IEIN=att;SNK7)g4y}%iB;$H2o z+iZ~mfi3ZEX+M*_xodBldE#a^Gd(4lu0_$aT#zP^%fjL%7jXIVAh{#$N$^$P^)CHT z-sgAZ4Po{2%&x2RXUV%)XRS9e@@G4gbhchErDY_g<+C*6wK#@yTV-Ws0XbVgcV}2- zvRg=D=cm8^p&2^4-jRN8uVl?M)@XT<5DGT^{?VT=f8Lm1H?sV1j%6f8p`R@Rw?tC; z>B>DS(lIHi-zAk>SQR?M^JQ4Zg`wj-J;`Q4u)QAv{i<5 zyRU2MHa>`vRH*!tII*XPMe!csS_9F&AFGZMFL?l0gSUR)Yzb-=D&vZ7%k*x*G;nd7 z@g|n2R{l|K51prsKC|>kLn7dw=gD?y~@(IOW_*`%;bZm6Wd!a=FOy*}0r* zJv#wBNERA^9#!u3<$iUKw*1xB`eC5EcrITwNR^+dPF5_Oqc((CGx|N5Oedk{{3N!w zm-Nw5vVI{KRy!xfXLs&w?#XW8ZpX}j-Ep-m*(V!uN3G=$6GEFdRxTJ3eeT7lDMkFLA{IZT$VkEzr{|mGn4K|bp&W|UA@Y~3A^Yg3)YiQpzf6Ek%Sq7W|9C!FrpmONTb5kF!#Z#XyKs`8qj zHyF6)Vi@iFGZGfru!S#xK&KACG$&KLYnRhBv1#ik;eFsgwBk&RN!1`+}QlJp(R1hn|-6>_k@ni7_<6er?Dv94EsViIFUTepL^pQ{US_A8Y_p0QlwGG?Ih6nwQ=}eOk5S+o%e6rB4S>Qrv{7+xfq`B5K@mEvdE%RXVtx?!Q(m+hPYz!en zlw_Pk9M36fp&z}kM~J_iy-xWgRa`ns*E~1p0l(c{Di96W5@hY1%DyDF>FT;|Ry)qG zo@YOMTJ;n|FXi;t93CnK*NN zHsVUZRZzKCOumEXn~EU3y)nKnPELFD^d{xS)%7u;`naes>^|nD;otTLP#Oyu@;2-#-*M+gFEG||ly+=X~q^hZhuns)I8^I@3 z3$_AXu_>Mth>WDa36JC=dIRz|1(Dkww{2IGng6Y9SHOgHbXrQwuQf(zx2wi3?J z5ctOe4-a%QJfnRpw1ZIpS(8m+f@}vX=&Szy_3W+UheW1~;-dy(F2SV|d}Zi()Z5H- z(7UcwHrx8v=H#i8q&?TyHwVcDv&m}*XzAcf=F!LJTT_4zb8X~oaq+CT>nq0VtKW<+ zvG~JeZYkY|WF`2-p%q-Aj8W@r7H`*27m!aa?SEe_G#ksG0gR1LZ2+k%7jehn{}isb zqC@<*H=V#r3T?C(v6_OpAIj(wIgwdiEN{WG69A&uwY9&$ZvsaBkX9x{aXElX83r12 z%*qXj_=^P@Pc{H|pfWe&rPSk%8Z8-9t(5#YO_OJwEtbkS&Fsf3g~T!*R!W3~4IW%E zI1{14+p$WZxG66(G(Ln{=N=TLq7}Guw|1-YVaO@}Q|?d&GV-TnmmZl~AjX)Dj$wyg z>^5MYV~kUob(K&X!CC-TO8$I! zb`~cCbfBx0rCCj=S-lm#Gq=1rd{#_{w{3Br$qk-=d*YJt`F`#E+t&WH$5^-Sp(A3> zpg5VCxMLarZ6`?4dBeQgkX8Z(h1`=eg{GG&J~9v;qJah`rbf4VXUXFCZ0p_uUNs7% zVnY0#YPc0-J6CtQVVy7l7gFgm{2`mbF2;Oo+2nBDQGv`(KY~_pM!viIdSiA2H6A)w!z3krq5rS^8#ZMo~8005EJ~fW=5lI zk>?HZXNln|iG3LS5UpIy#`X2}{MBqZkP8vZnpgouSc*8j|1QGAC!vn|!7HKhzH6ET z^LQsoq57zOGblkIekiMDfia6zA(bG71`PFyib@q3XIT5CC9&=GOLTBV3xR;^A_~i! z1h~!Le<(X$@-Xw4&oUVC)1^tFWF8wdb6n=qOp+bCXkP4IbqKKb{JBYSZmOQisLEVO zmkoyqhQNpYD{KBE0(WK)lW1)rJ1jJNM%7D9lm$i3mD0WG3ad0TB-1KCF2zut3D7!PuM5SuN`}w7b9K16oY&$WG zk7RBk%6WeuPCnw{y)kv`HkZeRhBIeM*NgH!#oZg&%D$Vw5LV-DZ@*SryK|?933Pfc z|96*()DyHL@IeOwLh~8Dk`57mRDk5@ zpKzYiSvChvZ`7uxFi5F>s71-B~9ftPC3B=ODP3N2XF2T{$DPGOO*9DaR7siU18Eh*x^ zgNFl7MZw8&D60Sb$`UzX*d}cp!1l3ZMDu{3>n*FoJ;m>MRIwq{_weAtWcaEfkO@>y ziI6nl-g$noqrSeIb$2Q4xU%^W$3g6xF{1$!s&%t%@lILfRSZWqaYeGS5t6>KPCxkN zqcnclS?)jYG+%zCG|rp^CH3O!_mF%r+u-Ho<~CILW$pRy%+j5*XD~$J=7q?3=4i%9 z@^TMg_3+*6U0k%(9|qm#moYDR&KdE3v!;l#33pyWE^{gExKZ4>k7_6biny@UMrj-| za6do47b64j9tvyzu#L5hMe{?HDOBN)slZbVk^EZ-1irDg2JbzRfZbvY&@%31K2hT$ zM*WX~9A2tbq5@TtwPa1Zy1n%GX8@6E+?RA$OY%HM!!ote; zHCw2^m1W45xc51EUOMqcn?v&lCCYsR&k$w8*->C2?4Wx>di^k>EfcvPeJw1~V<-c* zyDkl{^DA)Tj$akQSIGP{%=%qQ;z5FhghVy(!N4}FGmc|#&K_xp>Z>AWGjtk(Dt2~s zthHXQ49TB2CLlX}o7S^4hSrjMKhE?Q#2g>-gf7r}l+zz@v>FZH^zE-0sXOg8@3aL3 z2L)jVo^q%qnfbi4t%tCp6-TwRb{9?-@az}UPD_1cxv~#=vNuN&F3gLFL>7I}{*DVj- zTzcgjhAey4>n3^8qWk5vk6vqn6i4d<4-3Jd`-)56{qRp4Td26~(JY?znyE9OKIG|N zDmGm=RNS?jvJuAnp3@B2jdp;Vj&J^BOM~qL?&JZxQCvU^#TXy~02&Oh=Ygu=Q_SCl z^A>)};{>3YiOQ|S7eR|BARyq9B)x_zVGRd! zjKrJ;mXTBvyaBYbjMhtWN}(jh<;APCABR<0AushWFA%yVUZlBf){*h!xmmicB z@E)P0mm8Wb0WTba!D%GW!nw=>%=;l`xQm2C8p%ri7f~UC_NzA)#xJwQbS*i(^7ln# zY-p~QJ82w_;bA4XJ1Ys9)h_#7To6#RD>w3DM-L<8*e*Fz)+xT1o7L)vLeLErSN#Q4=$IX*0?ZQ_2qK<^@hq0~ur9;W;rWk;90o zK-rpz@cQ-37%%&Ucc1)9z#=02IV^EPp+En3>zTBk+uWs3k85`gmd(M&R6X72-6kiz zfBTUkr1&YB0wEcp4Navxo2%XE<_k!1ByC9zad~v-KuM@Xm2AtX%61xpwp_@=*3O#R zZoJKj?Y<&{U_$eq=^mty8HVnuE(tE8KkJOiyyH?tQsPvy7W3B2)!yD7==8LGvHhAP z8>%J)GHxQx_N?sTkA6u(NhuGMSq;fu3?Qq%++mC#iXXyi#kMcLoCK=gyC4)dMRU3- zbwN!#^~XsuPAkfnV@q%%5h}Lfot-kuxG%TS4A$tF^nI{``Sy$!+UCTD+ zr88&V0stRdq+KkI*=+3O3{yDUkSlr4z&}P|K8SmQ>)5c!9DHcaZSLtXH!N8#s!a|9 zaa9aVMD?hWF*{Pd2$jN9$XYqXM7kl^zS)EnjciU$>>b|Z)qbFBrF6K7=eq{?46*dp zT~%=p$scZF0Zp(MqQ1<@dVkSDJ>5BJ)J%Vjqiw*;5Q-c!OdqmGrb2eCF2!CTwgF1y>IAAq%tQT>GBu3F_elesSIUS#Pz+K=?QsUQDx?}QoFbW&Nq z1JHc{M4FbCh8$On@md%;==amjG1rpGz187vN~FY8Ud1pBoIq7oC*+S1kxnKM6>f5M z0y66Xbte0p2W#8#G#qUjLKwt_VZ?_>e}@jHKNh7o7&Q{=RJMeH!Xn72xJZgn7-?%b zjH=AW2!(~7%(cw_ZxyAbm+2!wQL&y;n$)z=CvzeqoKbf}(b-ltI%8+fx}T#IH(rSl zw$w>Vs4^LMOugbq4U%``hZFa*x^GW7byOM#uyX~nl`a=sg%^WDX~%SEL2=Yew2h`u zv(uhh-BI7^hp;tJ5d=k@lx|9oZzz#eiqma#?EJ1DVFEx%+>1(8V%?!xbXPxruU9Iw z(vO4R44%Her(09i3@fJRnQaKfYmXp5Dbs<~uI^QF!_TnF_hb|40xgcg%O@XZMOGUm zq9h;!NbVog+%&Kh8g}nJaeL>fRQmEAXzzJg`|-Hz|IuyeE~YoA_tqPXj~J_>$g}_o z^pz3fLFu~p`M9(~vMsVzf`pAElsF+IO4E_j#Grbe2L2`_geIg7lmvH*+K{&EE%P)7 zC#Gako9yD9KXnj-7&#Se?q$~Mi$b3-e)!348=St<#SOA5avLJemcB-`sTyzyc2Fo)hwP15^eIWY*Th92JL&gw+P5* zfrR`_=m?r5wi@m4{mLkHr3-zE^SzsMm&y|F?O#3Sjy#w5N3Eg3t)fELJfm7oct94R z6Qgn*7YiPO_Wko3Pl7sON3$<^fUq;p-G(>D;Ahjw%=E0fjNkwMkSvcS1P1;w{NU_z zs@i_|LJiRikWeUxSalhx(Dg%qA@hd$ZFVGC-%9A+O>(G3)-2MNbOTOK-BrKE-6w@T z6xc#vH>-C^+z+L~Ycpc14KpCU5BbhJfT?V4UhM4ew2L$K$(@o&vZ6vLzMo(oi|dGY zvx$ug7$@uw*md^b94`eLszf#YGDMs8VnH?W&U`_)&10qhz;(BRab3V+N`RkVIw#&! zYqcx1V+Adj!>gdwB{(^$@)YB*7@Z%Y`tg@xIS7I->GBRKGZhOd|3&m#ghh~_5+UZ8 z#Vh5Inxhm_90t{K;xigCjFm9JfT#X;^WsAkus};s&aCkp|c#MLd%8{ighRKyWmD)OuWxfg7Rb6sgx#PW2^K`BWubd+A5S(a}_Z z#N0FoKS=;ZgJ|l;om&7V)eKdGP{voi047&mA&Y6n$)!RK_t%AK&|YA6DR`0q0BY8h zNRki7Ef$_g{S?TDLeZgyE0Der^kaCOq9lYtAzDS~d>^kV2vIgb*ovq5mX+1aR;$}0 zan(hv>~mK7-%qO93~3FbFN{bxfr9ybkm_@)Q2Yu|hO3((gWKVgW$x4eo7&+q0*YKw z8Z?xhy}r5ws|QnEUF+4KwFUUG-OHAo+HoJ^;s&AH(de39fKog@*4i>)qUZre=zeK0 zvrjLyY?xL*0|OoVyy@T}k2ix$$b|Zj;MNzXDkLPJ68w#P(l>DpmT*xC!c64`i zov4(h&1`1M{Wixe?+#;3NvVKLb5Us7rnH>pSjhaj=2u@@CXNQZRTMW!A5jC83%0hh zDE+7+2YiRzj`Ea&Lghbfi?Y4>9{SPg>agl4=)i<3Xdo~uey-Ac)~$8$>Ib&B%6~Qn zBVN_N@JewYY!RlBK&hm#`LpxjlR)rLHRDogpB^#dCn%;H;^~v#N#w3l{X8-?J$)}; z9DNJ^|5r<;8XZW1hXfzwmrMBssP=FJ+aIWL`XC!JpgSYla{hY@%Ox`p0p;oyi<{f7 zoZltaPy-NKJ|v@-6c@pS9A7^=&uL0qn+5DxCChs1?D>jLro680RfUf|tW4;hwN9Jm z6}85ei0<#QpAdmedB`HYj4tt|z;#;j<{e!IUnPU2om^=0em8h+Vsm5$cs28Hu|Z(n z1wU1$YJAuKb`=)AsIdy%TWAL!UtoLd%Vlp!;NuP!;^FF5HvJTpLt6vLy%G2b!UZl4 z*YgRmRj$8hsVU2Wxl8&%8uF)bNVJEEnhNAL8HyN;u!>Jj%$9lh%{Dq3d=Q zug094?cf{pgoK38G4=juoHvK^H@F13%e0$w^Q)DcBZFC2AD=b4#Hrcll)@Y{x1YO| zfU+WAo{=IF$vJdhujZWVwJ$2x4V#Zj39V;)`^%;h0$RX?7CM<5K)ufHD{YbK1*);% zrYfK})(AKKwX?GJmTU89KrU0O$irF)w^4m~?pbG5J8X@WqHmp=oSvSXl$4j(uG05C zqRO0b0!$`pka2e*mFEuskEgSaiYngT{?G#w0}MEX2qQ59(hX7q5>m<#1JWr-cS}f1 zcS?&O4blx#gMf4iNP~3Od%XAl-m_T#rwiwt`JTP^^X$)~77GM(3JHs!v?`7_H<%MK zaXeV-G1gZvk~mhxNADPSSv-wJz;oUR6u%;%?^b@41hrI_`#`|j7Cbluz@aUbBI;4C8F zm``5sUgDQP+a0b{-Fo>1kG~Q{`$^pE?=7u;&GO+^<~9GeGk~Jmo~1f&aa-b*pPaov zQoWA=q^y#XyWNpHi+~%0yB)vNk^5_jYdc^bAO)HO;( z=qS*UJFw7bIMgUymW5Bw8DOR|LmxAHG?;_ByAc>ivO%9>NOlL&6OqP zpa53GV6c25Yp6*o%gDo>GRRvk8y>v)LxyzJ%iy0RK5h1xW(FD>ETuESR&A*U&dFVo zmHsXAOCKpEloV@nHRagc@8V!#@_SZ$TFRSI?$Rj9HRaM#WZ$)E|Nh{msHm5$I)e_j z3E{S5#giC%1jt90I((`A`u_2N%hk2(qFVd)EMr)SrVIC`3jjQ5yW434?54~ywu0wb z@q8BRtMPBR8aPU%+;)zss}`P8ZN~qO?VM+ziN~vw#^-OMYOGmg z#^yonCO>hyWo$mWX|_y0V=nT1YYas~#6!Ukcrjr-laLRJ2ZOLG{*dX=12{xx_F7t+-0X@{zrJ`+NUE;;U)~<29V#|_Om`!rwvK%exB#FDbrj$; zX_4~#W33#20^GR!@%!zznVF{3rP~<^)i*3405WuUe;{!i?e@3j^dVrmyaWou%Vr^A z;k%pTm*|GFs4~E*s#|YMBv>zCx3KMe-334lX^9(w*cYzN(=k3}8v>;l1h`-ZdN_hA zSvKke=w%0YU^oyr9-d!?0EHSu;h2(8^Lg+@(`c6)f2xu;^|#82G13O#6$~$+y zPs7K6A;VgTmW=d)sSb11nQ4LR?^^eX)9Eee?J6iyi;5d}`g8At{>v?Va3B}>i(?)x zGgKXO)%uI_%b#nv98~<&^jw9K1h|-zYL1cZ^2|K1M+*f?uZH*E=r!n<3Ve}CZt>U3 zS{r2H0)e>bS-JcXlDqm*oaXfJUbHiZCB(68+5ZBb1oqC|4tmM2nZRfa=x*)A@U9zi z{n-bl!5hGo%EF@c+mg@u0>J10%;o;LT?gC!{(8ypI@7C5%0P0kgfaKL?Y?DUVGp<@ z?vEwzFIMpk!GJDR1pL*98zX0Juup=bd839xfCKd3H9rj_4q5H^KE4$h(#5DS#;BSR zq2Gg@1jgY@Re#J6nyJ*jgw?v>Vbw2gW;n_p6wU6#$8o{xl0(uzU1piSU_z z*#49ke%jXyGdlah4ZZqRHIOtG^PO#y+3MjsQ0dmsz11)SGxYO9xb9aBZaDYa-~H!f zY%_CwO&^rP}X1y$B#{WzCbfdhx?DV#u54_98wS*d`&94!srzJZYIKBPcK7R3L(p)7?)q_^>d@nD+rzai0#0 zYDO*tI7v~~9FA@B0UU!ZW#$vprr&Z#QP(0@Dq@fRdh!jeS*4 zGkZ>kvp(8;fo}1do15!JJ;nr0GvbW?U#TRRQVi1Q_DAJ5vXhVy10Tm#%U@BuCBWq& zLysxjxz)4gEz;t2O-aRvX63<@B@fGGjpJ)_x}H4uJGf<6Wr?3Lu2fU2>J_mb>#iOO zzwGImIRu=Uhodu>Gv49`&=8Btk2CR#jdt1;8n&8ZY|6EQnunTec@tWg@E4OZ zFYgOMgxmtDh^plamomR>q|kPlEDf9SGJPlgD3!EE0e(*ajN0Dp<*9MzMX#papYEYZ znXcuErG4IN5}UFXkyStrJw*N0Mj}~8kZXc|=WYNwow_;tBsP^o4SB3GBH|{T3Z>&9 zc+M^jvvX*HbuvCHvNG<=tK^BR`b?(aPsmEe1>5slX6m}wS?{jU#Q$WOuRLfzjy$B% zN062O;3H)UW8w>iCRc(aO=IM-|F*j9mwBDX@jbI9kw-I0PXE_Z@~;lpmJN_1V8{TX z<{m%BY6rlx`wLAQ8CcSMn}b)E#~VOFweQkgURIzzLqv;-2b^o_3$UogMmIY*H#X^1nT2`4p;Zi;xYq>ttUJNAxYdtv2cUs-uIv>?xTbQe8Q{)l)YF z>|F>#<+z|9Fq0(AAHc)l{wR|B^BHS9Fe;EU;7q#QlZe5Cc4ls4i*$Dk##*tkR4U`G!q47^x6W zviQ4u=i$^9d1S$avZU;XpD>GzJrZ2E{iV6t#j{Q`q^`-^l>n}H|Nq474*Q@%YATRP z`{MNfg?N12@F!NC+7VLu?BagEA{!0*BcbM1fs4i2=Bfk*~}B!dG2w8Y(JMA1kJd>YTTd1V4N9MY7d!{o6Nh50pnd@>bfc; z{Wj#%yRpe@km>B?!rjSj(5cv4N=7H`^E;j7pt`xOZ$DNSn%vG^?e2FiB(A^SZ`|Ld zw_T=(0Fr@(7!WeUI>=+*P+$d&OKk*>7dh9DS65e6ikvEZ?47;8H#9WVS3ifH)CtzT z%u@$U89?GE&jy*2oEk(O2T3uS1OBpXmi~#m7xlGd@ftSmFl=i~wO^{0>N;hw%yGj* zZT~{5SnX+Dv2CbE=O ziIp_!7u?W;sNvSHR?hy;3rr@p;(|74L41iW-Q_JRkp^UbnjpavXp_1t=7R3`XLQQty&n*)6mjk7wUvQT}xmnN(vL!M)Xw6Egbp zmB)RgBLeJ{GF;f#_wst=Jo_;%`+D_Y|79*Byb2NSfz+gJuF$ql!Qy%XDlP_>V3vfk z1adgY!ve~;2k^>Ao27%9K2G2~ZZ0l%e49+>&6giavC@kUDEI;id|lHD`B=R8{S(bZ zEfQDXTMuKf%2{D0gKdyUA#T+DiOSB`hPNiO`~lqNGl-M-G$Bj;SqElDkzaN^DfY=8 zeV5Ij+sdGQbbs}*&HZfmX)&hd0Y3xEL_43j1C}QVEWfbyu`u^5rDs5WJ-K&?y_)a0 za!d*}zs$|eHxHLANL8i0s)&)Y5Mon=Vk67c2&wP;7B%48qV}i zy<=%@aaH^b5PMRl~fd+;ar;tbn={UyT z*YT#@*9qxYTn{qC*}PfG@x`FN(8{eeM92}gu6DW<43AdEmhJN_;~6|_*wdAW6unOR3;f(Iqn_ThT2@rx`}dR|SL zZ+@!rl;CiCYW37OvL9fg9K(|Ikw~2+kYOo~wA8M1(?3gSlhd4b{n;1$Q=FU$@_HwG zK-ZbwITT3|R(=CNTI}nehULLW+T1-IJmZ-Ab=~%D0cN1JiTXCMv<5M=+AfVcrYOcG zE~aOt$IQ(M7=>#mf-$f$pb0UMc1QtQ*ut&8zV*K4-1p*+WXWeEGjs2~5>)8qx%i`no#l-{z#B9Txn z8YGydF@gyUSXf#QFB+$0o`CgH-QBtnDjGk6DW~;3Dbpmgf3qqc8DIppUglu`pw)1$smIKSIGKrns1_{s71#0+-Z#Ez{|ieSh9- z=kH<}iQmm?_U%bgwz&5NpqL$9?4De9jGFQsE^4)MgaffZRVg8m!tt#?M@Kh*PJrw3 zZrPIW>aJ=3A0;lbPbZ1U^R}$4OsYP_@+UPT4T)FnSDI>GeJBwxZw2^=VjLoN-auVf zpVOH?9O8Z1?>$;6)GA7P`P;oifD$e7|tI*Vrm`S9s#z<8=OUA4s>S#qU*&?z zj^>?ao!_Vo4IpVV~& z_UvqJBjwhNC;J`g=ci|%m>A=~TiCZs+-_d!f=luFe_T`5*3qnV&j$^P*q*RxMh+1C ze8{}}aN}+QXsaKN@0Qjgk#F_&>FDSd+wKM6WC-4BE>hVK+%>ad`;3zzZvg-J=c7OU zKaUO&=75@&J_kBcp&9eG_ zFRGqf=}koEO;lNn(H6ATQ9I&+KShI`9dIg!b~cUEDjcd4H`DRV3P#RVf z8_EdA$mRb`sRZC?qC>hIQEU2jjhQ_?>Q(xy+(fkDKnXXp?6OdNxk z|2IYEPhrxE;2j2Dku|ad z3>Q|%;|=cDSF0liy8<^}z8on^2G+PgHX56ME4eflNmn+HujV}Hx1aVqzneQ>^bp)5 z94{T;KhOKirBc9IXrz$GL0t2vdklNZ>V^8}<*Px0%2vLi%bwOonp$p?$n!-J>$0dt zr%-p_f0sCQRF#TtWNh!}mBd!NXRW8&oN01c9pmHUKxTa~DeqTww9`ppU`C9@QkR=;6m*2p}s1(Av7Q6mq%x?O#XiQXlM5+UFz=C zuV$L(`%3rM&C}_HCdVhAo_}E@>K94<d$PIlKFE5b@o7Doz-B?16+9+Yk*GKJ4%!c8N2sq%a5Ai^BD36F*U1 z{-F%7`;i5SYRDiRt{@0wu|r*IXIS&OWrmWC`7;psD}k%XQ+TNKTO81)bNu;Y!!=se z?LJT9(n_b}_u%1^;%+kY_^svT<9Vh~ zwd=T4FOT)Fjip~ziUL3KNjCdp^e~z8WVVib%+36=dj6^=`v(qzKc)`it7Gft+1080 z{>fHe|9If>r8gJsr0F?6h7{=AXy1;)Kmb9$e^de(+rV_}WIH{Y3{EBe!jzCq3Mx+z zG|=?9wY}O+>@;mbs^scOsA*m+m227_W6uwXI!E<;0_t!IC3dy`(C=x1EB6 z7;Sc~)G6s&5J9)w|76ZRTLRMk>;ShiP|eRmR=eRps>)VZ~M_jgk0!ruMD zTO@s$G9n&0u(o#d@UlxV;H5ipf!V{%X54!&RmR**P>L^KrGujwhA zAt@*rAOSoyNNf!z9AkQtkNjy?n*%l!Ny^e}T3-@bO>~a2cvL77CUh)HBNjB`2M6~u z_w>vA7+`QCV8qYVzds<@(qiYw+bru3g}6-k6Tr3#?X%2WkYB2JT^&8{?Cyu#9yuS) zJ{;(PIijnuv1=!L6M7gGN~@))NM9W2Y;!P=kFM`+)dZE`BC=J9m55V!CaW7F`+#)C zm)UpQ9|Tnzg^T*TM(F;0oblabA>tjzmM>l+LA%DLPslop&gL5OtBl^$2mfIt!r|S6vA-M``&WK)RHzL9y zBmJ;#ES~xb{j~}^mIV;OhaMu4+=BzpYD>Q|_G3nzw-Sik8uwP1NXxvK6iye~AcKdK zVRvteR+eUl=OQ97Wd*#S6H;mQeeY$d_@X5IfF4r9I?N6Nyg7o|H|tvHG~aSBZ_lgI zzQ@^bRels=YOsg%1l`$#bCQ!EmaNbw$~rhYrWEws2oN#kD-`BbZw-ZTZJzZ+RAC$9 z5EuJLg0XYQxG1rqOc-(Bw@R8zot6i~y|v0*q6!kIu|aww)tJ4X+)1}iJpnrig{nXJ zV=@6|%*Cm>``dzk=^<|3EC zKJg0*!fO#|{5y60>zvjTa|;U-rBu^im%#naJwofWba>LkMOQ1G7&@*o3#MiH^ol4^7dM01rL2yAYu!Bq^ z86Kb)TD;txoOoSdcEdKN?CNU%yQh3{Hk4^_c3JaBXHf3j+Q|!C&~~G_Ik0D1Xcb3z zl~-1_*I_xoM`9Bv1wC?iRDO39VWBEeFL2e;(MLk(eRZJz z2$M}^qrjmb{a4?O3%*k)2-G01+l_Y@f^C<(%U#vgPJtFIXXgf zxB}u7$@_sM*l_AVzL*tPj&OQ{VuYSjRTQ~>Mw|g7N0j<@l?tr^S(1;&f<7?Q?dda_ zdh+@!%bma~(q%<^0sANLZ;E*w9cSOqQ z{zh=s%pQQK*jj4Mw0l29x_#?Y(aRhby049KM%Ep$^*!H&+!$~b!}2~0Tw$3qAb+NN zy1gCM(XOS^Bl62-R9@Z=Z*3&7Eu|~}tHsIAuJze%Sbv~OX$1B{p{l`Y2hdixT$?IS zxq2~B*NrIq|0#g`tRb2psAPDLvP~&bDDoM+p=Pc~rQ8l*o&VSAUx|ey|s85wyX2|^nH zNg6>Qa!l5d>I5IudNAaim|j@MTFOT5P{&~pRNY;2`uR9I@+?kopIzTC+ufbr7{f#3 zx4f&0JzMlAw^TNcR}NQ;t_@y|j4ZaEPa0Pu29F|&R3-dQHtp{tNPJK700pf}Y{dG@ z3vkO~yBQnHu}@Ho91d zb80L*I^O(==x90zjA;^HzWEj`$pkH>OF zEneqU?8l2wjOVSw@G}?Ncp~!4{)hDpUiD2C;RgJ3Hs)V8vq8DoAo);J)$&1=s&~51`7KGW_yg$EsVLj|F1S7$t|D2)xCYccLITqJ* z2~lrfdk4>?#{8*0GK`RRGLW?mH7O~n8p4zE2^@it6E&7I18Gu7zHS_tK@}{?sx;qO zymJlj05#{U(C+A)z5;BZ-4{nBj~$FuM!Z$A-)Pkd7TUmvyB9UF#W#7oZRkJ(cWGK_pM#881* zA+IxOwiamN_%sJurT@$8TeF2Z<+DLW4AF(V$@R0vvX&NIVD{uz?^+j8^%_pR>vNEJ z{sAc~OHY8Wq256cla}Vf4wL1P@&Ba(aLnVBkfanw_^hMz(z5=9iOA{um59D<39|L& z9D~H3*?Ls|21ahR-~b@25^S0=EV z(|$||L>QpMR-KG}0Bs&vpjnqiJwJ4dBkv=n2)I8j_qzo+k128;WDrT@Z?mzv^dK0i z`fC$L>||!N$T!&AbzZ@;?O?o=;q^QtKR&wC-tD+8ZwwbRA=B{Qd{f#u43laYY7buIJtm=fv_ zj$$yO;2J(^(REw&-B_?~+kX*y`N-kzcE$sSn&+P&214Qta0D;cE zU5kM7dNSaB*U*6Kb2Q! zY_&bun8IDn4Ui*%My%*S8#mrH!__z__d-~uS?Ny)&Ah)`1yG+2PyqVXS38N{cQ|GBo{*VDNNHIMF`hFPjZlat9U zGD%v$1W*`FY#)($Zr>yl8R1nimpg42f>a8M?XB`e zpFA^-fN0W|*rG3(=K#X3nMS5Up_l{ zOuC2LBU$uGR#5k%`Xn`89+@y;2%(c@pr>c5Q&(O628m27JQ6)(xqEvF_nZ2gU0y;S zVc)iNe|~?r^oW*L=8@kDt&%0m-Vjmm-^|FxW^A!g$GHDB!!LdIb&X}k<+ zb`nsoE&;BgD!y%|NT%-I)Oplu#v8Q_n`X&?b6QLWk&Q_13e&TXKOhYL;Si~!_ze%1 zK_1|Qh8B=`)ay<$3_9YJS}#40T=crX1r~<`KDWQ>?dFB(?&vR>6qS^@{xi}%Ypv$x zl~wX4CB!6zU2A||9XrvZc5v|c)CcB5sVH*#9RszA`6n?`5w0M5br8J_fFzwPu*!1t z4D`LfSqXSyc{2qS!!vN&8|;P!PZQ_U27tA#tNDo7!<@o5OQW1DIQQ@Tc3b-6O#2d< z-1m__dBf{Y-}?Z5q7*!J=ugb6IAp~3V$HAI9nN>7V@+gR5>~N`CnPoU;TkRlrpgOL zAKseAf$(BrSm5qI)lI{8Y7<^wpUp>xho5jU$unc^v+E5F4-XA5dcE^J*>2eQGqVdI zkXH{OJ)h*d`rY|b(Q@S;(HL3ZO@8 zI>4}vQuxM%lrbtyiR0zmOacQAeqVfF(8c;iz%LTl**FFcoCITI4*duP!4a+Pf8Sth z>fUL27ji7QGqW(m`-Xqh3ibbGHAr{XZ}PD zw}M}d#&ODEnbKIy(a-^0jHeXZ&={WAvhski$vl`Y_)V8Wq}R@OPt{qUvfBG~0`wz! z{L+%2x4ZAVPy_eN0_!GGhOJw``I}AKC;dJXA&JFoRfxj#$a*NN5+ns-El7EE?45{c z_s0xi*R;}OIMLtuZMD;r^F3z0iBDO#%(ZCTijNxIpp%qrHe*v~u47*Ic4^l4@@x5g zv&S18PqEavyP@Y__*uTG=gCEJaz3MEFt3SZ2j#?o6|f-iXCf$nZ}a(1iEP7Idc5Bj zLgo&glKF|ajOOMT80?B0Fl|V1sQ00u%D8y~vk?rnu9IbTL;(%!k&`*6UkuEtYO0_M5M2%Ola~Z10QD>90)W z1hbA9$7NE70~x_xYLW?>4lA+`#u>xHz@*;9W)RB)pCu5-Wb`C3tC0DQAP_azdK&3- zB;Pg{(OJxAmSrKUPHm$0#k^WL6`hNioohPmjNp84W5eTLnN)K{tD8`p^<6HCn!mNw zi3^u~SDU?>{G`;DV=r?mj0y*Xss+$@d$0rC49NDQgF02P{eNCc5;0J!{VsaXokS!A zCxEgRgc@$l7IO2@5`OGD_7-7FeXIWmmp6{_(-^>flSyl*;iAf`#m%J$%P@Xgl?2dn zqg~N|qh4Al#6e}bg(O_i!XE+0U6b2BX3jH$M@-@NVre%wQBzBP=Ph#7A>mjMb4s#4 zwFJtVH;RFVk_6+Lzm^d3(nWjBr1gS}J{P~)Ih}q;^|2DfWO5h$!Ni~k51IWGuhM)& z@wBd@1I01xQ+T{`8jEfa`UJH5K*tW4D6EObk||}JfldcTSXwIu8S0w;A<8xM-1BS1 zdk>vSkrZ|06@FfCms9TD-_^3k#r^#Gp*>4(kVKfv-~WtO#-aPJ21&{G261yHcMK6Gy+wQmxLN`P+O}TV6l* zD=i}d)6n8FkYo|CZZ}nLxxaruOr$C)4~d0xK~*9v<&D^d#HiN&hcju0x#(V1SC2Z= z?%4P^@xd~P@KS5%cgjPgb_vaNBuSt6zXs*|L*vP?L3p-VYAf>+vVl7~pWJ?@sT3_1 z3n`CZ<=#4W!kj!k(>6R@JcO*F!&)h=!Dw4;!(Z|Pm$9*JTR_;wx z>9pBH<{ss#%)_Q>s;LX^JW;FKU)F&q2q1s~-(nyM$dZqstKH5sWlW?_UybQ5B7h2q z?`eTX4p!OeyaY^3rKLLLfa=*oGVvNzF9oVWyVbt`6||8+&gX!c+-qAeu4*s;Iiu2>iG$n z7HAcfMX&R{6-x3StG&Bi?PGZ?9@8%bAIn_#EPa79 zNkJ@SBPjxc7|Jl%`Smy|C=h1XOGTynyrl&VREdd;w*mmwy`HnR?#s)|nVHm3M1eOd zgoN)*&aw(yg3u>=Av_BP39WHK)5E1LsiG=BJSl6E41QME^lZweAxyNEDdncWgWP8O zvvfX+eR+W7(b z=-Ooc?|IPmo>w6lNj=NUqqijcQMen!eC9M68{>$`sL=hY%@%4Ys< zi*rYjD|FVY3j*GM->a+h0&-g4wFLa&Ax_Gg!#S9rb%0<4i`)j+@>f#fn z%=gImzIIB5gf8->#g6XIWD<)--zv`=QvBcR>vBcocYrAWSR7bXR!^AGwYy(GD{Imp z`f2N?Tc#N&gBG@a|8=1>;rtkfvBHHAk-yH|je@fCEc=uK2@{s}0AaPfysYdC*QivC z8BPKd{Uv{wrN}5NVHYIhwlt*izbEUV9tI8vP4GZm@EucVC>R4gd>p>f;Q$K44E4=z z9M~`oUVF+&pWiT@qE3q+;Fft1&xdYt!J!3d5B?@!lGho8PogyC_w=U(gcWJ>mM`7K zvi_KkzsIIQIt$$8URLa(c=szx9vRZ2N$Q!bdN=OkC z6&3cm0rvLzaOk1ZuN`J54Wl4V#PTXNSX}b-&9yDUPcLu!TdTicj}6jTTQ>xf(D`W~ zDEK^w7d?FiV1y&8<|(+wneXyRxj})(q>_?nEhkz%-H(+*@nfX2$dm=$qF=M}_V#I$ z;9*(69}a7?!J+~|OznNe(?9W(#lo!Bpr0W*pZ}wgB~!I@V>+NH?fP`C0C!BX)WJKA&ifd~M#m`0BN~QDFp|Ct#TQkzlMNyz{rPMW-y;l%R|pUE z;q~Hsjpk>m)jvvG97m~+4&C9M#7Qf)Apcke$sfQFjjaG88}igLe74Lsj&aXMgvxBS zpD!K%iyNSD0L-N7(UbD~RlnBrj$4%`4_9%(ueRrU3`oGUwbl~A3@GO9lWuuY*ibPFbym8D0I{7ggzNMAt_ADT=%&Z_cjGTM)^%-MV_+$nV$i|pV zTb$yTsO!9*XKe?wQuO3HtE249OS?cILK*}SDCdYRe8hWkN5lcBoZpFQ1s5n47@y#h zemmmEIq)U^LC?5JMfGfm8PW`KmD2NJ-d&-Ki-@TU&m2-%T%k*oSQ2&x&8Bm=Bkwh& zFhF>naK7^Zn5v^%ek{m8fa|?8JoCG`u!sZ)t=No&n8-ZP)A6wlaB=FCj){yofv%QG z{D8A}+_DCD<4M5@u;+@7Ryor7n2)i3=`9J)4M3>d9F-Ev*Xvfk!`)P@nelvL6A}fP z2VV9H@{aFW;G+dpk7xzQ=tqs_-zm!#S>$!dv33rIw^7x8Yt^WIRsr0 zXGvP}f!W#Fyz9p|drP-nbNj7RTXpf8*WUIh^J+%I)~ktfpN*y^CEaJ-K(Wmg>3f`h z&y$8$>{1_-Ecn2O3Bb8uLz9>i1f~$`v@`)WBI844hC5lQyoS z-R$(NYXZJcX$Jne*)@G0*8Ws|QWyn!!(hl6dlG?};-wPih8{Tf){&{ygKJd2HVT~SbsnGUQEzEV0K>$;m&DPQuk>oFCJK(D)sUXmH?ql~k+_in~rhvHm0uGk(>Tvt-3f5HRXGQCahas zH8&@|u-WeNsEyZzNj7nNpL`#x)@CzDZGI#L;kY-{q6d}4_(xF&LFXKm zMzI!}l_jgZ<&X{a110iCJ7hK zbiVU$p;m0*+akmciNQ6JYq}H3EBhw~+zmA=>2e*bK;N#E-{0;@Tqg;O;y(KsdSs4O zxQ0PMq!f$jZr_bwdfeJ@W6s#16jfG01U(;V zA?j~JgxhP_`AZz_sT;*)tyx|~B6)vVtg&Y+qZA19Q{BUMMJzZc@$cx}r@$l^>?Md>HorygMc`|T@s$?0yct8)le|3cA;^mFtgQsy z^9m7h9u@Ri^=QAPCr?TisHf}{ees9uy{o?O8Zdac8ko|*_H3IGoApZ|3W<)!HET66 zkDsy8H0ABlrU z^gx{lFr+Tq!#;j4r^ocSz&$Ov^KQ?!HlmE>B24w*qmJq`flHV660;AEOE{RhaJNdX z2c@)7dVDKBc$of-DBf|G+5AVZz-$@fr$I}Lo3ltWO>dR&Gx6sVnMMh9UB!9jOYD(e zT-0dCATEFVM*^Oo6Vk0Js;ld3TMx$~I9m>m*nkbRNLAG(FD_VS){tBmd=MJW76EL< z4s>o#I(!hm;)F!3VABRXaYl3&Rt1w5^FTl7gNn2Z4WPx|n>cb?K{-$}~< z4!C!$%{MgMn3$jKhJc9W>yW3f(}K$@me*#W<&ON?ClemQl53R){P8;0&q*2KoK7tz zncqvQzJF&()WO8e!2-2&sl=QxrbqS#4oB7Q-~PsnQmG%c$)=@qnG~=nATsyh9t4zI zgS(492~9-`*$#9CFCb3A-ReLVgK&aXL{z+g?iL@L@<(hGIsKCWX6Z^yYSPp)ZrN^h zBpyEO{gJlRi>~iO(m3kHn%JyW;NmiIlnbHHiX?3xylS3Mu$;q>U9hCt{MK5;m3{5N z`{#SN6``{SB+81kt3{1u?{1tzoB$hp6(U8L@P+lBB_HcxTqxxoqhqZB`M1#610K`L zAEl-$^ecIvNn=d2!t!b-!;j!2-J}GYV&OC`=0NRPPwo~t8_naD(eEH`X=fXm_(~7Y z_PsxUTAAzo5cBBP^1Au-zH=(-Wl>=b9>89>sTTZO?IOUIVFp(tOJdTdNra3z=j8+i zVX!kif#H1o47CWPe=jq9hw^&wR6V}+?h$GbLmeu+=PF9rm5YF=vze8Z3IC@W{B;3M zEPC)sN&Mv}9m&uH>Fzb=#u2`94OjBSwN{pnEX=Ft!-+f-1YxD-ewb*Ztwo6t@U(AaO6|;%hi?5%|Ga<9XQ5{(*JP*0F$(; z@AX-e0yNZ#L(QfX$&?P62@`rN_p}bR;2LmfFE%hJ&4dA=Fw5#D6%`yN=ui`!B`x8u z;BDa1!DOy66U3i&5UMlF0q$wU-xmxZdJIx&kfCYw&!mfywK9eqj0P0FAEh8cKzm;z zGGt2RD^#Tj$k>?#_BluorM}nZUkFo`c}wXA(z6db3Z!#aYyR13u9EM+>|VaCd6e}a z^YujWhDY7&@KU5=k3*!aZRT|84~?y=-StIf%(v@#qM35k(7&6eC@6_4UH>eqW>Iza z8H?#rZpKhyou!e<{o(ROX}9h$kgv4-@*hB1R?dN%!BM5OmN6#*H$b{LC_z>jA|v}c zmscgIn?Z?eTfe@gsm0}X_N-T~JXX$kPUb0vY-~OKNmVYVCQ{Go->mHheb~2RclC1L zYHcqK#5oOYlxw@nIQej4;nVy38&cHNIZBq+MnLO=HDNt$aV;#iP}$IwjRwv!K58N$ zdbAg{v+*oNu> zbnSFP9xwVGT=d^LC*kF1JS!t5mM(DMd9+v96mlI6;1uR`cRp3mSPHP}NySznRJ8ky zvMj)?VO^c}nnO9G8W_WcU57KHQKzRWrPpP@R6>S@-s#UVW7>r>!;2x38BXm1p-xGa z-9EQbK+v*zHI?irump(H&_M0zkfV9RDg_bRC<&Uov?+6e$>HH$k8kC(4-OA2gQlma z>2rPCNR(LrM4+1szIrxzYd<$nZSo@~>U9$RbSHVR;iHb7hzJ)4B8#~Q2jMR=1WP%R z!^2J#-z*%7IIW4ufHr`xsX!fsokA6ifsrwqMw`Ah1Oj2E+Gx_N)w|vAaz*A=WY={< z1|?B-J_33)joJ4{7W2F13*XPynr}?eT@t&BZgJ zqFLWo&hFlR$1$eE?*HN3{qLM%=Wkc8q)(C^;cE(6FD+Kx5McFt%s;e^z z(&}I&s9^R)IZ>0I8q4>_h0Tbo^9|9g@~h|L*UGZ^CcWiYhhU8yXhVJh7D1 ziC{udnQCdevSrl}v0j=h^+97H>9$$n6DEwPOA}X$B|+^gUutJoJHCn-i8?sRLL0y?JLp$af)EPiQTF~2P z$dhSpo7-(BS1*$n#4ehcnBY^c(8_HhiVz=yxBt67+ZvRFwtrdspp?XBmbHLp7AyxD z0MY%;dzG<0y@j4yIbOetRnGFlk7(<@GlSg|$czoO5#tB5^@;h{Ev5?L)`G?-TmEo^ zNJE^uJQ`2(o3vRyChcyMcSd02-m4u(?1Uvr$sLhz5D>gg|jmdhfYTKulekJdA>aV z{_iM>h2_Ni#6s~0uvN)z{rk~+wwOMWcf^g_Co!{&!(0cJd8b>Pk&2BZ`5E4FlHelMTXK;2wb2|;NQIhI?AlJzE+O<+;?m4f@>u?L@Mo|PH$3pL!bG))B-Btjw- z>0~gs-zG*K&0@NIQY>XO>x;isNmiA9hpjVl&PR^?X8QXrcPkk*Z+w9kpqlxG)zyTJ zFFzTC;Hc}d>8k%t-p)6NnqC>wYPiW7AcY>SIThBeV(aug|G{bE$hX612@aNePaOLL zvBIPVC(0o-Y#H)t35f}^6N0Fl7xu=_Gb^3;BA*PNcb%V{tre^KnR-R1(Dy$+da8Zo znaDY}dM6zY8AV`mLk!&jr){P{J7`+j#z#iv!&x9m_DZ&ndYTv@DKjJ~Dg-=44=4-? z896y$|MpxDQ=Q;;l{x4_?4@b_T+DYMwC~rs3g`l#oV$Dj1CMe)DKW^($^wpP09t|) zc6oVe)$SQ^Ok`W!boFY)D6#G*@{TGjio4_$dyp;^bsVjL8SrwW!*kKoP%GKY#riS& zX7bxxck|!uJu2`OLXeb9M`@;joDi<8X>eM&ymOJKmuT37!}G|r&9jU9@f^m=-)TNR zZ3R~C++bv$&|-53z8q||B+8gt_r8!qjW#!PW!|bf(x@t{ACCNQ?k0>F9gAJtNxc`b zBuDBo)$hpn+vlCX*zS?|&wQR+G#)Y1F#f+6&#$sN$q!qjX;C1P?5gn>3`hZ^+`(#> zH(K;P8hJjx;+aG&n+i$#zNdi_xmleL5QrKoM2-Z68a=4>I(oak-GSX;pFl!gUx%Rc zY0>y$3x_QJuXE6a@o>>+UCPwSGk?b-PZy76y?t3>L=Zjj$P7k82djNXjj@qvEL0EM z95K;VYPf9tOj0t#EYx3&^`<~bNaW(!cLYj#)2OCguHZ&-Jj~m(nt!PI=Np*1)^E;OeloCu!jhJ05O;} zjpDDY9jf4_)`m?iq`o{ZiZkk5SU6b8{X6KBl4#A)qE7oCuMi3z}g&-mWYEZ3x^+ zHnT#YAU+zj`#_;9J;WkLtN|ra@0FD6}e$3h_2@lwzybD4NA^<{yUf*P@2jav`S7 z7eK)&hPE`7*o9ND^P|3V&p~U^M6sV4*}xTtF#(lIfa1Id$k_Aq^Wwm38Tf)R0dEi> zaVsveIbG>GM}diwr&2m=cUv1qC(n>7uXTKFu@W1%pL`Y-G52p`GpG;(f{+MmmW?ofupwYc$Bcxt*yLl&<|Qnxt~l_g*Z(;5 zm^-(~`82}zNonF&Yh@ZNZTVY=3-&-AsFns>k`PHkNz{_Hp{4V*i&?#jo@gQ^c>Pu9F`n5r6x-;(P4THnloVBVZUu^xae2!!W*fQoO zfrm}bRPq@U|CHve>?@d;F3A=z2-6oLNkgc4Ld_%)&A|H`RIgNc318@ot%}=~*pe}Z zqp}JAK%drQ{f_u|dy=FNRRKgn%LBytt<~|3)i}p~>iFW;F~v-M3^ueSFv*7>KU}d( zEiW&30751hY3=sh`EoID-ZF__`v9-qEa%K_QIWMi%yv))@w))xOGy?X3-U14oU3(;1*v0skb&I|A(ONCjrwB zsT2|Ev~Y>s@Ep{^WF1O(Jz?xkn*et|zw3_;OWweuz0kC&mw2C|{eSxNFCi_CGA?xV zNi2^%dXtRs8O3rmwQqc0@?slDt-dhQJ@$JY7_|&3Wh;F6y3%NA7f)|5IX`=9wYL>_V4v@ zOm;lCSX{sNV!&K_n04I{(Y5$p56QX3^R$gW1C2n<+V7R6z02pp{hH^E!{Yhpfu9M0#n*h_r%Z-fwRL97lIgXZqs!A;wN`Pm(HNkE7@VORxVDy`zel1=i z`CA|W)tC1Z1XZN-e@lE0O43_|*ny9;u`C&MQ zxDyl2Bw*i?posmc5S2hbbxx&()XPo9!%TCi*oE0c2LGlpb)Lqs*3dW3HpeJ!TNT~m zg=pO{t`A2B0g2cMX*D~E8fm0p$aa<0tYOp7jq|v3MHDB4Cx;UTD}4g|7YBSTFf z1yM>QtD?$FotdE|NO+7mFhsJy${jcQxb?~OXTbI08VN>lnn820zCD2?h6yIMO);iA zn#9*#xscr^6b&&UpI?k^t8#bp1Sl-p=xoqnY%>tm&jU6X%~^yN0Rb&YCGD6NQ8N?c z5L*gK4j)9s0FPFjX`HbyD8TCMZE#*`nEQAPPeJ;{5Ji9PT@t<3&6CnaM;|?kEssG^$eyq@e;vQKjzYa82oE&9KXk>qb7TU zrKLk{3~*kPv^EbE9e!!f8T}RS%XV6ezIK)VLaCjKLyKb zJslP#kk#0DAYFg@VV-48r={cplJ+ar^AHy3YAuCYFh~uAY!(NS-&bQk1X=6)bVUc} zsk~FN#p3h8cgx;F0rgQqJfvXqQDg%mqX`D%2a?dzG<$wsE^FGkQ7lp94S-cqf^ggKO@=F9|Whv&=2}|`HN>|q_Bm}m-BOPK)ok2|f z2pM$TXc$vMk!ZnNAD=+Cj~9y-#sO!40a`(u`}N@SdeDQ8v^t;?a~j_mHuUw@If%!&NSwNo|;+LiO_UGV!mXo z9gph9k3&ILEW}5hieN2z%Wv1D&QedhTo@jnx$vq_yl%oN8olOwDguWmqA&Vx?j;S1 z6%o-I=QgF$aB2wj&?6^a#?C>{!q=9kN^RgXGM=WC++R?o3o`}XDce{Wm7tKI&)Lp& z-lvvpuWH}@w%F!JX^DX1-(DeGgFR>MmpDVQmywy$D8k|N>@h82C(o`C?S>BobXCx@ zrF|e8BBKsV0~n<0i#GJO`=?K)?K5kOivbrmCZhQ^ly^{Yv1Y|AUNX=}d6((VF?GJ+ z0PwN%;lBB*4EPXC&mVF#5Zm`@()k$fg^iNvX>$tHpjy>>8N|wK_bwZigLl*LvCsYe z{jxY>8VVCl`0hAF;-e2Lh#xxTIO3D7Yn*j}?j{{KLh0(T;IyA#8a2*c+}fl{5Fjop zr3gJ-yr{8)RzX_lW*xfritj&KJ4s1Z$yLw@0L_%XljDaf_ji~7*NwNdr1%M|s;SOv zVRlI+4hkmO~W^zwU{hE(z_p^5yIhcM3=|A%cl5CVA!CO zFZZ`KS1Qia6+;}#qC(wQzm9Oz`IUoB4j$vyxIf{sdm)t}}BcEc}?sd3*Xz=ONC!^MMxDf8hM#{Ob@c4rt zm(17ytv^LMzudUd&k7l#+hom$)=l*`G+GC)E4!W83R3*)-` zbDDZ;(%RX!t5~l8p^}xOwGU=w)EOVE)m!gy=ayeEWu`l)qB&I+y2YaM(8wRhsEo)o zxyXbLG;q9IIlRhq=j?u%{bx@5>yShjzwWYZH)+&yzwxR2<971X2KF%kHQM^y zQ^U=aRsaM7tQ|##ME2(Vd^Q|XluYp9gzsv;8MYF(O zPYpqFQcW-svqO_Quw1NFgA*|9(aiHq8TlroD-_9mKbNHa3zZJ(G?KMv$L_lBJYIV~ z0U9=icoP0`p*_w3{FI<)pzHng)RjOQFcmi}F~!8dTFHhFvz=^}jEDfXp6DyUO$`ve zRZ8)PT~p}h^t(?Tt1fj0;onQDPti8#IVIr0i3BOcm@~jh#otrUQ;P}#6!-#xb8}-f ze`a6xse4jLuLBzw!IVD%-TutgHV!wraY5JE_}J^tz(54BV6HgbvyIoYMf`|8czjuQ zWg%BVg_^s$cFA1!@69XjUhaOr>oQ3Y(x`#C!zwIR6y`sz3)*F#6%&6AJWY~Krq=zX zT++`9(-3>Mgzmkipqca?WBgpW61Wx!!+i;Z^$p`hkeCi|v%=>lFF^_!i61s!miCu` zm*?iXTu-DaRHCPk2#GB=3~=W6wgL;?A0m!mpH*XeD|Tnceq^22@3)_>U-`;lj5TIe z++~Y@$)B6DYT#22qdIB4*)t6v>r_JzhvYIdV-Z3dGLRrW*=8CVAZF!D|55TkG z@g&c?`+Vj2>A?Eg=M4#+e0_6s2E5If{03)3dOiQjhdP`)GA$+)jC-zkH63*glr;$m z2mt+McX!{ec~Ow(^qXV*HE`NE3A&8-Dg4k{y}fTK#O7E5r92U4)^CK=)N$ok&g6?L z>wa4^Mo!iGpo$>3o`Uzne<>e3oD`DMxUlQd+|uIh<+a%9L@}^hSj(oUMlg^ZL}^~7 z%gS@SczLYHto83g(>3P{lXz72M*K@?IvVm9_>T;{t4k#mWlY?Qov+RL|CgZKv{(yIJtb+3b+`e(L<=&CPMwN5fwyE|a!| z!XbM32HRYi$&F2MG39vyAc@z32!95ABg%rR-Bkv(K7U0|TeILCOYt?L15`J*c(@Yu z`)h+XJ!bNn9lm^iU!A5h1#fbW?LL-RAEUC8;5VaFi*DK|zA-`1pj?`SJ77vD}}dc!M0xiUoi#n>u2#z*;5TM@V~7CH_SD z5iR_ACUn?v@e>g)qv7Sx2~r$Lh9wQ&uqy=ssq!T{qVFC{c%AQQPc!^RrD(*#!EnK* zMM|C|3cZ%XI_`%Z-R8P4ud?ws_x;T7TP$3lQ->)gvfs2~7TA#tWiiFD@PFsI{MyK^ zqZoOAe-EI^fS&+`6)2!t?dv0idvdCt5w z47`KOQ+;YlLeFeEc@k;hW#d+~V%M@{G?||np}_)`v?d-V4M{Sg&aR!i^9*j9V@+3Q zMMmH9_UnR{{bxLdpoWnAs5b`{pdmw`#Et1{a-#fK{?cz_Q>wGTI(VV1?{NcfI*?Y&HJghP}jr zmd!hP=deHb2DDwUM0{H;ZqyvKtjX+QeT>y1ei17^;Ty*|=T5kt&fmYW#wz0~RYt&! zSLMFH%r>)F>FHPGKt?zyQ$ws_{f1J+VEOkFY1eZy^u`CST`?G|vHbommNpwaW6g_V zc(M(UqINw#y1CVNb#>L%0g6-+9diuL7!M74KNo;0`=S%DN;s_;p9tTP8sHJ|L<{_^SV+xqmO}~ABi4?%>FE1`G zE$us30y;laOdl7)MWkEpZ=c?Dh4Y7@*BoXY|6bCL;506-ST4kyEXyow!KqG$hl@5U zugqfHvG6Qt8mwHQoZxoi&U(6}^bS9WO!DE^u+BHAon3dWi2*^G)ByK*m0E!FpAFTy z3^r`QC-nXNO`!PeM48m4_^POvQQ8Q$>|Y{_M*5?0mTb+f-78k?s1@?z(%H!{7Buf{ zteVCjzP@$V)G@y_j@R6b@v0r>&4hB165wu6Z-yo zrUYyp+5Yu~UE7A)#ovnxGrurc01MoN)ogSBtfkUhVR0 zcx*8VtV6~oMi1_@eH$|e@+b-~KnU$+?gdFDvj8FkCy;U z95{w)R}}a4JZE~f?|0k%76Kyzyg(ztmCCrsQHw2{-njoxsZ+UjSyks3k>w+<#VO$+ zx*k*}HDvk9n=9608*Yrgt;yOgw=}qV!EC~zULtXlrAh~nFQ-Alo%aTX2t1b%9#`u* zS$k7}O%b~}I{aJp&=s#Bzd!?TunMIXYh&le;({9t-8F=Nn>C_i2X?ypT;S` z@`1gEV}38!9d(a}$uApKtVrbmr_0$jta$N3%TWNA`)kq2!O6wJ-va=t*uj?TUM1sR zHNV?p;O)G!!@n`E%U;;Tp`>2FUsdDTz5;AmfyX`nPj&%h?dP5Hw%#++#<@t-oqn+x zSk{D-^#@8gcFk_qh! zLII8AtX^O@(L%-50B?8Ceu>%}dzt_IpBG@S{q}`6^zpRj-%*Cq1#vREC7%k0aU8a_ z@xxGryM`2_(rv?%cGYskM2r60fZ5h&))C_*MCWyo`q4L7p>8$4PVR4g*2!qkKDLBG zJ=2#7(#w_~UWV3cjAl5AW;;3@iV6p&WS^}+^|DP>8+Qjf`UxYeAAdR^i^!#}0V@M#amth1tEMBi59%@j{Z5jN2 z-T_lkVAik$-oK@(kB|TCRe?TkqZ+u#xj+BMws-cc{nvcb3i0W&YsS2RRkKbltPCs% z8B>|o9jpP_uf%Q~2VJVpzz-M4!}_sovkWL3qW#OdfF%?hF44ZS3aoXznrHT__{kkP zm#>=x6!xi5QN3 zJx{T8`q+dY)VBDI;>r6|FT-P!u5r1^%QTJJP%9_E@$&2G^i!|QAM&7EPKV{VO9AS9s&N6e--j!QiO{C1pNjz0EqwR9;5Wk{ltQPdq&2bpR&-L7Ms*po zB71#dSikfxMy-{`Fr{yem*#$+DXrMWTPSxSJHNWC#Az8qe>NF6hVx!4kPAmOk+wl? zc0~&`S^z-|frLjzwaMP_HkBUJ%i~FX&OXXFF}0m!A?gYnY@$4f1AN(9tZR*ei52)E?#_p(^b5YP4rDc-oZ&6ZZ{N2R`_1~ zBkni~OkeID1fn@Zhvty=_sGGeI{anSFsprq_tC0>o?ibipxYIML3(zn5_VNj!j>}>y*;CE`7u3SGlBiL^tBkOX89>Yr7uk?v3roH3!S0Zx?^m0EX2+uk3H%zO}V2*zo!1c<`TFs@NHtV-HS8#X616&dvsQ zKTkBk-KTOl2ejfRXdJtK#Ok1)j>+kv0}R?)K`#(k8n7@t#>WHOx~i4DrY3%J6yN+( zTj5uXt`);7^~>@(gq$sNND`-BP{cwQO$=mi{NmxUwLBW{5>5Xf_jL`Q8k~dVn+LUe zl2kIGE?Ne($~N=)88b;v9H6g_EC*=2Ts?t@m@c z5y0f;m&&KykS5eTauOzQ9{kY}SDf{Wg~FKZ8gu&B!C1&cK<$U1UG3)3+ZXBO=8a7F+xg8812|9jnqSiHfAJa#fh} zBqx;tU082<)cj-F?H%+gtNZ!>S+f9Iv!Qi@_iOXSDz4wMV81;jx?s`w4F1$nv*-g$ z>Bd6@-Kk-N*7jtiFgGYzLD|95jPm*4VDc})nuFdY2Ii17)bE8X7!749)Z|Dosy-Ub zLa7~*Ut_cWYJ3(|XyNI3&@yU88%O~C*v$$;*3q9Wu>r+l-(;c&f@xY7DykTh__{fo z7C;ske1wJo->6bsDnEJE%a<9$LR+Fts9qYD{FDmR+qg4zD$Dt<5HH_-!@nwJKL z;FH}=S$Uq*s%XrdFcwmCETcf~YW;UU)uc!va>a8;?_VI`1}F6Z)E6ocH5uJIsU1QV zL?{Y7H8s^|`JWD!mRfox~zL^mvWBkMZ~ z1B5O}<16Dx4C-Gvam<%sbf&$*iXa)oE5Cd5N9?~FAl#8~i5*={LBLgXPu_jM;_SDw zY9lB~hoqeHWq$Xo68>yyL%qgZ3M7dp);}}^AEtxw8=1z5f(C@LCVxPX5ik*x&~gqn zsqy1QR_q0wfwI!hPu@pYEnY~`gp{lpATl0=6!vBrRA}&1NA~Xag|iGa5JgXL_Rj^5 z;Y06&I7n_VPyG1!4b9yDlC3_TtOMu8W(1&<2o1Jx)1AXy<%or+I68YSFmyRka5*tH zUJTbIlY!fZuS61xkJa7Zlrd)4dOz&bzhxS2VP%ys=IL$A&6dt}o;bZm==>;5?8#OQ z%gdTTkWeQ?)*?XE0!z}UsmsrJ^vMg8kRnVC%@*o7Qo;IuDP7WY6uYN}&?Hx!b)%xf zAas=;TvWehNBKZ7eJ-I0rq-=fqvV4tzT~thd7lb-=4b@-q%(**s5t zx*~R7^V|2n-<>%pXm;9p%BPD;JQDxi<@G@-NmEMKE$A$b+8^X|`D?3K?7n`fb>U*p zp=f&N;_sKWV`nEPfVtB&i}jj29%@Q^){LT;vF_b68E{TDsP_`o^JEBlM+f?6TMICg zk>bD8V7;^kqTSxuB=uTP*KUSMB`w78=IeqhX7V{1=qM?i6z9yeVriuez9rehh51H)fkz0Xi3a)2@T$!>avVYGy4 zIaF9>=&SK<#8>1fc<+tdinwAxtfHQKleN<>mD;JBIsybDEr|zuhtRGR9tI%R&L&oY zp`hV(feOhbi&0r3G6{<-zr)AN|0DPs)_sTbe1A2$?QERuaNvaOI!^HRVOx6n@Z+7v z&@loe`>UVn`$xvAhVnfh(W?(;lWn~wNtO#HTtIen$skoQVNuQ3L`I0F_G-rkW%|9dej#v(KK4r3Vjq-ly`EGe&Px_yNL zrp=HWbOFahG5frcBAI~Y(gtUEZ6z7{+I-Z_*?k1r=ZiqRw%X%avx%-hJE(t@RV$cZ z#eQ&_y&q>A-700>bO9vnfeZx9LaL;|`wp||ls>-<`QoLTyT)?-xeh}8UL7zJZiF7p z3JJ7%>Js$q5)_0JtYq@8F$8PYDqGNvg9?MmR`{-;@wxtd@@0$j>dl3Z4-ZL63|dzB z<;{hte2Uw^LwG3&csCnev3P=d9!^{^}>z;XuKcv)Fl zE$2pZTaHwTiodr&L(d83lMt4HPsPg0TQOl5P`nizO~QwT?p6||R>AyP%hWdJ0vw0L zjmV}qV}>au65xw_d)9q>@3nxMX@?ioIyh&f#CDOfc}x+ z_d88~EAlyl+UD=d{?4ZB7qRl>su$n92&D>t--1pq81btPwtJxs7-T)K^Ssw?|MWLC zd2&`TB^D(*`G(<0eE1)7Wj^jTesT=X+Q}J;x)x25v}&f&#NSc+#bTZT9v?G~)p4C1 z;@cnBr_@GQd|H;KWhA*mnQfxiT6U*|=FaWf17<=snM~h1IY3qqE1*ITeRh88Exhj6 z1R=JQ(HR0`!!BQ)T|EiOS!iN@R(c0=sE1`}6YGv{p1DtzSFvPH?|C=!3r zl#8aB_6LFv(1bpn>xk*9fc%?Xgx;Zk-}VgzxDF+|CVW7APT#;_-$OW+4}nR8FzBc8 z$(}H#kP0wEzd`VuZ3+-@ z=R3U)7cckc=jZO!DN1~|1vaeTgZ>aZ?o7-E&HpcxWQ4NIWXx!~DoQJ@xG4CzSQ?HV6^)ukoUD+x7PX3f2)VRctQ?@MWq%T7m@ z%5$HzWU0($ZHQ6Y!bLPf3V|Tfu#AEtuJuf75uh;}Zj+QyG8%+66vlD|tqs=9Z;|Ym z>>Pw_#b;m2i?YTxnT$fEhiSh0w4l?=HCXt+Sy&577M2Yk&vnhH+y5O2WeIC4!KM0( zI0`DWIcF2`ubba7!taw3RBot#&nQY3KeWjW0=&bKreGvjip*#aF4pMVYBCg-@S6NS zUo;Qiy>#@-y%$t}jh|T~LsJWYpc&(14E=V%;z9`l)$i-|N)! zLctwUNLB0Hd9RWW-yHdZ+oF3GM@eW;J9deuIH&@W3=RcRfrc3MX-wKz9KHR3N}~4m zc|TUxxyZKm@8q1;{6?w|D48+#hf@C}Wjo#^#WJxL0c6z;USqW0G>U7>@5-}Dt@?ji zJ8j42zLh^8dBgfLxi`mNwW&#~M!X!Cey6J?Z)k&eW=J{4R?cE%OkUBYo>StRpJ_@) zj6$scqa8!?0k6Q>HK~Gj+cNWMl7gSPV(`h4@H=msg6LbntNXR*S61wTfg8E4cT*b9d2|c^oXc4|Pkj#h z)gJCfyfwJfLs<)cR<7DdV5WRnTlP5)yIu=84tp9RTBI_E6JR2PfMGSoLi82f*Qv_! z%_rv*>azWTwKM!@9{W&ny1>fE+q%{3VKVq@49^<*0I_j@qqM<&Qjiir^)NtK9HCR@ ziL&TPa>tIJ*1%9-rUse7{bg8j5n|mF=ykMMmX}@B5e??D%j-7>PoD#=9d<*w7`EZfAFh~cGJVEwP#AD6*sbc zbaft*f)GZTB~K1AIn4g~Yyd3rgI1V|oz*7dX3~%eZPq4-SR? zXxIBPB58^cBv9&%x@?^NMD9yC2TFy1JKiPO|?U9_&%f5eY5SaHaWBQF?dA zW+RFF;R@~1daN6YH5NfB!!@l+92s5PES0gBe=G~^6*lEq4GkZW0|hCp^~|c87yz&_ zJq>>3j2Rzq13rR%Ma9=OTCLK%KD(Z%*C*$vB&aX!XVn<=QsSmmRT(#_gM&d}Fo<~6 zrt{37ORZI;olX87ZR#|a1E6pLi(cEDtB;-kBtw8)LHg;hE&Mvmij$y^!W!8G@iIj( z0no8R`mhO+1;WQ!zzK#!N(0^mn0tt+<8i*KM(1K}aknp9d( zXxcXauFGneN*b&8#?@S?a7QBCt-954JZyjRXb#|LMb+Eh?$VGI(K(*rb@c`P-BjCU z%E3y$ipGn$4-fWvVQi`H%2NGH^QN2{3Y&69(N;5F(OTayhY^G^mY10@xl5wx=XtSB zocd&0qv5u((bBxH=hu+t8mgacSU;AHeLOwWTskMDF@tGFE7@Q&^o;-{=nX$PbYwlUyt!7)7X0@E{c zT=EXO39HMeWxjD{rx-mh6GuS+v2W}W5OiP~p7Bv8o{7?jvj0Z!R}0blaV_?7$oQ@8 znvK4w^32Jo*XsrtfYThIbK+m~y?&eq`eTJHe+boN?S*SgDP)5|H7u6e|7zEKC7$bUctudFruVR!?V66Bd3b4rtj?|1&V-i9W7ZutUYYxDb`g`K zeDFPwP^wyC`P|}W@51QlsK{}*b=Bj;npnWqfjkKbIZ9a}RS&FZ<^hj2VI40vdh6wO z%Jb>olwEgTIZu-95J`CU7-P}-`mP?&tI%4s$`}~Y0BWp-B_|zm4H7a084pQDgFxcb zH~-?L`|XP_l#%_;M&TP|NHV5;WC)O!rON>I@q-9_3|ag-uCAm^*NgkWGW|Tw*c|9@ z8@^n3002XQ9VOtr>fkM6$rF1$5D{aw8P70~nJ=Edh#~>RFwZvzV;g2Ry-Kk-IJ>Eg zX8+jl&DM}8ZylzxO-aFIHt*ue|A7H*Pd4kYkds4eH!nmveI+`R2c zkQ!^oh6OXEMq|CB;#FYS|3nV38rH45pY!O@?vt#|M9E@xX^qlYMBFFXz z#xV(bWBO=Gfr|zP3ucxHYa!7Sg8Bbq^rJ!x!=Ytjno_ugxP-}Q64AIM)cCuVmAKPB zf+-wWiHT0qLop(v!ud)Jokq?8=&TzUEds5#7aRv`YiP=X$D9c}&w)eOh!m<7t}KII7GTO`Q(OeT4o^LwXDxGeA*NuSCF4p^|O9%{>7_ zB{!B!ljnEIwxx6gNeLowdi6Ht3guc}UR_*XMT~Ieu@x{7a9W1KAW|sSjPTOZ>@iS} ze!VG}Mfi4xAi9EWhWN0ajl9;XilZE6cQo)-mk0Dch5YpcwOGjDd^A=ek(Rln79wBF zfLvS;o5<4qP?1!&DmJ!{D5|>r%I@iB_kUEpwd0o(CUMa);CZZ?c>mK#*ibaISax-` zKIT{<7FRtQJgq!Y`}hX1%l7sn=(#_V4OLl@LGM>J5eLZ6Uyj1N+r>Z}D*f@oyA_XtZ0Vwg+@gGHS+DisfoJip%{& zg#)a9>>%Z#R97A}$J)-$_V&*6ozt)yv1kA1K>^?V7bIcOImpp|?aV^ z@QYfACaPq9O^m!4#nuJj37fOhR(SD{(U<{iq|1+%;`F?#ICYw0q439ZbvMg0YR!7N z(f5icei<kfP%cu0ldIaNM3`3<%(vYzhg256YA;@a}!Y_EO^@x(9H-Bd`Mo3HJ#w)x(?*aY9-!mX#sT+NblJ*Lexhv9 z?etW?cCN)F@cCexEVflaqB@$J5c#zK2>3xZdgrfS_Va2&G&P$u;?OjEg))WUgy6PR zDpcL#*_i9=YroD{ycjk-D*kS64Y+yv`CdzT(>}lLn$GAZ7O*CxM>>`sV>Ze^=yXGc%t&j?SDVrhkYs-OKO@YQsC!?i2I=G+g)M5qun^6Mf z)5W91Yq5I=PUV|H>!9D!jjwywW210hiTYfxTss?eC#$3Y89SrWPu6ImWvy*SExV>U z(Ke^4cpxsmt%*^MWFxSi5x69CcR{gBme*@&w2w>qe6j%(7b}?>5%S!Ha}Jj-j+k4=M_$dSy^KppCQxI)82x?F{zNzRqBvw{S0 zw_W$rzZ%`Vt5Xp=%uX`|suqt}_rmxU2Sz9TOa3wt6b6lfec{FR&^mQWZ)Xz|n}0+h zyd3n-)B8}80|IGCKu##lsn9oODI@&*$gAa#wD8Nz53+pqxvrExaV}*GCY;Af0LkjN z*-B^QE3K}8$@e`NoXqm^vQC0d@?CN;in{;f9aflC(6cm8Hh9FwC8K!6hDTe=JgkR= zanDd@NF^nC-UkfHD4tu4#4<2om!incx71sVBUkT#)gh=l1m_?I$)yfNlab%}VhmwX zEAh@BRh^8Wi8wCy=(4uas-dt|)Y4Cjh>Lgoo^PMOycSupX;~8|dDSG)(zPo7Js#oz zdjXzzGR2?wJdh@~`=_3NI3u|{eCZ@#SzC%F2b{&5f>+vxv*!BhTPo7Oi+_4&pWV}A zJa3IOT#V?rr^PaseYAaJeLLN2O2L2k7zmCS$BdcNzqYy#ytO-3^bz|zK14z;?PyOv z!2r5Z8Q@cnmWw7(f51KErn*$M`)>e^D33vhQPbdB5P5}K?$5G~Fg@%2Xi^{ZVb#vhkX8Jto>&H za_$Rw_|%2VYTK(_S&v9+eWm4y|C2JmRM~i?^Z+GpvY?kQ5y{^5{bwxb$<7XH+R}to zj!FuhsZ{}To)A3Oo{tPT1C`(=V=cOF{yq4$Wm82-p_FxdbMjsPe6G_k&x&;lZ(CH^ z9beaLw9o=Gc(Dh`^cVD7DJS;4K5Gsc{Fth5bH#Q$+t%uhK-lGomk^+*`{8-zR(fS(a{0yrxe4h-hJeU?E0~W zuCJ{u*BV-XFOEgU7<-+K%eQo{Zr$9F-~u)$V`D}L2cSC z;6Q(`zkB@2&y=543c1{>qIgrPF6wT;VxHE1j>(>^r;s!!@>I6;t>@`u-5*&)bzg_wQG-Xy$hM1jfs|YKO+0Rc1w6=+FLCxNzv=Z;>&I!=0Ubk zw@%|E<;5F%=S_BG=hDV`#F(7HASta9Z2Rzt21ieOUS|bCl~k&@+)<`%hr^@gZ+^p! z&$nm7nut`oNSOQ%F9^>>W#8?S2jKtS+$?(RBo?wBs%v`V!1w8pBNz;FUv=bPJZyGX zp-laL^FR=n7Z;U4D8W!96~a!903Bmb=9~#d3=O{fj@$CBPWhruksC}Nwix$eNa6)$ zS(2az0+oaYw375kAwJ8enUs;bxrNuLMcmjGe3urMI z;${VRi`kexq!bi&LW+0kLlE>d`@saI{f*le*iJ;l*};SRLlKhXPe9 zJ6d(0tBOb4?CRVniFc#=*VorgTb8i;0TsnN!fl(8qkxG)zrp=ah2kauf9nzY*C;1i z$^^)8iguc^CKlVQdQ1dRGO2BN5JM&kc7vC`qRzZ>xt2 zI)|+Dm=amJRwhVDjeR>q#vuYh)Q?f$JbQsGlv0Y-2|g^Xd|2BNF{R?MKthnlm5>j} ztt;>$P@D=!%-Q~bJe_4+RPEZuhekl8TY&)uX%OjlP(r$-ySux?p}VCe1cvTzL`p=4 zl0kCl?tJ%i&U0Qq%#Y7|?%DShYyB5~;zEu=`;4fVn8V&--ZRDLr%nP8QuT{3UR)Hs zYuG8XTJ4kXOxfLpU`5HqrdhH{fF;H?jla+8)7MBr3ygPAIY>{dshC3YQZwR(S)TQu zsotMdL^zPJr{?cnP?dS0@0rb{UXuSkwrZ($z4zK%^`)(RY&U$^ttY?jpI%wRno7oU zd^?7DRBs7{I@~z9yW5^F#7@X@MisiSs6M|)pCZ=Uui(t9VHbbu#`o#ihI?04v{pQ> ztBD;9P%shoNQeiZA2RDNJ5nPnV@#r6$Bv#b)p`!eZjI%OG|dLK7L0Z?fQ{lsYO z4)+E+0mcz`J}v|K`^Y4QA}VZj5LpTc8-y{g0zRHt!m_NpIWSzlr+rMv8d=xFoHuhk zJ7?0}o*IAE$oqKi_>dawecAs^H^&25{}m6o6c}x{=s)K!OJCa|HgXnTc9+uFRPp5u z2V`_bMGTILF*B8?c`S8or$xpwPx^o6A)?PN-&pBLyMO79{}5la2!^sBt?ctb$e~=wVNZS4R0uOOqO%^vbcaihS|5;Cc!-N!`TvMZre+pNod`0=sHmZ!H7QPnTmS^Wv0pb7;}5jQTwsb3P#F85wY}r6lEG z?tF99W)(}Y_{W2E3)f5Mq!;lYn3nzAA0KbK9ba0~8t8J1+yGEZTJ!lExQAn7v#)*W zyd8zFF}F%C#YS82FIhr1b!bKOGmYpc$h6t`3fmhEMZJrF)Ln{za^;_Y!i8${tXo7b zsof@GC$NUGJ`2xQ<>lq^Q^nQ*ig#0u*fjwKwYorqh0F5my&HTT5HngPNI=r#`kRVJ#lqXSRh7c*oNDL4IGfKKjdX4K=BRM_*9QL1Ih<%(HsNZ=-zGCpcZ{o?OiJ1M9NHdsC1%JYrLX!@ z?cm9Ci+ug+S%1F}Xa1^Y-n-=Y@bGN!d_fo-4@om|;T9i@7H0(E04d8vEZ~CX_PU`k z$*a5TH&T1mFkRbIk-U$9zqE7+9Y6xk-)>3=)<2pY4#rZ?7QO!xGdx5=jLC;>PY}di z$jlNKk{nqE3C8Q0D$5E;R9zq0yZ!Qp=f!7C*N8-gf z;~z?sr)5vB9Rts|x*w7HG+mu0R6Iab;4#v0i9ANk@6hsa$-jaU!x%C{aOlWBZ}3Xh z(C5Rs`Ey6|`h3oMfRl-KOzMykg|0qBArDzX$Z^XO6V9Bd5BqGi577?O?);Yn+fhhY z_?rHrqp7S)R+0**Ls%6Xl};oJYzuZc`v|3P_ll-aUsx8=b_uV*0j|_H32W zO+QXlmSZXu&ExdfOj$7|6UvLdz{giqlqi1A-`;7}*`3p`0xFrNZk(Jv6*+{#9u9zD zHbVe3EFvUS7cgYPrc)H6C=jPRo`1g@&4gv_YTN05+TZMG_h7yTqn_;U3OxEd(rAx2 zB$yXJiP?|h+A!69JB1~D*u}69q}eH+wj@*Cj0ZjhGQ~gaTN)GKVXMle|^$ZJ{JSxYGo`MJpT^$5y z%6Eo_EUIVGfQAD0^vOti59!y3sj}nY{C@@fa#Bx%)H~=X)N!!5l~Rypm`OgWB9^m; zQISZW&2qO=9r_E6b(^lGnXoII!I}xG8V$kPv@h;&E)7LKMmX)}_y*pua5lAxx_i@nmICok8=jwxZq3wJ z9Bq9PSWQ3Io7i6HPPI(8CFj~zsuWV%%5en}0RdpqjE%Ij-a)7<2i`k4u$#Ji0CtT3 zi5##YUMrORF&gm{H8_pb<3%ymRKsQUaW8!y{4N}ee#G0k-cOa3_dNZ7~4mNi22<`kIdxVtwlIWU-{nag!) z5LSN)AffcqfHEhbU}$QlGhh>D((zzcFSSiWb%7eazjuD?Z`k)L2RkK~=GuDUkzXrL zUSc%vZLE(cBh}(JNBw}c1U!VU@+YPcYDa-CX++(97rpg(QyS=Zau?ZDNM1BW+vU^H z>TYZ4?prZ$*x9U4Q==3)c(?vGG0Ae6afl>ocLyWhVM3)`b@tomj9Hm*TlpskJ!`Hos(uA zr7`<~!#6CT=-Frn0+zk~eR~IoA!iy46e2-niY=esno`jJ)I;)6|3obf0{a=?xyQhb zysqVg!WVjt*=1cjeT*$qYMWOF=F+Pyj@pGOpAvM(ydWfp6|T7hA}@QxEx(Yfm-W}d zV+vP&&s%;Ir;C1qhEGV9_?R?UczSxeyT66@#pKY@fho~Kmgifde-ad+zQIQRO+IDI zefGhYRo|C=r?Rrc>tQ^a+!sX0p?~NYW_*RXrKNfCVzW}42eG)=?SJbLXj(B9v(^$m zM4(Ol30-wY_|ij6terJJ@73CGUJ?jx!0{FT2*dD@;FGD!s`DmKernc=VPN+AtXs_c zYI|huRycNxym@x(FB^#nb=iO(H;9Rk^3(TG0>cW1hWyXBV z@ErS9@{-hq#gaPgYhfim!FL_U&#Yi8y9puL)0X)zk6n+V8JgJlN_nDara3=!0o>1B zwx#c6xA)zZamBR%-I?~E9YlvWFt2CM`ooPuHnr{@RqKtsZ?}}aSmex`W9&G6uy1bf zeD-SF?K9?(woevb{O8cS?Bo@G-{j5@K1VZ?9-2bQr(5eaGuHkW*R$O>>$o+xo}P{Y zZl@Ev_b|+0IYoM93JYy~(%09cKUa62pplMLJG$wL409wK>0yU(UXHR3?nYO$9M&9# zd*%`|CRv+|PEDyaFD@-Cs6uEFY4t^I!&O7HpBFp}hp5B<`K(ZIdD2sDsr9<=;xzl*?&G?mzcRURDd z+3njAV-$jOSBwemm6g}D$FY0#oK;XrP*B1XTqXoOu_@5uRMGhp&Q|Y;=X#yY>`C4e zX6DcD)byvcnLi@0b zG!)~7O>Dx?yKnw-HqF8{vz=M-Lj=@qL3o6bTtP`mA%*!NNkjzs`GrZp{;=18z^|D@ zy59!v_%4Bz)lp;$T%tGLq$6;cqtcoKBG#HsL8F&E%66q*=sh4X=*{FtGDBHm1m9SF z<-CnYyFOzBUk&_~wOrGy!M6|4JWCA`0g(!<)gA8gOXPdB7+QP90)?E7V+2}x+6k}?JrF@wR5 zn}@PoZ$2A)$u5MX2(5j~EzprEF=yAVD@!Rm*)FfBz06^MkpH9pYGq&pJfY>G(Scz< z@g>w1TQw?XG_LKJuZD(faIowX5cbbf?(7~5?N``+J6S;o<$7_(MNnkn8^*H(Zq6?C5`Y{Mqy1k2P(xg8u;r2Ap zc;Xc5HZKFtPsIK%zX>&O5tj`GH5E^AF(`K94+=dCiuJkXysH_iDykX+%UD`s(!8`e zN+RgNneOcJ9#(gC`_F%qgj#l%2TeCRk7KQmIZI;ng&<0G2xG?fB5om@VKKvo=7LFSENm!++)ZfHgO%Bm55~nM#}y8>jp|sCcGoOd}dYJrx~02%Q9k9&Dk} zEu-_cR#hYGskQFMui2dvin}gaP2&oW+-i#kG2FLsuX>&eMU9TZFetI{ie8xX7aRsC z%dH&yN8!EAiw{4EHR-}dkUgKIzbBDk1DG$sp-mkdL44lmB}I^b$nfS|{Yq5|PabCs z=l;RMsIPu4nRldpDYg5iqC2v1Yg$R%eqbChtrXpMJ|nfL;BStvNi{&D z+G12seL6`&BdSPCo*?&n{n-D>Y2vgWjS{rEw`lIe!l6=S~?4u^p^hoX#ljF zk1BC=Z>rB{g>xoG<^h>!p#TIe#{kIUs0Iw&FA#xTl(DC5t=^{=6*HaswMZ$_^)|ZBB2HwijIcF1DAfBPG&q#0mT&Ij+Tv9n8qQO#2hq3aMG0;6WA*U zbT3=+s%jCewk{k!>&ZZ;HzgmK@@a7P@N4K6x8Yl)4ZL%%ClvR6SYPSK^7ZuvCal0G zkO%SrFlUtMu~EUK%8-U3^r56ij>*rVy(=rn^_`Bn;@&ss{aDXvMZ^RI=EUa!jkW*n zezW7BmfBWC{MuZCu|-3#w2sS5zRc$aWUxA3(JHgw(RidBh9Ap_{-hfZxmLpte#JaK zx#sG{b%_!1w?zkiKfT-g$G6EGS3mGJB%zptX!c)#L&wljtY=hEK1ikCFj3QLS5N1V4NJ!XuIX~N(J+VPB9EE77P0J1z|{gv8;Knp z*hq>PzSS z#p0~vUYF}344@Sux&t4lmjiERkcQ_%OL>oX$cl=JZ0bcoZEZ}!LKYm3d33e4#ozrf z&eVNB-hcZHKR$kFZJ_q{D)bU)`8+&5g>&#(@}(#uoN43_O3bc82#6DjI2wntPhVuN zb)|E%>HYRhSKZ&4Z@Giy!9$UJyGXCowbwRQ3z~xN?7`NFi-BPyW=V{)^-Gve5cPk= z0spFov0cK~ovG5~!EAWBkrSkmD^ljp^i&tIp2ch^fIr3+4>JwQZ4?)%m?v)d+>erW zHOWQe$$?#vEB&jk?^Ub@;F?Mqy!6lVr5sB7FNXhNq6`g1JPnD-ga%Z;J#*%%H4chU zZzSYz@@N8hg}LH^56h1mT1y_b72U`Dfv3&gSA&MRxw$cz?}q26dTRxq#}iq+zy}VD z5ib>!_RR=W9x%&&u}7N|9}!EZr)}uF3-8oycD=uG_+!J@_kA*^vJtKWIZJ$5Tn)`5 zCrpf&3X?YxAVX3ViywnYb488azEv;FH%YMH&`ySbCpl}=>+6Yb#6wrtkor+KmeC`~ z{~~@CFbVua>;CT};YU$Zlwi^M>K;Ty>P<7Fu_>*%hZZX@woa+~y0)eAd_TlnePXV+AI{ zr5UkNwPfF(qH6~bBo8ImpQfg!3N*|!%D$Pk;{#NR_IM9Fd5_og^_GT#$Hk3J(+H?b2h`a?W5(mmK^^-Fi7bV<`Cn2I@VHX&0e-ng9hfF-6nI$#DPIsv7gLB0 zis4oPywgyqbry#ry$HL3&MItkM8ok^q}l~ONE&fC5W^`fYNRbP3}(*_T(QG7N;5~) zfECmT>FeU&l-+OJ0<_#AR^|B{{O-u=-xs@U?&mEtYme`qlM@k2&=vBIFeO7sLg`NU z@S>|M!;fofsuKVV)$?fmtm{W}iy7QqlTVun<&^k>BgWh;9JOMhPp{E#f5vQU*S5GF z>`rTNXmpSZdvuBI`Q30pOOn4PbW*K}UVx9@6Q2ULGq}tn(!aG6U2W<3({f1^^?|gX|F5qx~8~EsH=yyyR zJnwsv;%YnrtQr84u1}y^@VxbbDpD`8?E^XpzVH+C0UKaCrB!kdeX>Qf?dNKM6D3A5 zOHiPbs}U;Mpg>Zcu4&jNT{C9B`2y7Q49%>H&UnP6*|9oX>p9ITwVcWuswlZ8P z2;w#Dl03wPOU_IE|(0F7@g~*Pl^;i8@yd!KD=qaFW-NR->UvE zhyC|eFNfx+{2;h6#7HI@?`gEe5c(cP+WDNuY(8rh{u|i|dHuPEus2^u>vmb<-$bPc zmyv8!SC-@8g|Ahnm~2V&uL|OmN6>?=%5cR|zR$xP?HYybZP^KY3>QPbb<5FreIt+7HPwZYQQ^eA z4Q_Sf#&HO`M z0tFG#cbHv%Gk5ADK6)+j|1X!>FtW)9YLLVeLWl;SqsAbW#|Y_$Pi`@nkB+;p&xsH3 zM&9pSlm7PT^|g;X0qcD;Xz8Qtb9FoWsQ*b@{cDFb!~(^bAX6@@cecqmlZyeMJz}4T zOxBH6V0>|fFWB-|RaaIma50O2y%MXWJv>S>7%=b?_SE_x7eLQR3|>QM*!~Yz{A{-Q zg?NBlO|v+~GtX+n(K+WdVNzA)4e;VKbV7ThSZ=r~MMNwYPKX4lzfJ)Qb2M}QM7AJX zuAPqPG|p*6py-om`N03aO0odxt_fv${YX4I8xpDQuO9a&DQmFlY38;QKx zNh2dc-bHdU3}`fSk`hkH6Ps`xAjc|ygmY%Is1*2_TXfWgZOhiDPZCWHZEnKhn!l}> zN&MP$7VZe~O%l013GawK7ro*ytV|6P>b%}e~>bux=zmvS0R)@A^bpaW&O;D2+% zhHVC57zW}t{W``x4CLOsg^-qKRFS8D3ZqJ#%4h~-Jj+wryv8sfcDT4Cn54s*# zh7Y?QACgPsu|j)+m{KQ!vE)eC3Bh5G)8TY==yxVBUw#vkGme2`U8q{Hd6kVCaeYNi z7$vLv69?~2FZtx1p0tLRtacUEmGU<_?rC+u+wC3jJ&wE7J~XZR5lFL)4t6!B^l_c- zV!AWE`(G7G-J6I3Rfc>4K*bOJ_7u*|7A-=Y_K$ zsWrq=brLD{zEf~m_CybmusjU7cDx64mrXqmP;8$j!j-#9F8qruBn;NL=$rb z>JS$ohjENxKuj+pykCjL)9M2cK#GX`XlSe~< zpa%$-V+xs1f9=ZYCrcV@j_R6!4s@6Z^XZLjT)j>p6?-;Bv4~Br_)_-tw3p5X9rAm} zt!>HSm|M_tbLHAPiLw8*9#Ekl9{~V{xc5c8vbx4Gg(4MbA6P2CVRYh=$N(M z*Oga(aw$WxnnHoed5{+qN)8?t`tW$+cW!a2Z2XAUi8CqTf4cq#lAroU0sY$*Hd_b; zz5uudBk0Mc;@Win{}E*M3Im~Hh00QnDnlF!Oe0=ja6^-@2l&9?I!qY7=}#&;0Pl|h zc}kBOlAlBv{-rkqM2bx?e=3DyE`bF_Etg@zmOz(@3hL!-*tMDYkL{ z2aI2VKhs{9sZYzC2I*g>}>N&yWZrR^=$}ViSFjxGiFaYV@ z#OKOx#hibv6Iv(#ETDr!SXx5gDTLwV1tBY$w7Zrjyr_5=;1sr))c!KM zWUf#Kgbod+uo)9{M67)DJ#4(IaYT%~`rqzzdF6USQV>3uNa}Z7saRQWF z^1Wsmh~j?Z?T}g;J}vAyWvB(I6cGVld{B%;5MBuCi!gMNqdu;Koz%%yoTrcua>jw5 zMR;M+lw#pWiTDFrzQI+BP@Tyj?7kkW#L#HdVN%ws)+ZhXQ6RVhbat1 z2Msa)?)XiM1Qe#aKKK=35-`Ti<%>OIj`uKJsf?Z$*Ebaj?mPP0cfr2oyv58Iom`Awcq_9+|bHXa){C4KS-}LuEBaCg( zO|Dh;v@-ka^Is+3Ml-W7ebB&!3Gdlz-x;Zf6!NIGBpmz=9$>)rk*r0flNsgVT9bCa zkgEtzm;bOaNVizHw7QDl#fE-tB9S0^HEQw1%;F;50%H#nW;Xx*BQp)J(Up*?69H~u zSw?%W&t2btSFY`Lsdt;tmuXR5ccR0@IU>3@W&9U{A&ML|L z_zH+IE-xRBr}aGy)zV*VDwqlDv@{MUP|bhmsz|Yh`_KiY_!yTCL%J`5K=ry~hmj!O z74zuH$L(R|sb|4d(O_;I9FR3$bQCBY1cZqz4+N~cj}(sTG1~dbY}6p=Ym8b1(0ao4 z=uy9idlV$R-b(^IdM*H{;1vECnJZK2M)& z7f!Ey&rKHkI1A?sk`}()I+|jZ$CPb?Kexlz!diNpbMt3C6SEJEPmgjfl?WE8E~gzl zqFiJnNi~Y#{`A>izUyUE91fCHRU4jc53K&(*-M~_j^Q4&%Xw?m^(kE)`~nn~sw$iN zH1^=k7je7jX<)bLA(p4~Dj9g;1NU9tWT$=k$bgT-9+-ZTB6%|$F0@YnS-bHsE>VL^ zvu@7^vmo)erkB5o4D2+lzN&zNR#5=K+RExGod{hbo$qDh=2Ub{Qgp=H&rgn>x@QyL zrI$tMQF^6$Mu&zpbKSqV$|iBuW2vb8f)u`rgMbr}RHh%xhA>qZM1J_Z7&;XjyI+(#9>C4g##&*UU195Qn5T@XOp@Y(!9(ye zjwX7$(1d^wu8ReK*S~-pA`_MWgpLBdMv8`WXZ1n1BZ=Nm`nN%&MZ1gI0}tQL4{}14 zDgp0aruI2hkc6pjY6egs0PHbF*-v56IV{SHaKZs>02Ju>j++$Jm!NG`52)a#w=1iv zbZlXbfUhyY&*N7L0HF&A2;j@pve%uB4KFc{_&HTYVw3Zg63hass<0_&+xQ0R*y!9= zI-|bO8rwq8B*+Z@Egg6=*swI5=0eDw@$_?m38<#afAcNCwob@wpn}1uOmzj6~j5UOQcaXgz)gNN>b8iF6_suy=>C?~s~4rS*G!m*a7|`#X1%LcZ?c zZ*OSm?IrE{_2=DqKK`on_q)=L?oJ+c9(sC)i3aaG4{VyzGT#?No-mZPx?%LV%uAUT zAJ6$*K)=$z1pNhmzGAQsoOab@m!s03!c+vVl*6>!xE>k*CSu$bvQq@7zsEu~;IKFe zX~7Z0L^UA09F!a|RDb?t-A3dID9HYP;bsVdFlb(cQRBXU8Hr-mWrYh+u$YH365Phe zCR*u2`mM55S@aAsj)f@jBt+iuD!k23T|3@3`;sID5a-L3G4;(rd~(fbo(fK<5j{*=X!{Aq$mq(xR#g^aPSP&-dSYv({9g1u*$ zOAh38Eff{;QL>T$p0de0sF__7Ut&WrlzLu?(VLxKwN?D#k=XP49SSAYLn@rZpmJOBOs3~a{Y)?L zd|9?Wz-V1c5eIMfsIE0MuNw=$=hV~Z?#o{qEC3hW;-V>2@_o@$jl1FL z!vKNoyWZx2weIWLz~9^Mh5&vYn9Dt$Zz>^tkjMS~9tQkt9kQRU!_Kx7^-(&F_Zm%_ z7DW+MvG5O}mFcb_s*FLeOJ1`|apC>I=Ba6|2^usC^e``+Fg#}5j2@{qqGJLx)0FI^ zi+Ev9j!pQIzuzS@HP{nbj7AnrlhFH(Zp2=VmJzm4oS=c;6Jd8b)^yg_cQt-<|J7jM z(&+%xkn1I9``J9bt@l<;O@~R2aLP^S>3ECW>tf<$z4siS1?+X3dkF5BV@BY7K5;p^ zo^V}{KW%W`!w&zo8Co7;iTb>!s1i5+XqsqgT6l0Qj) z-eL@vhPlskP~~#6jjx|LxI1O_jOy;l>G1=NF0i0sW=tSs@ zM16?-$3`s!XE1!BgL$E8u$0_|@kB`kLi;>#xbx_VAKdS09(mqi%kt`>{GW-u2vB;a z{mNN9cCYsi5TjzbmJEovMuC}mzwxqQX`@5VJ?+EoW9_2heKnvpIPg$4{*E_>3_`E& zIvxtVYCrTteirxJ5B-dFiqn2?XI~2M?+|AbiuhT`>RM9~5h1s<_y_UBcNVi~22m#C znqwv;>t3jAnoy48l$bPJ2Tjpkx5xg>)j%M+VR$i%I0P4(a{3dg8@2xg8PM8?~fwB6&)S z+m&{kaTS_6rC%s6==Ks|Y!NHWWhOmN{m)Uj{35Mh>(8|p|5*KNNd57%w=s0L(-0on z=}F&pP`8Ig&=##?G|v;P^$H*6J|UQQqcv zbrhg6UOH|4Hm_-d7^?be#`>uDXhmm){f4(ebwWSDKr4D6M-gc=3$c>G0-1i-k^kYv z3D-WnH!?pjPCtBU&4LXbEfbNXkBTKu%*+1t-v>!F8f9DNm}>6r=Lgu?RNYQ|FAvUd z^^4V~d3AOHXwc=%EP!Bss9$bx^-KnhmUHV6hg{}Akw9sH^J}s;Hj4TkhqvnjgeF^7 z1<{#5H`{pS?{z@&UvYEJ1{lfQxA(mTX(uO`PEYH;q0ah%&vA}(=6 zbu_l}45chwF=<2p#QgmdSit@|<$3)x|NhY!d=U1;0I)LtTYS4XIPNKv1Oe&TCNs`2 zECKAJ@%9|}e0~uJ=}ckq+Y89O$t)B5^Dy#=J_y7t=jlioI0Q13(eWK%h2Cs#8u5-r zOJ$O%JSl{FU6jd?3HrPsAYot3$=grF{%T#$vD0PDjjsKtiEq-?K55%dbLJd)OUQEu zZr>nc2iaqz$#Ahd$Dz)m|0}mc2ewMAL5vF1P4>VxIZg>b^B%z0Tmn)G0p6v!;WbZ$ zcg6C)|EX2(URUtGkS-WVU|bt&3k^adJur@b%fzu>ZN{*kqT^U);C0hx{$n7pcVK zvrhAjnsRFB>f)w?nMre?#)*P!gXnCElX<5Xyf)jcXNCuC8tkcY`rRZGIv6v)dbjZD z>Myn2o{YB7R-FTO$>j=$ReR?E+?S)8T>Y%80ROTL$mXj?xRLGChUceSHD`7{4q} zHA^w);vE?Wmf=T*yKf6<%3|gpoXdzgSsKY{fApOS#K6N94NYUX-|v34p_2S5n`G`? zI=g%BbHC!`Zm;p$G{yz~7KjJud4o}nceN$t4BgO83rK$|z-+^phdVlP(8w9MQQ_O{ zP@=8b?y((21n)n2S_CwC3N(=r@FW(Z)#;$ReCO|9Bc4pW521ke188BmZjE?v;ku4u z-X~WFOYOq59+K#ZI!LNv1hb?O=z}7IwxRGW*tignum;Q72pzM3bx;`C{(44KbSf4+ z6)>&H_0+a?w=TeVCR;3QS)v=sIIag!(|AwkE5A(a)YaMVW@%>F+h$S{ypwm%C_p1L zK9u_QvwhSHe-hz639nC<=j6hgESYzPK1aJ4t!7|zok~c^f?IfdtZj}{`|>NKH6aKI zK_}CstDGgTHVK|w*55yQ;e&lwAMiP!F2W)$+@f>qRcZKnEslyS!q?V*_qp}Pr^-`= zu7u35ugklz%9s-K_0~oOHGzonTc|5f&cxayOpW``4A_Kj4j3-?AaL zND+d3RQj5~Fi&_RdLN?x6tP$gd|$g?Eb&2XXg;D-Q>Wk;6AL%*6FnjMjZNJ$S;y&^*(Ny`2 z^G@oZIsWu6UTpaIa!dOyjZ~!bF@=b0BYZ*-d7ru|13vp6>v`@bBq}5%Br2+qv<{Ry z&5p}tgsCO=+CVbn!e%n_b7w(@xrlEvEPv=|Ksv$Y#RAeHoH1M1O_LOf6Kovg$m=vww=k8affH zJ3Fmc(Z`r$hxq;N7ut`X^ji!#|zQYZ0=^<>eWIBXv%W&jXwz1`HFHca0oTgTxotN;fHI z<2Oo+QcmCzPS#+XEDHdQz?7VKw+xk&cW7dMEmT>$!ULo?@$`~kyj>5^G_P=oz;;UTYmfiOBw7C z5EVgW16jq9XW(vX^`G|J?BzQ^vhKToTitol+yB8F5IZ36*G~Ojvf@k&RH(=ff5JdE zsQ_Umf8FqBjOHluvHX`mB#BVBl}pkp2GGd4f`XVO!M-bW&>SZjFHH$L`lmjW!LR5T z|EBVQ#@L`4j8E#bHOv>btLz=(G_@$cR_!_s=jJfP@aaCDN#DE?53t!yn%BYbv+m#-&gyDl2f z&)seJ{lpF%8;2o5QZ|?zp#>W|Df1iZgec6)%w8%in9_96Cm_0Y+iUnj^yNY4)#CCE zd{^A(^qhbB>hH0&vufUp=ZcoZsdOiZj-?E{o zOaa#hmoAb_fn;w^*OZF-5UW}BG}ugb#KJsWjZ&<%6qwK-l2>^Tc^ZxY!G>_f8xKB z)6Cgk+W9G})x`e!oNJRRprHA&?WUulk;Hf((9MifoN_6qFx~yI+s!xhr_=ZH?(Pc| zGqiVYINs-;kPY0~pc*B$BAD^SkZ=%>4i#XqGH`LRA4D+ZgXp0Ww#EpF#GcthyRNgo z&E|mn*~`oL<@@9QS%bjS8BYWaKeB#%D%ANK&rbE3p8iXO?a8>^uNOH#eq^!Ulwd5s zrju=W1tS4-xyr0cB!%y1S%ThMprfq(+;K(Yz>m>SA|LMt!Y*tBunxJ|dCuw~g(MzJY|1?q};&oRH8j?`X zBSZ*P6`&5aPfxD_^^~tL&6$w&duE*#r=Pya98W~x;nMQ`(lX$x6%Z7Zguo(Z{K^xd z&{#rKMujN~Rm{l0g~3vNB-ugO^-wT|RL|(o@Ps*BnFN-fg4iKkZrBHV9)=714;SOv zAC~VHbe}Ez-iLYy9QDR82b>^!_w2+(0nSXnNFIxjn1DF5etqj=l|6T|Hm&482iQiM z#Z3tp#Ef#xma9TBz>1w~OP`IF{xATFUKivkISsX;{GS%U-Ugx)=?qU-5T?MZ+DFVS zEZ~&TKr_rK^}eDHn_u_^_j*4)?kkQ@Plq}Umiuh;B$jNScz+jpwu}%W_q13~mp#jY zLd0$|UU*8a(;70-K59WoqRe`KX+RcA#QaXm>}_D~Kt8scP;W>S^kJ3rLF)DSzGI-U z0w8OuNU4KU!RGl^msX$o9)b6?GYBN4q6WcUc!W;~whIS8ap+`Ig7U39xxW&SpwN3^ zO@uZj6m!uObMD#iA2|45BXWS=fqC`ArFc+N_z*n#`ma<0HZ*F8}jGT|Wqepb!w-s@pF@XNzH_Gkx0?wBN7wRq?D^oqNa#&j z-6mP2q{?=DJjA|j7QY%CLt2_1i_qZ18Ua0M{0ou0oaO5r2=(kjNBV1E0}{pN{)NUSgx=7avpxVpT?dj^Iigm9Og;?_b8Vn*g8wIbOE=v+tEL&QgB%pzl`W`~ zSZGg6nTnkLV*T_hX&-osftdgTLJbR#%x;vzsgvT2zn+lXUFayX*QHDaeP6#?pXt8N zUIUC}!V6ZH!-q7A<@K&yf_Oqfc1RDh2T{6>dna(X8$Ox#r zet+tX^Oe)PqHtG-Z9kgwLGUVIk&cEa+*PpOiHH&s9To&S?2zRhIX~_h#^1SIJh~S7 zlZ%r{%1nT;#R#mkG&PDzQG;Oi24AUG*0;D6h>DJSdz0(f?A7K=Y!)wKXASTB#qav( z&G7aHbYXAX0SqS_H=+@TUOtB0DGhcx(S%2)9oFG$AZ+PYPE?eF0+XSRr(5M@$czMq z5rwfj)a7E3z7n$T)%bPG^$mdYH)J_H+thTvDO8X*?=iQF#s%dMdv6Pie9jB6#Rk!XdS`N12ayM1l2cCZ z`wIuL2q#`nd2_s>1zD?G8ZY{WKKfN8rtey_jOcAP>p_t3FfW=gZ2L|4{7So zagqv6BD;W(2TQzghf z>r8m5aMu3UN9r91*;TX8>kd<+B#Id&&#oXVFFKI=6&LDce z0ah<$FzUM6eu?|lJsv$^?dhdiDab(t&`e|GRC%7fdDAS1f_f?)?j`7=r7?ap^xxH9 zBV2GdG~NC`$M?U>NqoW^=6DmhPP4sy4}>dkd}4A~L9H|rvApcK*u;zj5fK+xns&3d z-#?!<%u@vLa^66jVl2{aoyErfVBu4bVnT*;utwi4AE-G(4 z5IP?0wiPk&&Cyk!lrdruK8=zIXSwY6Tn0?UlGD7qi@UnJ)N(3mJFxvlKztdg2s%61 z!3H6=$UOY^Dl3;e#I~}ELi@&0)-j$V7+3&^TP+r$TOVTsUY>ym zsV{-)7!azrc|m6Lwwgsf#f-jDvTz&%)N21|TOhge0=y#zlCL#1PDS1pd@vEqs&?7BM{oj#Qn%=X=-`Zn)ftj@)73V+);6Z;Ovqn63``d1}$R3UQ` z<8~tqE;L!ktB?#~EpCtkhwf$0VT}-z+|#0KY})F{*R}x4rsD{ zzaPqrn52M!l!SzINGlGMmKZQni6Jq%Qza)Q&47VQ$tYzo7zn78zy{JWMu*e@k*?q4 z`+k03|MZXX)P3LQI@h_*kqzD@j21)2Z~p-d2I`C!0u@;HWU;cKucJk=&rITz^rwQ4 zhX*4rT?hk&Wn)cPg%Revsk$;%JUHtHWU1zrk&yHe^ z%Q~ejUgmlGAel+s{3R{*U5Y1Cv}ZA!q5Fi$Q8RuSql~3gq6VdW1qznv*7qX~pEF|940+~qwSD5t zk9kf;M7%mx4<+aiZ;JHJr*@Sz{y2VpID3i?n_3Q44Ijat&tsRF7mry^@2F0%EzEQA z(BZP{J7{4OX@(t_fn>PtE}(hs*-K|Y9I?pBxpYY%G?T#Dq{5mob+~OYzg>#CemORP z60nQvk-YF{y*e@l?4ZfS${Q~M&A180K8X+@Bf%p2N8kd3<)e+pj$evm;cy4v zfFK{s(Z#Oq*@N{z+Y!LzfpV4(e}yloZR*WS@4sf%yxNkWXG_@1L1~BOwQ2(`KFtB? z1h_d0@N!e=zZEB;A*c?%auZ~>2HZujULUX|tW07L_K5C*qctOeTTOb)KuFHm1Wtto z5VrX+b^GXZsGNMG342-xL~VP*N!Z#C(s#5H44~gNCB1FqdY4FIoaw%mw1vPtucIVU z)W_N0OIEKsukP6Zn499|U$MXJx@l?(JaL1Sjt&}@2c$$a2r@hb$tg}4QP4~&_FeoUix4_O@yZ06L>edo)NEmz z;Y<+fLtZ9=|3avT2apR81!ko~ zd4qm#`29C7)YE{769Bfre~H|DhVM-+>d_nN#FyqSFzkq=)N3`c+dZBo^^#iO>;vua$1T8Lz&&RGn`T(enqml*?=YRSK`Qf(A z3a@xB9xfgpk-6NRyoc0`LWbO<6(T*=l|jlRS=pZV zFGQgIMzpS@^#ja<$-%0DkKgYZU8N#s=#j$@#F}@Bn&`5XNaa zJ|+#XjaJbB31cCNs=mQWSN<;O{|d0GnSYq+q2Mf}as>6)sByQu0#{#3YEoqtm&U$G za57;@Rfwr@F)B#abCbSRAfq-|UyV-Cj26ymO(&3=ECe2R>T{?n1e`3KoVbRmRIW9Y z_BdMucG$iKjPj162L?lM2n3j)k@0LHYNsr0ZT$>BZ`wQyAMBE+PARU*Nh|W!8yPj} z88`OGb0m#-ZSS}2`=??&t48|^1yV86gg9wM1qIqIJqnh=p~b+JKCt{MPPh zbVt|OS(v*dRJVGh%g2OS(BLYVv4P)Ybi^lHrzbE4=DGcUuhsiC*9D$;SI+P7jt|2NLXtoJy$4d-<0iypx zPJYb-xE4srqxq_Z{9q~#|A)!uumi|Qc7yclq(H*X_K2HG_2;h)-#o#Mu%@zBpmsV6 zQEpev4O$e3hpM{2J=-vM=WFf#LpUzT^!1YU?X+_kk3$W+N&kBD1Txw>y9F3ekNWu= zlwsis5~lmymqDP%I~D);a!XEXI)8q6ihr#os1D+K&GWkO)lWrP1O=#o0le;`keyZ= zeanpYCFRYF5>8QCFE5p~Hq2GKrR@efQx)ufP@H^$77;F9o*!QbQOU{8&%4dZ2_*Ev ztoh9abc{RHa*WJ&S+`qtK7$EBH!VDI!IVjh1NceCUjn-sP zX47vu-#@?nh1bcXPg{eUbOWAzMbqDGi3%6R*5PzCx_lSqHfqkytPcp~$THi@!!f%U>?vnme*S*`THtto zzxx4mFi`EVa--52j+aWWj|$9j<|TB|gw5f2v9FT}bEW zvE^rCL@bOEkp(UD6SJxmb?7YlTpd^Vy^}e#o>h5DU#nD8Xq&*sr zJdWG2QqMdWrnZJ310Ot`KFEAK<_z=j^O6+n8UGXF;K0|D3dk}Tf$m_l^7?KW`qthN zAcZ+^JQvT`Q4H)KDKfcB4YYSOO2b;R^)CfdeBUW3&@j+1o5U67`uUirvU6-y*^3jy z12)QRdSb8AD(3WB)q2k#?dAld^g4sx2O`tVTqw4X6pH37ejzGJQhmpVi-F^3ViVhk zgXEZS^66gOz`efIf6M6~YF!2&DPtzYV{tKYC_cpgG)YU(IuC4xD>lNa21gH!FfZ4C`C+6b$cU0Z<+4lH$*E8`a49X}y z7z8KFD)hRcGM}AYr^G0grN|gMns~Yj)CYr#Dk@a(tV_>a?I#KZd?TMI6H zOKb2TcV|wC&PU<)+BX(6sFfy$JaM$r)z#%AsUoj%a#VG?)YadAyx9^S;$_Wv>%CGy zO^d>+obO>kc#GTWHxE<|8jUkV6IWbNN?*=D4z9dRHx1vS*=#!Yv#rKqpk!`cgIjbJ z4~5mu*(fzA_~I|*z3lHb2))VJs%;F{l&l-3V1TCNlP^%{-%DDDK>UajwPt0Y!1ar&7k~bIABfHiWS00E9PhT z%2#BYyqgR==ZTDr&CuWVN^(d_|Lnp28V9)DE-ubk+Y zPhUn-jNdVi);u(?O4VTR)-*O)Jpv6NsZ!T{uoc^VqQjS|`VH!}O@N|7`wo>JG5H zrfT#Apmjf3KA~BebOyhmvmevs7xM2Wss?N}Jx=2AkJFRSS=JPqtAIZNGGe7=zz-0D zC{r~`j;Nbb41ttY_3Dq!^Eq$(KAE1F(kn4~)_j~E>|&84uygn&SGcHJdY5Y^cSHfZ z2()tkg9kgU)y2ZxO&94v;H~jkY+U9=$;%XymoM;82({6Mh7{d7^fHbD-Mm5(EY>SO zYEDO?R>Vk$ctRQ*|8n8GTmQ=b_0m5}R{`Ns9Y@%~D?NOVZ~@?uydVC1?-Ja?1j9?v z%_fvJROX22M}2aeXl*U%f94>IJXt{buT`%uqp)b1lznT~A%p~io{qv@T_*eKM~`;Ot+9=J&q!5YATwYt!R4;!9>wKN72;el_dd;OlapCFRyVusEn(7jK?@=e4@Jr|p z8vB;j@>eMJ*aI?X=dle`!m?H=Gr3th2c;VL=b1Q5$eKlqQM!XX>Qi0peKBqDkGSs& zVlzF}R3?MlP^(eR6dgwf^S?+1~wpm~Xijip2&k=(JGVAt+$`4UY&%@1i8 z`g()hN&Wp2QsO(VDq?SX0YPSMP90e~!&D9{*rn_&*5LKBA(g2hqaSPQl9$+*l&EKz zx}YwL(i>Frtn}>-+@yHbR>v|u|obIH~cOBq^Hz|}9C7+F( zyY1+09=HOkS*q3Y-4}QDAJD(UmMYT&mb8y4G(^@K+*X}@^H{X5r&khg`d(U#MAnIX z2W26zfyRSCPtpQ|`o)#pZ_Wj<2Q;f>hLh*|0V^_a)Z>V#LQnabI^yh zy9Ffcb#mdkV*7lwER{L$X|?y|-ny9_ODjrD7Q50Kw*&q4?g99rxsM(|Ja>Qi7^2>$ z8hT@|*Cqp*E{?gt69gzwk6MRw#HK?3oO9g1op4-m9koXlk^H;)$p9KHNo3K*R;2Jc z5t(Am9UDoa7ty>BEesch5R8iALY(dR9Ukt$C>}3K`Fp=Zer^U8ewg0ejRv#Y<4U)A zZzI4eYi(1AzruZUs5LSVJCwCZX; zg**N|wb57@&+KEpT1p*^2Q^+4(ic)aNklT z*9-7~8Lc_fgrx=tZ!u}>hP0n#WlsC<67oaOjQBfwU&aEkvvzc<#SeZweUbwhpH+pQ z_MNTwS%>aIMn@t}Y-;k>G9C(Oai@02<@w&AL%CB4-*F7hD=dT%&7QKXj)J&o%@cs+ zsF|6ru$IB`Ny|&yB)!j{8#;O!p5`SGS|fc>pEQ=g<*3Q?6>QpO0aftp{yfCVqYWa*sWwwIJwRpm_Tw6L%Myx;Ka;b%5yqgWJqoqSH- zKVMwm6=pVZnSY_Z^Jix3p5k7Z&p-HjkS>gz0^7ROxDu>CrA}kmAb2_(u)q9#6KDy z)rp}Au579|_R}tT*jpN(beEzosTTq%O7rUFjzpuuyhYMTooN55$Ft9aw=E%KFvx1p z*&ArDtQ1T^RW(T>n%24{Y(r1PH{SDn=9^gfX^#7O$bozK0m?aOf9ZHgPjKiGjjT;e zs9fda9JU-mIl&^?qNa$}ogM!S-|%q2Yc^zmGyJTQ!+m7;V7Sb*esYkq$QHE@?cjWlR7??%< z?W|>Pyk;^Fi$VCAT_j^%IZJz{ILpEqM66rJoORYi88D3!-cDm4a{fF^uF~l505jjU zUD}u$2!Y^G9sM6Go$0!CgZp*XXdf3`w{3XAw*2X{Ot$o(`}yx>C*t}B=f_oY@7cGA zO9lP0_dV=kCNlJR<_j+sFCtlhfoTZh(#}|S5$y$e0Zh5GhL!uaTKar;KZExu&2jW` zpU~n0ee%`WLzDTUZ%5fxi*6B}um~381Me>pwV{)l}33d}x8%|8|1xWD{Cw_GeA1 znQ4Fl1xQi?^fhRP_BBk-7cy$8L4Va?oEYF>UK9mw*G~1!H_{GQA1^5&UWp8Gx?mkd z(=#Z4xb^&x@QD`cJ{Xu{iGwMm6Z-GBc^u3HI65u^b;~)xiCPT?D8UdMS@(5}Tprq5 zb#5Q5&&?fkT5HG0#5~R+HbPuERZr&@`t2@5QfpJb(o3u{fZhT`0Qtocs){yK7m@I! zt8qi>N%YORq9z7!qRc*bE$>i!cO^24R*Rp!zhZW6oYPQ*I{LOfudCcHN(y z4eMk!4? zUM?64jFmoU)GjfXAFpszwAq6@Yf))^y#oUs))DRnRI z$8BhZ`9g0xABRl((%YbZV}%ZS1?>36ie5Cwx1YAv;gs{WBVru&2aAzUj=PQSQuJfl=OZVpg zfWAS__VzRU@)9&7irQ{DKHETrT~OWo(r_&6xQ)#dTQaf^XBXex!Gu`hv~l4QQgU8Q zvv=vIQTjd6EX5?hn~OOt_wl-S$ehcQxieleggw%)W4`Xjg8q*-=A&Yt?tE~u-49_U z2i-Fxb?J~U248N&m*WWX%adrKoWABOwaB(EO)E^GthRHPRc8)c)pRpyl0;NiI@u}X z3_Gt1|FLR8WMg)3K94zHR^4#hJfQ)6q00UCmUhL$_I9VwNz+~HrEIATiu|8QNz;%0 z7r*$7_T?WmhgWwZrhpm7S^1&ZtXzcIUD|)-JRSXo3h-KbsJO<_n)4f`GxvJka@d}P z6r>*5&PU!Lf6vmg%8qSV^ey5xujp%oxwe%%7Z-L__-d2=_KIZ)aAKa7&isp=?H#f3 z0ROYqMqu`f<~-={zu)3T_VA#+^~1R3J_y9V-aQ|)e{6T>_QkKLSAQ>~Cry6zx{|AG zmX!_D*!JW`m6L0I*f(|p6@7Ss2*=d&9hK52gSou0ZIUL*w z5OVUgl{#66?`JBZ*5Po>>gHLGYF+Be+1c6D6h|rC)%8or;qUGF&eH-(%4eYZo~Hs- zpm$|X!^kWosjW+QxFIhF_fsG)utrYq9o)@a-0B{E-$)aobB<>G8+ldf&GQ${I`~$O zIpNK$dPS#!TuX~u*NKKkaVaF0P^b%4juf)7)ajj44)sYR`kay154OIgb|%r#(4g*i zJXzwSEoi^=?`AXd7QJNe5I8vuyPT&!$%hPBaqA1cGBr6<`C$q!(CH4=ULMn!d_~*MJd?Jo$!TK8U$Nj|y6MDAGO$9> z6teqgWstcq-;}<$4>+Hb57QTYehE;$Y@}{t04Bm2K2UqVtF*db-w4y!>~fGu*&8H8 zyJwQc>&8Tt_WN;Di1x%-^_p@|+ulzuAF8g|G?yWDth`sM#Ek@eO+Dj8iV@PLJR`Eq zRW_!2`kbiMnozH!UzsfjM_u!sia8bzvBYx9shbG8Sc;iMHPqj8hlYcE(PjK$#3P98 zSFR5ODdJl(qSv`PssHDvJ2)hhH^^Z2xXK-*5*85_ovfLOkqkRJR$Z+W>@d z4fKgB*(__EfY5$kPXrgd*-c5vCM~nZGuN%Yb3omU!^AAV-W`~2<4lQX-XvHp!{{5w zpUqjU6&E9=8y$G=$N?$o!;?W<3Xul1mm!cS`y+3pvc)xB2-*_G> zko{cWOy<~b%RQBy_g}2Z{+9C^ZZ7Q?G8?V$Kv@)XeBF1PW4JF zVCGes7Dt#YFLYeN(hJUKI$#0cDibD-D23&69wOVF;!2kQ@mDOMXS!z{j{vOs>!b6E zfGFZA1kruhRv;zi5-BSd0bd!K9e5rRhX_0jK}6kHB3CFH2(tO_AZq{U+57r?)sCA4 zqPwg}=~e_3Dz}jMCt?hbgkm~bY~xeAz~ICiH`<+6@U^pzi&U@G#6esP7eSK-Fn;!| z2=rnu1XWMm2;?rYUZLlx%xL6iQfvyJ+8U^lZ^>}OV%;l!v#4nBmn;(gj9MO+4?qpD zsI}%?+T_LtDa?I_%Z`JEfhALc2U}T9inJ#D{m=O&K;?Ayz;l6KkooX*f~p$5#}MVn znUTUrLgg}hukW%=gq{=xO^4JyFQLp#q?QtpGBsT@ok-WWH679Iee#AbSnu-^l+O_$q&{`2YMNUuJ%**+k*4N&EEp z0hZ=XJExUEaS@8%v{k~u=~tF8L*FPutV-gJ%yLw&?wq|dldbV^Vc_|*^FLklEOuI2 z;C0f3yq%Zp$~Dm11pwO3Xz`0Sn%4(YtKrca^i<<%J(e*z{gbym+mAEfn*K9)C|p&e zk@m)KJns?WqwDM}2Cmp`;%Bchu&QF-dt!LB9`d6)sy=g+%H^ z%i03l!FW$edes82p5>VxHmyfFhW17h$2vQEvts^zqr=VaN4dHm z9&k~;R74@>Syk&6TR;-b44s^v8`hmRLh@CAZqnZJ=91*;T7oqBN)U93Xvo8{C-})C z=}EsFo44LhjSe4vsI7y^Bfg80>CLbCglD4_J=3mk-p=V(iEAev%t945^WG3vF{i!V zX(%rfjE-{=?|Sj8v0Sf_TviB#;JUCb(a|G+Q*VJI7x58J+^9(48a_N+$ZR&*sOOIcVy zzPMZz?AE4+4{?Zyr%zl~Tk9sz?w|4>ygXgi8o)04_qK}lU%%OGD9gV*@L-lCBFked z<>}?cjiD!?j`Ril6|_F32{02@3I>6m!_JDm(!^7_r9;QaaA(SwwXYahL6eG@^}G1@ z>p-$aevf=+;_K%{@5T0e+b3PH#cUnFa0#eow-at$;C4pY5yJ6Lw|N6@oUtsTksxXc zfyjo39sXVfxc~Nc_4v=O6PG}rDuL7R<#86`_)CvSk^gI`p%yyRpq{4QVRMn@a@(o0 z7}Z?ZZR_)XoFa7ZfhoTor%35qOU8A6ZQAt2Sxam=o5sR7&!2~8Iz=&NX(tPRW&vyB zGIWZ@1Qs$Z^dbHN=tmm}~;laYSxWx4Lp%*|S%xB!!K;)av*ItP( z%yksoYssf;GG-<)gg&}ZLB1B|&UN5#`IYvTM&ddM8$2pzSdTDLjK;tv|KU5;ex{@G-twsNKt7d-&*PEI-4eH`>Ga-iXsP?XQX`%p zFud>ixn<7Td6Qh2w2L2-quE(cK}#m18_dfuU`mE)J>w;00;O4#w|o@fURNO33~wC* zT-RE$lkG>%F%nQc7w<7N=WP<#ICnxlPr~CncZ^QiN$L4E{*P59fDiSmGQH(q@H|^y z^|T^sz3Q;tufXW=MCgH#)i-mhr)fpLB7FM6oCS}l;Y6>uPfcGn5ds|@*ABit|Hu>P zK?{>DmMp;0`~iVnE-&8)neBi=WK^%wa?m={IjQpnkTaySl)q$|gtwK{&2$ea2p=c?T0hK~b;(SX#>Z#% z!1&OsL-_LmtcIia*$B;+5|GYn0vMr@cHFXij_d44WQ}E zMIYSURIN8Jfxa$-&Y7q{`@Bqj4#413HKi_u1O>l%A3Aq&t*z!${*EnI^RC&Kr`*l# zD9_sT@7gpHm@+i9_#0@cx=lRCq@W*I`G96X7E*_cijIu3{0}a{q8Vbnd(l%g$z}@1 z2S=_A(wkx3l(?Tu&&dk8qK`uhVv*>*d=@ovOs+Teb9eVmK#3FJf+4m=MiXrc)UN%z z!q);;rGzYuJ!HGB!aeJqK3FOE*gB!l>djU#dA}e%=aqW7zozafdeYMQdJDuN5!x%J zF&1l@*We@kE*~`%gO34QPKW#(a!d@c8(x>YfOo@ogm52UmW|mgIcmr%iJL!xvU75h zEhqW3?Rac$yR!uboz{eWeKPs^V94p+gpYXfVuw3@@mYv2M8jGa;`H~y4i`~@PJK2f zEGHg;N{H=>?b7VNCIcDPDQ;UL_4>ekX$V%(BEC5n)hhgFy^)bu)IR{ z$96YnXSRN=V3y~%m)aZSfba8B;MjWRrA>hl<%=^)@zYoHXX?2bE`B}Ao2N1ec#w-g zR41q8C;}PV@_qlbzSP$W|D%98+qZYawJd`)rSkHteA|Z7b9@GOK!%d2VaHV7wzwn64^rO zEKok4Jj5+6Ab8H5tfH;DO(v69R#pO($T{fkD-UO4FuSC*b^(>_Y ziWZ~;MyGONDWhw6*fR5)k&&03mtFR~32njK92|gUu?b{Y`npu6j9)+(2)J7X0EY?Z zO?OvD+A;5^AbN(Z-|quwWSBrAj%b-G=*})zHRU*-mWT}fr?H%&Z%I3?K_*$T5#x_A z>ptrP8nFTb0)T_|B17YI#F>tA0{j|s_@2!-C)A7mseIEux;#VkWzoh_R`InM^FKFmipV&c{3x;Y#eVqAX!rsZj;*F zdych*I8TVAoj<=H58u73>$dTOPF@4s0ZJ%6yLcdFLsePXcc~f!_=e$?SQ93&R--#z z4S9~@Nleqs3$HBXY2N7pm@>Q0ij6^`Q+8tkw;nmV0w=!RdcLey& z{?-<03={PBC1;Qm_sbzF;_oekFC-}eoBcUp{%+jEllt6 zuh~}K?|R0g4uOCNqyrh3ftP>3Xzv@%Iv?A>bCvSTDqBjjD>HSR$#mYQetN|;u3J7 z0N~+IWxc}>0>K2FhY%Fc60GzNHc}nNb3f$kSXMG7&t9u;zkf`pZhKUAjL_aHIy2}U z5J#p4uCS0VY^T3+nb;hc$o-z-Jq0MTelK(ZPOn;}XrV7EAW(D*5RNxuRM(dHLo>HM zHr+D8a!lSw?$>H#a~8A;*)DrRzj^zSXW+#asEEmabvqRu(uUNW7+pFFOJE>3+aFO% zl{KJ&*cau1Ew0F)(i<zZs zuuZRxtWq|aVZ#JNKB+t;NU%S6_#Lc=ncKAV^&5LWN#a%v3`*BUo?Tvfch10B<+N3LgzdX3kY}su((Kh_rbvN%+#O< zm;P=F+V{y+GWb1YPSLE}b&^QC5FH}z`&xRtGX}p3?p5mPKmCmpMr3s}vuXf23{lH8 zg0Fo7CvpktDbA~zBc$ohNk(wSO@g8(&pEQEjfQSXY8X8WONfPNgcfDdxA(3Xcq#9hu?kfnc*Ym&QB_o<>vRwOf?RTPR&6(LWWgt`lpkjo0qOK7#!BnekY#+ses!r>@3eXXz8T6 zDE|FZp|e&Il$qbI!g{^Nm!8hOs4MDR_fk!IZQ_IVrNb6Z--PB;*-cPIymeBsmbyN$ zb<%{O#WbeNw@xVEmbtUGT%CTQzA?G6bkB3L5eg(o1AvH~ogD!FbOu^o+7|7roizWU zm*~%CS&qXd^p_)^2Jc3)%sZrTT$8l8>4z}c)5C{qWk#%=HZio`4B%19`U)#ta)u!% z8{Mw-Wv(4kS&Yc1<^a3t4Tw_Mfrr1psjWDsd}8B80{Gg$zrFu(H2;=P$v%TE3*&@+Pxq&0Rv(DfJ zH$y6>Og}m=BPl7S%Etvy+kx%O&CM<24xq2K)oK1DN(-7%X$=8RYq4n5w>Uy0m{ILl zXQfr5_VLH`7r+@Zm&j4ZvGqyMwGuXtpG+r|60_#LS`!VqMf1(xv<-ip8k?FR63aAX z=#o9C-%IPIb=ZPHcb^KJ={y$|OYAFAa$5_^g~)XLV$Z=UtL87{+Oc%9V6MM*8hsLi zi}7x`QZX5U-s`J#^&cgb3yTkWRMnq>(gQZgDi&h`JQ%8&#T`TscAzy0?bKUQgkOT8 z<#U{A`?1LD23SK?n54gHT|;HbV5vlcMgd?JFj9~(eX=CyFcOJYV4!o9`z<^;4O*ti zRh^XzM4d!>rzHa$*ePM3SDePBgNFyqlj2R5Tfd8}|5AZQ=g*H!zsFrK(ZrMB`EFt@ zk+Cbg!NvGpJs$!+8lBN|<2LEfWhnvQx*q*~^2XsI5Ha9OJ-FiI=)XT6x6H=IX0=_f zQ~dQr2K3V5ry>PtjXmmkz#V}L-630I+*j^C1!#0lXl^^-(^z)ldljJ87P}X;d}nr^4nF1wKVaUc)1HM19dsGm^CoQ zj;uZwdu4wO-*8U-jD$X{Hr+FR-SkoM(W4&86YggNnzQh>aZj-Ty7RFGT)L zz*wM?%j!Mmo~9_;*xzU!CD*T61Qyx8R_V!`2u;GhM#a7k-9P?3c;Iee8HRxQoVYZ|puZ)?OkUyaZ!EFmjwMoAschXETh#>#U8!?TSIV?S{y;5xiC=#+ z=)He9yWLcyleJi#iYdeSdB{TF}fJvT$f`VcvwfG$a zmj8a9gMS{n34R94fk)u2O2l?6ZWLv++2yX4vm|voP@CsJcDy54D0X?jAnsT;)(c0| zHY!4St2gtm%xtdIVS3o*HEgx8@M`Q2RL%Kh3c{${)0m+jz^H&2Sk50?qKkffXLoVe z>Crj+zXkkcqmE^eK!c7ZMkCfO?-t!>4;yX{H=@Ck?6n9l+;laaRer=VaclU&=1(ubQBl4qaH?@pD zHC~mtDy2Q1l!zzchm;jF+r7~lDWzBfn8?dBmm%%c%Oj#USZpxN(*A=uDef)9(UhZ8 zw+|?{!>Swoe@ep#rP{%%8lhL?U zM1s8J_?+I&MddrIe&Z~8b5$FG;+{ORUP#iTOex%&^DjU0T>=eW$E~-mO^-K@ZN;g@ z6lHE=e!fLKLTyYNG#{Oma*6>v zZj??Ez>~VHX<3N(jmj^fZ(}N!8ba5PsHUIulRMcm_q!p|U)IJQr0&e2(Q4F1yRVTr z;k!2D$E{841LaFN?PhtGZYajZucs)9r$~0$GGnbM4Nx};Uz7-tW?j?~l!=LH?8{eG zRZ`Ls!~sEEi-IAOdqW`5{*~2#K%bVvkM?nXo^c7!$E=2RzSLiun!9m3Zr|jCH^7u7 zWqRiwTQ-zGa>;M$X+z`^$#7ztpjS~2F8tWT&kP`SK$_r(#yk!U>;$HB-4Y`R30PhL z+Un}kgg~q)9m%VMAkbE`4HH0zeZn@h!!bUJnJ&jWGnO^GWhN$!RCe*qt!^z1m9CFX zd0e59qoJ1#ch)OOc9`|-dwnKDP(y+sAA|tZ3f&*?UtTB_Rnmp~#T87L_3|5KdW3i# zt&d|GDg{yz=xEyR%(JikKY;sU4-x=9Bb@&cL)ORr=xN}OrpTTe)lfRH+$3)~Gm7T3 z*)bwWXLvFndmpSmeZ{>f*i73Wyb80BmM_XpbrzjRplZ_Is28GzE*sDJu4I2iqm>E) zxDNyY06}ESxjDsxx?FeZFM>h>uK)8FL@6mCm>~Ywf3PT?$ zd}Z+_0!}PW>((6>p%lD0`U5rj1Ang!U6gB>>Xl=dW7IuiE<0S9F^0!f2U_(67~_Id zWpX4iw`6p^QbqX*fSRHxoKri>dx0F(RZHjG=5D6xUyl*GZ zuB}~Z{WU4D6gCGgWnf5--SW7qH1JU1^U@?tSH2|IqP8&Gn5_pvIFbqHj;yv#ip7^( zzR2z%?E|hEiHUxGd)dX1;rgh`hBwXMySLb~^XKD*fg3vDBH;iQk7JxG1{>49=wsOdy{6scu)YPPerY)=pwd_? z8dHscaX3FIzkB%wXn8(uxL(DQYzco!hoK4FyEg-Kzn0L32eN8qHSBs6ka_@(I@tdL z=;|9OD1;sCjr4mfz4V~E+c@PT~zk#sN>miwZ&sPZQ6V`hKFI$$UI%-54R=xQilzuVLps& z9$`p_fVm$-+r9OMo=hAOWb7Uf8Ah<*qX&UFul{}Es!W5f6qBwG zw$g`)?&fl;vH=WxRrNB*!El+hjJy@zTWktQsS^kN+Q@>R}l?dD)JA9bUMbu}H#1EU_5%!da$P zz7Fl2r<*=xs3mDOJgVQ9rBed19KdWE&{sJ<4V7}4XnO+C)PJe!(Yv>dMHO!~*lx~L z*cb^|KWWW;4+XzAK7G@G)dhxXRYFw?{nl28L|n!{i58`0%gVreD~e5IaL`-kIvIA) z`kcF@8lQZL-_+`SOamm=ey*!?TwPVE6P5us2>^#%!k%Vt92KL#p(Y`a?wHCEL>1QX zz&2*vkUNq^E6NNg(5)TaMpEjZ=zYstnX^m|ihm2Tz7T zETCN_#e8=ajb?!JTc9sbCFI~K`aYZuCdxK3t9awzCngTW)umlUPozf>p!TAancH;Q zkHp2|ImvZyOv$wNCfsg0#Rj|06s=UPqdKH7t}imB7t@H7HM&HdlEJi`TugR08uytY zIgTOuvkR@)6)>Q~LPKO&-Ca*kmQ_{d7z$6NCAJKQig7x-vz zE4(|~ZY2vFO^fm@VjCkBS@KIRJ+KF>+2buIqEHc69c%eZOr*R&@|ww+ni1lk99gY- z1nN-*YFeGo_7 z!U^ND6})M=mnx@p?75BUSD%`~^_Z7av2X$&nOoC^L=F%Ch}UUQ_jS%7r7UVHqV#g& zfL8$@l-2Ep-^?OSb_?JrZIfvqeO$$M;Rw9B)t}n{*23m=Y4rV@js<((wzeXyj*m;@ zFlkr5F`tcHpZ#3_@L)UWxPBhdgrazc!ihh&_2bbl_1r9x^SQ{Lbun2=QIR3IcU%`z zTi$hthlfw7g2_H(5`_e-QHyZbXcEhzq#p$2Sl49N@x8U!hNWl2t`p{Y#gm0f1b9wu z*F?4hrkvM7Ul9hA_+a>BFV2afh-Wqz6S+F`>)XowV}RM~sySbT>3|o&ZHW}^z*;^$ z{(k%KayH>YtCg!!w++U{HLwP6oECSJ0^cGLSy`m+AJiDPx&%q$7%H;RQWMNgc{y1< z-bn$DDRuC^!|&f8l?T?jAxL@X^2k$LK>3L_%raDQXiiZ|*tr!|zy1~3;oi+!i z>SQSfT*D&2)K35QcBbn2IDiTtQFnc^k^+6b2lSO+?(%}avm-7TDZd%qLB!SQCy9oFMJR}{7>^}MuR;5^m4w7{8>ZM6cv<}%_1VCe%!Rg*fd8Lc_ zSnUlypeLLZ{g=eq5fpukae6i}!IIyiqOI%N8hM{OIfqRVlWJltc@GB@;QuXY{#rdt zGqx)sH;eBn*PX6xqcTCh9*4Ald=(euKP#3JsCXRz9^8J}*|K%IQphE27s1#F`Dk6I zO%JVs=LM5>tO}x&izc& z^rx5nCcLP3V^JbtLAyRJDqol+A3YDu4rVL2=r!JzrG0;?u$1U>XOZiUoSoR<-5UHu zKO+H|9(l(e!J=X(e!z08Bu!Mb8au*2EMon7{e)|wl5YIRk7BrrlEUF?S=Ha+ejr0; zrzOq(4>N*z-%IQiuWdkc;z^K+9O2P~- z<^>uyXZX%XkrHAj1JA$BGK&FucZasY{sPOnBsFU9xZ-vMOn3tXnko4EG!)KBo7u7U zcG5S#Cls%L&&kO!zoG#~-lfMqe$MZ|`EPB4ZJUU##BF4S|dfL*lqH2fm`Vxdrlf4L6uGKpV)&3Cazw zs1NFR0d_E{h69stN^@|xq%P6HdeP)O!__@UerF@wB_NFSQl~)p{{DG?R(INEI>CDk z+RS5!>7_MJ)yE#3&6{gS2dZ_;!GoQLMz_PuKVN+5YXX7f5HKc?S{zQEV;G-1QCeEx zct6l2J9&$ofO3;Xa$NAe&>~Vs(9eu(+(Zl(!_NT(D$vVG`@~0WJj> z&4y(Y(`truAx6KjZZLmSNIvRxtwBXqRp7(+k_H6A3mDS^!KsJ$(s#q8TO6c1XaVtt z0wAz3)9)4G#=>2eEQVhMD*}-nO+mY>>l=+|G#=wpi8i1%xF7U`J<{7l_Wg`&ck)Gt zE9|jW@oDif?ub}3kuo%zZ@3WdY?SIv#10PW<-jJ2OC1S$ngpu^=nu^cbm>sI&a23r zAvaez79Ms=UVrAlxn^_v8;D+=k{`>jNsyx3n*;r;k3M(-MZ`kYOl~FvN2Y0&_34U! z_{7wdtd!|anqB!LYSHA^^`9it6+GWPMYngDXgavg8KT=4D;gUphjR_9bG?yjlX~7c z0FZ#YmB`mQ$XG-F5l|x=2MK_+S{{ubk7IHq;BfbrgVi3JvsKgJ;7h7sLK$p%jidf+ z4XWg6=XhBqWi@H)GLEa>zpoOuRib)oK$l zPNz@j%50v#HFdYvrtaOj$VYj-;XiyMXUp6BkjG-MCc__#O-xL@L9^dC)$A)Hb%jGM z)&Lzn#^-T6y$gkif0Bigr-lAM&fYRAt|e#}#w`Tb;O_1cAcWxV?h*(=gUb+ty9T!q z+}$k<7Bs<~pn<_1hJkN$&Uydc^}Xxf{W<=62DW5f>= z3hr5U>^8I7yG?C|q-Q{vC}R}G6!byM@8yb4sc^+Ye#!KXBJ06H4Ti|%M173G?TKR>Xk2}N zL#R3ca}EO-J=LUbrep;9H2L^+baIX~_Q31`)SfrlI^Sf_}bI{@smfRIH zA?<;;r+*}Y#>(xsTlGBdw0v|wW!wJLJIhAa_Tx(1@Eb{LER2ouCzTi1hoa(U7%22N zOj=;!(I;?c0li4|T!Dy+_H4;V-YVHyps30^Ed0q81d`OH<5ltD%}_2cr~K$>ts>tB z2bYHex`8c=!H~G0&Zo&y$?eF)#k|C0!3w1n4VekJiLLmHRF6AePgi+Q`|FQa*g7cy zWt{X@$3)tu0ml3HpqYYy!P}>~Aq?5gOQ6B&6HhXZSaQb@Nk#c4we_*`=XdlN^CDRt zSsmqZErLA{i+X0j`INb1EL;&+mdm9L1GGR+^VRqZ6OgI*18@j~I}fn=>1U36TW#3l ze)kVRab!uLlJ*C;8%G0#`9cR?6{i*C70z3{@#{K>+T5ygq@dz6z&O#FrlE2F^hnF~BS+3tIR)@?9IZanGL-zXR$^R;2(VCa# z2GHRiI!Xc8*DEtXObzsSkq5fE$fI~I9_eATn)LeL-QD_8+S=NE6;%~X58M@q@Kj#| zb#^ZroDW0?Nr19ymX+^}`7REtvT(9&nFQVT*D+8nG4Rs6oCO3A6i02p@>e*Z6;yvH z`<7wCKaEoX>&kgPe5BWNcXizN2+&K5iv|L(Qn6y&2;E|6|C8&gjnF}KCdEuIStGSP zi5%sLw`eD84+(B@JiKBZ$qB+r);H=vt0Eg)TAG73Ues?>0^~2W=7ruI+a8wz)IhAD zV2r}}l7f;9?O9sS1F&3FQXO{-D<7cUbq zFyF_IV!67#&wvV1X=V?OR#tr4gk{_f?K_9Gnqekz|3diqqO4u9zsfj~DttT*KUpN@w3DEu^d!fn7OW5+Yj7HQ2QjTLH9r91|j7609d zu2EG}i`+h1_L^>9TwkXe9jutIS#AcH5o%J*05*HFbwRiwwHFNwb4a#zf3Cu|+J@y( zG8Q7*G1@@mRfz7iR?HXhM3& zSQrGBf#}xR=D@reD8T=IYHVVHQ?`zC^kjkwpLS_wg&@&>nf)4nnVM<~iUtYD<{8C| ze{u%`=7Dy+XXRG>*_2W4sDZm@{;t_If$;m&r>Pf%8;}V`gy>cn)f4my$fyP~u5W4f zjORUcbXbc1soY7GGHNd;lm2!((>;P`&ckG0fNw8*IUCSyRIdZh&vyV?l@3=y1YZNK z?>tqG7qjoi;YIuMefQQw{9fo@Xr+I2Lgd-2ce3D%uK5h_^q8ughn;2Tz?=2Qo%P4d z@CGkpFwu96#L-IhVkyUBYar1x;~^C#IVGi&qw{k$?yWO#E33EC z%w!T;^FaWo=8w?r?8i%ozttJC7drGrDnWVqoT{+76VTS3UX&eSZRgxmUVgTF{O9bK z(7HeLVAd;HA=!;Ac`U)m&nuhGR+suThv|EBgNBj&Q zONdo|3$~Q!7HSv9`nq=tyo$9fEq5TWqW_knnQW-zaZ_II-JFPu%P@_XXq9ayz;xS9 zhfgQA>GS6dL>Z6zoG~pUBg?zCqFk1vOlB94SMlq;_>$Xo!@<~MD0mSO6%T_vJ;Ov( zQDwTcoNs^xXe@6Plf2)Ena|x|?O;1*tdrWYDGV@UxzAkc$JEu0YW@?>GMpD4eiF;y z6^;k-6tbBc4UA?F+p32+DMi{_TdgOnt#^596NI%eP5N5wmq$J+%9J1cR&il-XO*GP z`aS#lKzH2O=zJLdA0xIQXC(usm$9~`0jne19*5N+W1F_siV0-4_kqV~@zTdDG2g$S z0h44HjJK;=9uyO$*=}Y72ug?0r4=4dLd~l?k0fwu>x+bye)86Sy@Ncmsh)SvhVaJS zrcXd~{1Xw?B+PgN9*$d&s#hI|>-)U~EGICYkInoqm*Wz#9y`?Qj-fL^5YE7^t$9Ox z#d{+if!WRw;f+0n^&#jf>^@@X3*ce_W5w&4c=?y%`Cl$BlB*ea;PiELud}N*4AYjN zi?zLri`MFO;<3Kaj@yeX{BFwU^nT!GP^|xp`FhXi!R-=kLhDtB>{6kgE2sB;XLlbe zMX@U4$O0+nw>&(I+}(NXd|#XDQJwip0om=qI2Hr2Eij%B-T|X^Xyw_72FCyVqjmn@ zxxoF;7rG+e!sRtU1;Yt1Y$T7bg0_4lL8eX+;gvaKBXTuyGx0|;Sb*IB@$Ucq$p7)u zn#Y}Y%NN=f4+$W5^7TJnh9GTlKKfTdjPNYU`o%;XZ zB?xN&aSz`rj(P>vJ7=r)&t2gCRx^gFB;@1lMHkx;YWzjl|I4F}czZhC4!OW`ez9v7 zn7QRMJx}wG;I;k{?j3@4ZixG|P?mHQ0_iBgxS;@!ivi=AIs0EOD{AR#5BNs&KH-wr zXMM(dlNZA4M0`+<9?sqK&Al@%N>qL4^piLs#Nc&89x&~m5wXJDu<0xfytruVSuXMC z`v*Y*6&57WSpMj1^cqnJ=6+vt&u9|322N55*efn67$!f<}_0(>DFJc%AZq0M>+bb1&OYJ>&W+68M8J{a>4a3-cv`X zCCSE_4Zq^xH^hD77N|SY%VcFc49;U2Tkl#^YZ9!GoY;ZC#4eol?}v;ow>hi$czN%f z4l>Yju8ow75hv;hb^mhhu)prAGH|Ro?x}{5bxr8mKy>0Snthc{FCwJB!*`%?fQc->3eg{x;kj zTT$X{uU3=1Mnl_*oZbJV>++LhlX34#81gQb#|L_=o6d`#sWj}WK*OBb*Z}e2<>?ho zXS=`NSu1*pH*Z%DadsJJ?XuW9{~dC4ER>V#Ilrol(zOp;;b&W)dj+J&0DJA0B^2lD z+!rWj^8tOBi**UNkBg#{m zYN1QkeXM7**!?Kf!d<-*=&A{Bf2?Y9h>v;nz8^!)xotmpVbuJloT7lIv3t%*Ru`FE zhr{&k?=D!?^Z>jg#_&a5thHBlbc+SsN&Epkc>vvUGTyv$nYy})WDGHT3sB4QUm_*mwa(~)oy~ovruhBit$smH(N1;WU$WDbo z5Unz?Gm}Eob&rj3(?-K+Magf#_#|Y~W>b^X!)KD>G2)NcK%if-P`QhFAo4$wAZNSz zXm%I=t~H5+sO1e74Hog(mA$t<6)b_-U$6eWd?=&A^hs#2yv#-Eczq;t1hEbu)s2ye zHj8bsJ((}HM=xSmRNvoo>(MQ;vwtXG?YjpTSP1bd~_cJNg-y;n}Jog&#}U|8GiQJ z)Lu-@ZLdx@pfq}X)h2gQUq(FgZXjA6MIqp^Lm0e~tZrkCRTbqwi}4`3nP5&E%^iu( z(4W2U6w5y1UeWp@k?*xxJ#*)De+!j{uEb5V0jJHBW!7{;GqTHOVrr~6@j#0PCiVD} z)%#BfzusspqCTY-dGAmHEc{Y!hnL1JuiB{N=|Ftz{)pU|-tp7j=39xI?(rGK=Z(=y zq4%Np_oQM)dDK@GKYanVk4G>1g?{??!`*1u*PGGU=_S{Vv;I7sNGsaZ(b2NJmIrVD z4qYAH7Wda~`0P|Uab$PZGNeK_T{npJ3}-e9O{aLSKMRLU$yvYpgo3>cCmo^G;5^~O zIkYnAB3_xsbxe5v$UJ6qA7VxtHz-5ju;V4O`n&zNjyMo1N8xG7lc52Nc2wA0Fo@&* z+W9B}l@xhKDhZLG%k`a0(j&{$t;Y%I$}V!?iYtlkudqTRrGb{7ZcI;;%mCs&CU#CN zGAG`aa;}T!$MO5-YtHT}C=1_i7>Ljq_5rIL)bwkc~x z350icneTOjo!8`Iz{1m0W=>jeX8FVz8WTESYJmC|+|D3X->DPU#K^Zo!6;L32$mQc z8oeL%V+uA4!`13N5v^aklt@#q4*n=};fP_{Ksc0*BELCo1)(B*mU7wbWwRa}$N%_> z#L3e>moL1_ShNAJ-y4Hz?N7(e+}?%MmT}}3x-r%p`3%Qj_O9?%obW${8JFQV!9?%f zA_CmlgB0#ntOf8OE1TdgAvX=TJzvaojJvHD9X}T{h9H%*glK9lQq(wTs^s3|3wkQb z0+kc-uj#WjmwfztD6Yf@krBlNzL7EIR#?q%gi(r}LBGhkWiK;lta?ey*kdRZ;)lMG zXRI%=hYr7)>uw-MXb&*5=}&@uAo~K|Ja#s%D(ts!{&|zj6klcEhV#?dcXQ%|ArS2| z@RQlXr_u%GVvEkxL9VZOUZPWdSI5Qn6PYHjEwrJIRYW z7PmvyEikmv``~p;e^I9Ow-mRY7i1onDq2(G3^h&>q9z5517#J|#ybAmsc(=|b__pj zC>YBgfm`*I&4px(#qbg51U)(&@GKNAW> zMpTn9r;lL3{2j#iHF;N`Y!U^i-9GaxTW1q*Aj;>h!Tk&x`X$&Gx>| zg$0ZJ^pj%oaS${v)7sJ35lBq(G&z7uFc{Qa2&+%mZT4B}NIB+U4DQksyeE_9j>NYB~HMBS|Y`nJOc}TqGG|QfphK?r&JV zO5fc%_NG?-5m8>XBK=EMax^4_zDUGLaAcjHQM&c|4JA#k#2g6D-n(M*yLaB?adrW? zue$inI-^a-A8^*)NZ?fmYHW`(%XwQ<+-qreQ;f{~Tgj}>-P>2#XoPu3VxLj(HT>!L z0@JYvQ*fX&rPC6eivJ0+rha`nCsFh@PLDk+t$gRC@7_|0t*6{JzL?+Qk)`}UG*V$?6xm(M2s}!dG^m53^%(~q~=I6 zrDq-E=5@gdv}^<3iV(tLakU>J=N=y;(mb#-;c9mn`D+u*A@9E~6Ury<9sY9b4X!cQ zSOE@M?3%IKm_j)DNO`BV-KHD{VP5H?aA4BEDn)8T0sSn6sKvS_r_^q0^ZxBo{~qv8M}{vjg@v_NAgqo zDSa-(Jvd7<^P=#*8Aue-{!0D&PdC06kSF;#1brP()$-94Qs}(41ApxA0xI9jj1iD% zO{5c29CL7ZgCBu&ry+9IHgsd0m+)dPWi7+yK3el1X~&Hmanj{3(9l^KvjI z<^1zYPzHzSz)*2NJ%#ZR>%qg~J=f)tUPN#lXfUJ1XKT)Bzv`4Ab z*(mIak0VBtTRevhyq8{F;9biOpDkk%nwd~kmsxzx-ue0s$P<=0u4^)5sfCE@sO)pM zjb=PH2K==Qlc~i-BBhCNp(&4~hGRC)xRWD&UPEfe-&s2jnYs{rH2M0V{S{aBBcyp8EjUXI z#QdQ5C12Sizpdxw2eRo_%%*XfjU65wl%GHo@liRj{!z{+ zh+N}pzs3wRHp>b=&l6oUT?uQen@@y$57}Gfik)xNil5n?!Za^E)g={0{gk-fH|W0N$Q4Fh9Jbs}6TVb_dwaz*5e{jIm3Mz3b) zrmGSK3{&5}V9A%3B9xjDoo74AmTY*1xZ{(Im%W$#Qh@-i3nz~t0s%#VmT}1tqkvx4 zXb)Du##@K8*s8TWW$$21R`nZW1oU(Rsu7^m(Lb*>^fXDkANbJ5+2v`rFkk<)=P+sN z$Gy37anzNAeG*Gd(}@3B&x^HZvSQFREy%e>q1l+zPS~ks@;c5~U0lyubb0YC0MWXU z;riM=wlB_Pk^fznN&9lE_qbIHPkQBmc{o$>0M`G30mU-Qs(l z#++%RMGyw8r~FN#|145X%F7-#L;p_BRY6>Fmf=624%QMck5t*RbI!{G;w1VFCgX<2 zR93&ZYZ8&w20M=UMw-i&}rsh6Y;L7LnM?BFg3Me>a_QAqfNI z#h7y*;xTb|e=k~1^PgqHs8wUSHkk1%9!NXq5xzBu=gplMh>z*&MCGxs;1`tC%^uWFV)uQRiDw?5(fUS4KF{`UDf`x}W^T41ubQy%%&Io} zM977n93Sgeqz)Z+R70Q=xg#k5LdXj1KxmoyiHLm6o%caXgM>cfyf{M~Ric)#YqBzV zPUlrbvbI*g^#G+L{+-^c;KLKGaRP=+;(Rb-JR!qdC7x-KGH&}sw-97l6Ic_)3XUUAn1m>VJ zYMGQRxA2#Ft*g$FLu$|-AyxlZe4M=Q-vNDLO!r4XICIjFbdFNQQ%<~P@4|nmb@*S4 z)mu^WJz%R>!9jVw9(zJUkc^@jWm9zkQUBJre z*Zr06YmfJy^=!1q$aRycWTdNsEf4WeXOgc$6E=NSC_@vkcT>J@{R6JOzCP>0(Z~|) zziKgAD5khHkFvJ@?RWi&*Rq~BTGGpTMxk&@)iR`~iey!6d}LvL1ASG>H|G$&dSx|x zLfq8xyD?XzOMKH}rl;%`@#2X8_6n!)S-0_3)!c8Ow%4LN)TfqchYS{GC${bL*jN20 zLlkKeC?gg+kNnBCw*Tpq*q09sfoV*nR!W1E>nwPm8bR4F`M{HJhcxP zf+mmfhMfWDR5RNCemtko?u3>4?DO3eb11iyYbOIu2j>0nA17}JyZt9NTW()Y@|xuC zP<56m)#vr^S(wM)3bLH8rme3?{21kGX(=vT8l#l~yA9G?IN23K9T&F1TGHY+BQ%W9 zx}EOXTz}EN6)y2n%D#p5*Pwyu^trZBQXqx-0PF^}^ks7eOGedY6L~DMUFNSgT1PTzOE2jmSTm?WZ z4p!&*NjUN$-S|Zj2;&SNhe|A4J_*urXK`=Q1rpFRFuVTi;f-lV$i-!;LNk_1a+hJ9 zTqmle%d6QXuT=&tB$swUoehx`Pf>JrEi7Ao&63p-E6aiBXFo#Y=KHSR>DZ$_92SSW zR>r|6u_BP<2POU<)XA@+P{+N8ShoG1dt0*p2I$ip)g|yzO6cH&7c6K<)FmGtDYkJx z7Y?QNYg%Dh3}FGRF~f0Q0NW=-E*Jzo68aV~VvdNx%ZGvSla@oKQ>a`KUK-k0)|4Kqjz>DxDiiW+$2&UY3HX!0d^aDdHoPbSKqnl8-?lFip37$ITDvF8b+y;s zMa3=9?w^o#{E3Y=2s;$S9U1hgnhS2o!JU%6xSUe^_3h&!W@d!9O;iAT+UWj0+11CL zeARPd)z6wsF7I>Lc`)Brkj#U-ZFfan*4Dn#i&0=RC~&_i)u!)Fp^ip)Y%i0b-2ZwS zMBb6#1-x$VcP^V!8c?=K-+o(?-hb1wD@=5 z*wYE--gbU??*Ltj-1-iRvp;eXcD}y3zOml(Yf@|L;cEV1k>J>rQbO>RUMY7lfb6EL zqeJX3zCR9Nd7NjobcBYwFj334_me~Xy!qmD@=z<8BHGFZX2de^ZH8I2y8m^d&^oma z!&l<8vfEtt$?bCJsGy>|;jSxwJ@Z(*{ODTMJp!l;TK97>Jqkjgq4>h-S{-i~2#19s zroUr-89v~2c+a!dk)=pLwQDk@xj!;syzJVl@?Y(yX~--^BKOPRM#9-~&G>S~4*(33p9 zCoZ=M=6eKpxVPn~pJ8zfDwhhoefh`81KMps-1G0!gc0=6!LEr&OdL;7f+16wYKQ}S zqZOJyZ=U_;7EYfNb={4#Lyk=Z6H((jyxsLL1%eQh+xw-+92GISy!y4At$NAHzF)Vl zkdKl`elBBFT-xF#^triFOb3y59D{%*`)`GioNkH48}bwiwKOP9*es($;5BA{-?irX z%EYA0d$DBqJf>HD5BK5HRRlYI8#^n+_Q-43J@cy8jd2%iEfRe~TR{r)l#me%&5u|? z25Tjw>GL^~cpSNY5K7Qy1nPf|Hs24elP(8LH{S+r4}Zf*rg54q5-c57CjEa^4t@IX?52|-e=!? zn~M?h0$X*BjP`kou)DK2Oorq?9hZfyy5*s+eS=#(Rz6Fv5*09dTk)p}3(%%YXP}-K z4Wm0NC;dH65bg9d_S7)$Ju=BwDL=gVwnT7<-Aawo~XAMM|1c?e!@Q{ z_Qp=0KZUf$^v{QfBF_V%#;F@hO_Gi^lyi@kG#^2$ZCC`s2sF&$jvH8EW@SeZ=O_() zMuD+6njz9?)RqVerX5H)5!~o4DBSWc|Js;re=bl$&q-h43W8u!ism`BrK09fBlr3C zc@&7j^`5zoAo&?~?*8=(dB+P0qjj!;->T)#hcAPE?9OFDEy$m`jr^4Ue#!=;v6=@V zgyqo7BTD6vvosI+DnCZVW8kUd!qWsxmkcl>5Yk%&qai_b3@>xoS5isT(;cKId`Q9u zEZ+d|_$FZe2IkPD$YOD_|3*wr)fwdYQnvMc;ISv%wR`3!fFtnt-tlD79C6~5DpKy< zOgxFsM%CJ9tme@W3$b^)2n*kS2rG|&gnDVwAUV?Eq9~gyY8levbMSa6;Jsw{GTd-&M(57^L7o6|6qI35$B2=v28~LSM2g`5jKQSS^wmI4+v<@ zi{~F1qc3OVb;|p!M>z>lK-1srH;%3cV^S|?IuuMqizCw);L7pxBTCi5GBRL1C9Zeh zy?4taN;UCl5crZZWHEF!4~T^3g{YhuSeo&Pu-hAsp2WSr{eT)qmqZc`dC=i_`_0ep z-J3+q18_Pzf56rGMQ3a@^h~`Dow*i$y+}a|oy{nuwHv2-Jyi8I&v#!*tzW`CN&1Qm zJpCLCjcNlWiZ~>iWYh(d~Tf4h!QkOLMCBTzw%9+VxMoiJ$Kt zzT)X#VhQY*o5&OCu}^i5L7mq~Aw%}y=S zqDQ7-%_6+xtBe1HA&hM0dx>;LPO+m`kB_2rhAAmj`s}P$yVxgmgd3B zIzee=G_;v@gm>~djo|hq@0X(K5lP^VT6Fu-9Uei{LpR)G`4e!FbM+5#)J(KY)F)8IG{rA z4fZ}b6=t~Cg2vIGT2;=3pDwmV=gB>KY20 zC3RiFKqRK^X5zI9Cbk$1XIsG4eH}H+fRDg5)bvO$-i4)`ipWifp)8}FC?oKza3Cj> zIfu4_e~x(!rS#2t0$&}ceiq5q?(`mH89O>_d4@y2u5XOlt^g5FLO+4<44Thi1YwHmn9lJE&~#`Equ<)7k`ltl6XJU zewEQKP_*lX(^AColqOYK?3I46OVeJkz`E?9pLJ>PI=#B`a2!sh<@Iv^qShjJmf>!D zAM8rCsnkRl3}C5ef+43cWiwKOg(04ZYNYN3(u8H#e@ksxwn3m)ERaf&$$^iiK}V`i zG{1_5^DR)E#f?2uOR z{7$6Ec!KU-^xi|v&En}aQsft(e}Nn^l2;gS!>mK9yXr_Z77(=(N45{lRIk(3K%!2f zM))H2PRzs2IElJU_r$^iRcTX{mUSgJHb^e|4Ut#cDV3^)VIh#SaC-#FOn}4#>O(T% z_HuRhYRDK&o#5c|Mw$jE;rcR!MD7ZVOAowNKvA7gu=oV$RLy_DH2_$Nfz4o8mQ-7l zKR!;-9=jO{1H~+o415ankx|ZToa*UN6#|SB+xNP8$tsc_rH-~>jPk>LSHT}}45Rcq zPWK!Rq`UO}^7u5|9$g`Zc+640OWEnHNfG(=8cE$LcEbB*z?A4@-6f z=~Z2jdq~Ae^*ux_x&r&#>gp=*Rdn}Bas**eXp**u_hhYj^odOEpJ#Y-`%T$mH|f>> zD>c4}3onBhi~4;I9D2nv8n#&^bCPrJ?W_tm9S?!f@`P0UznC8!=w)S;1slPNXP6+j z2BiG$;m^&+RyK;Z+%(BY4~qs*E`C+*wLOo!lSjmSu%KOZ{ohLg*yEV_Qh%;KD||+f z#W2rr^i+q#kC`kSIuUSC+L^k^fz>rW4CVZ(a}P8NxnFznMnhe=olD-PK~QAU(cQY# z1Bo$y!^552a7rV8GslsYaqeS9@`i1~3s!Jr{<&K-ye8Zd16*hzl0)sB`dCz?PpnM> z?e`OO6|@@h5}e);3?60~<`8DF&rxjG?GkL zcP#YDz84nLV4L-@gG{RDXrI=5o)mwYJ>7?|KV6tf`rle3VM=sakNA+Qd`mxi#c}eK zeN(?)oLu)s0-W8QZtUDLC;5qVvCPj)Sm!L!KYFVhXX}Ep`=tK>T^!c>y70;M+0wrf zvC|P~NJ*+-Db^wLbbAm{cty*yqK&m&YyK1iVRDU;CE6Mc3KxEtT#v>WrkbAET`0q6~0^)dO z%)^4e>28YgQ0$CH2Hac1bK4|@9?5Z)iw9(tfiTCsmKzj zn}TFXQo<|+t;wP=fs&?e-O%Ny`*^cJBj404o89@E{=C2^;JnwUS>XMCNs8vgodoO{ zv5L}jE)Vi#ngTS1|DRj{wn*m{Cu15Qs0IKEzt3z8jxr3I<INsdK6Gm-etk`8iK7nGMhF}NpY?V57Gc_aYlhuZ$NeY@!bPwwmqik!_EfPj)t=4T`E_Yf8 zt$H6VVOh35K;W_I)@=X5!YeKDr%~7^T1u zkMUw#4Rk-6_w=ww1$xks`8vul(tW~nf+`Nf&2hSNae<*;f)bA?4ft@-{I_62!miY( z!BfXIu{g=fEEztoT)#5EpI{<4Ds<`^uc0IC+H272(j{6wc5FBb`U^X?w?#QN6*>+H z7>PGMiUiPveB>PvHbAiSRP6}bs&Dp-#!y~4$;V*%-Zaekwu%#(R#S3d1kVb4`DhwA zN1J9$%!o$T#9%D;D`Zd0ogW^oOu#+QLmsv6JP;p%)f5m?D{`DG57ee-Wh9ug!7qF- zGkDqJ(6KEa>!j)R~|ScDo9?Yk9iwH~}5DPpozm zM~4Cpc(HO9u&)s%S|1Vb;#(cs^ILQu_2305BYlD;T)S8vMMP^H`N_8c$U zacDK#DIiIo`+`$nKReGg>M;T|4as}DH+#H-uEQ3t0wxy6?z>N*Yh!K`Ci6$iyfCHW3fD>Jxds~N(WV1QYY~}rn_OY05U4VItrG)sy z+=Gbyao5#HptiiG-RrI2BR%qkKeSl9(;UUuOKX2^#L8+(hX!K#er!WB?JG~xFD)M- zU#UMJa-L*>sh}n0R@!Af(8DcD~dG zO}00xiss6<;j0kU5%&|ppHT;xMoRmNsgAl%e_8bjdCoVFyT_g8lN$s_%TT<2#|;VM z5alXNAH8Y3{nTSk5|Xs^(8qvtEY|m`XqFb=(-eQ*dTiXC?X|Nu#mmUHf@NE3btzU1 zm;n158jnySDfb;|OT zPYgnF@$*yq-ETe-nS+Gg50{Vsv2)QTCpkZ#|A3{myGyz>0_WSNqsQe11JbEKo4dxo z_CY&M9dG7_>ayGgABIT1P`j5)aO+yjzNN{FD$y;f%8!=|VcYW1;&0%E_})I`k z-s|Iy7n#~R?u+aL+M>trbIS-8{>oG)zak-6SECSt*na&*-_1+(g^VJys)>ndg)^)e zo?gkSsM}Wa&3IG=C%J-*d6#;E93{IZ>`Mm0W=7^uB(e`&%bSV{_`&reLU7aHZ8Hk9 zDWvLXvQmEABx~wNh?_Ipv{8mRLUas>jjDgHx(Q&~_>Y681=#p=%C zess|a7tQJKbBf;a1lVhr)eIQWYrw^u2oblrFRKW06t({{2%b?>`8vH6D0T#hG4s2H zuZ-Hsq9_vJmA6zl(U$gWOwe!fg0u=u>LV z+!+6dxgR)W8P(Ft775>aZFP}w4cF)6elw5Z7U5B(%m2#s*i&_YOGc>WFLpa%4rjKB z-QCfn_yd=pPx78U(3H@S#fDiQTa>^An_(}TPw%Zk)kVVD@+w6^7^jg?dZnUi%{)Xr zoyR^;lb4XK-_69am8>$t^Xa*WaSI6Q-1F2w8GH$JJbK#>xDn&L;#)Ot$5_5jet?3O zd1n3z`?>k058u>e2JTsia-G=Hmm!U)Y6X`@_`VTOq*r{S$y4`ga#_Zx;^P^~&DDD< z!k-7fH$n&W-(#>e{-o$bh+D&|Bv&{7DtfObf3ze-Cl6NZkiQ!=dDOdaMtIgyeVXclg*a}nk3AIJvaI#u_!!*0tNHAIGKGu z=m=MuZ;PPb=xpWE3OjI*@k7=*iF;b+8gClq(a1v)o;6Jq6ol0QX823ek^;fN4uGtyy`K#j|8@% zP1kz3u7-z`DKA1S1J*~sMxM(5bnI!YRM$6;q-N-o*C0|Se3w9gB!m2&Sj+QRU!~cQ z0o`Jj$0%7CaiHS3ZG)72HRXfMqQQQjXO6uWVUu!W#~NZ~M8z9x>)gksE^K|s6MQup z%MT3?_z$CXhHhoYAFVmQtKg?kN!{K$ew8Ie%=q5@;v0U%PL*45B`ZPNeYs>=O_`f^ zFJTw$H;!-YDdljUHgy&D`x8T%Xc5xo0-4lrsHHO}QNa!CGXw|)nMFSXn&#|@$OM?S zT4%Q85l{p$`U(j6i1;K|!z@UEOcI(s&DNg)2?NRg`oXBm1IV{|ORC7Z7-pFvXw61Y zuj!x&Q}r@CIrkkF(c11WIRUWs9_YSb67&SS0o_5&dIDkh%kwq$h9*Eb+QbB26q9Y> zLfmMbsa0$<{GWK}Gv?BNuV_g@W6Dij+1HtAxVMQK#9!~2`bluK$QQw}5O;gkNLa!3 z4IGO+t(FJRFO01=iyAC;(XZ+s0<9EF%M-qBe#h7OIi~B~{!xGEh|+OB<0?ziz@lnm zWsXG_IZ8vnf3iB0lhW$?M847ULUF(n1E+XRa}RA7cU|*?epXzcNln9Q`A5BPT^-gn zmIyf!VK(3NQzP>-lW70yAiv zGe|K>!Vpwg7*e$r4X}ZPfZ;EI*$Q7)lY~8DOTr$Y0Af9RZWIOdN12_Sl?2?HYKTPO zJvFUuvmw_T+)xMK!944bsQ-*K>2Y@~&>E(^I3=GpN;l@M%y%V9A1h9r^r6d4ozPSd z&dtd=ou#DUioiGXjTl`6Y46q684^GJKzh$oL@F=EovGh@)gjNI;xruJ8>^>LMJs3l+F9q(DSEhvs<%#a(GNzPNI{sABKi2e7Xgw6Z2=HPM~Lyc zIjMdP2Qk*5aU}s(8z!RL#KzAkOx>|4HHsMi1}E1hQvl+?+Kp?*l(nIc2luvTKuOjgcFH)*B3gOHCpQXQN|36kYPRS5c7tejJk43D!^ z=DV;Ug;r4^a~?x zgvlb?<9vyM(_`TJ;x-+W_&(q^p5Qz4=B!_p-ZA!no9 zjt4=d#XR^`b}f;X&D`noZ0SN*jD;iu@QUx;c9m##1W*~D zWUo(LAdo|HNImM%LWfa_1yX?7pWr^BTlrV?g-U&0ie~-GL1X!- zhCk9%=HCXu^(nMp-Ir<2ZOJQBG#_Cg*bzXoU+hgvK0cPLKiy8>NCrNw4xQW&T=|+S zDm3LDurNr{%tM;Wfohtq4y7r)tRWKvgI`Y@cNQ(Sob9mzgvzu-_;lgi17@c7r^<86 zp1c@J<-;CTcPlPPC#!2KrY)K&aWcHeDlCzi`0$akmyVRsvdOT`sybX~XqCHf$tvpj z#Rja!(nQPbg-($>7w)Q>$kMG*4CaV@qCk^y1BDGux2j&3Z%ermA`a2h_Jn5B#e8-C zb^?9hw5xwk3BDiBPf29p|3f+G@p@^MRX;l@Q|$k1?8?KTY}@{1Nl{U@WY3ml zOZH`?#TG(Y$0(IOV`A)M3E4@JeG4fBY&uc%6xHvH-R+}4~VrU=2L|d4*P|E?K)k_wX)_-M7m6Hg6$JcVo-ATTpL0*J$ zg3aNrw#V)JQIPtubUO^ITnCVXhb}x@xFRNg^rGnp@xsx0Bvi6c=+E8HFk+!8pzcjJ%izCEz0LYH%UR~EaO=%ZUf z*QAGZT{Co##9TNk^IYm$PB=7pa`(fz$UcaSt|&kI6RX`S_ItV$QYUW0Y4=eES>*LF z@IJsy1Dq;l0p6lEWoDPy^pkYs6RtQ6U99G2nb+qr`AYq{>|;t$|K-azL~QOnjos-f z-!WhY`+0*O*Z>s6Z3<3j#;v8&NBe)d`~`0LRb2ecap`cn$!M0-4@3tfHSW;NtX=F< zxScvy+J6R-onjiBec>u|zC}>7W_p3|qwVVc&1}Ui#rxwIE*1uuRf;%`+g{vMfDp8jucL;bd5`y3$3ueTA)2>3^K9?k zz3g>G^0ZtG^MkFadwN>8`0k!~!{UCCh1WE4$WD%fdan45{8-j`qfgR=?vIHbv0<{> z)WAv9eNiEHmeG5eB8Q{V3CDgq1&&*Dts~1l#te>av3#o1>g*R89Tz?U&7M z?TiwUXI~Ww=iArkv|b*sbpd7Hmb*CPjEy+BWAi=A#Z=_xgXpx^KHXY+v=(nG(KKj` z@sx>M^XG&@<+ zXhCQ`0)Z1You9szJJHVHY(WB7#}^w_m*dzDJkL1IX3<^==EWK5a4`DJrJCsEXofNr zxsT<4vYi)_+jmMd+R&d^d3m;QcKWaDG7mAACnd`NNS2#N4Sf;*se_chxG6r>%MSX{|8LynA*(>_S$% z`CTtbyNo8;0YSg0=C*i6Y>MZH&!Z8$dNcw7dW8D#`YL+hoD6#su#sASa~q==$3LCH zxow7ez|6w6dX)Z-Y($}>$Z}VW<(5t6?oAoy*!TJsA5HmlLPQfU+_EZ$-x`u*$x(mb zo+j`6wN6CI(D=@&yil`i9|^D*AYHA%#Fo^VKFjMbjx6p4>r?lXZA-FoA^k{=-Sp1w zzvPx3f3P@wwnlYHrAV2&(A3{0Hn^#S0-;f3+Ky2Ww=^a<7H!UN_s^y$R9!RSC>MkY znLE!Ks@{pvovXp_*cPeOKhN)vV|krmb6bY3NU%ny+ATwe_00OP6hpCBdio3T_=;ZG zE^h$29Y{ogFsI}|KF8+ybvA26>!QKacWZvV3+io?{8RwI71y$ z4wh)%26o~n1R=FJC9|zYb~WAMUvlrX%u7f6$f@-v>MUsWC;BVt2DfMiQ}Scb>H{Z< zgjAEG930mq_URKUx`RSwW7DLx?Sadq?_ye0pH)Ur<>fs%<{=j1CslHS@4j-Agk^)r zM$i0&b}>_O@&Xn}#TA|y!^~x7F;c~yozT^xQN-8q1VU}Ep~Dk;=8E+9=%Yf9qInp! zgU7{_#63R@q=?<)=~5|KA+glanCs59J;Wd9aD<;^Ydta2IQ)gtk5so}?1@AIX*x*L zz~-ijxU&S@Ph#2u+w8l7GGw)?{+{4Z+OQl#NN}6nm2tDI2J(8m*-UZtoll~ zzSANk2TC=Ju);&7HkXe}6%zHs-#VJch`kUC?!FLd()x5@F2qg5J znEEE>c=7`IAb{A^46F<5EFe}^l5C`b0mPJN0B}8_qfKlw#ik{tq);~DJ;AC=eM>-K zD%rW}qv|06wO795u+SdEz|ad7@6aqYQr7Jlf*vyZRIcfxRX| z9jl&kP=}^dOxeJPs)2d)eN-IpjXYz+(C|o8`!{v$LDfEwPl#&7S3dGQW?Kw5e9+ay zr216bMDt3J5Iz+}FD*OLmM0@GVVj9Cb&}(36IQb@%IN>9H+Ra~0%4Y$>~?(!tSnzS zUh&;o7vvo#^dOG8JbLe*kZz8lN5izj+?4S!kBCdhTKZ7TQ-c{)-MOQn(8P@&ZJ-}I zaz^y+T{;{CUqCmUuG+rT5X(3DX|^DJJZ?V4Ewjn=iJZ)kQS>+OOZk3#TkotPQX*O@UwpnzZo6R{t)2@3oXUx7W`773tz1iBgQzrQm*i%LslL{0@9 z?2ibyviisg_d2NF@NCU@!;P9`!wMRgni(Ah^$XG#_UJnG<$hfwru3<#>vk+4Ll>e$ zC37>pN{F2!@+&eTtVDE_#2C4DOtqSvG|xza5J__i{RV1Y zR?7KV#M7$62af^XqDGR`Nk_IbLN6gDgRa4o%a9|drSDg31;${R^xiS^oy_lFcEJlz z#M9J6j(I802h31UkcVp6FJxA!p?A&?Y_92yh%xC?O8`i-N0kHs~pZRrk>TZ zztq*9Lp{4ZH%OlozB#!}Jj#^qA-lW^F{eJK?%A$AFMq_TBQA(aFtXUH=7qt4{0=Z!X(^1@ zMBYVZS-iGHm@%`)8%0)>Yl)Q=(>BCq!ZaQ4rb~boO3og9*`|ZZ&olw+wiwE~Z31pH za_8c+A^Ncpp&J>smG)sG8cSanUPz>Na)MHG*sk)t`_)z-(>nJd&t-sL_krr^Xbtn$$+F4I_&5%aXi}8p+89haXlJ@=gR;!v<*`qKCKY)XmEBGRhvYPNq zdqu?@0CUnuZu!S}on>(Jq*p`SY*n9Yb>?^`Y9yTzXWm7e^hn&S@-21wSM(fJX&|$~ z$OnO(Wxol<*T>oy;lL@;$}%Ks=xY(p(Bsi_+K**ZFiz7SpG!TzLa=rf{#Jr}_vGzn@$`SEpXDa)*4=m!%y@ek^0@fR!_^-*T(&Q!Fx8Dm7_IXjv{ym-H_Dyj* zOD@HHe@9N0y2qez^4ht*#iLpvYty&iV9b5?0{P6>nDw3Q-G>k+_nsM9GwU*%$zB=QcE~H(L^va1^1%f<%5<0bSwE>P(+^qhYuZju4 zj>T{cbw&swJ9l}3(`c_+@Wz{jw^tGpxv2Z&7X|fR`Z&y2V(85-DI@d>UF4?)D^)QB z^|wPdM_rLf)q!3U6wU2-8a1EK-i%zne$F?uMJGJ^fLg9tCW+mOv|i&-mEJ0z__UeL zV}h#Q|I=(i9-_Xsg0=KEcG>2;8!`N&1oT%et$+LM$D&f>p1RXF?x>bUq$CT;@K=8F zClMu?B_`=hzQUSG*92o^>68JI`?nofY;hPuRX`kXrPEjlwX%X&05NgT9rrArR@L~M zGh#k&k>I9uk&a1xvOKqb&Tsn|hx;ziPVc$tsr523od+${lrDQe3HQaqe0ZpBgDdG>Uveq$qmuF?upce6F?FiJG8e_) z$(2rJsK{|0V~t|{km#9tEZ(#zrc_2GbZ-!Yw>5C?8}LDjoWFZi?{Q@|*l#b$Mq9~H zukdwhUT{bAr2p&eD%~FvwZdaH@b!U&)Wo%+Ijb=@dFO4|FVxT+^LcxAd9z3mh%K0s zBfx}FsZjG6J12W*yM3kK)UWb`_PdoC+{@=(B_F?KQhd(i2`ifufX^5^UP2eUHlmQ!0b2p`Or}cM=^rqnFRC zJgL%Qwx|vFVBnc;;@PMW6?qkrFerPb2;rhyPc<-$dgpW2_vcBjs0s6pGpOYgTn{o- zjAPTy66po&>c{X;ef8}?z!g7D?z5buZYSrGted{Rnh#PQMD*cA-Py(*HDQq&z_KGm z*W4EfZ{w9Cnc)LKu5O!GudAC1+`&n-KWhlN9HH^(;U{j|SKaD4=Z=?lT>V~CQwS&6 zaBYlsLB0XI3))X0Lv3b}V`UdjM4@L(^%x({K6_J${L!C(-fVuR=?8SCK7;ln2d_cS z6;G*buI;GxmQv%~Zw&c8WnIimYd8hmt`fb9bNy*b1SQP%923-;F>MN^g3p=VSAjY! zCsJAL%ONs%+b4pH((sSdE?4O|Up8bk#nM!7wXJhiKAv348ZB)9?x-A9tm_e1Ui|c& zGSA&^I_lKW8x>fCzIKn-2TFayzLsoA$?+#iW5=BhP+_m1UeW$Kn`sD-itu^f=&1F@ zIwta%*~GZ8oLQYBBvP+<>Ey19riOg)qp9&%p2@p6zu-jpXy;FHB7T71^~;gOi*8xH zWcX&`TWX!`j844=1VMBkxg{6_?F9|w75+$*LpHY~bH_Xz?r_(@N@VODY)Q2T1qfGt z{$Q4*o?F`=xH%tIuqWoP|tgZ&yumZzWf zm{iz=lQg4F>e)*-TCDWPPJX*L=2$VoQeCW7?81sD+Bo5Y#BnQ^*NNovxAw!lI^NHH zU&IbC^4M#>PXFlN{aM+AR@KYCtw$*we2azDVT-v+CjHDpG;*J$;YSIDl@2q$``tsVWTH4G8(9BokSXjO(k6` zKx5N`$rr9XT$67eksnapQ;wlG;P~OMY%Va|x1A9=GMmM%&DY(1Kd?5rIlW8~_%)67I|87V0;;|@R1aSSQ zKrtxxaJpNVM!n-MX;Zw>T)fUGXv1z`a9fW5hl~ed)U*m!+je_468b7JpY?plypt#G zD;ff?xqVP$XcG5)9Ba}uSX6)8h3mpXUblDcTKRtTtUTcFOYsT}ih44`eRoxDDE)Fz zZ5_OuJk3X%C}>B`b`wcx_*4d7o;Q7=t&crTeM6vp#yE3n%`1%C8Jtv}c?R~S_Z$~W zUb=J0yDJx~j+Rk7;|9lhD~B;GAtfvP`PLJLHj}C*c95zg@Z*4&2?RvPTFnWLw8{_S z+VUP=TIZ{tbeLNBPUql`sbb|-Y>lo~V^ICL5%fj#742kaL>vmvo8Bjfih$>Y)CM;( zt0$Udl^w6O`vJ4=)R0d&5^PEUga?yIH z&-yMUM51QBaxDR~f>R+OpDD#K&)$AC&s{S#21FT2?CCCgXH^0|ogc!y!!lktc;;mV zr&pSgc0BYi(VQbqG=P?*cVi~n`1QRtYM*<3IR}8vNv)r;+>&Rc!8jhl>c?oXBtUiA(f{Y@v zK1m5C8Cpxq0>}EyA9RY!*w$W1ClCRLg zMMzy}i}S@c^;hDJ5S+cbm15`MR;4Pa?5N4-ydf_Mzgx`N<@-UGm}>$ z#p4R7h4Optm@1{Q~8-Qx2BUofPG*?WekJ1krd<(zxlIK;NQOiFX?}k{t-CzN7MgTh(pSq zLvarICa7RX?&nj&l7Vf6UkDh-%}!_Ugu>Yhe)E0KxrdQ*9)%RnN7TU=`DhAck$;tCgRKLgSJzj44s)d`#h- z9{=2=83OActvG(Vi8<&~l+Bm;B<{Xs*rx}+r*(ETfCkna`IjsJzAUFj{B6@Qy5|mJ z(aM>2#IGCP+hhnYs&iLa4Gm9UTkQIL1M*NM3!@PEHCO4(#&I>=ixN%%No2_;wk)6^ zY0s*8fOwCSm;4l7AK*jr*#IJvXx@gWvQzr(Hl@JJId$VL2~B(ER|DRTI*%=Eg@4xj z9SA=%c9PN%iaWyGbgiQm)RDB=&QzLKbo__8^R^NCX%>dVogy%0CIDhH+8(H-DmZm) zp5na>ymuHCC?)3gMgf=q1n%mw+JmuunRE`VJLi&FYsGJEv2WH2l>*+T=uz@eVut`B zARf;Vw(?_^d2QL8p9t{b(C4r}@r=do#}hVdpD0PnW|j)Gtbd*5-64fU5UV7BbO)4*S;zpZ;$94+|C)LV% zeb%NLmz%6IlI9$$w((o7r0#iuL=kxJ=)OD;r48ZJvNG!e*VsXzA1Tb#>P)11fHZU> zK(?9&#MR;iQ<@n%Hfro>k2*UC*8AFVa^nH-JH7l{n&9Eb|{Y z0nHC|hXN@J+4D-zMJ7|~>`6ZhlKAS&krV!Zzy3CR(APY6bxoy6q^1(THrJ?`zW`5t zV?0<;Neb9%!p1u39yfj6!2vizWvmjQ-cz6?ca z^<14P-CvEGpn3qYLylE-xzdb41|>|RiDg!`O~Av1@;&>EY`K`(MJ2}tAIQX@nya-{ z1|imG5EkY`tWk+NYK?hB>FWIeWpRL*lY#<;+>*lA8VFFW9u{2xVQ_+L^*z+UmAkhd z>Jy&DLnhtiewMRk*B=l_k#31XMoamlF!llDf`|OZhXr5r0E+rRI!o1-%DoRxs{ZY2 z5B@FD-|C?hJl6(N&ojPiLR%Ux8nIiH(e-bJvKR09n2zBeWXT8pb8Uh4KH-cOXhwo6 zCdEUwY1g}((%B;a!sp*I{aLxXFsbd6!&U@U4H?KlfKgk)%zMin!V5_Mx2F#aQUE6I zg?d??)z!pb;eAK84SF{R%ApStS+MB?*rC}_EQ<2?H%Kloi5&fTHMlV+Q_^qPr1{Ab z!f;O^zp;n4)c7}Gad*D^wxPfB)pkScX-7O=(l*E1qTyc~+cNL{>Q8x@x&ajgQFJ}L z0O*CqNpoaZ5f7yDd;UUEJQNG(`e$T7-^&K+;ne{A0sb7i#n?i-BqTABRn`Fn@yk3HL0(r8$ER*Geb~G9A2In8q@NMwOGiMT)O1BwvFtFD zUmNZjrmtSi64=K9F#_Ewn)x5K^C6&}AZ|;1m4tY)C9-5NM?$p?fi^8h@St!_(mqR4 znQt66vlPTYppcgU7JpMwN&(+Xe;d%^aACN7@vEIJM2#cZeaUBa)d8w{FgUwnhJKv^ z1mFF$?olvSZ861$Nm!xfvv&GWl2~x&n*)M~wW z^DYMGDfQ3V-z|zQruix3h^Hy#Sy;k0ZXJO2jFbBw#gq-mnJ;+DS=4)+_{*zjcZZ6Q>dXTo+(V=8X-m9ctj% z->{l{%|zQpOYtqK6TFLkjq5i4gbJAN0J`yaEbd-GJ`lUi0W|f{ojy+q{(ciED(7+|tkJZ+fn(v;y)qCLG`>}MD zFxJ#fQ8IO<|2q7G?EB+L^(PAv_bdlmdA(+S15BQ+A7RV8RSuPbmWXl)UTF^rz7wz? zdAN%CuM-j}-`GmLNy#_Z62P_+Y<9SfFp|15B zmc0{(4>twYRsYY#Ng03yfzdkMc4-KLcX?7$q1F#1pK%{;<|##TWFF9<;8*@K`27E~ zSs+~*@@))38olYKoHwRfJQ=gXtXA$~IW#*+azy>kU|C?kC&0NDs@JD$4Z|accl!3r zybx!fRlFWA_jxL|{d1#Zm!$H~hU}UO^|_zH?)2knxsUfQj;godV4n2Qi8{$;C6fK= zKP#a^x5-ptlfjNltvW=q1|85WF-ZaNKPyq-oq!_)3dy0Pe8l4vGJEYC`qxV|?mhh< DV literal 0 HcmV?d00001 diff --git a/frontend/public/pro_icon.svg b/frontend/public/pro_icon.svg new file mode 100644 index 0000000..e075b78 --- /dev/null +++ b/frontend/public/pro_icon.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/frontend/src/api/AuthTemplate.ts b/frontend/src/api/AuthTemplate.ts new file mode 100644 index 0000000..d27449d --- /dev/null +++ b/frontend/src/api/AuthTemplate.ts @@ -0,0 +1,119 @@ +import { request } from '@umijs/max'; + +/** + * 授权模板 + */ +export default { + /** + * 创建授权模板 + * @param params + * @returns + */ + SaveCreateAuthTemp(params: AuthTemplateTypes.AuthTemplateType) { + return request('/api/authorize/AddAuthorTemp', { + method: 'POST', + data: { + ...params + } + }); + }, + + /** + * 删除授权模板 + * @param params + * @returns + */ + DeleteAuthTemp(id: string) { + return request(`/api/authorize/RemoveAuthorTemp/${id}`, { + method: 'GET' + }); + }, + + /** + * 修改授权模板 + * @param params + * @returns + */ + SaveModifyAuthTemp(params: AuthTemplateTypes.AuthTemplateType) { + return request('/api/authorize/EditAuthorTemp', { + method: 'POST', + data: { + ...params + } + }); + }, + + /** + * 授权模板分页查询 + * @param params + * @returns + */ + GetPagedListAuthTemp(params: AuthTemplateTypes.PageParams) { + return request('/api/authorize/QueryAuthorTemp', { + method: 'POST', + data: { + ...params + } + }); + }, + + /** + * 模板 授权模块 + */ + SaveUpdateItems(params: AuthTemplateTypes.TempAuthModule) { + return request('/api/authorize/EditTemplateItem', { + method: 'POST', + data: { + ...params + } + }); + }, + + /** + * 根据模板ID 查询已授权用户|角色 + * @param params + * @returns + */ + GetauthorizeObjects(params: AuthTemplateTypes.AuthObjectParams) { + return request('/api/authorize/GetauthorizeObjects', { + method: 'POST', + data: { + ...params + } + }); + }, + + /** + * 添加授权 + */ + Addauthorize(params: AuthTemplateTypes.AddAuthParams) { + return request('/api/authorize/Addauthorize', { + method: 'POST', + data: { + ...params + } + }); + }, + + /** + * 移除授权 + */ + Removeauthorize(params: AuthTemplateTypes.RemoveAuthParams) { + return request('/api/authorize/Removeauthorize', { + method: 'POST', + data: { + ...params + } + }); + }, + + /** + * 获取授权模板列表 + * @param templateId + */ + GetModules(templateId: string) { + return request(`/api/authorize/getmodulebytemplateid/${templateId}`, { + method: 'GET' + }); + } +} \ No newline at end of file diff --git a/frontend/src/api/Bucket.ts b/frontend/src/api/Bucket.ts new file mode 100644 index 0000000..fb86198 --- /dev/null +++ b/frontend/src/api/Bucket.ts @@ -0,0 +1,132 @@ + +import { request } from '@umijs/max'; + + +export default { + /** + * 新增 + * @param parms + * @returns + */ + Add(parms: BucketTypes.Info) { + return request('/api/bucketinfo/add', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 删除 + * @param parms + * @returns + */ + Del(parms: BucketTypes.BucketInfoDelInput) { + return request(`/api/bucketinfo/del`, { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 修改 + * @param parms + * @returns + */ + Update(parms: BucketTypes.Info) { + return request('/api/bucketinfo/update', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + + + + /** + * 详情 + * @param parms + * @returns + */ + Detail(id: string) { + return request(`/api/bucketinfo/detail?id=${id}`, { + method: 'GET' + }); + }, + /** + * 获取列表 + * @param parms + * @returns + */ + List() { + return request('/api/bucketinfo/list', { + method: 'POST' + }); + }, + /** + * 未绑定的设备列表 + * @param parms + * @returns + */ + UnBindList() { + return request('/api/bucketinfo/UnBindList', { + method: 'GET' + }); + + }, + /** + * 分页查询 + * @param parms + * @returns + */ + PagedList(parms: BucketTypes.Page) { + return request('/api/bucketinfo/pagedlist', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 批量更新 + * @param parms + * @returns + */ + BatchUpdate(parms: BucketTypes.BatchAdd) { + return request('/api/bucketrecipe/batchupdate', { + method: 'POST', + data: parms + }); + }, + /** + * 根据设备Id查询配方信息 + * @param parms + * @returns + */ + RecipeList(id: string){ + return request('api/bucketrecipe/list', { + method: 'POST', + data: { + bucketId: id + } + }); + }, + // 根据桶id查询桶的物料记录 + + materialtrecored(parms: BucketTypes.BucketMaterialsRecordQueryPageInput){ + return request('/api/bucketmaterialsrecord/pagedlist',{ + method: 'POST', + data:{...parms} + }) + }, + // materialtrecored(){ + // return request('/api/bucketmaterialsrecord/list',{ + // method: 'GET', + + // }) + // } + +} + diff --git a/frontend/src/api/DeviceInfo.ts b/frontend/src/api/DeviceInfo.ts new file mode 100644 index 0000000..e300905 --- /dev/null +++ b/frontend/src/api/DeviceInfo.ts @@ -0,0 +1,119 @@ + +import { request } from '@umijs/max'; + + +export default { + /** + * 新增 + * @param parms + * @returns + */ + Add(parms: DeviceTypes.Info) { + return request('/api/devicesinfo/add', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 删除 + * @param parms + * @returns + */ + Del(parms: DeviceTypes.DeviceInfoDelInput) { + return request(`/api/devicesinfo/del`, { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 修改 + * @param parms + * @returns + */ + Update(parms: DeviceTypes.Info) { + return request('/api/devicesinfo/update', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 详情 + * @param parms + * @returns + */ + Detail(id: string) { + return request(`/api/devicesinfo/detail?id=${id}`, { + method: 'GET' + }); + }, + /** + * 获取列表 + * @param parms + * @returns + */ + List() { + return request('/api/devicesinfo/list', { + method: 'POST' + }); + }, + /** + * 未绑定的设备列表 + * @param parms + * @returns + */ + UnBindList() { + return request('/api/devicesinfo/UnBindList', { + method: 'GET' + }); + + }, + /** + * 分页查询 + * @param parms + * @returns + */ + PagedList(parms: DeviceTypes.Page) { + return request('/api/devicesinfo/pagedlist', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 批量更新 + * @param parms + * @returns + */ + BatchUpdate(parms: DeviceTypes.BatchAdd) { + return request('/api/devicerecipe/batchupdate', { + method: 'POST', + data: parms + }); + }, + /** + * 根据设备Id查询配方信息 + * @param parms + * @returns + */ + RecipeList(id: string){ + return request(' api/devicerecipe/list', { + method: 'POST', + data: { + deviceId: id + } + }); + }, + // 设备下拉 + selectlist(){ + return request('/api/devicesinfo/selectlist',{ + method:'GET' + }) + } +} \ No newline at end of file diff --git a/frontend/src/api/Material.ts b/frontend/src/api/Material.ts new file mode 100644 index 0000000..8853278 --- /dev/null +++ b/frontend/src/api/Material.ts @@ -0,0 +1,334 @@ +import { request } from '@umijs/max'; + +export default { + /** + * 物料列表 + * @param params + * @returns + */ + MaterialList(params: MaterialTypes.MaterialPageListParams) { + return request('/erp/material/Material/GetMaterialPage', { + method: 'POST', + data: { + ...params + } + }); + }, + + /** + * 根据Id获取物料信息 + * @param id + */ + GetMaterialById(id: string) { + return request(`/erp/material/Material/GetMaterialById?id=${id}`, { + method: 'GET' + }); + }, + + /** + * 新增物料 + * @param params + * @returns + */ + AddMaterial(params: MaterialTypes.MaterialItemEA) { + return request('/erp/material/Material/AddMaterial', { + method: 'POST', + data: { + ...params + } + }); + }, + + /** + * 修改物料 + * @param params + * @returns + */ + UpdateMaterial(params: MaterialTypes.MaterialItemEA) { + return request('/erp/material/Material/UpdateMaterial', { + method: 'POST', + data: { + ...params + } + }); + }, + + /** + * 修改物料价格 + * @param params + * @returns + */ + UpdateMateriaPrice(params: MaterialTypes.MaterialPriceParams) { + return request('/erp/material/Material/UpdateMateriaPrice', { + method: 'POST', + data: { + ...params + } + }); + }, + + + /** + * 扩展属性分页列表 + * @param params + * @returns + */ + GetExtendAttributePage(params: MaterialTypes.ExtendAttributePageParams) { + return request('/erp/material/ExtendAttribute/GetExtendAttributePage', { + method: 'POST', + data: { + ...params + } + }); + }, + + /** + * 添加扩展属性 + * @param params + * @returns + */ + AddExtendAttribute(params: MaterialTypes.ExtendAttributeItem) { + return request('/erp/material/ExtendAttribute/AddExtendAttribute', { + method: 'POST', + data: { + ...params + } + }); + }, + + /** + * 修改扩展属性 + * @param params + */ + UpdateExtendAttribute(params: MaterialTypes.ExtendAttributeItem) { + return request('/erp/material/ExtendAttribute/UpdateExtendAttribute', { + method: 'POST', + data: { + ...params + } + }); + }, + + /** + * 根据获取扩展属性id获取扩展属性 + * @param id + * @returns + */ + GetExtendAttributeById(id: string) { + return request(`/erp/material/ExtendAttribute/GetExtendAttributeById?id=${id}`, { + method: 'GET' + }); + }, + + /** + * 根据物料ID查询物料扩展属性列表 + * @param materialId + * @returns + */ + GetMaterialExtendAttributeById(materialId: string) { + return request(`/erp/material/MaterialExtend/GetMaterialExtendAttributeById/${materialId}`, { + method: 'GET' + }); + }, + + /** + * 新增物料的扩展属性信息 + * @param params + * @returns + */ + AddMaterialExtendAttribute(params: MaterialTypes.MaterialExtendAttributeItem) { + return request('/erp/material/MaterialExtend/AddMaterialExtendAttribute', { + method: 'POST', + data: { + ...params + } + }); + }, + + /** + * 编辑物料的扩展属性信息 + * @param params + */ + UpdateMaterialExtendAttribute(params: MaterialTypes.MaterialExtendAttributeItem) { + return request('/erp/material/MaterialExtend/UpdateMaterialExtendAttribute', { + method: 'POST', + data: { + ...params + } + }); + }, + + /** + * 获取物料类型分页列表 + * @param params + */ + GetMaterialTypePage(params: MaterialTypes.MaterialTypeParams) { + return request('/erp/material/MaterialType/GetMaterialTypePage', { + method: 'POST', + data: { + ...params + } + }); + }, + + /** + * 新增物料类型 + * @param params + * @returns + */ + AddMaterialType(params: MaterialTypes.MaterialType) { + return request('/erp/material/MaterialType/AddMaterialType', { + method: 'POST', + data: { + ...params + } + }); + }, + + /** + * 更新物料类型 + * @param params + * @returns + */ + UpdateMaterialType(params: MaterialTypes.MaterialType) { + return request('/erp/material/MaterialType/UpdateMaterialType', { + method: 'POST', + data: { + ...params + } + }); + }, + + /** + * 根据物料类型Id获取物料的拓展信息 + * @param id + */ + GetMaterialTypeExtendAttributeById(id: string) { + return request(`/erp/material/MaterialType/GetMaterialTypeExtendAttributeById?Id=${id}`, { + method: 'GET' + }); + }, + + /** + * 新增物料类型的拓展信息 + * @param params + * @returns + */ + AddMaterialTypeExtendAttribute(params: MaterialTypes.MaterialTypeExtend) { + return request('/erp/material/MaterialTypeExtend/AddMaterialTypeExtendAttribute', { + method: 'POST', + data: { + ...params + } + }); + }, + + /** + * 更新物料类型扩展信息 + * @param params + * @returns + */ + UpdateMaterialTypeExtendAttribute(params: MaterialTypes.MaterialTypeExtend) { + return request('/erp/material/MaterialTypeExtend/UpdateMaterialTypeExtendAttribute', { + method: 'POST', + data: { + ...params + } + }); + }, + + /** + * 根据物料Id查询物料的修改记录 + * @param params + * @returns + */ + MeterialModifyPage(params: MaterialTypes.MaterialModifyPageParams) { + return request(`/erp/material/MeterialModify/MeterialModifyPage`, { + method: 'POST', + data: { + ...params + } + }); + }, + + /** + * 新增物料修改记录 + * @param params + * @returns + */ + AddMeterialModify(params: MaterialTypes.MaterialModify) { + return request('/erp/material/MeterialModify/AddMeterialModify', { + method: 'POST', + data: { + ...params + } + }); + }, + + /** + * 根据物料Id获取物料单位的换算列表 + * @param id + * @returns + */ + GetUnitTransformationsById(id: string) { + return request(`/erp/material/UnitTransformation/GetUnitTransformationsById?Id=${id}`, { + method: 'GET' + }); + }, + + /** + * 添加物料换算 + * @param params + * @returns + */ + AddUnitTransformation(params: MaterialTypes.MaterialUnitTransform) { + return request('/erp/material/UnitTransformation/AddUnitTransformation', { + method: 'POST', + data: { + ...params + } + }); + }, + + /** + * 编辑物料换算 + * @param params + * @returns + */ + UpdateUnitTransformation(params: MaterialTypes.MaterialUnitTransform) { + return request('/erp/material/UnitTransformation/UpdateUnitTransformation', { + method: 'POST', + data: { + ...params + } + }); + }, + + + /** + * 导出物料模板 + * @param materialTypeId + * @returns + */ + MaterialTemplateExport(materialTypeId: string) { + return request(`/erp/material/Material/MaterialTemplateExport?materialTypeId=${materialTypeId}`, { + method: 'GET', + responseType: 'blob' + }); + }, + + /** + * 导出物料数据 + * @param params + * @returns + */ + MaterialDataExport(params: MaterialTypes.ExportMaterialParams) { + return request('/erp/material/Material/MaterialDataExport', { + method: 'POST', + responseType: 'blob', + data: { + ...params + } + }); + } +} \ No newline at end of file diff --git a/frontend/src/api/StockService.ts b/frontend/src/api/StockService.ts new file mode 100644 index 0000000..5c44644 --- /dev/null +++ b/frontend/src/api/StockService.ts @@ -0,0 +1,119 @@ + +import { request } from '@umijs/max'; + + +export default { + /** + * 新增料仓 + * @param parms + * @returns + */ + Add(parms: StockTypes.Info) { + return request('/api/stockinfo/add', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 删除 + * @param parms + * @returns + */ + Del(parms: StockTypes.StockInfoDelInput) { + return request(`/api/stockinfo/del`, { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 修改 + * @param parms + * @returns + */ + Update(parms: StockTypes.Info) { + return request('/api/stockinfo/update', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 详情 + * @param parms + * @returns + */ + Detail(id: string) { + return request(`/api/stockinfo/detail?id=${id}`, { + method: 'GET' + }); + }, + /** + * 获取列表 + * @param parms + * @returns + */ + List() { + return request('/api/stockinfo/list', { + method: 'POST' + }); + }, + /** + * 未绑定的设备列表 + * @param parms + * @returns + */ + UnBindList() { + return request('/api/stockinfo/UnBindList', { + method: 'GET' + }); + + }, + /** + * 分页查询 + * @param parms + * @returns + */ + PagedList(parms: StockTypes.Page) { + return request('/api/stockinfo/pagedlist', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + // /** + // * 批量更新 + // * @param parms + // * @returns + // */ + // BatchUpdate(parms: StockTypes.BatchAdd) { + // return request('/api/Stockrecipe/batchupdate', { + // method: 'POST', + // data: parms + // }); + // }, + /** + * 根据设备Id查询配方信息 + * @param parms + * @returns + */ + RecipeList(id: string){ + return request(' api/stockrecipe/list', { + method: 'POST', + data: { + StockId: id + } + }); + }, + // 料仓下拉列表 + selectlist(){ + return request('/api/stockinfo/selectlist',{ + method :'GET' + }) + } +} \ No newline at end of file diff --git a/frontend/src/api/agvbasicService.ts b/frontend/src/api/agvbasicService.ts new file mode 100644 index 0000000..6ea776c --- /dev/null +++ b/frontend/src/api/agvbasicService.ts @@ -0,0 +1,60 @@ +import { request } from '@umijs/max'; + +// agv点位基础数据 +export default { + //创建分组 + Add(parms: AgvbasicInfoTypes.Info) { + return request('/api/agvpoint/add', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + //删除 + Del(parms: AgvbasicInfoTypes.Info) { + return request(`/api/agvpoint/del`, { + method: 'POST', + data: { + ...parms, + }, + }); + }, + //修改 + Update(parms: AgvbasicInfoTypes.Info) { + return request('/api/agvpoint/update', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + //列表 + List() { + return request('/api/agvpoint/list', { + method: 'POST', + }); + }, + /** + * 分页查询 + * @param parms + * @returns + */ + PagedList(parms: AgvbasicInfoTypes.Page) { + return request('/api/agvpoint/pagedlist', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + // 下拉 + selectlist() { + return request('/api/agvpoint/selectlist', { + method: 'GET' + } + + ) + } +} + diff --git a/frontend/src/api/agvlineService.ts b/frontend/src/api/agvlineService.ts new file mode 100644 index 0000000..5e1d7f4 --- /dev/null +++ b/frontend/src/api/agvlineService.ts @@ -0,0 +1,60 @@ +import { request } from '@umijs/max'; + +// +export default { + //创建分组 + Add(parms: AgvlineInfoTypes.Info) { + return request('/api/agvline/add', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + //删除 + Del(parms: AgvlineInfoTypes.Info) { + return request(`/api/agvline/del`, { + method: 'POST', + data: { + ...parms, + }, + }); + }, + //修改 + Update(parms: AgvlineInfoTypes.Info) { + return request('/api/agvline/update', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + //列表 + List() { + return request('/api/agvline/list', { + method: 'POST', + }); + }, + /** + * 分页查询 + * @param parms + * @returns + */ + PagedList(parms: AgvlineInfoTypes.Page) { + return request('/api/agvline/pagedlist', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + // 下拉 + selectlist() { + return request('/api/agvline/selectlist', { + method: 'GET' + } + + ) + } +} + diff --git a/frontend/src/api/craftsinfo.ts b/frontend/src/api/craftsinfo.ts new file mode 100644 index 0000000..c365305 --- /dev/null +++ b/frontend/src/api/craftsinfo.ts @@ -0,0 +1,159 @@ +import { Pztj_CraftStepsAddInput } from './../types/Crafts.d'; + +import { request } from '@umijs/max'; + +// 工艺 +export default { + /** + * 新增 + * @param parms + * @returns + */ + Add(parms: CraftsTypes.Info) { + return request('/api/craftsinfo/add', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 删除 + * @param parms + * @returns + */ + Del(parms: CraftsTypes.craftsInfoDelInput) { + return request(`/api/craftsinfo/del`, { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 修改 + * @param parms + * @returns + */ + Update(parms: CraftsTypes.Info) { + return request('/api/craftsinfo/update', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + + + + /** + * 详情 + * @param parms + * @returns + */ + Detail(id: string) { + return request(`/api/craftsinfo/detail?id=${id}`, { + method: 'GET' + }); + }, + /** + * 获取列表 + * @param parms + * @returns + */ + List() { + return request('/api/craftsinfo/list', { + method: 'POST' + }); + }, + /** + * 未绑定的设备列表 + * @param parms + * @returns + */ + UnBindList() { + return request('/api/craftsinfo/UnBindList', { + method: 'GET' + }); + + }, + /** + * 分页查询 + * @param parms + * @returns + */ + PagedList(parms: CraftsTypes.Page) { + return request('/api/craftsinfo/pagedlist', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 批量更新 + * @param parms + * @returns + */ + BatchUpdate(parms: CraftsTypes.BatchAdd) { + return request('/api/craftsrecipe/batchupdate', { + method: 'POST', + data: parms + }); + }, + // 下拉 + selectlist() { + return request('/api/craftsinfo/selectlist', { + method: 'GET', + + }) + }, + BatchAdd(parms :CraftsTypes.Pztj_CraftStepsAddInput[]){ + return request('',{ + method: 'POST', + data:{...parms} + }) + }, + //根据工艺查询步骤 + craftsStepPage(parms: CraftsTypes.Pztj_CraftStepsPageInput){ + return request(`/api/craftssteps/pagedlist`, { + method: 'POST', + data:{...parms} + }) + }, + //根据批量更新步骤 + BatchUpdateStep(parms :CraftsTypes.craftsInfoUpdateInput[]){ + return request('/api/craftssteps/batchupdate',{ + method: 'POST', + data: parms + }) + }, + //更新步骤 + UpdateStep(parms:CraftsTypes.craftsInfoUpdateInput){ + return request('/api/craftssteps/update',{ + method: 'POST', + data: parms + }) + }, + /** + * 删除 + * @param parms + * @returns + */ + DelStep(parms: CraftsTypes.craftsInfoDelInput) { + return request(`/api/craftssteps/del`, { + method: 'POST', + data: { + ...parms, + }, + }); + }, + //增加步骤 + StepAdd(parms : CraftsTypes.Pztj_CraftStepsAddInput){ + return request('/api/craftssteps/add',{ + method: 'POST', + data: parms + }) + } +} + diff --git a/frontend/src/api/deviceInfo/dtos/deviceProduct.d.ts b/frontend/src/api/deviceInfo/dtos/deviceProduct.d.ts new file mode 100644 index 0000000..fcdf087 --- /dev/null +++ b/frontend/src/api/deviceInfo/dtos/deviceProduct.d.ts @@ -0,0 +1,72 @@ +declare namespace deviceProduct { + /** + * 基类 + */ + type base_dto = { + /** + * 编码 + */ + code: string; + /** + * 描述 + */ + description?: null | string; + /** + * 名称 + */ + name: string; + + params:string; + } + /** + * 增加输入参数 + */ + type addInput = base_dto + /** + * 更新输入参数 + */ + interface updateInput extends base_dto { + /** + * 主键 + */ + id: string + } + /** + * 删除输入参数 + */ + interface delInput { + /** + * 主键 + */ + id: string + } + /** + * 查询输入参数 + */ + interface queryParms { + /** + * 名称 + */ + name?: null | string; + deviceProductId? : null | string; + code? : null | string; + + } + /** + * 查询分页输入参数 + */ + interface queryPage { + pageIndex: number, + pageSize: number, + name:string + } + /** + * 查询输出参数 + */ + interface output extends base_dto { + /** + * 主键 + */ + id: string + } +} \ No newline at end of file diff --git a/frontend/src/api/deviceInfo/dtos/deviceProductFunction.d.ts b/frontend/src/api/deviceInfo/dtos/deviceProductFunction.d.ts new file mode 100644 index 0000000..29798bf --- /dev/null +++ b/frontend/src/api/deviceInfo/dtos/deviceProductFunction.d.ts @@ -0,0 +1,77 @@ +declare namespace deviceProductFunction { + /** + * 基类 + */ + type base_dto = { + + /** + * 设备产品Id + */ + deviceProductId:string; + /** + * 编码 + */ + code: string; + /** + * 描述 + */ + description?: null | string; + /** + * 名称 + */ + name: string; + params:string; + } + /** + * 增加输入参数 + */ + type addInput = base_dto + /** + * 更新输入参数 + */ + interface updateInput extends base_dto { + /** + * 主键 + */ + id: string + } + /** + * 删除输入参数 + */ + interface delInput { + /** + * 主键 + */ + id: string + } + /** + * 查询输入参数 + */ + interface queryParms { + /** + * 名称 + */ + name?: null | string; + deviceProductId?: null | string; + } + /** + * 查询分页输入参数 + */ + interface queryPage { + pageIndex: number, + pageSize: number, + /** + * 设备产品Id + */ + deviceProductId?: null | string; + } + /** + * 查询输出参数 + */ + interface output extends base_dto { + /** + * 主键 + */ + id: string + } +} \ No newline at end of file diff --git a/frontend/src/api/deviceInfo/dtos/deviceProductParm.d.ts b/frontend/src/api/deviceInfo/dtos/deviceProductParm.d.ts new file mode 100644 index 0000000..91e626a --- /dev/null +++ b/frontend/src/api/deviceInfo/dtos/deviceProductParm.d.ts @@ -0,0 +1,74 @@ +declare namespace deviceProductParm { + /** + * 基类 + */ + type base_dto = { + /** + * 设备产品Id + */ + deviceProductId:string; + /** + * 编码 + */ + code: string; + /** + * 描述 + */ + description?: null | string; + /** + * 名称 + */ + name: string; + } + /** + * 增加输入参数 + */ + type addInput = base_dto + /** + * 更新输入参数 + */ + interface updateInput extends base_dto { + /** + * 主键 + */ + id: string + } + /** + * 删除输入参数 + */ + interface delInput { + /** + * 主键 + */ + id: string + } + /** + * 查询输入参数 + */ + interface queryParms { + /** + * 名称 + */ + name?: null | string; + } + /** + * 查询分页输入参数 + */ + interface queryPage { + pageIndex: number, + pageSize: number, + /** + * 设备产品Id + */ + deviceProductId:string; + } + /** + * 查询输出参数 + */ + interface output extends base_dto { + /** + * 主键 + */ + id: string + } +} \ No newline at end of file diff --git a/frontend/src/api/deviceInfo/services/deviceProduct.ts b/frontend/src/api/deviceInfo/services/deviceProduct.ts new file mode 100644 index 0000000..bd0a203 --- /dev/null +++ b/frontend/src/api/deviceInfo/services/deviceProduct.ts @@ -0,0 +1,88 @@ + +import { request } from '@umijs/max'; + + +export default { + /** + * 新增 + * @param parms + * @returns + */ + Add(parms: deviceProduct.addInput) { + return request('/api/deviceProduct/add', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 删除 + * @param parms + * @returns + */ + Del(parms: deviceProduct.delInput) { + return request(`/api/deviceProduct/del`, { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 修改 + * @param parms + * @returns + */ + Update(parms: deviceProduct.updateInput) { + return request('/api/deviceProduct/update', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 详情 + * @param parms + * @returns + */ + Detail(id: string) { + return request(`/api/deviceProduct/detail?id=${id}`, { + method: 'GET' + }); + }, + /** + * 获取列表 + * @param parms + * @returns + */ + List(parms: deviceProduct.queryParms) { + return request('/api/deviceProduct/list', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 分页查询 + * @param parms + * @returns + */ + PagedList(parms: deviceProduct.queryPage) { + return request('/api/deviceProduct/pagedlist', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + SelectList(){ + return request('/api/deviceProduct/selectlist', { + method: 'GET', + }); + } + +} + diff --git a/frontend/src/api/deviceInfo/services/deviceProductFunction.ts b/frontend/src/api/deviceInfo/services/deviceProductFunction.ts new file mode 100644 index 0000000..07e9e93 --- /dev/null +++ b/frontend/src/api/deviceInfo/services/deviceProductFunction.ts @@ -0,0 +1,83 @@ + +import { request } from '@umijs/max'; + + +export default { + /** + * 新增 + * @param parms + * @returns + */ + Add(parms: deviceProductFunction.addInput) { + return request('/api/deviceproductfunction/add', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 删除 + * @param parms + * @returns + */ + Del(parms: deviceProductFunction.delInput) { + return request(`/api/deviceproductfunction/del`, { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 修改 + * @param parms + * @returns + */ + Update(parms: deviceProductFunction.updateInput) { + return request('/api/deviceproductfunction/update', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 详情 + * @param parms + * @returns + */ + Detail(id: string) { + return request(`/api/deviceproductfunction/detail?id=${id}`, { + method: 'GET' + }); + }, + /** + * 获取列表 + * @param parms + * @returns + */ + List(parms: deviceProductFunction.queryParms) { + return request('/api/deviceproductfunction/list', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 分页查询 + * @param parms + * @returns + */ + PagedList(parms: deviceProductFunction.queryPage) { + return request('/api/deviceproductfunction/pagedlist', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + +} + diff --git a/frontend/src/api/deviceInfo/services/deviceProductParm.ts b/frontend/src/api/deviceInfo/services/deviceProductParm.ts new file mode 100644 index 0000000..aeb348a --- /dev/null +++ b/frontend/src/api/deviceInfo/services/deviceProductParm.ts @@ -0,0 +1,83 @@ + +import { request } from '@umijs/max'; + + +export default { + /** + * 新增 + * @param parms + * @returns + */ + Add(parms: deviceProductParm.addInput) { + return request('/api/deviceProductParm/add', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 删除 + * @param parms + * @returns + */ + Del(parms: deviceProductParm.delInput) { + return request(`/api/deviceProductParm/del`, { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 修改 + * @param parms + * @returns + */ + Update(parms: deviceProductParm.updateInput) { + return request('/api/deviceProductParm/update', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 详情 + * @param parms + * @returns + */ + Detail(id: string) { + return request(`/api/deviceProductParm/detail?id=${id}`, { + method: 'GET' + }); + }, + /** + * 获取列表 + * @param parms + * @returns + */ + List(parms: deviceProductParm.queryParms) { + return request('/api/deviceProductParm/list', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 分页查询 + * @param parms + * @returns + */ + PagedList(parms: deviceProductParm.queryPage) { + return request('/api/deviceProductParm/pagedlist', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + +} + diff --git a/frontend/src/api/dictType/dto.d.ts b/frontend/src/api/dictType/dto.d.ts new file mode 100644 index 0000000..d12b187 --- /dev/null +++ b/frontend/src/api/dictType/dto.d.ts @@ -0,0 +1,145 @@ +declare namespace dictType { + /** + * 基类 + */ + type base_dto = { + /** + * 编码 + */ + code?: null | string; + /** + * 描述 + */ + sort?: null | string; + /** + * 名称 + */ + name?: null | string; + } + /** + * 增加输入参数 + */ + type addInput = base_dto + /** + * 更新输入参数 + */ + interface updateInput extends base_dto { + /** + * 主键 + */ + id: string + } + /** + * 删除输入参数 + */ + interface delInput { + /** + * 主键 + */ + id: string + } + /** + * 查询输入参数 + */ + interface queryParms { + /** + * 名称 + */ + name?: null | string; + } + /** + * 查询分页输入参数 + */ + interface queryPage { + pageIndex: number, + pageSize: number, + name:string, + code:string + } + /** + * 查询输出参数 + */ + interface output extends base_dto { + /** + * 主键 + */ + id: string + } +} +declare namespace dictData { + /** + * 基类 + */ + type base_dto = { + /** + * 编码 + */ + code?: null | string; + /** + * 描述 + */ + sort?: null | string; + /** + * 名称 + */ + value?: null | string; + /** + * 类型id + */ + typeId?: null |string; + + } + /** + * 增加输入参数 + */ + type addInput = base_dto + /** + * 更新输入参数 + */ + interface updateInput extends base_dto { + /** + * 主键 + */ + id: string + typeId:string + } + /** + * 删除输入参数 + */ + interface delInput { + /** + * 主键 + */ + id: string + } + /** + * 查询输入参数 + */ + interface queryParms { + /** + * 名称 + */ + name?: null | string; + typeId?: null|string, + typeCode?: null | string , + id?: null | string + } + /** + * 查询分页输入参数 + */ + interface queryPage { + pageIndex: number , + pageSize: number, + name:string, + typeId:string + } + /** + * 查询输出参数 + */ + interface output extends base_dto { + /** + * 主键 + */ + id: string + } +} \ No newline at end of file diff --git a/frontend/src/api/dictType/service.ts b/frontend/src/api/dictType/service.ts new file mode 100644 index 0000000..c598468 --- /dev/null +++ b/frontend/src/api/dictType/service.ts @@ -0,0 +1,164 @@ + +import { request } from '@umijs/max'; + + +const dictTypeApi= { + /** + * 新增 + * @param parms + * @returns + */ + Add(parms: dictType.addInput) { + return request('/api/dictType/add', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 删除 + * @param parms + * @returns + */ + Del(parms: dictType.delInput) { + return request(`/api/dictType/del`, { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 修改 + * @param parms + * @returns + */ + Update(parms: dictType.updateInput) { + return request('/api/dictType/update', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 详情 + * @param parms + * @returns + */ + Detail(id: string) { + return request(`/api/dictType/detail?id=${id}`, { + method: 'GET' + }); + }, + /** + * 获取列表 + * @param parms + * @returns + */ + List(parms: dictType.queryParms) { + return request('/api/dictType/list', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 分页查询 + * @param parms + * @returns + */ + PagedList(parms: dictType.queryPage) { + return request('/api/dictType/pagedlist', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + +} + +const dictDataApi= { + /** + * 新增 + * @param parms + * @returns + */ + Add(parms: dictData.addInput) { + return request('/api/dictData/add', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 删除 + * @param parms + * @returns + */ + Del(parms: dictData.delInput) { + return request(`/api/dictData/del`, { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 修改 + * @param parms + * @returns + */ + Update(parms: dictData.updateInput) { + return request('/api/dictData/update', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 详情 + * @param parms + * @returns + */ + Detail(id: string) { + return request(`/api/dictData/detail?id=${id}`, { + method: 'GET' + }); + }, + /** + * 获取列表 + * @param parms + * @returns + */ + List(parms: dictData.queryParms) { + return request('/api/dictData/list', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 分页查询 + * @param parms + * @returns + */ + PagedList(parms: dictData.queryPage) { + return request('/api/dictData/pagedlist', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + +} + +export {dictTypeApi,dictDataApi} + diff --git a/frontend/src/api/finalService.ts b/frontend/src/api/finalService.ts new file mode 100644 index 0000000..3f0f9cf --- /dev/null +++ b/frontend/src/api/finalService.ts @@ -0,0 +1,123 @@ + +import { request } from '@umijs/max'; + + +export default { + /** + * 新增 + * @param parms + * @returns + */ + Add(parms: FinalTypes.Info) { + return request('/api/finalsinfo/add', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 删除 + * @param parms + * @returns + */ + Del(parms: FinalTypes.FinalInfoDelInput) { + return request(`/api/finalsinfo/del`, { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 修改 + * @param parms + * @returns + */ + Update(parms: FinalTypes.Info) { + return request('/api/finalsinfo/update', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 详情 + * @param parms + * @returns + */ + Detail(id: string) { + return request(`/api/finalsinfo/detail?id=${id}`, { + method: 'GET' + }); + }, + /** + * 获取列表 + * @param parms + * @returns + */ + List() { + return request('/api/finalsinfo/list', { + method: 'POST' + }); + }, + /** + * 获取列表 + * @param parms + * @returns + */ + SelectList() { + return request('/api/finalsinfo/selectlist', { + method: 'GET' + }); + }, + /** + * 未绑定的设备列表 + * @param parms + * @returns + */ + UnBindList() { + return request('/api/finalsinfo/UnBindList', { + method: 'GET' + }); + + }, + /** + * 分页查询 + * @param parms + * @returns + */ + PagedList(parms: FinalTypes.Page) { + return request('/api/finalsinfo/pagedlist', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 批量更新 + * @param parms + * @returns + */ + BatchUpdate(parms: FinalTypes.BatchAdd) { + return request('/api/finalsinfo/batchupdate', { + method: 'POST', + data: parms + }); + }, + /** + * 根据设备Id查询配方信息 + * @param parms + * @returns + */ + RecipeList(id: string){ + return request(' api/finalsinfo/list', { + method: 'POST', + data: { + deviceId: id + } + }); + } +} \ No newline at end of file diff --git a/frontend/src/api/groupService.ts b/frontend/src/api/groupService.ts new file mode 100644 index 0000000..0edc4af --- /dev/null +++ b/frontend/src/api/groupService.ts @@ -0,0 +1,60 @@ +import { request } from '@umijs/max'; + + +export default { + //创建分组 + Add(parms: GroupInfoTypes.Info) { + return request('/api/groupinfo/add', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + //删除 + Del(parms: GroupInfoTypes.Info) { + return request(`/api/groupinfo/del`, { + method: 'POST', + data: { + ...parms, + }, + }); + }, + //修改 + Update(parms: GroupInfoTypes.Info) { + return request('/api/groupinfo/update', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + //列表 + List() { + return request('/api/groupinfo/list', { + method: 'POST', + }); + }, + /** + * 分页查询 + * @param parms + * @returns + */ + PagedList(parms: GroupInfoTypes.Page) { + return request('/api/groupinfo/pagedlist', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + // 下拉 + selectlist() { + return request('/api/groupinfo/selectlist', { + method: 'GET' + } + + ) + } +} + diff --git a/frontend/src/api/kepService.ts b/frontend/src/api/kepService.ts new file mode 100644 index 0000000..5af41c2 --- /dev/null +++ b/frontend/src/api/kepService.ts @@ -0,0 +1,48 @@ +import { request } from '@umijs/max'; + + +export default { + + + Getdatavalarmlimitpage(params) { + return request('/api/kepdata/getdatavalarmlimitlist', { + method: 'POST', + data: { + ...params + } + }); + }, + Adddatavalarmlimit(params) { + return request('/api/kepdata/adddatavalarmlimit', { + method: 'POST', + data: { + ...params + } + }); + }, + Updatedatavalarmlimit(params) { + return request('/api/kepdata/updatedatavalarmlimit', { + method: 'POST', + data: { + ...params + } + }); + }, + Del(parms) { + return request(`/api/kepdata/deldatavalarmlimitlist/`+parms, { + method: 'POST', + }); + }, + getdatavData() { + return request(`/api/kepdata/getdatavlist`, { + method: 'GET', + }); + }, + getlogs() { + return request(`/api/kepdata/getlogs`, { + method: 'GET', + }); + } + +} + diff --git a/frontend/src/api/logs/dto.d.ts b/frontend/src/api/logs/dto.d.ts new file mode 100644 index 0000000..b014fad --- /dev/null +++ b/frontend/src/api/logs/dto.d.ts @@ -0,0 +1,316 @@ +declare namespace alarmlog { + /** + * 基类 + */ + type base_dto = { + /** + * 报警信息 + */ + msgInfo?: null | string; + /** + * 报警值 + */ + value?: null | string; + /** + * 报警等级 + */ + grade?: null | string; + /** + * 设备名称 + */ + deviceName?: null | string; + createDate: string + } + /** + * 增加输入参数 + */ + type addInput = base_dto + /** + * 更新输入参数 + */ + interface updateInput extends base_dto { + /** + * 主键 + */ + id: string + } + /** + * 删除输入参数 + */ + interface delInput { + /** + * 主键 + */ + id: string + } + /** + * 查询输入参数 + */ + interface queryParms { + /** + * 名称 + */ + name?: null | string; + } + /** + * 查询分页输入参数 + */ + interface queryPage { + pageIndex: number, + pageSize: number, + /** + * 报警信息 + */ + msgInfo?: null | string; + /** + * 报警值 + */ + value?: null | string; + /** + * 报警等级 + */ + grade?: null | string; + /** + * 设备名称 + */ + deviceName?: null | string; + startTime?: Date | null + endTime?: Date | null, + } + /** + * 查询输出参数 + */ + interface output extends base_dto { + /** + * 主键 + */ + id: string + } +} +declare namespace programlog { + /** + * 基类 + */ + type base_dto = { + /** + * 类型 + */ + logType?: null | number; + /** + * 日志消息 + */ + msgInfo?: null | string; + createDate: string; + } + /** + * 增加输入参数 + */ + type addInput = base_dto + /** + * 更新输入参数 + */ + interface updateInput extends base_dto { + /** + * 主键 + */ + id: string + } + /** + * 删除输入参数 + */ + interface delInput { + /** + * 主键 + */ + id: string + } + /** + * 查询输入参数 + */ + interface queryParms { + /** + * 日志消息 + */ + msgInfo?: null | string; + } + /** + * 查询分页输入参数 + */ + interface queryPage { + pageIndex: number, + pageSize: number, + /** + * 编码 + */ + logType?: null | number; + /** + * 日志消息 + */ + msgInfo?: null | string; + + startTime?: Date | null; + endTime?: Date | null + } + /** + * 查询输出参数 + */ + interface output extends base_dto { + /** + * 主键 + */ + id: string + } +} +declare namespace userlog { + /** + * 基类 + */ + type base_dto = { + /** + * 权限 + */ + permission?: null | string; + /** + * 用户名 + */ + userName?: null | string; + /** + * 日志消息 + */ + msgInfo?: null | string; + + createDate: string; + + } + /** + * 增加输入参数 + */ + type addInput = base_dto + /** + * 更新输入参数 + */ + interface updateInput extends base_dto { + /** + * 主键 + */ + id: string + typeId: string + } + /** + * 删除输入参数 + */ + interface delInput { + /** + * 主键 + */ + id: string + } + /** + * 查询输入参数 + */ + interface queryParms { + /** + * 名称 + */ + name?: null | string; + } + /** + * 查询分页输入参数 + */ + interface queryPage { + pageIndex: number, + pageSize: number, + /** + * 用户名 + */ + userName?: null | string; + /** + * 日志消息 + */ + msgInfo?: null | string; + } + /** + * 查询输出参数 + */ + interface output extends base_dto { + /** + * 主键 + */ + id: string + } +} +declare namespace runlog { + /** + * 基类 + */ + type base_dto = { + /** + * 日志类别 + */ + logType?: null | string; + /** + * 日志消息 + */ + msgInfo?: null | string; + createDate: string + + } + /** + * 增加输入参数 + */ + type addInput = base_dto + /** + * 更新输入参数 + */ + interface updateInput extends base_dto { + /** + * 主键 + */ + id: string + typeId: string + } + /** + * 删除输入参数 + */ + interface delInput { + /** + * 主键 + */ + id: string + } + /** + * 查询输入参数 + */ + interface queryParms { + /** + * 名称 + */ + name?: null | string; + } + /** + * 查询分页输入参数 + */ + interface queryPage { + pageIndex: number, + pageSize: number, + /** + * 日志类别 + */ + logType?: null | string; + /** + * 日志消息 + */ + msgInfo?: null | string; + startTime?: Date | null; + endTime?: Date | null + } + /** + * 查询输出参数 + */ + interface output extends base_dto { + /** + * 主键 + */ + id: string + } +} \ No newline at end of file diff --git a/frontend/src/api/logs/service.ts b/frontend/src/api/logs/service.ts new file mode 100644 index 0000000..572af08 --- /dev/null +++ b/frontend/src/api/logs/service.ts @@ -0,0 +1,338 @@ +import { request } from '@umijs/max'; + +/** + * 告警日志 + * @param parms + * @returns + */ +const alarmlogApi = { + /** + * 新增 + * @param parms + * @returns + */ + Add(parms: alarmlog.addInput) { + return request('/api/alarmlog/add', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 删除 + * @param parms + * @returns + */ + Del(parms: alarmlog.delInput) { + return request(`/api/alarmlog/del`, { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 修改 + * @param parms + * @returns + */ + Update(parms: alarmlog.updateInput) { + return request('/api/alarmlog/update', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 详情 + * @param parms + * @returns + */ + Detail(id: string) { + return request(`/api/alarmlog/detail?id=${id}`, { + method: 'GET' + }); + }, + /** + * 获取列表 + * @param parms + * @returns + */ + List(parms: alarmlog.queryParms) { + return request('/api/alarmlog/list', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 分页查询 + * @param parms + * @returns + */ + PagedList(parms: alarmlog.queryPage) { + return request('/api/alarmlog/pagedlist', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + +} +/** + * 系统日志 + * @param parms + * @returns + */ +const programlogApi = { + /** + * 新增 + * @param parms + * @returns + */ + Add(parms: programlog.addInput) { + return request('/api/programlog/add', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 删除 + * @param parms + * @returns + */ + Del(parms: programlog.delInput) { + return request(`/api/programlog/del`, { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 修改 + * @param parms + * @returns + */ + Update(parms: programlog.updateInput) { + return request('/api/programlog/update', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 详情 + * @param parms + * @returns + */ + Detail(id: string) { + return request(`/api/programlog/detail?id=${id}`, { + method: 'GET' + }); + }, + /** + * 获取列表 + * @param parms + * @returns + */ + List(parms: programlog.queryParms) { + return request('/api/programlog/list', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 分页查询 + * @param parms + * @returns + */ + PagedList(parms: programlog.queryPage) { + return request('/api/programlog/pagedlist', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + +} + +/** + * 操作日志 + * @param parms + * @returns + */ +const userlogApi = { + /** + * 新增 + * @param parms + * @returns + */ + Add(parms: userlog.addInput) { + return request('/api/userlog/add', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 删除 + * @param parms + * @returns + */ + Del(parms: userlog.delInput) { + return request(`/api/userlog/del`, { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 修改 + * @param parms + * @returns + */ + Update(parms: userlog.updateInput) { + return request('/api/userlog/update', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 详情 + * @param parms + * @returns + */ + Detail(id: string) { + return request(`/api/userlog/detail?id=${id}`, { + method: 'GET' + }); + }, + /** + * 获取列表 + * @param parms + * @returns + */ + List(parms: userlog.queryParms) { + return request('/api/userlog/list', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 分页查询 + * @param parms + * @returns + */ + PagedList(parms: userlog.queryPage) { + return request('/api/userlog/pagedlist', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + +} +/** + * 运行日志 + * @param parms + * @returns + */ +const runlogApi = { + /** + * 新增 + * @param parms + * @returns + */ + Add(parms: runlog.addInput) { + return request('/api/runlog/add', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 删除 + * @param parms + * @returns + */ + Del(parms: runlog.delInput) { + return request(`/api/runlog/del`, { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 修改 + * @param parms + * @returns + */ + Update(parms: runlog.updateInput) { + return request('/api/runlog/update', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 详情 + * @param parms + * @returns + */ + Detail(id: string) { + return request(`/api/runlog/detail?id=${id}`, { + method: 'GET' + }); + }, + /** + * 获取列表 + * @param parms + * @returns + */ + List(parms: runlog.queryParms) { + return request('/api/runlog/list', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 分页查询 + * @param parms + * @returns + */ + PagedList(parms: runlog.queryPage) { + return request('/api/runlog/pagedlist', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + +} + + +export { alarmlogApi, programlogApi, runlogApi, userlogApi } \ No newline at end of file diff --git a/frontend/src/api/materialService.ts b/frontend/src/api/materialService.ts new file mode 100644 index 0000000..efaa10f --- /dev/null +++ b/frontend/src/api/materialService.ts @@ -0,0 +1,70 @@ + + +import { request } from '@umijs/max'; + + + +export default { + //创建 + Add(parms: MaterialsTypes.Info) { + return request('/api/materialsinfo/add', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + + //删除 + + Del(parms: MaterialsTypes.MaterialsInfoDelInput) { + return request(`/api/materialsinfo/del`, { + method: 'POST', + data: { + ...parms, + }, + }); + }, + + //修改 + Update(parms: MaterialsTypes.Info) { + return request('/api/materialsinfo/update', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + + + //获取列表 + List() { + return request('/api/materialsinfo/list', { + method: 'GET', + }); + }, + + // 下拉列表 + selectlist(){ + return request ('/api/materialsinfo/selectlist' ,{ + method:'GET' + }) + }, + + + + /** + * 分页查询 + * @param parms + * @returns + */ + PagedList(parms: MaterialsTypes.Page) { + return request('/api/materialsinfo/pagedlist', { + method: 'POST', + data: { + ...parms, + }, + }); + } +} + diff --git a/frontend/src/api/orderService.ts b/frontend/src/api/orderService.ts new file mode 100644 index 0000000..0d17f47 --- /dev/null +++ b/frontend/src/api/orderService.ts @@ -0,0 +1,95 @@ +import { request } from '@umijs/max'; +import { List } from 'lodash'; + +export default { + + /** + * 分页查询 + * @param parms + * @returns + */ + PagedList(parms: OrderType.Page) { + return request('/api/order/pagedlist', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + + /** + * 添加 + * @param parms + * @returns + */ + Add(parms: OrderType.orderFinalsl[]) { + return request('/api/order/add', { + method: 'POST', + data: parms, + }); + }, + + /** + * 修改 + * @param parms + * @returns + */ + update(parms: OrderType.orderFinalsl[]) { + return request('/api/order/update', { + method: 'POST', + data: parms, + }); + }, + + /** + * 删除 + * @param parms + * @returns + */ + del(parms: string) { + return request('/api/order/del/'+parms, { + method: 'POST', + }); + }, + + + /** + * 獲取訂單的產品信息 + * @param parms + * @returns + */ + GetorderMaterial(parms: string) { + return request('/api/order/getordermaterial/' + parms, { + method: 'get', + }); + }, + + /** + * 生成工单 + * @param parms + * @returns + */ + orderassociationwork(parms: OrderType.orderFinalsl[]) { + return request('/api/order/orderassociationwork', { + method: 'POST', + data: parms, + }); + }, + + /** + * 获取成品可制造数量 + * @param parms + * @returns + */ + getFinalslLImit(parms:string) { + return request('/api/order/getfinalsllimit/'+parms, { + method: 'get', + }); + }, + +} + + + + + diff --git a/frontend/src/api/productlineService.ts b/frontend/src/api/productlineService.ts new file mode 100644 index 0000000..e197d5a --- /dev/null +++ b/frontend/src/api/productlineService.ts @@ -0,0 +1,124 @@ +import { request } from '@umijs/max'; + + +export default { + //创建产线 + Add(parms: ProductlineTypes.Info) { + return request('/api/productline/add', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + //删除 + Del(parms: ProductlineTypes.Info) { + return request(`/api/productline/del`, { + method: 'POST', + data: { + ...parms, + }, + }); + }, + //修改 + Update(parms: ProductlineTypes.Info) { + return request('/api/productline/update', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + //列表 + List() { + return request('/api/productline/list', { + method: 'GET', + }); + }, + /** + * 分页查询 + * @param parms + * @returns + */ + PagedList(parms: ProductlineTypes.Page) { + return request('/api/productline/pagedlist', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + // 下拉列表 + selectlist() { + return request('/api/productline/selectlist', { + method: 'GET', + + }); + }, + // 产线添加设备 + adddevice(parms: ProductlineTypes.Productlinedevice) { + return request('/api/productline/adddevice', { + method: 'POST', + data: { + ...parms, + } + }) + }, + // 产线添加料仓 + addstock(parms: ProductlineTypes.Productlinestock) { + return request('/api/productline/addstock', { + method: 'POST', + data: { + ...parms, + } + }) + }, + // 产线设备分页 + devicepagelist(parms: ProductlineTypes.Productionlinepaging) { + return request('/api/productline/devicepagelist', { + method: 'POST', + data: { + ...parms + } + }) + }, + // 产线设备列表 + devicelist(parms: ProductlineTypes.ProductionlineQuery) { + return request('/api/productline/devicelist', { + method: 'POST', + data: { + ...parms + } + }) + }, + // 产线料仓分页 + stockpagelist(parms: ProductlineTypes.Productionlinestockpaging) { + return request('/api/productline/stockpagelist', { + method: 'POST', + data: { + ...parms + } + }) + }, + // 产线删除设备 + + deletedevice(parms: ProductlineTypes.Productionlinedeletiondevice) { + return request('/api/productline/deletedevice', { + method: 'POST', + data: { + ...parms + } + }) + }, + // 产线删除料仓 + deletestock(parms: ProductlineTypes.Productionlinedeletstock) { + return request('/api/productline/deletestock', { + method: 'POST', + data: { + ...parms + } + }) + } +} + + diff --git a/frontend/src/api/recipeService.ts b/frontend/src/api/recipeService.ts new file mode 100644 index 0000000..570af4d --- /dev/null +++ b/frontend/src/api/recipeService.ts @@ -0,0 +1,90 @@ +import { request } from '@umijs/max'; + + +export default { + //创建配方 + Add(parms: RecipeTypes.Info) { + return request('/api/recipesinfo/add', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + //删除 + Del(parms: RecipeTypes.Info) { + return request(`/api/recipesinfo/del`, { + method: 'POST', + data: { + ...parms, + }, + }); + }, + + //修改角色 + Update(parms: RecipeTypes.Info) { + return request('/api/recipesinfo/update', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + + + //获取角色列表 + List() { + return request('/api/recipesinfo/list', { + method: 'GET', + }); + }, + + /** + * 角色分页查询 + * @param parms + * @returns + */ + PagedList(parms: RecipeTypes.Page) { + return request('/api/recipesinfo/pagedlist', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 获取配方物料列表 + * @param parms + * @returns + */ + MaterialList(parms:RecipeMaterialTypes.Info ){ + return request('/api/recipematerial/list', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + //批量创建物料信息 + BatchAdd(parms: RecipeMaterialTypes.Info[]){ + return request('/api/recipematerial/batchadd', { + method: 'POST', + data: parms + }); + }, + //更改分组 + ChangeGroup(parms: RecipeTypes.RecipesGroupInput){ + return request('/api/recipesinfo/changegroup', { + method: 'POST', + data: parms + }); + }, + // 下拉 + selectlist() { + return request('/api/recipesinfo/selectlist', { + method: 'GET', + + }) + } +} + diff --git a/frontend/src/api/reportService.ts b/frontend/src/api/reportService.ts new file mode 100644 index 0000000..f77ab36 --- /dev/null +++ b/frontend/src/api/reportService.ts @@ -0,0 +1,34 @@ +import { request } from '@umijs/max'; +import { List } from 'lodash'; + +export default { + + /** + * 获取产品统计 + * @param parms + * @returns + */ + PagedList(parms: ReportType.ReportInput) { + return request('/api/report/getproductreport', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + + /** + * 获取原料统计 + * @param parms + * @returns + */ + PagedMaterialList(parms: ReportType.ReportInput) { + return request('/api/report/getmaterialsreport', { + method: 'POST', + data: { + ...parms, + }, + }); + } + +} diff --git a/frontend/src/api/storeService.ts b/frontend/src/api/storeService.ts new file mode 100644 index 0000000..f3d1d1a --- /dev/null +++ b/frontend/src/api/storeService.ts @@ -0,0 +1,59 @@ + + +import { request } from '@umijs/max'; + + +export default { + //创建 + Add(parms: StoreTypes.StoreInfo) { + return request('/api/storeinfo/add', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + + //删除 + Del(parms: StoreTypes.StoreInfo) { + return request(`/api/storeinfo/del`, { + method: 'POST', + data: { + ...parms, + }, + }); + }, + + //修改角色 + Update(parms: StoreTypes.StoreInfo) { + return request('/api/storeinfo/update', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + + + //获取角色列表 + List() { + return request('/api/storeinfo/list', { + method: 'GET', + }); + }, + + /** + * 角色分页查询 + * @param parms + * @returns + */ + PagedList(parms: StoreTypes.StoreInfo) { + return request('/api/storeinfo/pagedlist', { + method: 'POST', + data: { + ...parms, + }, + }); + } +} + diff --git a/frontend/src/api/sys/dto.d.ts b/frontend/src/api/sys/dto.d.ts new file mode 100644 index 0000000..80631bb --- /dev/null +++ b/frontend/src/api/sys/dto.d.ts @@ -0,0 +1,146 @@ + + + // 账号 +declare namespace account { + type base_dto = { + id?: string | null | undefined; + /** + * + * @type {string} + * @memberof Account + */ + account?: string | null; + /** + * + * @type {string} + * @memberof Account + */ + pwd: string + /** + * + * @type {string} + * @memberof Account + */ + tB_Employee_Id?: string | null; + } + type updatePwdInput = { + /** + * + * @type {string} + * @memberof Account + */ + tB_Employee_Id: string; + /** + * + * @type {string} + * @memberof Account + */ + oldPwd: string; + /** + * + * @type {string} + * @memberof Account + */ + newPwd: string; + } + interface queryPage { + pageIndex:number, + pageSize:number + account:string + } +} + // 模块类型 +declare namespace moduleTypes { + + type ModuleType = { + category: number, + openType: number, + parentId: string, + name: string, + icon: string, + url: string, + sort: number, + isDisabled: boolean, + id: string, + children: ModuleType[] + } + +} + // 角色类型 +declare namespace RolelTypes { + + type RoleType = { + id?: string, + name: string, + description: string + } + + type RolePageParams = { + keyword: string, + sortName: string, + sortByAsc: boolean, + pageIndex: number, + pageSize: number + } +} +//人员 +declare namespace UserTypes { + // 登录参数类型 + type LoginParams = { + account: string, + pwd: string + } + + //人员数据类型 + type PersonnelType = { + account?:string|null + /** + * + * @type {string} + * @memberof TBEmployeeDTO + */ + id?: string | null; + /** + * 排序 + * @type {number} + * @memberof TBEmployeeDTO + */ + sort?: number; + /** + * 员工姓名 + * @type {string} + * @memberof TBEmployeeDTO + */ + name?: string | null; + /** + * 1男2女 + * @type {number} + * @memberof TBEmployeeDTO + */ + gender?: number; + + /** + * 1在职2出差3离职 + * @type {number} + * @memberof TBEmployeeDTO + */ + status?: number; + /** + * 角色Id + * @type {string} + * @memberof TBEmployeeDTO + */ + roleId?: string | null; + + isAccount?: null | boolean ; + } + + //人员分页查询参数 + type UserPageParams = { + name: string, + status: number?, + pageIndex: number, + pageSize: number, + gender: number?, + } +} \ No newline at end of file diff --git a/frontend/src/api/sys/service.ts b/frontend/src/api/sys/service.ts new file mode 100644 index 0000000..076f8d6 --- /dev/null +++ b/frontend/src/api/sys/service.ts @@ -0,0 +1,294 @@ +import { request } from '@umijs/max'; + +/* +* +*账号 +* +*/ +const accountApi={ + //创建 + Add(parms: account.base_dto) { + return request('/api/authorize/addaccount', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + //删除 + Del(parms: account.base_dto) { + return request(`/api/authorize/del`, { + method: 'POST', + data: { + ...parms, + }, + }); + }, + //修改 + Update(parms: account.base_dto) { + return request('/api/authorize/update', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + //列表 + List() { + return request('/api/authorize/list', { + method: 'POST', + }); + }, + /** + * 分页查询 + * @param parms + * @returns + */ + PagedList(parms: account.queryPage) { + return request('/api/authorize/accountpagelist', { + method: 'POST', + data: { + ...parms, + }, + }); + } +} + +/* +* +*模块 +* +*/ + +const moduleApi={ + //创建模块 + SaveCreateModule(params: moduleTypes.ModuleType) { + return request('/api/authorize/addmodule', { + method: 'POST', + data: { + ...params + } + }); + }, + + //获取模块视图 + GetTreeGridModule(params?: moduleTypes.ModuleType) { + return request(`/api/authorize/gettreegrid`, { + method: 'POST', + data:{ + ...params + } + }); + }, + + //修改模块 + SaveModifyModule(params: moduleTypes.ModuleType) { + return request('/api/authorize/editmodule', { + method: 'POST', + data: { + ...params + } + }); + }, + + //删除模块 + DeleteModule(id: string) { + return request(`/api/authorize/removemodule/${id}`, { + method: 'GET' + }); + }, +} + +/* +* +*角色 +* +*/ +const roleApi={ + //创建角色 + CreateRole(parms: RolelTypes.RoleType) { + return request('/api/authorize/addrole', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + + //删除角色 + DeleteRole(id: string) { + return request(`/api/authorize/removerole/${id}`, { + method: 'GET' + }); + }, + + //修改角色 + ModifyRole(parms: RolelTypes.RoleType) { + return request('/api/authorize/editrole', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + + + //获取角色列表 + GetRoleList() { + return request('/api/authorize/getroleList', { + method: 'GET', + }); + }, + + /** + * 角色分页查询 + * @param parms + * @returns + */ + GetRolePagedList(parms: RolelTypes.RolePageParams) { + return request('/api/authorize/queryrole', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /* + * + * 获取角色模块 + * + */ + GetRoleModuleList(roleId:string){ + return request(`/api/authorize/rolemodulelist/${roleId}`, { + method: 'GET', + }); + }, + /* + * + * 分配角色模块 + * + */ + AddRoleModule(parms:any){ + return request(`/api/authorize/addrolemodule`, { + method: 'POST', + data: { + ...parms, + }, + }); + } +} +/* +* +*人员 +* +*/ +const userApi={ + //登录 + Login(parms: UserTypes.LoginParams) { + return request('/api/authorize/login', { + method: 'POST', + data: { + ...parms + } + }); +}, + +//新增人员 +CreateUser(params: UserTypes.PersonnelType) { + return request('/api/authorize/addemployee', { + method: 'POST', + data: { + ...params, + }, + }); +}, + +//修改人员信息 +ModifyUser(params: UserTypes.PersonnelType) { + return request('/api/authorize/editemployee', { + method: 'POST', + data: { + ...params, + }, + }); +}, + + +//根据用户ID查询用户信息 +GetUserById(id: string) { + return request(`/api/base/user/getuserbyid?id=${id}`, { + method: 'GET', + }); +}, + +//人员分页查询 +GetUserPagedList(params: UserTypes.UserPageParams) { + return request('/api/authorize/queryemployee', { + method: 'POST', + data: { + ...params, + }, + }); +}, + +/** + * 获取用户已授权菜单 + */ +GetUserAuthInfo() { + return request('/api/base/authorize/getuserinfo', { + method: 'POST', + }); +}, + +GetUserInfo() { + return request('/api/authorize/getuserinfo', { + method: 'GET', + }); +}, +/** + * 删除用户 + * @param params + */ +RemoveUser(employeeId:string){ + return request(`/api/authorize/removeemployee?employeeId=${employeeId}`, { + method: 'GET' + }); +}, +/** + * 绑定账户 + * @param params + */ +BindAccount(params: account.base_dto) { + return request('/api/authorize/addaccountbyuser', { + method: 'POST', + data: { + ...params, + }, + }); +}, +/** + * 重置账户 + * @param params + * @returns + */ +RestoreAccount(params: string) { + return request(`/api/authorize/restoreaccountbyuser/${params}`, { + method: 'GET', + }); +}, +/** + * 编辑密码 + * @param params + * @returns + */ +EditPwd(params: account.updatePwdInput) { + return request(`/api/authorize/editaccountpwd`, { + method: 'POST', + data: { + ...params, + }, + }); +} +} + +export { accountApi,moduleApi,roleApi,userApi } \ No newline at end of file diff --git a/frontend/src/api/template/dto.d.ts b/frontend/src/api/template/dto.d.ts new file mode 100644 index 0000000..850b776 --- /dev/null +++ b/frontend/src/api/template/dto.d.ts @@ -0,0 +1,67 @@ +declare namespace template { + /** + * 基类 + */ + type base_dto = { + /** + * 编码 + */ + code?: null | string; + /** + * 描述 + */ + des?: null | string; + /** + * 名称 + */ + name?: null | string; + } + /** + * 增加输入参数 + */ + type addInput = base_dto + /** + * 更新输入参数 + */ + interface updateInput extends base_dto { + /** + * 主键 + */ + id: string + } + /** + * 删除输入参数 + */ + interface delInput { + /** + * 主键 + */ + id: string + } + /** + * 查询输入参数 + */ + interface queryParms { + /** + * 名称 + */ + name?: null | string; + } + /** + * 查询分页输入参数 + */ + interface queryPage { + pageIndex: number, + pageSize: number, + name:string + } + /** + * 查询输出参数 + */ + interface output extends base_dto { + /** + * 主键 + */ + id: string + } +} \ No newline at end of file diff --git a/frontend/src/api/template/service.ts b/frontend/src/api/template/service.ts new file mode 100644 index 0000000..3906b66 --- /dev/null +++ b/frontend/src/api/template/service.ts @@ -0,0 +1,83 @@ + +import { request } from '@umijs/max'; + + +export default { + /** + * 新增 + * @param parms + * @returns + */ + Add(parms: template.addInput) { + return request('/api/template/add', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 删除 + * @param parms + * @returns + */ + Del(parms: template.delInput) { + return request(`/api/template/del`, { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 修改 + * @param parms + * @returns + */ + Update(parms: template.updateInput) { + return request('/api/template/update', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 详情 + * @param parms + * @returns + */ + Detail(id: string) { + return request(`/api/template/detail?id=${id}`, { + method: 'GET' + }); + }, + /** + * 获取列表 + * @param parms + * @returns + */ + List(parms: template.queryParms) { + return request('/api/template/list', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + /** + * 分页查询 + * @param parms + * @returns + */ + PagedList(parms: template.queryPage) { + return request('/api/template/pagedlist', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + +} + diff --git a/frontend/src/api/workService.ts b/frontend/src/api/workService.ts new file mode 100644 index 0000000..6ed4a28 --- /dev/null +++ b/frontend/src/api/workService.ts @@ -0,0 +1,121 @@ +import { request } from '@umijs/max'; + + +export default { + //创建分组 + Add(parms: WorkInfoTypes.WorkInfoAddInput) { + return request('/api/workinfo/add', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + AddBatch(parms:any){ + return request('/api/workbatch/add', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + UpdateBatch(parms:any){ + return request('/api/workbatch/update', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + DelBatch(parms:any){ + return request(`/api/workbatch/del`, { + method: 'POST', + data: { + ...parms, + }, + }); + }, + //删除 + Del(parms: WorkInfoTypes.WorkInfoDelInput) { + return request(`/api/workinfo/del`, { + method: 'POST', + data: { + ...parms, + }, + }); + }, + //修改 + Update(parms: WorkInfoTypes.WorkInfoUpdateInput) { + return request('/api/workinfo/update', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + //列表 + List(parms: WorkInfoTypes.Query) { + return request('/api/workinfo/list', { + method: 'POST', + data: { + ...parms, + } + }); + }, + /** + * 分页查询 + * @param parms + * @returns + */ + PagedList(parms: WorkInfoTypes.Page) { + return request('/api/workinfo/pagedlist', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + WorkBatchPagedList(parms: WorkInfoTypes.Page) { + return request('/api/workbatch/pagedlist', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + Publish(parms: any) { + return request(`/api/workinfo/publish`, { + method: 'POST', + data: { + ...parms, + }, + }); + }, + publishs(parms:any){ + return request(`/api/workinfo/publishs`, { + method: 'POST', + data: { + ...parms, + }, + }); + }, + UpdateStatus(parms: WorkInfoTypes.WorkInfoStatusUpdateInput) { + return request('/api/workinfo/ForcedEnd', { + method: 'POST', + data: { + ...parms, + }, + }); + }, + ForcedEnd(workId: string) { + return request(`/api/workinfo/forcedend/${workId}`, { + method: 'POST' + }); + }, + UpdateStatusList(workId: string) { + return request(`/api/workinfo/statuslist/${workId}`, { + method: 'GET' + }); + } +} + diff --git a/frontend/src/app.tsx b/frontend/src/app.tsx new file mode 100644 index 0000000..aa9ba5e --- /dev/null +++ b/frontend/src/app.tsx @@ -0,0 +1,145 @@ +import Footer from '@/components/Footer'; +import type { MenuDataItem, Settings as LayoutSettings } from '@ant-design/pro-components'; +import type { RunTimeLayoutConfig } from '@umijs/max'; +import defaultSettings from '../config/defaultSettings'; +import { errorConfig } from './requestErrorConfig'; +import HeaderRight from './components/HeaderRight'; +import { history } from '@umijs/max'; +import { userApi } from '@/api/sys/service'; +import React from 'react'; +import * as Icon from '@ant-design/icons'; +const isDev = process.env.NODE_ENV === 'development'; + +const loopMenuItem = (menus: MenuDataItem[]): MenuDataItem[] => { + return menus?.map(({ icon, routes, ...item }) => ({ + ...item, + icon: icon && React.createElement(Icon && (Icon as any)[item.icon]), + routes: routes && loopMenuItem(routes), + })); +}; + +const formartRoutes = (menuTree: any[]) => { + menuTree.forEach((item) => { + item.path = item.url; + if (item.children && item.children.length > 0 && item.category < 2) { + formartRoutes(item.children); + } else { + delete item.children; + } + }); + return menuTree; +}; + +/** + * @see https://umijs.org/zh-CN/plugins/plugin-initial-state + * */ +export async function getInitialState(): Promise<{ + settings?: Partial; + fetchUserInfo: () => any; + menuData: any[]; + currentUser: any; +}> { + const fetchUserInfo = async () => { + const response:MyResponse.Content = await userApi.GetUserInfo(); + if (response.statusCode===200) { + console.log('response',response); + + return response.data; + } + return null; + }; + const response = await fetchUserInfo(); + if (response) { + localStorage.setItem('USER_INFO', JSON.stringify(response.userInfo)); + localStorage.setItem('USER_MENU', JSON.stringify(response.menus)); + return { + menuData: formartRoutes(response.menus), + currentUser: response.userInfo, + fetchUserInfo, + settings: defaultSettings, + }; + } + return { + menuData: [], + currentUser: null, + fetchUserInfo, + settings: defaultSettings, + }; +} +// ProLayout 支持的api https://procomponents.ant.design/components/layout +export const layout: RunTimeLayoutConfig = ({ initialState }) => { + const config: any = { + rightContentRender: () => , + waterMarkProps: { + content: '黑菠萝科技研发部', + }, + token: { + colorBgAppListIconHover: 'rgba(0,0,0,0.06)', + colorTextAppListIconHover: 'rgba(255,255,255,0.95)', + colorTextAppListIcon: 'rgba(255,255,255,0.85)', + sider: { + colorBgCollapsedButton: '#13C2C2', + colorTextCollapsedButtonHover: 'rgba(0,0,0,0.65)', + colorTextCollapsedButton: 'rgba(0,0,0,0.45)', + colorMenuBackground: '#000', + colorBgMenuItemCollapsedHover: 'rgba(0,0,0,0.06)', + colorBgMenuItemCollapsedSelected: '#13C2C2', + colorMenuItemDivider: 'rgba(255,255,255,0.15)', + colorBgMenuItemHover: '#F5222D', + colorBgMenuItemSelected: '#13C2C2', + colorTextMenuSelected: '#fff', + colorTextMenuItemHover: 'rgba(255,255,255,0.75)', + colorTextMenu: 'rgba(255,255,255,0.75)', + colorTextMenuSecondary: 'rgba(255,255,255,0.65)', + colorTextMenuTitle: 'rgba(255,255,255,0.95)', + colorTextMenuActive: 'rgba(255,255,255,0.95)', + colorTextSubMenuSelected: '#fff', + }, + header: { + colorBgHeader: '#000', + colorMenuBackground: '#000', + colorHeaderTitle: '#ffffff', + }, + pageContainer:{ + paddingInlinePageContainerContent: 20, + paddingBlockPageContainerContent:10 + } + }, + footerRender: () =>