From d8afe78f6a31bf0cf6743f85fb05a121f541c6aa Mon Sep 17 00:00:00 2001 From: Your Name <123456> Date: 星期一, 30 一月 2023 10:52:38 +0800 Subject: [PATCH] 复制框架 --- src/views/doublePrevent/riskLevel/event/components/safetyRiskEventDialog.vue | 184 src/views/specialWorkSystem/plan/appoint/index.vue | 616 src/api/systemManage/appVersion/index.ts | 59 src/layout/index.vue | 54 src/views/contingencyManagement/panManagement/component/approval.vue | 239 src/views/system/department/index.vue | 126 src/views/goalManagement/Goalsummary/index.vue | 227 src/assets/menu/icon1.png | 0 src/assets/warningScreen/skin.png | 0 src/assets/warningScreen/riskprocast.jpg | 0 src/views/loginPage/loginPage.vue | 196 src/api/specialWorkSystem/safetyAction/index.ts | 46 src/views/riskWarningSys/warningBigScreen/index.vue | 1043 src/views/riskWarningSys/warningBigScreen/components/risk.vue | 505 src/views/contingencyManagement/emergencyResources/emergencySupplies/component/openEdit.vue | 549 src/utils/customDirective.ts | 178 src/assets/newMenu/icon4.png | 0 src/views/intellectInspect/inspectTaskManage/inspectTask/components/inspectTaskDialog.vue | 782 src/views/system/personShiftManage/personTimeManage/workingHoursSet/index.vue | 564 src/layout/navBars/breadcrumb/search.vue | 138 src/components/emergencySupplies/index.vue | 215 yarn.lock | 2419 + src/theme/media/home.scss | 23 src/assets/avator.png | 0 src/assets/warningScreen/body-bg.jpg | 0 package-lock.json | 8210 ++++ src/api/intellectInspectSystem/RFID/index.ts | 64 src/theme/media/dialog.scss | 12 src/assets/menu/bg_home.jpg | 0 src/i18n/pages/login/zh-cn.ts | 28 vite.config.ts | 81 src/assets/newMenu/leftbg.png | 0 src/views/error/401.vue | 117 src/views/facilityManagement/InstrumentationInformation/index.vue | 391 src/views/accidentManagementSystem/accidentCasesCop/index.vue | 82 src/i18n/pages/formI18n/en.ts | 13 src/views/contingencyManagement/emergencyResources/maintenanceOfEmergencyMaterials/index.vue | 395 src/assets/newMenu/pic_line2.png | 0 src/assets/menu/card7.png | 0 src/assets/loginPage/login-bg.jpg | 0 src/views/goalManagement/targetSettings/index.vue | 300 src/views/specialWorkSystem/workTicket/zysq/components/hoist.vue | 308 src/api/systemManage/personShiftManage/holidayTime/index.ts | 0 src/views/system/personShiftManage/personTimeManage/timeStrategy/index.vue | 587 src/theme/media/media.scss | 13 src/views/contingencyManagement/emergencyResources/emergencySupplies/component/inspect.vue | 225 src/views/intellectInspect/inspectBasic/inspectTarget/components/inspectTargetDialog.vue | 164 src/main.ts | 27 src/views/intellectInspect/inspectBasic/index.vue | 9 src/views/goalManagement/targetDecompositionYear/component/DailogAdd.vue | 308 src/views/safeKnowledge/law/index.vue | 40 src/views/doublePrevent/riskLevel/device/components/productionDeviceDialog.vue | 197 src/layout/navMenu/subItem.vue | 48 src/views/intellectInspect/inspectRecordManage/inspectRecord/components/sum.vue | 131 src/views/riskWarningSys/warningBigScreen/indexs/msgDetail.vue | 137 src/assets/warningScreen/pagebg-l.png | 0 src/theme/media/cityLinkage.scss | 10 src/api/systemManage/personShiftManage/holidayTimeGroup/index.ts | 0 src/theme/index.scss | 8 src/views/specialWorkSystem/foundationSet/safetyAction/components/safetyActionDialog.vue | 221 src/views/system/personShiftManage/scheduleManage/strategy/index.vue | 672 src/assets/menu/icon11.png | 0 src/assets/newMenu/card-8.png | 0 src/views/specialWorkSystem/workTicket/wdsq/components/heightLog.vue | 125 src/views/goalManagement/Incentivestandard/component/DailogAdd.vue | 147 src/api/doublePreventSystem/work/index.ts | 38 src/views/doublePrevent/riskCheckManage/checkTaskManage/checkTask/index.vue | 316 src/views/doublePrevent/riskLevel/action/components/riskControlMeasureDialog.vue | 265 src/assets/menu/card1.png | 0 src/api/facilityManagement/claimReturnRecords/index.ts | 27 src/views/system/dic/index.vue | 220 src/api/contingencyManagement/emergencyDrillPlan/index.ts | 45 src/api/login/index.ts | 34 LICENSE | 21 src/api/specialWorkSystem/workPlan/workReservation/index.ts | 41 src/utils/formatTime.ts | 137 src/views/system/personShiftManage/personTimeManage/durationManage/index.vue | 561 src/views/contingencyManagement/contingency/component/upData.vue | 125 src/views/intellectInspect/inspectIndex/index.vue | 587 src/assets/menu/icon2.png | 0 src/views/doublePrevent/riskCheckManage/hiddenManagement/hiddenCheck/index.vue | 222 src/views/contingencyManagement/panManagement/index.vue | 614 src/views/specialWorkSystem/flow/ruleofApp/components/approveItemDialog.vue | 183 src/views/goalManagement/index.vue | 14 src/views/contingencyManagement/panManagement/component/initiateApproval.vue | 159 src/views/facilityManagement/safetyGoodsAndEquipment/components/addGoodsDialog.vue | 270 src/views/specialWorkSystem/workTicket/wdsp/components/fireLog.vue | 137 src/views/facilityManagement/goodsTypeManage/index.vue | 435 src/stores/screenTheme.ts | 21 src/views/specialWorkSystem/workTicket/zysq/components/fire.vue | 366 src/assets/loginPage/xj-bg.png | 0 src/views/specialWorkSystem/workTicket/wdsq/components/plateLog.vue | 149 src/layout/navBars/breadcrumb/userNews.vue | 115 src/assets/newMenu/icon5.png | 0 src/theme/media/date.scss | 25 src/api/systemManage/personShiftManage/workingHoursSet/index.ts | 50 src/views/safeKnowledge/internationalRules/index.vue | 40 src/views/contingencyManagement/emergencyDrill/releaseOfDrillPlan/component/openAdd.vue | 591 src/views/facilityManagement/keyEquipment/index.vue | 449 src/utils/getStyleSheets.ts | 93 src/views/contingencyManagement/emergencyDrill/drillImplementationEvaluation/component/approvalProgress.vue | 925 src/layout/main/classic.vue | 35 src/assets/warningScreen/riskprocast-light.jpg | 0 src/views/contingencyManagement/releaseOfDrillStart/component/lowerPlate.vue | 120 src/api/contingencyManagement/emergencyPlanLog/index.ts | 45 src/utils/setIconfont.ts | 48 src/views/loginPage/component/accountLogin.vue | 371 src/stores/index.ts | 15 src/views/doublePrevent/riskLevel/unit/index.vue | 265 src/views/contingencyManagement/abolishDialog/component/lowerPlate.vue | 120 src/views/doublePrevent/riskLevel/action/index.vue | 323 src/views/contingencyManagement/emergencyPlanStartRecord/index.vue | 408 src/views/layoutPage/index.vue | 182 src/views/specialWorkSystem/workTicket/wdsp/components/brokenLog.vue | 152 src/views/intellectInspect/inspectBasic/inspectPoint/components/inspectPointDialog.vue | 166 src/views/contingencyManagement/emergencyResources/emergencyMaterialsInspection/component/openAdd.vue | 284 src/assets/menu/card6.png | 0 src/views/goalManagement/performanceAppraisal/component/DailogKhS.vue | 133 src/assets/newMenu/pic_line1.png | 0 src/views/doublePrevent/riskLevel/riskCheckUnit/components/selectMeasureControlDialog.vue | 219 src/assets/default-img.jpg | 0 src/views/riskWarningSys/warningBigScreen/components/stock.vue | 681 src/utils/other.ts | 200 package.json | 88 src/views/specialWorkSystem/workTicket/wdsq/components/groundLog.vue | 131 src/views/doublePrevent/riskCheckManage/riskCheckUnit/components/selectMeasureControlDialog.vue | 219 src/views/safeKnowledge/xzfg/index.vue | 40 src/assets/newMenu/card-7.png | 0 src/views/specialWorkSystem/workTicket/zysq/index.vue | 177 .prettierrc.js | 40 src/views/accidentManagementSystem/workInjuryDeclaration/index.vue | 397 src/utils/toolsValidate.ts | 368 static/loginPage.js/login.js | 1544 src/views/contingencyManagement/abolishDialog/component/formInformationTop.vue | 144 src/theme/media/chart.scss | 94 src/views/specialWorkSystem/workTicket/wdsq/components/powerLog.vue | 128 src/views/facilityManagement/goodsDetailManage/components/goodsDetailEdit.vue | 227 static/loginPage.js/loginApp.js | 137 src/views/specialWorkSystem/flow/ruleofApp/components/approveRuleDialog.vue | 526 src/assets/newMenu/card-9.png | 0 src/components/equipmentDailog/planDailog.vue | 156 src/views/safeKnowledge/df/index.vue | 40 src/assets/menu/card2.png | 0 src/api/systemManage/basicDateManage/personShiftManage/workingHours/index.ts | 58 src/i18n/pages/formI18n/zh-tw.ts | 13 src/theme/element.scss | 282 src/theme/waves.scss | 101 src/views/contingencyManagement/emergencyResources/emergencySupplies/component/openAdd.vue | 515 src/components/equipmentDailog/regionDailog.vue | 156 src/theme/iconSelector.scss | 70 src/views/contingencyManagement/contingency/component/addEmergencyPersonnel.vue | 305 src/views/riskWarningSys/warningBigScreen/components/training.vue | 423 src/views/doublePrevent/riskCheckManage/riskCheckUnit/index.vue | 194 src/assets/methods/index.ts | 15 src/i18n/pages/formI18n/zh-cn.ts | 13 src/views/goalManagement/targetImprovements/component/Dailogprove.vue | 105 src/views/goalManagement/targetSettings/component/search.vue | 52 src/assets/menu/icon3.png | 0 src/assets/newMenu/card-2.png | 0 src/views/doublePrevent/riskCheckManage/checkTaskManage/checkWork/index.vue | 361 src/assets/newMenu/icon6.png | 0 src/views/contingencyManagement/emergencyDrill/drillImplementationEvaluation/component/flowChart.vue | 307 src/views/specialWorkSystem/process/qtjcfx/index.vue | 511 src/views/contingencyManagement/emergencyDrill/implementationOfEmergencyDrill/component/openAdd.vue | 629 src/views/goalManagement/targetDecompositionMonth/index.vue | 286 src/components/DailogSearch/DailogSearch.vue | 193 src/i18n/lang/en.ts | 180 src/views/specialWorkSystem/workTicket/zysq/components/broken.vue | 504 src/assets/menu/card5.png | 0 src/theme/dark.scss | 236 src/views/doublePrevent/riskCheckManage/riskCheckUnit/components/checkUnitDialog.vue | 260 src/assets/loginPage/map-bg.jpg | 0 src/views/specialWorkSystem/foundationSet/goods/index.vue | 989 src/views/intellectInspect/inspectBasic/facility/components/facilityAreaDialog.vue | 154 src/stores/routesList.ts | 28 src/views/system/menu/index.vue | 206 src/views/contingencyManagement/emergencyResources/emergencySupplies/component/maintain.vue | 236 src/api/contingencyManagement/emergencyDrillEvaluation/index.ts | 45 src/components/equipmentDailog/maintenanceDailog.vue | 206 src/layout/component/main.vue | 101 src/views/contingencyManagement/emergencyDrillStatistics/index.vue | 359 src/views/intellectInspect/inspectRecordManage/inspectRecord/components/inspectRecordDialog.vue | 560 plugins.d.ts | 4 src/layout/routerView/iframes.vue | 66 src/views/contingencyManagement/panManagement/component/abolishLibrary.vue | 226 src/utils/arrayOperation.ts | 66 src/assets/newMenu/icon9.png | 0 src/theme/media/layout.scss | 55 src/views/contingencyManagement/emergencyResources/emergencySupplies/index.vue | 397 src/assets/newMenu/card-10.png | 0 src/i18n/index.ts | 67 src/components/auth/auths.vue | 36 src/views/contingencyManagement/emergencyDrill/implementationOfEmergencyDrill/component/userSelect.vue | 443 src/views/contingencyManagement/panManagement/component/startUp.vue | 160 src/api/intelligentLine/index.ts | 22 src/views/goalManagement/targetClassification/index.vue | 261 src/api/contingencyManagement/contingency/index.ts | 83 src/views/facilityManagement/safetyEquipment/index.vue | 391 src/views/goalManagement/processForms/component/formInformationTops.vue | 162 src/views/specialWorkSystem/workTicket/wdsp/components/plateLog.vue | 170 src/assets/newMenu/icon7.png | 0 src/views/goalManagement/targetDecompositionHalfYear/index.vue | 286 src/views/facilityManagement/goodsDetailManage/index.ts | 101 src/components/DailogSearchUser/index.vue | 246 src/views/doublePrevent/riskLevel/event/index.vue | 212 src/views/specialWorkSystem/process/components/dialogPermitNo.vue | 225 src/api/doublePreventSystem/checkUnit/index.ts | 44 src/theme/media/scrollbar.scss | 56 src/views/goalManagement/Incentivestandard/index.vue | 283 src/api/doublePreventSystem/riskControlMeasure/index.ts | 50 public/favicon.ico | 0 src/router/index.ts | 106 src/theme/media/pagination.scss | 15 src/views/accidentManagementSystem/accidentCases/index.vue | 274 src/views/facilityManagement/claimReturnRecords/components/returnAndWatch.vue | 239 src/layout/main/defaults.vue | 47 src/assets/newMenu/card-1.png | 0 src/utils/request.ts | 119 src/views/system/department/component/deptDialog.vue | 171 src/assets/loginPage/login-bg.png | 0 src/assets/newMenu/icon10.png | 0 src/views/goalManagement/TargetBook/index.vue | 289 src/api/systemManage/basicDateManage/personShiftManage/teamStrategy/index.ts | 50 src/views/doublePrevent/riskLevel/map/components/rectifyDialog.vue | 327 src/views/goalManagement/IncentiveRecording/index.vue | 302 src/components/svgIcon/index.vue | 73 src/components/equipmentDailog/DailogS.vue | 701 src/assets/menu/card3.png | 0 src/views/goalManagement/targetDecompositionYear/index.vue | 284 src/layout/navMenu/horizontal.vue | 157 src/views/goalManagement/targetEscalation/component/Dailog.vue | 65 src/assets/loginPage/login_icon_password.png | 0 src/views/specialWorkSystem/workTicket/wdsqjl/index.vue | 888 src/i18n/lang/zh-tw.ts | 180 src/utils/loading.ts | 42 src/views/system/appVersion/index.vue | 698 src/api/specialWorkSystem/material/index.ts | 50 src/views/accidentManagementSystem/accidentCases/component/wangEditor/index.vue | 174 src/views/specialWorkSystem/flow/basicApprove/index.vue | 448 src/assets/menu/icon4.png | 0 src/utils/directive.ts | 21 src/views/contingencyManagement/emergencyPlanStartRecord/component/openSee.vue | 195 src/views/facilityManagement/safetyGoodsAndEquipment/components/safetyGoodsAndEquipmentDialog.vue | 238 src/views/newHome/index.vue | 967 src/layout/routerView/link.vue | 59 src/views/doublePrevent/riskCheckManage/hiddenManagement/hiddenRectify/index.vue | 437 src/components/uploaderImg/index.vue | 158 src/i18n/lang/zh-cn.ts | 180 src/components/regionsDialog/index.vue | 129 src/stores/userInfo.ts | 73 src/views/facilityManagement/goodsDetailManage/components/checkOut.vue | 136 src/assets/loginPage/back-icon.png | 0 src/api/systemManage/basicDateManage/personShiftManage/timeStrategy/index.ts | 83 src/layout/navBars/tagsView/contextmenu.vue | 138 src/views/system/role/component/roleDialog.vue | 150 src/assets/menu/card4.png | 0 src/views/facilityManagement/goodsDetailManage/components/goodsDetailAdd.vue | 278 src/views/specialWorkSystem/workTicket/wdsq/components/brokenLog.vue | 131 src/api/systemManage/basicDateManage/personShiftManage/holidayTimeGroup/index.ts | 58 src/views/riskWarningSys/warningBigScreen/components/monitor.vue | 104 src/views/specialWorkSystem/workTicket/wdsp/components/groundLog.vue | 152 src/views/accidentManagementSystem/accidentCases/component/DailogCases.vue | 187 src/views/specialWorkSystem/flow/basicApprove/components/approveBasicDialog.vue | 254 .env | 19 src/api/workInjuryDeclaration/index.ts | 123 src/components/noticeBar/index.vue | 195 src/views/goalManagement/TargetBook/component/DailogSearch.vue | 175 src/stores/requestOldRoutes.ts | 17 src/views/contingencyManagement/emergencyResources/emergencyMaterialsInspection/index.vue | 391 src/theme/app.scss | 281 src/views/accidentManagementSystem/accidentExpress/component/numberOfCasualties.vue | 461 src/views/accidentManagementSystem/accidentExpress/component/openAdd.vue | 534 src/views/facilityManagement/securities/index.vue | 860 src/assets/newMenu/card-11.png | 0 src/views/facilityManagement/EquipmentStatistics/index.vue | 101 src/assets/index.css | 10 src/components/auth/auth.vue | 30 source.d.ts | 6 src/views/riskWarningSys/warningBigScreen/components/message.vue | 221 src/views/goalManagement/targetStatistics/index.vue | 92 src/views/intellectInspect/inspectIndex/components/sum.vue | 131 src/assets/loginPage/login_icon_user.png | 0 src/assets/companyLogo.png | 0 src/views/facilityManagement/claimReturnRecords/index.vue | 258 src/views/contingencyManagement/contingency/component/openAdd.vue | 569 src/layout/routerView/parent.vue | 88 src/theme/media/error.scss | 45 src/assets/newMenu/icon8.png | 0 src/components/cropper/index.vue | 149 src/utils/authDirective.ts | 40 src/views/doublePrevent/riskCheckManage/checkTaskManage/checkWork/components/workDialog.vue | 313 src/views/facilityManagement/claimReturnRecords/components/invalidDealDialog.vue | 85 src/assets/newMenu/leftbg.jpg | 0 src/layout/lockScreen/index.vue | 372 src/assets/menu/admin.png | 0 src/api/facilityManagement/safetyGoodsAndEquipment/index.ts | 82 src/views/error/404.vue | 115 src/views/goalManagement/processForms/component/lowerPlate.vue | 120 .env.development | 51 src/assets/style/index.scss | 19 src/assets/newMenu/icon11.png | 0 src/views/contingencyManagement/releaseOfDrillStart/component/formInformationTop.vue | 144 src/layout/navBars/index.vue | 40 src/views/facilityManagement/ProductionEquipment/index.vue | 390 src/assets/menu/card10.png | 0 src/components/equipmentDailog/repairDailog.vue | 216 src/views/contingencyManagement/emergencyDrill/releaseOfDrillPlan/component/regionsDialog.vue | 223 src/views/riskWarningSys/warningBigScreen/components/educate.vue | 180 src/views/system/personShiftManage/personTimeManage/holidayTime/index.vue | 660 src/views/system/menu/component/menuDialog.vue | 254 src/api/systemManage/user/index.ts | 51 src/views/contingencyManagement/processForm/component/formInformationTops.vue | 312 src/views/goalManagement/safetyAssessment/index.vue | 241 src/views/specialWorkSystem/plan/sumReserve/index.vue | 436 src/views/system/role/index.vue | 153 src/views/system/personShiftManage/scheduleManage/schedule/index.vue | 574 src/views/intellectInspect/intelligentLine/index.vue | 1412 src/views/specialWorkSystem/workTicket/wdsq/components/hoistLog.vue | 125 src/assets/menu/icon5.png | 0 src/api/intellectInspectSystem/inspectTask/index.ts | 83 src/views/goalManagement/targetDecompositionQuarter/index.vue | 286 src/views/goalManagement/targetEscalation/index.vue | 199 src/views/doublePrevent/riskCheckManage/hiddenManagement/hiddenRectify/components/rectifyDialog.vue | 303 src/views/doublePrevent/riskLevel/map/index.vue | 261 src/views/goalManagement/safetyAssessment/component/Dailog.vue | 264 src/assets/newMenu/card-4.png | 0 src/views/contingencyManagement/releaseOfDrillStart/releaseOfDrillStart.vue | 137 src/views/contingencyManagement/panManagement/component/upData.vue | 125 src/views/goalManagement/performanceAppraisal/component/DailogSearch.vue | 196 src/views/facilityManagement/deviceType/component/Dailog.vue | 198 src/views/intellectInspect/inspectTaskManage/inspectTask/index.vue | 595 src/components/editor/index.vue | 115 src/layout/navMenu/vertical.vue | 101 src/views/doublePrevent/riskCheckManage/hiddenManagement/hiddenReport/index.vue | 352 src/theme/mixins/index.scss | 56 src/theme/media/personal.scss | 16 src/router/backEnd.ts | 98 src/api/systemManage/menu/index.ts | 50 src/views/safeKnowledge/bmgz/index.vue | 31 src/api/specialWorkSystem/workApproval/index.ts | 41 src/views/doublePrevent/riskLevel/riskCheckUnit/index.vue | 194 src/assets/warningScreen/small-full.png | 0 src/views/intellectInspect/inspectBasic/facility/index.vue | 201 src/assets/warningScreen/pagebg-l-light.png | 0 src/utils/commonFunction.ts | 65 src/utils/theme.ts | 59 src/views/safeKnowledge/index.vue | 40 src/views/accidentManagementSystem/workInjuryDeclaration/component/accidentName.vue | 246 src/views/specialWorkSystem/flow/ruleofApp/components/approveLevelDialog.vue | 327 src/api/contingencyManagement/maintenanceEmergencyMaterials/index.ts | 45 src/i18n/pages/login/zh-tw.ts | 28 src/layout/navBars/breadcrumb/setings.vue | 816 src/views/safeKnowledge/sfjs/index.vue | 40 src/components/auth/authAll.vue | 31 src/views/facilityManagement/safetyGoodsAndEquipment/index.vue | 343 src/layout/main/transverse.vue | 17 src/components/updata/updata.vue | 89 src/router/frontEnd.ts | 97 src/api/systemManage/basicDateManage/personShiftManage/workingHoursSet/index.ts | 50 src/api/contingencyManagement/emergencyMaterialsInspection/index.ts | 45 src/views/safeKnowledge/inner/index.vue | 40 src/views/facilityManagement/safetyGoodsAndEquipment/components/batchInStorage.vue | 145 .eslintrc.js | 63 src/api/facilityManagement/goodsDetailManage/index.ts | 89 src/theme/loading.scss | 51 index.html | 31 src/views/system/dic/component/editDic.vue | 162 src/api/specialWorkSystem/workApply/index.ts | 190 src/views/contingencyManagement/emergencyDrill/releaseOfDrillPlan/index.vue | 404 src/views/goalManagement/targetEscalation/component/TypeDailog.vue | 341 src/i18n/pages/login/en.ts | 29 src/views/goalManagement/targetImprovements/index.vue | 307 src/views/doublePrevent/riskCheckManage/checkTaskManage/checkTask/components/recordDialog.vue | 186 src/views/riskWarningSys/warningBigScreen/components/danger.vue | 330 CHANGELOG.md | 356 src/stores/tagsViewRoutes.ts | 24 src/views/contingencyManagement/abolishDialog/abolishDialog.vue | 139 src/components/DailogSearchUserManger/index.vue | 223 src/layout/logo/index.vue | 85 src/assets/menu/card11.png | 0 src/views/contingencyManagement/emergencyResources/emergencySupplies/component/regionsCheckbox.vue | 164 src/views/specialWorkSystem/workTicket/wdsp/components/hoistLog.vue | 146 tsconfig.json | 71 src/views/contingencyManagement/abolishDialog/component/formInformationTops.vue | 318 src/views/contingencyManagement/emergencyResources/maintenanceOfEmergencyMaterials/component/openAdd.vue | 277 src/views/contingencyManagement/processForm/component/lowerPlate.vue | 120 src/views/riskWarningSys/warningBigScreen/components/accident.vue | 328 src/assets/loginPage/watersys.JPG | 0 src/theme/media/tagsView.scss | 11 src/views/accidentManagementSystem/workInjuryDeclaration/component/openAdd.vue | 547 src/api/contingencyManagement/emergencyDrillExecute/index.ts | 45 src/api/doublePreventSystem/safetyRiskEvent/index.ts | 45 src/assets/newMenu/card-3.png | 0 src/views/specialWorkSystem/workTicket/wdsq/components/spaceLog.vue | 128 src/views/goalManagement/performanceAppraisal/index.vue | 526 src/api/doublePreventSystem/safetyRiskAnalyseUnit/index.ts | 45 src/views/specialWorkSystem/workTicket/wdsq/index.vue | 877 src/components/userCheckbox/index.vue | 422 src/api/intellectInspectSystem/inspectRecord/index.ts | 43 src/api/systemManage/basicDateManage/personShiftManage/teamManage/index.ts | 94 src/assets/menu/icon6.png | 0 src/api/systemManage/personShiftManage/timeStrategy/index.ts | 83 src/assets/loginPage/wind.JPG | 0 src/assets/warningScreen/skin-light.png | 0 src/views/system/dic/component/addDic.vue | 129 src/views/specialWorkSystem/flow/ruleofApp/index.vue | 477 src/views/contingencyManagement/emergencyDrill/implementationOfEmergencyDrill/index.vue | 375 src/views/specialWorkSystem/workTicket/zysq/components/plate.vue | 619 src/views/system/user/component/userDialog.vue | 241 src/views/contingencyManagement/emergencyPlanStartRecord/component/selectEmergencyPlan.vue | 246 src/views/doublePrevent/riskLevel/unit/components/safetyRiskAnalyseUnitDialog.vue | 227 src/views/system/user/index.vue | 227 src/views/doublePrevent/riskLevel/device/index.vue | 261 src/assets/loginPage/xj-icon.png | 0 src/assets/newMenu/icon1.png | 0 src/App.vue | 115 src/layout/navBars/breadcrumb/closeFull.vue | 61 src/api/doublePreventSystem/report/index.ts | 38 src/views/facilityManagement/safetyGoodsAndEquipment/components/batchOutStorage.vue | 154 src/assets/loginPage/map-bg.png | 0 src/assets/loginPage/star-bg.png | 0 src/layout/component/aside.vue | 164 src/stores/keepAliveNames.ts | 37 src/layout/main/columns.vue | 41 src/theme/media/login.scss | 63 src/api/systemManage/personShiftManage/workingHours/index.ts | 58 src/api/doublePreventSystem/rectify/index.ts | 51 src/utils/authFunction.ts | 38 src/assets/loginPage/device-pic.png | 0 src/assets/newMenu/toplogo.png | 0 src/views/intellectInspect/inspectBasic/discriminate/index.vue | 190 src/router/route.ts | 115 src/assets/menu/card9.png | 0 src/assets/warningScreen/pagebg-r.png | 0 src/components/DailogClass/index.vue | 147 src/layout/navBars/breadcrumb/user.vue | 430 src/views/doublePrevent/riskCheckManage/hiddenManagement/hiddenReport/components/reportDialog.vue | 391 src/views/facilityManagement/claimReturnRecords/index.ts | 76 src/assets/loginPage/arrow-r.png | 0 src/api/contingencyManagement/emergencyResources/index.ts | 45 src/views/contingencyManagement/emergencyDrill/drillImplementationEvaluation/component/rectificationDialog.vue | 775 src/stores/interface/index.ts | 109 src/views/accidentManagementSystem/accidentReport/component/openAdd.vue | 723 src/components/editor/toolbar.ts | 60 src/api/doublePreventSystem/check/index.ts | 29 src/api/specialWorkSystem/approveRule/index.ts | 46 src/components/equipmentDailog/Dailog.vue | 903 src/views/riskWarningSys/warningBigScreen/components/profession.vue | 177 src/api/systemManage/role/index.ts | 37 src/assets/menu/companyLogo.png | 0 src/api/doublePreventSystem/record/index.ts | 31 src/assets/newMenu/icon2.png | 0 src/views/specialWorkSystem/workTicket/zysq/components/height.vue | 413 src/views/riskWarningSys/warningBigScreen/components/SPI.vue | 441 src/components/userSelections/index.vue | 446 src/theme/bigScreen.css | 22 src/views/accidentManagementSystem/accidentReport/index.vue | 404 src/views/specialWorkSystem/foundationSet/safetyAction/index.vue | 453 src/api/systemManage/personShiftManage/teamStrategy/index.ts | 50 src/views/intellectInspect/inspectBasic/discriminate/components/RFIDDialog.vue | 248 src/views/goalManagement/IncentiveRecording/component/DailogAdd.vue | 204 src/api/specialWorkSystem/workPlan/workAppoint/index.ts | 50 src/components/checkTemplate/index.vue | 230 src/views/contingencyManagement/processForm/processForm.vue | 137 src/views/specialWorkSystem/workTicket/zysq/components/materialDialog.vue | 293 src/views/contingencyManagement/emergencyDrill/implementationOfEmergencyDrill/component/regionsDialog.vue | 221 src/api/systemManage/personShiftManage/teamManage/index.ts | 94 src/views/goalManagement/processForms/component/formInformationTop.vue | 144 src/api/facilityManagement/index.ts | 104 src/api/intellectInspectSystem/facilityAreaManage/index.ts | 60 src/views/doublePrevent/riskCheckManage/hiddenManagement/hiddenCheck/components/checkDialog.vue | 201 src/assets/warningScreen/logo_dark.png | 0 src/assets/menu/icon7.png | 0 src/views/intellectInspect/inspectBasic/inspectPoint/index.vue | 217 src/assets/warningScreen/pagebg-r-light.png | 0 src/views/contingencyManagement/panManagement/component/approvalProcess.vue | 196 src/assets/newMenu/card-6.png | 0 src/theme/media/form.scss | 16 src/views/specialWorkSystem/process/zyjcgl/index.vue | 632 src/views/contingencyManagement/emergencyDrill/drillImplementationEvaluation/index.vue | 502 src/views/contingencyManagement/releaseOfDrillStart/component/formInformationTops.vue | 440 src/views/specialWorkSystem/workTicket/wdsp/index.vue | 815 src/utils/storage.ts | 59 src/assets/index.ts | 17 src/layout/navBars/tagsView/tagsView.vue | 734 src/views/contingencyManagement/emergencyResources/emergencySupplies/component/personInCharge.vue | 213 src/stores/loginInfo.ts | 20 src/layout/footer/index.vue | 47 src/theme/common/transition.scss | 94 src/views/doublePrevent/dpIndex/index.vue | 596 src/views/contingencyManagement/contingency/index.vue | 401 src/assets/warningScreen/logo_light.png | 0 .eslintignore | 18 src/views/intellectInspect/inspectBasic/inspectTarget/index.vue | 191 src/views/system/personShiftManage/personTimeManage/holidayTimeGroup/index.vue | 561 src/components/equipmentDailog/detectDailog.vue | 194 src/assets/menu/icon10.png | 0 src/views/goalManagement/performanceAppraisal/component/DailogAq.vue | 455 shim.d.ts | 13 src/api/accidentManagementSystem/index.ts | 145 src/components/equipmentDailog/standardDailog.vue | 151 src/views/accidentManagementSystem/accidentCasesCop/component/wangEditor/index.vue | 174 src/views/facilityManagement/deviceType/index.vue | 130 src/views/specialWorkSystem/workTicket/zysq/components/space.vue | 379 src/views/riskWarningSys/warningBigScreen/indexs/index.vue | 470 src/views/accidentManagementSystem/accidentExpress/index.vue | 359 src/views/goalManagement/processForms/processForms.vue | 124 src/stores/themeConfig.ts | 146 src/assets/menu/icon9.png | 0 src/views/contingencyManagement/emergencyDrill/releaseOfDrillPlan/component/flowChart.vue | 325 src/views/specialWorkSystem/workTicket/wdsq/components/fireLog.vue | 122 src/api/contingencyManagement/emergencyPlan/index.ts | 91 src/assets/warningScreen/video.png | 0 src/assets/login-icon-two.svg | 1 src/theme/media/index.scss | 15 src/views/specialWorkSystem/alarm/zyyjjl/index.vue | 364 src/components/iconSelector/index.vue | 252 src/layout/navBars/breadcrumb/index.vue | 119 src/utils/wartermark.ts | 47 src/api/specialWorkSystem/workProcess/index.ts | 59 src/views/accidentManagementSystem/accidentStatistics/index.vue | 183 src/assets/logo-mini.svg | 9 src/api/systemManage/department/index.ts | 37 src/theme/other.scss | 36 src/views/facilityManagement/safetyGoodsAndEquipment/index.ts | 129 src/views/goalManagement/safetyAssessment/component/DailogAdd.vue | 281 src/components/equipmentDailog/categoryDailog.vue | 147 src/views/accidentManagementSystem/workInjuryDeclaration/component/openEdit.vue | 400 src/views/specialWorkSystem/workTicket/wdsp/components/spaceLog.vue | 149 src/layout/component/header.vue | 34 src/assets/warningScreen/pagebg-t-light.png | 0 src/views/specialWorkSystem/plan/reservation/index.vue | 632 src/api/intellectInspectSystem/inspectTargetManage/index.ts | 59 .env.production | 22 src/api/goalManagement/index.ts | 412 src/layout/navBars/breadcrumb/breadcrumb.vue | 162 src/views/goalManagement/TargetBook/component/DailogAdd.vue | 246 src/views/goalManagement/performanceAppraisal/component/DailogKh.vue | 247 src/api/intellectInspectSystem/inspectPointManage/index.ts | 59 src/views/specialWorkSystem/workTicket/wdsp/components/powerLog.vue | 149 src/assets/loginPage/task-job-pic.png | 0 src/views/contingencyManagement/panManagement/component/openAdd.vue | 471 src/views/goalManagement/IncentiveRecording/component/DailogSearch.vue | 204 src/assets/icon.png | 0 src/assets/warningScreen/pagebg-t.png | 0 src/views/goalManagement/targetDecompositionYear/component/Dailog.vue | 262 src/api/systemManage/basicDateManage/personShiftManage/holidayTime/index.ts | 50 src/utils/throttle.ts | 36 src/views/specialWorkSystem/workTicket/zysq/components/ground.vue | 563 src/assets/newMenu/icon3.png | 0 src/layout/component/columnsAside.vue | 292 src/assets/menu/bg_home1.jpg | 0 src/assets/loginPage/equipment.JPG | 0 src/assets/newMenu/card-5.png | 0 src/api/specialWorkSystem/approveBasic/index.ts | 46 src/assets/newMenu/topbg.jpg | 0 src/api/doublePreventSystem/productionDevice/index.ts | 45 src/assets/menu/card8.png | 0 src/views/facilityManagement/goodsDetailManage/index.vue | 444 src/views/contingencyManagement/processForm/component/formInformationTop.vue | 144 src/components/uploaderFile/index.vue | 183 src/assets/menu/icon8.png | 0 src/views/specialWorkSystem/workTicket/wdsp/components/heightLog.vue | 146 src/views/specialWorkSystem/workTicket/zysq/components/power.vue | 294 src/views/goalManagement/targetSettings/component/dailogAdd.vue | 284 src/views/doublePrevent/riskLevel/riskCheckUnit/components/checkUnitDialog.vue | 260 src/views/intellectInspect/inspectIndex/components/inspectRecordDialog.vue | 592 src/views/intellectInspect/inspectRecordManage/inspectRecord/index.vue | 546 568 files changed, 114,692 insertions(+), 0 deletions(-) diff --git a/.env b/.env new file mode 100644 index 0000000..19f641e --- /dev/null +++ b/.env @@ -0,0 +1,19 @@ +# port 端口号 +VITE_PORT = 8888 + +# open 运行 npm run dev 时自动打开浏览器 +VITE_OPEN = false + +# public path 配置线上环境路径(打包)、本地通过 http-server 访问时,请置空即可 + +#内网test环境 +#VITE_PUBLIC_PATH = 'http://192.168.0.52:6002' + +#内网UAT环境 +#VITE_PUBLIC_PATH = 'http://192.168.0.52:6006' + +#线上UAT预发环境 +#VITE_PUBLIC_PATH = 'http://121.239.169.27:6006' + +#国泰线上试用环境 +VITE_PUBLIC_PATH = 'http://121.239.169.27:6622' diff --git a/.env.development b/.env.development new file mode 100644 index 0000000..2ef70b0 --- /dev/null +++ b/.env.development @@ -0,0 +1,51 @@ +# 本地环境 +ENV = 'development' + +#VITE_API_URL = 'http://192.168.0.35:8008' +#李宇飞接口地址 + +VITE_API_URL = 'http://192.168.0.50:8008' +#张凤接口地址 + +#VITE_API_URL = 'http://192.168.0.29:8008' +#黄振接口地址 + +#VITE_API_URL = 'http://192.168.0.179:8008' +#施正红接口地址 + +#VITE_API_URL = 'http://192.168.0.69:8008' +#戚会山接口地址 + +#VITE_API_URL = 'http://121.239.169.27:16006/safeplatform' +#线上正式环境接口地址 + +#VITE_API_URL_OUT = 'http://121.239.169.27:16006/safeplatform-out' +#线上正式环境外包接口地址 + +#VITE_API_URL = 'http://192.168.0.52:8011/safeplatform' +#本地预发接口地址 + +#VITE_API_URL_OUT = 'http://192.168.0.52:8011/safeplatform-out' +#本地外包预发接口地址 + + +VITE_API_URL_OUT = 'http://192.168.0.50:8009' +#张凤外包接口地址 + +#VITE_API_URL_OUT = 'http://192.168.0.52:7021/safeplatform-out' + + +#VITE_API_URL = 'http://192.168.0.52:7021/safeplatform' +#本地测试接口地址 + +VITE_API_URL_SOCKET = 'http://192.168.0.52:7021/safeplatform' +#本地测试websocket接口地址 + +#VITE_API_URL = 'http://192.168.0.29:7008' +#黄振接口test地址 + +#VITE_API_URL_SOCKET = 'http://192.168.0.29:16107' +#黄振websocket test接口地址 + +#VITE_API_URL_SOCKET = 'http://192.168.0.29:8018' +#黄振websocket接口地址 diff --git a/.env.production b/.env.production new file mode 100644 index 0000000..c50fbea --- /dev/null +++ b/.env.production @@ -0,0 +1,22 @@ +# 线上环境 +ENV = 'production' + +#内网test环境接口地址 +#VITE_API_URL = 'http://192.168.0.52:7021/safeplatform' +#VITE_API_URL_OUT = 'http://192.168.0.52:7021/safeplatform-out' +#VITE_API_URL_SOCKET = 'http://192.168.0.52:7021/safeplatform' + +#内网UAT环境接口地址 +#VITE_API_URL = 'http://192.168.0.52:8011/safeplatform' +#VITE_API_URL_OUT = 'http://192.168.0.52:8011/safeplatform-out' +#VITE_API_URL_SOCKET = 'http://192.168.0.52:8011/safeplatform' + +# 线上UAT预发环境接口地址 +#VITE_API_URL = 'http://121.239.169.27:16006/safeplatform' +#VITE_API_URL_OUT = 'http://121.239.169.27:16006/safeplatform-out' +#VITE_API_URL_SOCKET = 'http://121.239.169.27:16006/safeplatform' + +# 国泰线上试用环境接口地址 +VITE_API_URL = 'http://121.239.169.27:16016/safeplatform' +VITE_API_URL_OUT = 'http://121.239.169.27:16016/safeplatform-out' +VITE_API_URL_SOCKET = 'http://121.239.169.27:16016/safeplatform' diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..cfc877d --- /dev/null +++ b/.eslintignore @@ -0,0 +1,18 @@ + +*.sh +node_modules +lib +*.md +*.scss +*.woff +*.ttf +.vscode +.idea +dist +mock +public +bin +build +config +index.html +src/assets \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..732bfbe --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,63 @@ +module.exports = { + root: true, + env: { + browser: true, + es2021: true, + node: true, + }, + parser: 'vue-eslint-parser', + parserOptions: { + ecmaVersion: 12, + parser: '@typescript-eslint/parser', + sourceType: 'module', + }, + extends: ['plugin:vue/vue3-essential', 'plugin:vue/essential', 'eslint:recommended'], + plugins: ['vue', '@typescript-eslint'], + rules: { + // http://eslint.cn/docs/rules/ + // https://eslint.vuejs.org/rules/ + '@typescript-eslint/ban-ts-ignore': 'off', + '@typescript-eslint/explicit-function-return-type': 'off', + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-var-requires': 'off', + '@typescript-eslint/no-empty-function': 'off', + '@typescript-eslint/no-use-before-define': 'off', + '@typescript-eslint/ban-ts-comment': 'off', + '@typescript-eslint/ban-types': 'off', + '@typescript-eslint/no-non-null-assertion': 'off', + '@typescript-eslint/explicit-module-boundary-types': 'off', + 'vue/custom-event-name-casing': 'off', + 'vue/attributes-order': 'off', + 'vue/one-component-per-file': 'off', + 'vue/html-closing-bracket-newline': 'off', + 'vue/max-attributes-per-line': 'off', + 'vue/multiline-html-element-content-newline': 'off', + 'vue/singleline-html-element-content-newline': 'off', + 'vue/attribute-hyphenation': 'off', + 'vue/html-self-closing': 'off', + 'vue/no-multiple-template-root': 'off', + 'vue/require-default-prop': 'off', + 'vue/no-v-model-argument': 'off', + 'vue/no-arrow-functions-in-watch': 'off', + 'vue/no-template-key': 'off', + 'vue/no-v-html': 'off', + 'vue/comment-directive': 'off', + 'vue/no-parsing-error': 'off', + 'vue/no-deprecated-v-on-native-modifier': 'off', + 'vue/multi-word-component-names': 'off', + 'no-useless-escape': 'off', + 'no-sparse-arrays': 'off', + 'no-prototype-builtins': 'off', + 'no-constant-condition': 'off', + 'no-use-before-define': 'off', + 'no-restricted-globals': 'off', + 'no-restricted-syntax': 'off', + 'generator-star-spacing': 'off', + 'no-unreachable': 'off', + 'no-multiple-template-root': 'off', + 'no-unused-vars': 'error', + 'no-v-model-argument': 'off', + 'no-case-declarations': 'off', + 'no-console': 'error', + }, +}; diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 0000000..5a12c4d --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1,40 @@ +module.exports = { + // 一行最多多少个字符 + printWidth: 1500, + // 指定每个缩进级别的空格数 + tabWidth: 4, + // 使用制表符而不是空格缩进行 + useTabs: false, + // // 在语句末尾打印分号 + // semi: true, + // 使用单引号而不是双引号 + singleQuote: true, + // // 更改引用对象属性的时间 可选值"<as-needed|consistent|preserve>" + // quoteProps: 'as-needed', + // // 在JSX中使用单引号而不是双引号 + // jsxSingleQuote: false, + // // 多行时尽可能打印尾随逗号。(例如,单行数组永远不会出现逗号结尾。) 可选值"<none|es5|all>",默认none + trailingComma: 'none', + bracketSpacing: true, + // 在对象文字中的括号之间打印空格 + // bracketSpacing: true, + // // jsx 标签的反尖括号需要换行 + // jsxBracketSameLine: false, + // // 在单独的箭头函数参数周围包括括号 always:(x) => x \ avoid:x => x + // arrowParens: 'always', + // // 这两个选项可用于格式化以给定字符偏移量(分别包括和不包括)开始和结束的代码 + // rangeStart: 2, + // rangeEnd: Infinity, + // // 指定要使用的解析器,不需要写文件开头的 @prettier + // requirePragma: false, + // // 不需要自动在文件开头插入 @prettier + // insertPragma: false, + // // 使用默认的折行标准 always\never\preserve + // proseWrap: 'preserve', + // // 指定HTML文件的全局空格敏感度 css\strict\ignore + // htmlWhitespaceSensitivity: 'css', + // // Vue文件脚本和样式标签缩进 + // vueIndentScriptAndStyle: false, + // 换行符使用 lf 结尾是 可选值"<auto|lf|crlf|cr>" + endOfLine: 'lf' +}; diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..34eedbe --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,356 @@ +# <a href="https://gitee.com/lyt-top/vue-next-admin" target="_blank">vue-next-admin 更新日志</a> + +🎉🎉🔥 `vue-next-admin` 基于 vue3.x 、Typescript、vite、Element plus 等,适配手机、平板、pc 的后台开源免费模板库(vue2.x 请切换 vue-prev-admin 分支) + +## 2.1.1 + +`2022.05.27` + +- 🌟 更新 依赖更新最新版本 +- 🎯 优化 深色模式下,`<el-button text></el-button>` 时,`:active` 样式 +- 🎯 优化 [页面缓存在刷新之后失效 #I58U75](https://gitee.com/lyt-top/vue-next-admin/issues/I58U75)),感谢[@ls0428](https://gitee.com/ls0428) +- 🎯 优化 [SvgIcon 对下载的 Svg 图像设置颜色无效 #I59ND0](https://gitee.com/lyt-top/vue-next-admin/issues/I59ND0)),感谢[@elus_z](https://gitee.com/elus_z) +- 🎯 优化 `/src/utils/toolsValidate.ts` 工具类 +- 🐞 修复 [布局切换,TagsView 显示的 tab 会多一个出来 #I58WGM](https://gitee.com/lyt-top/vue-next-admin/issues/I58WGM),感谢[@lg_boy](https://gitee.com/lg_boy) +- 🐞 修复 [如果设置顶部面包屑导航开启图标 isBreadcrumbIcon=true 后,样式有点问题 如果不开启就是正常的 #I58VB8](https://gitee.com/lyt-top/vue-next-admin/issues/I58VB8) +- 🐞 修复 地址栏路由地址输入错误时,返回首页后,再次输入路由地址错误时,不跳转 404 问题 +- 🐞 修复 [2.1.0 版本的图标选择组件多次点击后功能失效 #I590TH](https://gitee.com/lyt-top/vue-next-admin/issues/I590TH),感谢[@quber](https://gitee.com/quber) + +## 2.1.0 + +`2022.04.18` + +⚡⚡⚡ 此版本为破环性更新,优化内容如下:(谨慎更新!谨慎更新!!谨慎更新!!!)。因为 `vuex` 替换成 `pinia` + +- 🌟 更新 依赖更新最新版本 +- 🎯 优化 部分界面图片不显示问题(更换 gitee 在线图片地址源) +- 🎯 优化 各界面方法引入与逻辑之间添加一行空行,方便区分内容 +- 🎯 优化 图标选择器 [#I4YAHB](https://gitee.com/lyt-top/vue-next-admin/issues/I4YAHB),感谢[@真有你的](https://gitee.com/sunliusen) +- 🎯 优化 图标选择器 icon type 类型为 all 时,类型 ali、ele、awe 回显问题 +- 🎯 优化 去掉开发环境 i18n 控制台警告,页面代码:[i18n/index.ts](https://gitee.com/lyt-top/vue-next-admin/blob/master/src/i18n/index.ts) +- 🎯 优化 `NextLoading.start()` 方法,防止第一次进入界面时出现短暂空白 +- 🎯 优化 地址栏有参数退出登录,再次登录不跳之前界面问题 `src/layout/navBars/breadcrumb/user.vue` +- 🎯 优化 `SvgIcon` 组件,防止 `开启 Tagsview 图标` 时,`tagsView 右键菜单关闭` 报错问题,工作流不可连线、全屏时关闭按钮消失问题 +- 🎯 优化 [如果 url 中有中文等特殊字符,第一次切换该 tab 时 keep-alive 失效#I55JS7](https://gitee.com/lyt-top/vue-next-admin/issues/I55JS7),感谢[yuyong1566](https://gitee.com/yuyong1566) +- 🎯 优化 [wangEditor](https://www.wangeditor.com/) 更新到 v5,[vue3 版本线上示例中 wangeditor 富文本编辑器 demo 实例,无法换行#I5565B](https://gitee.com/lyt-top/vue-next-admin/issues/I5565B),感谢@[jenchih](https://gitee.com/jenchih) +- 🎯 优化 [在关闭 tagview 时,高度刷新时会会变化,出现滚动条](https://gitee.com/lyt-top/vue-next-admin/issues/I55FHM),感谢[张松](https://gitee.com/zs310071113) +- 🎯 优化 [路由参数](https://lyt-top.gitee.io/vue-next-admin-preview/#/params/common)演示 +- 🎉 新增 [vuex](https://vuex.vuejs.org/) 替换成 [pinia](https://pinia.vuejs.org/getting-started.html) +- 🎉 新增 tagsView 支持自定义 tagsView 名称(文章详情时有用),前往体验:[路由参数/普通路由](https://lyt-top.gitee.io/vue-next-admin-preview/#/params/common)。新增 tagsView 支持自定义名称国际化,感谢[@q7but](https://gitee.com/q7but)、[!22 add 添加自定义 tagVIewName 拓展,支持国际化](https://gitee.com/lyt-top/vue-next-admin/pulls/22/files)、感谢[@tony_tong_xin](https://gitee.com/tony_tong_xin) +- 🐞 修复 适配 `"element-plus": "^2.1.9",2.2.0` 版本 +- 🐞 修复 [导航栏横向布局后,一级菜单显示问题#I4Z3M3](https://gitee.com/lyt-top/vue-next-admin/issues/I4Z3M3) +- 🐞 修复 横向布局三级及以上导航菜单高亮、导航高度不统一问题 +- 🐞 修复 分栏模式下,选中的菜单是 primary 样式,鼠标移入字也变成 primary 色了,感谢群友@孤夜-流殇 +- 🐞 修复 [vuex 里面改了颜色 但是不生效 #I4WFMA](https://gitee.com/lyt-top/vue-next-admin/issues/I4WFMA) +- 🐞 修复 全局主题 primary 清空颜色后报错,[#I4X0LG](https://gitee.com/lyt-top/vue-next-admin/issues/I4X0LG),感谢[面向 BUG 编程](https://gitee.com/fhtfy) +- 🐞 修复 [.eslintrc.js 文件 rules 标签名错误 #I53IPK](https://gitee.com/lyt-top/vue-next-admin/issues/I53IPK),感谢[yuyong1566](https://gitee.com/yuyong1566) +- 🐞 修复 `开启 Tagsview 图标` 时,`tagsView 右键菜单关闭` 报错问题 +- 🐞 修复 `router.push` 路径找不到时报错问题,`404、401 界面` 已移入到 `main` 主布局里(之前全屏) +- 🐞 修复 [全局修改组件大小失效了](https://gitee.com/lyt-top/vue-next-admin/issues/I551RP),感谢[lg_boy](https://gitee.com/lg_boy) +- 🐞 修复 [修改一下配置时,需要每次都清理 `window.localStorage` 浏览器永久缓存,配置才会生效,问题解决#I567R1](https://gitee.com/lyt-top/vue-next-admin/issues/I567R1),感谢[@lanbao123](https://gitee.com/lanbao123) +- 🐞 修复 [标记为需要缓存的 tab 页后,再次从左侧菜单打开,还是显示被缓存的页面内容#I4UY3G](https://gitee.com/lyt-top/vue-next-admin/issues/I4UY3G),感谢@axcc1234、特别感谢群友@华仔 +- 🌈 重构 路由(`/src/router/index.ts`)解决 No match found for location with path "xxx"(前端控制,后端控制未解决) 问题 + +## 2.0.2 + +`2022.03.04` + +- 🌟 更新 依赖更新最新版本 +- 🎯 优化 Alert 提示添加边框 +- 🎯 优化 功能 / 数字滚动 演示界面 +- 🐞 修复 全局主题按钮颜色 :active 问题 +- 🐞 修复 Dropdown 下拉菜单样式问题 +- 🐞 修复 SvgIcon 图标组件动态切换时报警告问题,[SvgIcon 改变 name 时可能导致图像不显示](https://gitee.com/lyt-top/vue-next-admin/issues/I4VGE0),感谢@axcc1234 + +## 2.0.1 + +`2022.02.25` + +- 🌟 更新 依赖更新最新版本 +- 🎯 优化 svgIcon 图标组件 +- 🎯 优化 vite.config.ts 打包,感谢群友@YourObjec +- 🐞 修复 tagViews 开启图标不显示问题(风格 5),感谢群友@坏人 +- 🐞 修复 [Element Plus 1.2.0-beta.6 以后的版本 el-table 在移动端无法左右滑动](https://gitee.com/lyt-top/vue-next-admin/issues/I4UPTP),感谢@YGDada + +## 2.0.0 + +`2022.02.21` + +⚡⚡⚡ 此版本为破环性更新,优化内容如下:(谨慎更新!谨慎更新!!谨慎更新!!!)。演示界面建议直接覆盖文件。如需使用之前版本,请前往[gitee 发行版](https://gitee.com/lyt-top/vue-next-admin/releases) 进行对应版本下载。基础版会基于 `master` 分支进行修改 + +- 🌟 更新 依赖更新最新版本 +- 🌟 更新 登录页、首页 +- 💔 移除 vue-web-screen-shot +- 💔 移除 城市多级联动,完整 json 数据请去 [vue-next-admin-images/menu](https://gitee.com/lyt-top/vue-next-admin-images/tree/master/menu) 仓库查看 +- 💔 移除 功能/echartsTree 树图 +- 💔 移除 其它设置/Tagsview 风格 2、Tagsview 风格 3 +- 💔 移除 功能/验证器 +- 🚧 调整 src/api 编写方式 +- 🚧 调整 自定义封装公用组件演示,更好的维护 +- 🎉 新增 Volar 支持,vs code 配置参考 [Vue Language Features (Volar)](https://lyt-top.gitee.io/vue-next-admin-doc-preview/home/vscode/) +- 🎉 新增 `SvgIcon` 支持本地 svg 图标使用 +- 🎉 新增 表单表格验证演示 +- 🎯 优化 全局主题(移除 success、info、warning、danger) +- 🎯 优化 工作流(开源) +- 🎯 优化 element plus svg 图标,`elementXXX` 改成 `ele-XXX` +- 🌈 重构 深色模式 +- 🌹 合并 [处理 parent 的 h100 由于外层有 min-height 导致失效的问题](https://gitee.com/lyt-top/vue-next-admin/pulls/20),感谢@MaxNull、@21030442-mao +- 🐞 修复 element plus 升级 `^1.3.0-beta.5` 后 组件 size 大小问题(大改:涉及布局、演示界面) +- 🐞 修复 vs code 使用 Vue Language Features (Volar) 插件 代码报红问题(可以把公用的 ts 类型定义封装起来公用) + +## 1.2.2 + +`2021.12.21` + +- 🌟 更新 依赖更新最新版本 +- 🎯 优化 iframes 滚动条问题 +- 🎯 优化 部署后每次都要强制刷新清浏览器缓存问题 +- 🎉 新增 工具类百分比验证演示 +- 🐞 修复 [tag-view 标签右键会超出浏览器 #I4KN78](https://gitee.com/lyt-top/vue-next-admin/issues/I4KN78) + +## 1.2.1 + +`2021.12.12` + +- 🌟 更新 依赖更新最新版本 +- 🎯 优化 cropper 裁剪时卡顿问题 [#I4M2VQ](https://gitee.com/lyt-top/vue-next-admin/issues/I4M2VQ) +- 🎯 优化 Wangeditor 富文本编辑器的问题 [#I4LPC1](https://gitee.com/lyt-top/vue-next-admin/issues/I4LPC1)、[#I4LM7I](https://gitee.com/lyt-top/vue-next-admin/issues/I4LM7I) +- 🐞 修复 浏览器标题问题 +- 🐞 修复 element plus svg 图标引入 +- 🐞 修复 工作流不可以拖线连接问题 + +## 1.2.0 + +`2021.11.28` + +- 🌟 更新 依赖更新最新版本 +- 🎯 优化 深色模式 +- 🎯 优化 `/@/utils` 文件夹,合并删除单一内容 +- 🎯 优化 系统设置:菜单管理(新增、修改)、角色管理(新增菜单权限)、用户管理、部门管理、字典管理 +- 🎯 优化 登录界面逻辑、权限管理逻辑 +- 🎯 优化 同步 [vue-next-admin-images](https://gitee.com/lyt-top/vue-next-admin-images/tree/master/menu) 后端控制菜单模拟数据 +- 🎉 新增 适配 Font Icon 向 SVG Icon 迁移(改动大,"element-plus": "^1.2.0-beta.4" 谨慎更新) +- 🐞 修复 热更新问题,感谢@甜蜜蜜 +- 🐞 修复 页面/element 字体图标演示 +- 🐞 修复 功能/图标选择器演示,新增高级功能 [issues #I4GJXQ](https://gitee.com/lyt-top/vue-next-admin/issues/I4GJXQ) + +## 1.1.2 + +`2021.10.17` + +- 🌟 更新 依赖更新最新版本 +- 🐞 修复 开启全屏时,刷新界面被还原成未全屏的状态 +- 🎯 优化 tagsView 右键菜单关闭逻辑 +- 🎯 优化 wangeditor 富文本编辑器(增加双向绑定) +- 🎉 新增 工作流(暂不开源) +- 🎉 新增 基础版 ts(不带国际化),切换 `vue-next-admin-template` 分支 + +## 1.1.1 + +`2021.09.25` + +- 🌟 更新 依赖更新最新版本(`"element-plus": "^1.1.0-beta.13"` 版本运行错误,`^1.1.0-beta.16`修复横向菜单卡死问题) +- 🐞 修复 Dialog 弹窗位置错误、Drawer 抽屉内边距、el-menu 菜单收起时背景色问题 +- 🎯 优化 锁屏界面自动锁屏(s/秒)必须设置至少 1 秒 +- 🎉 新增 分栏布局,鼠标移入当前项时,显示当前项菜单内容 +- 🎉 新增 工作流(未完成) + +## 1.1.0 + +`2021.09.10` + +- 🌟 更新 依赖更新最新版本 +- 🎯 优化 小屏模式下登录页二维码遮挡标题问题 +- 🎉 新增 图片验证器 +- 🎉 新增 动态复杂表单 +- 🎉 新增 工作流(未完成) +- 🎉 新增 深色主题(伪深色,样式变动大,谨慎更新) + +## 1.0.18 + +`2021.08.29` + +- 🌟 更新 依赖更新最新版本 +- 🎯 优化 权限组件去掉顶级 div(`/src/components/auth`) +- 🎉 新增 布局配置添加恢复默认按钮 +- 🐞 修复 升级 <a href="https://element-plus.gitee.io/#/zh-CN/component/changelog" target="_blank">element plus 1.1.0-beta.7</a>后项目无法启动、el-menu 菜单 +- 🐞 修复 表格固定列时的层级、设置了相对定位时,遮挡左侧导航菜单问题 + +## 1.0.17 + +`2021.08.22` + +- 🌟 更新 依赖更新最新版本 +- 🎯 优化 去除设置布局切换,重置主题样式(initSetLayoutChange),切换布局需手动设置样式,设置的样式自动同步各布局 +- 🎯 优化 Dropdown 下拉菜单用户账号靠边时换行问题 +- 🎯 优化 左侧导航菜单,共用菜单树,防止 `布局配置` 设置 `菜单 / 顶栏` 时,样式丢失等问题 +- 🐞 修复 固定 header 后没有回到顶部的 bug,拉取项目后运行不起来的 bug。<a href="https://gitee.com/lyt-top/vue-next-admin/pulls/14" target="_blank">!14</a>,感谢<a href="https://gitee.com/wjs0509" target="_blank">@wjs0509</a> +- 🐞 修复 tagView 右键全屏后,浏览器窗口大小发生任何变化都会导致左边菜单显示出来,并且可点击打开对应页面。<a href="https://gitee.com/lyt-top/vue-next-admin/issues/I46E6T" target="_blank">I46E6T</a> +- 🐞 修复 默认设置 `菜单 / 顶栏` 样式不生效问题(/@/src/store/modules/themeConfig.ts) + +## 1.0.16 + +`2021.08.14` + +- 🌟 更新 依赖更新最新版本 +- 🎯 优化 菜单高亮(详情且详情设置了 meta.isHide 时,顶级菜单高亮),感谢群友@YourObject +- 🎯 优化 详情路径写法:如父级(/pages/filtering),那么详情为(/pages/filtering/details?id=1)。这样写可实现(详情时,父级菜单高亮),否则写成(/pages/filteringDetails?id=1)顶级菜单将不会高亮。可参考:`页面/过滤筛选组件`,点击当前图片进行测试 +- 🎯 优化 tagsView 右键菜单全屏时,打开的界面高度问题 +- 🎯 优化 图表批量 resize 问题 +- 🐞 修复 菜单收起时(设置全局主题:primary 且有二级菜单时),文字高亮颜色不对 +- 🐞 修复 国际化 <a href="https://gitee.com/lyt-top/vue-next-admin/issues/I43NPE" target="_blank">#I43NPE</a>。可参考:`页面/过滤筛选组件`,点击顶部语言切换,进行底部分页国际化查看 + +## 1.0.15 + +`2021.08.06` + +- 🌟 更新 依赖更新最新版本 +- 🎯 优化 tagsView 右键菜单点击时的字段名(id 已修改成 contextMenuClickId)与路由中返回的 id 名冲突问题,感谢群友@伯牙已遇钟子期 +- 🎉 新增 多个 form 表单验证界面演示 + +## 1.0.14 + +`2021.07.29` + +- 🌟 更新 依赖更新最新版本(vue、vuex、vue-router),出现问题,请手动降级。版本查看:<a href="https://www.npmjs.com/" target="_blank">vnpm</a> +- 🎯 优化 数据可视化图表演示加载卡顿问题、优化有图表的演示界面 +- 🎯 优化 路由参数演示界面 +- 🎯 优化 tagsView 操作演示界面,由于存在相同路由多标签,必须要传全部参数值(query 或者 params) +- 🎉 新增 开启 TagsView 共用,开启时:(多个路由菜单共用一个详情组件(参数为后点击的覆盖前面点击的),tagsView 中只会出现一个(不支持同时出现多个 tagsView 标签))。关闭时:(多个路由菜单共用一个详情组件,参数不同,会同时出现多个 tagsView 标签) +- 🐞 修复 tagsView 共用(单标签)时,右键菜单功能点击,参数不对的问题(第 2n+个参数未覆盖第一个参数值) +- 🐞 修复 多 tagsView 标签(参数不同)、单个 tagsView 标签公用(参数不同)所带来的刷新功能、横向自动滚动等问题 +- 🐞 修复 处理全屏若干问题,<a href="https://gitee.com/lyt-top/vue-next-admin/pulls/12" target="_blank">pr!12</a>,感谢群友@另一个前端 + +## 1.0.13 + +`2021.07.25` + +- 🌟 更新 依赖更新最新版本 +- 🎉 新增 数据可视化演示界面(/visualizingDemo1、/visualizingDemo2) +- 🎉 新增 登录页扫码登录 + +## 1.0.12 + +`2021.07.16` + +- 🌟 更新 依赖更新最新版本 +- 🎉 新增 数据可视化演示空界面(待完善) +- 🎯 优化 tagsView 动态路由(xxx/:id/:name)时的右键菜单刷新、关闭其它时参数丢失问题(2021.07.15 优化) +- 🐞 修复 路由带参数时,复制路径到登录页,跳转后参数消失的问题 +- 🐞 修复 设置多个外链,点击后,页面内容停留在上一个内容(内容未改变)、国际化处理、打开新窗口 sessionStorage 共享等 + +## 1.0.11 + +`2021.07.14` + +- 🌟 更新 依赖更新最新版本 +- 🎉 新增 路由参数、图片懒加载界面演示 +- ⚠️ 警告 Form 表单 `binding value must be a string or number`,解决:加上 `label-position="top"` 不报警告(等待官方修复) +- 🎯 优化 锁屏界面动画效果、首页图表显示 +- 🎯 优化 tagsView 右键菜单 `关闭` 功能逻辑 +- 🐞 修复 开启 TagsView 拖拽报错及小于 `1000px` 时自动设置禁止拖拽(<a href="https://gitee.com/lyt-top/vue-next-admin/issues/I3ZRRI" target="_blank">#I3ZRRI</a>) +- 🐞 修复 `iframe 内嵌、外链` 高度问题,使用 computed 进行计算 +- 🐞 修复 默认布局开启 `侧边栏 Logo` 与关闭 `菜单水平折叠`,切换到横向布局时,菜单看不见的问题 +- 🐞 修复 切换不同布局时,再去开启 `经典布局分割菜单` 功能不生效问题 +- 🐞 修复 浏览器窗口标题中/英文切换不实时生效的问题 +- 🐞 修复 切换布局时,某些功能不可以使用。部分界面不需要取消事件监听(proxy.mittBus.off('xxx')) +- 🐞 修复 动态路由带参数,router-link 跳转问题(<a href="hhttps://gitee.com/lyt-top/vue-next-admin/issues/I3YX6G" target="_blank">#I3YX6G</a>) +- 🐞 修复 横向菜单有二级菜单时,点击子级菜单不高亮问题 +- 🐞 修复 功能 tagsView 操作演示不生效 + +## 1.0.10 + +`2021.07.07` + +- 🌟 更新 依赖更新最新版本(字体图标无问题) +- 🎯 优化 内嵌 iframe、外链,解决 tagsView 刷新问题 + +## 1.0.9 + +`2021.07.02` + +- 🌟 更新 依赖更新最新版本 +- 🎯 优化 图标选择器设置宽度、v-model 等问题 +- 🎯 优化 滚动通知栏在手机上的体验 +- 🎯 优化 系统管理/新增菜单(编辑菜单),使用 `图标选择器` 进行模拟 +- 🎯 优化 字体图标(自动载入) 逻辑 +- 🐞 修复 screenfull 全屏时,按键盘 esc 键图标不改变问题,感谢群友@伯牙已遇钟子期 + +## 1.0.8 + +`2021.06.29` + +- 🌟 更新 依赖更新最新版本 +- 🎉 新增 表单中英文切换演示 +- 🎯 优化 登录页查看密码 icon 图标 +- 🎯 优化 图标选择器 +- 🎯 优化 拖动指令 +- 🐞 修复 form 表单在页面小于 576px 时的排版问题 + +## 1.0.7 + +`2021.06.24` + +- 🌟 更新 依赖更新最新版本 +- 🎉 新增 拖动指令及其演示界面 +- 🎯 优化 锁屏界面,解锁提示 +- 🎯 优化 登录页在手机上显示的效果 + +## 1.0.6 + +`2021.06.23` + +- 🎯 优化 去掉内嵌 iframe 内边距(padding) +- 🎯 优化 城市多级联动组件 +- 🎯 优化 Tree 树形控件改成表格组件 +- 🐞 修复 Cascader 级联选择器高度问题 + +## 1.0.5 + +`2021.06.22` + +- 🌟 更新 vite 降级为@vite2.3.7,降级方法 `cnpm install vite@2.3.7`,防止 element plus 字体图标消失 +- 🐞 修复 开启后端控制路由(isRequestRoutes = true)时,内嵌 iframe、外链不可使用的问题 + +## 1.0.4 + +`2021.06.19` + +- 🌟 更新 依赖更新最新版本("vite": "^2.3.7")热更新无问题 +- 🎉 新增 深克隆工具,方便开发,感谢<a href="https://gitee.com/kangert" target="_blank">@kangert</a>(<a href="https://gitee.com/lyt-top/vue-next-admin/pulls/6" target="_blank">#6</a>) +- 🎯 优化 vuex 模块自动导入。感谢<a href="https://gitee.com/kangert" target="_blank">@kangert</a>(<a href="https://gitee.com/lyt-top/vue-next-admin/pulls/4" target="_blank">#4</a>),感谢群友@web 小学生-第五君 +- 🎯 优化 类型定义提高编码体验,修复不能将类型“string | undefined”分配给类型“string”的问题。感谢<a href="https://gitee.com/kangert" target="_blank">@kangert</a>(<a href="https://gitee.com/lyt-top/vue-next-admin/pulls/5" target="_blank">#5</a>) +- 🎯 优化 `layout` 文件夹移动到与 `views` 文件夹同级(改动较大,`/@/views/layout` 变成 `/@/layout`) +- 🎯 优化 页面有 `console.log` 时 `eslint` 不生效问题 +- 🎯 优化 页面、ts 中 `any` 类型问题(改动较大) +- 🎯 优化 登录页在手机上显示的效果 +- 🎯 优化 多行注释信息,鼠标放到方法名即可查看,更加直观的知道方法参数等。引入方法时需去掉以 `.ts` 结尾的后缀(改动较大) +- 🎯 优化 移除 `utils/storage.ts` 下的旧写法(改动较大) +- 🎯 优化 拆分 `router` 下内容,路由、前端、后端控制分开写,方便理解 +- 🐞 修复 鼠标移入顶部用户信息栏 `开/关全屏` 文字反向问题 +- 🐞 修复 热更新时,NextLoading(界面 loading) 不消失问题 `window.nextLoading === undefined` +- 🐞 修复 vuex 中不可以使用 `/@/api/xxx` 下的接口调用问题 + +## 1.0.3 + +`2021.06.02` + +- ❄️ 删除 G6 思维导图界面 +- 🌟 更新 手动更新 vue、vue-router、vuex 到最近最多人使用的版本,出现不可预测的问题请降低版本。版本查看:<a href="https://www.npmjs.com/package/vue" target="_blank">vue 版本查看</a> +- 🐞 修复 开启后端控制路由 `isRequestRoutes` 在非首页刷新页面后,回到首页的问题,感谢群友@伯牙已遇钟子期 + +## 1.0.2 + +`2021.06.01` + +- 🌟 更新 依赖更新最新版本 +- 🐞 修复 菜单搜索中文不可以搜索的问题,感谢群友@逍遥天意 + +## 1.0.1 + +`2021.05.31` + +- 🎉 新增 更新日志文件 `CHANGELOG.md`,以后每次更新都会在这里显示对应内容 +- 🌟 更新 依赖更新最新版本 +- 🐞 修复 分栏、经典布局路由设置 `meta.isHide` 为 `true` 时报错问题,感谢群友@29、@芭芭拉 +- 🐞 修复 经典布局点击 `tagsView` 左侧菜单数据不变问题 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..6f6a7ea --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 lyt-Top + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..a550d07 --- /dev/null +++ b/index.html @@ -0,0 +1,31 @@ +<!DOCTYPE html> +<html lang="zh-CN"> + <head> + <meta charset="utf-8" /> + <meta http-equiv="X-UA-Compatible" content="IE=edge" /> + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> + <meta + name="keywords" + content="vue-next-admin,vue-prev-admin,vue-admin-wonderful,后台管理系统一站式平台模板,希望可以帮你完成快速开发。vue2.x,vue2.0,vue2,vue3,vue3.x,vue3.0,CompositionAPI,typescript,element plus,element,plus,admin,wonderful,wonderful-next,vue-next-admin,vite,vite-admin,快速,高效,后台模板,后台系统,管理系统" + /> + <meta + name="description" + content="vue-next-admin,基于 vue3 + CompositionAPI + typescript + vite + element plus,适配手机、平板、pc 的后台开源免费管理系统模板!vue-prev-admin,基于 vue2 + element ui,适配手机、平板、pc 的后台开源免费管理系统模板!" + /> + <title>vue-next-admin</title> + </head> + <body> + <div id="app"></div> + <script type="text/javascript"> + var _hmt = _hmt || []; + (function () { + var hm = document.createElement('script'); + hm.src = 'https://hm.baidu.com/hm.js?d9c8b87d10717013641458b300c552e4'; + var s = document.getElementsByTagName('script')[0]; + s.parentNode.insertBefore(hm, s); + })(); + </script> + <script type="module" src="/src/main.ts"></script> + <script type="text/javascript" src="https://api.map.baidu.com/api?v=3.0&ak=wsijQt8sLXrCW71YesmispvYHitfG9gv&s=1"></script> + </body> +</html> diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..5149933 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,8210 @@ +{ + "name": "vue-next-admin", + "version": "2.1.1", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "vue-next-admin", + "version": "2.1.1", + "license": "MIT", + "dependencies": { + "@element-plus/icons-vue": "^2.0.6", + "@kjgl77/datav-vue3": "^1.2.1", + "@wangeditor/editor": "^5.1.14", + "axios": "^0.27.2", + "countup.js": "^2.2.0", + "cropperjs": "^1.5.12", + "echarts": "^5.3.3", + "echarts-gl": "^2.0.9", + "echarts-wordcloud": "^2.0.0", + "element-plus": "^2.2.9", + "js-base64": "^3.7.2", + "js-cookie": "^3.0.1", + "json-bigint": "^1.0.0", + "jsplumb": "^2.15.6", + "mitt": "^3.0.0", + "nprogress": "^0.2.0", + "pinia": "^2.0.14", + "pinia-plugin-persistedstate": "^2.1.1", + "print-js": "^1.6.0", + "qrcodejs2-fixes": "^0.0.2", + "screenfull": "^6.0.1", + "sortablejs": "^1.15.0", + "splitpanes": "^3.1.1", + "vue": "^3.2.36", + "vue-clipboard3": "^2.0.0", + "vue-grid-layout": "^3.0.0-beta1", + "vue-i18n": "^9.1.10", + "vue-router": "^4.0.15", + "wangeditor": "^4.7.15", + "xlsx": "^0.18.5" + }, + "devDependencies": { + "@types/json-bigint": "^1.0.1", + "@types/node": "^17.0.39", + "@types/nprogress": "^0.2.0", + "@types/sortablejs": "^1.13.0", + "@typescript-eslint/eslint-plugin": "^5.27.0", + "@typescript-eslint/parser": "^5.27.0", + "@vitejs/plugin-vue": "^2.3.3", + "@vue/compiler-sfc": "^3.2.36", + "dotenv": "^16.0.1", + "eslint": "^8.17.0", + "eslint-plugin-vue": "^9.1.0", + "prettier": "^2.6.2", + "sass": "^1.52.2", + "sass-loader": "^13.0.0", + "typescript": "^4.7.3", + "vite": "^2.9.9", + "vue-eslint-parser": "^9.0.2" + }, + "engines": { + "node": ">=12.0.0", + "npm": ">= 6.0.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.0.tgz", + "integrity": "sha512-AqDccGC+m5O/iUStSJy3DGRIUFu7WbY/CppZYwrEUB4N0tZlnI8CSTsgL7v5fHVFmUbRv2sd+yy27o8Ydt4MGg==", + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.0.tgz", + "integrity": "sha512-YMQvx/6nKEaucl0MY56mwIG483xk8SDNdlUwb2Ts6FUpr7fm85DxEmsY18LXBNhcTz6tO6JwZV8w1W06v8UKeg==", + "dependencies": { + "regenerator-runtime": "^0.13.4" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/runtime-corejs3": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.18.9.tgz", + "integrity": "sha512-qZEWeccZCrHA2Au4/X05QW5CMdm4VjUDCrGq5gf1ZDcM4hRqreKrtwAn7yci9zfgAS9apvnsFXiGBHBAxZdK9A==", + "dependencies": { + "core-js-pure": "^3.20.2", + "regenerator-runtime": "^0.13.4" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@ctrl/tinycolor": { + "version": "3.4.1", + "resolved": "https://registry.npmmirror.com/@ctrl/tinycolor/-/tinycolor-3.4.1.tgz", + "integrity": "sha512-ej5oVy6lykXsvieQtqZxCOaLT+xD4+QNarq78cIYISHmZXshCvROLudpQN3lfL8G0NL7plMSSK+zlyvCaIJ4Iw==", + "engines": { + "node": ">=10" + } + }, + "node_modules/@element-plus/icons-vue": { + "version": "2.0.6", + "resolved": "https://registry.npmmirror.com/@element-plus/icons-vue/-/icons-vue-2.0.6.tgz", + "integrity": "sha512-lPpG8hYkjL/Z97DH5Ei6w6o22Z4YdNglWCNYOPcB33JCF2A4wye6HFgSI7hEt9zdLyxlSpiqtgf9XcYU+m5mew==", + "peerDependencies": { + "vue": "^3.2.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.0.tgz", + "integrity": "sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.3.2", + "globals": "^13.15.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@floating-ui/core": { + "version": "0.7.3", + "resolved": "https://registry.npmmirror.com/@floating-ui/core/-/core-0.7.3.tgz", + "integrity": "sha512-buc8BXHmG9l82+OQXOFU3Kr2XQx9ys01U/Q9HMIrZ300iLc8HLMgh7dcCqgYzAzf4BkoQvDcXf5Y+CuEZ5JBYg==" + }, + "node_modules/@floating-ui/dom": { + "version": "0.5.4", + "resolved": "https://registry.npmmirror.com/@floating-ui/dom/-/dom-0.5.4.tgz", + "integrity": "sha512-419BMceRLq0RrmTSDxn8hf9R3VCJv2K9PUfugh5JyEFmdjzDo+e8U5EdR8nzKq8Yj1htzLm3b6eQEEam3/rrtg==", + "dependencies": { + "@floating-ui/core": "^0.7.3" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", + "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, + "node_modules/@interactjs/actions": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/actions/-/actions-1.10.11.tgz", + "integrity": "sha512-P39zeefr4hkmKx+5nZ+mrH1s0l2YJ3gIHrthXmE81n6MlMa42m0WtHcTms4C5JTTNBP2EEDY+KGgGxSnmJKvUw==", + "optionalDependencies": { + "@interactjs/interact": "1.10.11" + }, + "peerDependencies": { + "@interactjs/core": "1.10.11", + "@interactjs/utils": "1.10.11" + } + }, + "node_modules/@interactjs/auto-scroll": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/auto-scroll/-/auto-scroll-1.10.11.tgz", + "integrity": "sha512-feHNjhi0EMNLV2nQcEgjYPz2mI54aeSW2RiaoNtFLyBvtXKp0b4DmluwDv6DvuXmUpDwD5g/Hk1gGM2rgl7iqQ==", + "optionalDependencies": { + "@interactjs/interact": "1.10.11" + }, + "peerDependencies": { + "@interactjs/utils": "1.10.11" + } + }, + "node_modules/@interactjs/auto-start": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/auto-start/-/auto-start-1.10.11.tgz", + "integrity": "sha512-cIg5CcalCPtC6AiGq6j/0hKUtL2MweEpvw12FuB19sz2Q9Dye0J4GliHKhOYvtumNinnvfVAZ4FZMqZEuX7YZA==", + "optionalDependencies": { + "@interactjs/interact": "1.10.11" + }, + "peerDependencies": { + "@interactjs/core": "1.10.11", + "@interactjs/utils": "1.10.11" + } + }, + "node_modules/@interactjs/core": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/core/-/core-1.10.11.tgz", + "integrity": "sha512-aJ50ccVeszpJt7wPH7Yfqm7f1aG1SA94qd90P0NaESh5/QUXn4CESO6igobo4DFHQ5z+1Rfdl8aphP4JxlH4gw==", + "peerDependencies": { + "@interactjs/utils": "1.10.11" + } + }, + "node_modules/@interactjs/dev-tools": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/dev-tools/-/dev-tools-1.10.11.tgz", + "integrity": "sha512-BP2FNfMbF7zLuOAUGMkDhCo1e1B0fnqyb9ih/Y8yAIJuoLrZxP/9htbsS1vZOIVZ4UgtrId4cYOwfcAZBMQtmw==", + "optionalDependencies": { + "@interactjs/interact": "1.10.11" + }, + "peerDependencies": { + "@interactjs/modifiers": "1.10.11", + "@interactjs/utils": "1.10.11" + } + }, + "node_modules/@interactjs/inertia": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/inertia/-/inertia-1.10.11.tgz", + "integrity": "sha512-h+sknCzRqBSyHy4ctPNsq56mxkAMMdwHWD6en7rDEw899gdGKYaXVDVdv1jMfiwNRw0eRFBNoCiol8r3a/a3Jw==", + "dependencies": { + "@interactjs/offset": "1.10.11" + }, + "optionalDependencies": { + "@interactjs/interact": "1.10.11" + }, + "peerDependencies": { + "@interactjs/core": "1.10.11", + "@interactjs/modifiers": "1.10.11", + "@interactjs/utils": "1.10.11" + } + }, + "node_modules/@interactjs/interact": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/interact/-/interact-1.10.11.tgz", + "integrity": "sha512-0iZJ9l547JuBA/lKxK4ARGYVmMqRSsAdA8gXL1zWe51qEIQq8PyWmMipoi8JbDaL7exC2THKwkXu5uq5ndT+iA==", + "dependencies": { + "@interactjs/core": "1.10.11", + "@interactjs/types": "1.10.11", + "@interactjs/utils": "1.10.11" + } + }, + "node_modules/@interactjs/interactjs": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/interactjs/-/interactjs-1.10.11.tgz", + "integrity": "sha512-cGOxf6rp3Y8/sk88LhIT0XDn4gCiCzAnUG5Kkj9SAqiUO6BK/9+Wbp1IBkNaPgl/8uG8gNHh/dXBrlBBNcqJAg==", + "dependencies": { + "@interactjs/actions": "1.10.11", + "@interactjs/auto-scroll": "1.10.11", + "@interactjs/auto-start": "1.10.11", + "@interactjs/core": "1.10.11", + "@interactjs/dev-tools": "1.10.11", + "@interactjs/inertia": "1.10.11", + "@interactjs/interact": "1.10.11", + "@interactjs/modifiers": "1.10.11", + "@interactjs/offset": "1.10.11", + "@interactjs/pointer-events": "1.10.11", + "@interactjs/reflow": "1.10.11", + "@interactjs/utils": "1.10.11" + } + }, + "node_modules/@interactjs/modifiers": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/modifiers/-/modifiers-1.10.11.tgz", + "integrity": "sha512-ltqX1RSqeAIikixlQBlyEUdclT5+rbfIGi3sIdLLYaIZQnltYkWqL9MHKx/w5b+hV+Mc0p5MLUFWJbTdkSCZ9g==", + "dependencies": { + "@interactjs/snappers": "1.10.11" + }, + "optionalDependencies": { + "@interactjs/interact": "1.10.11" + }, + "peerDependencies": { + "@interactjs/core": "1.10.11", + "@interactjs/utils": "1.10.11" + } + }, + "node_modules/@interactjs/offset": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/offset/-/offset-1.10.11.tgz", + "integrity": "sha512-mBT7eIfy5ivofECiv+VwtEwwIMLV54fT9ujSMWJPduxdSYIHepUWgEf/3zjJknFh6jQc7pqz9dtjvVvyzRCLlQ==", + "optionalDependencies": { + "@interactjs/interact": "1.10.11" + }, + "peerDependencies": { + "@interactjs/core": "1.10.11", + "@interactjs/utils": "1.10.11" + } + }, + "node_modules/@interactjs/pointer-events": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/pointer-events/-/pointer-events-1.10.11.tgz", + "integrity": "sha512-yBT8JJVMZ+MgBay5l1WAHnL8ch/mZsRfaFahti+QFYeQyRloDtsWmEMDSYI/Onyy9+hS3gN/ge77ArGciZZ0Ow==", + "optionalDependencies": { + "@interactjs/interact": "1.10.11" + }, + "peerDependencies": { + "@interactjs/core": "1.10.11", + "@interactjs/utils": "1.10.11" + } + }, + "node_modules/@interactjs/reflow": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/reflow/-/reflow-1.10.11.tgz", + "integrity": "sha512-NSCtcCkjImOYSbxzzv2kFqR9t49J8KlhEr9UoePc7GyLbNXsiv3WQ3n0ehZd7CgZXQDiVXnP2UnmIOv5Zd4HQg==", + "optionalDependencies": { + "@interactjs/interact": "1.10.11" + }, + "peerDependencies": { + "@interactjs/core": "1.10.11", + "@interactjs/utils": "1.10.11" + } + }, + "node_modules/@interactjs/snappers": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/snappers/-/snappers-1.10.11.tgz", + "integrity": "sha512-yYtOMUZ7aFUZ1IYheq9Tj5hZ4J1r5dnaXhLF44WsI/awQ5L0DjZf07GPWof0B+7rZHEVudxyQNbPfFmb+1K94Q==", + "optionalDependencies": { + "@interactjs/interact": "1.10.11" + }, + "peerDependencies": { + "@interactjs/utils": "1.10.11" + } + }, + "node_modules/@interactjs/types": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/types/-/types-1.10.11.tgz", + "integrity": "sha512-YRsVFWjL8Gkkvlx3qnjeaxW4fnibSJ9791g8BA7Pv5ANByI64WmtR1vU7A2rXcrOn8XvyCEfY0ss1s8NhZP+MA==" + }, + "node_modules/@interactjs/utils": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/utils/-/utils-1.10.11.tgz", + "integrity": "sha512-410ZoxKF+r1roeSelL+WHXfdryUMg5iykC1XwQ3l6XqNw43IMACzyvTH6k6Pwxj7w7x42nce0Qdn1GQ3Y8xyCw==" + }, + "node_modules/@intlify/core-base": { + "version": "9.1.10", + "resolved": "https://registry.npmjs.org/@intlify/core-base/-/core-base-9.1.10.tgz", + "integrity": "sha512-So9CNUavB/IsZ+zBmk2Cv6McQp6vc2wbGi1S0XQmJ8Vz+UFcNn9MFXAe9gY67PreIHrbLsLxDD0cwo1qsxM1Nw==", + "dependencies": { + "@intlify/devtools-if": "9.1.10", + "@intlify/message-compiler": "9.1.10", + "@intlify/message-resolver": "9.1.10", + "@intlify/runtime": "9.1.10", + "@intlify/shared": "9.1.10", + "@intlify/vue-devtools": "9.1.10" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@intlify/devtools-if": { + "version": "9.1.10", + "resolved": "https://registry.npmjs.org/@intlify/devtools-if/-/devtools-if-9.1.10.tgz", + "integrity": "sha512-SHaKoYu6sog3+Q8js1y3oXLywuogbH1sKuc7NSYkN3GElvXSBaMoCzW+we0ZSFqj/6c7vTNLg9nQ6rxhKqYwnQ==", + "dependencies": { + "@intlify/shared": "9.1.10" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@intlify/message-compiler": { + "version": "9.1.10", + "resolved": "https://registry.npmjs.org/@intlify/message-compiler/-/message-compiler-9.1.10.tgz", + "integrity": "sha512-+JiJpXff/XTb0EadYwdxOyRTB0hXNd4n1HaJ/a4yuV960uRmPXaklJsedW0LNdcptd/hYUZtCkI7Lc9J5C1gxg==", + "dependencies": { + "@intlify/message-resolver": "9.1.10", + "@intlify/shared": "9.1.10", + "source-map": "0.6.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@intlify/message-resolver": { + "version": "9.1.10", + "resolved": "https://registry.npmjs.org/@intlify/message-resolver/-/message-resolver-9.1.10.tgz", + "integrity": "sha512-5YixMG/M05m0cn9+gOzd4EZQTFRUu8RGhzxJbR1DWN21x/Z3bJ8QpDYj6hC4FwBj5uKsRfKpJQ3Xqg98KWoA+w==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/@intlify/runtime": { + "version": "9.1.10", + "resolved": "https://registry.npmjs.org/@intlify/runtime/-/runtime-9.1.10.tgz", + "integrity": "sha512-7QsuByNzpe3Gfmhwq6hzgXcMPpxz8Zxb/XFI6s9lQdPLPe5Lgw4U1ovRPZTOs6Y2hwitR3j/HD8BJNGWpJnOFA==", + "dependencies": { + "@intlify/message-compiler": "9.1.10", + "@intlify/message-resolver": "9.1.10", + "@intlify/shared": "9.1.10" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@intlify/shared": { + "version": "9.1.10", + "resolved": "https://registry.npmjs.org/@intlify/shared/-/shared-9.1.10.tgz", + "integrity": "sha512-Om54xJeo1Vw+K1+wHYyXngE8cAbrxZHpWjYzMR9wCkqbhGtRV5VLhVc214Ze2YatPrWlS2WSMOWXR8JktX/IgA==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/@intlify/vue-devtools": { + "version": "9.1.10", + "resolved": "https://registry.npmjs.org/@intlify/vue-devtools/-/vue-devtools-9.1.10.tgz", + "integrity": "sha512-5l3qYARVbkWAkagLu1XbDUWRJSL8br1Dj60wgMaKB0+HswVsrR6LloYZTg7ozyvM621V6+zsmwzbQxbVQyrytQ==", + "dependencies": { + "@intlify/message-resolver": "9.1.10", + "@intlify/runtime": "9.1.10", + "@intlify/shared": "9.1.10" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@jiaminghi/bezier-curve": { + "version": "0.0.9", + "resolved": "https://registry.npmmirror.com/@jiaminghi/bezier-curve/-/bezier-curve-0.0.9.tgz", + "integrity": "sha512-u9xJPOEl6Dri2E9FfmJoGxYQY7vYJkURNX04Vj64tdi535tPrpkuf9Sm0lNr3QTKdHQh0DdNRsaa62FLQNQEEw==", + "dependencies": { + "@babel/runtime": "^7.5.5" + } + }, + "node_modules/@jiaminghi/c-render": { + "version": "0.4.3", + "resolved": "https://registry.npmmirror.com/@jiaminghi/c-render/-/c-render-0.4.3.tgz", + "integrity": "sha512-FJfzj5hGj7MLqqqI2D7vEzHKbQ1Ynnn7PJKgzsjXaZpJzTqs2Yw5OSeZnm6l7Qj7jyPAP53lFvEQNH4o4j6s+Q==", + "dependencies": { + "@babel/runtime": "^7.5.5", + "@jiaminghi/bezier-curve": "*", + "@jiaminghi/color": "*", + "@jiaminghi/transition": "*" + } + }, + "node_modules/@jiaminghi/charts": { + "version": "0.2.18", + "resolved": "https://registry.npmmirror.com/@jiaminghi/charts/-/charts-0.2.18.tgz", + "integrity": "sha512-K+HXaOOeWG9OOY1VG6M4mBreeeIAPhb9X+khG651AbnwEwL6G2UtcAQ8GWCq6GzhczcLwwhIhuaHqRygwHC0sA==", + "dependencies": { + "@babel/runtime": "^7.5.5", + "@jiaminghi/c-render": "^0.4.3" + } + }, + "node_modules/@jiaminghi/color": { + "version": "0.1.1", + "resolved": "https://registry.npmmirror.com/@jiaminghi/color/-/color-0.1.1.tgz", + "integrity": "sha512-M09+Sb5HGqVim0zo+nG5gU1v+6gXT8ptr0BZR6dMGt83XmCJgnZtO8s7llTW4hLFFFM5co6geZvTekqLpSPAAQ==", + "dependencies": { + "@babel/runtime": "^7.5.5" + } + }, + "node_modules/@jiaminghi/transition": { + "version": "1.1.11", + "resolved": "https://registry.npmmirror.com/@jiaminghi/transition/-/transition-1.1.11.tgz", + "integrity": "sha512-owBggipoHMikDHHDW5Gc7RZYlVuvxHADiU4bxfjBVkHDAmmck+fCkm46n2JzC3j33hWvP9nSCAeh37t6stgWeg==", + "dependencies": { + "@babel/runtime": "^7.5.5" + } + }, + "node_modules/@kjgl77/datav-vue3": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/@kjgl77/datav-vue3/-/datav-vue3-1.2.1.tgz", + "integrity": "sha512-hiSodPvXkp6o8nyPPgDFcrb+M4h9dZd2hmuT3WqHY+sInEHCFtypCGrhvxRFT3oGlcIlLKSX9WVb117JksFROA==", + "dependencies": { + "@jiaminghi/c-render": "^0.4.3", + "@jiaminghi/charts": "^0.2.18", + "@vueuse/core": "^9.1.0" + } + }, + "node_modules/@kjgl77/datav-vue3/node_modules/@types/web-bluetooth": { + "version": "0.0.15", + "resolved": "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.15.tgz", + "integrity": "sha512-w7hEHXnPMEZ+4nGKl/KDRVpxkwYxYExuHOYXyzIzCDzEZ9ZCGMAewulr9IqJu2LR4N37fcnb1XVeuZ09qgOxhA==" + }, + "node_modules/@kjgl77/datav-vue3/node_modules/@vueuse/core": { + "version": "9.1.1", + "resolved": "https://registry.npmmirror.com/@vueuse/core/-/core-9.1.1.tgz", + "integrity": "sha512-QfuaNWRDMQcCUwXylCyYhPC3ScS9Tiiz4J0chdwr3vOemBwRToSywq8MP+ZegKYFnbETzRY8G/5zC+ca30wrRQ==", + "dependencies": { + "@types/web-bluetooth": "^0.0.15", + "@vueuse/metadata": "9.1.1", + "@vueuse/shared": "9.1.1", + "vue-demi": "*" + } + }, + "node_modules/@kjgl77/datav-vue3/node_modules/@vueuse/metadata": { + "version": "9.1.1", + "resolved": "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-9.1.1.tgz", + "integrity": "sha512-XZ2KtSW+85LLHB/IdGILPAtbIVHasPsAW7aqz3BRMzJdAQWRiM/FGa1OKBwLbXtUw/AmjKYFlZJo7eOFIBXRog==" + }, + "node_modules/@kjgl77/datav-vue3/node_modules/vue-demi": { + "version": "0.13.11", + "resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.13.11.tgz", + "integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==", + "hasInstallScript": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@popperjs/core": { + "name": "@sxzz/popperjs-es", + "version": "2.11.7", + "resolved": "https://registry.npmmirror.com/@sxzz/popperjs-es/-/popperjs-es-2.11.7.tgz", + "integrity": "sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ==" + }, + "node_modules/@transloadit/prettier-bytes": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@transloadit/prettier-bytes/-/prettier-bytes-0.0.7.tgz", + "integrity": "sha512-VeJbUb0wEKbcwaSlj5n+LscBl9IPgLPkHVGBkh00cztv6X4L/TJXK58LzFuBKX7/GAfiGhIwH67YTLTlzvIzBA==" + }, + "node_modules/@types/eslint": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.2.tgz", + "integrity": "sha512-Z1nseZON+GEnFjJc04sv4NSALGjhFwy6K0HXt7qsn5ArfAKtb63dXNJHf+1YW6IpOIYRBGUbu3GwJdj8DGnCjA==", + "dev": true, + "peer": true, + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.3.tgz", + "integrity": "sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g==", + "dev": true, + "peer": true, + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "0.0.51", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", + "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", + "dev": true, + "peer": true + }, + "node_modules/@types/event-emitter": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@types/event-emitter/-/event-emitter-0.3.3.tgz", + "integrity": "sha512-UfnOK1pIxO7P+EgPRZXD9jMpimd8QEFcEZ5R67R1UhGbv4zghU5+NE7U8M8G9H5Jc8FI51rqDWQs6FtUfq2e/Q==" + }, + "node_modules/@types/json-bigint": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/@types/json-bigint/-/json-bigint-1.0.1.tgz", + "integrity": "sha512-zpchZLNsNuzJHi6v64UBoFWAvQlPhch7XAi36FkH6tL1bbbmimIF+cS7vwkzY4u5RaSWMoflQfu+TshMPPw8uw==", + "dev": true + }, + "node_modules/@types/json-schema": { + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", + "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", + "dev": true + }, + "node_modules/@types/lodash": { + "version": "4.14.182", + "resolved": "https://registry.npmmirror.com/@types/lodash/-/lodash-4.14.182.tgz", + "integrity": "sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q==" + }, + "node_modules/@types/lodash-es": { + "version": "4.17.6", + "resolved": "https://registry.npmmirror.com/@types/lodash-es/-/lodash-es-4.17.6.tgz", + "integrity": "sha512-R+zTeVUKDdfoRxpAryaQNRKk3105Rrgx2CFRClIgRGaqDTdjsm8h6IYA8ir584W3ePzkZfst5xIgDwYrlh9HLg==", + "dependencies": { + "@types/lodash": "*" + } + }, + "node_modules/@types/node": { + "version": "17.0.39", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.39.tgz", + "integrity": "sha512-JDU3YLlnPK3WDao6/DlXLOgSNpG13ct+CwIO17V8q0/9fWJyeMJJ/VyZ1lv8kDprihvZMydzVwf0tQOqGiY2Nw==", + "dev": true + }, + "node_modules/@types/nprogress": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@types/nprogress/-/nprogress-0.2.0.tgz", + "integrity": "sha512-1cYJrqq9GezNFPsWTZpFut/d4CjpZqA0vhqDUPFWYKF1oIyBz5qnoYMzR+0C/T96t3ebLAC1SSnwrVOm5/j74A==", + "dev": true + }, + "node_modules/@types/sortablejs": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@types/sortablejs/-/sortablejs-1.13.0.tgz", + "integrity": "sha512-C3064MH72iEfeGCYEGCt7FCxXoAXaMPG0QPnstcxvPmbl54erpISu06d++FY37Smja64iWy5L8wOyHHBghWbJQ==", + "dev": true + }, + "node_modules/@types/web-bluetooth": { + "version": "0.0.14", + "resolved": "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.14.tgz", + "integrity": "sha512-5d2RhCard1nQUC3aHcq/gHzWYO6K0WJmAbjO7mQJgCQKtZpgXxv1rOM6O/dBDhDYYVutk1sciOgNSe+5YyfM8A==" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.27.0.tgz", + "integrity": "sha512-DDrIA7GXtmHXr1VCcx9HivA39eprYBIFxbQEHI6NyraRDxCGpxAFiYQAT/1Y0vh1C+o2vfBiy4IuPoXxtTZCAQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "5.27.0", + "@typescript-eslint/type-utils": "5.27.0", + "@typescript-eslint/utils": "5.27.0", + "debug": "^4.3.4", + "functional-red-black-tree": "^1.0.1", + "ignore": "^5.2.0", + "regexpp": "^3.2.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.27.0.tgz", + "integrity": "sha512-8oGjQF46c52l7fMiPPvX4It3u3V3JipssqDfHQ2hcR0AeR8Zge+OYyKUCm5b70X72N1qXt0qgHenwN6Gc2SXZA==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "5.27.0", + "@typescript-eslint/types": "5.27.0", + "@typescript-eslint/typescript-estree": "5.27.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.27.0.tgz", + "integrity": "sha512-VnykheBQ/sHd1Vt0LJ1JLrMH1GzHO+SzX6VTXuStISIsvRiurue/eRkTqSrG0CexHQgKG8shyJfR4o5VYioB9g==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.27.0", + "@typescript-eslint/visitor-keys": "5.27.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.27.0.tgz", + "integrity": "sha512-vpTvRRchaf628Hb/Xzfek+85o//zEUotr1SmexKvTfs7czXfYjXVT/a5yDbpzLBX1rhbqxjDdr1Gyo0x1Fc64g==", + "dev": true, + "dependencies": { + "@typescript-eslint/utils": "5.27.0", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.27.0.tgz", + "integrity": "sha512-lY6C7oGm9a/GWhmUDOs3xAVRz4ty/XKlQ2fOLr8GAIryGn0+UBOoJDWyHer3UgrHkenorwvBnphhP+zPmzmw0A==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.27.0.tgz", + "integrity": "sha512-QywPMFvgZ+MHSLRofLI7BDL+UczFFHyj0vF5ibeChDAJgdTV8k4xgEwF0geFhVlPc1p8r70eYewzpo6ps+9LJQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.27.0", + "@typescript-eslint/visitor-keys": "5.27.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.27.0.tgz", + "integrity": "sha512-nZvCrkIJppym7cIbP3pOwIkAefXOmfGPnCM0LQfzNaKxJHI6VjI8NC662uoiPlaf5f6ymkTy9C3NQXev2mdXmA==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "@typescript-eslint/scope-manager": "5.27.0", + "@typescript-eslint/types": "5.27.0", + "@typescript-eslint/typescript-estree": "5.27.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.27.0.tgz", + "integrity": "sha512-46cYrteA2MrIAjv9ai44OQDUoCZyHeGIc4lsjCUX2WT6r4C+kidz1bNiR4017wHOPUythYeH+Sc7/cFP97KEAA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.27.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@uppy/companion-client": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@uppy/companion-client/-/companion-client-2.1.0.tgz", + "integrity": "sha512-1Zsag2z9kygXuVbUxqHhkTJUmEHwbejjyf7vmm+P/AiVgK3O37JINYBGOpdTJNgbC9UydLBjleXo8peDVgpg8Q==", + "dependencies": { + "@uppy/utils": "^4.0.7", + "namespace-emitter": "^2.0.1" + } + }, + "node_modules/@uppy/core": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@uppy/core/-/core-2.2.0.tgz", + "integrity": "sha512-qdDoNCjrVjjOmFCFCxc+HEbtbQ9K0k6LKNbZZwWK7d4Cx3xEa6VsxmqVhfFL6ekH2gyboqYV8Z5IbRkJT/0Nqg==", + "dependencies": { + "@transloadit/prettier-bytes": "0.0.7", + "@uppy/store-default": "^2.0.3", + "@uppy/utils": "^4.0.7", + "lodash.throttle": "^4.1.1", + "mime-match": "^1.0.2", + "namespace-emitter": "^2.0.1", + "nanoid": "^3.1.25", + "preact": "^10.5.13" + } + }, + "node_modules/@uppy/store-default": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@uppy/store-default/-/store-default-2.0.3.tgz", + "integrity": "sha512-2BGlN1sW0cFv4rOqTK8dfSg579S984N1HxCJxLFqeW9nWD6zd/O8Omyd85tbxGQ+FLZLTmLOm/feD0YeCBMahg==" + }, + "node_modules/@uppy/utils": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@uppy/utils/-/utils-4.0.7.tgz", + "integrity": "sha512-nKViMT8XchKy+NWpb3DtVKuzZBmW7au26LrMq89EsvTwIOT6UR9+7bmz/+zr3+lc7UC7vMgNChIC6G+/Ya9wWQ==", + "dependencies": { + "lodash.throttle": "^4.1.1" + } + }, + "node_modules/@uppy/xhr-upload": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@uppy/xhr-upload/-/xhr-upload-2.1.0.tgz", + "integrity": "sha512-io1uNu7lGkhIkMnt13bu3FYSAdRbBRWl8n/6njYi+727Jyr0XhKfmBYV9OiruFSxLz5Bfxkw2gTs6e0qUb63nA==", + "dependencies": { + "@uppy/companion-client": "^2.1.0", + "@uppy/utils": "^4.0.7", + "nanoid": "^3.1.25" + }, + "peerDependencies": { + "@uppy/core": "^2.2.0" + } + }, + "node_modules/@vitejs/plugin-vue": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-2.3.3.tgz", + "integrity": "sha512-SmQLDyhz+6lGJhPELsBdzXGc+AcaT8stgkbiTFGpXPe8Tl1tJaBw1A6pxDqDuRsVkD8uscrkx3hA7QDOoKYtyw==", + "dev": true, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "vite": "^2.5.10", + "vue": "^3.2.25" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.36.tgz", + "integrity": "sha512-bbyZM5hvBicv0PW3KUfVi+x3ylHnfKG7DOn5wM+f2OztTzTjLEyBb/5yrarIYpmnGitVGbjZqDbODyW4iK8hqw==", + "dependencies": { + "@babel/parser": "^7.16.4", + "@vue/shared": "3.2.36", + "estree-walker": "^2.0.2", + "source-map": "^0.6.1" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.36.tgz", + "integrity": "sha512-tcOTAOiW4s24QLnq+ON6J+GRONXJ+A/mqKCORi0LSlIh8XQlNnlm24y8xIL8la+ZDgkdbjarQ9ZqYSvEja6gVA==", + "dependencies": { + "@vue/compiler-core": "3.2.36", + "@vue/shared": "3.2.36" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.36.tgz", + "integrity": "sha512-AvGb4bTj4W8uQ4BqaSxo7UwTEqX5utdRSMyHy58OragWlt8nEACQ9mIeQh3K4di4/SX+41+pJrLIY01lHAOFOA==", + "dependencies": { + "@babel/parser": "^7.16.4", + "@vue/compiler-core": "3.2.36", + "@vue/compiler-dom": "3.2.36", + "@vue/compiler-ssr": "3.2.36", + "@vue/reactivity-transform": "3.2.36", + "@vue/shared": "3.2.36", + "estree-walker": "^2.0.2", + "magic-string": "^0.25.7", + "postcss": "^8.1.10", + "source-map": "^0.6.1" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.36.tgz", + "integrity": "sha512-+KugInUFRvOxEdLkZwE+W43BqHyhBh0jpYXhmqw1xGq2dmE6J9eZ8UUSOKNhdHtQ/iNLWWeK/wPZkVLUf3YGaw==", + "dependencies": { + "@vue/compiler-dom": "3.2.36", + "@vue/shared": "3.2.36" + } + }, + "node_modules/@vue/devtools-api": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.1.4.tgz", + "integrity": "sha512-IiA0SvDrJEgXvVxjNkHPFfDx6SXw0b/TUkqMcDZWNg9fnCAHbTpoo59YfJ9QLFkwa3raau5vSlRVzMSLDnfdtQ==" + }, + "node_modules/@vue/reactivity": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.36.tgz", + "integrity": "sha512-c2qvopo0crh9A4GXi2/2kfGYMxsJW4tVILrqRPydVGZHhq0fnzy6qmclWOhBFckEhmyxmpHpdJtIRYGeKcuhnA==", + "dependencies": { + "@vue/shared": "3.2.36" + } + }, + "node_modules/@vue/reactivity-transform": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.2.36.tgz", + "integrity": "sha512-Jk5o2BhpODC9XTA7o4EL8hSJ4JyrFWErLtClG3NH8wDS7ri9jBDWxI7/549T7JY9uilKsaNM+4pJASLj5dtRwA==", + "dependencies": { + "@babel/parser": "^7.16.4", + "@vue/compiler-core": "3.2.36", + "@vue/shared": "3.2.36", + "estree-walker": "^2.0.2", + "magic-string": "^0.25.7" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.2.36.tgz", + "integrity": "sha512-PTWBD+Lub+1U3/KhbCExrfxyS14hstLX+cBboxVHaz+kXoiDLNDEYAovPtxeTutbqtClIXtft+wcGdC+FUQ9qQ==", + "dependencies": { + "@vue/reactivity": "3.2.36", + "@vue/shared": "3.2.36" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.2.36.tgz", + "integrity": "sha512-gYPYblm7QXHVuBohqNRRT7Wez0f2Mx2D40rb4fleehrJU9CnkjG0phhcGEZFfGwCmHZRqBCRgbFWE98bPULqkg==", + "dependencies": { + "@vue/runtime-core": "3.2.36", + "@vue/shared": "3.2.36", + "csstype": "^2.6.8" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.2.36.tgz", + "integrity": "sha512-uZE0+jfye6yYXWvAQYeHZv+f50sRryvy16uiqzk3jn8hEY8zTjI+rzlmZSGoE915k+W/Ol9XSw6vxOUD8dGkUg==", + "dependencies": { + "@vue/compiler-ssr": "3.2.36", + "@vue/shared": "3.2.36" + }, + "peerDependencies": { + "vue": "3.2.36" + } + }, + "node_modules/@vue/shared": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.36.tgz", + "integrity": "sha512-JtB41wXl7Au3+Nl3gD16Cfpj7k/6aCroZ6BbOiCMFCMvrOpkg/qQUXTso2XowaNqBbnkuGHurLAqkLBxNGc1hQ==" + }, + "node_modules/@vueuse/core": { + "version": "8.9.2", + "resolved": "https://registry.npmmirror.com/@vueuse/core/-/core-8.9.2.tgz", + "integrity": "sha512-dE3/JgwqIHmmtmRBdZAnq87rZCSFbYVps2t3gWy9Jv/+Qp6sHSSKuPFtwguJVZ2OnaGnB/AMRmx4CuFRxFin3A==", + "dependencies": { + "@types/web-bluetooth": "^0.0.14", + "@vueuse/metadata": "8.9.2", + "@vueuse/shared": "8.9.2", + "vue-demi": "*" + }, + "peerDependencies": { + "@vue/composition-api": "^1.1.0", + "vue": "^2.6.0 || ^3.2.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + }, + "vue": { + "optional": true + } + } + }, + "node_modules/@vueuse/core/node_modules/@vueuse/shared": { + "version": "8.9.2", + "resolved": "https://registry.npmmirror.com/@vueuse/shared/-/shared-8.9.2.tgz", + "integrity": "sha512-s4Nk82oheL5z1GywyGnqjob0MzbAt88olMZa0vgt/p3gcMsT8Ff7+SqmNgEFC6AAs6xiuhOAZpnew9Zs3d90yQ==", + "dependencies": { + "vue-demi": "*" + }, + "peerDependencies": { + "@vue/composition-api": "^1.1.0", + "vue": "^2.6.0 || ^3.2.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + }, + "vue": { + "optional": true + } + } + }, + "node_modules/@vueuse/core/node_modules/vue-demi": { + "version": "0.13.4", + "resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.13.4.tgz", + "integrity": "sha512-KP4lq9uSz0KZbaqCllRhnxMV3mYRsRWJfdsAhZyt5bV5O1RTpoeDptBRV9NOa/JgOpfaA9ane88VF7OjWNK/DA==", + "hasInstallScript": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/@vueuse/metadata": { + "version": "8.9.2", + "resolved": "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-8.9.2.tgz", + "integrity": "sha512-g2s2BeyeEtJElmMFfFPnM+BTvnt0omniyvz8U18/zXDpQIMGozlNQgHoFeratyMfgVBhH/u2VKzmchChtDsgPQ==" + }, + "node_modules/@vueuse/shared": { + "version": "9.1.1", + "resolved": "https://registry.npmmirror.com/@vueuse/shared/-/shared-9.1.1.tgz", + "integrity": "sha512-c+IfcOYmHiHqoEa3ED1Tbpue5GHmoUmTp8PtO4YbczthtY155Rt6DmWhjxMLXBF1Bcidagxljmp/7xtAzEHXLw==", + "dependencies": { + "vue-demi": "*" + } + }, + "node_modules/@vueuse/shared/node_modules/vue-demi": { + "version": "0.13.11", + "resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.13.11.tgz", + "integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==", + "hasInstallScript": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/@wangeditor/basic-modules": { + "version": "1.1.3", + "resolved": "https://registry.npmmirror.com/@wangeditor/basic-modules/-/basic-modules-1.1.3.tgz", + "integrity": "sha512-TGJix4UelO46yAgwI946ctx4lSIJbYBwNvjSJ9Tf8mKr0WMCeLVBV+MV85rXPsfcmWtR4wBNwSg648Z+RbqRUg==", + "dependencies": { + "is-url": "^1.2.4" + }, + "peerDependencies": { + "@wangeditor/core": "1.x", + "dom7": "^3.0.0", + "lodash.throttle": "^4.1.1", + "nanoid": "^3.2.0", + "slate": "^0.72.0", + "snabbdom": "^3.1.0" + } + }, + "node_modules/@wangeditor/code-highlight": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@wangeditor/code-highlight/-/code-highlight-1.0.2.tgz", + "integrity": "sha512-SCtOcUxjKqIso/LSxGSOaYr3G6MC2En0gNTyHIMCG928T0fo0ufaqp/vIXKQzVL2Y+X/CSAOB2EbrFlgGvr0AQ==", + "dependencies": { + "prismjs": "^1.23.0" + }, + "peerDependencies": { + "@wangeditor/core": "1.x", + "dom7": "^3.0.0", + "slate": "^0.72.0", + "snabbdom": "^3.1.0" + } + }, + "node_modules/@wangeditor/core": { + "version": "1.1.11", + "resolved": "https://registry.npmmirror.com/@wangeditor/core/-/core-1.1.11.tgz", + "integrity": "sha512-BwHVRJzESnkjKikTc2U2zsbd06l1pSo7qKy5+SpZLudYWrFxmd85VN+5GxM57FodogkNw/k04DFHcFSUfXcaKA==", + "dependencies": { + "@types/event-emitter": "^0.3.3", + "event-emitter": "^0.3.5", + "html-void-elements": "^2.0.0", + "i18next": "^20.4.0", + "scroll-into-view-if-needed": "^2.2.28", + "slate-history": "^0.66.0" + }, + "peerDependencies": { + "@uppy/core": "^2.1.1", + "@uppy/xhr-upload": "^2.0.3", + "dom7": "^3.0.0", + "is-hotkey": "^0.2.0", + "lodash.camelcase": "^4.3.0", + "lodash.clonedeep": "^4.5.0", + "lodash.debounce": "^4.0.8", + "lodash.foreach": "^4.5.0", + "lodash.isequal": "^4.5.0", + "lodash.throttle": "^4.1.1", + "lodash.toarray": "^4.4.0", + "nanoid": "^3.2.0", + "slate": "^0.72.0", + "snabbdom": "^3.1.0" + } + }, + "node_modules/@wangeditor/editor": { + "version": "5.1.14", + "resolved": "https://registry.npmmirror.com/@wangeditor/editor/-/editor-5.1.14.tgz", + "integrity": "sha512-erILPAkpKldyGi4cEwrOW65v12GhZy2qj2A8kPlypU46lE72Y3XowZxWogN1TI/mqMDR84AHr0QWOvygOV1xwQ==", + "dependencies": { + "@uppy/core": "^2.1.1", + "@uppy/xhr-upload": "^2.0.3", + "@wangeditor/basic-modules": "^1.1.3", + "@wangeditor/code-highlight": "^1.0.2", + "@wangeditor/core": "^1.1.11", + "@wangeditor/list-module": "^1.0.2", + "@wangeditor/table-module": "^1.1.1", + "@wangeditor/upload-image-module": "^1.0.1", + "@wangeditor/video-module": "^1.1.1", + "dom7": "^3.0.0", + "is-hotkey": "^0.2.0", + "lodash.camelcase": "^4.3.0", + "lodash.clonedeep": "^4.5.0", + "lodash.debounce": "^4.0.8", + "lodash.foreach": "^4.5.0", + "lodash.isequal": "^4.5.0", + "lodash.throttle": "^4.1.1", + "lodash.toarray": "^4.4.0", + "nanoid": "^3.2.0", + "slate": "^0.72.0", + "snabbdom": "^3.1.0" + } + }, + "node_modules/@wangeditor/list-module": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@wangeditor/list-module/-/list-module-1.0.2.tgz", + "integrity": "sha512-VfENZEFvsLTiLxN/cj8cibFGy9NVV+/cfATTiLiH9ef+8lgKv8apttXYVlqIAfnlJLLuCk0cIm8c/zH+hbtrZg==", + "peerDependencies": { + "@wangeditor/core": "1.x", + "dom7": "^3.0.0", + "slate": "^0.72.0", + "snabbdom": "^3.1.0" + } + }, + "node_modules/@wangeditor/table-module": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/@wangeditor/table-module/-/table-module-1.1.1.tgz", + "integrity": "sha512-VPjEWQtncS2DsXYXiHUxPSxn2Xhc8GdhG3la7N5YhvxQde1+4N0SZLXeWsYvbGzOq4um5XToq5pktLLbE8G+EA==", + "peerDependencies": { + "@wangeditor/core": "1.x", + "dom7": "^3.0.0", + "lodash.isequal": "^4.5.0", + "lodash.throttle": "^4.1.1", + "nanoid": "^3.2.0", + "slate": "^0.72.0", + "snabbdom": "^3.1.0" + } + }, + "node_modules/@wangeditor/upload-image-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@wangeditor/upload-image-module/-/upload-image-module-1.0.1.tgz", + "integrity": "sha512-vgUV4ENttTITblqtVuzleIq732OmzmzzgrIvX6b3GRGPSw5u8glJ/87tOEhvHjHECc4oFo18B7xzJ1GpBj79/w==", + "peerDependencies": { + "@uppy/core": "^2.0.3", + "@uppy/xhr-upload": "^2.0.3", + "@wangeditor/basic-modules": "1.x", + "@wangeditor/core": "1.x", + "dom7": "^3.0.0", + "lodash.foreach": "^4.5.0", + "slate": "^0.72.0", + "snabbdom": "^3.1.0" + } + }, + "node_modules/@wangeditor/video-module": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/@wangeditor/video-module/-/video-module-1.1.1.tgz", + "integrity": "sha512-6gzpS5cnJihW2T0HFjqmbv6v8ouyaeMUjdM2X8BPohwD74p1ov00dCmRt5QekNTyYSmRHK0ASkUMOvRGqaDxMg==", + "peerDependencies": { + "@uppy/core": "^2.1.4", + "@uppy/xhr-upload": "^2.0.7", + "@wangeditor/core": "1.x", + "dom7": "^3.0.0", + "nanoid": "^3.2.0", + "slate": "^0.72.0", + "snabbdom": "^3.1.0" + } + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", + "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", + "dev": true, + "peer": true, + "dependencies": { + "@webassemblyjs/helper-numbers": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", + "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==", + "dev": true, + "peer": true + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", + "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", + "dev": true, + "peer": true + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", + "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", + "dev": true, + "peer": true + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", + "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", + "dev": true, + "peer": true, + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", + "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", + "dev": true, + "peer": true + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", + "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", + "dev": true, + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", + "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", + "dev": true, + "peer": true, + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", + "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", + "dev": true, + "peer": true, + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", + "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", + "dev": true, + "peer": true + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", + "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", + "dev": true, + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/helper-wasm-section": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-opt": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "@webassemblyjs/wast-printer": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", + "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", + "dev": true, + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", + "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", + "dev": true, + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", + "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", + "dev": true, + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", + "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", + "dev": true, + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true, + "peer": true + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true, + "peer": true + }, + "node_modules/acorn": { + "version": "8.7.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", + "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-assertions": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", + "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", + "dev": true, + "peer": true, + "peerDependencies": { + "acorn": "^8" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/adler-32": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.3.1.tgz", + "integrity": "sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peer": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/async-validator": { + "version": "4.2.5", + "resolved": "https://registry.npmmirror.com/async-validator/-/async-validator-4.2.5.tgz", + "integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/axios": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", + "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", + "dependencies": { + "follow-redirects": "^1.14.9", + "form-data": "^4.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/batch-processor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/batch-processor/-/batch-processor-1.0.0.tgz", + "integrity": "sha512-xoLQD8gmmR32MeuBHgH0Tzd5PuSZx71ZsbhVxOCRbgktZEPe4SQy7s9Z50uPp0F/f7iw2XmkHN2xkgbMfckMDA==" + }, + "node_modules/bignumber.js": { + "version": "9.0.2", + "resolved": "https://registry.npmmirror.com/bignumber.js/-/bignumber.js-9.0.2.tgz", + "integrity": "sha512-GAcQvbpsM0pUb0zw1EI0KhQEZ+lRwR5fYaAp3vPOYuP7aDvGy6cVN6XHLauvF8SOga2y0dcLcjt3iQDTSEliyw==", + "engines": { + "node": "*" + } + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.20.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.3.tgz", + "integrity": "sha512-NBhymBQl1zM0Y5dQT/O+xiLP9/rzOIQdKM/eMJBAq7yBgaB6krIYLGejrwVYnSHZdqjscB1SPuAjHwxjvN6Wdg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "peer": true, + "dependencies": { + "caniuse-lite": "^1.0.30001332", + "electron-to-chromium": "^1.4.118", + "escalade": "^3.1.1", + "node-releases": "^2.0.3", + "picocolors": "^1.0.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true, + "peer": true + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001342", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001342.tgz", + "integrity": "sha512-bn6sOCu7L7jcbBbyNhLg0qzXdJ/PMbybZTH/BA6Roet9wxYRm6Tr9D0s0uhLkOZ6MSG+QU6txUgdpr3MXIVqjA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + } + ], + "peer": true + }, + "node_modules/cfb": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cfb/-/cfb-1.2.2.tgz", + "integrity": "sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==", + "dependencies": { + "adler-32": "~1.3.0", + "crc-32": "~1.2.0" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/claygl": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/claygl/-/claygl-1.3.0.tgz", + "integrity": "sha512-+gGtJjT6SSHD2l2yC3MCubW/sCV40tZuSs5opdtn79vFSGUgp/lH139RNEQ6Jy078/L0aV8odCw8RSrUcMfLaQ==" + }, + "node_modules/clipboard": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.11.tgz", + "integrity": "sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==", + "dependencies": { + "good-listener": "^1.2.2", + "select": "^1.1.2", + "tiny-emitter": "^2.0.0" + } + }, + "node_modules/codepage": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/codepage/-/codepage-1.15.0.tgz", + "integrity": "sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true, + "peer": true + }, + "node_modules/compute-scroll-into-view": { + "version": "1.0.17", + "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-1.0.17.tgz", + "integrity": "sha512-j4dx+Fb0URmzbwwMUrhqWM2BEWHdFGx+qZ9qqASHRPqvTYdqvWnHg0H1hIbcyLnvgnoNAVMlwkepyqM3DaIFUg==" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "node_modules/core-js-pure": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.25.0.tgz", + "integrity": "sha512-IeHpLwk3uoci37yoI2Laty59+YqH9x5uR65/yiA0ARAJrTrN4YU0rmauLWfvqOuk77SlNJXj2rM6oT/dBD87+A==", + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/countup.js": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/countup.js/-/countup.js-2.2.0.tgz", + "integrity": "sha512-m0TvFNXm9/eFqJm+QiKVI8e0wRUHzlQSewz9dqVjlhl2DFoZtceLbomwzxHz0hJ1+r4zBC7wSpR/TpthG49h6g==" + }, + "node_modules/crc-32": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/cropperjs": { + "version": "1.5.12", + "resolved": "https://registry.npmjs.org/cropperjs/-/cropperjs-1.5.12.tgz", + "integrity": "sha512-re7UdjE5UnwdrovyhNzZ6gathI4Rs3KGCBSc8HCIjUo5hO42CtzyblmWLj6QWVw7huHyDMfpKxhiO2II77nhDw==" + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csstype": { + "version": "2.6.20", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.20.tgz", + "integrity": "sha512-/WwNkdXfckNgw6S5R125rrW8ez139lBHWouiBvX8dfMFtcn6V81REDqnH7+CRpRipfYlyU1CmOnOxrmGcFOjeA==" + }, + "node_modules/d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "dependencies": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, + "node_modules/dayjs": { + "version": "1.11.3", + "resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.3.tgz", + "integrity": "sha512-xxwlswWOlGhzgQ4TKzASQkUhqERI3egRNqgV4ScR8wlANA/A9tZ7miXa44vTTKEq5l7vWoL5G57bG3zA+Kow0A==" + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/delegate": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz", + "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==" + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dom7": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/dom7/-/dom7-3.0.0.tgz", + "integrity": "sha512-oNlcUdHsC4zb7Msx7JN3K0Nro1dzJ48knvBOnDPKJ2GV9wl1i5vydJZUSyOfrkKFDZEud/jBsTk92S/VGSAe/g==", + "dependencies": { + "ssr-window": "^3.0.0-alpha.1" + } + }, + "node_modules/dotenv": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.1.tgz", + "integrity": "sha512-1K6hR6wtk2FviQ4kEiSjFiH5rpzEVi8WW0x96aztHVMhEspNpc4DVOUTEHtEva5VThQ8IaBX1Pe4gSzpVVUsKQ==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/echarts": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/echarts/-/echarts-5.3.3.tgz", + "integrity": "sha512-BRw2serInRwO5SIwRviZ6Xgm5Lb7irgz+sLiFMmy/HOaf4SQ+7oYqxKzRHAKp4xHQ05AuHw1xvoQWJjDQq/FGw==", + "dependencies": { + "tslib": "2.3.0", + "zrender": "5.3.2" + } + }, + "node_modules/echarts-gl": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/echarts-gl/-/echarts-gl-2.0.9.tgz", + "integrity": "sha512-oKeMdkkkpJGWOzjgZUsF41DOh6cMsyrGGXimbjK2l6Xeq/dBQu4ShG2w2Dzrs/1bD27b2pLTGSaUzouY191gzA==", + "dependencies": { + "claygl": "^1.2.1", + "zrender": "^5.1.1" + }, + "peerDependencies": { + "echarts": "^5.1.2" + } + }, + "node_modules/echarts-wordcloud": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/echarts-wordcloud/-/echarts-wordcloud-2.0.0.tgz", + "integrity": "sha512-K7l6pTklqdW7ZWzT/1CS0KhBSINr/cd7c5N1fVMzZMwLQHEwT7x+nivK7g5hkVh7WNcAv4Dn6/ZS5zMKRozC1g==", + "peerDependencies": { + "echarts": "^5.0.1" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.4.137", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.137.tgz", + "integrity": "sha512-0Rcpald12O11BUogJagX3HsCN3FE83DSqWjgXoHo5a72KUKMSfI39XBgJpgNNxS9fuGzytaFjE06kZkiVFy2qA==", + "dev": true, + "peer": true + }, + "node_modules/element-plus": { + "version": "2.2.9", + "resolved": "https://registry.npmmirror.com/element-plus/-/element-plus-2.2.9.tgz", + "integrity": "sha512-jYbL0JkCdv95rkT6trZJjCAizLPySa0qcd2cgq+57SKQnCZAcNDDq4GbTuFRnNavdoeCJnuM3HIficTIUpsMOQ==", + "dependencies": { + "@ctrl/tinycolor": "^3.4.1", + "@element-plus/icons-vue": "^2.0.6", + "@floating-ui/dom": "^0.5.4", + "@popperjs/core": "npm:@sxzz/popperjs-es@^2.11.7", + "@types/lodash": "^4.14.182", + "@types/lodash-es": "^4.17.6", + "@vueuse/core": "^8.7.5", + "async-validator": "^4.2.5", + "dayjs": "^1.11.3", + "escape-html": "^1.0.3", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", + "lodash-unified": "^1.0.2", + "memoize-one": "^6.0.0", + "normalize-wheel-es": "^1.1.2" + }, + "peerDependencies": { + "vue": "^3.2.0" + } + }, + "node_modules/element-resize-detector": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/element-resize-detector/-/element-resize-detector-1.2.4.tgz", + "integrity": "sha512-Fl5Ftk6WwXE0wqCgNoseKWndjzZlDCwuPTcoVZfCP9R3EHQF8qUtr3YUPNETegRBOKqQKPW3n4kiIWngGi8tKg==", + "dependencies": { + "batch-processor": "1.0.0" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.3.tgz", + "integrity": "sha512-Bq9VSor+kjvW3f9/MiiR4eE3XYgOl7/rS8lnSxbRbF3kS0B2r+Y9w5krBWxZgDxASVZbdYrn5wT4j/Wb0J9qow==", + "dev": true, + "peer": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/es-module-lexer": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", + "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", + "dev": true, + "peer": true + }, + "node_modules/es5-ext": { + "version": "0.10.61", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.61.tgz", + "integrity": "sha512-yFhIqQAzu2Ca2I4SE2Au3rxVfmohU9Y7wqGR+s7+H7krk26NXhIRAZDgqd6xqjCEFUomDEA3/Bo/7fKmIkW1kA==", + "hasInstallScript": true, + "dependencies": { + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.3", + "next-tick": "^1.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "dependencies": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "dependencies": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "node_modules/esbuild": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.39.tgz", + "integrity": "sha512-2kKujuzvRWYtwvNjYDY444LQIA3TyJhJIX3Yo4+qkFlDDtGlSicWgeHVJqMUP/2sSfH10PGwfsj+O2ro1m10xQ==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "esbuild-android-64": "0.14.39", + "esbuild-android-arm64": "0.14.39", + "esbuild-darwin-64": "0.14.39", + "esbuild-darwin-arm64": "0.14.39", + "esbuild-freebsd-64": "0.14.39", + "esbuild-freebsd-arm64": "0.14.39", + "esbuild-linux-32": "0.14.39", + "esbuild-linux-64": "0.14.39", + "esbuild-linux-arm": "0.14.39", + "esbuild-linux-arm64": "0.14.39", + "esbuild-linux-mips64le": "0.14.39", + "esbuild-linux-ppc64le": "0.14.39", + "esbuild-linux-riscv64": "0.14.39", + "esbuild-linux-s390x": "0.14.39", + "esbuild-netbsd-64": "0.14.39", + "esbuild-openbsd-64": "0.14.39", + "esbuild-sunos-64": "0.14.39", + "esbuild-windows-32": "0.14.39", + "esbuild-windows-64": "0.14.39", + "esbuild-windows-arm64": "0.14.39" + } + }, + "node_modules/esbuild-android-64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.39.tgz", + "integrity": "sha512-EJOu04p9WgZk0UoKTqLId9VnIsotmI/Z98EXrKURGb3LPNunkeffqQIkjS2cAvidh+OK5uVrXaIP229zK6GvhQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-android-arm64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.39.tgz", + "integrity": "sha512-+twajJqO7n3MrCz9e+2lVOnFplRsaGRwsq1KL/uOy7xK7QdRSprRQcObGDeDZUZsacD5gUkk6OiHiYp6RzU3CA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-darwin-64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.39.tgz", + "integrity": "sha512-ImT6eUw3kcGcHoUxEcdBpi6LfTRWaV6+qf32iYYAfwOeV+XaQ/Xp5XQIBiijLeo+LpGci9M0FVec09nUw41a5g==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-darwin-arm64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.39.tgz", + "integrity": "sha512-/fcQ5UhE05OiT+bW5v7/up1bDsnvaRZPJxXwzXsMRrr7rZqPa85vayrD723oWMT64dhrgWeA3FIneF8yER0XTw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-freebsd-64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.39.tgz", + "integrity": "sha512-oMNH8lJI4wtgN5oxuFP7BQ22vgB/e3Tl5Woehcd6i2r6F3TszpCnNl8wo2d/KvyQ4zvLvCWAlRciumhQg88+kQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-freebsd-arm64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.39.tgz", + "integrity": "sha512-1GHK7kwk57ukY2yI4ILWKJXaxfr+8HcM/r/JKCGCPziIVlL+Wi7RbJ2OzMcTKZ1HpvEqCTBT/J6cO4ZEwW4Ypg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-32": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.39.tgz", + "integrity": "sha512-g97Sbb6g4zfRLIxHgW2pc393DjnkTRMeq3N1rmjDUABxpx8SjocK4jLen+/mq55G46eE2TA0MkJ4R3SpKMu7dg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.39.tgz", + "integrity": "sha512-4tcgFDYWdI+UbNMGlua9u1Zhu0N5R6u9tl5WOM8aVnNX143JZoBZLpCuUr5lCKhnD0SCO+5gUyMfupGrHtfggQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-arm": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.39.tgz", + "integrity": "sha512-t0Hn1kWVx5UpCzAJkKRfHeYOLyFnXwYynIkK54/h3tbMweGI7dj400D1k0Vvtj2u1P+JTRT9tx3AjtLEMmfVBQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-arm64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.39.tgz", + "integrity": "sha512-23pc8MlD2D6Px1mV8GMglZlKgwgNKAO8gsgsLLcXWSs9lQsCYkIlMo/2Ycfo5JrDIbLdwgP8D2vpfH2KcBqrDQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-mips64le": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.39.tgz", + "integrity": "sha512-epwlYgVdbmkuRr5n4es3B+yDI0I2e/nxhKejT9H0OLxFAlMkeQZxSpxATpDc9m8NqRci6Kwyb/SfmD1koG2Zuw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-ppc64le": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.39.tgz", + "integrity": "sha512-W/5ezaq+rQiQBThIjLMNjsuhPHg+ApVAdTz2LvcuesZFMsJoQAW2hutoyg47XxpWi7aEjJGrkS26qCJKhRn3QQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-riscv64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.39.tgz", + "integrity": "sha512-IS48xeokcCTKeQIOke2O0t9t14HPvwnZcy+5baG13Z1wxs9ZrC5ig5ypEQQh4QMKxURD5TpCLHw2W42CLuVZaA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-s390x": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.39.tgz", + "integrity": "sha512-zEfunpqR8sMomqXhNTFEKDs+ik7HC01m3M60MsEjZOqaywHu5e5682fMsqOlZbesEAAaO9aAtRBsU7CHnSZWyA==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-netbsd-64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.39.tgz", + "integrity": "sha512-Uo2suJBSIlrZCe4E0k75VDIFJWfZy+bOV6ih3T4MVMRJh1lHJ2UyGoaX4bOxomYN3t+IakHPyEoln1+qJ1qYaA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-openbsd-64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.39.tgz", + "integrity": "sha512-secQU+EpgUPpYjJe3OecoeGKVvRMLeKUxSMGHnK+aK5uQM3n1FPXNJzyz1LHFOo0WOyw+uoCxBYdM4O10oaCAA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-sunos-64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.39.tgz", + "integrity": "sha512-qHq0t5gePEDm2nqZLb+35p/qkaXVS7oIe32R0ECh2HOdiXXkj/1uQI9IRogGqKkK+QjDG+DhwiUw7QoHur/Rwg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-32": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.39.tgz", + "integrity": "sha512-XPjwp2OgtEX0JnOlTgT6E5txbRp6Uw54Isorm3CwOtloJazeIWXuiwK0ONJBVb/CGbiCpS7iP2UahGgd2p1x+Q==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.39.tgz", + "integrity": "sha512-E2wm+5FwCcLpKsBHRw28bSYQw0Ikxb7zIMxw3OPAkiaQhLVr3dnVO8DofmbWhhf6b97bWzg37iSZ45ZDpLw7Ow==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-arm64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.39.tgz", + "integrity": "sha512-sBZQz5D+Gd0EQ09tZRnz/PpVdLwvp/ufMtJ1iDFYddDaPpZXKqPyaxfYBLs3ueiaksQ26GGa7sci0OqFzNs7KA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.17.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.17.0.tgz", + "integrity": "sha512-gq0m0BTJfci60Fz4nczYxNAlED+sMcihltndR8t9t1evnU/azx53x3t2UHXC/uRjcbvRw/XctpaNygSTcQD+Iw==", + "dev": true, + "dependencies": { + "@eslint/eslintrc": "^1.3.0", + "@humanwhocodes/config-array": "^0.9.2", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.1.1", + "eslint-utils": "^3.0.0", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.3.2", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^6.0.1", + "globals": "^13.15.0", + "ignore": "^5.2.0", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "regexpp": "^3.2.0", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-plugin-vue": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.1.0.tgz", + "integrity": "sha512-EPCeInPicQ/YyfOWJDr1yfEeSNoFCMzUus107lZyYi37xejdOolNzS5MXGXp8+9bkoKZMdv/1AcZzQebME6r+g==", + "dev": true, + "dependencies": { + "eslint-utils": "^3.0.0", + "natural-compare": "^1.4.0", + "nth-check": "^2.0.1", + "postcss-selector-parser": "^6.0.9", + "semver": "^7.3.5", + "vue-eslint-parser": "^9.0.1", + "xml-name-validator": "^4.0.0" + }, + "engines": { + "node": "^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^2.0.0" + }, + "engines": { + "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=5" + } + }, + "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", + "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/eslint/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/espree": { + "version": "9.3.2", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.2.tgz", + "integrity": "sha512-D211tC7ZwouTIuY5x9XnS0E9sWNChB7IYKX/Xp5eQj3nFXhqmiUDB9q27y76oFl8jTg3pXcQx/bpxMfs3CIZbA==", + "dev": true, + "dependencies": { + "acorn": "^8.7.1", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "dependencies": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/ext": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz", + "integrity": "sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==", + "dependencies": { + "type": "^2.5.0" + } + }, + "node_modules/ext/node_modules/type": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.6.0.tgz", + "integrity": "sha512-eiDBDOmkih5pMbo9OqsqPRGMljLodLcwd5XD5JbtNB0o89xZAwynY9EdCDsJU7LtcVCClu9DvM7/0Ep1hYX3EQ==" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", + "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "node_modules/fastq": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "dependencies": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", + "dev": true + }, + "node_modules/follow-redirects": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.0.tgz", + "integrity": "sha512-aExlJShTV4qOUOL7yF1U5tvLCB0xQuudbf6toyYA0E/acBNw71mvjFTnLaRp50aQaYocMR0a/RMMBIHeZnGyjQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/frac": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/frac/-/frac-1.1.2.tgz", + "integrity": "sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true, + "peer": true + }, + "node_modules/globals": { + "version": "13.15.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.15.0.tgz", + "integrity": "sha512-bpzcOlgDhMG070Av0Vy5Owklpv1I6+j96GhUI7Rh7IzDCKLzboflLrrfqMu8NquDbiR4EOQk7XzJwqVJxicxog==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/good-listener": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz", + "integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=", + "dependencies": { + "delegate": "^3.1.2" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true, + "peer": true + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/html-void-elements": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-2.0.1.tgz", + "integrity": "sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/i18next": { + "version": "20.6.1", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-20.6.1.tgz", + "integrity": "sha512-yCMYTMEJ9ihCwEQQ3phLo7I/Pwycf8uAx+sRHwwk5U9Aui/IZYgQRyMqXafQOw5QQ7DM1Z+WyEXWIqSuJHhG2A==", + "dependencies": { + "@babel/runtime": "^7.12.0" + } + }, + "node_modules/ignore": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/immer": { + "version": "9.0.14", + "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.14.tgz", + "integrity": "sha512-ubBeqQutOSLIFCUBN03jGeOS6a3DoYlSYwYJTa+gSKEZKU5redJIqkIdZ3JVv/4RZpfcXdAWH5zCNLWPRv2WDw==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, + "node_modules/immutable": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.0.0.tgz", + "integrity": "sha512-zIE9hX70qew5qTUjSS7wi1iwj/l7+m54KWU247nhM3v806UdGj1yDndXj+IOYxxtW9zyLI+xqFNZjTuDaLUqFw==", + "dev": true + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", + "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-hotkey": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/is-hotkey/-/is-hotkey-0.2.0.tgz", + "integrity": "sha512-UknnZK4RakDmTgz4PI1wIph5yxSs/mvChWs9ifnlXsKuXgWmOkY/hAE0H/k2MIqH0RlRye0i1oC07MCRSD28Mw==" + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-url": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", + "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "peer": true, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/js-base64": { + "version": "3.7.2", + "resolved": "https://registry.npmmirror.com/js-base64/-/js-base64-3.7.2.tgz", + "integrity": "sha512-NnRs6dsyqUXejqk/yv2aiXlAvOs56sLkX6nUdeaNezI5LFFLlsZjOThmwnrcwh5ZZRwZlCMnVAY3CvhIhoVEKQ==" + }, + "node_modules/js-cookie": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.1.tgz", + "integrity": "sha512-+0rgsUXZu4ncpPxRL+lNEptWMOWl9etvPHc/koSRp6MPwpRYAhmk0dUG00J4bxVV3r9uUzfo24wW0knS07SKSw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/json-bigint/-/json-bigint-1.0.0.tgz", + "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "dependencies": { + "bignumber.js": "^9.0.0" + } + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, + "peer": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "node_modules/jsplumb": { + "version": "2.15.6", + "resolved": "https://registry.npmjs.org/jsplumb/-/jsplumb-2.15.6.tgz", + "integrity": "sha512-sIpbpz5eMVM+vV+MQzFCidlaa1RsknrQs6LOTKYDjYUDdTAi2AN2bFi94TxB33TifcIsRNV1jebcaxg0tCoPzg==" + }, + "node_modules/klona": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.5.tgz", + "integrity": "sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6.11.5" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmmirror.com/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + }, + "node_modules/lodash-unified": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/lodash-unified/-/lodash-unified-1.0.2.tgz", + "integrity": "sha512-OGbEy+1P+UT26CYi4opY4gebD8cWRDxAT6MAObIVQMiqYdxZr1g3QHWCToVsm31x2NkLS4K3+MC2qInaRMa39g==", + "peerDependencies": { + "@types/lodash-es": "*", + "lodash": "*", + "lodash-es": "*" + } + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=" + }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=" + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=" + }, + "node_modules/lodash.foreach": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz", + "integrity": "sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM=" + }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", + "dev": true, + "peer": true + }, + "node_modules/lodash.throttle": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", + "integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ=" + }, + "node_modules/lodash.toarray": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.toarray/-/lodash.toarray-4.4.0.tgz", + "integrity": "sha1-JMS/zWsvuji/0FlNsRedjptlZWE=" + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/magic-string": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", + "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "dependencies": { + "sourcemap-codec": "^1.4.8" + } + }, + "node_modules/memoize-one": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/memoize-one/-/memoize-one-6.0.0.tgz", + "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==" + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true, + "peer": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/mime-match/-/mime-match-1.0.2.tgz", + "integrity": "sha1-P4fDHprxpf1IX7nbE0Qosju7e6g=", + "dependencies": { + "wildcard": "^1.1.0" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/mitt": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.0.tgz", + "integrity": "sha512-7dX2/10ITVyqh4aOSVI9gdape+t9l2/8QxHrFmUXu4EEUpdlxl6RudZUPZoc+zuY2hk1j7XxVroIVIan/pD/SQ==" + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/namespace-emitter": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/namespace-emitter/-/namespace-emitter-2.0.1.tgz", + "integrity": "sha512-N/sMKHniSDJBjfrkbS/tpkPj4RAbvW3mr8UAzvlMHyun93XEm83IAvhWtJVHo+RHn/oO8Job5YN4b+wRjSVp5g==" + }, + "node_modules/nanoid": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node_modules/next-tick": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", + "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==" + }, + "node_modules/node-releases": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.4.tgz", + "integrity": "sha512-gbMzqQtTtDz/00jQzZ21PQzdI9PyLYqUSvD0p3naOhX4odFji0ZxYdnVwPTxmSwkmxhcFImpozceidSG+AgoPQ==", + "dev": true, + "peer": true + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-wheel-es": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/normalize-wheel-es/-/normalize-wheel-es-1.1.2.tgz", + "integrity": "sha512-scX83plWJXYH1J4+BhAuIHadROzxX0UBF3+HuZNY2Ks8BciE7tSTQ+5JhTsvzjaO0/EJdm4JBGrfObKxFf3Png==" + }, + "node_modules/nprogress": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/nprogress/-/nprogress-0.2.0.tgz", + "integrity": "sha1-y480xTIT2JVyP8urkH6UIq28r7E=" + }, + "node_modules/nth-check": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz", + "integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pinia": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.0.14.tgz", + "integrity": "sha512-0nPuZR4TetT/WcLN+feMSjWJku3SQU7dBbXC6uw+R6FLQJCsg+/0pzXyD82T1FmAYe0lsx+jnEDQ1BLgkRKlxA==", + "dependencies": { + "@vue/devtools-api": "^6.1.4", + "vue-demi": "*" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "@vue/composition-api": "^1.4.0", + "typescript": ">=4.4.4", + "vue": "^2.6.14 || ^3.2.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/pinia-plugin-persistedstate": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/pinia-plugin-persistedstate/-/pinia-plugin-persistedstate-2.1.1.tgz", + "integrity": "sha512-HUgsU5IRtM75eAQiIqzT3p1oPEuYH1/B2ipTMU++yE+FV0LkHaBswdKXs0RMWYCmugO8s62oxLTh/N1dLNp+5A==", + "peerDependencies": { + "pinia": "^2.0.0" + }, + "peerDependenciesMeta": { + "pinia": { + "optional": true + } + } + }, + "node_modules/pinia/node_modules/vue-demi": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.12.5.tgz", + "integrity": "sha512-BREuTgTYlUr0zw0EZn3hnhC3I6gPWv+Kwh4MCih6QcAeaTlaIX0DwOVN0wHej7hSvDPecz4jygy/idsgKfW58Q==", + "hasInstallScript": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/postcss": { + "version": "8.4.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz", + "integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + } + ], + "dependencies": { + "nanoid": "^3.3.4", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", + "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/preact": { + "version": "10.7.2", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.7.2.tgz", + "integrity": "sha512-GLjn0I3r6ka+NvxJUppsVFqb4V0qDTEHT/QxHlidPuClGaxF/4AI2Qti4a0cv3XMh5n1+D3hLScW10LRIm5msQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.6.2.tgz", + "integrity": "sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew==", + "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/print-js": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/print-js/-/print-js-1.6.0.tgz", + "integrity": "sha512-BfnOIzSKbqGRtO4o0rnj/K3681BSd2QUrsIZy/+WdCIugjIswjmx3lDEZpXB2ruGf9d4b3YNINri81+J0FsBWg==" + }, + "node_modules/prismjs": { + "version": "1.28.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.28.0.tgz", + "integrity": "sha512-8aaXdYvl1F7iC7Xm1spqSaY/OJBpYW3v+KJ+F17iYxvdc8sfjW194COK5wVhMZX45tGteiBQgdvD/nhxcRwylw==", + "engines": { + "node": ">=6" + } + }, + "node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/qrcodejs2-fixes": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/qrcodejs2-fixes/-/qrcodejs2-fixes-0.0.2.tgz", + "integrity": "sha512-wMUXYMOixAEJlLnjk5MbLiFaz0gQObWYm/TIFWB5+j7sTY5gPyr09Cx1EpcLYbsgfFdN3wHjrKAhZofTuCBGhg==" + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "peer": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.13.9", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", + "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" + }, + "node_modules/regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/resolve": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", + "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.8.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rollup": { + "version": "2.74.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.74.1.tgz", + "integrity": "sha512-K2zW7kV8Voua5eGkbnBtWYfMIhYhT9Pel2uhBk2WO5eMee161nPze/XRfvEQPFYz7KgrCCnmh2Wy0AMFLGGmMA==", + "dev": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=10.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "peer": true + }, + "node_modules/sass": { + "version": "1.52.2", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.52.2.tgz", + "integrity": "sha512-mfHB2VSeFS7sZlPv9YohB9GB7yWIgQNTGniQwfQ04EoQN0wsQEv7SwpCwy/x48Af+Z3vDeFXz+iuXM3HK/phZQ==", + "dev": true, + "dependencies": { + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/sass-loader": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-13.0.0.tgz", + "integrity": "sha512-IHCFecI+rbPvXE2zO/mqdVFe8MU7ElGrwga9hh2H65Ru4iaBJAMRteum1c4Gsxi9Cq1FOtTEDd6+/AEYuQDM4Q==", + "dev": true, + "dependencies": { + "klona": "^2.0.4", + "neo-async": "^2.6.2" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "fibers": ">= 3.1.0", + "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0", + "sass": "^1.3.0", + "sass-embedded": "*", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "fibers": { + "optional": true + }, + "node-sass": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + } + } + }, + "node_modules/schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/screenfull": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/screenfull/-/screenfull-6.0.1.tgz", + "integrity": "sha512-yzQW+j4zMUBQC51xxWaoDYjxOtl8Kn+xvue3p6v/fv2pIi1jH4AldgVLU8TBfFVgH2x3VXlf3+YiA/AYIPlaew==", + "engines": { + "node": "^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/scroll-into-view-if-needed": { + "version": "2.2.29", + "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.29.tgz", + "integrity": "sha512-hxpAR6AN+Gh53AdAimHM6C8oTN1ppwVZITihix+WqalywBeFcQ6LdQP5ABNl26nX8GTEL7VT+b8lKpdqq65wXg==", + "dependencies": { + "compute-scroll-into-view": "^1.0.17" + } + }, + "node_modules/select": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz", + "integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=" + }, + "node_modules/semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "dev": true, + "peer": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/slate": { + "version": "0.72.8", + "resolved": "https://registry.npmjs.org/slate/-/slate-0.72.8.tgz", + "integrity": "sha512-/nJwTswQgnRurpK+bGJFH1oM7naD5qDmHd89JyiKNT2oOKD8marW0QSBtuFnwEbL5aGCS8AmrhXQgNOsn4osAw==", + "dependencies": { + "immer": "^9.0.6", + "is-plain-object": "^5.0.0", + "tiny-warning": "^1.0.3" + } + }, + "node_modules/slate-history": { + "version": "0.66.0", + "resolved": "https://registry.npmjs.org/slate-history/-/slate-history-0.66.0.tgz", + "integrity": "sha512-6MWpxGQZiMvSINlCbMW43E2YBSVMCMCIwQfBzGssjWw4kb0qfvj0pIdblWNRQZD0hR6WHP+dHHgGSeVdMWzfng==", + "dependencies": { + "is-plain-object": "^5.0.0" + }, + "peerDependencies": { + "slate": ">=0.65.3" + } + }, + "node_modules/snabbdom": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/snabbdom/-/snabbdom-3.5.0.tgz", + "integrity": "sha512-Ff5BKG18KrrPuskHJlA9aujPHqEabItaDl96l7ZZndF4zt5AYSczz7ZjjgQAX5IBd5cd25lw9NfgX21yVUJ+9g==", + "engines": { + "node": ">=8.3.0" + } + }, + "node_modules/sortablejs": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.0.tgz", + "integrity": "sha512-bv9qgVMjUMf89wAvM6AxVvS/4MX3sPeN0+agqShejLU5z5GX4C75ow1O2e5k4L6XItUyAK3gH6AxSbXrOM5e8w==" + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "peer": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==" + }, + "node_modules/splitpanes": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/splitpanes/-/splitpanes-3.1.1.tgz", + "integrity": "sha512-VUkxDJfIGSvTM/fm/+OSrx8ha9URwE/9B8FPvfzoBuAxVELIHBWpsfnJXIXv77zVwuex//QQL4kTU9SDBPeHjA==" + }, + "node_modules/ssf": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/ssf/-/ssf-0.11.2.tgz", + "integrity": "sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==", + "dependencies": { + "frac": "~1.1.2" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/ssr-window": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ssr-window/-/ssr-window-3.0.0.tgz", + "integrity": "sha512-q+8UfWDg9Itrg0yWK7oe5p/XRCJpJF9OBtXfOPgSJl+u3Xd5KI328RUEvUqSMVM9CiQUEf1QdBzJMkYGErj9QA==" + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/terser": { + "version": "5.13.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.13.1.tgz", + "integrity": "sha512-hn4WKOfwnwbYfe48NgrQjqNOH9jzLqRcIfbYytOXCOv46LBfWr9bDS17MQqOi+BWGD0sJK3Sj5NC/gJjiojaoA==", + "dev": true, + "peer": true, + "dependencies": { + "acorn": "^8.5.0", + "commander": "^2.20.0", + "source-map": "~0.8.0-beta.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.1.tgz", + "integrity": "sha512-GvlZdT6wPQKbDNW/GDQzZFg/j4vKU96yl2q6mcUkzKOgW4gwf1Z8cZToUCrz31XHlPWH8MVb1r2tFtdDtTGJ7g==", + "dev": true, + "peer": true, + "dependencies": { + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.0", + "source-map": "^0.6.1", + "terser": "^5.7.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/terser/node_modules/source-map": { + "version": "0.8.0-beta.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", + "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", + "dev": true, + "peer": true, + "dependencies": { + "whatwg-url": "^7.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "node_modules/tiny-emitter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", + "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==" + }, + "node_modules/tiny-warning": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", + "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", + "dev": true, + "peer": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/tslib": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", + "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==" + }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/tsutils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "4.7.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.3.tgz", + "integrity": "sha512-WOkT3XYvrpXx4vMMqlD+8R8R37fZkjyLGlxavMc4iB8lrl8L0DeTcHbYgw/v0N/z9wAFsgBhcsF0ruoySS22mA==", + "devOptional": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "node_modules/v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true + }, + "node_modules/vite": { + "version": "2.9.9", + "resolved": "https://registry.npmjs.org/vite/-/vite-2.9.9.tgz", + "integrity": "sha512-ffaam+NgHfbEmfw/Vuh6BHKKlI/XIAhxE5QSS7gFLIngxg171mg1P3a4LSRME0z2ZU1ScxoKzphkipcYwSD5Ew==", + "dev": true, + "dependencies": { + "esbuild": "^0.14.27", + "postcss": "^8.4.13", + "resolve": "^1.22.0", + "rollup": "^2.59.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": ">=12.2.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + }, + "peerDependencies": { + "less": "*", + "sass": "*", + "stylus": "*" + }, + "peerDependenciesMeta": { + "less": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + } + } + }, + "node_modules/vue": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.2.36.tgz", + "integrity": "sha512-5yTXmrE6gW8IQgttzHW5bfBiFA6mx35ZXHjGLDmKYzW6MMmYvCwuKybANRepwkMYeXw2v1buGg3/lPICY5YlZw==", + "dependencies": { + "@vue/compiler-dom": "3.2.36", + "@vue/compiler-sfc": "3.2.36", + "@vue/runtime-dom": "3.2.36", + "@vue/server-renderer": "3.2.36", + "@vue/shared": "3.2.36" + } + }, + "node_modules/vue-clipboard3": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/vue-clipboard3/-/vue-clipboard3-2.0.0.tgz", + "integrity": "sha512-Q9S7dzWGax7LN5iiSPcu/K1GGm2gcBBlYwmMsUc5/16N6w90cbKow3FnPmPs95sungns4yvd9/+JhbAznECS2A==", + "dependencies": { + "clipboard": "^2.0.6" + } + }, + "node_modules/vue-eslint-parser": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.0.2.tgz", + "integrity": "sha512-uCPQwTGjOtAYrwnU+76pYxalhjsh7iFBsHwBqDHiOPTxtICDaraO4Szw54WFTNZTAEsgHHzqFOu1mmnBOBRzDA==", + "dev": true, + "dependencies": { + "debug": "^4.3.4", + "eslint-scope": "^7.1.1", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.3.1", + "esquery": "^1.4.0", + "lodash": "^4.17.21", + "semver": "^7.3.6" + }, + "engines": { + "node": "^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=6.0.0" + } + }, + "node_modules/vue-eslint-parser/node_modules/eslint-scope": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/vue-eslint-parser/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/vue-grid-layout": { + "version": "3.0.0-beta1", + "resolved": "https://registry.npmjs.org/vue-grid-layout/-/vue-grid-layout-3.0.0-beta1.tgz", + "integrity": "sha512-MsW0yfYNtnAO/uDhfZvkP6effxSJxvhAFbIL37x6Rn3vW9xf0WHVefKaSbQMLpSq3mXnR6ut0pg2Cd5lqIIZzg==", + "dependencies": { + "@interactjs/actions": "^1.10.2", + "@interactjs/auto-start": "^1.10.2", + "@interactjs/dev-tools": "^1.10.2", + "@interactjs/interactjs": "^1.10.2", + "@interactjs/modifiers": "^1.10.2", + "element-resize-detector": "^1.2.1", + "mitt": "^2.1.0" + } + }, + "node_modules/vue-grid-layout/node_modules/mitt": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-2.1.0.tgz", + "integrity": "sha512-ILj2TpLiysu2wkBbWjAmww7TkZb65aiQO+DkVdUTBpBXq+MHYiETENkKFMtsJZX1Lf4pe4QOrTSjIfUwN5lRdg==" + }, + "node_modules/vue-i18n": { + "version": "9.1.10", + "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-9.1.10.tgz", + "integrity": "sha512-jpr7gV5KPk4n+sSPdpZT8Qx3XzTcNDWffRlHV/cT2NUyEf+sEgTTmLvnBAibjOFJ0zsUyZlVTAWH5DDnYep+1g==", + "dependencies": { + "@intlify/core-base": "9.1.10", + "@intlify/shared": "9.1.10", + "@intlify/vue-devtools": "9.1.10", + "@vue/devtools-api": "^6.0.0-beta.7" + }, + "engines": { + "node": ">= 10" + }, + "peerDependencies": { + "vue": "^3.0.0" + } + }, + "node_modules/vue-router": { + "version": "4.0.15", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.0.15.tgz", + "integrity": "sha512-xa+pIN9ZqORdIW1MkN2+d9Ui2pCM1b/UMgwYUCZOiFYHAvz/slKKBDha8DLrh5aCG/RibtrpyhKjKOZ85tYyWg==", + "dependencies": { + "@vue/devtools-api": "^6.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "vue": "^3.2.0" + } + }, + "node_modules/wangeditor": { + "version": "4.7.15", + "resolved": "https://registry.npmjs.org/wangeditor/-/wangeditor-4.7.15.tgz", + "integrity": "sha512-aPTdREd8BxXVyJ5MI+LU83FQ7u1EPd341iXIorRNYSOvoimNoZ4nPg+yn3FGbB93/owEa6buLw8wdhYnMCJQLg==", + "dependencies": { + "@babel/runtime": "^7.11.2", + "@babel/runtime-corejs3": "^7.11.2", + "tslib": "^2.1.0" + } + }, + "node_modules/watchpack": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz", + "integrity": "sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA==", + "dev": true, + "peer": true, + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "dev": true, + "peer": true + }, + "node_modules/webpack": { + "version": "5.72.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.72.1.tgz", + "integrity": "sha512-dXG5zXCLspQR4krZVR6QgajnZOjW2K/djHvdcRaDQvsjV9z9vaW6+ja5dZOYbqBBjF6kGXka/2ZyxNdc+8Jung==", + "dev": true, + "peer": true, + "dependencies": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^0.0.51", + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/wasm-edit": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "acorn": "^8.4.1", + "acorn-import-assertions": "^1.7.6", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.9.3", + "es-module-lexer": "^0.9.0", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.9", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.1.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.1.3", + "watchpack": "^2.3.1", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "dev": true, + "peer": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "dev": true, + "peer": true, + "dependencies": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wildcard": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-1.1.2.tgz", + "integrity": "sha1-pwIEUwhNjNLv5wup02liY94XEKU=" + }, + "node_modules/wmf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wmf/-/wmf-1.0.2.tgz", + "integrity": "sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/word": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/word/-/word-0.3.0.tgz", + "integrity": "sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "node_modules/xlsx": { + "version": "0.18.5", + "resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.18.5.tgz", + "integrity": "sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==", + "dependencies": { + "adler-32": "~1.3.0", + "cfb": "~1.2.1", + "codepage": "~1.15.0", + "crc-32": "~1.2.1", + "ssf": "~0.11.2", + "wmf": "~1.0.1", + "word": "~0.3.0" + }, + "bin": { + "xlsx": "bin/xlsx.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/xml-name-validator": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", + "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/zrender": { + "version": "5.3.2", + "resolved": "https://registry.npmmirror.com/zrender/-/zrender-5.3.2.tgz", + "integrity": "sha512-8IiYdfwHj2rx0UeIGZGGU4WEVSDEdeVCaIg/fomejg1Xu6OifAL1GVzIPHg2D+MyUkbNgPWji90t0a8IDk+39w==", + "dependencies": { + "tslib": "2.3.0" + } + } + }, + "dependencies": { + "@babel/parser": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.0.tgz", + "integrity": "sha512-AqDccGC+m5O/iUStSJy3DGRIUFu7WbY/CppZYwrEUB4N0tZlnI8CSTsgL7v5fHVFmUbRv2sd+yy27o8Ydt4MGg==" + }, + "@babel/runtime": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.0.tgz", + "integrity": "sha512-YMQvx/6nKEaucl0MY56mwIG483xk8SDNdlUwb2Ts6FUpr7fm85DxEmsY18LXBNhcTz6tO6JwZV8w1W06v8UKeg==", + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "@babel/runtime-corejs3": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.18.9.tgz", + "integrity": "sha512-qZEWeccZCrHA2Au4/X05QW5CMdm4VjUDCrGq5gf1ZDcM4hRqreKrtwAn7yci9zfgAS9apvnsFXiGBHBAxZdK9A==", + "requires": { + "core-js-pure": "^3.20.2", + "regenerator-runtime": "^0.13.4" + } + }, + "@ctrl/tinycolor": { + "version": "3.4.1", + "resolved": "https://registry.npmmirror.com/@ctrl/tinycolor/-/tinycolor-3.4.1.tgz", + "integrity": "sha512-ej5oVy6lykXsvieQtqZxCOaLT+xD4+QNarq78cIYISHmZXshCvROLudpQN3lfL8G0NL7plMSSK+zlyvCaIJ4Iw==" + }, + "@element-plus/icons-vue": { + "version": "2.0.6", + "resolved": "https://registry.npmmirror.com/@element-plus/icons-vue/-/icons-vue-2.0.6.tgz", + "integrity": "sha512-lPpG8hYkjL/Z97DH5Ei6w6o22Z4YdNglWCNYOPcB33JCF2A4wye6HFgSI7hEt9zdLyxlSpiqtgf9XcYU+m5mew==", + "requires": {} + }, + "@eslint/eslintrc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.0.tgz", + "integrity": "sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.3.2", + "globals": "^13.15.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + } + }, + "@floating-ui/core": { + "version": "0.7.3", + "resolved": "https://registry.npmmirror.com/@floating-ui/core/-/core-0.7.3.tgz", + "integrity": "sha512-buc8BXHmG9l82+OQXOFU3Kr2XQx9ys01U/Q9HMIrZ300iLc8HLMgh7dcCqgYzAzf4BkoQvDcXf5Y+CuEZ5JBYg==" + }, + "@floating-ui/dom": { + "version": "0.5.4", + "resolved": "https://registry.npmmirror.com/@floating-ui/dom/-/dom-0.5.4.tgz", + "integrity": "sha512-419BMceRLq0RrmTSDxn8hf9R3VCJv2K9PUfugh5JyEFmdjzDo+e8U5EdR8nzKq8Yj1htzLm3b6eQEEam3/rrtg==", + "requires": { + "@floating-ui/core": "^0.7.3" + } + }, + "@humanwhocodes/config-array": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", + "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==", + "dev": true, + "requires": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + } + }, + "@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, + "@interactjs/actions": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/actions/-/actions-1.10.11.tgz", + "integrity": "sha512-P39zeefr4hkmKx+5nZ+mrH1s0l2YJ3gIHrthXmE81n6MlMa42m0WtHcTms4C5JTTNBP2EEDY+KGgGxSnmJKvUw==", + "requires": { + "@interactjs/interact": "1.10.11" + } + }, + "@interactjs/auto-scroll": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/auto-scroll/-/auto-scroll-1.10.11.tgz", + "integrity": "sha512-feHNjhi0EMNLV2nQcEgjYPz2mI54aeSW2RiaoNtFLyBvtXKp0b4DmluwDv6DvuXmUpDwD5g/Hk1gGM2rgl7iqQ==", + "requires": { + "@interactjs/interact": "1.10.11" + } + }, + "@interactjs/auto-start": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/auto-start/-/auto-start-1.10.11.tgz", + "integrity": "sha512-cIg5CcalCPtC6AiGq6j/0hKUtL2MweEpvw12FuB19sz2Q9Dye0J4GliHKhOYvtumNinnvfVAZ4FZMqZEuX7YZA==", + "requires": { + "@interactjs/interact": "1.10.11" + } + }, + "@interactjs/core": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/core/-/core-1.10.11.tgz", + "integrity": "sha512-aJ50ccVeszpJt7wPH7Yfqm7f1aG1SA94qd90P0NaESh5/QUXn4CESO6igobo4DFHQ5z+1Rfdl8aphP4JxlH4gw==", + "requires": {} + }, + "@interactjs/dev-tools": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/dev-tools/-/dev-tools-1.10.11.tgz", + "integrity": "sha512-BP2FNfMbF7zLuOAUGMkDhCo1e1B0fnqyb9ih/Y8yAIJuoLrZxP/9htbsS1vZOIVZ4UgtrId4cYOwfcAZBMQtmw==", + "requires": { + "@interactjs/interact": "1.10.11" + } + }, + "@interactjs/inertia": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/inertia/-/inertia-1.10.11.tgz", + "integrity": "sha512-h+sknCzRqBSyHy4ctPNsq56mxkAMMdwHWD6en7rDEw899gdGKYaXVDVdv1jMfiwNRw0eRFBNoCiol8r3a/a3Jw==", + "requires": { + "@interactjs/interact": "1.10.11", + "@interactjs/offset": "1.10.11" + } + }, + "@interactjs/interact": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/interact/-/interact-1.10.11.tgz", + "integrity": "sha512-0iZJ9l547JuBA/lKxK4ARGYVmMqRSsAdA8gXL1zWe51qEIQq8PyWmMipoi8JbDaL7exC2THKwkXu5uq5ndT+iA==", + "requires": { + "@interactjs/core": "1.10.11", + "@interactjs/types": "1.10.11", + "@interactjs/utils": "1.10.11" + } + }, + "@interactjs/interactjs": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/interactjs/-/interactjs-1.10.11.tgz", + "integrity": "sha512-cGOxf6rp3Y8/sk88LhIT0XDn4gCiCzAnUG5Kkj9SAqiUO6BK/9+Wbp1IBkNaPgl/8uG8gNHh/dXBrlBBNcqJAg==", + "requires": { + "@interactjs/actions": "1.10.11", + "@interactjs/auto-scroll": "1.10.11", + "@interactjs/auto-start": "1.10.11", + "@interactjs/core": "1.10.11", + "@interactjs/dev-tools": "1.10.11", + "@interactjs/inertia": "1.10.11", + "@interactjs/interact": "1.10.11", + "@interactjs/modifiers": "1.10.11", + "@interactjs/offset": "1.10.11", + "@interactjs/pointer-events": "1.10.11", + "@interactjs/reflow": "1.10.11", + "@interactjs/utils": "1.10.11" + } + }, + "@interactjs/modifiers": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/modifiers/-/modifiers-1.10.11.tgz", + "integrity": "sha512-ltqX1RSqeAIikixlQBlyEUdclT5+rbfIGi3sIdLLYaIZQnltYkWqL9MHKx/w5b+hV+Mc0p5MLUFWJbTdkSCZ9g==", + "requires": { + "@interactjs/interact": "1.10.11", + "@interactjs/snappers": "1.10.11" + } + }, + "@interactjs/offset": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/offset/-/offset-1.10.11.tgz", + "integrity": "sha512-mBT7eIfy5ivofECiv+VwtEwwIMLV54fT9ujSMWJPduxdSYIHepUWgEf/3zjJknFh6jQc7pqz9dtjvVvyzRCLlQ==", + "requires": { + "@interactjs/interact": "1.10.11" + } + }, + "@interactjs/pointer-events": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/pointer-events/-/pointer-events-1.10.11.tgz", + "integrity": "sha512-yBT8JJVMZ+MgBay5l1WAHnL8ch/mZsRfaFahti+QFYeQyRloDtsWmEMDSYI/Onyy9+hS3gN/ge77ArGciZZ0Ow==", + "requires": { + "@interactjs/interact": "1.10.11" + } + }, + "@interactjs/reflow": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/reflow/-/reflow-1.10.11.tgz", + "integrity": "sha512-NSCtcCkjImOYSbxzzv2kFqR9t49J8KlhEr9UoePc7GyLbNXsiv3WQ3n0ehZd7CgZXQDiVXnP2UnmIOv5Zd4HQg==", + "requires": { + "@interactjs/interact": "1.10.11" + } + }, + "@interactjs/snappers": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/snappers/-/snappers-1.10.11.tgz", + "integrity": "sha512-yYtOMUZ7aFUZ1IYheq9Tj5hZ4J1r5dnaXhLF44WsI/awQ5L0DjZf07GPWof0B+7rZHEVudxyQNbPfFmb+1K94Q==", + "requires": { + "@interactjs/interact": "1.10.11" + } + }, + "@interactjs/types": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/types/-/types-1.10.11.tgz", + "integrity": "sha512-YRsVFWjL8Gkkvlx3qnjeaxW4fnibSJ9791g8BA7Pv5ANByI64WmtR1vU7A2rXcrOn8XvyCEfY0ss1s8NhZP+MA==" + }, + "@interactjs/utils": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@interactjs/utils/-/utils-1.10.11.tgz", + "integrity": "sha512-410ZoxKF+r1roeSelL+WHXfdryUMg5iykC1XwQ3l6XqNw43IMACzyvTH6k6Pwxj7w7x42nce0Qdn1GQ3Y8xyCw==" + }, + "@intlify/core-base": { + "version": "9.1.10", + "resolved": "https://registry.npmjs.org/@intlify/core-base/-/core-base-9.1.10.tgz", + "integrity": "sha512-So9CNUavB/IsZ+zBmk2Cv6McQp6vc2wbGi1S0XQmJ8Vz+UFcNn9MFXAe9gY67PreIHrbLsLxDD0cwo1qsxM1Nw==", + "requires": { + "@intlify/devtools-if": "9.1.10", + "@intlify/message-compiler": "9.1.10", + "@intlify/message-resolver": "9.1.10", + "@intlify/runtime": "9.1.10", + "@intlify/shared": "9.1.10", + "@intlify/vue-devtools": "9.1.10" + } + }, + "@intlify/devtools-if": { + "version": "9.1.10", + "resolved": "https://registry.npmjs.org/@intlify/devtools-if/-/devtools-if-9.1.10.tgz", + "integrity": "sha512-SHaKoYu6sog3+Q8js1y3oXLywuogbH1sKuc7NSYkN3GElvXSBaMoCzW+we0ZSFqj/6c7vTNLg9nQ6rxhKqYwnQ==", + "requires": { + "@intlify/shared": "9.1.10" + } + }, + "@intlify/message-compiler": { + "version": "9.1.10", + "resolved": "https://registry.npmjs.org/@intlify/message-compiler/-/message-compiler-9.1.10.tgz", + "integrity": "sha512-+JiJpXff/XTb0EadYwdxOyRTB0hXNd4n1HaJ/a4yuV960uRmPXaklJsedW0LNdcptd/hYUZtCkI7Lc9J5C1gxg==", + "requires": { + "@intlify/message-resolver": "9.1.10", + "@intlify/shared": "9.1.10", + "source-map": "0.6.1" + } + }, + "@intlify/message-resolver": { + "version": "9.1.10", + "resolved": "https://registry.npmjs.org/@intlify/message-resolver/-/message-resolver-9.1.10.tgz", + "integrity": "sha512-5YixMG/M05m0cn9+gOzd4EZQTFRUu8RGhzxJbR1DWN21x/Z3bJ8QpDYj6hC4FwBj5uKsRfKpJQ3Xqg98KWoA+w==" + }, + "@intlify/runtime": { + "version": "9.1.10", + "resolved": "https://registry.npmjs.org/@intlify/runtime/-/runtime-9.1.10.tgz", + "integrity": "sha512-7QsuByNzpe3Gfmhwq6hzgXcMPpxz8Zxb/XFI6s9lQdPLPe5Lgw4U1ovRPZTOs6Y2hwitR3j/HD8BJNGWpJnOFA==", + "requires": { + "@intlify/message-compiler": "9.1.10", + "@intlify/message-resolver": "9.1.10", + "@intlify/shared": "9.1.10" + } + }, + "@intlify/shared": { + "version": "9.1.10", + "resolved": "https://registry.npmjs.org/@intlify/shared/-/shared-9.1.10.tgz", + "integrity": "sha512-Om54xJeo1Vw+K1+wHYyXngE8cAbrxZHpWjYzMR9wCkqbhGtRV5VLhVc214Ze2YatPrWlS2WSMOWXR8JktX/IgA==" + }, + "@intlify/vue-devtools": { + "version": "9.1.10", + "resolved": "https://registry.npmjs.org/@intlify/vue-devtools/-/vue-devtools-9.1.10.tgz", + "integrity": "sha512-5l3qYARVbkWAkagLu1XbDUWRJSL8br1Dj60wgMaKB0+HswVsrR6LloYZTg7ozyvM621V6+zsmwzbQxbVQyrytQ==", + "requires": { + "@intlify/message-resolver": "9.1.10", + "@intlify/runtime": "9.1.10", + "@intlify/shared": "9.1.10" + } + }, + "@jiaminghi/bezier-curve": { + "version": "0.0.9", + "resolved": "https://registry.npmmirror.com/@jiaminghi/bezier-curve/-/bezier-curve-0.0.9.tgz", + "integrity": "sha512-u9xJPOEl6Dri2E9FfmJoGxYQY7vYJkURNX04Vj64tdi535tPrpkuf9Sm0lNr3QTKdHQh0DdNRsaa62FLQNQEEw==", + "requires": { + "@babel/runtime": "^7.5.5" + } + }, + "@jiaminghi/c-render": { + "version": "0.4.3", + "resolved": "https://registry.npmmirror.com/@jiaminghi/c-render/-/c-render-0.4.3.tgz", + "integrity": "sha512-FJfzj5hGj7MLqqqI2D7vEzHKbQ1Ynnn7PJKgzsjXaZpJzTqs2Yw5OSeZnm6l7Qj7jyPAP53lFvEQNH4o4j6s+Q==", + "requires": { + "@babel/runtime": "^7.5.5", + "@jiaminghi/bezier-curve": "*", + "@jiaminghi/color": "*", + "@jiaminghi/transition": "*" + } + }, + "@jiaminghi/charts": { + "version": "0.2.18", + "resolved": "https://registry.npmmirror.com/@jiaminghi/charts/-/charts-0.2.18.tgz", + "integrity": "sha512-K+HXaOOeWG9OOY1VG6M4mBreeeIAPhb9X+khG651AbnwEwL6G2UtcAQ8GWCq6GzhczcLwwhIhuaHqRygwHC0sA==", + "requires": { + "@babel/runtime": "^7.5.5", + "@jiaminghi/c-render": "^0.4.3" + } + }, + "@jiaminghi/color": { + "version": "0.1.1", + "resolved": "https://registry.npmmirror.com/@jiaminghi/color/-/color-0.1.1.tgz", + "integrity": "sha512-M09+Sb5HGqVim0zo+nG5gU1v+6gXT8ptr0BZR6dMGt83XmCJgnZtO8s7llTW4hLFFFM5co6geZvTekqLpSPAAQ==", + "requires": { + "@babel/runtime": "^7.5.5" + } + }, + "@jiaminghi/transition": { + "version": "1.1.11", + "resolved": "https://registry.npmmirror.com/@jiaminghi/transition/-/transition-1.1.11.tgz", + "integrity": "sha512-owBggipoHMikDHHDW5Gc7RZYlVuvxHADiU4bxfjBVkHDAmmck+fCkm46n2JzC3j33hWvP9nSCAeh37t6stgWeg==", + "requires": { + "@babel/runtime": "^7.5.5" + } + }, + "@kjgl77/datav-vue3": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/@kjgl77/datav-vue3/-/datav-vue3-1.2.1.tgz", + "integrity": "sha512-hiSodPvXkp6o8nyPPgDFcrb+M4h9dZd2hmuT3WqHY+sInEHCFtypCGrhvxRFT3oGlcIlLKSX9WVb117JksFROA==", + "requires": { + "@jiaminghi/c-render": "^0.4.3", + "@jiaminghi/charts": "^0.2.18", + "@vueuse/core": "^9.1.0" + }, + "dependencies": { + "@types/web-bluetooth": { + "version": "0.0.15", + "resolved": "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.15.tgz", + "integrity": "sha512-w7hEHXnPMEZ+4nGKl/KDRVpxkwYxYExuHOYXyzIzCDzEZ9ZCGMAewulr9IqJu2LR4N37fcnb1XVeuZ09qgOxhA==" + }, + "@vueuse/core": { + "version": "9.1.1", + "resolved": "https://registry.npmmirror.com/@vueuse/core/-/core-9.1.1.tgz", + "integrity": "sha512-QfuaNWRDMQcCUwXylCyYhPC3ScS9Tiiz4J0chdwr3vOemBwRToSywq8MP+ZegKYFnbETzRY8G/5zC+ca30wrRQ==", + "requires": { + "@types/web-bluetooth": "^0.0.15", + "@vueuse/metadata": "9.1.1", + "@vueuse/shared": "9.1.1", + "vue-demi": "*" + } + }, + "@vueuse/metadata": { + "version": "9.1.1", + "resolved": "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-9.1.1.tgz", + "integrity": "sha512-XZ2KtSW+85LLHB/IdGILPAtbIVHasPsAW7aqz3BRMzJdAQWRiM/FGa1OKBwLbXtUw/AmjKYFlZJo7eOFIBXRog==" + }, + "vue-demi": { + "version": "0.13.11", + "resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.13.11.tgz", + "integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==", + "requires": {} + } + } + }, + "@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, + "@popperjs/core": { + "version": "npm:@sxzz/popperjs-es@2.11.7", + "resolved": "https://registry.npmmirror.com/@sxzz/popperjs-es/-/popperjs-es-2.11.7.tgz", + "integrity": "sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ==" + }, + "@transloadit/prettier-bytes": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@transloadit/prettier-bytes/-/prettier-bytes-0.0.7.tgz", + "integrity": "sha512-VeJbUb0wEKbcwaSlj5n+LscBl9IPgLPkHVGBkh00cztv6X4L/TJXK58LzFuBKX7/GAfiGhIwH67YTLTlzvIzBA==" + }, + "@types/eslint": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.2.tgz", + "integrity": "sha512-Z1nseZON+GEnFjJc04sv4NSALGjhFwy6K0HXt7qsn5ArfAKtb63dXNJHf+1YW6IpOIYRBGUbu3GwJdj8DGnCjA==", + "dev": true, + "peer": true, + "requires": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "@types/eslint-scope": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.3.tgz", + "integrity": "sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g==", + "dev": true, + "peer": true, + "requires": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "@types/estree": { + "version": "0.0.51", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", + "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", + "dev": true, + "peer": true + }, + "@types/event-emitter": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@types/event-emitter/-/event-emitter-0.3.3.tgz", + "integrity": "sha512-UfnOK1pIxO7P+EgPRZXD9jMpimd8QEFcEZ5R67R1UhGbv4zghU5+NE7U8M8G9H5Jc8FI51rqDWQs6FtUfq2e/Q==" + }, + "@types/json-bigint": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/@types/json-bigint/-/json-bigint-1.0.1.tgz", + "integrity": "sha512-zpchZLNsNuzJHi6v64UBoFWAvQlPhch7XAi36FkH6tL1bbbmimIF+cS7vwkzY4u5RaSWMoflQfu+TshMPPw8uw==", + "dev": true + }, + "@types/json-schema": { + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", + "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", + "dev": true + }, + "@types/lodash": { + "version": "4.14.182", + "resolved": "https://registry.npmmirror.com/@types/lodash/-/lodash-4.14.182.tgz", + "integrity": "sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q==" + }, + "@types/lodash-es": { + "version": "4.17.6", + "resolved": "https://registry.npmmirror.com/@types/lodash-es/-/lodash-es-4.17.6.tgz", + "integrity": "sha512-R+zTeVUKDdfoRxpAryaQNRKk3105Rrgx2CFRClIgRGaqDTdjsm8h6IYA8ir584W3ePzkZfst5xIgDwYrlh9HLg==", + "requires": { + "@types/lodash": "*" + } + }, + "@types/node": { + "version": "17.0.39", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.39.tgz", + "integrity": "sha512-JDU3YLlnPK3WDao6/DlXLOgSNpG13ct+CwIO17V8q0/9fWJyeMJJ/VyZ1lv8kDprihvZMydzVwf0tQOqGiY2Nw==", + "dev": true + }, + "@types/nprogress": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@types/nprogress/-/nprogress-0.2.0.tgz", + "integrity": "sha512-1cYJrqq9GezNFPsWTZpFut/d4CjpZqA0vhqDUPFWYKF1oIyBz5qnoYMzR+0C/T96t3ebLAC1SSnwrVOm5/j74A==", + "dev": true + }, + "@types/sortablejs": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@types/sortablejs/-/sortablejs-1.13.0.tgz", + "integrity": "sha512-C3064MH72iEfeGCYEGCt7FCxXoAXaMPG0QPnstcxvPmbl54erpISu06d++FY37Smja64iWy5L8wOyHHBghWbJQ==", + "dev": true + }, + "@types/web-bluetooth": { + "version": "0.0.14", + "resolved": "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.14.tgz", + "integrity": "sha512-5d2RhCard1nQUC3aHcq/gHzWYO6K0WJmAbjO7mQJgCQKtZpgXxv1rOM6O/dBDhDYYVutk1sciOgNSe+5YyfM8A==" + }, + "@typescript-eslint/eslint-plugin": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.27.0.tgz", + "integrity": "sha512-DDrIA7GXtmHXr1VCcx9HivA39eprYBIFxbQEHI6NyraRDxCGpxAFiYQAT/1Y0vh1C+o2vfBiy4IuPoXxtTZCAQ==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "5.27.0", + "@typescript-eslint/type-utils": "5.27.0", + "@typescript-eslint/utils": "5.27.0", + "debug": "^4.3.4", + "functional-red-black-tree": "^1.0.1", + "ignore": "^5.2.0", + "regexpp": "^3.2.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/parser": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.27.0.tgz", + "integrity": "sha512-8oGjQF46c52l7fMiPPvX4It3u3V3JipssqDfHQ2hcR0AeR8Zge+OYyKUCm5b70X72N1qXt0qgHenwN6Gc2SXZA==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "5.27.0", + "@typescript-eslint/types": "5.27.0", + "@typescript-eslint/typescript-estree": "5.27.0", + "debug": "^4.3.4" + } + }, + "@typescript-eslint/scope-manager": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.27.0.tgz", + "integrity": "sha512-VnykheBQ/sHd1Vt0LJ1JLrMH1GzHO+SzX6VTXuStISIsvRiurue/eRkTqSrG0CexHQgKG8shyJfR4o5VYioB9g==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.27.0", + "@typescript-eslint/visitor-keys": "5.27.0" + } + }, + "@typescript-eslint/type-utils": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.27.0.tgz", + "integrity": "sha512-vpTvRRchaf628Hb/Xzfek+85o//zEUotr1SmexKvTfs7czXfYjXVT/a5yDbpzLBX1rhbqxjDdr1Gyo0x1Fc64g==", + "dev": true, + "requires": { + "@typescript-eslint/utils": "5.27.0", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/types": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.27.0.tgz", + "integrity": "sha512-lY6C7oGm9a/GWhmUDOs3xAVRz4ty/XKlQ2fOLr8GAIryGn0+UBOoJDWyHer3UgrHkenorwvBnphhP+zPmzmw0A==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.27.0.tgz", + "integrity": "sha512-QywPMFvgZ+MHSLRofLI7BDL+UczFFHyj0vF5ibeChDAJgdTV8k4xgEwF0geFhVlPc1p8r70eYewzpo6ps+9LJQ==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.27.0", + "@typescript-eslint/visitor-keys": "5.27.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/utils": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.27.0.tgz", + "integrity": "sha512-nZvCrkIJppym7cIbP3pOwIkAefXOmfGPnCM0LQfzNaKxJHI6VjI8NC662uoiPlaf5f6ymkTy9C3NQXev2mdXmA==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.9", + "@typescript-eslint/scope-manager": "5.27.0", + "@typescript-eslint/types": "5.27.0", + "@typescript-eslint/typescript-estree": "5.27.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.27.0.tgz", + "integrity": "sha512-46cYrteA2MrIAjv9ai44OQDUoCZyHeGIc4lsjCUX2WT6r4C+kidz1bNiR4017wHOPUythYeH+Sc7/cFP97KEAA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.27.0", + "eslint-visitor-keys": "^3.3.0" + } + }, + "@uppy/companion-client": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@uppy/companion-client/-/companion-client-2.1.0.tgz", + "integrity": "sha512-1Zsag2z9kygXuVbUxqHhkTJUmEHwbejjyf7vmm+P/AiVgK3O37JINYBGOpdTJNgbC9UydLBjleXo8peDVgpg8Q==", + "requires": { + "@uppy/utils": "^4.0.7", + "namespace-emitter": "^2.0.1" + } + }, + "@uppy/core": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@uppy/core/-/core-2.2.0.tgz", + "integrity": "sha512-qdDoNCjrVjjOmFCFCxc+HEbtbQ9K0k6LKNbZZwWK7d4Cx3xEa6VsxmqVhfFL6ekH2gyboqYV8Z5IbRkJT/0Nqg==", + "requires": { + "@transloadit/prettier-bytes": "0.0.7", + "@uppy/store-default": "^2.0.3", + "@uppy/utils": "^4.0.7", + "lodash.throttle": "^4.1.1", + "mime-match": "^1.0.2", + "namespace-emitter": "^2.0.1", + "nanoid": "^3.1.25", + "preact": "^10.5.13" + } + }, + "@uppy/store-default": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@uppy/store-default/-/store-default-2.0.3.tgz", + "integrity": "sha512-2BGlN1sW0cFv4rOqTK8dfSg579S984N1HxCJxLFqeW9nWD6zd/O8Omyd85tbxGQ+FLZLTmLOm/feD0YeCBMahg==" + }, + "@uppy/utils": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@uppy/utils/-/utils-4.0.7.tgz", + "integrity": "sha512-nKViMT8XchKy+NWpb3DtVKuzZBmW7au26LrMq89EsvTwIOT6UR9+7bmz/+zr3+lc7UC7vMgNChIC6G+/Ya9wWQ==", + "requires": { + "lodash.throttle": "^4.1.1" + } + }, + "@uppy/xhr-upload": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@uppy/xhr-upload/-/xhr-upload-2.1.0.tgz", + "integrity": "sha512-io1uNu7lGkhIkMnt13bu3FYSAdRbBRWl8n/6njYi+727Jyr0XhKfmBYV9OiruFSxLz5Bfxkw2gTs6e0qUb63nA==", + "requires": { + "@uppy/companion-client": "^2.1.0", + "@uppy/utils": "^4.0.7", + "nanoid": "^3.1.25" + } + }, + "@vitejs/plugin-vue": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-2.3.3.tgz", + "integrity": "sha512-SmQLDyhz+6lGJhPELsBdzXGc+AcaT8stgkbiTFGpXPe8Tl1tJaBw1A6pxDqDuRsVkD8uscrkx3hA7QDOoKYtyw==", + "dev": true, + "requires": {} + }, + "@vue/compiler-core": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.36.tgz", + "integrity": "sha512-bbyZM5hvBicv0PW3KUfVi+x3ylHnfKG7DOn5wM+f2OztTzTjLEyBb/5yrarIYpmnGitVGbjZqDbODyW4iK8hqw==", + "requires": { + "@babel/parser": "^7.16.4", + "@vue/shared": "3.2.36", + "estree-walker": "^2.0.2", + "source-map": "^0.6.1" + } + }, + "@vue/compiler-dom": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.36.tgz", + "integrity": "sha512-tcOTAOiW4s24QLnq+ON6J+GRONXJ+A/mqKCORi0LSlIh8XQlNnlm24y8xIL8la+ZDgkdbjarQ9ZqYSvEja6gVA==", + "requires": { + "@vue/compiler-core": "3.2.36", + "@vue/shared": "3.2.36" + } + }, + "@vue/compiler-sfc": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.36.tgz", + "integrity": "sha512-AvGb4bTj4W8uQ4BqaSxo7UwTEqX5utdRSMyHy58OragWlt8nEACQ9mIeQh3K4di4/SX+41+pJrLIY01lHAOFOA==", + "requires": { + "@babel/parser": "^7.16.4", + "@vue/compiler-core": "3.2.36", + "@vue/compiler-dom": "3.2.36", + "@vue/compiler-ssr": "3.2.36", + "@vue/reactivity-transform": "3.2.36", + "@vue/shared": "3.2.36", + "estree-walker": "^2.0.2", + "magic-string": "^0.25.7", + "postcss": "^8.1.10", + "source-map": "^0.6.1" + } + }, + "@vue/compiler-ssr": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.36.tgz", + "integrity": "sha512-+KugInUFRvOxEdLkZwE+W43BqHyhBh0jpYXhmqw1xGq2dmE6J9eZ8UUSOKNhdHtQ/iNLWWeK/wPZkVLUf3YGaw==", + "requires": { + "@vue/compiler-dom": "3.2.36", + "@vue/shared": "3.2.36" + } + }, + "@vue/devtools-api": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.1.4.tgz", + "integrity": "sha512-IiA0SvDrJEgXvVxjNkHPFfDx6SXw0b/TUkqMcDZWNg9fnCAHbTpoo59YfJ9QLFkwa3raau5vSlRVzMSLDnfdtQ==" + }, + "@vue/reactivity": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.36.tgz", + "integrity": "sha512-c2qvopo0crh9A4GXi2/2kfGYMxsJW4tVILrqRPydVGZHhq0fnzy6qmclWOhBFckEhmyxmpHpdJtIRYGeKcuhnA==", + "requires": { + "@vue/shared": "3.2.36" + } + }, + "@vue/reactivity-transform": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.2.36.tgz", + "integrity": "sha512-Jk5o2BhpODC9XTA7o4EL8hSJ4JyrFWErLtClG3NH8wDS7ri9jBDWxI7/549T7JY9uilKsaNM+4pJASLj5dtRwA==", + "requires": { + "@babel/parser": "^7.16.4", + "@vue/compiler-core": "3.2.36", + "@vue/shared": "3.2.36", + "estree-walker": "^2.0.2", + "magic-string": "^0.25.7" + } + }, + "@vue/runtime-core": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.2.36.tgz", + "integrity": "sha512-PTWBD+Lub+1U3/KhbCExrfxyS14hstLX+cBboxVHaz+kXoiDLNDEYAovPtxeTutbqtClIXtft+wcGdC+FUQ9qQ==", + "requires": { + "@vue/reactivity": "3.2.36", + "@vue/shared": "3.2.36" + } + }, + "@vue/runtime-dom": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.2.36.tgz", + "integrity": "sha512-gYPYblm7QXHVuBohqNRRT7Wez0f2Mx2D40rb4fleehrJU9CnkjG0phhcGEZFfGwCmHZRqBCRgbFWE98bPULqkg==", + "requires": { + "@vue/runtime-core": "3.2.36", + "@vue/shared": "3.2.36", + "csstype": "^2.6.8" + } + }, + "@vue/server-renderer": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.2.36.tgz", + "integrity": "sha512-uZE0+jfye6yYXWvAQYeHZv+f50sRryvy16uiqzk3jn8hEY8zTjI+rzlmZSGoE915k+W/Ol9XSw6vxOUD8dGkUg==", + "requires": { + "@vue/compiler-ssr": "3.2.36", + "@vue/shared": "3.2.36" + } + }, + "@vue/shared": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.36.tgz", + "integrity": "sha512-JtB41wXl7Au3+Nl3gD16Cfpj7k/6aCroZ6BbOiCMFCMvrOpkg/qQUXTso2XowaNqBbnkuGHurLAqkLBxNGc1hQ==" + }, + "@vueuse/core": { + "version": "8.9.2", + "resolved": "https://registry.npmmirror.com/@vueuse/core/-/core-8.9.2.tgz", + "integrity": "sha512-dE3/JgwqIHmmtmRBdZAnq87rZCSFbYVps2t3gWy9Jv/+Qp6sHSSKuPFtwguJVZ2OnaGnB/AMRmx4CuFRxFin3A==", + "requires": { + "@types/web-bluetooth": "^0.0.14", + "@vueuse/metadata": "8.9.2", + "@vueuse/shared": "8.9.2", + "vue-demi": "*" + }, + "dependencies": { + "@vueuse/shared": { + "version": "8.9.2", + "resolved": "https://registry.npmmirror.com/@vueuse/shared/-/shared-8.9.2.tgz", + "integrity": "sha512-s4Nk82oheL5z1GywyGnqjob0MzbAt88olMZa0vgt/p3gcMsT8Ff7+SqmNgEFC6AAs6xiuhOAZpnew9Zs3d90yQ==", + "requires": { + "vue-demi": "*" + } + }, + "vue-demi": { + "version": "0.13.4", + "resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.13.4.tgz", + "integrity": "sha512-KP4lq9uSz0KZbaqCllRhnxMV3mYRsRWJfdsAhZyt5bV5O1RTpoeDptBRV9NOa/JgOpfaA9ane88VF7OjWNK/DA==", + "requires": {} + } + } + }, + "@vueuse/metadata": { + "version": "8.9.2", + "resolved": "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-8.9.2.tgz", + "integrity": "sha512-g2s2BeyeEtJElmMFfFPnM+BTvnt0omniyvz8U18/zXDpQIMGozlNQgHoFeratyMfgVBhH/u2VKzmchChtDsgPQ==" + }, + "@vueuse/shared": { + "version": "9.1.1", + "resolved": "https://registry.npmmirror.com/@vueuse/shared/-/shared-9.1.1.tgz", + "integrity": "sha512-c+IfcOYmHiHqoEa3ED1Tbpue5GHmoUmTp8PtO4YbczthtY155Rt6DmWhjxMLXBF1Bcidagxljmp/7xtAzEHXLw==", + "requires": { + "vue-demi": "*" + }, + "dependencies": { + "vue-demi": { + "version": "0.13.11", + "resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.13.11.tgz", + "integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==", + "requires": {} + } + } + }, + "@wangeditor/basic-modules": { + "version": "1.1.3", + "resolved": "https://registry.npmmirror.com/@wangeditor/basic-modules/-/basic-modules-1.1.3.tgz", + "integrity": "sha512-TGJix4UelO46yAgwI946ctx4lSIJbYBwNvjSJ9Tf8mKr0WMCeLVBV+MV85rXPsfcmWtR4wBNwSg648Z+RbqRUg==", + "requires": { + "is-url": "^1.2.4" + } + }, + "@wangeditor/code-highlight": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@wangeditor/code-highlight/-/code-highlight-1.0.2.tgz", + "integrity": "sha512-SCtOcUxjKqIso/LSxGSOaYr3G6MC2En0gNTyHIMCG928T0fo0ufaqp/vIXKQzVL2Y+X/CSAOB2EbrFlgGvr0AQ==", + "requires": { + "prismjs": "^1.23.0" + } + }, + "@wangeditor/core": { + "version": "1.1.11", + "resolved": "https://registry.npmmirror.com/@wangeditor/core/-/core-1.1.11.tgz", + "integrity": "sha512-BwHVRJzESnkjKikTc2U2zsbd06l1pSo7qKy5+SpZLudYWrFxmd85VN+5GxM57FodogkNw/k04DFHcFSUfXcaKA==", + "requires": { + "@types/event-emitter": "^0.3.3", + "event-emitter": "^0.3.5", + "html-void-elements": "^2.0.0", + "i18next": "^20.4.0", + "scroll-into-view-if-needed": "^2.2.28", + "slate-history": "^0.66.0" + } + }, + "@wangeditor/editor": { + "version": "5.1.14", + "resolved": "https://registry.npmmirror.com/@wangeditor/editor/-/editor-5.1.14.tgz", + "integrity": "sha512-erILPAkpKldyGi4cEwrOW65v12GhZy2qj2A8kPlypU46lE72Y3XowZxWogN1TI/mqMDR84AHr0QWOvygOV1xwQ==", + "requires": { + "@uppy/core": "^2.1.1", + "@uppy/xhr-upload": "^2.0.3", + "@wangeditor/basic-modules": "^1.1.3", + "@wangeditor/code-highlight": "^1.0.2", + "@wangeditor/core": "^1.1.11", + "@wangeditor/list-module": "^1.0.2", + "@wangeditor/table-module": "^1.1.1", + "@wangeditor/upload-image-module": "^1.0.1", + "@wangeditor/video-module": "^1.1.1", + "dom7": "^3.0.0", + "is-hotkey": "^0.2.0", + "lodash.camelcase": "^4.3.0", + "lodash.clonedeep": "^4.5.0", + "lodash.debounce": "^4.0.8", + "lodash.foreach": "^4.5.0", + "lodash.isequal": "^4.5.0", + "lodash.throttle": "^4.1.1", + "lodash.toarray": "^4.4.0", + "nanoid": "^3.2.0", + "slate": "^0.72.0", + "snabbdom": "^3.1.0" + } + }, + "@wangeditor/list-module": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@wangeditor/list-module/-/list-module-1.0.2.tgz", + "integrity": "sha512-VfENZEFvsLTiLxN/cj8cibFGy9NVV+/cfATTiLiH9ef+8lgKv8apttXYVlqIAfnlJLLuCk0cIm8c/zH+hbtrZg==", + "requires": {} + }, + "@wangeditor/table-module": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/@wangeditor/table-module/-/table-module-1.1.1.tgz", + "integrity": "sha512-VPjEWQtncS2DsXYXiHUxPSxn2Xhc8GdhG3la7N5YhvxQde1+4N0SZLXeWsYvbGzOq4um5XToq5pktLLbE8G+EA==", + "requires": {} + }, + "@wangeditor/upload-image-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@wangeditor/upload-image-module/-/upload-image-module-1.0.1.tgz", + "integrity": "sha512-vgUV4ENttTITblqtVuzleIq732OmzmzzgrIvX6b3GRGPSw5u8glJ/87tOEhvHjHECc4oFo18B7xzJ1GpBj79/w==", + "requires": {} + }, + "@wangeditor/video-module": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/@wangeditor/video-module/-/video-module-1.1.1.tgz", + "integrity": "sha512-6gzpS5cnJihW2T0HFjqmbv6v8ouyaeMUjdM2X8BPohwD74p1ov00dCmRt5QekNTyYSmRHK0ASkUMOvRGqaDxMg==", + "requires": {} + }, + "@webassemblyjs/ast": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", + "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", + "dev": true, + "peer": true, + "requires": { + "@webassemblyjs/helper-numbers": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", + "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==", + "dev": true, + "peer": true + }, + "@webassemblyjs/helper-api-error": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", + "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", + "dev": true, + "peer": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", + "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", + "dev": true, + "peer": true + }, + "@webassemblyjs/helper-numbers": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", + "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", + "dev": true, + "peer": true, + "requires": { + "@webassemblyjs/floating-point-hex-parser": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", + "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", + "dev": true, + "peer": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", + "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", + "dev": true, + "peer": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", + "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", + "dev": true, + "peer": true, + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", + "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", + "dev": true, + "peer": true, + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", + "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", + "dev": true, + "peer": true + }, + "@webassemblyjs/wasm-edit": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", + "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", + "dev": true, + "peer": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/helper-wasm-section": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-opt": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "@webassemblyjs/wast-printer": "1.11.1" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", + "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", + "dev": true, + "peer": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", + "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", + "dev": true, + "peer": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", + "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", + "dev": true, + "peer": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", + "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", + "dev": true, + "peer": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@xtuc/long": "4.2.2" + } + }, + "@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true, + "peer": true + }, + "@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true, + "peer": true + }, + "acorn": { + "version": "8.7.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", + "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", + "dev": true + }, + "acorn-import-assertions": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", + "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", + "dev": true, + "peer": true, + "requires": {} + }, + "acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "requires": {} + }, + "adler-32": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.3.1.tgz", + "integrity": "sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==" + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peer": true, + "requires": {} + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, + "async-validator": { + "version": "4.2.5", + "resolved": "https://registry.npmmirror.com/async-validator/-/async-validator-4.2.5.tgz", + "integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "axios": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", + "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", + "requires": { + "follow-redirects": "^1.14.9", + "form-data": "^4.0.0" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "batch-processor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/batch-processor/-/batch-processor-1.0.0.tgz", + "integrity": "sha512-xoLQD8gmmR32MeuBHgH0Tzd5PuSZx71ZsbhVxOCRbgktZEPe4SQy7s9Z50uPp0F/f7iw2XmkHN2xkgbMfckMDA==" + }, + "bignumber.js": { + "version": "9.0.2", + "resolved": "https://registry.npmmirror.com/bignumber.js/-/bignumber.js-9.0.2.tgz", + "integrity": "sha512-GAcQvbpsM0pUb0zw1EI0KhQEZ+lRwR5fYaAp3vPOYuP7aDvGy6cVN6XHLauvF8SOga2y0dcLcjt3iQDTSEliyw==" + }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true + }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "browserslist": { + "version": "4.20.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.3.tgz", + "integrity": "sha512-NBhymBQl1zM0Y5dQT/O+xiLP9/rzOIQdKM/eMJBAq7yBgaB6krIYLGejrwVYnSHZdqjscB1SPuAjHwxjvN6Wdg==", + "dev": true, + "peer": true, + "requires": { + "caniuse-lite": "^1.0.30001332", + "electron-to-chromium": "^1.4.118", + "escalade": "^3.1.1", + "node-releases": "^2.0.3", + "picocolors": "^1.0.0" + } + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true, + "peer": true + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "caniuse-lite": { + "version": "1.0.30001342", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001342.tgz", + "integrity": "sha512-bn6sOCu7L7jcbBbyNhLg0qzXdJ/PMbybZTH/BA6Roet9wxYRm6Tr9D0s0uhLkOZ6MSG+QU6txUgdpr3MXIVqjA==", + "dev": true, + "peer": true + }, + "cfb": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cfb/-/cfb-1.2.2.tgz", + "integrity": "sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==", + "requires": { + "adler-32": "~1.3.0", + "crc-32": "~1.2.0" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "dependencies": { + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + } + } + }, + "chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "dev": true, + "peer": true + }, + "claygl": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/claygl/-/claygl-1.3.0.tgz", + "integrity": "sha512-+gGtJjT6SSHD2l2yC3MCubW/sCV40tZuSs5opdtn79vFSGUgp/lH139RNEQ6Jy078/L0aV8odCw8RSrUcMfLaQ==" + }, + "clipboard": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.11.tgz", + "integrity": "sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==", + "requires": { + "good-listener": "^1.2.2", + "select": "^1.1.2", + "tiny-emitter": "^2.0.0" + } + }, + "codepage": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/codepage/-/codepage-1.15.0.tgz", + "integrity": "sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==" + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true, + "peer": true + }, + "compute-scroll-into-view": { + "version": "1.0.17", + "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-1.0.17.tgz", + "integrity": "sha512-j4dx+Fb0URmzbwwMUrhqWM2BEWHdFGx+qZ9qqASHRPqvTYdqvWnHg0H1hIbcyLnvgnoNAVMlwkepyqM3DaIFUg==" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "core-js-pure": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.25.0.tgz", + "integrity": "sha512-IeHpLwk3uoci37yoI2Laty59+YqH9x5uR65/yiA0ARAJrTrN4YU0rmauLWfvqOuk77SlNJXj2rM6oT/dBD87+A==" + }, + "countup.js": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/countup.js/-/countup.js-2.2.0.tgz", + "integrity": "sha512-m0TvFNXm9/eFqJm+QiKVI8e0wRUHzlQSewz9dqVjlhl2DFoZtceLbomwzxHz0hJ1+r4zBC7wSpR/TpthG49h6g==" + }, + "crc-32": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==" + }, + "cropperjs": { + "version": "1.5.12", + "resolved": "https://registry.npmjs.org/cropperjs/-/cropperjs-1.5.12.tgz", + "integrity": "sha512-re7UdjE5UnwdrovyhNzZ6gathI4Rs3KGCBSc8HCIjUo5hO42CtzyblmWLj6QWVw7huHyDMfpKxhiO2II77nhDw==" + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true + }, + "csstype": { + "version": "2.6.20", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.20.tgz", + "integrity": "sha512-/WwNkdXfckNgw6S5R125rrW8ez139lBHWouiBvX8dfMFtcn6V81REDqnH7+CRpRipfYlyU1CmOnOxrmGcFOjeA==" + }, + "d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "requires": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, + "dayjs": { + "version": "1.11.3", + "resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.3.tgz", + "integrity": "sha512-xxwlswWOlGhzgQ4TKzASQkUhqERI3egRNqgV4ScR8wlANA/A9tZ7miXa44vTTKEq5l7vWoL5G57bG3zA+Kow0A==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "delegate": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz", + "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==" + }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + } + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "dom7": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/dom7/-/dom7-3.0.0.tgz", + "integrity": "sha512-oNlcUdHsC4zb7Msx7JN3K0Nro1dzJ48knvBOnDPKJ2GV9wl1i5vydJZUSyOfrkKFDZEud/jBsTk92S/VGSAe/g==", + "requires": { + "ssr-window": "^3.0.0-alpha.1" + } + }, + "dotenv": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.1.tgz", + "integrity": "sha512-1K6hR6wtk2FviQ4kEiSjFiH5rpzEVi8WW0x96aztHVMhEspNpc4DVOUTEHtEva5VThQ8IaBX1Pe4gSzpVVUsKQ==", + "dev": true + }, + "echarts": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/echarts/-/echarts-5.3.3.tgz", + "integrity": "sha512-BRw2serInRwO5SIwRviZ6Xgm5Lb7irgz+sLiFMmy/HOaf4SQ+7oYqxKzRHAKp4xHQ05AuHw1xvoQWJjDQq/FGw==", + "requires": { + "tslib": "2.3.0", + "zrender": "5.3.2" + } + }, + "echarts-gl": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/echarts-gl/-/echarts-gl-2.0.9.tgz", + "integrity": "sha512-oKeMdkkkpJGWOzjgZUsF41DOh6cMsyrGGXimbjK2l6Xeq/dBQu4ShG2w2Dzrs/1bD27b2pLTGSaUzouY191gzA==", + "requires": { + "claygl": "^1.2.1", + "zrender": "^5.1.1" + } + }, + "echarts-wordcloud": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/echarts-wordcloud/-/echarts-wordcloud-2.0.0.tgz", + "integrity": "sha512-K7l6pTklqdW7ZWzT/1CS0KhBSINr/cd7c5N1fVMzZMwLQHEwT7x+nivK7g5hkVh7WNcAv4Dn6/ZS5zMKRozC1g==", + "requires": {} + }, + "electron-to-chromium": { + "version": "1.4.137", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.137.tgz", + "integrity": "sha512-0Rcpald12O11BUogJagX3HsCN3FE83DSqWjgXoHo5a72KUKMSfI39XBgJpgNNxS9fuGzytaFjE06kZkiVFy2qA==", + "dev": true, + "peer": true + }, + "element-plus": { + "version": "2.2.9", + "resolved": "https://registry.npmmirror.com/element-plus/-/element-plus-2.2.9.tgz", + "integrity": "sha512-jYbL0JkCdv95rkT6trZJjCAizLPySa0qcd2cgq+57SKQnCZAcNDDq4GbTuFRnNavdoeCJnuM3HIficTIUpsMOQ==", + "requires": { + "@ctrl/tinycolor": "^3.4.1", + "@element-plus/icons-vue": "^2.0.6", + "@floating-ui/dom": "^0.5.4", + "@popperjs/core": "npm:@sxzz/popperjs-es@^2.11.7", + "@types/lodash": "^4.14.182", + "@types/lodash-es": "^4.17.6", + "@vueuse/core": "^8.7.5", + "async-validator": "^4.2.5", + "dayjs": "^1.11.3", + "escape-html": "^1.0.3", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", + "lodash-unified": "^1.0.2", + "memoize-one": "^6.0.0", + "normalize-wheel-es": "^1.1.2" + } + }, + "element-resize-detector": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/element-resize-detector/-/element-resize-detector-1.2.4.tgz", + "integrity": "sha512-Fl5Ftk6WwXE0wqCgNoseKWndjzZlDCwuPTcoVZfCP9R3EHQF8qUtr3YUPNETegRBOKqQKPW3n4kiIWngGi8tKg==", + "requires": { + "batch-processor": "1.0.0" + } + }, + "enhanced-resolve": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.3.tgz", + "integrity": "sha512-Bq9VSor+kjvW3f9/MiiR4eE3XYgOl7/rS8lnSxbRbF3kS0B2r+Y9w5krBWxZgDxASVZbdYrn5wT4j/Wb0J9qow==", + "dev": true, + "peer": true, + "requires": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + } + }, + "es-module-lexer": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", + "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", + "dev": true, + "peer": true + }, + "es5-ext": { + "version": "0.10.61", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.61.tgz", + "integrity": "sha512-yFhIqQAzu2Ca2I4SE2Au3rxVfmohU9Y7wqGR+s7+H7krk26NXhIRAZDgqd6xqjCEFUomDEA3/Bo/7fKmIkW1kA==", + "requires": { + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.3", + "next-tick": "^1.1.0" + } + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "requires": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "esbuild": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.39.tgz", + "integrity": "sha512-2kKujuzvRWYtwvNjYDY444LQIA3TyJhJIX3Yo4+qkFlDDtGlSicWgeHVJqMUP/2sSfH10PGwfsj+O2ro1m10xQ==", + "dev": true, + "requires": { + "esbuild-android-64": "0.14.39", + "esbuild-android-arm64": "0.14.39", + "esbuild-darwin-64": "0.14.39", + "esbuild-darwin-arm64": "0.14.39", + "esbuild-freebsd-64": "0.14.39", + "esbuild-freebsd-arm64": "0.14.39", + "esbuild-linux-32": "0.14.39", + "esbuild-linux-64": "0.14.39", + "esbuild-linux-arm": "0.14.39", + "esbuild-linux-arm64": "0.14.39", + "esbuild-linux-mips64le": "0.14.39", + "esbuild-linux-ppc64le": "0.14.39", + "esbuild-linux-riscv64": "0.14.39", + "esbuild-linux-s390x": "0.14.39", + "esbuild-netbsd-64": "0.14.39", + "esbuild-openbsd-64": "0.14.39", + "esbuild-sunos-64": "0.14.39", + "esbuild-windows-32": "0.14.39", + "esbuild-windows-64": "0.14.39", + "esbuild-windows-arm64": "0.14.39" + } + }, + "esbuild-android-64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.39.tgz", + "integrity": "sha512-EJOu04p9WgZk0UoKTqLId9VnIsotmI/Z98EXrKURGb3LPNunkeffqQIkjS2cAvidh+OK5uVrXaIP229zK6GvhQ==", + "dev": true, + "optional": true + }, + "esbuild-android-arm64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.39.tgz", + "integrity": "sha512-+twajJqO7n3MrCz9e+2lVOnFplRsaGRwsq1KL/uOy7xK7QdRSprRQcObGDeDZUZsacD5gUkk6OiHiYp6RzU3CA==", + "dev": true, + "optional": true + }, + "esbuild-darwin-64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.39.tgz", + "integrity": "sha512-ImT6eUw3kcGcHoUxEcdBpi6LfTRWaV6+qf32iYYAfwOeV+XaQ/Xp5XQIBiijLeo+LpGci9M0FVec09nUw41a5g==", + "dev": true, + "optional": true + }, + "esbuild-darwin-arm64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.39.tgz", + "integrity": "sha512-/fcQ5UhE05OiT+bW5v7/up1bDsnvaRZPJxXwzXsMRrr7rZqPa85vayrD723oWMT64dhrgWeA3FIneF8yER0XTw==", + "dev": true, + "optional": true + }, + "esbuild-freebsd-64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.39.tgz", + "integrity": "sha512-oMNH8lJI4wtgN5oxuFP7BQ22vgB/e3Tl5Woehcd6i2r6F3TszpCnNl8wo2d/KvyQ4zvLvCWAlRciumhQg88+kQ==", + "dev": true, + "optional": true + }, + "esbuild-freebsd-arm64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.39.tgz", + "integrity": "sha512-1GHK7kwk57ukY2yI4ILWKJXaxfr+8HcM/r/JKCGCPziIVlL+Wi7RbJ2OzMcTKZ1HpvEqCTBT/J6cO4ZEwW4Ypg==", + "dev": true, + "optional": true + }, + "esbuild-linux-32": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.39.tgz", + "integrity": "sha512-g97Sbb6g4zfRLIxHgW2pc393DjnkTRMeq3N1rmjDUABxpx8SjocK4jLen+/mq55G46eE2TA0MkJ4R3SpKMu7dg==", + "dev": true, + "optional": true + }, + "esbuild-linux-64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.39.tgz", + "integrity": "sha512-4tcgFDYWdI+UbNMGlua9u1Zhu0N5R6u9tl5WOM8aVnNX143JZoBZLpCuUr5lCKhnD0SCO+5gUyMfupGrHtfggQ==", + "dev": true, + "optional": true + }, + "esbuild-linux-arm": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.39.tgz", + "integrity": "sha512-t0Hn1kWVx5UpCzAJkKRfHeYOLyFnXwYynIkK54/h3tbMweGI7dj400D1k0Vvtj2u1P+JTRT9tx3AjtLEMmfVBQ==", + "dev": true, + "optional": true + }, + "esbuild-linux-arm64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.39.tgz", + "integrity": "sha512-23pc8MlD2D6Px1mV8GMglZlKgwgNKAO8gsgsLLcXWSs9lQsCYkIlMo/2Ycfo5JrDIbLdwgP8D2vpfH2KcBqrDQ==", + "dev": true, + "optional": true + }, + "esbuild-linux-mips64le": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.39.tgz", + "integrity": "sha512-epwlYgVdbmkuRr5n4es3B+yDI0I2e/nxhKejT9H0OLxFAlMkeQZxSpxATpDc9m8NqRci6Kwyb/SfmD1koG2Zuw==", + "dev": true, + "optional": true + }, + "esbuild-linux-ppc64le": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.39.tgz", + "integrity": "sha512-W/5ezaq+rQiQBThIjLMNjsuhPHg+ApVAdTz2LvcuesZFMsJoQAW2hutoyg47XxpWi7aEjJGrkS26qCJKhRn3QQ==", + "dev": true, + "optional": true + }, + "esbuild-linux-riscv64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.39.tgz", + "integrity": "sha512-IS48xeokcCTKeQIOke2O0t9t14HPvwnZcy+5baG13Z1wxs9ZrC5ig5ypEQQh4QMKxURD5TpCLHw2W42CLuVZaA==", + "dev": true, + "optional": true + }, + "esbuild-linux-s390x": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.39.tgz", + "integrity": "sha512-zEfunpqR8sMomqXhNTFEKDs+ik7HC01m3M60MsEjZOqaywHu5e5682fMsqOlZbesEAAaO9aAtRBsU7CHnSZWyA==", + "dev": true, + "optional": true + }, + "esbuild-netbsd-64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.39.tgz", + "integrity": "sha512-Uo2suJBSIlrZCe4E0k75VDIFJWfZy+bOV6ih3T4MVMRJh1lHJ2UyGoaX4bOxomYN3t+IakHPyEoln1+qJ1qYaA==", + "dev": true, + "optional": true + }, + "esbuild-openbsd-64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.39.tgz", + "integrity": "sha512-secQU+EpgUPpYjJe3OecoeGKVvRMLeKUxSMGHnK+aK5uQM3n1FPXNJzyz1LHFOo0WOyw+uoCxBYdM4O10oaCAA==", + "dev": true, + "optional": true + }, + "esbuild-sunos-64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.39.tgz", + "integrity": "sha512-qHq0t5gePEDm2nqZLb+35p/qkaXVS7oIe32R0ECh2HOdiXXkj/1uQI9IRogGqKkK+QjDG+DhwiUw7QoHur/Rwg==", + "dev": true, + "optional": true + }, + "esbuild-windows-32": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.39.tgz", + "integrity": "sha512-XPjwp2OgtEX0JnOlTgT6E5txbRp6Uw54Isorm3CwOtloJazeIWXuiwK0ONJBVb/CGbiCpS7iP2UahGgd2p1x+Q==", + "dev": true, + "optional": true + }, + "esbuild-windows-64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.39.tgz", + "integrity": "sha512-E2wm+5FwCcLpKsBHRw28bSYQw0Ikxb7zIMxw3OPAkiaQhLVr3dnVO8DofmbWhhf6b97bWzg37iSZ45ZDpLw7Ow==", + "dev": true, + "optional": true + }, + "esbuild-windows-arm64": { + "version": "0.14.39", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.39.tgz", + "integrity": "sha512-sBZQz5D+Gd0EQ09tZRnz/PpVdLwvp/ufMtJ1iDFYddDaPpZXKqPyaxfYBLs3ueiaksQ26GGa7sci0OqFzNs7KA==", + "dev": true, + "optional": true + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "peer": true + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, + "eslint": { + "version": "8.17.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.17.0.tgz", + "integrity": "sha512-gq0m0BTJfci60Fz4nczYxNAlED+sMcihltndR8t9t1evnU/azx53x3t2UHXC/uRjcbvRw/XctpaNygSTcQD+Iw==", + "dev": true, + "requires": { + "@eslint/eslintrc": "^1.3.0", + "@humanwhocodes/config-array": "^0.9.2", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.1.1", + "eslint-utils": "^3.0.0", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.3.2", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^6.0.1", + "globals": "^13.15.0", + "ignore": "^5.2.0", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "regexpp": "^3.2.0", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "dependencies": { + "eslint-scope": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + } + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } + } + }, + "eslint-plugin-vue": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.1.0.tgz", + "integrity": "sha512-EPCeInPicQ/YyfOWJDr1yfEeSNoFCMzUus107lZyYi37xejdOolNzS5MXGXp8+9bkoKZMdv/1AcZzQebME6r+g==", + "dev": true, + "requires": { + "eslint-utils": "^3.0.0", + "natural-compare": "^1.4.0", + "nth-check": "^2.0.1", + "postcss-selector-parser": "^6.0.9", + "semver": "^7.3.5", + "vue-eslint-parser": "^9.0.1", + "xml-name-validator": "^4.0.0" + } + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^2.0.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true + } + } + }, + "eslint-visitor-keys": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", + "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "dev": true + }, + "espree": { + "version": "9.3.2", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.2.tgz", + "integrity": "sha512-D211tC7ZwouTIuY5x9XnS0E9sWNChB7IYKX/Xp5eQj3nFXhqmiUDB9q27y76oFl8jTg3pXcQx/bpxMfs3CIZbA==", + "dev": true, + "requires": { + "acorn": "^8.7.1", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.3.0" + } + }, + "esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, + "events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "peer": true + }, + "ext": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz", + "integrity": "sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==", + "requires": { + "type": "^2.5.0" + }, + "dependencies": { + "type": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.6.0.tgz", + "integrity": "sha512-eiDBDOmkih5pMbo9OqsqPRGMljLodLcwd5XD5JbtNB0o89xZAwynY9EdCDsJU7LtcVCClu9DvM7/0Ep1hYX3EQ==" + } + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", + "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "dependencies": { + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + } + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "fastq": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, + "file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "requires": { + "flat-cache": "^3.0.4" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "requires": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + } + }, + "flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", + "dev": true + }, + "follow-redirects": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.0.tgz", + "integrity": "sha512-aExlJShTV4qOUOL7yF1U5tvLCB0xQuudbf6toyYA0E/acBNw71mvjFTnLaRp50aQaYocMR0a/RMMBIHeZnGyjQ==" + }, + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "frac": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/frac/-/frac-1.1.2.tgz", + "integrity": "sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==" + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "requires": { + "is-glob": "^4.0.3" + } + }, + "glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true, + "peer": true + }, + "globals": { + "version": "13.15.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.15.0.tgz", + "integrity": "sha512-bpzcOlgDhMG070Av0Vy5Owklpv1I6+j96GhUI7Rh7IzDCKLzboflLrrfqMu8NquDbiR4EOQk7XzJwqVJxicxog==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } + }, + "globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + } + }, + "good-listener": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz", + "integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=", + "requires": { + "delegate": "^3.1.2" + } + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true, + "peer": true + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "html-void-elements": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-2.0.1.tgz", + "integrity": "sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A==" + }, + "i18next": { + "version": "20.6.1", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-20.6.1.tgz", + "integrity": "sha512-yCMYTMEJ9ihCwEQQ3phLo7I/Pwycf8uAx+sRHwwk5U9Aui/IZYgQRyMqXafQOw5QQ7DM1Z+WyEXWIqSuJHhG2A==", + "requires": { + "@babel/runtime": "^7.12.0" + } + }, + "ignore": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "dev": true + }, + "immer": { + "version": "9.0.14", + "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.14.tgz", + "integrity": "sha512-ubBeqQutOSLIFCUBN03jGeOS6a3DoYlSYwYJTa+gSKEZKU5redJIqkIdZ3JVv/4RZpfcXdAWH5zCNLWPRv2WDw==" + }, + "immutable": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.0.0.tgz", + "integrity": "sha512-zIE9hX70qew5qTUjSS7wi1iwj/l7+m54KWU247nhM3v806UdGj1yDndXj+IOYxxtW9zyLI+xqFNZjTuDaLUqFw==", + "dev": true + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-core-module": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", + "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-hotkey": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/is-hotkey/-/is-hotkey-0.2.0.tgz", + "integrity": "sha512-UknnZK4RakDmTgz4PI1wIph5yxSs/mvChWs9ifnlXsKuXgWmOkY/hAE0H/k2MIqH0RlRye0i1oC07MCRSD28Mw==" + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==" + }, + "is-url": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", + "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "peer": true, + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "dependencies": { + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "peer": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "js-base64": { + "version": "3.7.2", + "resolved": "https://registry.npmmirror.com/js-base64/-/js-base64-3.7.2.tgz", + "integrity": "sha512-NnRs6dsyqUXejqk/yv2aiXlAvOs56sLkX6nUdeaNezI5LFFLlsZjOThmwnrcwh5ZZRwZlCMnVAY3CvhIhoVEKQ==" + }, + "js-cookie": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.1.tgz", + "integrity": "sha512-+0rgsUXZu4ncpPxRL+lNEptWMOWl9etvPHc/koSRp6MPwpRYAhmk0dUG00J4bxVV3r9uUzfo24wW0knS07SKSw==" + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "json-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/json-bigint/-/json-bigint-1.0.0.tgz", + "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "requires": { + "bignumber.js": "^9.0.0" + } + }, + "json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, + "peer": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "jsplumb": { + "version": "2.15.6", + "resolved": "https://registry.npmjs.org/jsplumb/-/jsplumb-2.15.6.tgz", + "integrity": "sha512-sIpbpz5eMVM+vV+MQzFCidlaa1RsknrQs6LOTKYDjYUDdTAi2AN2bFi94TxB33TifcIsRNV1jebcaxg0tCoPzg==" + }, + "klona": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.5.tgz", + "integrity": "sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ==", + "dev": true + }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "dev": true, + "peer": true + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmmirror.com/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + }, + "lodash-unified": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/lodash-unified/-/lodash-unified-1.0.2.tgz", + "integrity": "sha512-OGbEy+1P+UT26CYi4opY4gebD8cWRDxAT6MAObIVQMiqYdxZr1g3QHWCToVsm31x2NkLS4K3+MC2qInaRMa39g==", + "requires": {} + }, + "lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=" + }, + "lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=" + }, + "lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=" + }, + "lodash.foreach": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz", + "integrity": "sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM=" + }, + "lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" + }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", + "dev": true, + "peer": true + }, + "lodash.throttle": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", + "integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ=" + }, + "lodash.toarray": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.toarray/-/lodash.toarray-4.4.0.tgz", + "integrity": "sha1-JMS/zWsvuji/0FlNsRedjptlZWE=" + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "magic-string": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", + "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "requires": { + "sourcemap-codec": "^1.4.8" + } + }, + "memoize-one": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/memoize-one/-/memoize-one-6.0.0.tgz", + "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==" + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true, + "peer": true + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, + "micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "requires": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + } + }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + }, + "mime-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/mime-match/-/mime-match-1.0.2.tgz", + "integrity": "sha1-P4fDHprxpf1IX7nbE0Qosju7e6g=", + "requires": { + "wildcard": "^1.1.0" + } + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "requires": { + "mime-db": "1.52.0" + } + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "mitt": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.0.tgz", + "integrity": "sha512-7dX2/10ITVyqh4aOSVI9gdape+t9l2/8QxHrFmUXu4EEUpdlxl6RudZUPZoc+zuY2hk1j7XxVroIVIan/pD/SQ==" + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "namespace-emitter": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/namespace-emitter/-/namespace-emitter-2.0.1.tgz", + "integrity": "sha512-N/sMKHniSDJBjfrkbS/tpkPj4RAbvW3mr8UAzvlMHyun93XEm83IAvhWtJVHo+RHn/oO8Job5YN4b+wRjSVp5g==" + }, + "nanoid": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==" + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "next-tick": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", + "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==" + }, + "node-releases": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.4.tgz", + "integrity": "sha512-gbMzqQtTtDz/00jQzZ21PQzdI9PyLYqUSvD0p3naOhX4odFji0ZxYdnVwPTxmSwkmxhcFImpozceidSG+AgoPQ==", + "dev": true, + "peer": true + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "normalize-wheel-es": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/normalize-wheel-es/-/normalize-wheel-es-1.1.2.tgz", + "integrity": "sha512-scX83plWJXYH1J4+BhAuIHadROzxX0UBF3+HuZNY2Ks8BciE7tSTQ+5JhTsvzjaO0/EJdm4JBGrfObKxFf3Png==" + }, + "nprogress": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/nprogress/-/nprogress-0.2.0.tgz", + "integrity": "sha1-y480xTIT2JVyP8urkH6UIq28r7E=" + }, + "nth-check": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz", + "integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==", + "dev": true, + "requires": { + "boolbase": "^1.0.0" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "requires": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + } + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true + }, + "pinia": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.0.14.tgz", + "integrity": "sha512-0nPuZR4TetT/WcLN+feMSjWJku3SQU7dBbXC6uw+R6FLQJCsg+/0pzXyD82T1FmAYe0lsx+jnEDQ1BLgkRKlxA==", + "requires": { + "@vue/devtools-api": "^6.1.4", + "vue-demi": "*" + }, + "dependencies": { + "vue-demi": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.12.5.tgz", + "integrity": "sha512-BREuTgTYlUr0zw0EZn3hnhC3I6gPWv+Kwh4MCih6QcAeaTlaIX0DwOVN0wHej7hSvDPecz4jygy/idsgKfW58Q==", + "requires": {} + } + } + }, + "pinia-plugin-persistedstate": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/pinia-plugin-persistedstate/-/pinia-plugin-persistedstate-2.1.1.tgz", + "integrity": "sha512-HUgsU5IRtM75eAQiIqzT3p1oPEuYH1/B2ipTMU++yE+FV0LkHaBswdKXs0RMWYCmugO8s62oxLTh/N1dLNp+5A==", + "requires": {} + }, + "postcss": { + "version": "8.4.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz", + "integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==", + "requires": { + "nanoid": "^3.3.4", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + } + }, + "postcss-selector-parser": { + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", + "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", + "dev": true, + "requires": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + } + }, + "preact": { + "version": "10.7.2", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.7.2.tgz", + "integrity": "sha512-GLjn0I3r6ka+NvxJUppsVFqb4V0qDTEHT/QxHlidPuClGaxF/4AI2Qti4a0cv3XMh5n1+D3hLScW10LRIm5msQ==" + }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, + "prettier": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.6.2.tgz", + "integrity": "sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew==", + "dev": true + }, + "print-js": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/print-js/-/print-js-1.6.0.tgz", + "integrity": "sha512-BfnOIzSKbqGRtO4o0rnj/K3681BSd2QUrsIZy/+WdCIugjIswjmx3lDEZpXB2ruGf9d4b3YNINri81+J0FsBWg==" + }, + "prismjs": { + "version": "1.28.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.28.0.tgz", + "integrity": "sha512-8aaXdYvl1F7iC7Xm1spqSaY/OJBpYW3v+KJ+F17iYxvdc8sfjW194COK5wVhMZX45tGteiBQgdvD/nhxcRwylw==" + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "qrcodejs2-fixes": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/qrcodejs2-fixes/-/qrcodejs2-fixes-0.0.2.tgz", + "integrity": "sha512-wMUXYMOixAEJlLnjk5MbLiFaz0gQObWYm/TIFWB5+j7sTY5gPyr09Cx1EpcLYbsgfFdN3wHjrKAhZofTuCBGhg==" + }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "peer": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "regenerator-runtime": { + "version": "0.13.9", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", + "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" + }, + "regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true + }, + "resolve": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", + "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", + "dev": true, + "requires": { + "is-core-module": "^2.8.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "rollup": { + "version": "2.74.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.74.1.tgz", + "integrity": "sha512-K2zW7kV8Voua5eGkbnBtWYfMIhYhT9Pel2uhBk2WO5eMee161nPze/XRfvEQPFYz7KgrCCnmh2Wy0AMFLGGmMA==", + "dev": true, + "requires": { + "fsevents": "~2.3.2" + } + }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "requires": { + "queue-microtask": "^1.2.2" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "peer": true + }, + "sass": { + "version": "1.52.2", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.52.2.tgz", + "integrity": "sha512-mfHB2VSeFS7sZlPv9YohB9GB7yWIgQNTGniQwfQ04EoQN0wsQEv7SwpCwy/x48Af+Z3vDeFXz+iuXM3HK/phZQ==", + "dev": true, + "requires": { + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + } + }, + "sass-loader": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-13.0.0.tgz", + "integrity": "sha512-IHCFecI+rbPvXE2zO/mqdVFe8MU7ElGrwga9hh2H65Ru4iaBJAMRteum1c4Gsxi9Cq1FOtTEDd6+/AEYuQDM4Q==", + "dev": true, + "requires": { + "klona": "^2.0.4", + "neo-async": "^2.6.2" + } + }, + "schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "peer": true, + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + }, + "screenfull": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/screenfull/-/screenfull-6.0.1.tgz", + "integrity": "sha512-yzQW+j4zMUBQC51xxWaoDYjxOtl8Kn+xvue3p6v/fv2pIi1jH4AldgVLU8TBfFVgH2x3VXlf3+YiA/AYIPlaew==" + }, + "scroll-into-view-if-needed": { + "version": "2.2.29", + "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.29.tgz", + "integrity": "sha512-hxpAR6AN+Gh53AdAimHM6C8oTN1ppwVZITihix+WqalywBeFcQ6LdQP5ABNl26nX8GTEL7VT+b8lKpdqq65wXg==", + "requires": { + "compute-scroll-into-view": "^1.0.17" + } + }, + "select": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz", + "integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=" + }, + "semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "dev": true, + "peer": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "slate": { + "version": "0.72.8", + "resolved": "https://registry.npmjs.org/slate/-/slate-0.72.8.tgz", + "integrity": "sha512-/nJwTswQgnRurpK+bGJFH1oM7naD5qDmHd89JyiKNT2oOKD8marW0QSBtuFnwEbL5aGCS8AmrhXQgNOsn4osAw==", + "requires": { + "immer": "^9.0.6", + "is-plain-object": "^5.0.0", + "tiny-warning": "^1.0.3" + } + }, + "slate-history": { + "version": "0.66.0", + "resolved": "https://registry.npmjs.org/slate-history/-/slate-history-0.66.0.tgz", + "integrity": "sha512-6MWpxGQZiMvSINlCbMW43E2YBSVMCMCIwQfBzGssjWw4kb0qfvj0pIdblWNRQZD0hR6WHP+dHHgGSeVdMWzfng==", + "requires": { + "is-plain-object": "^5.0.0" + } + }, + "snabbdom": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/snabbdom/-/snabbdom-3.5.0.tgz", + "integrity": "sha512-Ff5BKG18KrrPuskHJlA9aujPHqEabItaDl96l7ZZndF4zt5AYSczz7ZjjgQAX5IBd5cd25lw9NfgX21yVUJ+9g==" + }, + "sortablejs": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.0.tgz", + "integrity": "sha512-bv9qgVMjUMf89wAvM6AxVvS/4MX3sPeN0+agqShejLU5z5GX4C75ow1O2e5k4L6XItUyAK3gH6AxSbXrOM5e8w==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==" + }, + "source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "peer": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==" + }, + "splitpanes": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/splitpanes/-/splitpanes-3.1.1.tgz", + "integrity": "sha512-VUkxDJfIGSvTM/fm/+OSrx8ha9URwE/9B8FPvfzoBuAxVELIHBWpsfnJXIXv77zVwuex//QQL4kTU9SDBPeHjA==" + }, + "ssf": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/ssf/-/ssf-0.11.2.tgz", + "integrity": "sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==", + "requires": { + "frac": "~1.1.2" + } + }, + "ssr-window": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ssr-window/-/ssr-window-3.0.0.tgz", + "integrity": "sha512-q+8UfWDg9Itrg0yWK7oe5p/XRCJpJF9OBtXfOPgSJl+u3Xd5KI328RUEvUqSMVM9CiQUEf1QdBzJMkYGErj9QA==" + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true + }, + "tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "peer": true + }, + "terser": { + "version": "5.13.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.13.1.tgz", + "integrity": "sha512-hn4WKOfwnwbYfe48NgrQjqNOH9jzLqRcIfbYytOXCOv46LBfWr9bDS17MQqOi+BWGD0sJK3Sj5NC/gJjiojaoA==", + "dev": true, + "peer": true, + "requires": { + "acorn": "^8.5.0", + "commander": "^2.20.0", + "source-map": "~0.8.0-beta.0", + "source-map-support": "~0.5.20" + }, + "dependencies": { + "source-map": { + "version": "0.8.0-beta.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", + "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", + "dev": true, + "peer": true, + "requires": { + "whatwg-url": "^7.0.0" + } + } + } + }, + "terser-webpack-plugin": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.1.tgz", + "integrity": "sha512-GvlZdT6wPQKbDNW/GDQzZFg/j4vKU96yl2q6mcUkzKOgW4gwf1Z8cZToUCrz31XHlPWH8MVb1r2tFtdDtTGJ7g==", + "dev": true, + "peer": true, + "requires": { + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.0", + "source-map": "^0.6.1", + "terser": "^5.7.2" + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "tiny-emitter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", + "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==" + }, + "tiny-warning": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", + "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", + "dev": true, + "peer": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "tslib": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", + "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==" + }, + "tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + } + } + }, + "type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" + }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + }, + "typescript": { + "version": "4.7.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.3.tgz", + "integrity": "sha512-WOkT3XYvrpXx4vMMqlD+8R8R37fZkjyLGlxavMc4iB8lrl8L0DeTcHbYgw/v0N/z9wAFsgBhcsF0ruoySS22mA==", + "devOptional": true + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true + }, + "vite": { + "version": "2.9.9", + "resolved": "https://registry.npmjs.org/vite/-/vite-2.9.9.tgz", + "integrity": "sha512-ffaam+NgHfbEmfw/Vuh6BHKKlI/XIAhxE5QSS7gFLIngxg171mg1P3a4LSRME0z2ZU1ScxoKzphkipcYwSD5Ew==", + "dev": true, + "requires": { + "esbuild": "^0.14.27", + "fsevents": "~2.3.2", + "postcss": "^8.4.13", + "resolve": "^1.22.0", + "rollup": "^2.59.0" + } + }, + "vue": { + "version": "3.2.36", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.2.36.tgz", + "integrity": "sha512-5yTXmrE6gW8IQgttzHW5bfBiFA6mx35ZXHjGLDmKYzW6MMmYvCwuKybANRepwkMYeXw2v1buGg3/lPICY5YlZw==", + "requires": { + "@vue/compiler-dom": "3.2.36", + "@vue/compiler-sfc": "3.2.36", + "@vue/runtime-dom": "3.2.36", + "@vue/server-renderer": "3.2.36", + "@vue/shared": "3.2.36" + } + }, + "vue-clipboard3": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/vue-clipboard3/-/vue-clipboard3-2.0.0.tgz", + "integrity": "sha512-Q9S7dzWGax7LN5iiSPcu/K1GGm2gcBBlYwmMsUc5/16N6w90cbKow3FnPmPs95sungns4yvd9/+JhbAznECS2A==", + "requires": { + "clipboard": "^2.0.6" + } + }, + "vue-eslint-parser": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.0.2.tgz", + "integrity": "sha512-uCPQwTGjOtAYrwnU+76pYxalhjsh7iFBsHwBqDHiOPTxtICDaraO4Szw54WFTNZTAEsgHHzqFOu1mmnBOBRzDA==", + "dev": true, + "requires": { + "debug": "^4.3.4", + "eslint-scope": "^7.1.1", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.3.1", + "esquery": "^1.4.0", + "lodash": "^4.17.21", + "semver": "^7.3.6" + }, + "dependencies": { + "eslint-scope": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + } + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } + } + }, + "vue-grid-layout": { + "version": "3.0.0-beta1", + "resolved": "https://registry.npmjs.org/vue-grid-layout/-/vue-grid-layout-3.0.0-beta1.tgz", + "integrity": "sha512-MsW0yfYNtnAO/uDhfZvkP6effxSJxvhAFbIL37x6Rn3vW9xf0WHVefKaSbQMLpSq3mXnR6ut0pg2Cd5lqIIZzg==", + "requires": { + "@interactjs/actions": "^1.10.2", + "@interactjs/auto-start": "^1.10.2", + "@interactjs/dev-tools": "^1.10.2", + "@interactjs/interactjs": "^1.10.2", + "@interactjs/modifiers": "^1.10.2", + "element-resize-detector": "^1.2.1", + "mitt": "^2.1.0" + }, + "dependencies": { + "mitt": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-2.1.0.tgz", + "integrity": "sha512-ILj2TpLiysu2wkBbWjAmww7TkZb65aiQO+DkVdUTBpBXq+MHYiETENkKFMtsJZX1Lf4pe4QOrTSjIfUwN5lRdg==" + } + } + }, + "vue-i18n": { + "version": "9.1.10", + "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-9.1.10.tgz", + "integrity": "sha512-jpr7gV5KPk4n+sSPdpZT8Qx3XzTcNDWffRlHV/cT2NUyEf+sEgTTmLvnBAibjOFJ0zsUyZlVTAWH5DDnYep+1g==", + "requires": { + "@intlify/core-base": "9.1.10", + "@intlify/shared": "9.1.10", + "@intlify/vue-devtools": "9.1.10", + "@vue/devtools-api": "^6.0.0-beta.7" + } + }, + "vue-router": { + "version": "4.0.15", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.0.15.tgz", + "integrity": "sha512-xa+pIN9ZqORdIW1MkN2+d9Ui2pCM1b/UMgwYUCZOiFYHAvz/slKKBDha8DLrh5aCG/RibtrpyhKjKOZ85tYyWg==", + "requires": { + "@vue/devtools-api": "^6.0.0" + } + }, + "wangeditor": { + "version": "4.7.15", + "resolved": "https://registry.npmjs.org/wangeditor/-/wangeditor-4.7.15.tgz", + "integrity": "sha512-aPTdREd8BxXVyJ5MI+LU83FQ7u1EPd341iXIorRNYSOvoimNoZ4nPg+yn3FGbB93/owEa6buLw8wdhYnMCJQLg==", + "requires": { + "@babel/runtime": "^7.11.2", + "@babel/runtime-corejs3": "^7.11.2", + "tslib": "^2.1.0" + } + }, + "watchpack": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz", + "integrity": "sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA==", + "dev": true, + "peer": true, + "requires": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + } + }, + "webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "dev": true, + "peer": true + }, + "webpack": { + "version": "5.72.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.72.1.tgz", + "integrity": "sha512-dXG5zXCLspQR4krZVR6QgajnZOjW2K/djHvdcRaDQvsjV9z9vaW6+ja5dZOYbqBBjF6kGXka/2ZyxNdc+8Jung==", + "dev": true, + "peer": true, + "requires": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^0.0.51", + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/wasm-edit": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "acorn": "^8.4.1", + "acorn-import-assertions": "^1.7.6", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.9.3", + "es-module-lexer": "^0.9.0", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.9", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.1.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.1.3", + "watchpack": "^2.3.1", + "webpack-sources": "^3.2.3" + } + }, + "webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "dev": true, + "peer": true + }, + "whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "dev": true, + "peer": true, + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "wildcard": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-1.1.2.tgz", + "integrity": "sha1-pwIEUwhNjNLv5wup02liY94XEKU=" + }, + "wmf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wmf/-/wmf-1.0.2.tgz", + "integrity": "sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==" + }, + "word": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/word/-/word-0.3.0.tgz", + "integrity": "sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==" + }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "xlsx": { + "version": "0.18.5", + "resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.18.5.tgz", + "integrity": "sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==", + "requires": { + "adler-32": "~1.3.0", + "cfb": "~1.2.1", + "codepage": "~1.15.0", + "crc-32": "~1.2.1", + "ssf": "~0.11.2", + "wmf": "~1.0.1", + "word": "~0.3.0" + } + }, + "xml-name-validator": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", + "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "zrender": { + "version": "5.3.2", + "resolved": "https://registry.npmmirror.com/zrender/-/zrender-5.3.2.tgz", + "integrity": "sha512-8IiYdfwHj2rx0UeIGZGGU4WEVSDEdeVCaIg/fomejg1Xu6OifAL1GVzIPHg2D+MyUkbNgPWji90t0a8IDk+39w==", + "requires": { + "tslib": "2.3.0" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..8b2ab23 --- /dev/null +++ b/package.json @@ -0,0 +1,88 @@ +{ + "name": "vue-next-admin", + "version": "2.1.1", + "description": "vue3 vite next admin template", + "author": "lyt_20201208", + "license": "MIT", + "scripts": { + "dev": "vite --force", + "build": "vite build", + "lint-fix": "eslint --fix --ext .js --ext .jsx --ext .vue src/" + }, + "dependencies": { + "@element-plus/icons-vue": "^2.0.6", + "@kjgl77/datav-vue3": "^1.2.1", + "@wangeditor/editor": "^5.1.14", + "axios": "^0.27.2", + "countup.js": "^2.2.0", + "cropperjs": "^1.5.12", + "echarts": "^5.3.3", + "echarts-gl": "^2.0.9", + "echarts-wordcloud": "^2.0.0", + "element-plus": "^2.2.9", + "js-base64": "^3.7.2", + "js-cookie": "^3.0.1", + "json-bigint": "^1.0.0", + "jsplumb": "^2.15.6", + "mitt": "^3.0.0", + "nprogress": "^0.2.0", + "pinia": "^2.0.14", + "pinia-plugin-persistedstate": "^2.1.1", + "print-js": "^1.6.0", + "qrcodejs2-fixes": "^0.0.2", + "screenfull": "^6.0.1", + "sortablejs": "^1.15.0", + "splitpanes": "^3.1.1", + "vue": "^3.2.36", + "vue-clipboard3": "^2.0.0", + "vue-grid-layout": "^3.0.0-beta1", + "vue-i18n": "^9.1.10", + "vue-router": "^4.0.15", + "wangeditor": "^4.7.15", + "xlsx": "^0.18.5" + }, + "devDependencies": { + "@types/json-bigint": "^1.0.1", + "@types/node": "^17.0.39", + "@types/nprogress": "^0.2.0", + "@types/sortablejs": "^1.13.0", + "@typescript-eslint/eslint-plugin": "^5.27.0", + "@typescript-eslint/parser": "^5.27.0", + "@vitejs/plugin-vue": "^2.3.3", + "@vue/compiler-sfc": "^3.2.36", + "dotenv": "^16.0.1", + "eslint": "^8.17.0", + "eslint-plugin-vue": "^9.1.0", + "prettier": "^2.6.2", + "sass": "^1.52.2", + "sass-loader": "^13.0.0", + "typescript": "^4.7.3", + "vite": "^2.9.9", + "vue-eslint-parser": "^9.0.2" + }, + "browserslist": [ + "> 1%", + "last 2 versions", + "not dead" + ], + "bugs": { + "url": "https://gitee.com/lyt-top/vue-next-admin/issues" + }, + "engines": { + "node": ">=12.0.0", + "npm": ">= 6.0.0" + }, + "keywords": [ + "vue", + "vue3", + "vuejs/vue-next", + "element-ui", + "element-plus", + "vue-next-admin", + "next-admin" + ], + "repository": { + "type": "git", + "url": "https://gitee.com/lyt-top/vue-next-admin.git" + } +} diff --git a/plugins.d.ts b/plugins.d.ts new file mode 100644 index 0000000..be0457a --- /dev/null +++ b/plugins.d.ts @@ -0,0 +1,4 @@ +declare module 'vue-grid-layout'; +declare module 'qrcodejs2-fixes'; +declare module 'splitpanes'; +declare module 'js-cookie'; diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..9da231b --- /dev/null +++ b/public/favicon.ico Binary files differ diff --git a/shim.d.ts b/shim.d.ts new file mode 100644 index 0000000..3e9bfd0 --- /dev/null +++ b/shim.d.ts @@ -0,0 +1,13 @@ +/* eslint-disable */ + +// 声明文件,*.vue 后缀的文件交给 vue 模块来处理 +declare module '*.vue' { + import type { DefineComponent } from 'vue'; + const component: DefineComponent<{}, {}, any>; + export default component; +} + +// 声明文件,定义全局变量。其它 app.config.globalProperties.xxx,使用 getCurrentInstance() 来获取 +interface Window { + nextLoading: boolean; +} diff --git a/source.d.ts b/source.d.ts new file mode 100644 index 0000000..2f9c768 --- /dev/null +++ b/source.d.ts @@ -0,0 +1,6 @@ +declare module '*.json'; +declare module '*.png'; +declare module '*.jpg'; +declare module '*.scss'; +declare module '*.ts'; +declare module '*.js'; diff --git a/src/App.vue b/src/App.vue new file mode 100644 index 0000000..942737a --- /dev/null +++ b/src/App.vue @@ -0,0 +1,115 @@ +<template> +<!-- <transition name="fade" mode="out-in">--> +<!-- <keep-alive :exclude="excludeList">--> +<!-- <router-view v-if="!$route.meta.iskeepAlive" :key="$route.path"></router-view>--> +<!-- </keep-alive>--> +<!-- </transition>--> + <!-- <router-view v-if="!$route.meta.iskeepAlive" v-slot="{ Component }">--> + <!-- <transition name="fade" mode="in-out">--> + <!-- <keep-alive :exclude="excludeList" :include="includeList">--> + <!-- <components :is="Component" :key="$route.id"></components>--> + <!-- </keep-alive>--> + <!-- </transition>--> + <!-- </router-view>--> + <el-config-provider :size="getGlobalComponentSize" :locale="i18nLocale"> + <router-view v-show="themeConfig.lockScreenTime > 1" /> + <LockScreen v-if="themeConfig.isLockScreen" /> + <Setings ref="setingsRef" v-show="themeConfig.lockScreenTime > 1" /> + <CloseFull v-if="!themeConfig.isLockScreen" /> + </el-config-provider> +</template> + +<script lang="ts"> +import { computed, ref, getCurrentInstance, onBeforeMount, onMounted, onUnmounted, nextTick, defineComponent, watch, reactive, toRefs } from 'vue'; +import { useRoute } from 'vue-router'; +import { storeToRefs } from 'pinia'; +import { useTagsViewRoutes } from '/@/stores/tagsViewRoutes'; +import { useThemeConfig } from '/@/stores/themeConfig'; +import other from '/@/utils/other'; +import { Local, Session } from '/@/utils/storage'; +import setIntroduction from '/@/utils/setIconfont'; +import LockScreen from '/@/layout/lockScreen/index.vue'; +import Setings from '/@/layout/navBars/breadcrumb/setings.vue'; +import CloseFull from '/@/layout/navBars/breadcrumb/closeFull.vue'; +import { initBackEndControlRoutes } from './router/backEnd'; + +export default { + name: 'app', + components: { LockScreen, Setings, CloseFull }, + setup() { + const { proxy } = <any>getCurrentInstance(); + const setingsRef = ref(); + const route = useRoute(); + const stores = useTagsViewRoutes(); + const storesThemeConfig = useThemeConfig(); + const { themeConfig } = storeToRefs(storesThemeConfig); + const state = reactive({ + i18nLocale: null, + excludeList: ['a-e'], + includeList: [] + }); + + // 获取全局组件大小 + const getGlobalComponentSize = computed(() => { + return other.globalComponentSize(); + }); + // 布局配置弹窗打开 + const openSetingsDrawer = () => { + setingsRef.value.openDrawer(); + }; + // 设置初始化,防止刷新时恢复默认 + onBeforeMount(() => { + // 设置批量第三方 icon 图标 + setIntroduction.cssCdn(); + // 设置批量第三方 js + setIntroduction.jsCdn(); + }); + // 页面加载时 + onMounted(() => { + nextTick(() => { + // 监听布局配置弹窗点击打开 + proxy.mittBus.on('openSetingsDrawer', () => { + openSetingsDrawer(); + }); + // 设置 i18n,App.vue 中的 el-config-provider + proxy.mittBus.on('getI18nConfig', (locale: string) => { + (state.i18nLocale as string | null) = locale; + }); + // 获取缓存中的布局配置; + if (Local.get('themeConfig')) { + storesThemeConfig.setThemeConfig(themeConfig.value); + // storesThemeConfig.setThemeConfig(Local.get('themeConfig')); + document.documentElement.style.cssText = Local.get('themeConfigStyle'); + } + // 获取缓存中的全屏配置 + if (Session.get('isTagsViewCurrenFull')) { + stores.setCurrenFullscreen(Session.get('isTagsViewCurrenFull')); + } + }); + // if(!Session.get('token')) return + // initBackEndControlRoutes() + }); + // 页面销毁时,关闭监听布局配置/i18n监听 + onUnmounted(() => { + proxy.mittBus.off('openSetingsDrawer', () => {}); + proxy.mittBus.off('getI18nConfig', () => {}); + }); + // 监听路由的变化,设置网站标题 + watch( + () => route.path, + () => { + other.useTitle(); + }, + { + deep: true + } + ); + return { + themeConfig, + setingsRef, + getGlobalComponentSize, + ...toRefs(state) + }; + } +}; +</script> diff --git a/src/api/accidentManagementSystem/index.ts b/src/api/accidentManagementSystem/index.ts new file mode 100644 index 0000000..657ef56 --- /dev/null +++ b/src/api/accidentManagementSystem/index.ts @@ -0,0 +1,145 @@ +import request from '/@/utils/request'; + +export function accidentManagementSystemApi() { + return { + // 事故快报一览 + accidentList: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/accidentExpress/page/list', + method: 'post', + data: params + }); + }, + // 事故快报新增 + accidentAdd: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/accidentExpress/add', + method: 'post', + data: params + }); + }, + // 事故快报详情 + accidentScarh: (params: number) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/accidentExpress/info/${params}`, + method: 'get' + }); + }, + // 事故快报修改 + accidentView: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/accidentExpress/update', + method: 'post', + data: params + }); + }, + // 事故快报删除 + accidentDele: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/accidentExpress/batchDelete`, + method: 'post', + data: params + }); + }, + // 工伤申报一览 + workList: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/workInjuryDeclaration/page/list', + method: 'post', + data: params + }); + }, + // 工伤申报新增 + workAdd: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/workInjuryDeclaration/add', + method: 'post', + data: params + }); + }, + // 工伤申报详情 + workScarh: (params: number) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/workInjuryDeclaration/info/${params}`, + method: 'get' + }); + }, + // 工伤申报修改 + workView: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/workInjuryDeclaration/update', + method: 'post', + data: params + }); + }, + // 工伤申报删除/批量删除 + workDelete: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/workInjuryDeclaration/batchDelete`, + method: 'post', + data: params + }); + }, + // 伤亡人员一览 + casualtyList: (id: number) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/accidentExpress/casualty/list/${id}`, + method: 'get' + }); + }, + // 伤亡人员新增 + casualtyAdd: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/accidentExpress/casualty/add`, + method: 'post', + data: params + }); + }, + // 伤亡人员删除 + casualtyDel: (id: number) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/accidentExpress/casualty/del/${id}`, + method: 'get' + }); + }, + // 事故案例 一览 + getaccidentCaseList: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/accidentCase/page/list`, + method: 'post', + data: params + }); + }, + //事故案例 新增 + getaccidentCaseAdd: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/accidentCase/add`, + method: 'post', + data: params + }); + }, + //事故案例 新增 + getaccidentCaseUpdata: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/accidentCase/update`, + method: 'post', + data: params + }); + }, + //事故案例 详情 + getaccidentCaseDetail: (id: number) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/accidentCase/info/${id}`, + method: 'get' + }); + }, + //事故案例 删除 + getaccidentCaseDelete: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/accidentCase/batchDelete`, + method: 'post', + data: params + }); + } + }; +} diff --git a/src/api/contingencyManagement/contingency/index.ts b/src/api/contingencyManagement/contingency/index.ts new file mode 100644 index 0000000..b54e382 --- /dev/null +++ b/src/api/contingencyManagement/contingency/index.ts @@ -0,0 +1,83 @@ +import request from '/@/utils/request'; + +export function contingencyApi() { + return { + //应急队伍一览 + getTeamManagementList: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/emergencyTeam/page/list`, + method: 'post', + data: params + }); + }, + // 应急队伍新增 + addEmergencyTeam: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/emergencyTeam/add`, + method: 'post', + data: params + }); + }, + // 应急队伍详情 + seeEmergencyTeam: (params: number) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/emergencyTeam/info/${params}`, + method: 'get' + }); + }, + // 应急队伍编辑 + editEmergencyTeam: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/emergencyTeam/update`, + method: 'post', + data: params + }); + }, + // 应急队伍删除 + deleteEmergencyTeam: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/emergencyTeam/batchDelete`, + method: 'post', + data: params + }); + }, + // 应急队伍人员一览 + getEmergencyTeamPersonnelList: (params: number) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/emergencyTeam/memberList/${params}`, + method: 'get' + // data:params + }); + }, + // 应急队伍人员新增 + addEmergencyTeamPersonnel: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/emergencyTeam/addMember`, + method: 'post', + data: params + }); + }, + // 应急队伍人员详情 + seeEmergencyTeamPersonnel: (params: number) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/emergencyTeam/infoMember/${params}`, + method: 'get' + }); + }, + // 应急队伍人员编辑 + editEmergencyTeamPersonnel: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/emergencyTeam/updateMember`, + method: 'post', + data: params + }); + }, + // 应急队伍人员删除 + deleteEmergencyTeamPersonnel: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/emergencyTeam/deleteMember/${params}`, + method: 'get' + }); + } + }; +} diff --git a/src/api/contingencyManagement/emergencyDrillEvaluation/index.ts b/src/api/contingencyManagement/emergencyDrillEvaluation/index.ts new file mode 100644 index 0000000..b2f81aa --- /dev/null +++ b/src/api/contingencyManagement/emergencyDrillEvaluation/index.ts @@ -0,0 +1,45 @@ +import request from '/@/utils/request'; + +export function emergencyDrillEvaluationApi() { + return { + // 应急演练实施评价一览 + getEmergencyDrillEvaluationList: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/emergencyDrillEvaluation/page/list', + method: 'post', + data: params + }); + }, + // 应急演练实施评价新增 + addEmergencyDrillEvaluation: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/emergencyDrillEvaluation/add`, + method: 'post', + data: params + }); + }, + // 应急演练实施评价详情 + seeEmergencyDrillEvaluation: (params: number) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/emergencyDrillEvaluation/info/${params}`, + method: 'get' + }); + }, + // 应急演练实施评价编辑 + editEmergencyDrillEvaluation: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/emergencyDrillEvaluation/update`, + method: 'post', + data: params + }); + }, + // 应急演练实施评价删除 + deleteEmergencyDrillEvaluation: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/emergencyDrillEvaluation/batchDelete`, + method: 'post', + data: params + }); + } + }; +} diff --git a/src/api/contingencyManagement/emergencyDrillExecute/index.ts b/src/api/contingencyManagement/emergencyDrillExecute/index.ts new file mode 100644 index 0000000..911ac5f --- /dev/null +++ b/src/api/contingencyManagement/emergencyDrillExecute/index.ts @@ -0,0 +1,45 @@ +import request from '/@/utils/request'; + +export function emergencyDrillExecuteApi() { + return { + // 应急演练实施一览 + getEmergencyDrillExecuteList: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/emergencyDrillExecute/page/list', + method: 'post', + data: params + }); + }, + // 应急演练实施新增 + addEmergencyDrillExecute: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/emergencyDrillExecute/add`, + method: 'post', + data: params + }); + }, + // 应急演练实施详情 + seeEmergencyDrillExecute: (params: number) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/emergencyDrillExecute/info/${params}`, + method: 'get' + }); + }, + // 应急演练实施编辑 + editEmergencyDrillExecute: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/emergencyDrillExecute/update`, + method: 'post', + data: params + }); + }, + // 应急演练实施删除 + deleteEmergencyDrillExecute: (params: any) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/emergencyDrillExecute/batchDelete`, + method: 'post', + data: params + }); + } + }; +} diff --git a/src/api/contingencyManagement/emergencyDrillPlan/index.ts b/src/api/contingencyManagement/emergencyDrillPlan/index.ts new file mode 100644 index 0000000..110d032 --- /dev/null +++ b/src/api/contingencyManagement/emergencyDrillPlan/index.ts @@ -0,0 +1,45 @@ +import request from '/@/utils/request'; + +export function releaseDrillPlanApi() { + return { + //演练计划发布一览 + getReleaseDrillPlanList: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/emergencyDrillPlan/page/list', + method: 'post', + data: params + }); + }, + // 演练计划发布新增 + addReleaseDrillPlan: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/emergencyDrillPlan/add`, + method: 'post', + data: params + }); + }, + // 演练计划发布详情 + seeReleaseDrillPlan: (params: number) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/emergencyDrillPlan/info/${params}`, + method: 'get' + }); + }, + // 演练计划发布编辑 + editReleaseDrillPlan: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/emergencyDrillPlan/update`, + method: 'post', + data: params + }); + }, + // 演练计划发布删除 + deleteReleaseDrillPlan: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/emergencyDrillPlan/batchDelete`, + method: 'post', + data: params + }); + } + }; +} diff --git a/src/api/contingencyManagement/emergencyMaterialsInspection/index.ts b/src/api/contingencyManagement/emergencyMaterialsInspection/index.ts new file mode 100644 index 0000000..0809c93 --- /dev/null +++ b/src/api/contingencyManagement/emergencyMaterialsInspection/index.ts @@ -0,0 +1,45 @@ +import request from '/@/utils/request'; + +export function emergencyMaterialsInspectionApi() { + return { + //应急物资检查一览 + getEmergencyMaterialsInspectionList: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/emergencySuppliesInspect/page/list', + method: 'post', + data: params + }); + }, + // 应急物资检查新增 + addEmergencyMaterialsInspection: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/emergencySuppliesInspect/add`, + method: 'post', + data: params + }); + }, + // 应急物资检查详情 + seeEmergencyMaterialsInspection: (params: number) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/emergencySuppliesInspect/info/${params}`, + method: 'get' + }); + }, + // 应急物资检查编辑 + editEmergencyMaterialsInspection: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/emergencySuppliesInspect/update`, + method: 'post', + data: params + }); + }, + // 应急物资检查删除 + deleteEmergencyMaterialsInspection: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/emergencySuppliesInspect/batchDelete`, + method: 'post', + data: params + }); + } + }; +} diff --git a/src/api/contingencyManagement/emergencyPlan/index.ts b/src/api/contingencyManagement/emergencyPlan/index.ts new file mode 100644 index 0000000..4b7a323 --- /dev/null +++ b/src/api/contingencyManagement/emergencyPlan/index.ts @@ -0,0 +1,91 @@ +import request from '/@/utils/request'; + +export function emergencyPlanApi() { + return { + // 应急预案管理一览 + getEmergencyPlanList: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/emergencyPlan/page/list', + method: 'post', + data: params + }); + }, + // 应急预案管理新增 + addEmergencyPlan: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/emergencyPlan/add`, + method: 'post', + data: params + }); + }, + // 应急队伍详情 + seeEmergencyTeam: (params: number) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/emergencyPlan/info/${params}`, + method: 'get' + }); + }, + // 应急队伍编辑 + editEmergencyTeam: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/emergencyPlan/update`, + method: 'post', + data: params + }); + }, + // 应急队伍删除 + deleteEmergencyTeam: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/emergencyPlan/batchDelete`, + method: 'post', + data: params + }); + }, + // 应急队伍废止 + EmergencyTeam: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/emergencyPlan/updateAbolish?id=${params}&abolishStatus=true`, + method: 'get' + }); + }, + // 应急队伍还原 + reductionEmergencyTeam: (params: number) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/emergencyPlan/updateAbolish?id=${params}&abolishStatus=false`, + method: 'get' + }); + }, + // 应急预案管理审批新增 + approvalEmergencyPlan: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/emergencyWorkApprove/add`, + method: 'post', + data: params + }); + }, + // 应急预案管理审批修改 + editApprovalEmergencyPlan: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/emergencyWorkApprove/update`, + method: 'post', + data: params + }); + }, + // 应急预案管理审批查看 + approvalProcessEmergencyPlan: (params: number) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/emergencyWorkApprove/info/${params}`, + method: 'get', + data: params + }); + }, + // 审批一览 + processEmergencyPlan: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/emergencyWorkApprove/page/list`, + method: 'post', + data: params + }); + } + }; +} diff --git a/src/api/contingencyManagement/emergencyPlanLog/index.ts b/src/api/contingencyManagement/emergencyPlanLog/index.ts new file mode 100644 index 0000000..80c1885 --- /dev/null +++ b/src/api/contingencyManagement/emergencyPlanLog/index.ts @@ -0,0 +1,45 @@ +import request from '/@/utils/request'; + +export function emergencyPlanLogApi() { + return { + // 应急预案启动记录一览 + getEmergencyPlanLogList: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/emergencyPlanLog/page/list', + method: 'post', + data: params + }); + }, + // 应急预案启动记录新增 + addEmergencyPlanLog: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/emergencyPlanLog/add', + method: 'post', + data: params + }); + }, + // 应急预案启动记录详情 + seeEmergencyPlanLog: (params: number) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/emergencyPlanLog/info/${params}`, + method: 'get' + }); + }, + // 应急预案启动记录修改 + editEmergencyPlanLog: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/emergencyPlanLog/update', + method: 'post', + data: params + }); + }, + // 应急预案启动记录删除 + deleteEmergencyPlanLog: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/emergencyPlanLog/batchDelete`, + method: 'post', + data: params + }); + } + }; +} diff --git a/src/api/contingencyManagement/emergencyResources/index.ts b/src/api/contingencyManagement/emergencyResources/index.ts new file mode 100644 index 0000000..d1c0a9b --- /dev/null +++ b/src/api/contingencyManagement/emergencyResources/index.ts @@ -0,0 +1,45 @@ +import request from '/@/utils/request'; + +export function emergencySuppliesApi() { + return { + // 应急物资一览 + getEmergencySuppliesList: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/emergencySupplies/page/list', + method: 'post', + data: params + }); + }, + // 应急物资新增 + addEmergencySupplies: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/emergencySupplies/add', + method: 'post', + data: params + }); + }, + // 应急物资详情 + seeEmergencySupplies: (params: number) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/emergencySupplies/info/${params}`, + method: 'get' + }); + }, + // 应急物资编辑 + editEmergencySupplies: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/emergencySupplies/update`, + method: 'post', + data: params + }); + }, + // 应急物资删除 + deleteEmergencySupplies: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/emergencySupplies/batchDelete`, + method: 'post', + data: params + }); + } + }; +} diff --git a/src/api/contingencyManagement/maintenanceEmergencyMaterials/index.ts b/src/api/contingencyManagement/maintenanceEmergencyMaterials/index.ts new file mode 100644 index 0000000..082041c --- /dev/null +++ b/src/api/contingencyManagement/maintenanceEmergencyMaterials/index.ts @@ -0,0 +1,45 @@ +import request from '/@/utils/request'; + +export function maintenanceEmergencyMaterialsApi() { + return { + //应急物资保养一览 + getMaintenanceEmergencyMaterialsList: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/emergencySuppliesMaintain/page/list', + method: 'post', + data: params + }); + }, + // 应急物资保养新增 + addMaintenanceEmergencyMaterials: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/emergencySuppliesMaintain/add`, + method: 'post', + data: params + }); + }, + // 应急物资保养详情 + seeMaintenanceEmergencyMaterials: (params: number) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/emergencySuppliesMaintain/info/${params}`, + method: 'get' + }); + }, + // 应急物资保养编辑 + editMaintenanceEmergencyMaterials: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/emergencySuppliesMaintain/update`, + method: 'post', + data: params + }); + }, + // 应急物资保养删除 + deleteMaintenanceEmergencyMaterials: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/emergencySuppliesMaintain/batchDelete`, + method: 'post', + data: params + }); + } + }; +} diff --git a/src/api/doublePreventSystem/check/index.ts b/src/api/doublePreventSystem/check/index.ts new file mode 100644 index 0000000..2bf8d00 --- /dev/null +++ b/src/api/doublePreventSystem/check/index.ts @@ -0,0 +1,29 @@ +import request from '/@/utils/request'; + +export function hiddenCheckApi() { + return { + // v1 + getHiddenCheckList: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/prevent/dangerRectify/select/getRectifyOverPage`, + method: 'post', + data: data + }); + }, + // v1 + submitHiddenCheck: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/prevent/dangerRectify/update/reportRectify`, + method: 'post', + data: data + }); + }, + // v1 + getAllHiddenCheckList: () => { + return request({ + url: import.meta.env.VITE_API_URL + `/prevent/device/select/listDevices`, + method: 'post' + }); + } + }; +} diff --git a/src/api/doublePreventSystem/checkUnit/index.ts b/src/api/doublePreventSystem/checkUnit/index.ts new file mode 100644 index 0000000..70a60d9 --- /dev/null +++ b/src/api/doublePreventSystem/checkUnit/index.ts @@ -0,0 +1,44 @@ +import request from '/@/utils/request'; + +export function checkUnitApi() { + return { + // v1 + getCheckUnitList: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/prevent/taskUnit/select/getTaskUnitPage`, + method: 'post', + data: data + }); + }, + // v1 + addCheckUnit: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/prevent/taskUnit/insert/saveTaskUnit`, + method: 'post', + data: data + }); + }, + // v1 + modCheckUnit: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/prevent/taskUnit/update/updateTaskUnit`, + method: 'post', + data: data + }); + }, + // v1 + deleteCheckUnit: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/prevent/taskUnit/delete/deleteTaskUnit`, + method: 'post', + data: data + }); + }, + getAllCheckUnitList: () => { + return request({ + url: import.meta.env.VITE_API_URL + `/prevent/taskUnit/select/listTaskUnit`, + method: 'post' + }); + } + }; +} diff --git a/src/api/doublePreventSystem/productionDevice/index.ts b/src/api/doublePreventSystem/productionDevice/index.ts new file mode 100644 index 0000000..f090b09 --- /dev/null +++ b/src/api/doublePreventSystem/productionDevice/index.ts @@ -0,0 +1,45 @@ +import request from '/@/utils/request'; + +export function productionDeviceApi() { + return { + // v1 + getProductionDeviceList: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/prevent/device/select/getDevicePage`, + method: 'post', + data: data + }); + }, + // v1 + addProductionDevice: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/prevent/device/insert/saveDevice`, + method: 'post', + data: data + }); + }, + // v1 + modProductionDevice: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/prevent/device/update/updateDevice`, + method: 'post', + data: data + }); + }, + // v1 + deleteProductionDevice: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/prevent/device/delete/deleteDevice`, + method: 'post', + data: data + }); + }, + // v1 + getAllProductionDeviceList: () => { + return request({ + url: import.meta.env.VITE_API_URL + `/prevent/device/select/listDevices`, + method: 'post' + }); + } + }; +} diff --git a/src/api/doublePreventSystem/record/index.ts b/src/api/doublePreventSystem/record/index.ts new file mode 100644 index 0000000..38122d7 --- /dev/null +++ b/src/api/doublePreventSystem/record/index.ts @@ -0,0 +1,31 @@ +import request from '/@/utils/request'; + +export function recordApi() { + return { + // v1 + getRecordList: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/prevent/checkTask/select/getTaskPage`, + method: 'post', + data: data + }); + }, + + // v1 + submitRecord: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/prevent/checkTask/update/updateTask`, + method: 'post', + data: data + }); + }, + + getTask: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/prevent/checkTask/update/taskToUser`, + method: 'post', + data: data + }); + } + }; +} diff --git a/src/api/doublePreventSystem/rectify/index.ts b/src/api/doublePreventSystem/rectify/index.ts new file mode 100644 index 0000000..30f1466 --- /dev/null +++ b/src/api/doublePreventSystem/rectify/index.ts @@ -0,0 +1,51 @@ +import request from '/@/utils/request'; + +export function hiddenRectifyApi() { + return { + // v1 + getHiddenRectifyList: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/prevent/dangerRectify/select/getDangerRectifyPage`, + method: 'post', + data: data + }); + }, + // v1 + submitHiddenRectify: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/prevent/dangerRectify/update/applyReport`, + method: 'post', + data: data + }); + }, + // v1 + delayHiddenRectifyTime: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/prevent/dangerRectify/update/timeOutRectify`, + method: 'post', + data: data + }); + }, + // v1 + deleteHiddenRectify: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/prevent/dangerRectify/delete/deleteDangerRectify`, + method: 'post', + data: data + }); + }, + // v1 + getAllHiddenRectifyList: () => { + return request({ + url: import.meta.env.VITE_API_URL + `/prevent/device/select/listDevices`, + method: 'post' + }); + }, + getCodeByTime: (date: string) => { + return request({ + url: import.meta.env.VITE_API_URL + `/prevent/dangerManage/count/byCreateDate?date=${date}`, + method: 'get' + }); + } + }; +} diff --git a/src/api/doublePreventSystem/report/index.ts b/src/api/doublePreventSystem/report/index.ts new file mode 100644 index 0000000..89e12ef --- /dev/null +++ b/src/api/doublePreventSystem/report/index.ts @@ -0,0 +1,38 @@ +import request from '/@/utils/request'; + +export function hiddenReportApi() { + return { + // v1 + getHiddenReportList: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/prevent/dangerManage/select/getDangerManagePage`, + method: 'post', + data: data + }); + }, + // v1 + addHiddenReport: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/prevent/dangerManage/insert/saveDangerManage`, + method: 'post', + data: data + }); + }, + // v1 + modHiddenReport: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/prevent/dangerManage/update/updateDangerManage`, + method: 'post', + data: data + }); + }, + // v1 + deleteHiddenReport: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/prevent/dangerManage/delete/deleteDangerManage`, + method: 'post', + data: data + }); + } + }; +} diff --git a/src/api/doublePreventSystem/riskControlMeasure/index.ts b/src/api/doublePreventSystem/riskControlMeasure/index.ts new file mode 100644 index 0000000..c9d4955 --- /dev/null +++ b/src/api/doublePreventSystem/riskControlMeasure/index.ts @@ -0,0 +1,50 @@ +import request from '/@/utils/request'; + +export function riskControlMeasureApi() { + return { + // v1 + getRiskControlMeasureList: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/prevent/riskControlMeasure/select/getRiskControlMeasurePage`, + method: 'post', + data: data + }); + }, + // v1 + addRiskControlMeasure: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/prevent/riskControlMeasure/insert/saveRiskControlMeasure`, + method: 'post', + data: data + }); + }, + // v1 + modRiskControlMeasure: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/prevent/riskControlMeasure/update/updateRiskControlMeasure`, + method: 'post', + data: data + }); + }, + // v1 + deleteRiskControlMeasure: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/prevent/riskControlMeasure/delete/deleteRiskControlMeasure`, + method: 'post', + data: data + }); + }, + getAllRiskControlMeasureList: () => { + return request({ + url: import.meta.env.VITE_API_URL + `/prevent/riskControlMeasure/select/listControlMeasure`, + method: 'post' + }); + }, + getClassifyData: () => { + return request({ + url: import.meta.env.VITE_API_URL + `/prevent/riskControlMeasure/select/listMeasures`, + method: 'post' + }); + } + }; +} diff --git a/src/api/doublePreventSystem/safetyRiskAnalyseUnit/index.ts b/src/api/doublePreventSystem/safetyRiskAnalyseUnit/index.ts new file mode 100644 index 0000000..58e8d2f --- /dev/null +++ b/src/api/doublePreventSystem/safetyRiskAnalyseUnit/index.ts @@ -0,0 +1,45 @@ +import request from '/@/utils/request'; + +export function safetyRiskAnalyseUnitApi() { + return { + // v1 + getSafetyRiskAnalyseUnitList: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/prevent/riskAnaUnit/select/getRiskUnitPage`, + method: 'post', + data: data + }); + }, + // v1 + addSafetyRiskAnalyseUnit: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/prevent/riskAnaUnit/insert/saveRiskAnaUnit`, + method: 'post', + data: data + }); + }, + // v1 + modSafetyRiskAnalyseUnit: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/prevent/riskAnaUnit/update/updateRiskAnaUnit`, + method: 'post', + data: data + }); + }, + // v1 + deleteSafetyRiskAnalyseUnit: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/prevent/riskAnaUnit/delete/deleteRiskAnaUnit`, + method: 'post', + data: data + }); + }, + // v1 + getAllSafetyRiskAnalyseUnitList: () => { + return request({ + url: import.meta.env.VITE_API_URL + `/prevent/riskEvent/select/listRiskUnits`, + method: 'post' + }); + } + }; +} diff --git a/src/api/doublePreventSystem/safetyRiskEvent/index.ts b/src/api/doublePreventSystem/safetyRiskEvent/index.ts new file mode 100644 index 0000000..4eb648e --- /dev/null +++ b/src/api/doublePreventSystem/safetyRiskEvent/index.ts @@ -0,0 +1,45 @@ +import request from '/@/utils/request'; + +export function safetyRiskEventApi() { + return { + // v1 + getSafetyRiskEventList: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/prevent/riskEvent/select/getRiskEventPage`, + method: 'post', + data: data + }); + }, + // v1 + addSafetyRiskEvent: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/prevent/riskEvent/insert/saveRiskEvent`, + method: 'post', + data: data + }); + }, + // v1 + modSafetyRiskEvent: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/prevent/riskEvent/update/updateRiskEvent`, + method: 'post', + data: data + }); + }, + // v1 + deleteSafetyRiskEvent: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/prevent/riskEvent/delete/deleteRiskEvent`, + method: 'post', + data: data + }); + }, + // v1 + getAllSafetyRiskEventList: () => { + return request({ + url: import.meta.env.VITE_API_URL + `/prevent/riskEvent/select/getListEvents`, + method: 'post' + }); + } + }; +} diff --git a/src/api/doublePreventSystem/work/index.ts b/src/api/doublePreventSystem/work/index.ts new file mode 100644 index 0000000..c4737e4 --- /dev/null +++ b/src/api/doublePreventSystem/work/index.ts @@ -0,0 +1,38 @@ +import request from '/@/utils/request'; + +export function workApi() { + return { + // v1 + getWorkList: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/prevent/checkWork/select/getCheckWorkPage`, + method: 'post', + data: data + }); + }, + // v1 + addWork: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/prevent/checkWork/insert/saveCheckWork`, + method: 'post', + data: data + }); + }, + // v1 + modWork: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/prevent/checkWork/update/updateCheckWork`, + method: 'post', + data: data + }); + }, + // v1 + deleteWork: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/prevent/checkWork/delete/deleteCheckWork`, + method: 'post', + data: data + }); + } + }; +} diff --git a/src/api/facilityManagement/claimReturnRecords/index.ts b/src/api/facilityManagement/claimReturnRecords/index.ts new file mode 100644 index 0000000..58e17b0 --- /dev/null +++ b/src/api/facilityManagement/claimReturnRecords/index.ts @@ -0,0 +1,27 @@ +import request from "/@/utils/request"; + +export function claimReturnRecordsApi() { + return { + getClaimReturnRecords: (data: {}) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/equipment/material/record/page/list`, + method: 'post', + data + }); + }, + returnGoods: (data: {}) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/equipment/material/record/revert`, + method: 'post', + data + }); + }, + refreshReturnAndNoReturn: (data: {}) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/equipment/material/record/queryById`, + method: 'post', + data + }); + }, + } +} diff --git a/src/api/facilityManagement/goodsDetailManage/index.ts b/src/api/facilityManagement/goodsDetailManage/index.ts new file mode 100644 index 0000000..6ca4c36 --- /dev/null +++ b/src/api/facilityManagement/goodsDetailManage/index.ts @@ -0,0 +1,89 @@ +import request from '/@/utils/request'; +export function goodsDetailApi() { + return { + // 设备设施类型管理 查询单条数据 + getGoodsDetailList: (data: {}) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/equipment/smDetail/page/list`, + method: 'post', + data + }); + }, + addGoodsDetail: (data: {}) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/equipment/smDetail/save`, + method: 'post', + data + }); + }, + checkOutBySingle: (data: {}) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/equipment/smDetail/single/delivery`, + method: 'post', + data + }); + }, + checkOutByMore: (data: {}) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/equipment/smDetail/batch/delivery/ids`, + method: 'post', + data + }); + }, + updateGoodsDetail: (data: {}) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/equipment/smDetail/update`, + method: 'post', + data + }); + }, + getGoodsListByLevel: () => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/equipment/safeMaterial/list`, + method: 'post', + }); + }, + checkOutOne: (data: {}) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/equipment/smDetail/single/delivery`, + method: 'post', + data + }); + }, + checkOutMore: (data: {}) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/equipment/smDetail/batch/delivery/ids`, + method: 'post', + data + }); + }, + checkInOne: (data: {}) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/equipment/smDetail/single/receipt`, + method: 'post', + data + }); + }, + checkInMore: (data: {}) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/equipment/smDetail/batch/receipt`, + method: 'post', + data + }); + }, + deleteSingleGoods: (data: {}) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/equipment/smDetail/delete`, + method: 'post', + data + }); + }, + deleteBatchGoods: (data: {}) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/equipment/smDetail/deleteBatch`, + method: 'post', + data + }); + }, + } +} diff --git a/src/api/facilityManagement/index.ts b/src/api/facilityManagement/index.ts new file mode 100644 index 0000000..ffb78be --- /dev/null +++ b/src/api/facilityManagement/index.ts @@ -0,0 +1,104 @@ +import request from '/@/utils/request'; +export function facilityManagementApi() { + return { + // 设备设施类型管理 查询单条数据 + getequipmentTypeMngDetail: (params: any) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/equipmentTypeMng/selectOne/${params}`, + method: 'get' + }); + }, + // 设备设施类型管理 新增或者修改数据 + getequipmentTypeMngAddOrUpdate: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/equipmentTypeMng/addOrUpdate', + method: 'post', + data: params + }); + }, + // 设备设施类型管理 删除 + getequipmentTypeMngDelete: (params: any) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/equipmentTypeMng/delete`, + method: 'post', + data: params + }); + }, + // 设备设施类型管理 查询树状数据 + getequipmentTypeMngTreeData: () => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/equipmentTypeMng/treeData`, + method: 'get' + }); + }, + // 仪器仪表信息、生产设备设施、安全设备设施 查询单条数据 + getequipmentInfoDetail: (params: any) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/equipmentInfo/selectOne/${params}`, + method: 'get' + }); + }, + // 仪器仪表信息、生产设备设施、安全设备设施 新增或者修改数据 + getequipmentInfoAddOrUpdate: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/equipmentInfo/addOrUpdate', + method: 'post', + data: params + }); + }, + // 仪器仪表信息、生产设备设施、安全设备设施 删除 + getequipmentInfoDelete: (params: any) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/equipmentInfo/delete`, + method: 'post', + data: params + }); + }, + // 仪器仪表信息、生产设备设施、安全设备设施 分页查询数据 + getequipmentInfoList: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/equipmentInfo/page/list', + method: 'post', + data: params + }); + }, + // 仪器仪表信息、生产设备设施、安全设备设施 统计 + getequipmentInfoStatistics: () => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/equipmentInfo/statistics`, + method: 'get' + }); + }, + // 重点监管装置/设备 查询单条数据 + getkeypointEquipmentInfoDetail: (params: any) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/keypointEquipmentInfo/selectOne/${params}`, + method: 'get' + }); + }, + // 重点监管装置/设备 新增或者修改数据 + getkeypointEquipmentInfoAddOrUpdate: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/keypointEquipmentInfo/addOrUpdate`, + method: 'post', + data: params + }); + }, + // 重点监管装置/设备 删除 + getkeypointEquipmentInfoDetele: (params: any) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/keypointEquipmentInfo/delete`, + method: 'post', + data: params + }); + }, + // 重点监管装置/设备 分页查询数据 + getkeypointEquipmentInfoAddOrList: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/keypointEquipmentInfo/page/list`, + method: 'post', + data: params + }); + } + }; +} diff --git a/src/api/facilityManagement/safetyGoodsAndEquipment/index.ts b/src/api/facilityManagement/safetyGoodsAndEquipment/index.ts new file mode 100644 index 0000000..d8daf35 --- /dev/null +++ b/src/api/facilityManagement/safetyGoodsAndEquipment/index.ts @@ -0,0 +1,82 @@ +import request from '/@/utils/request'; +export function goodsAndEquipmentApi() { + return { + // 设备设施类型管理 查询单条数据 + getGoodsEquipmentData: (data: {}) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/equipment/safeMaterial/page/list`, + method: 'post', + data + }); + }, + getAllSafetyEquipment: () => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/equipment/classify/list`, + method: 'post', + }); + }, + getAllSafetyEquipmentByPage: (data: {}) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/equipment/classify/page/list`, + method: 'post', + data + }); + }, + addGoodsEquipment: (data: {}) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/equipment/safeMaterial/save`, + method: 'post', + data + }); + }, + updateGoodsEquipment: (data: {}) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/equipment/safeMaterial/update`, + method: 'post', + data + }); + }, + deleteGoodsEquipment: (data: {}) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/equipment/safeMaterial/delete`, + method: 'post', + data + }); + }, + addGoodsClassify: (data: {}) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/equipment/classify/save`, + method: 'post', + data + }); + }, + updateGoodsClassify: (data: {}) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/equipment/classify/update`, + method: 'post', + data + }); + }, + deleteGoodsClassify: (data: {}) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/equipment/classify/delete`, + method: 'post', + data + }); + }, + batchInStorageGoods: (data: {}) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/equipment/smDetail/saveBatch`, + method: 'post', + data + }); + }, + batchOutStorageGoods: (data: {}) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/equipment/smDetail/batch/delivery/random`, + method: 'post', + data + }); + }, + } +} diff --git a/src/api/goalManagement/index.ts b/src/api/goalManagement/index.ts new file mode 100644 index 0000000..2b9409f --- /dev/null +++ b/src/api/goalManagement/index.ts @@ -0,0 +1,412 @@ +import request from '/@/utils/request'; +export function goalManagementApi() { + return { + // 目标设置、目标指标分解列表 + getTargetMngList: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/targetMng/page/list', + method: 'post', + data: params + }); + }, + // 目标设置详情 + getTargetMngDetail: (params: any) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/targetMng/selectOne/${params}`, + method: 'get' + }); + }, + // 目标设置新增或者修改数据 + getTargetMngAddOrupdata: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/targetMng/addOrUpdate', + method: 'post', + data: params + }); + }, + // 目标设置删除 + getTargetMngDelete: (params: any) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/targetMng/delete`, + method: 'post', + data: params + }); + }, + // 目标指标分解-新增或者修改数据 + gettargetDivideDetail: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/targetDivideDetail/addOrUpdate', + method: 'post', + data: params + }); + }, + // 统计 + getEquipmentInfo: () => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/equipmentInfo/statistics', + method: 'get' + }); + }, + // 目标责任书 分页查询数据 + gettargetDutyfileInfoList: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/targetDutyfileInfo/page/list', + method: 'post', + data: params + }); + }, + // 目标责任书 查询单条数据 + gettargetDutyfileInfoDetail: (params: number) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/targetDutyfileInfo/selectOne/${params}`, + method: 'get' + }); + }, + // 目标责任书 新增或者修改数据 + gettargetDutyfileInfoAddorUpdata: (params: any) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/targetDutyfileInfo/addOrUpdate`, + method: 'post', + data: params + }); + }, + // 目标责任书 删除 + gettargetDutyfileInfoDelete: (params: any) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/targetDutyfileInfo/delete`, + method: 'post', + data: params + }); + }, + // 奖惩标准设定 分页查询数据 + getrewardPunishmentStandardList: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/rewardPunishmentStandard/page/list', + method: 'post', + data: params + }); + }, + // 奖惩标准设定 查询单条数据 + getrewardPunishmentStandardDetail: (params: any) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/rewardPunishmentStandard/selectOne/${params}`, + method: 'get' + }); + }, + // 奖惩标准设定 新增或者修改数据 + getrewardPunishmentStandardaddOrUpdate: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/rewardPunishmentStandard/addOrUpdate', + method: 'post', + data: params + }); + }, + // 奖惩标准设定 删除 + getrewardPunishmentStandardDelete: (params: any) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/rewardPunishmentStandard/delete`, + method: 'post', + data: params + }); + }, + // 奖惩记录 分页查询数据 + getrewardPunishmentList: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/rewardPunishmentDetail/page/list', + method: 'post', + data: params + }); + }, + // 奖惩记录 查询单条数据 + getrewardPunishmentDetail: (params: any) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/rewardPunishmentDetail/selectOne/${params}`, + method: 'get' + }); + }, + // 奖惩记录 新增或者修改数据 + getrewardPunishmentAddOrUpdate: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/rewardPunishmentDetail/addOrUpdate`, + method: 'post', + data: params + }); + }, + // 奖惩记录 删除 + getrewardPunishmentDelete: (params: any) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/rewardPunishmentDetail/delete`, + method: 'post', + data: params + }); + }, + // 绩效考核管理 安全考核管理 分页查询数据 + getexamineMngList: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/examineMng/page/list', + method: 'post', + data: params + }); + }, + // 绩效考核管理 安全考核管理 查询单条数据 + getexamineMngDetail: (params: any) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/examineMng/selectOne/${params}`, + method: 'get' + }); + }, + // 绩效考核管理 安全考核管理 新增或者修改数据 + getexamineMngAddOrUpdate: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/examineMng/addOrUpdate`, + method: 'post', + data: params + }); + }, + // 绩效考核管理 安全考核管理 删除 + getexamineMngDelete: (params: any) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/examineMng/delete`, + method: 'post', + data: params + }); + }, + // 绩效考核管理 考核标准设定 分页查询数据 + getexamineTemplateList: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/examineTemplate/page/list', + method: 'post', + data: params + }); + }, + // 绩效考核管理 考核标准设定 查询单条数据 + getexamineTemplateDetail: (params: any) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/examineTemplate/selectOne/${params}`, + method: 'get' + }); + }, + // 绩效考核管理 考核标准设定 新增或者修改数据 + getexamineTemplateAddOrUpdate: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/examineTemplate/addOrUpdate`, + method: 'post', + data: params + }); + }, + // 绩效考核管理 考核标准设定 删除 + getexamineTemplateDelete: (params: any) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/examineTemplate/delete`, + method: 'post', + data: params + }); + }, + // 目标汇总 分页查询数据 + gettargetDutySummaryList: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/targetDutySummary/page/list', + method: 'post', + data: params + }); + }, + // 目标汇总 查询单条数据 + gettargetDutySummaryDetail: (params: any) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/targetDutySummary/selectOne/${params}`, + method: 'get' + }); + }, + // 目标汇总 新增或者修改数据 + gettargetDutySummaryAddOrUpdate: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/targetDutySummary/addOrUpdate`, + method: 'post', + data: params + }); + }, + // 目标汇总 删除 + gettargetDutySummaryDelete: (params: any) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/targetDutySummary/delete?ids=${params}`, + method: 'get' + }); + }, + //安全目标考核 列表 + gettargetExamineList: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/targetMng/page/list', + method: 'post', + data: params + }); + }, + // 安全目标考核 查询单条数据 + gettargetExamineDetail: (params: any) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/targetExamine/selectOne/${params}`, + method: 'get' + }); + }, + // 安全目标考核 新增或者修改数据 + gettargetExamineAddOrUpdate: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/targetExamine/addOrUpdate', + method: 'post', + data: params + }); + }, + // 目标检查上报 分页查询数据 + getworkApproveList: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/targetMng/checkAndSubimt/list', + method: 'post', + data: params + }); + }, + // 目标检查上报 查看审批流程 + getworkApproveListCode: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/targetDutyWorkApprove/page/list', + method: 'post', + data: params + }); + }, + // 目标检查上报 分页查询检查记录 + getworkApproveListCheckData: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/targetDutyWorkApprove/page/listCheckData', + method: 'post', + data: params + }); + }, + // 目标检查上报 查询单条数据 + getworkApproveDetail: (params: any) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/targetDutyWorkApprove/selectOne/${params}`, + method: 'get' + }); + }, + + // 目标检查上报 新增数据 + getworkApproveAdd: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/targetDutyWorkApprove/add', + method: 'post', + data: params + }); + }, + // 目标检查上报 新增数据 + getworkApproveUpdata: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/targetDutyWorkApprove/update', + method: 'post', + data: params + }); + }, + // 目标检查上报 删除 + getworkApproveDelete: (params: any) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/targetDutyWorkApprove/delete', + method: 'post', + data: params + }); + }, + // 部门树 + getTreedepartment: () => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/department/list', + method: 'post' + }); + }, + // 人员 + getManName: (params: any) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/account/dep/list?depId=${params}`, + method: 'get' + }); + }, + beforeUploadFile(fileName1: string, fileName2: string) { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/minio/file/presign?prefixName=' + fileName1 + '&suffixName=' + fileName2, + method: 'get' + }); + }, + searchFile(fileName: string) { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/minio/file/view?obj=' + fileName, + method: 'get' + }); + }, + // 应急统计 + emergencyStat(params: object) { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/emergencyCount/emergencyDrillExecute/count`, + method: 'post', + data: params + }); + }, + // 目标分类 分页查询数据 + gettargetClassList(params: object) { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/targetType/page/list', + method: 'post', + data: params + }); + }, + // 目标分类 查询单条数据 + gettargetClassDetail(params: any) { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/targetType/selectOne/${params}`, + method: 'get' + }); + }, + // 目标分类 新增或者修改数据 + gettargetClassAdd(params: object) { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/targetType/addOrUpdate', + method: 'post', + data: params + }); + }, + // 目标分类 删除 + gettargetClassDelete(params: any) { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/targetType/delete', + method: 'post', + data: params + }); + }, + // 目标分类 查询所有数据All + gettargetClassAll(params: any) { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/targetType/page/listAll', + method: 'post', + data: params + }); + }, + // 统计 查询应急物资 + emergencySuppliesCount(params: any) { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/emergencyCount/emergencySupplies/count', + method: 'post', + data: params + }); + }, + // 统计 事故快报 + accidentReportCount(params: any) { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/accidentCount/accidentReport/count', + method: 'post', + data: params + }); + }, + // 目标 统计 + gettargetstatistics(params: any) { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/targetMng/statistics?targetType=${params}`, + method: 'get' + // data:params + }); + } + }; +} diff --git a/src/api/intellectInspectSystem/RFID/index.ts b/src/api/intellectInspectSystem/RFID/index.ts new file mode 100644 index 0000000..534ffda --- /dev/null +++ b/src/api/intellectInspectSystem/RFID/index.ts @@ -0,0 +1,64 @@ +import request from '/@/utils/request'; + +export function RFIDApi() { + return { + // v1 + getRFIDList: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/SafeCheckRfid/select/listRfidByPage`, + method: 'post', + data: data + }); + }, + // v1 + addRFID: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/SafeCheckRfid/insert/saveRfid`, + method: 'post', + data: data + }); + }, + // v1 + modRFID: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/SafeCheckRfid/update/updateRfidById`, + method: 'post', + data: data + }); + }, + // v1 + deleteRFID: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/SafeCheckRfid/delete/deleteRfidById`, + method: 'post', + data: data + }); + }, + // v1 + getAllRFIDList: () => { + return request({ + url: import.meta.env.VITE_API_URL + `/SafeCheckRfid/select/listRfidName`, + method: 'get' + }); + }, + + // 获取图片上传地址 + getUploadUrl: (name: string) => { + return request({ + url: import.meta.env.VITE_API_URL + `/SafeCheck/minio/file/presign`, + method: 'post', + data: { prefixName: name.split('.')[0], suffixName: name.split('.')[1] } + }); + }, + uploadFile: (path: string, file: any) => { + return request({ + headers: { + contentType: 'application/json;charset=UTF-8' + }, + url: path, + method: 'put', + data: file + }); + } + }; +} diff --git a/src/api/intellectInspectSystem/facilityAreaManage/index.ts b/src/api/intellectInspectSystem/facilityAreaManage/index.ts new file mode 100644 index 0000000..3c71309 --- /dev/null +++ b/src/api/intellectInspectSystem/facilityAreaManage/index.ts @@ -0,0 +1,60 @@ +import request from '/@/utils/request'; + +export function facilityAreaApi() { + return { + // v1 + getFacilityAreaList: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/safeCheckRegion/select/listRegionByPage`, + method: 'post', + data: data + }); + }, + // v1 + getFacilityAreaById: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/safeCheckRegion/select/getRegionById`, + method: 'post', + data: data + }); + }, + // v1 + addFacilityArea: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/safeCheckRegion/insert/saveRegion`, + method: 'post', + data: data + }); + }, + // v1 + modFacilityArea: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/safeCheckRegion/update/updateRegionById`, + method: 'post', + data: data + }); + }, + // v1 + deleteFacilityArea: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/safeCheckRegion/delete/deleteRegionById`, + method: 'post', + data: data + }); + }, + // v1 + getAllFacilityAreaList: () => { + return request({ + url: import.meta.env.VITE_API_URL + `/safeCheckRegion/select/listRegionName`, + method: 'get' + }); + }, + // v1 + getFacilityAreaType: () => { + return request({ + url: import.meta.env.VITE_API_URL + `/SafeCheckRegionType/select/listRegionType`, + method: 'get' + }); + } + }; +} diff --git a/src/api/intellectInspectSystem/inspectPointManage/index.ts b/src/api/intellectInspectSystem/inspectPointManage/index.ts new file mode 100644 index 0000000..500e718 --- /dev/null +++ b/src/api/intellectInspectSystem/inspectPointManage/index.ts @@ -0,0 +1,59 @@ +import request from '/@/utils/request'; + +export function inspectPointApi() { + return { + // v1 + getInspectPointList: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/safeCheckPoint/select/listPointByPage`, + method: 'post', + data: data + }); + }, + // v1 + getInspectPointById: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/safeCheckPoint/select/getPointById`, + method: 'post', + data: data + }); + }, + // v1 + addInspectPoint: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/safeCheckPoint/insert/savePoint`, + method: 'post', + data: data + }); + }, + // v1 + modInspectPoint: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/safeCheckPoint/update/updatePointById`, + method: 'post', + data: data + }); + }, + // v1 + deleteInspectPoint: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/safeCheckPoint/delete/deletePointById`, + method: 'post', + data: data + }); + }, + // v1 + getAllInspectPointList: () => { + return request({ + url: import.meta.env.VITE_API_URL + `/safeCheckRegion/select/listRegionName`, + method: 'get' + }); + }, + getInspectPointAll: () => { + return request({ + url: import.meta.env.VITE_API_URL + `/safeCheckPoint/select/getPointRegionRfidId`, + method: 'post' + }); + } + }; +} diff --git a/src/api/intellectInspectSystem/inspectRecord/index.ts b/src/api/intellectInspectSystem/inspectRecord/index.ts new file mode 100644 index 0000000..a7d17bb --- /dev/null +++ b/src/api/intellectInspectSystem/inspectRecord/index.ts @@ -0,0 +1,43 @@ +import request from '/@/utils/request'; + +export function inspectRecordApi() { + return { + // v1 + getInspectRecordList: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/SafeCheckTask/select/listTaskByPage`, + method: 'post', + data: data + }); + }, + // v1 + getInspectRecordById: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/SafeCheckTask/select/listTaskMainAndQuota`, + method: 'post', + data: data + }); + }, + getInspectRecordByIndex: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/SafeCheckTask/select/listTaskByPageAndStatusAndTime`, + method: 'post', + data: data + }); + }, + getInspectRecordSum: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/SafeCheckTask/select/listTaskQuotaGbRegionGbQuotaGbPoint`, + method: 'post', + data: data + }); + }, + + getDayRecord: () => { + return request({ + url: import.meta.env.VITE_API_URL + `/SafeCheckTask/select/listTaskByNoCheckTaskAndAbnormalTask`, + method: 'get', + }); + } + }; +} diff --git a/src/api/intellectInspectSystem/inspectTargetManage/index.ts b/src/api/intellectInspectSystem/inspectTargetManage/index.ts new file mode 100644 index 0000000..cec17ec --- /dev/null +++ b/src/api/intellectInspectSystem/inspectTargetManage/index.ts @@ -0,0 +1,59 @@ +import request from '/@/utils/request'; + +export function inspectTargetApi() { + return { + // v1 + getInspectTargetList: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/safeCheckQuota/select/listQuotaByPage`, + method: 'post', + data: data + }); + }, + // v1 + getInspectTargetById: (id: number) => { + return request({ + url: import.meta.env.VITE_API_URL + `/safeCheckQuota/select/getQuotaById?id=${id}`, + method: 'get' + }); + }, + // v1 + addInspectTarget: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/safeCheckQuota/insert/saveQuota`, + method: 'post', + data: data + }); + }, + // v1 + modInspectTarget: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/safeCheckQuota/update/updateQuotaById`, + method: 'post', + data: data + }); + }, + // v1 + deleteInspectTarget: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/safeCheckQuota/delete/deleteQuotaById`, + method: 'post', + data: data + }); + }, + // v1 + getAllInspectTargetList: () => { + return request({ + url: import.meta.env.VITE_API_URL + `/prevent/device/select/listDevices`, + method: 'post' + }); + }, + // v1 + getQuotaTypeList: () => { + return request({ + url: import.meta.env.VITE_API_URL + `/safeCheckQuotaType/select/listQuotaType`, + method: 'get' + }); + } + }; +} diff --git a/src/api/intellectInspectSystem/inspectTask/index.ts b/src/api/intellectInspectSystem/inspectTask/index.ts new file mode 100644 index 0000000..683bdd8 --- /dev/null +++ b/src/api/intellectInspectSystem/inspectTask/index.ts @@ -0,0 +1,83 @@ +import request from '/@/utils/request'; + +export function inspectTaskApi() { + return { + // v1 + getInspectTaskList: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/SafeCheckTaskUnit/select/listTaskUnitByPage`, + method: 'post', + data: data + }); + }, + // v1 + getInspectTaskById: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/SafeCheckTaskUnit/select/getTaskUnitById`, + method: 'post', + data: data + }); + }, + // v1 + addInspectTask: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/SafeCheckTaskUnit/insert/saveTaskUnit`, + method: 'post', + data: data + }); + }, + // v1 + modInspectTask: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/SafeCheckTaskUnit/update/updateTaskUnitMainById`, + method: 'post', + data: data + }); + }, + // v1 + deleteInspectTask: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/SafeCheckTaskUnit/delete/deleteTaskUnit`, + method: 'post', + data: data + }); + }, + // v1 + addChainOfInspectTask: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/SafeCheckTaskUnit/insert/saveTaskUnitPoint`, + method: 'post', + data: data + }); + }, + // v1 + modChainOfInspectTask: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/SafeCheckTaskUnit/update/updateTaskUnitPointById`, + method: 'post', + data: data + }); + }, + // v1 + deleteChainOfInspectTask: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/SafeCheckTaskUnit/delete/deleteTaskUnitPoint`, + method: 'post', + data: data + }); + }, + getQuotaList: () => { + return request({ + url: import.meta.env.VITE_API_URL + `/safeCheckQuotaType/select/listQuotaType`, + method: 'get' + }); + }, + openOrCloseInspectTask: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/SafeCheckTaskUnit/update/updateTaskUnitStatusById`, + method: 'post', + data: data + }); + } + }; +} diff --git a/src/api/intelligentLine/index.ts b/src/api/intelligentLine/index.ts new file mode 100644 index 0000000..d79e528 --- /dev/null +++ b/src/api/intelligentLine/index.ts @@ -0,0 +1,22 @@ +import request from '/@/utils/request'; + +export function lineApi() { + return { + // 分页获取休息日列表 + getLine: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/SafeCheckSmartScreen/select/getSmartScreenDataByTaskId`, + method: 'post', + data: data + }); + }, + + // 获取Url + getUrl: () => { + return request({ + url: import.meta.env.VITE_API_URL_SOCKET + `/ws/namesrv/get/one?srv=safeplatform-websocket`, + method: 'get' + }); + } + }; +} diff --git a/src/api/login/index.ts b/src/api/login/index.ts new file mode 100644 index 0000000..61d862f --- /dev/null +++ b/src/api/login/index.ts @@ -0,0 +1,34 @@ +import request from '/@/utils/request'; + +/** + * 登录api接口集合 + * @method signIn 用户登录 + * @method signOut 用户退出登录 + */ +export function useLoginApi() { + return { + // v1 + signIn: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL + '/auth/login', + method: 'post', + data: params + }); + }, + // v1 + signOut: () => { + return request({ + url: import.meta.env.VITE_API_URL + '/auth/logout', + method: 'post' + }); + }, + // 更改密码 + changeCode: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL + '/account/pwd/forget', + method: 'post', + data: params + }); + }, + }; +} diff --git a/src/api/specialWorkSystem/approveBasic/index.ts b/src/api/specialWorkSystem/approveBasic/index.ts new file mode 100644 index 0000000..15b3ba4 --- /dev/null +++ b/src/api/specialWorkSystem/approveBasic/index.ts @@ -0,0 +1,46 @@ +import request from '/@/utils/request'; + +export function approveBasicApi() { + return { + // v1 + getApproveBasicList: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/work/ruleItemStand/page/list`, + method: 'post', + data: data + }); + }, + // v1 + addApproveBasic: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/work/ruleItemStand/save`, + method: 'post', + data: data + }); + }, + // v1 + modApproveBasic: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/work/ruleItemStand/update`, + method: 'post', + data: data + }); + }, + // v1 + deleteApproveBasic: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/work/ruleItemStand/delete`, + method: 'post', + data: data + }); + }, + // v1 + getAllApproveBasicList: (data: {}) => { + return request({ + url: import.meta.env.VITE_API_URL + `/work/ruleItemStand/list`, + method: 'post', + data + }); + } + }; +} diff --git a/src/api/specialWorkSystem/approveRule/index.ts b/src/api/specialWorkSystem/approveRule/index.ts new file mode 100644 index 0000000..a95e65d --- /dev/null +++ b/src/api/specialWorkSystem/approveRule/index.ts @@ -0,0 +1,46 @@ +import request from '/@/utils/request'; + +export function approveRuleApi() { + return { + // v1 + getApproveRuleList: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/rule/listByPage`, + method: 'post', + data: data + }); + }, + // v1 + addApproveRule: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/rule/save`, + method: 'post', + data: data + }); + }, + // v1 + modApproveRule: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/rule/update`, + method: 'post', + data: data + }); + }, + // v1 + deleteApproveRule: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/rule/del`, + method: 'post', + data: data + }); + }, + // v1 + getAllApproveRuleList: (data: {}) => { + return request({ + url: import.meta.env.VITE_API_URL + `/prevent/device/select/listDevices`, + method: 'post', + data + }); + } + }; +} diff --git a/src/api/specialWorkSystem/material/index.ts b/src/api/specialWorkSystem/material/index.ts new file mode 100644 index 0000000..5133881 --- /dev/null +++ b/src/api/specialWorkSystem/material/index.ts @@ -0,0 +1,50 @@ +import request from '/@/utils/request'; + +export function materialApi() { + return { + + //物资管理分页列表 + getRecordPage: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/specialWork/material/page/list`, + method: 'post', + data: data + }); + }, + + //物资列表 + getRecordList: () => { + return request({ + url: import.meta.env.VITE_API_URL + `/specialWork/material/equipment/materialClassify`, + method: 'post' + }); + }, + + // 新增 + addRecord: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/specialWork/material/save`, + method: 'post', + data: data + }); + }, + + // 修改 + updateRecord: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/specialWork/material/update`, + method: 'post', + data: data + }); + }, + + // 删除 + deleteRecord: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/specialWork/material/delete`, + method: 'post', + data: data + }); + } + }; +} diff --git a/src/api/specialWorkSystem/safetyAction/index.ts b/src/api/specialWorkSystem/safetyAction/index.ts new file mode 100644 index 0000000..13f945a --- /dev/null +++ b/src/api/specialWorkSystem/safetyAction/index.ts @@ -0,0 +1,46 @@ +import request from '/@/utils/request'; + +export function safetyActionApi() { + return { + // v1 + getSafetyActionList: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/rule/measure/page/list`, + method: 'post', + data: data + }); + }, + // v1 + addSafetyAction: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/rule/measure/save`, + method: 'post', + data: data + }); + }, + // v1 + modSafetyAction: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/rule/measure/mod`, + method: 'post', + data: data + }); + }, + // v1 + deleteSafetyAction: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/rule/measure/delete`, + method: 'post', + data: data + }); + }, + // v1 + getAllSafetyActionList: (data: {}) => { + return request({ + url: import.meta.env.VITE_API_URL + `/rule/measure/list`, + method: 'post', + data: data + }); + } + }; +} diff --git a/src/api/specialWorkSystem/workApply/index.ts b/src/api/specialWorkSystem/workApply/index.ts new file mode 100644 index 0000000..6258f0e --- /dev/null +++ b/src/api/specialWorkSystem/workApply/index.ts @@ -0,0 +1,190 @@ +import request from '/@/utils/request'; + +export function workApplyApi() { + return { + // 分页获取申请列表 + getApplyListPage: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/work/apply/applying/page/list`, + method: 'post', + data: data + }); + }, + + // 所有记录列表 + getApplyList: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/work/apply/all/page/list`, + method: 'post', + data: data + }); + }, + + // 分页获取申请列表 + getAllUsers: () => { + return request({ + url: import.meta.env.VITE_API_URL + `/account/list`, + method: 'get' + }); + }, + + // 导出打印接口 + postPrinting: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/work/apply/printing`, + method: 'post', + data: data, + responseType: 'blob', + headers:{'Content-Type': 'application/json'} + }); + }, + + + // 动火申请 + postFireApply: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/work/apply/hot`, + method: 'post', + data: data + }); + }, + + // 受限空间申请 + postSpaceApply: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/work/apply/confinedspace`, + method: 'post', + data: data + }); + }, + + // 吊装申请 + postHoistApply: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/work/apply/hoisting`, + method: 'post', + data: data + }); + }, + + // 动土申请 + postGroundApply: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/work/apply/groundBreaking`, + method: 'post', + data: data + }); + }, + + // 断路申请 + postBrokenApply: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/work/apply/brokenCircuit`, + method: 'post', + data: data + }); + }, + + // 高处申请 + postHeightApply: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/work/apply/height`, + method: 'post', + data: data + }); + }, + + // 临时用电申请 + postPowerApply: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/work/apply/temporaryPower`, + method: 'post', + data: data + }); + }, + + // 盲板申请 + postPlateApply: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/work/apply/blindPlatePlugging`, + method: 'post', + data: data + }); + }, + + // 取消申请 + cancelApply: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/work/apply/cancel`, + method: 'post', + data: data + }); + }, + + // 查询进度 + getStatus: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/work/apply/applicant/approved/view`, + method: 'post', + data: data + }); + }, + + // 查询所有进度 + getAllStatus: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/work/apply/others/view`, + method: 'post', + data: data + }); + }, + + // 获取图片上传路径 + getUploadUrl: (name: string) => { + return request({ + url: import.meta.env.VITE_API_URL + `/specialWork/file/getPresignUrl`, + method: 'post', + data: { prefixName: name.split('.')[0], suffixName: name.split('.')[1] } + }); + }, + + // 上传图片 + uploadFile: (path: string, file: any) => { + return request({ + headers: { + contentType: 'application/json;charset=UTF-8' + }, + url: path, + method: 'put', + data: file + }); + }, + + // 删除图片 + deleteFile: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/specialWork/file/deleteFile`, + method: 'post', + data: data + }); + }, + + // 获取物资配置数据 + getMaterial: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/specialWork/material/queryByWorkTypeOrLevel`, + method: 'post', + data: data + }); + }, + + // 根据物资配置id和领取人获取领取情况 + getMaterialDetail: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/specialWork/material/receive`, + method: 'post', + data: data + }); + } + }; +} diff --git a/src/api/specialWorkSystem/workApproval/index.ts b/src/api/specialWorkSystem/workApproval/index.ts new file mode 100644 index 0000000..2365cee --- /dev/null +++ b/src/api/specialWorkSystem/workApproval/index.ts @@ -0,0 +1,41 @@ +import request from '/@/utils/request'; + +export function workApprovalApi() { + return { + // 分页获取审批列表 + getApprovalListPage: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/work/apply/pending/page/list`, + method: 'post', + data: data + }); + }, + + // 获取当前层级审批数据 + getApprovalData: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/work/approval/pending/data`, + method: 'post', + data: data + }); + }, + + // 获取当前层级审批进度 + getApprovalStatus: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/work/apply/approver/approved/view`, + method: 'post', + data: data + }); + }, + + // 终止当前审批进度 + postAbord: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/work/apply/abord`, + method: 'post', + data: data + }); + } + }; +} diff --git a/src/api/specialWorkSystem/workPlan/workAppoint/index.ts b/src/api/specialWorkSystem/workPlan/workAppoint/index.ts new file mode 100644 index 0000000..9d44e51 --- /dev/null +++ b/src/api/specialWorkSystem/workPlan/workAppoint/index.ts @@ -0,0 +1,50 @@ +import request from '/@/utils/request'; + +export function workAppointApi() { + return { + // 分页获取列表 + getAppointListPage: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/specialWork/appointment/listAll`, + method: 'post', + data: data + }); + }, + + // 新增列表 + addRecord: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/specialWork/appointment/save`, + method: 'post', + data: data + }); + }, + + //修改列表 + editRecord: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/specialWork/appointment/update`, + method: 'post', + data: data + }); + }, + + //删除列表 + deleteRecord: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/specialWork/appointment/delete`, + method: 'post', + data: data + }); + }, + + //获取各部门各作业的数量 + getAllRecords: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/specialWork/appointment/statistics`, + method: 'post', + data: data + }); + } + }; +} diff --git a/src/api/specialWorkSystem/workPlan/workReservation/index.ts b/src/api/specialWorkSystem/workPlan/workReservation/index.ts new file mode 100644 index 0000000..d432b75 --- /dev/null +++ b/src/api/specialWorkSystem/workPlan/workReservation/index.ts @@ -0,0 +1,41 @@ +import request from '/@/utils/request'; + +export function workReserveApi() { + return { + // 分页获取列表 + getReserveListPage: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/specialWork/appointment/listByDep`, + method: 'post', + data: data + }); + }, + + // 新增列表 + addRecord: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/specialWork/appointment/save`, + method: 'post', + data: data + }); + }, + + //修改列表 + editRecord: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/specialWork/appointment/update`, + method: 'post', + data: data + }); + }, + + //删除列表 + deleteRecord: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/specialWork/appointment/delete`, + method: 'post', + data: data + }); + } + }; +} diff --git a/src/api/specialWorkSystem/workProcess/index.ts b/src/api/specialWorkSystem/workProcess/index.ts new file mode 100644 index 0000000..0cd1ff0 --- /dev/null +++ b/src/api/specialWorkSystem/workProcess/index.ts @@ -0,0 +1,59 @@ +import request from '/@/utils/request'; + +export function workProcessApi() { + return { + // 分页获取检测列表 + getDetectionListPage: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/work/process/detection/page/list`, + method: 'post', + data: data + }); + }, + + // 分页获取检查列表 + getCheckListPage: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/work/process/check/page/list`, + method: 'post', + data: data + }); + }, + + // 检测上报 + postDetectionReport: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/work/process/detection/report`, + method: 'post', + data: data + }); + }, + + // 检查上报 + postCheckReport: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/work/process/check/report`, + method: 'post', + data: data + }); + }, + + // 获取可上报作业列表 + postReportList: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/work/process/workApply/list`, + method: 'post', + data: data + }); + }, + + // 获取预警记录 + postAlertList: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/work/process/warning/page/list`, + method: 'post', + data: data + }); + }, + }; +} diff --git a/src/api/systemManage/appVersion/index.ts b/src/api/systemManage/appVersion/index.ts new file mode 100644 index 0000000..915bdee --- /dev/null +++ b/src/api/systemManage/appVersion/index.ts @@ -0,0 +1,59 @@ +import request from '/@/utils/request'; + +export function appVersionApi() { + return { + + //app版本分页列表 + getRecordPage: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/appVersion/page/list`, + method: 'post', + data: data + }); + }, + + //获取最新版本 + getRecordByNew: () => { + return request({ + url: import.meta.env.VITE_API_URL + `/appVersion/lastest-release`, + method: 'get' + }); + }, + + // app版本新增 + addRecord: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/appVersion/add`, + method: 'post', + data: data + }); + }, + + // app版本修改 + updateRecord: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/appVersion/mod`, + method: 'post', + data: data + }); + }, + + // app版本删除 + deleteRecord: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/appVersion/del`, + method: 'post', + data: data + }); + }, + + // 获取上传路径 + getUploadUrl: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/appVersion/presign`, + method: 'post', + data: data + }); + }, + }; +} diff --git a/src/api/systemManage/basicDateManage/personShiftManage/holidayTime/index.ts b/src/api/systemManage/basicDateManage/personShiftManage/holidayTime/index.ts new file mode 100644 index 0000000..99ee915 --- /dev/null +++ b/src/api/systemManage/basicDateManage/personShiftManage/holidayTime/index.ts @@ -0,0 +1,50 @@ +import request from '/@/utils/request'; + +export function holidayTimeApi() { + return { + // 分页获取休息日列表 + getAllBreakTimeRuleByPage: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/breakTime/getAllBreakTimeRuleByPage`, + method: 'post', + data: data + }); + }, + + // 新增休息日 + addBreakTime: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/breakTime/addBreakTimeRule`, + method: 'post', + data: data + }); + }, + + // 修改休息日 + updateBreakTime: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/breakTime/updateBreakTimeRule`, + method: 'post', + data: data + }); + }, + + // 删除休息日 + deleteBreakTime: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/breakTime/deleteBreakTimeRule`, + method: 'post', + data: data + }); + }, + + // 删除休息日 + deleteBatch: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/breakTime/deleteBatchBreakTimeRule`, + method: 'post', + data: data + }); + } + }; +} diff --git a/src/api/systemManage/basicDateManage/personShiftManage/holidayTimeGroup/index.ts b/src/api/systemManage/basicDateManage/personShiftManage/holidayTimeGroup/index.ts new file mode 100644 index 0000000..751c76e --- /dev/null +++ b/src/api/systemManage/basicDateManage/personShiftManage/holidayTimeGroup/index.ts @@ -0,0 +1,58 @@ +import request from '/@/utils/request'; + +export function holidayGroupApi() { + return { + //休息时间组分页列表 + getRecordPage: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/breakTime/getAllBreakTimeGroupByPage`, + method: 'post', + data: data + }); + }, + + // 休息时间组新增 + addRecord: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/breakTime/addBreakTimeGroup`, + method: 'post', + data: data + }); + }, + + // 休息时间组修改 + updateRecord: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/breakTime/updateBreakTimeGroup`, + method: 'post', + data: data + }); + }, + + // 休息时间组删除 + deleteRecord: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/breakTime/deleteBreakTimeGroup`, + method: 'post', + data: data + }); + }, + + // 休息时间组批量删除 + deletBatchRecord: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/breakTime/deleteBatchBreakTimeGroup`, + method: 'post', + data: data + }); + }, + + //休息时间列表 + getAllBreak: () => { + return request({ + url: import.meta.env.VITE_API_URL + `/breakTime/getAllBreakTimeRule`, + method: 'get' + }); + } + }; +} diff --git a/src/api/systemManage/basicDateManage/personShiftManage/teamManage/index.ts b/src/api/systemManage/basicDateManage/personShiftManage/teamManage/index.ts new file mode 100644 index 0000000..d378691 --- /dev/null +++ b/src/api/systemManage/basicDateManage/personShiftManage/teamManage/index.ts @@ -0,0 +1,94 @@ +import request from '/@/utils/request'; + +export function teamManageApi() { + return { + //班组分页列表 + getRecordPage: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/schedule/group/page/list`, + method: 'post', + data: data + }); + }, + + //班组列表 + getRecord: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/schedule/group/list`, + method: 'post', + data: data + }); + }, + + //班组-班组成员分页列表 + getAllRecordPage: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/schedule/group/member/page/list`, + method: 'post', + data: data + }); + }, + + //所有部门列表 + getAllDepartment: () => { + return request({ + url: import.meta.env.VITE_API_URL + `/department/list`, + method: 'post' + }); + }, + + //用户-部门所有用户 + getAllMember: (data: number) => { + return request({ + url: import.meta.env.VITE_API_URL + `/account/dep/list?depId=${data}`, + method: 'get', + data: data + }); + }, + + // 班组-班组成员列表 + getAllRecord: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/schedule/group/member/list`, + method: 'get', + data: data + }); + }, + + // 班组新增 + addRecord: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/schedule/group/add`, + method: 'post', + data: data + }); + }, + + // 班组修改 + updateRecord: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/schedule/group/mod`, + method: 'post', + data: data + }); + }, + + // 班组删除 + deleteRecord: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/schedule/group/del`, + method: 'post', + data: data + }); + } + + // 时间策略批量删除 + // deletBatchRecord: (data: object)=>{ + // return request({ + // url: `/timeStrategy/deleteBatchTimeStrategy`, + // method: 'post', + // data: data + // }) + // }, + }; +} diff --git a/src/api/systemManage/basicDateManage/personShiftManage/teamStrategy/index.ts b/src/api/systemManage/basicDateManage/personShiftManage/teamStrategy/index.ts new file mode 100644 index 0000000..1e9365f --- /dev/null +++ b/src/api/systemManage/basicDateManage/personShiftManage/teamStrategy/index.ts @@ -0,0 +1,50 @@ +import request from '/@/utils/request'; + +export function teamStrategyApi() { + return { + //获取班组策略分页列表 + getRecordPage: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/schedule/groupStrategy/page/list`, + method: 'post', + data: data + }); + }, + + // 班组策略新增 + addRecord: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/schedule/groupStrategy/add`, + method: 'post', + data: data + }); + }, + + // 班组策略修改 + updateRecord: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/schedule/groupStrategy/mod`, + method: 'post', + data: data + }); + }, + + // 班组策略删除 + deleteRecord: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/schedule/groupStrategy/del`, + method: 'post', + data: data + }); + } + + // 时间策略批量删除 + // deletBatchRecord: (data: object)=>{ + // return request({ + // url: `/timeStrategy/deleteBatchTimeStrategy`, + // method: 'post', + // data: data + // }) + // }, + }; +} diff --git a/src/api/systemManage/basicDateManage/personShiftManage/timeStrategy/index.ts b/src/api/systemManage/basicDateManage/personShiftManage/timeStrategy/index.ts new file mode 100644 index 0000000..e33a1cd --- /dev/null +++ b/src/api/systemManage/basicDateManage/personShiftManage/timeStrategy/index.ts @@ -0,0 +1,83 @@ +import request from '/@/utils/request'; + +export function timeStrategyApi() { + return { + //获取工作时间组列表 + getWorkTimeList: () => { + return request({ + url: import.meta.env.VITE_API_URL + `/workTime/getWorkTimeGroup`, + method: 'get' + }); + }, + + //获取休息时间组列表 + getRestTimeList: () => { + return request({ + url: import.meta.env.VITE_API_URL + `/breakTime/getAllBreakTimeGroup`, + method: 'get' + }); + }, + + //时间策略分页列表 + getRecordPage: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/timeStrategy/getAllTimeStrategyByPage`, + method: 'post', + data: data + }); + }, + + // 时间策略全部列表 + getAllRecord: () => { + return request({ + url: import.meta.env.VITE_API_URL + `/timeStrategy/getAllTimeStrategy`, + method: 'get' + }); + }, + + //根据id获取时间策略列表 + getRecordById: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/timeStrategy/getTimeStrategyById`, + method: 'post', + data: data + }); + }, + + // 时间策略新增 + addRecord: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/timeStrategy/addTimeStrategy`, + method: 'post', + data: data + }); + }, + + // 时间策略修改 + updateRecord: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/timeStrategy/updateTimeStrategy`, + method: 'post', + data: data + }); + }, + + // 时间策略删除 + deleteRecord: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/timeStrategy/deleteTimeStrategy`, + method: 'post', + data: data + }); + }, + + // 时间策略批量删除 + deletBatchRecord: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/timeStrategy/deleteBatchTimeStrategy`, + method: 'post', + data: data + }); + } + }; +} diff --git a/src/api/systemManage/basicDateManage/personShiftManage/workingHours/index.ts b/src/api/systemManage/basicDateManage/personShiftManage/workingHours/index.ts new file mode 100644 index 0000000..6bde267 --- /dev/null +++ b/src/api/systemManage/basicDateManage/personShiftManage/workingHours/index.ts @@ -0,0 +1,58 @@ +import request from '/@/utils/request'; + +export function workingHoursApi() { + return { + // 获取工作时间段列表 + getWorkTimePeriod: () => { + return request({ + url: import.meta.env.VITE_API_URL + `/workTime/getWorkTimePeriod`, + method: 'get' + }); + }, + + //工作时间段分页列表 + postPeriodPage: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/workTime/getWorkTimePeriodByPage?pageSiz`, + method: 'post', + data: data + }); + }, + + // 新增工作时间段 + postWorkTimePeriod: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/workTime/addWorkTimePeriod`, + method: 'post', + data: data + }); + }, + + // 修改工作时间段 + updateWorkTimePeriod: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/workTime/updateWorkTimePeriod`, + method: 'post', + data: data + }); + }, + + // 删除工作时间段 + deletWorkTimePeriod: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/workTime/deletWorkTimePeriod`, + method: 'post', + data: data + }); + }, + + // 批量删除 + deleteBatchWorkTimePeriod: (data: any) => { + return request({ + url: import.meta.env.VITE_API_URL + `/workTime/deleteBatchWorkTimePeriod`, + method: 'post', + data: data + }); + } + }; +} diff --git a/src/api/systemManage/basicDateManage/personShiftManage/workingHoursSet/index.ts b/src/api/systemManage/basicDateManage/personShiftManage/workingHoursSet/index.ts new file mode 100644 index 0000000..564f5e4 --- /dev/null +++ b/src/api/systemManage/basicDateManage/personShiftManage/workingHoursSet/index.ts @@ -0,0 +1,50 @@ +import request from '/@/utils/request'; + +export function workingHoursSetApi() { + return { + //工作时间组分页列表 + postWorkTimeGroupPage: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/workTime/getWorkTimeGroupByPage`, + method: 'post', + data: data + }); + }, + + // 工作时间组新增 + addWorkTimeGroup: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/workTime/addWorkTimeGroup`, + method: 'post', + data: data + }); + }, + + // 工作时间组修改 + updateWorkTimeGroup: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/workTime/updateWorkTimeGroup`, + method: 'post', + data: data + }); + }, + + // 工作时间组删除 + deleteWorkTimeGroup: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/workTime/deleteWorkTimeGroup`, + method: 'post', + data: data + }); + }, + + // 工作时间组批量删除 + deletBatchWorkTimeGroup: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/workTime/deletBatchWorkTimeGroup`, + method: 'post', + data: data + }); + } + }; +} diff --git a/src/api/systemManage/department/index.ts b/src/api/systemManage/department/index.ts new file mode 100644 index 0000000..fb22c65 --- /dev/null +++ b/src/api/systemManage/department/index.ts @@ -0,0 +1,37 @@ +import request from '/@/utils/request'; + +export function departmentApi() { + return { + // v2 + getDepartmentList: () => { + return request({ + url: import.meta.env.VITE_API_URL + `/department/list`, + method: 'post' + }); + }, + // v2 + addDepartment: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/department/add`, + method: 'post', + data: data + }); + }, + // v2 + modDepartment: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/department/mod`, + method: 'post', + data: data + }); + }, + // v1 + deleteDepartment: (value?: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/department/del`, + method: 'post', + data: value + }); + } + }; +} diff --git a/src/api/systemManage/menu/index.ts b/src/api/systemManage/menu/index.ts new file mode 100644 index 0000000..85514f2 --- /dev/null +++ b/src/api/systemManage/menu/index.ts @@ -0,0 +1,50 @@ +import request from '/@/utils/request'; + +/** + * 后端控制菜单模拟json,路径在 https://gitee.com/lyt-top/vue-next-admin-images/tree/master/menu + * 后端控制路由,isRequestRoutes 为 true,则开启后端控制路由 + * @method getMenuAdmin 获取后端动态路由菜单(admin) + * @method getMenuTest 获取后端动态路由菜单(test) + */ +export function useMenuApi() { + return { + // v2 + getMenuAdmin: (value?: string) => { + return request({ + url: import.meta.env.VITE_API_URL + `/auth/menu?projectId= ${value}`, + method: 'post' + }); + }, + // v1 + addMenu: (value?: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/menu/add`, + method: 'post', + data: value + }); + }, + // v1 + modMenu: (value?: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/menu/mod`, + method: 'post', + data: value + }); + }, + // v1 + deleteMenu: (value?: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/menu/del`, + method: 'post', + data: value + }); + }, + // v1 + getProjectList: () => { + return request({ + url: import.meta.env.VITE_API_URL + `/project/list`, + method: 'post' + }); + } + }; +} diff --git a/src/api/systemManage/personShiftManage/holidayTime/index.ts b/src/api/systemManage/personShiftManage/holidayTime/index.ts new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/api/systemManage/personShiftManage/holidayTime/index.ts diff --git a/src/api/systemManage/personShiftManage/holidayTimeGroup/index.ts b/src/api/systemManage/personShiftManage/holidayTimeGroup/index.ts new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/api/systemManage/personShiftManage/holidayTimeGroup/index.ts diff --git a/src/api/systemManage/personShiftManage/teamManage/index.ts b/src/api/systemManage/personShiftManage/teamManage/index.ts new file mode 100644 index 0000000..d378691 --- /dev/null +++ b/src/api/systemManage/personShiftManage/teamManage/index.ts @@ -0,0 +1,94 @@ +import request from '/@/utils/request'; + +export function teamManageApi() { + return { + //班组分页列表 + getRecordPage: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/schedule/group/page/list`, + method: 'post', + data: data + }); + }, + + //班组列表 + getRecord: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/schedule/group/list`, + method: 'post', + data: data + }); + }, + + //班组-班组成员分页列表 + getAllRecordPage: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/schedule/group/member/page/list`, + method: 'post', + data: data + }); + }, + + //所有部门列表 + getAllDepartment: () => { + return request({ + url: import.meta.env.VITE_API_URL + `/department/list`, + method: 'post' + }); + }, + + //用户-部门所有用户 + getAllMember: (data: number) => { + return request({ + url: import.meta.env.VITE_API_URL + `/account/dep/list?depId=${data}`, + method: 'get', + data: data + }); + }, + + // 班组-班组成员列表 + getAllRecord: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/schedule/group/member/list`, + method: 'get', + data: data + }); + }, + + // 班组新增 + addRecord: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/schedule/group/add`, + method: 'post', + data: data + }); + }, + + // 班组修改 + updateRecord: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/schedule/group/mod`, + method: 'post', + data: data + }); + }, + + // 班组删除 + deleteRecord: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/schedule/group/del`, + method: 'post', + data: data + }); + } + + // 时间策略批量删除 + // deletBatchRecord: (data: object)=>{ + // return request({ + // url: `/timeStrategy/deleteBatchTimeStrategy`, + // method: 'post', + // data: data + // }) + // }, + }; +} diff --git a/src/api/systemManage/personShiftManage/teamStrategy/index.ts b/src/api/systemManage/personShiftManage/teamStrategy/index.ts new file mode 100644 index 0000000..1e9365f --- /dev/null +++ b/src/api/systemManage/personShiftManage/teamStrategy/index.ts @@ -0,0 +1,50 @@ +import request from '/@/utils/request'; + +export function teamStrategyApi() { + return { + //获取班组策略分页列表 + getRecordPage: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/schedule/groupStrategy/page/list`, + method: 'post', + data: data + }); + }, + + // 班组策略新增 + addRecord: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/schedule/groupStrategy/add`, + method: 'post', + data: data + }); + }, + + // 班组策略修改 + updateRecord: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/schedule/groupStrategy/mod`, + method: 'post', + data: data + }); + }, + + // 班组策略删除 + deleteRecord: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/schedule/groupStrategy/del`, + method: 'post', + data: data + }); + } + + // 时间策略批量删除 + // deletBatchRecord: (data: object)=>{ + // return request({ + // url: `/timeStrategy/deleteBatchTimeStrategy`, + // method: 'post', + // data: data + // }) + // }, + }; +} diff --git a/src/api/systemManage/personShiftManage/timeStrategy/index.ts b/src/api/systemManage/personShiftManage/timeStrategy/index.ts new file mode 100644 index 0000000..e33a1cd --- /dev/null +++ b/src/api/systemManage/personShiftManage/timeStrategy/index.ts @@ -0,0 +1,83 @@ +import request from '/@/utils/request'; + +export function timeStrategyApi() { + return { + //获取工作时间组列表 + getWorkTimeList: () => { + return request({ + url: import.meta.env.VITE_API_URL + `/workTime/getWorkTimeGroup`, + method: 'get' + }); + }, + + //获取休息时间组列表 + getRestTimeList: () => { + return request({ + url: import.meta.env.VITE_API_URL + `/breakTime/getAllBreakTimeGroup`, + method: 'get' + }); + }, + + //时间策略分页列表 + getRecordPage: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/timeStrategy/getAllTimeStrategyByPage`, + method: 'post', + data: data + }); + }, + + // 时间策略全部列表 + getAllRecord: () => { + return request({ + url: import.meta.env.VITE_API_URL + `/timeStrategy/getAllTimeStrategy`, + method: 'get' + }); + }, + + //根据id获取时间策略列表 + getRecordById: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/timeStrategy/getTimeStrategyById`, + method: 'post', + data: data + }); + }, + + // 时间策略新增 + addRecord: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/timeStrategy/addTimeStrategy`, + method: 'post', + data: data + }); + }, + + // 时间策略修改 + updateRecord: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/timeStrategy/updateTimeStrategy`, + method: 'post', + data: data + }); + }, + + // 时间策略删除 + deleteRecord: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/timeStrategy/deleteTimeStrategy`, + method: 'post', + data: data + }); + }, + + // 时间策略批量删除 + deletBatchRecord: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/timeStrategy/deleteBatchTimeStrategy`, + method: 'post', + data: data + }); + } + }; +} diff --git a/src/api/systemManage/personShiftManage/workingHours/index.ts b/src/api/systemManage/personShiftManage/workingHours/index.ts new file mode 100644 index 0000000..590bbf5 --- /dev/null +++ b/src/api/systemManage/personShiftManage/workingHours/index.ts @@ -0,0 +1,58 @@ +import request from '/@/utils/request'; + +export function workingHoursApi() { + return { + // 获取工作时间段列表 + getWorkTimePeriod: (value: { name: string }) => { + return request({ + url: import.meta.env.VITE_API_URL + `/workTime/getWorkTimePeriod`, + method: 'get' + }); + }, + + //工作时间段分页列表 + postPeriodPage: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/workTime/getWorkTimePeriodByPage?pageSiz`, + method: 'post', + data: data + }); + }, + + // 新增工作时间段 + postWorkTimePeriod: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/workTime/addWorkTimePeriod`, + method: 'post', + data: data + }); + }, + + // 修改工作时间段 + updateWorkTimePeriod: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/workTime/updateWorkTimePeriod`, + method: 'post', + data: data + }); + }, + + // 删除工作时间段 + deletWorkTimePeriod: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/workTime/deletWorkTimePeriod`, + method: 'post', + data: data + }); + }, + + // 批量删除 + deleteBatchWorkTimePeriod: (data: any) => { + return request({ + url: import.meta.env.VITE_API_URL + `/workTime/deleteBatchWorkTimePeriod`, + method: 'post', + data: data + }); + } + }; +} diff --git a/src/api/systemManage/personShiftManage/workingHoursSet/index.ts b/src/api/systemManage/personShiftManage/workingHoursSet/index.ts new file mode 100644 index 0000000..564f5e4 --- /dev/null +++ b/src/api/systemManage/personShiftManage/workingHoursSet/index.ts @@ -0,0 +1,50 @@ +import request from '/@/utils/request'; + +export function workingHoursSetApi() { + return { + //工作时间组分页列表 + postWorkTimeGroupPage: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/workTime/getWorkTimeGroupByPage`, + method: 'post', + data: data + }); + }, + + // 工作时间组新增 + addWorkTimeGroup: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/workTime/addWorkTimeGroup`, + method: 'post', + data: data + }); + }, + + // 工作时间组修改 + updateWorkTimeGroup: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/workTime/updateWorkTimeGroup`, + method: 'post', + data: data + }); + }, + + // 工作时间组删除 + deleteWorkTimeGroup: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/workTime/deleteWorkTimeGroup`, + method: 'post', + data: data + }); + }, + + // 工作时间组批量删除 + deletBatchWorkTimeGroup: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/workTime/deletBatchWorkTimeGroup`, + method: 'post', + data: data + }); + } + }; +} diff --git a/src/api/systemManage/role/index.ts b/src/api/systemManage/role/index.ts new file mode 100644 index 0000000..85b00cf --- /dev/null +++ b/src/api/systemManage/role/index.ts @@ -0,0 +1,37 @@ +import request from '/@/utils/request'; + +export function useRoleApi() { + return { + // v2 + getRoleList: () => { + return request({ + url: import.meta.env.VITE_API_URL + `/role/list`, + method: 'post' + }); + }, + // v2 + addRole: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/role/add`, + method: 'post', + data: data + }); + }, + // v2 + modRole: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/role/mod`, + method: 'post', + data: data + }); + }, + // v2 + deleteRole: (value?: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/role/del`, + method: 'post', + data: value + }); + } + }; +} diff --git a/src/api/systemManage/user/index.ts b/src/api/systemManage/user/index.ts new file mode 100644 index 0000000..52370a6 --- /dev/null +++ b/src/api/systemManage/user/index.ts @@ -0,0 +1,51 @@ +import request from '/@/utils/request'; + +export function userApi() { + return { + // v1 + getUserList: (data: any) => { + return request({ + url: import.meta.env.VITE_API_URL + `/account/page/list`, + method: 'post', + data: data + }); + }, + // v1 + addUser: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/account/add`, + method: 'post', + data: data + }); + }, + // v1 + modUser: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/account/mod`, + method: 'post', + data: data + }); + }, + // v1 + deleteUser: (data: object) => { + return request({ + url: import.meta.env.VITE_API_URL + `/account/del`, + method: 'post', + data: data + }); + }, + // v1 + getUserLByDepartment: (depId: number | null) => { + return request({ + url: import.meta.env.VITE_API_URL + `/account/dep/list?depId=${depId == null ? '' : depId}`, + method: 'get' + }); + }, + getAllUser: () => { + return request({ + url: import.meta.env.VITE_API_URL + `/account/list`, + method: 'get' + }); + } + }; +} diff --git a/src/api/workInjuryDeclaration/index.ts b/src/api/workInjuryDeclaration/index.ts new file mode 100644 index 0000000..630f412 --- /dev/null +++ b/src/api/workInjuryDeclaration/index.ts @@ -0,0 +1,123 @@ +import request from '/@/utils/request'; + +export function accidentManagementSystemApi() { + return { + // 事故快报一览 + accidentList: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/accidentExpress/page/list', + method: 'post', + data: params + }); + }, + // 事故快报新增 + accidentAdd: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/accidentExpress/add', + method: 'post', + data: params + }); + }, + // 事故快报详情 + accidentScarh: (params: number) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/accidentExpress/info/${params}`, + method: 'get' + }); + }, + // 事故快报修改 + accidentView: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/accidentExpress/update', + method: 'post', + data: params + }); + }, + // 事故快报删除 + accidentDele: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/accidentExpress/batchDelete/${params}`, + method: 'get' + }); + }, + + // 事故报告一览 + getAccidentReportList: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/accidentReport/page/list', + method: 'post', + data: params + }); + }, + // 事故报告新增 + addAccidentReport: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/accidentReport/add`, + method: 'post', + data: params + }); + }, + // 事故报告详情 + seeAccidentReport: (params: number) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/accidentReport/info/${params}`, + method: 'get' + }); + }, + // 事故报告编辑 + editAccidentReport: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/accidentReport/update`, + method: 'post', + data: params + }); + }, + // 事故报告删除 + deleteAccidentReport: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/accidentReport/batchDelete`, + method: 'post', + data: params + }); + }, + + // 工伤申报一览 + workList: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/workInjuryDeclaration/page/list', + method: 'post', + data: params + }); + }, + // 工伤申报新增 + workAdd: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/workInjuryDeclaration/add', + method: 'post', + data: params + }); + }, + // 工伤申报详情 + seeAccidentManagementSystem: (params: number) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `workInjuryDeclaration/info/${params}`, + method: 'get' + }); + }, + // 工伤申报修改 + workView: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + '/workInjuryDeclaration/update', + method: 'post', + data: params + }); + }, + // 工伤申报删除/批量删除 + workDelete: (params: object) => { + return request({ + url: import.meta.env.VITE_API_URL_OUT + `/workInjuryDeclaration/batchDelete/${params}`, + method: 'get' + }); + } + }; +} diff --git a/src/assets/avator.png b/src/assets/avator.png new file mode 100644 index 0000000..3d7f367 --- /dev/null +++ b/src/assets/avator.png Binary files differ diff --git a/src/assets/companyLogo.png b/src/assets/companyLogo.png new file mode 100644 index 0000000..0f9f2d1 --- /dev/null +++ b/src/assets/companyLogo.png Binary files differ diff --git a/src/assets/default-img.jpg b/src/assets/default-img.jpg new file mode 100644 index 0000000..7eb2590 --- /dev/null +++ b/src/assets/default-img.jpg Binary files differ diff --git a/src/assets/icon.png b/src/assets/icon.png new file mode 100644 index 0000000..342ace7 --- /dev/null +++ b/src/assets/icon.png Binary files differ diff --git a/src/assets/index.css b/src/assets/index.css new file mode 100644 index 0000000..08d6baa --- /dev/null +++ b/src/assets/index.css @@ -0,0 +1,10 @@ +.pot { + position: absolute; + top: 19px; + right: 40px; + border: none !important; + padding: 0; +} +.pot:focus,.pot:hover{ + background-color: #fff !important; +} \ No newline at end of file diff --git a/src/assets/index.ts b/src/assets/index.ts new file mode 100644 index 0000000..de3e571 --- /dev/null +++ b/src/assets/index.ts @@ -0,0 +1,17 @@ +export function timeDate(row: any, column: any, cellValue: any, index: any) { + const daterc = row[column.property] + if (daterc != null) { + var date = new Date(daterc); + var year = date.getFullYear(); + /* 在日期格式中,月份是从0开始,11结束,因此要加0 + * 使用三元表达式在小于10的前面加0,以达到格式统一 如 09:11:05 + * */ + var month = date.getMonth() + 1 < 10 ? "0" + (date.getMonth() + 1) : date.getMonth() + 1; + var day = date.getDate() < 10 ? "0" + date.getDate() : date.getDate(); + var hours = date.getHours() < 10 ? "0" + date.getHours() : date.getHours(); + var minutes = date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes(); + var seconds = date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds(); + // 拼接 + return year + "-" + month + "-" + day + " " + hours + ":" + minutes + ":" + seconds; + } +} \ No newline at end of file diff --git a/src/assets/login-icon-two.svg b/src/assets/login-icon-two.svg new file mode 100644 index 0000000..b930211 --- /dev/null +++ b/src/assets/login-icon-two.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" data-name="Layer 1" width="1151.5635" height="842.24197" viewBox="0 0 1151.5635 842.24197" xmlns:xlink="http://www.w3.org/1999/xlink"><title>sunlight</title><path d="M1080.33549,309.07821h-.00006c-22.0216,0-39.87364,19.81184-39.87364,44.251v31.0502h9.54961l5.52868-11.50435-1.38218,11.50435h61.38126l5.02608-10.4585-1.25651,10.4585h6.91087v-24.38C1126.2196,331.87644,1105.67658,309.07821,1080.33549,309.07821Z" transform="translate(-24.21825 -28.87901)" fill="#2f2e41"/><path d="M1042.88322,452.6347l-6.62276,25.38724,61.81242-2.20758-1.1038-20.97207S1050.60977,442.70056,1042.88322,452.6347Z" transform="translate(-24.21825 -28.87901)" fill="#ffb9b9"/><polygon points="959.06 525.305 978.928 569.456 997.693 546.277 982.24 515.371 959.06 525.305" fill="#ffb9b9"/><polygon points="1008.731 687.562 1010.938 738.337 1035.222 738.337 1031.91 687.562 1008.731 687.562" fill="#ffb9b9"/><path d="M1004.25045,507.82436l11.03794,36.42517,16.55689,176.60691s15.45311,4.41518,26.491-1.10379l2.20759-24.28345,4.41517-139.07794s20.97207-11.03793,18.76448-26.491-7.72655-36.42517-7.72655-36.42517Z" transform="translate(-24.21825 -28.87901)" fill="#2f2e41"/><path d="M1038.468,755.074h-6.62276s-18.76448,19.86828-25.38724,22.07587-40.84035,20.97207-13.24552,24.28345,45.25552-11.03794,45.25552-11.03794,8.83035,5.519,20.97207,1.1038,5.519-17.66069,5.519-17.66069-6.16367-20.18749-6.39321-20.02789S1051.71356,763.90438,1038.468,755.074Z" transform="translate(-24.21825 -28.87901)" fill="#2f2e41"/><circle cx="1048.46738" cy="323.31051" r="25.38724" fill="#ffb9b9"/><path d="M1110.2146,385.30331l-11.67815,9.73547-1.56737,1.30247-1.10379,13.24551h-43.04794s5.87219-5.08847,11.32493-10.35358c.11036-.1214.23176-.25385.36427-.37532.73953-.71743,1.40178-1.37974,1.99787-1.97577.32007-.33112.6291-.64021.90505-.92721.45259-.47462.89414-.92715,1.33561-1.37974a.03829.03829,0,0,0,.01105-.022,43.07955,43.07955,0,0,0,3.17893-3.73083l.01105-.011a12.81791,12.81791,0,0,0,.73952-1.09274c3.31138-5.519-4.41517-16.5569-4.41517-16.5569l24.28345-12.14173c.84994,11.96508,10.97171,19.95654,15.49723,22.95889C1109.37571,384.85072,1110.2146,385.30331,1110.2146,385.30331Z" transform="translate(-24.21825 -28.87901)" fill="#ffb9b9"/><path d="M1169.81943,570.74057c-16.5569,4.41517-17.66069-28.69862-17.66069-28.69862l-22.59765-45.1953a104.51533,104.51533,0,0,1-9.73594-30.31979l-5.19538-32.65665-1.57841,1.88745v.01105l-2.83676,1.41288-17.24124-27.59483-4.83462-7.72655v-8.83034l16.55689-7.72656h6.62276s.1435-.02209.39735-.04419c3.04648-.32008,22.87063-1.64464,23.8861,17.70489.39969,7.59413.36519,13.88569.15854,18.82226a145.76191,145.76191,0,0,0,3.84972,40.63177c1.16857,4.79412,2.44343,8.95772,3.7183,11.18873,4.41517,7.72655,19.86827,68.43518,19.86827,68.43518S1186.37633,566.3254,1169.81943,570.74057Z" transform="translate(-24.21825 -28.87901)" fill="#ffb9b9"/><path d="M1068.27046,397.445l-4.18335,7.62718-2.47256,4.51454L1049.506,431.66263s-3.43278,2.80361-8.99594,6.42408c-9.24979,6.01562-24.4159,14.272-39.571,15.65178-24.28345,2.20759-1.10379-76.16173-1.10379-76.16173s7.72655-30.90621,18.76449-27.59483,2.20758,14.34931-5.519,35.32138S1011.977,429.455,1011.977,429.455s23.17965-14.34931,35.32138-25.38724c6.32471-5.75079,11.75542-7.30711,15.49723-7.4727h.011a14.05473,14.05473,0,0,1,3.69775.287A8.35071,8.35071,0,0,1,1068.27046,397.445Z" transform="translate(-24.21825 -28.87901)" fill="#ffb9b9"/><path d="M1071.93506,390.82228c-.04413.1214-.56294,1.10379-4.52559,5.1326A53.271,53.271,0,0,0,1071.93506,390.82228Z" transform="translate(-24.21825 -28.87901)" fill="#d0cde1"/><path d="M1114.07788,434.42211l-1.02652,1.3466-16.08228,27.90392s-20.97207-7.72655-36.42517-9.93414a21.64727,21.64727,0,0,0-22.06482,9.901l4.40413-17.62754-2.37319-7.92523c-.27594-.92721-.596-1.95373-.93819-3.1127-3.31138-11.03793,8.83034-23.17966,8.83034-23.17966l14.39344-15.19925h.011a14.05473,14.05473,0,0,1,3.69775.287c-.59609.596-1.25834,1.25834-1.99787,1.97577-.13251.12147-.25391.25392-.36427.37532-4.22754,4.3158-2.031,5.519-.05517,5.839a9.71986,9.71986,0,0,0,1.97576.09937c4.6028.66225,14.68044-3.3776,22.07587-6.75521,5.03329-2.29591,8.83034-4.28272,8.83034-4.28272l9.63609-8.83035,1.446-1.32456c1.32457.872,2.16346,1.32456,2.16346,1.32456h1.10379s.1435-.02209.39735-.04419l-5.02587,3.72943a18.68469,18.68469,0,0,0-7.5132,16.183h0Z" transform="translate(-24.21825 -28.87901)" fill="#d0cde1"/><path d="M1053.92115,465.88022l-16.1372,6.30165s-87.61936-33.89648-100.86488-6.30165,46.35931,93.82242,46.35931,93.82242l26.491-12.14173-11.03793-33.11379s64.02,54.08586,90.511,24.28345,8.83035-71.94211,8.83035-71.94211S1081.516,453.73849,1053.92115,465.88022Z" transform="translate(-24.21825 -28.87901)" fill="#2f2e41"/><path d="M1007.56183,586.19367l-9.93413,7.72656s8.83034,35.32138,5.519,40.84034-9.93414,20.97208,2.20759,19.86828,25.38724-19.86828,26.491-26.491,8.83035-26.491,8.83035-26.491,13.24552-30.90621,3.31138-32.01-25.75662-1.84256-25.75662-1.84256Z" transform="translate(-24.21825 -28.87901)" fill="#2f2e41"/><path d="M1091.67085,321.26789a20.91185,20.91185,0,0,0-16.50006-8.4201h-.78284c-15.09365,0-27.32941,13.658-27.32941,30.50606v.00006h5.05749l.81677-6.217,1.19755,6.217H1084.126l2.51307-5.25968-.62828,5.25968h5.901q4.13043,20.51274-11.86947,41.02548h10.05221l5.02608-10.51935-1.2565,10.51935h19.162l3.76958-24.19458C1116.79567,342.06532,1106.26771,326.70034,1091.67085,321.26789Z" transform="translate(-24.21825 -28.87901)" fill="#2f2e41"/><circle cx="971.03374" cy="113.59071" r="91" fill="#ff6584"/><path d="M771.29477,567.032c-1.6806,13.391-3.05862,26.28082-4.18757,38.571h36.55924q1.99625-19.38064,5.00548-38.571Z" transform="translate(-24.21825 -28.87901)" fill="#3f3d56"/><path d="M801.19676,703.21105q-1.17629-19.19032-.9509-38.571H763.184c-.60171,14.7787-.83742,27.751-.88075,38.571Z" transform="translate(-24.21825 -28.87901)" fill="#3f3d56"/><path d="M864.4142,361.58256C894.89157,280.388,924.75032,225.797,924.75032,225.797L893.6574,207.29872c-32.37571,48.82045-56.84558,101.59229-75.3218,154.28384Z" transform="translate(-24.21825 -28.87901)" fill="#3f3d56"/><path d="M766.21242,615.836c-1.14212,13.751-1.97242,26.66388-2.56481,38.571h36.792q.53185-19.28516,2.25137-38.571Z" transform="translate(-24.21825 -28.87901)" fill="#3f3d56"/><path d="M778.50126,518.22788c-2.24695,13.1965-4.19314,26.08124-5.8747,38.571h37.70491q3.28452-19.4853,7.41146-38.571Z" transform="translate(-24.21825 -28.87901)" fill="#3f3d56"/><path d="M814.82354,371.81567q-6.5049,19.34635-11.981,38.571h44.39012c4.3882-13.35371,8.88306-26.24037,13.39195-38.571Z" transform="translate(-24.21825 -28.87901)" fill="#3f3d56"/><path d="M787.981,469.42381q-4.29519,19.6076-7.68675,38.571H820.004q4.44783-19.61091,9.56837-38.571Z" transform="translate(-24.21825 -28.87901)" fill="#3f3d56"/><path d="M762.3185,713.44417c.12069,16.62136.66994,25.97636.66994,25.97636l-.39358,7.478h43.29393q-2.59815-16.58382-3.96368-33.4544Z" transform="translate(-24.21825 -28.87901)" fill="#3f3d56"/><path d="M799.97844,420.61974q-5.32646,19.46534-9.69876,38.571H832.379q5.53043-19.7784,11.542-38.571Z" transform="translate(-24.21825 -28.87901)" fill="#3f3d56"/><path d="M1110.252,261.1651c-15.40963-32.21182-30.90977-56.23791-46.0196-73.94267l-7.89046,12.123.671-20.13755a158.22113,158.22113,0,0,0-16.6583-15.2789L1029.57149,180.496l.78947-23.69016a99.14041,99.14041,0,0,0-20.48314-10.11247l-7.97482,12.25252.48352-14.50965c-27.51475-6.905-50.1228,2.55337-63.22081,10.629l-7.86615-1.17354,13.49035-5.63347a99.1429,99.1429,0,0,0-6.25118-21.97146l-23.44384-3.4975L933.3355,115.172a158.21342,158.21342,0,0,0-12.02277-19.14149l-19.92822-2.973,13.34774-5.574c-14.68838-18.056-35.52378-37.63644-64.42682-58.60454,0,0-2.13827,18.67657-3.3293,44.71673l19.575,20.025-20.111-5.20116c-.21044,7.9976-.30047,16.41755-.20141,25.00812l14.43606,14.76794-14.20045-3.67257c.20688,6.56884.54118,13.17147,1.02835,19.7a77.7484,77.7484,0,0,0-37.38522.21323l.48352,14.50965-7.97482-12.25252A99.14066,99.14066,0,0,0,782.143,156.80588l.78947,23.69016L772.14939,163.929a158.22118,158.22118,0,0,0-16.65831,15.2789l.671,20.13755-7.89046-12.123c-15.10983,17.70476-30.61,41.73085-46.0195,73.94267,0,0,18.75584-1.2664,44.58355-4.79292l16.16488-22.86653L761.513,254.225c7.90429-1.2359,16.20236-2.66638,24.63409-4.31364l11.92111-16.86355-1.05035,14.63006c11.76-2.54214,23.55587-5.52,34.6978-8.989l8.00048,7.44239-14.31143-2.98448a99.14327,99.14327,0,0,0-7.27222,21.65494l17.35524,16.14443-19.35091-4.03541a158.216,158.216,0,0,0-.91179,22.58566l14.75256,13.72341-14.16008-2.95292c1.90026,23.19813,8.00769,51.13034,19.98347,84.7701,0,0,12.327-14.19261,28.03786-34.99356l-4.81657-27.58585,13.64313,15.66426c4.697-6.47636,9.53377-13.36913,14.311-20.50951l-3.55213-20.344L893.0578,318.329c9.67465-15.1043,18.722-30.948,25.38657-46.03838A385.08247,385.08247,0,0,0,946.086,304.50881l7.38-12.67579.33948,20.64894c6.03555,6.11391,12.08293,11.97343,17.91467,17.45027l10.45191-17.95172.46027,27.99943c19.34428,17.473,34.12174,29.09258,34.12174,29.09258,5.43182-35.29231,6.17421-63.8748,3.67531-87.01609l-13.35149,5.56466,11.9067-16.25425a158.22134,158.22134,0,0,0-5.14539-22.01061l-18.246,7.60454,8.67646-11.84438q5.59182,1.34816,11.21649,2.56145l-1.05035-14.63006,11.92111,16.86355c8.43173,1.64726,16.7298,3.07774,24.63409,4.31364l-1.48755-20.71932,16.16488,22.86653C1091.49615,259.8987,1110.252,261.1651,1110.252,261.1651Z" transform="translate(-24.21825 -28.87901)" fill="#e6a23c"/><path d="M706.516,543.343c1.1863,9.45251,2.159,18.55119,2.95593,27.2266H683.6654q-1.40913-13.68048-3.53328-27.2266Z" transform="translate(-24.21825 -28.87901)" fill="#3f3d56"/><path d="M685.40871,639.4695q.83031-13.54614.67122-27.2266h26.16136c.42474,10.432.59112,19.589.62171,27.2266Z" transform="translate(-24.21825 -28.87901)" fill="#3f3d56"/><path d="M640.78457,398.31967c-21.51346-57.31385-42.59025-95.84872-42.59025-95.84872l21.948-13.05765c22.85347,34.46154,40.12634,71.71229,53.16839,108.90637Z" transform="translate(-24.21825 -28.87901)" fill="#3f3d56"/><path d="M710.10356,577.79293c.8062,9.70662,1.3923,18.82158,1.81046,27.22659H685.94319q-.37542-13.61307-1.5892-27.22659Z" transform="translate(-24.21825 -28.87901)" fill="#3f3d56"/><path d="M701.42907,508.893c1.58609,9.31519,2.95987,18.41031,4.14686,27.22659H678.96066q-2.31847-13.75434-5.23162-27.22659Z" transform="translate(-24.21825 -28.87901)" fill="#3f3d56"/><path d="M675.78979,405.54305q4.59169,13.65627,8.45716,27.2266H652.91271c-3.09755-9.42616-6.2704-18.52264-9.45315-27.2266Z" transform="translate(-24.21825 -28.87901)" fill="#3f3d56"/><path d="M694.73746,474.443q3.0319,13.84068,5.42595,27.2266H672.133q-3.13965-13.843-6.75415-27.2266Z" transform="translate(-24.21825 -28.87901)" fill="#3f3d56"/><path d="M712.85221,646.69288c-.08519,11.73274-.47289,18.33627-.47289,18.33627l.27782,5.27863H682.09668q1.834-11.70624,2.79789-23.6149Z" transform="translate(-24.21825 -28.87901)" fill="#3f3d56"/><path d="M686.26869,439.993q3.75987,13.74026,6.8462,27.22659H663.39766q-3.90382-13.96124-8.14726-27.22659Z" transform="translate(-24.21825 -28.87901)" fill="#3f3d56"/><path d="M467.25181,327.43668c10.87739-22.73779,21.81868-39.6974,32.48446-52.1949l5.56974,8.55742-.47364-14.21476a111.68489,111.68489,0,0,1,11.75882-10.78512l7.61163,11.69442-.55728-16.72249a69.98142,69.98142,0,0,1,14.4587-7.13822l5.6293,8.64885-.34131-10.24212c19.4222-4.8741,35.38084,1.80238,44.62651,7.50279l5.55258-.82838-9.52261-3.97657a69.98374,69.98374,0,0,1,4.4126-15.50928l16.54861-2.46883-12.87573-5.37687a111.68,111.68,0,0,1,8.48667-13.51166l14.067-2.09862-9.422-3.93455c10.36829-12.74544,25.07564-26.56694,45.47782-41.368,0,0,1.50937,13.18347,2.35009,31.56478l-13.81766,14.1353,14.196-3.67141c.14854,5.64537.21209,11.58887.14216,17.65281l-10.19016,10.42444,10.02385-2.59241c-.146,4.63684-.382,9.29752-.72589,13.90591a54.88123,54.88123,0,0,1,26.3896.15051l-.34131,10.24212,5.62929-8.64885a69.98117,69.98117,0,0,1,14.4587,7.13822l-.55727,16.72249,7.61163-11.69442a111.68687,111.68687,0,0,1,11.75882,10.78512l-.47364,14.21476,5.56974-8.55742c10.66577,12.4975,21.60706,29.45711,32.48439,52.1949,0,0-13.23943-.89394-31.47078-3.38325l-11.41052-16.1411,1.05,14.62542c-5.57951-.8724-11.437-1.88215-17.38879-3.04492l-8.41491-11.9037.74142,10.32711c-8.30116-1.79445-16.62769-3.8965-24.49259-6.34518l-5.6474,5.25346,10.10219-2.10669a69.98325,69.98325,0,0,1,5.13334,15.28586L661.2033,341.39976l13.65948-2.84853a111.68285,111.68285,0,0,1,.64362,15.94284l-10.41359,9.68713,9.99537-2.08442c-1.34137,16.37518-5.6525,36.092-14.106,59.83779,0,0-8.70142-10.01832-19.79145-24.70136l3.39993-19.47239L634.96021,388.818c-3.31556-4.57156-6.72974-9.437-10.10193-14.47732l2.50739-14.36046-6.80014,7.80752A247.60106,247.60106,0,0,1,602.64558,335.29a271.82334,271.82334,0,0,1-19.51173,22.74229l-5.20944-8.94763-.23963,14.57574c-4.2604,4.31571-8.52914,8.45185-12.64567,12.31786l-7.37783-12.67182-.32489,19.76432c-13.65481,12.33393-24.086,20.536-24.086,20.536-3.83423-24.91224-4.35827-45.08815-2.59434-61.4232l9.4246,3.928-8.40474-11.47361a111.68612,111.68612,0,0,1,3.632-15.53692l12.87953,5.36792-6.12457-8.36075q-3.94716.95164-7.91753,1.80808l.74143-10.32711-8.41492,11.9037c-5.95181,1.16277-11.80928,2.17252-17.38879,3.04492l1.05-14.62542-11.41052,16.1411C480.49124,326.54274,467.25181,327.43668,467.25181,327.43668Z" transform="translate(-24.21825 -28.87901)" fill="#e6a23c"/><ellipse cx="379.53374" cy="720.59071" rx="147.5" ry="14" fill="#3f3d56"/><ellipse cx="734.53374" cy="720.59071" rx="147.5" ry="14" fill="#3f3d56"/><path d="M870.752,606.96972s10.65,73.95-40.48,117.67c-33.09,28.29-80.27,32.92-118.99,13.01-14.38-7.39-29.72-18.62-44.37006-35.57a191.08437,191.08437,0,0,1-15.26-20.3,242.48469,242.48469,0,0,1-17.73-32.37q-4.8-10.485-9.17-22.44c-.56-1.53-1.08-3.03-1.58-4.52-26.55-78.91,25.09-101.93,72.49-107.45a243.44911,243.44911,0,0,1,29.96-1.51,268.64314,268.64314,0,0,1,35.13,2.48s.97.01,2.72.08a210.98673,210.98673,0,0,1,26.93005,2.99C827.022,525.46972,883.072,545.38971,870.752,606.96972Z" transform="translate(-24.21825 -28.87901)" fill="#e6a23c"/><path d="M544.752,626.96972c-23.34,64.07-56.95,95.47-86.53,110.68-38.72,19.91-85.9,15.28-118.99-13.01a104.52345,104.52345,0,0,1-9-8.67,108.90024,108.90024,0,0,1-15.01-20.66,128.65459,128.65459,0,0,1-12.09-30.09,161.53735,161.53735,0,0,1-5.17-35.23,140.93566,140.93566,0,0,1,.79-23.02c-11.53-57.65,36.85-78.78,73.12-86.52a215.32462,215.32462,0,0,1,31.83-4.29c3.21-.18,5.05-.19,5.05-.19a276.07877,276.07877,0,0,1,57.57-1.71C516.412,518.29968,576.402,540.09973,544.752,626.96972Z" transform="translate(-24.21825 -28.87901)" fill="#e6a23c"/><path d="M403.702,516.15973l-100.57,149.06a161.53735,161.53735,0,0,1-5.17-35.23l73.91-109.54A215.32462,215.32462,0,0,1,403.702,516.15973Z" transform="translate(-24.21825 -28.87901)" fill="#fff" opacity="0.2"/><path d="M466.322,514.2597l-136.09,201.71a108.90024,108.90024,0,0,1-15.01-20.66l122.6-181.71A262.51415,262.51415,0,0,1,466.322,514.2597Z" transform="translate(-24.21825 -28.87901)" fill="#fff" opacity="0.2"/><path d="M725.622,513.48968l-91.7,135.92q-4.8-10.485-9.17-22.44c-.56-1.53-1.08-3.03-1.58-4.52l72.49-107.45A243.44911,243.44911,0,0,1,725.622,513.48968Z" transform="translate(-24.21825 -28.87901)" fill="#fff" opacity="0.2"/><path d="M790.402,519.03973l-123.49,183.04a191.08437,191.08437,0,0,1-15.26-20.3l111.81995-165.73A210.98673,210.98673,0,0,1,790.402,519.03973Z" transform="translate(-24.21825 -28.87901)" fill="#fff" opacity="0.2"/><path d="M894.752,599.96972H871.86472c10.12915-83.03949-111.11273-84-111.11273-84a276.47448,276.47448,0,0,0-58-1.67132v-.32868h-237v.24872a276.75793,276.75793,0,0,0-57,1.75128s-121.24188.96051-111.11273,84H275.752v22H297.8389c-.22119,23.90107,4.52283,71.14319,41.39307,102.67,33.09,28.29,80.27,32.92,118.99,13.01,29.58-15.21,63.19-46.61,86.53-110.68,7.996-21.94982,10.13965-39.74377,8.07287-54.14819a635.39219,635.39219,0,0,1,63.85425,0c-2.06677,14.40442.07684,32.19837,8.07288,54.14819,23.34,64.07,56.95,95.47,86.53,110.68,38.72,19.91,85.9,15.28,118.99-13.01,36.87024-31.5268,41.61425-78.76892,41.39306-102.67H894.752Zm-360.54,27.41c-22.21,60.97-54.61,89.49-82.4,102.65-33.81,16.01-74.1,11.56-103.12-12.03-35.08-28.52-39.75-72.35-39.62-94.69.06-8.88-.34-17.74-.69-26.61-2.77-69.71,101.83-70.53,101.83-70.53S580.722,499.72973,534.212,627.3797Zm83.38928-59.56537a424.54686,424.54686,0,0,0-65.69861,0c-5.48632-24.48639-23.97729-38.28705-45.937-45.84461H663.53824C641.57859,529.52728,623.08762,543.32794,617.60129,567.81433ZM862.202,596.3797c-.36,8.95-.76,17.9-.7,26.85.14,22.55-4.58,66.79-39.98,95.56-29.28,23.81-69.92005,28.31-104.03,12.17-28.06-13.27-60.78-42.05-83.21-103.62-46.93006-128.83,125.15-102.14,125.15-102.14S864.992,526.01971,862.202,596.3797Z" transform="translate(-24.21825 -28.87901)" fill="#3f3d56"/><path d="M428.14356,741.71275c-.11325-.18506-2.78356-4.64376-3.70932-13.90237-.84914-8.49429-.30313-22.81207,7.12226-42.7842,14.06719-37.83586-3.24186-68.36391-3.41872-68.668l.854-.49541a75.78134,75.78134,0,0,1,7.14973,20.25453,88.3638,88.3638,0,0,1-3.65968,49.253c-14.04309,37.77129-3.60282,55.65189-3.49584,55.82827Z" transform="translate(-24.21825 -28.87901)" fill="#3f3d56"/><circle cx="398.4247" cy="578.84223" r="6.41529" fill="#3f3d56"/><circle cx="418.65754" cy="602.52946" r="6.41529" fill="#3f3d56"/><circle cx="404.83999" cy="618.32095" r="6.41529" fill="#fff"/><circle cx="421.61845" cy="631.64502" r="6.41529" fill="#fff"/><circle cx="399.90515" cy="652.37134" r="6.41529" fill="#3f3d56"/><path d="M432.01914,741.94889s-6.41529-15.79149,12.83059-27.63511Z" transform="translate(-24.21825 -28.87901)" fill="#3f3d56"/><path d="M424.12933,741.66244s-2.91966-16.79294-25.51732-16.649Z" transform="translate(-24.21825 -28.87901)" fill="#3f3d56"/><path d="M363.072,370.10974a6.35543,6.35543,0,0,1-2.83,5.21l-.24.15h-106.8l.43-1.31c.07-.23,7.89-22.92005,42.5-18.54,3.26-1.12,35.12-11.52,54.19.17C358.782,360.96972,363.072,365.78973,363.072,370.10974Z" transform="translate(-24.21825 -28.87901)" fill="#f1f1f1"/><path d="M561.072,447.10974a6.35543,6.35543,0,0,1-2.83,5.21l-.24.15h-106.8l.43-1.31c.07-.23,7.89-22.92005,42.5-18.54,3.26-1.12,35.12-11.52,54.19.17C556.782,437.96972,561.072,442.78973,561.072,447.10974Z" transform="translate(-24.21825 -28.87901)" fill="#f1f1f1"/><path d="M606.072,137.10974a6.35543,6.35543,0,0,1-2.83,5.21l-.24.15h-106.8l.43-1.31c.07-.23,7.89-22.92,42.5-18.54,3.26-1.12,35.12-11.52,54.19.17C601.782,127.96972,606.072,132.78973,606.072,137.10974Z" transform="translate(-24.21825 -28.87901)" fill="#f1f1f1"/><path d="M53.17754,652.8835l9.13713,28.28159s-8.26692,26.54118-4.351,56.12807,1.7404,30.4571,1.7404,30.4571-39.12624-2.25247-35.21033,9.49526,42.172,4.86308,42.172,4.86308,7.34723-1.97821,10.828-22.86308S89.72606,698.134,89.72606,698.134l-8.22935-37.97489Z" transform="translate(-24.21825 -28.87901)" fill="#ffb8b8"/><path d="M56.22325,595.015S39.6894,601.10644,39.6894,617.64029s6.09142,39.15912,10.00733,40.46443,30.022,19.14446,34.80811,6.52652S56.22325,595.015,56.22325,595.015Z" transform="translate(-24.21825 -28.87901)" fill="#d0cde1"/><polygon points="170.367 761.932 205.175 760.626 231.717 756.71 223.885 782.816 159.49 784.557 170.367 761.932" fill="#ffb8b8"/><path d="M244.62214,794.29144s-.43511-9.57223-4.351-9.13713-1.3053-3.48081,2.17551-4.351,13.48814-5.22122,13.48814-5.22122l39.59422,2.61061S321.2,800.818,310.75754,813.0008s-37.41872,1.3053-37.41872,1.3053l-29.15179.4351S234.6148,799.07755,244.62214,794.29144Z" transform="translate(-24.21825 -28.87901)" fill="#2f2e41"/><polygon points="236.068 731.91 248.685 791.083 274.792 785.862 259.998 711.895 244.334 703.628 236.068 731.91" fill="#ffb8b8"/><path d="M110.17582,753.39191s-73.097,33.0677-42.20483,66.57051c0,0,0,15.66365,32.6326,12.61794s95.7223-8.702,98.768-6.96162,12.61793-34.373,4.351-36.11342-18.27426-3.91591-18.27426-3.91591,8.702-1.3053,8.702-8.702c0,0,24.80078-1.7404,32.1975-17.404S240.70622,732.072,240.70622,732.072l16.969,43.51013s19.57956-36.11341,34.373-20.01466c0,0-16.53385-103.98922-29.15179-113.56145s-21.32-12.61794-33.0677-3.91591-22.62527,30.89219-22.62527,30.89219Z" transform="translate(-24.21825 -28.87901)" fill="#2f2e41"/><path d="M284.65146,802.12326a98.03577,98.03577,0,0,0-8.702,7.39673c-3.48081,3.48081-8.26692,1.7404-8.702,0s-8.26692,1.3053-9.13712,13.92324-6.09142,23.93057,7.83182,27.84648,13.48814,15.22855,13.48814,15.22855a46.93427,46.93427,0,0,0,35.24321,2.17551c19.57956-6.52652,12.61794-13.48814,12.61794-13.48814l-26.10608-43.075S294.22369,799.07755,284.65146,802.12326Z" transform="translate(-24.21825 -28.87901)" fill="#2f2e41"/><path d="M212.42464,586.313s41.76972,14.35834,46.12074,17.404,23.93057,17.404,14.35834,24.80078-17.40405,12.18283-36.11341,6.52652S197.19609,611.984,197.19609,611.984Z" transform="translate(-24.21825 -28.87901)" fill="#ffb8b8"/><path d="M170.65491,567.16854s16.53385-3.04571,28.28158,3.48081,21.75507,19.57956,21.75507,19.57956S209.814,613.28928,201.9822,616.77009,179.792,602.84685,179.792,602.84685Z" transform="translate(-24.21825 -28.87901)" fill="#d0cde1"/><path d="M94.51217,554.5506s.4351,16.96895-1.3053,18.70936,20.88486,53.08236,45.68564,30.45709,5.65632-31.7624,5.65632-31.7624-9.13713-16.969-8.702-18.70936-40.46443,0-40.46443,0Z" transform="translate(-24.21825 -28.87901)" fill="#ffb8b8"/><path d="M94.51217,554.5506s.4351,16.96895-1.3053,18.70936,20.88486,53.08236,45.68564,30.45709,5.65632-31.7624,5.65632-31.7624-9.13713-16.969-8.702-18.70936-40.46443,0-40.46443,0Z" transform="translate(-24.21825 -28.87901)" opacity="0.1"/><path d="M101.47379,587.1832s16.53385,11.31263,23.49548,8.702,15.66364-13.92325,16.53385-14.79345,45.25054,88.32557,45.25054,88.32557-6.52652,32.6326-23.93058,42.20483-17.1865,17.18651-19.362,23.713-30.23954-20.66732-30.23954-20.66732L95.38237,638.96026V592.83952Z" transform="translate(-24.21825 -28.87901)" fill="#d0cde1"/><path d="M94.29462,566.951s-5.43877-1.08776-11.09508,3.69836S51.002,593.27462,52.30734,595.015s13.053,26.54118,15.66365,36.54852,6.52652,11.31263,6.52652,11.31263,9.13713,6.52652,7.83182,11.31264-6.96162,70.05131.87021,84.40966,6.52652,26.97628,4.351,30.45709,20.88486-10.00733,20.88486-10.00733,34.373-27.84649,36.98362-36.11341a97.263,97.263,0,0,0,3.48081-17.40406s-22.19017-87.89047-29.15179-92.67658S94.29462,566.951,94.29462,566.951Z" transform="translate(-24.21825 -28.87901)" fill="#575a89"/><path d="M142.0946,567.29509s10.72115-6.65307,12.89666-4.91267,22.62527,1.74041,23.06037,3.48081,1.3053,43.51014,16.09875,54.38767,5.22122,32.6326,5.22122,32.6326l10.87753,17.40406s-59.17285,56.99362-55.25787,37.41871c.21755-1.08775,0-1.3053,0-1.3053s-23.06037-98.768-20.01466-103.98922S143.55629,573.51306,142.0946,567.29509Z" transform="translate(-24.21825 -28.87901)" fill="#575a89"/><path d="M233.3095,607.19786l-59.17378,20.44976s-58.73868,13.92325-49.60156,30.022S172.39531,646.357,172.39531,646.357l78.7996-8.82909S282.476,611.11377,233.3095,607.19786Z" transform="translate(-24.21825 -28.87901)" fill="#ffb8b8"/><circle cx="93.78939" cy="509.57283" r="32.1975" fill="#ffb8b8"/><path d="M92.36668,506.4531l-5.95587-2.16578s12.45312-12.45312,29.77934-11.37019l-4.8731-4.873s11.91174-4.33148,22.74055,7.03872c5.69249,5.97707,12.27878,13.00279,16.38465,20.91719h6.37832l-2.66208,5.32415,9.31726,5.32415-9.56325-.95636a26.866,26.866,0,0,1-.90453,13.789l-2.16569,5.95579s-8.66312-17.32606-8.66312-19.49184v5.4144s-5.95587-4.87294-5.95587-8.12156l-3.24862,3.79009-1.62432-5.95587-20.0333,5.95587,3.24863-4.87294-12.45312,1.62431,4.8731-5.95587s-14.07744,7.03872-14.619,12.99459-7.58,13.536-7.58,13.536L81.538,538.93944S76.66493,514.57467,92.36668,506.4531Z" transform="translate(-24.21825 -28.87901)" fill="#2f2e41"/><path d="M146.61566,540.19858s1.05805,7.34674-4.02158,11.6902a10.68163,10.68163,0,0,1-11.82134,1.29251,14.7297,14.7297,0,0,1-4.40805-3.53378,18.98358,18.98358,0,0,1-1.516-2.01675,24.0899,24.0899,0,0,1-1.76144-3.21588q-.47687-1.04165-.911-2.22935c-.05564-.152-.1073-.301-.157-.449-2.63767-7.8395,2.49263-10.12648,7.20169-10.67488a24.18681,24.18681,0,0,1,2.97645-.15,26.68959,26.68959,0,0,1,3.49007.24639s.09637.001.27022.00794a20.96175,20.96175,0,0,1,2.67543.29706C142.2712,532.10177,147.83962,534.08077,146.61566,540.19858Z" transform="translate(-24.21825 -28.87901)" fill="#e6a23c"/><path d="M114.22842,542.18553c-2.31877,6.36518-5.65784,9.48469-8.59653,10.99576a10.68165,10.68165,0,0,1-11.82135-1.29251,10.38378,10.38378,0,0,1-.89412-.86134,10.81892,10.81892,0,0,1-1.49121-2.05252,12.78124,12.78124,0,0,1-1.2011-2.98936,16.04808,16.04808,0,0,1-.51363-3.5,14.00278,14.00278,0,0,1,.07848-2.287c-1.14547-5.72738,3.661-7.82659,7.26428-8.59554a21.39066,21.39066,0,0,1,3.16223-.42619c.3189-.01789.50171-.01888.50171-.01888a27.42839,27.42839,0,0,1,5.71942-.16989C111.41291,531.38944,117.37277,533.55522,114.22842,542.18553Z" transform="translate(-24.21825 -28.87901)" fill="#e6a23c"/><path d="M100.21547,531.17685l-9.99136,14.80871a16.04808,16.04808,0,0,1-.51363-3.5L97.05324,531.603A21.39066,21.39066,0,0,1,100.21547,531.17685Z" transform="translate(-24.21825 -28.87901)" fill="#fff" opacity="0.2"/><path d="M106.4366,530.98808,92.91642,551.02744a10.81892,10.81892,0,0,1-1.49121-2.05252l12.18-18.0524A26.08038,26.08038,0,0,1,106.4366,530.98808Z" transform="translate(-24.21825 -28.87901)" fill="#fff" opacity="0.2"/><path d="M132.19738,530.91158l-9.11016,13.5033q-.47687-1.04165-.911-2.22935c-.05564-.152-.1073-.301-.157-.449l7.20169-10.67488A24.18681,24.18681,0,0,1,132.19738,530.91158Z" transform="translate(-24.21825 -28.87901)" fill="#fff" opacity="0.2"/><path d="M138.6331,531.463l-12.26841,18.18454a18.98358,18.98358,0,0,1-1.516-2.01675l11.109-16.46485A20.96175,20.96175,0,0,1,138.6331,531.463Z" transform="translate(-24.21825 -28.87901)" fill="#fff" opacity="0.2"/><path d="M149,539.50315h-2.27379c1.0063-8.24976-11.03876-8.34518-11.03876-8.34518a27.46661,27.46661,0,0,0-5.76215-.166v-.03266H106.38v.02471a27.49535,27.49535,0,0,0-5.6628.174s-12.04507.09542-11.03876,8.34518H87.504v2.18564h2.19428c-.022,2.37451.44933,7.06789,4.11229,10.2a10.68165,10.68165,0,0,0,11.82135,1.29251c2.93869-1.51107,6.27776-4.63058,8.59653-10.99576a11.22868,11.22868,0,0,0,.802-5.37948,63.12484,63.12484,0,0,1,6.34375,0,11.22856,11.22856,0,0,0,.802,5.37948c2.31877,6.36518,5.65783,9.48469,8.59653,10.99576a10.68163,10.68163,0,0,0,11.82134-1.29251c3.663-3.1321,4.13427-7.82548,4.1123-10.2H149Zm-35.8187,2.72311c-2.20651,6.05721-5.42537,8.89059-8.18623,10.198a9.69145,9.69145,0,0,1-10.2447-1.19515c-3.48511-2.83339-3.94906-7.18778-3.93614-9.40721.006-.8822-.03378-1.76242-.06855-2.64363-.27519-6.92551,10.11654-7.007,10.11654-7.007S117.80194,529.54457,113.1813,542.22626Zm8.28451-5.91767a42.17881,42.17881,0,0,0-6.527,0c-.54505-2.43265-2.38208-3.80371-4.56371-4.55454h15.65441C123.84789,532.50488,122.01086,533.87594,121.46581,536.30859Zm24.30043,2.8379c-.03576.88916-.0755,1.77832-.06954,2.66748.01391,2.24028-.455,6.63541-3.97191,9.49363a9.77755,9.77755,0,0,1-10.33511,1.20906c-2.78768-1.31834-6.03833-4.17756-8.26669-10.29437-4.66238-12.79893,12.43332-10.14735,12.43332-10.14735S146.04342,532.15641,145.76624,539.14649Z" transform="translate(-24.21825 -28.87901)" fill="#3f3d56"/></svg> \ No newline at end of file diff --git a/src/assets/loginPage/arrow-r.png b/src/assets/loginPage/arrow-r.png new file mode 100644 index 0000000..1855c8c --- /dev/null +++ b/src/assets/loginPage/arrow-r.png Binary files differ diff --git a/src/assets/loginPage/back-icon.png b/src/assets/loginPage/back-icon.png new file mode 100644 index 0000000..ea6dea7 --- /dev/null +++ b/src/assets/loginPage/back-icon.png Binary files differ diff --git a/src/assets/loginPage/device-pic.png b/src/assets/loginPage/device-pic.png new file mode 100644 index 0000000..c52a119 --- /dev/null +++ b/src/assets/loginPage/device-pic.png Binary files differ diff --git a/src/assets/loginPage/equipment.JPG b/src/assets/loginPage/equipment.JPG new file mode 100644 index 0000000..301d435 --- /dev/null +++ b/src/assets/loginPage/equipment.JPG Binary files differ diff --git a/src/assets/loginPage/login-bg.jpg b/src/assets/loginPage/login-bg.jpg new file mode 100644 index 0000000..6427cb6 --- /dev/null +++ b/src/assets/loginPage/login-bg.jpg Binary files differ diff --git a/src/assets/loginPage/login-bg.png b/src/assets/loginPage/login-bg.png new file mode 100644 index 0000000..71fd539 --- /dev/null +++ b/src/assets/loginPage/login-bg.png Binary files differ diff --git a/src/assets/loginPage/login_icon_password.png b/src/assets/loginPage/login_icon_password.png new file mode 100644 index 0000000..1f6653d --- /dev/null +++ b/src/assets/loginPage/login_icon_password.png Binary files differ diff --git a/src/assets/loginPage/login_icon_user.png b/src/assets/loginPage/login_icon_user.png new file mode 100644 index 0000000..a113a9b --- /dev/null +++ b/src/assets/loginPage/login_icon_user.png Binary files differ diff --git a/src/assets/loginPage/map-bg.jpg b/src/assets/loginPage/map-bg.jpg new file mode 100644 index 0000000..d8d3715 --- /dev/null +++ b/src/assets/loginPage/map-bg.jpg Binary files differ diff --git a/src/assets/loginPage/map-bg.png b/src/assets/loginPage/map-bg.png new file mode 100644 index 0000000..e642a41 --- /dev/null +++ b/src/assets/loginPage/map-bg.png Binary files differ diff --git a/src/assets/loginPage/star-bg.png b/src/assets/loginPage/star-bg.png new file mode 100644 index 0000000..a707818 --- /dev/null +++ b/src/assets/loginPage/star-bg.png Binary files differ diff --git a/src/assets/loginPage/task-job-pic.png b/src/assets/loginPage/task-job-pic.png new file mode 100644 index 0000000..610bf09 --- /dev/null +++ b/src/assets/loginPage/task-job-pic.png Binary files differ diff --git a/src/assets/loginPage/watersys.JPG b/src/assets/loginPage/watersys.JPG new file mode 100644 index 0000000..dc1c159 --- /dev/null +++ b/src/assets/loginPage/watersys.JPG Binary files differ diff --git a/src/assets/loginPage/wind.JPG b/src/assets/loginPage/wind.JPG new file mode 100644 index 0000000..2def54d --- /dev/null +++ b/src/assets/loginPage/wind.JPG Binary files differ diff --git a/src/assets/loginPage/xj-bg.png b/src/assets/loginPage/xj-bg.png new file mode 100644 index 0000000..e2317d1 --- /dev/null +++ b/src/assets/loginPage/xj-bg.png Binary files differ diff --git a/src/assets/loginPage/xj-icon.png b/src/assets/loginPage/xj-icon.png new file mode 100644 index 0000000..a82b8fc --- /dev/null +++ b/src/assets/loginPage/xj-icon.png Binary files differ diff --git a/src/assets/logo-mini.svg b/src/assets/logo-mini.svg new file mode 100644 index 0000000..53df94c --- /dev/null +++ b/src/assets/logo-mini.svg @@ -0,0 +1,9 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 50" width="64" height="50"> + <defs> + <image width="64" height="50" id="img1" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAAAyCAYAAADsg90UAAAAAXNSR0IB2cksfwAACI5JREFUeJy1WgtsW9UZdvNq0xU6WhZoCCVx7Gunbld1GSsMdYpGREhwr+2IMbQWqRoTk+iWPZi2wWhm1kwEmqV52feRJrbvvd6DiUnbQCAemzY2xh4tSB0wOqZIqAtLYzultIWEpt13btLq+sap/R8nRzpK4vh+5/++85///8851yEk1V+hX6B0tyE3OWwt0x789VR78AKlZ0KBz1oxBE3+BdUW9PNuQ7nJbk/BDQ/v4hi0x44z1R64jyrAVCjQ/fLNN8/ZoUWdgqGc57AFE6I86giH+QRw6XI9QE4RBz3iTAyVW3EyQdEDUmeIIhyeFNtMHO/o0B4e8qYASfVvLk2p4BKgdnioFCAvEQeddhnyFivOpOgvBaFXiAKcygQDrk927S/zjkae5xUA/X3YI/C5AFwHLrSPw+2+YYfCMugiCvDaCbGt0hc9uAXuP1OEAPACZQ+fAGguQ9nGgglx0OfsOAhq24lBcG/YYQa/kWLIz3XlCW4B6mKRCoCMEQdNu3VpnRVnMhBYA2L/LVCATCooXuNJSHXFzv58P+mMyyu5RQDAKNntdLnNjoN0+NMCM0D8901NDkGXuyBAseRZn3Ubagu3AFjTd1GXAdZdpCqurMgSIBS4BwRn8wgwje/d4pV6yz2adGQJyM/bo/ZyC+DSlWqApIiDHqtPyFdlCyBeD4Lv5xHgr5mAWO4ZjTRh9s8tlQDoryIbrOISoLYvvAIALxIHnIHn3GnFmfDfztLhH/IEv/vYd72xyKElJM/6Gdjj4fYCuNA3yYMa6ogdBwQfvIwAk+mguHZz3+MbMPsfLrEALD3v5RfAkH3UOID+Jqqwj2ULIDZeJvhF2He8I0NfX2ry8wI85VSy41LBzaUPsXT4L/Iy0OUbrTgpsXUlyI7lEOAsvGOboPRdKejK28shAPqpek1etxjHArxAiXCo/pAdB2QPLRQg8BLcv8ITi4h4bnaZBGD2+IsQQG0DCDUyv2LfjcHVQyB93iLAecz+bvY/T1x6YrnImwIkVakIAeSrAfIucdCz7qRcY8VJh8RrQDplWfvHxttaVvkGe6vg/h8tpwDoR926wpcOb9CkEhQ4Mbrqym4rTkrcydLhs5bU95Wwwwx+311m8qxPQ4CtvE6AdKjcLlCrQkNJXNXdnYUD0t+eF+AE1v76rV0/qvTEo/8kkkGJq/yFLIKhPsgtgEszl8E4cdAxPHdllgDBwGZW9k6Fguaa9A4PtMEwkrDe0chhCPAZ/E5dNn/kPiWqGe5mVSH1rJCdze2w4rDNDsi/gdn/FPtb0KTfUmeyQenvuE45WCLQd6unsc3fwKeAw0yHX+Zwu247DpbB3emQv3R7x7du8GgybdtrKGc39Ty23rQnqfKk5y9wCwD1XACZJg56xGUMZFVhx1taytjPBnWAfuihyT+3TEiAQwC1Mhzmqwrr9QhbBoeJg36A6Ou0Y/kGe2qQ+mhiGspHDcODTZfs0eRr8fkE0Z4xpyGt4RJgTnX1carq8Jw9dhzv6BB5k+VJyK9t6+y8dNK74bGHMSHK00Scc/CC7fwC6MotAjX6GuqTzsTBkosYW/f9YKUnIb1OFiAW/c4Ce5Lq18jLKKnu5xaApTWBHn0n8Nz6ixhw4zvJ5HXlvU2R3gWui02XizwhrEznbTW9vQ64nUEckBUut13EQOHzFFUA70jErBv+09xcYrXHqUXK8H9qIXXapSs1dm4FN1SF95DdzlD72LMNUt/15CMvXT65NfzIRtQOq5FCv7jAHkPppdqDZ3YvZFZgY8WEQN8dvvFxpB8hLvWT3T8uyWxckG9CEfX38fk0ahGgmboMMIk/2xg5UJKbYZ62sf9RbI7UPxGJzLgT0R2Y/RM0z1HO+QZ6Gl/3+dh2Wmdb6HQwUJc9IfI6fPc40Z5xCLeW2wvw8Pfoy0B5mfoMAuYLn+7oKE0FxZqp+YvWTHugw24PvvtLIjZLh83cAghzmxHqASb5qntz/4EvsfEy7UHroepvJoKtWdUcPPKrVGwsA6k2FuYTAPXAGoC8RfYCStflqRvv3VuB4Hc1SI9bBJjAZ1VWe+p1+TqBHpfG+M8Ksa0EgLacAnhiETNzIPjdbztLPIfPWrME0CSkQ+UfxDFmkQ5v5RPAYcYBckFTcDfUWc+hwZsw06tA+EiOi5RoDns66ctA/Qm3AE4tuhYgZ5Zl9uPR32165PtlINoMwjM5jtPfSvn9WTe/iEufw7PUW+U3a2NSKZ8CTU0s+DyzHAJgq9yuNDaywxNtkQuVWaTDBqs5SIdsQt4hjsXOCvmvzrDu6Fdnebo3Hj3u69xXngoFqkH09KL3ie2BB6y2XCsfZNt1apnOqsL7uY/KoB57k+SDJRUhIZlX2iD4UJ4b5ef+3dqabY9hlunUdPt0XXyIryqs1yKVAv3qbPFuKNNedaAR5FeD4NE8AqRTwZ1ZmxqnHv0EcI4Rxz3hNqSqxThevrEXqpJq31IJgOD3TN3+h0tYmmPpLt9bJex80W4SRBzmEF7kE8Bhbo5aONwutwCx6K4JUVyByu/JfOTn+6EFAiTNN1uoAgxyC1BvqFcAZLJo8pr8rlvuq8wExfpFUl+u/s7/dt6R9UKkS5ergHeaOP6Yc2SQLw7Mqa6SDznsHakvzLAyoeAPCyRvVoXpUGCb1ZZqRWFnhdQXPWcg3Jac5App7C2MImf/5Kb+nupJ0X8FSL1NEOACEyyHPQ9QbWA73CIEkBuEIqrCzUO9CsNB6esCqQ8pAqD/Oe33l9vs2SLQd6svuhJSWW6GeVptLFKGbMD9eltjZ2cjw5m4o60ChF4lCvBeJhjIuntAYF4N3KNEO9Lwgmo+F/D5mNt1cbr/2OeD916qx+HSB4gCsDdNdmXZM7dbjRJtYXeZd/EJ4DDX3Q4uARLSj604yO23UgVA2jRy2EO+OkNX/w+fZNm8pw5QbAAAAABJRU5ErkJggg=="/> + </defs> + <style> + tspan { white-space:pre } + </style> + <use id="Background" href="#img1" x="0" y="0" /> +</svg> \ No newline at end of file diff --git a/src/assets/menu/admin.png b/src/assets/menu/admin.png new file mode 100644 index 0000000..55eeace --- /dev/null +++ b/src/assets/menu/admin.png Binary files differ diff --git a/src/assets/menu/bg_home.jpg b/src/assets/menu/bg_home.jpg new file mode 100644 index 0000000..c8b3afd --- /dev/null +++ b/src/assets/menu/bg_home.jpg Binary files differ diff --git a/src/assets/menu/bg_home1.jpg b/src/assets/menu/bg_home1.jpg new file mode 100644 index 0000000..b4389fb --- /dev/null +++ b/src/assets/menu/bg_home1.jpg Binary files differ diff --git a/src/assets/menu/card1.png b/src/assets/menu/card1.png new file mode 100644 index 0000000..d70d653 --- /dev/null +++ b/src/assets/menu/card1.png Binary files differ diff --git a/src/assets/menu/card10.png b/src/assets/menu/card10.png new file mode 100644 index 0000000..cb8129f --- /dev/null +++ b/src/assets/menu/card10.png Binary files differ diff --git a/src/assets/menu/card11.png b/src/assets/menu/card11.png new file mode 100644 index 0000000..2155f53 --- /dev/null +++ b/src/assets/menu/card11.png Binary files differ diff --git a/src/assets/menu/card2.png b/src/assets/menu/card2.png new file mode 100644 index 0000000..9415cb6 --- /dev/null +++ b/src/assets/menu/card2.png Binary files differ diff --git a/src/assets/menu/card3.png b/src/assets/menu/card3.png new file mode 100644 index 0000000..b22eae4 --- /dev/null +++ b/src/assets/menu/card3.png Binary files differ diff --git a/src/assets/menu/card4.png b/src/assets/menu/card4.png new file mode 100644 index 0000000..d29a9f4 --- /dev/null +++ b/src/assets/menu/card4.png Binary files differ diff --git a/src/assets/menu/card5.png b/src/assets/menu/card5.png new file mode 100644 index 0000000..ee12eb6 --- /dev/null +++ b/src/assets/menu/card5.png Binary files differ diff --git a/src/assets/menu/card6.png b/src/assets/menu/card6.png new file mode 100644 index 0000000..cc7d602 --- /dev/null +++ b/src/assets/menu/card6.png Binary files differ diff --git a/src/assets/menu/card7.png b/src/assets/menu/card7.png new file mode 100644 index 0000000..d5bf656 --- /dev/null +++ b/src/assets/menu/card7.png Binary files differ diff --git a/src/assets/menu/card8.png b/src/assets/menu/card8.png new file mode 100644 index 0000000..a839c27 --- /dev/null +++ b/src/assets/menu/card8.png Binary files differ diff --git a/src/assets/menu/card9.png b/src/assets/menu/card9.png new file mode 100644 index 0000000..7481ef0 --- /dev/null +++ b/src/assets/menu/card9.png Binary files differ diff --git a/src/assets/menu/companyLogo.png b/src/assets/menu/companyLogo.png new file mode 100644 index 0000000..0f9f2d1 --- /dev/null +++ b/src/assets/menu/companyLogo.png Binary files differ diff --git a/src/assets/menu/icon1.png b/src/assets/menu/icon1.png new file mode 100644 index 0000000..bef5341 --- /dev/null +++ b/src/assets/menu/icon1.png Binary files differ diff --git a/src/assets/menu/icon10.png b/src/assets/menu/icon10.png new file mode 100644 index 0000000..0f1d961 --- /dev/null +++ b/src/assets/menu/icon10.png Binary files differ diff --git a/src/assets/menu/icon11.png b/src/assets/menu/icon11.png new file mode 100644 index 0000000..392b926 --- /dev/null +++ b/src/assets/menu/icon11.png Binary files differ diff --git a/src/assets/menu/icon2.png b/src/assets/menu/icon2.png new file mode 100644 index 0000000..5ca9d63 --- /dev/null +++ b/src/assets/menu/icon2.png Binary files differ diff --git a/src/assets/menu/icon3.png b/src/assets/menu/icon3.png new file mode 100644 index 0000000..c512b58 --- /dev/null +++ b/src/assets/menu/icon3.png Binary files differ diff --git a/src/assets/menu/icon4.png b/src/assets/menu/icon4.png new file mode 100644 index 0000000..1088209 --- /dev/null +++ b/src/assets/menu/icon4.png Binary files differ diff --git a/src/assets/menu/icon5.png b/src/assets/menu/icon5.png new file mode 100644 index 0000000..28200e7 --- /dev/null +++ b/src/assets/menu/icon5.png Binary files differ diff --git a/src/assets/menu/icon6.png b/src/assets/menu/icon6.png new file mode 100644 index 0000000..c58c489 --- /dev/null +++ b/src/assets/menu/icon6.png Binary files differ diff --git a/src/assets/menu/icon7.png b/src/assets/menu/icon7.png new file mode 100644 index 0000000..838cb9a --- /dev/null +++ b/src/assets/menu/icon7.png Binary files differ diff --git a/src/assets/menu/icon8.png b/src/assets/menu/icon8.png new file mode 100644 index 0000000..0e7d42f --- /dev/null +++ b/src/assets/menu/icon8.png Binary files differ diff --git a/src/assets/menu/icon9.png b/src/assets/menu/icon9.png new file mode 100644 index 0000000..ce58f60 --- /dev/null +++ b/src/assets/menu/icon9.png Binary files differ diff --git a/src/assets/methods/index.ts b/src/assets/methods/index.ts new file mode 100644 index 0000000..c994fa6 --- /dev/null +++ b/src/assets/methods/index.ts @@ -0,0 +1,15 @@ +import { userApi } from '/@/api/systemManage/user'; +import { ElMessage } from 'element-plus'; + +export async function getUserByDepartment(value: number | null) { + let res = await userApi().getUserLByDepartment(value); + if (res.data.code === '200') { + return res.data.data; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + return []; + } +} diff --git a/src/assets/newMenu/card-1.png b/src/assets/newMenu/card-1.png new file mode 100644 index 0000000..eb8fa9b --- /dev/null +++ b/src/assets/newMenu/card-1.png Binary files differ diff --git a/src/assets/newMenu/card-10.png b/src/assets/newMenu/card-10.png new file mode 100644 index 0000000..e80c260 --- /dev/null +++ b/src/assets/newMenu/card-10.png Binary files differ diff --git a/src/assets/newMenu/card-11.png b/src/assets/newMenu/card-11.png new file mode 100644 index 0000000..7ae2a5e --- /dev/null +++ b/src/assets/newMenu/card-11.png Binary files differ diff --git a/src/assets/newMenu/card-2.png b/src/assets/newMenu/card-2.png new file mode 100644 index 0000000..7261d75 --- /dev/null +++ b/src/assets/newMenu/card-2.png Binary files differ diff --git a/src/assets/newMenu/card-3.png b/src/assets/newMenu/card-3.png new file mode 100644 index 0000000..6ea4da0 --- /dev/null +++ b/src/assets/newMenu/card-3.png Binary files differ diff --git a/src/assets/newMenu/card-4.png b/src/assets/newMenu/card-4.png new file mode 100644 index 0000000..bf5f61b --- /dev/null +++ b/src/assets/newMenu/card-4.png Binary files differ diff --git a/src/assets/newMenu/card-5.png b/src/assets/newMenu/card-5.png new file mode 100644 index 0000000..adde896 --- /dev/null +++ b/src/assets/newMenu/card-5.png Binary files differ diff --git a/src/assets/newMenu/card-6.png b/src/assets/newMenu/card-6.png new file mode 100644 index 0000000..83a90cc --- /dev/null +++ b/src/assets/newMenu/card-6.png Binary files differ diff --git a/src/assets/newMenu/card-7.png b/src/assets/newMenu/card-7.png new file mode 100644 index 0000000..676e989 --- /dev/null +++ b/src/assets/newMenu/card-7.png Binary files differ diff --git a/src/assets/newMenu/card-8.png b/src/assets/newMenu/card-8.png new file mode 100644 index 0000000..95e0528 --- /dev/null +++ b/src/assets/newMenu/card-8.png Binary files differ diff --git a/src/assets/newMenu/card-9.png b/src/assets/newMenu/card-9.png new file mode 100644 index 0000000..c8024f0 --- /dev/null +++ b/src/assets/newMenu/card-9.png Binary files differ diff --git a/src/assets/newMenu/icon1.png b/src/assets/newMenu/icon1.png new file mode 100644 index 0000000..99f305d --- /dev/null +++ b/src/assets/newMenu/icon1.png Binary files differ diff --git a/src/assets/newMenu/icon10.png b/src/assets/newMenu/icon10.png new file mode 100644 index 0000000..f7ae382 --- /dev/null +++ b/src/assets/newMenu/icon10.png Binary files differ diff --git a/src/assets/newMenu/icon11.png b/src/assets/newMenu/icon11.png new file mode 100644 index 0000000..a19d8da --- /dev/null +++ b/src/assets/newMenu/icon11.png Binary files differ diff --git a/src/assets/newMenu/icon2.png b/src/assets/newMenu/icon2.png new file mode 100644 index 0000000..1b2dae3 --- /dev/null +++ b/src/assets/newMenu/icon2.png Binary files differ diff --git a/src/assets/newMenu/icon3.png b/src/assets/newMenu/icon3.png new file mode 100644 index 0000000..9097055 --- /dev/null +++ b/src/assets/newMenu/icon3.png Binary files differ diff --git a/src/assets/newMenu/icon4.png b/src/assets/newMenu/icon4.png new file mode 100644 index 0000000..23ad0da --- /dev/null +++ b/src/assets/newMenu/icon4.png Binary files differ diff --git a/src/assets/newMenu/icon5.png b/src/assets/newMenu/icon5.png new file mode 100644 index 0000000..71c54e5 --- /dev/null +++ b/src/assets/newMenu/icon5.png Binary files differ diff --git a/src/assets/newMenu/icon6.png b/src/assets/newMenu/icon6.png new file mode 100644 index 0000000..cbad202 --- /dev/null +++ b/src/assets/newMenu/icon6.png Binary files differ diff --git a/src/assets/newMenu/icon7.png b/src/assets/newMenu/icon7.png new file mode 100644 index 0000000..34e62ed --- /dev/null +++ b/src/assets/newMenu/icon7.png Binary files differ diff --git a/src/assets/newMenu/icon8.png b/src/assets/newMenu/icon8.png new file mode 100644 index 0000000..9c8d052 --- /dev/null +++ b/src/assets/newMenu/icon8.png Binary files differ diff --git a/src/assets/newMenu/icon9.png b/src/assets/newMenu/icon9.png new file mode 100644 index 0000000..cb1199e --- /dev/null +++ b/src/assets/newMenu/icon9.png Binary files differ diff --git a/src/assets/newMenu/leftbg.jpg b/src/assets/newMenu/leftbg.jpg new file mode 100644 index 0000000..cdfc4f8 --- /dev/null +++ b/src/assets/newMenu/leftbg.jpg Binary files differ diff --git a/src/assets/newMenu/leftbg.png b/src/assets/newMenu/leftbg.png new file mode 100644 index 0000000..61eab20 --- /dev/null +++ b/src/assets/newMenu/leftbg.png Binary files differ diff --git a/src/assets/newMenu/pic_line1.png b/src/assets/newMenu/pic_line1.png new file mode 100644 index 0000000..4212982 --- /dev/null +++ b/src/assets/newMenu/pic_line1.png Binary files differ diff --git a/src/assets/newMenu/pic_line2.png b/src/assets/newMenu/pic_line2.png new file mode 100644 index 0000000..b6a65a5 --- /dev/null +++ b/src/assets/newMenu/pic_line2.png Binary files differ diff --git a/src/assets/newMenu/topbg.jpg b/src/assets/newMenu/topbg.jpg new file mode 100644 index 0000000..3d2dd9c --- /dev/null +++ b/src/assets/newMenu/topbg.jpg Binary files differ diff --git a/src/assets/newMenu/toplogo.png b/src/assets/newMenu/toplogo.png new file mode 100644 index 0000000..8f50c3d --- /dev/null +++ b/src/assets/newMenu/toplogo.png Binary files differ diff --git a/src/assets/style/index.scss b/src/assets/style/index.scss new file mode 100644 index 0000000..1503233 --- /dev/null +++ b/src/assets/style/index.scss @@ -0,0 +1,19 @@ +.input-box{ + width: 200px !important; + padding-right: 10px; + padding-bottom: 10px; +} +.input-box2{ + width: 200px !important; + padding-right: 10px; +} +.input-add{ + width: 90% !important; +} +.basic-line{ + display: inline-block; + padding-left: 10px; +} +.page-position{ + float: right; +} diff --git a/src/assets/warningScreen/body-bg.jpg b/src/assets/warningScreen/body-bg.jpg new file mode 100644 index 0000000..92def2a --- /dev/null +++ b/src/assets/warningScreen/body-bg.jpg Binary files differ diff --git a/src/assets/warningScreen/logo_dark.png b/src/assets/warningScreen/logo_dark.png new file mode 100644 index 0000000..96a4d41 --- /dev/null +++ b/src/assets/warningScreen/logo_dark.png Binary files differ diff --git a/src/assets/warningScreen/logo_light.png b/src/assets/warningScreen/logo_light.png new file mode 100644 index 0000000..ae1f11c --- /dev/null +++ b/src/assets/warningScreen/logo_light.png Binary files differ diff --git a/src/assets/warningScreen/pagebg-l-light.png b/src/assets/warningScreen/pagebg-l-light.png new file mode 100644 index 0000000..8986559 --- /dev/null +++ b/src/assets/warningScreen/pagebg-l-light.png Binary files differ diff --git a/src/assets/warningScreen/pagebg-l.png b/src/assets/warningScreen/pagebg-l.png new file mode 100644 index 0000000..c630e6f --- /dev/null +++ b/src/assets/warningScreen/pagebg-l.png Binary files differ diff --git a/src/assets/warningScreen/pagebg-r-light.png b/src/assets/warningScreen/pagebg-r-light.png new file mode 100644 index 0000000..4f74fe3 --- /dev/null +++ b/src/assets/warningScreen/pagebg-r-light.png Binary files differ diff --git a/src/assets/warningScreen/pagebg-r.png b/src/assets/warningScreen/pagebg-r.png new file mode 100644 index 0000000..26976dc --- /dev/null +++ b/src/assets/warningScreen/pagebg-r.png Binary files differ diff --git a/src/assets/warningScreen/pagebg-t-light.png b/src/assets/warningScreen/pagebg-t-light.png new file mode 100644 index 0000000..57372d2 --- /dev/null +++ b/src/assets/warningScreen/pagebg-t-light.png Binary files differ diff --git a/src/assets/warningScreen/pagebg-t.png b/src/assets/warningScreen/pagebg-t.png new file mode 100644 index 0000000..dd132ec --- /dev/null +++ b/src/assets/warningScreen/pagebg-t.png Binary files differ diff --git a/src/assets/warningScreen/riskprocast-light.jpg b/src/assets/warningScreen/riskprocast-light.jpg new file mode 100644 index 0000000..e82b553 --- /dev/null +++ b/src/assets/warningScreen/riskprocast-light.jpg Binary files differ diff --git a/src/assets/warningScreen/riskprocast.jpg b/src/assets/warningScreen/riskprocast.jpg new file mode 100644 index 0000000..e2cc4b9 --- /dev/null +++ b/src/assets/warningScreen/riskprocast.jpg Binary files differ diff --git a/src/assets/warningScreen/skin-light.png b/src/assets/warningScreen/skin-light.png new file mode 100644 index 0000000..8f6500d --- /dev/null +++ b/src/assets/warningScreen/skin-light.png Binary files differ diff --git a/src/assets/warningScreen/skin.png b/src/assets/warningScreen/skin.png new file mode 100644 index 0000000..5736022 --- /dev/null +++ b/src/assets/warningScreen/skin.png Binary files differ diff --git a/src/assets/warningScreen/small-full.png b/src/assets/warningScreen/small-full.png new file mode 100644 index 0000000..d985854 --- /dev/null +++ b/src/assets/warningScreen/small-full.png Binary files differ diff --git a/src/assets/warningScreen/video.png b/src/assets/warningScreen/video.png new file mode 100644 index 0000000..b68fec6 --- /dev/null +++ b/src/assets/warningScreen/video.png Binary files differ diff --git a/src/components/DailogClass/index.vue b/src/components/DailogClass/index.vue new file mode 100644 index 0000000..f629089 --- /dev/null +++ b/src/components/DailogClass/index.vue @@ -0,0 +1,147 @@ +<template> + <el-dialog v-model="dialogVisible" @close="resetForm(ruleFormRef)" :fullscreen="full" :title="titles" width="30%" draggable> + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-form :model="form" ref="ruleFormRef" :rules="rules" :disabled="disabled" label-width="120px"> + <el-row> + <el-col :span="20"> + <el-form-item label="名称" size="default" prop="typeName"> + <el-input v-model="form.typeName" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="20"> + <el-form-item label="描述" size="default" prop="memo"> + <el-input v-model="form.memo" type="textarea" /> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="resetForm(ruleFormRef)" size="default">关闭</el-button> + <el-button type="primary" v-if="disabled == false" @click="submitForm(ruleFormRef)" size="default">确定</el-button> + </span> + </template> + </el-dialog> +</template> +<script lang="ts"> +import { defineComponent, ref, reactive } from 'vue'; +import { timeDate } from '/@/assets/index.ts'; +import type { FormInstance, FormRules } from 'element-plus'; +import { Search, FullScreen } from '@element-plus/icons-vue'; +import { ElMessageBox, ElMessage, ElButton, ElInput, TabsPaneContext } from 'element-plus'; +import { goalManagementApi } from '/@/api/goalManagement'; +export default defineComponent({ + components: {}, + setup(props, { emit }) { + const ruleFormRef = ref<FormInstance>(); + const dialogVisible = ref<boolean>(false); + const form = ref({ + typeName: '', + memo: '', + }); + const targetType = ref(); + const disabled = ref(false); + const titles = ref(); + const titleT=ref() + const openDailog = (title: string, type: any, id: number) => { + dialogVisible.value = true; + titles.value = `${title}目标分解`; + titleT.value=title + targetType.value = type; + disabled.value = title == '查看' ? true : false; + if (title == '查看' || title == '修改') { + goalManagementApi() + .gettargetClassDetail(id) + .then((res) => { + if (res.data.code == 200) { + form.value = res.data.data; + } else { + ElMessage.error(res.data.msg); + } + }); + } + }; + const rules = reactive<FormRules>({ + typeName: [ + { + required: true, + message: '名称不能为空', + trigger: 'blur', + }, + ], + memo: [ + { + required: true, + message: '描述不能为空', + trigger: 'blur', + }, + ], + }); + const submitForm = async (formEl: FormInstance | undefined) => { + if (!formEl) return; + await formEl.validate((valid, fields) => { + if (valid) { + if(titleT.value=='新建'){ + delete form.value.id + } + dialogVisible.value = false; + goalManagementApi() + .gettargetClassAdd(form.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + message: res.data.msg, + type: 'success', + }); + emit('onAdd'); + } else { + ElMessage.error(res.data.msg); + } + }); + } else { + console.log('error submit!', fields); + } + }); + }; + const resetForm = (formEl: FormInstance | undefined) => { + if (!formEl) return; + formEl.resetFields(); + dialogVisible.value = false; + }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + return { + timeDate, + ruleFormRef, + titleT, + rules, + submitForm, + resetForm, + form, + dialogVisible, + openDailog, + Search, + full, + toggleFullscreen, + FullScreen, + targetType, + disabled, + titles, + }; + }, +}); +</script> +<style scoped> +.el-row { + padding: 0 0 20px 0; +} +</style> \ No newline at end of file diff --git a/src/components/DailogSearch/DailogSearch.vue b/src/components/DailogSearch/DailogSearch.vue new file mode 100644 index 0000000..fcf71a6 --- /dev/null +++ b/src/components/DailogSearch/DailogSearch.vue @@ -0,0 +1,193 @@ +<template> + <el-dialog v-model="dialogVisible" :fullscreen="full" title="选择安全目标指标" width="50%" draggable> + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-row> + <el-col :span="17"> + <el-form ref="ruleFormRef" :model="ruleForm" status-icon> + <el-row> + <el-col :span="6"> + <el-form-item size="default"> + <el-input v-model="ruleForm.searchParams.qName" placeholder="安全目标指标" /> + </el-form-item> + </el-col> + <el-col :span="6" :offset="1"> + <el-form-item size="default"> + <el-input v-model="ruleForm.searchParams.indexNum" placeholder="目标指标编号" /> + </el-form-item> + </el-col> + <el-col :span="10" :offset="1"> + <el-form-item> + <el-button size="default" type="primary" @click="listApi">查询</el-button> + <el-button size="default" @click="resetForm">重置</el-button> + </el-form-item> + </el-col> + </el-row> + </el-form> + <el-button size="default" :icon="Delete" @click="clear">清除选择</el-button> + <el-table :data="tableData" style="width: 100%; margin-top: 20px"> + <el-table-column align="center"> + <template #default="scope"> + <el-radio-group v-model="radio1"> + <el-radio :label="scope.row.id" @click="radio(scope.row)" size="large">{{ null }}</el-radio> + </el-radio-group> + </template> + </el-table-column> + <el-table-column align="center" prop="qName" label="安全目标指标" width="180" /> + <el-table-column align="center" prop="indexNum" label="目标指标编号" width="180" /> + <el-table-column align="center" prop="year" label="年度" /> + <el-table-column align="center" prop="value" label="指标值" /> + </el-table> + <el-pagination + style="padding: 20px 0; border-bottom: 1px solid #dedede" + v-model:currentPage="currentPage4" + v-model:page-size="pageSize4" + :page-sizes="[10, 20, 30, 40]" + layout="total, sizes, prev, pager, next, jumper" + :total="total" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </el-col> + <el-col :span="7"> + <div v-if="dynamicTags[0]==''?false:true"> + <el-tag + v-for="tag in dynamicTags" + :key="tag" + class="mx-1" + style="margin: 5px" + closable + :disable-transitions="false" + @close="handleClose(tag)" + > + {{ tag.qName }} + </el-tag> + </div> + </el-col> + </el-row> + <template #footer> + <span class="dialog-footer"> + <el-button @click="dialogVisible = false" size="default">关闭</el-button> + <el-button type="primary" @click="submitForm" size="default">确定</el-button> + </span> + </template> + </el-dialog> +</template> +<script lang="ts"> +import { defineComponent, reactive, ref, onMounted } from 'vue'; +import { Delete, FullScreen } from '@element-plus/icons-vue'; +import { ElMessageBox, ElMessage, ElButton, ElInput, TabsPaneContext, FormInstance } from 'element-plus'; +import { goalManagementApi } from '/@/api/goalManagement'; +export default defineComponent({ + setup(props,{emit}) { + const dialogVisible = ref<boolean>(false); + const openDailog = (type:any) => { + dialogVisible.value = true; + ruleForm.searchParams.targetType=type + listApi(); + }; + // 搜索条件 + const ruleForm = reactive({ + pageSize: 10, + pageIndex: 1, + searchParams: { + qName: '', ////安全目标指标 + indexNum: '', ////目标指标编号 + targetType: '', ////指标类型 1:年指标 2:月指标 + divideStatus: '2', ////分解状态 1:已分解 2:未分解 + }, + }); + // 下方导航与表格 + const tableData = ref([]); + const currentPage4 = ref(); + const pageSize4 = ref(); + const total = ref(); + const resetForm = () => { + ruleForm.searchParams.qName = ''; + ruleForm.searchParams.indexNum = ''; + }; + const listApi = () => { + goalManagementApi() + .getTargetMngList(ruleForm) + .then((res) => { + if (res.data.code == 200) { + tableData.value = res.data.data; + currentPage4.value = res.data.pageIndex; + pageSize4.value = res.data.pageSize; + total.value = res.data.total; + } else { + ElMessage.error(res.data.msg); + } + }); + }; + onMounted(() => { + }); + + const handleSizeChange = (val: number) => { + // console.log(`${val} items per page`); + ruleForm.pageSize = val; + listApi(); + }; + const handleCurrentChange = (val: number) => { + // console.log(`current page: ${val}`); + ruleForm.pageIndex = val; + listApi(); + }; + // 右方点击添加后显示标签 + const dynamicTags = ref(['']); + const handleClose = (tag: string) => { + dynamicTags.value.splice(dynamicTags.value.indexOf(tag), 1); + radio1.value = ''; + }; + const radio1 = ref(''); + const radio = (data: any) => { + dynamicTags.value[0] = data; + }; + const clear=()=>{ + dynamicTags.value=[''] + radio1.value="" + } + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + const submitForm=()=>{ + let obj=JSON.parse(JSON.stringify(dynamicTags.value)) + emit("backNum",obj[0]) + dialogVisible.value = false + } + return { + dialogVisible, + openDailog, + ruleForm, + tableData, + currentPage4, + total, + pageSize4, + resetForm, + listApi, + handleSizeChange, + handleCurrentChange, + dynamicTags, + handleClose, + radio1, + radio, + full, + toggleFullscreen, + Delete, + FullScreen, + clear, + submitForm + }; + }, +}); +</script> +<style scoped> +.el-row { + padding: 0 0 20px 0; +} +</style> diff --git a/src/components/DailogSearchUser/index.vue b/src/components/DailogSearchUser/index.vue new file mode 100644 index 0000000..7345d2e --- /dev/null +++ b/src/components/DailogSearchUser/index.vue @@ -0,0 +1,246 @@ +<template> + <el-dialog v-model="dialogVisible" :fullscreen="full" title="用户选择" width="60%" draggable> + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-row> + <el-col :span="6"> + <div class="userTree"> + <el-input v-model="filterText" placeholder="请输入组织机构过滤"></el-input> + <div class="tree"> + <el-tree ref="treeRef" :data="data" :props="propse" @node-click="handleNodeClick" :filter-node-method="filterNode" /> + </div> + </div> + </el-col> + <el-col :span="14" style="padding: 20px"> + <el-form ref="ruleFormRef" :model="ruleForm" status-icon> + <el-row> + <!-- <el-col :span="10" :offset="1"> + <el-form-item size="default"> + <el-input v-model="ruleForm.pass" placeholder="登录名" /> + </el-form-item> + </el-col> --> + <el-col :span="8" :offset="1"> + <el-form-item> + <!-- <el-button size="default" type="primary" >查询</el-button> --> + <el-button size="default" @click="clear">清除选择</el-button> + </el-form-item> + </el-col> + </el-row> + </el-form> + <el-table :data="tableData" style="width: 100%; margin-top: 20px" ref="clearAll" @selection-change="handleSelectionChange"> + <el-table-column type="selection" width="55" v-if="types==0"/> + <el-table-column align="center" v-if="types!=0"> + <template #default="scope"> + <el-radio-group v-model="radio1"> + <el-radio :label="scope.row.uid" @click="radio(scope.row)" size="large">{{ null }}</el-radio> + </el-radio-group> + </template> + </el-table-column> + <el-table-column align="center" prop="realName" label="登录名" /> + <el-table-column align="center" prop="username" label="用户名" /> + <el-table-column align="center" prop="address" label="所属机构" /> + <el-table-column align="center" prop="address" label="所属部门" /> + <el-table-column align="center" prop="type" label="状态" /> + </el-table> + <el-pagination + style="padding: 20px 0; border-bottom: 1px solid #dedede" + v-model:currentPage="currentPage4" + v-model:page-size="pageSize4" + :page-sizes="[10, 20, 30, 40]" + layout="total, sizes, prev, pager, next, jumper" + :total="total" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </el-col> + <el-col :span="4"> + <div v-if="dynamicTags[0]==''?false:true"> + <el-tag + v-for="tag in dynamicTags" + :key="tag" + class="mx-1" + style="margin: 5px" + closable + :disable-transitions="false" + @close="handleClose(tag)" + > + {{ tag.realName }} + </el-tag> + </div> + </el-col> + </el-row> + <template #footer> + <span class="dialog-footer"> + <el-button @click="dialogVisible = false" size="default">关闭</el-button> + <el-button type="primary" @click="submitForm" size="default">确定</el-button> + </span> + </template> + </el-dialog> +</template> +<script lang="ts"> +import { defineComponent, ref, onMounted, reactive, watch } from 'vue'; +import { FullScreen } from '@element-plus/icons-vue'; +import { ElMessageBox, ElTree, ElMessage, ElButton, ElInput, TabsPaneContext } from 'element-plus'; +import { goalManagementApi } from '/@/api/goalManagement'; +interface Tree { + label: string; + children?: Tree[]; +} +export default defineComponent({ + setup(props, { emit }) { + //部门树 + const department = () => { + goalManagementApi() + .getTreedepartment() + .then((res) => { + if (res.data.code == 200) { + data.value = res.data.data; + } else { + ElMessage.error(res.data.msg); + } + }); + }; + const propse = { + label: 'depName', + children: 'children', + value: 'depId', + }; + //部门树查询 + const filterText = ref(''); + const treeRef = ref<InstanceType<typeof ElTree>>(); + watch(filterText, (val) => { + treeRef.value!.filter(val); + }); + const filterNode = (depName: string, data: Tree) => { + if (!depName) return true; + return data.depName.includes(depName); + }; + onMounted(() => { + department(); + }); + //左边树形部分点击获取回调 + const names = ref<any>(); + const handleNodeClick = (data: Tree) => { + goalManagementApi() + .getManName(data.depId) + .then((res) => { + if (res.data.code == 200) { + tableData.value=res.data.data + total.value=tableData.value.length + }else{ + ElMessage.error(res.data.msg); + } + }); + }; + + const data = ref(); + //中间表格 + // 搜索条件 + const ruleForm = reactive({ + pass: '', + checkPass: '', + }); + // 表格 + const tableData = ref(); + const currentPage4 = ref(1); + const pageSize4 = ref(10); + const total=ref() + const handleSizeChange = (val: number) => { + // console.log(`${val} items per page`); + pageSize4.value=val + }; + const handleCurrentChange = (val: number) => { + // console.log(`current page: ${val}`); + currentPage4.value=val + }; + // 右方点击添加后显示标签 + const dynamicTags = ref(['']); + const handleClose = (tag: any) => { + dynamicTags.value.splice(dynamicTags.value.indexOf(tag), 1); + radio1.value = ''; + }; + const radio1 = ref(''); + const radio = (data: any) => { + dynamicTags.value[0] = data; + }; + const handleSelectionChange = (val:any) => { + dynamicTags.value=val + } + const types=ref() + // 开启弹窗 + const dialogVisible = ref(false); + const openDailog = (type:any) => { + types.value=type + dialogVisible.value = true; + }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + const submitForm = () => { + if(types.value==0){ + emit('SearchUser', dynamicTags.value,types.value); + }else { + emit('SearchUser', dynamicTags.value[0],types.value); + } + + dialogVisible.value = false; + clear() + }; + const clearAll=ref() + const clear=()=>{ + dynamicTags.value=[] + radio1.value="" + clearAll.value.clearSelection() + } + return { + clear, + clearAll, + total, + types, + filterText, + treeRef, + filterNode, + propse, + dialogVisible, + names, + data, + handleNodeClick, + openDailog, + ruleForm, + tableData, + currentPage4, + pageSize4, + handleSizeChange, + handleCurrentChange, + handleSelectionChange, + radio1, + dynamicTags, + handleClose, + FullScreen, + full, + toggleFullscreen, + radio, + submitForm, + }; + }, +}); +</script> +<style scoped> +.userTree { + border: 1px solid #ebeef5; +} +.userTree .el-input { + padding: 10px; + border-bottom: 1px solid #ebeef5; +} +.tree { + height: 500px; + overflow: hidden; + overflow-y: auto; +} +</style> diff --git a/src/components/DailogSearchUserManger/index.vue b/src/components/DailogSearchUserManger/index.vue new file mode 100644 index 0000000..1632e6a --- /dev/null +++ b/src/components/DailogSearchUserManger/index.vue @@ -0,0 +1,223 @@ +<template> + <el-dialog v-model="dialogVisible" :fullscreen="full" title="用户选择" width="60%" draggable> + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-row> + <el-col :span="6"> + <div class="userTree"> + <el-input v-model="filterText" placeholder="请输入组织机构过滤"></el-input> + <div class="tree"> + <el-tree ref="treeRef" :data="data" :props="propse" @node-click="handleNodeClick" :filter-node-method="filterNode" /> + </div> + </div> + </el-col> + <el-col :span="14" style="padding: 20px"> + <el-form ref="ruleFormRef" :model="ruleForm" status-icon> + <el-row> + <el-col :span="10" :offset="1"> + <el-form-item size="default"> + <el-input v-model="ruleForm.pass" placeholder="登录名" /> + </el-form-item> + </el-col> + <el-col :span="8" :offset="1"> + <el-form-item> + <el-button size="default" type="primary" >查询</el-button> + <el-button size="default">重置</el-button> + </el-form-item> + </el-col> + </el-row> + </el-form> + <el-table :data="tableData" style="width: 100%; margin-top: 20px" @cell-click="radio"> + <el-table-column align="center"> + <template #default="scope"> + <el-radio-group v-model="radio1"> + <el-radio :label="scope.row.uid" size="large">{{ null }}</el-radio> + </el-radio-group> + </template> + </el-table-column> + <el-table-column align="center" prop="realName" label="登录名" /> + <el-table-column align="center" prop="username" label="用户名" /> + <el-table-column align="center" prop="address" label="所属机构" /> + <el-table-column align="center" prop="address" label="所属部门" /> + <el-table-column align="center" prop="type" label="状态" /> + </el-table> + <el-pagination + style="padding: 20px 0; border-bottom: 1px solid #dedede" + v-model:currentPage="currentPage4" + v-model:page-size="pageSize4" + :page-sizes="[100, 200, 300, 400]" + layout="total, sizes, prev, pager, next, jumper" + :total="400" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </el-col> + <el-col :span="4"> + <div v-if="dynamicTags[0]==''?false:true"> + <el-tag + v-for="tag in dynamicTags" + :key="tag" + class="mx-1" + style="margin: 5px" + closable + :disable-transitions="false" + @close="handleClose(tag)" + > + {{ tag.realName }} + </el-tag> + </div> + </el-col> + </el-row> + <template #footer> + <span class="dialog-footer"> + <el-button @click="dialogVisible = false" size="default">关闭</el-button> + <el-button type="primary" @click="submitForm" size="default">确定</el-button> + </span> + </template> + </el-dialog> +</template> +<script lang="ts"> +import { defineComponent, ref, onMounted, reactive, watch } from 'vue'; +import { FullScreen } from '@element-plus/icons-vue'; +import { ElMessageBox, ElTree, ElMessage, ElButton, ElInput, TabsPaneContext } from 'element-plus'; +import { goalManagementApi } from '/@/api/goalManagement'; +interface Tree { + label: string; + children?: Tree[]; +} +export default defineComponent({ + setup(props, { emit }) { + //部门树 + const department = () => { + goalManagementApi() + .getTreedepartment() + .then((res) => { + if (res.data.code == 200) { + data.value = res.data.data; + } else { + ElMessage.error(res.data.msg); + } + }); + }; + const propse = { + label: 'depName', + children: 'children', + value: 'depId', + }; + //部门树查询 + const filterText = ref(''); + const treeRef = ref<InstanceType<typeof ElTree>>(); + watch(filterText, (val) => { + treeRef.value!.filter(val); + }); + const filterNode = (depName: string, data: Tree) => { + if (!depName) return true; + return data.depName.includes(depName); + }; + onMounted(() => { + department(); + }); + //左边树形部分点击获取回调 + const names = ref<any>(); + const handleNodeClick = (data: Tree) => { + goalManagementApi() + .getManName(data.depId) + .then((res) => { + if (res.data.code == 200) { + tableData.value=res.data.data + }else{ + ElMessage.error(res.data.msg); + } + }); + }; + + const data = ref(); + //中间表格 + // 搜索条件 + const ruleForm = reactive({ + pass: '', + checkPass: '', + }); + // 表格 + const tableData = ref(); + const currentPage4 = ref(); + const pageSize4 = ref(); + const handleSizeChange = (val: number) => { + console.log(`${val} items per page`); + }; + const handleCurrentChange = (val: number) => { + console.log(`current page: ${val}`); + }; + // 右方点击添加后显示标签 + const dynamicTags = ref(['']); + const handleClose = (tag: any) => { + dynamicTags.value.splice(dynamicTags.value.indexOf(tag), 1); + radio1.value = ''; + }; + const radio1 = ref(''); + const radio = (event: any) => { + dynamicTags.value[0] = event; + }; + const types=ref() + // 开启弹窗 + const dialogVisible = ref(false); + const openDailog = (type:any) => { + console.log(type) + types.value=type + dialogVisible.value = true; + }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + const submitForm = () => { + emit('SearchUser', dynamicTags.value); + dialogVisible.value = false; + }; + return { + types, + filterText, + treeRef, + filterNode, + propse, + dialogVisible, + names, + data, + handleNodeClick, + openDailog, + ruleForm, + tableData, + currentPage4, + pageSize4, + handleSizeChange, + handleCurrentChange, + radio1, + dynamicTags, + handleClose, + FullScreen, + full, + toggleFullscreen, + radio, + submitForm, + }; + }, +}); +</script> +<style scoped> +.userTree { + border: 1px solid #ebeef5; +} +.userTree .el-input { + padding: 10px; + border-bottom: 1px solid #ebeef5; +} +.tree { + height: 500px; + overflow: hidden; + overflow-y: auto; +} +</style> diff --git a/src/components/auth/auth.vue b/src/components/auth/auth.vue new file mode 100644 index 0000000..ae010d4 --- /dev/null +++ b/src/components/auth/auth.vue @@ -0,0 +1,30 @@ +<template> + <slot v-if="getUserAuthBtnList" /> +</template> + +<script lang="ts"> +import { computed, defineComponent } from 'vue'; +import { storeToRefs } from 'pinia'; +import { useUserInfo } from '/@/stores/userInfo'; + +export default defineComponent({ + name: 'auth', + props: { + value: { + type: String, + default: () => '', + }, + }, + setup(props) { + const stores = useUserInfo(); + const { userInfos } = storeToRefs(stores); + // 获取 vuex 中的用户权限 + const getUserAuthBtnList = computed(() => { + return userInfos.value.authBtnList.some((v: string) => v === props.value); + }); + return { + getUserAuthBtnList, + }; + }, +}); +</script> diff --git a/src/components/auth/authAll.vue b/src/components/auth/authAll.vue new file mode 100644 index 0000000..76c5e01 --- /dev/null +++ b/src/components/auth/authAll.vue @@ -0,0 +1,31 @@ +<template> + <slot v-if="getUserAuthBtnList" /> +</template> + +<script lang="ts"> +import { computed, defineComponent } from 'vue'; +import { storeToRefs } from 'pinia'; +import { useUserInfo } from '/@/stores/userInfo'; +import { judementSameArr } from '/@/utils/arrayOperation'; + +export default defineComponent({ + name: 'authAll', + props: { + value: { + type: Array, + default: () => [], + }, + }, + setup(props) { + const stores = useUserInfo(); + const { userInfos } = storeToRefs(stores); + // 获取 pinia 中的用户权限 + const getUserAuthBtnList = computed(() => { + return judementSameArr(props.value, userInfos.value.authBtnList); + }); + return { + getUserAuthBtnList, + }; + }, +}); +</script> diff --git a/src/components/auth/auths.vue b/src/components/auth/auths.vue new file mode 100644 index 0000000..ef31019 --- /dev/null +++ b/src/components/auth/auths.vue @@ -0,0 +1,36 @@ +<template> + <slot v-if="getUserAuthBtnList" /> +</template> + +<script lang="ts"> +import { computed, defineComponent } from 'vue'; +import { storeToRefs } from 'pinia'; +import { useUserInfo } from '/@/stores/userInfo'; + +export default defineComponent({ + name: 'auths', + props: { + value: { + type: Array, + default: () => [], + }, + }, + setup(props) { + const stores = useUserInfo(); + const { userInfos } = storeToRefs(stores); + // 获取 vuex 中的用户权限 + const getUserAuthBtnList = computed(() => { + let flag = false; + userInfos.value.authBtnList.map((val: string) => { + props.value.map((v) => { + if (val === v) flag = true; + }); + }); + return flag; + }); + return { + getUserAuthBtnList, + }; + }, +}); +</script> diff --git a/src/components/checkTemplate/index.vue b/src/components/checkTemplate/index.vue new file mode 100644 index 0000000..7dcd7eb --- /dev/null +++ b/src/components/checkTemplate/index.vue @@ -0,0 +1,230 @@ +<template> + <el-dialog v-model="dialogVisible" title="选择应急队伍" width="900px" draggable :fullscreen="full"> + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-row> + <el-col :span="18"> + <el-row> + <el-col :span="24"> + <el-form ref="ruleFormRef" :inline="true" status-icon> + <el-form-item> + <el-input size="default" v-model="listQuery.searchParams.teamName" placeholder="队伍名称" style="max-width: 215px; padding: 0 12px" /> + </el-form-item> + <el-form-item> + <el-button size="default" type="primary" @click="onSubmit">查询</el-button> + <el-button size="default" @click="submitReset">重置</el-button> + </el-form-item> + </el-form> + </el-col> + <el-col :span="24"> + <el-button size="default" :icon="Delete" style="margin-top: 15px" @click="submitReset">清除选择</el-button> + </el-col> + </el-row> + <el-table :data="tableData" ref="multipleTableRef" style="width: 100%; margin-top: 20px" @selection-change="handleSelectionChange"> + <el-table-column type="selection" width="55" v-if="types == 0"> + <template #default="scope" v-if="types != 0"> + <el-radio-group v-model="radio1"> + <el-radio :label="scope.row.id" @click="radio(scope.row)" size="large">{{ null }}</el-radio> + </el-radio-group> + </template> + </el-table-column> + <el-table-column align="center" prop="id" label="id" /> + <el-table-column align="center" prop="teamName" label="队伍名称" /> + </el-table> + <div class="pages"> + <el-pagination + v-model:currentPage="pageIndex" + v-model:page-size="pageSize" + :page-sizes="[10, 20, 30, 40]" + layout="total, sizes, prev, pager, next, jumper" + :total="total" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + </el-col> + <el-col :span="6" style="padding-left: 15px"> + <div v-if="dynamicTags[0] == '' ? false : true"> + <el-tag + v-for="tag in dynamicTags" + :key="tag" + class="mx-1" + style="margin: 5px" + closable + :disable-transitions="false" + @close="handleClose(tag)" + > + {{ tag.teamName }} + </el-tag> + </div> + </el-col> + </el-row> + <template #footer> + <span class="dialog-footer"> + <el-button @click="dialogVisible = false" size="default">关闭</el-button> + <el-button type="primary" @click="submitForm" size="default">确定</el-button> + </span> + </template> + </el-dialog> +</template> +<script lang="ts"> +import { defineComponent, reactive, ref, onMounted } from 'vue'; +import { Delete, FullScreen } from '@element-plus/icons-vue'; +import { ElMessage } from 'element-plus'; +import { contingencyApi } from '/@/api/contingencyManagement/contingency'; + +export default defineComponent({ + setup(props, { emit }) { + const types = ref(); + const dialogVisible = ref<boolean>(false); + const openDailog = (type: any) => { + types.value = type; + dialogVisible.value = true; + // onSubmit(); + }; + // 搜索条件 + const listQuery = reactive({ + pageIndex: 1, + pageSize: 10, + searchParams: { + teamName: '', + }, + }); + // 列表数据请求 + const onSubmit = async () => { + let res = await contingencyApi().getTeamManagementList(listQuery); + if (res.data.code === '200') { + tableData.value = res.data.data; + pageIndex.value = res.data.pageIndex; + pageSize.value = res.data.pageSize; + total.value = res.data.total; + } else { + ElMessage({ + showClose: true, + type: 'error', + message: res.data.msg, + }); + } + }; + const submitForm = () => { + if (types.value == 0) { + emit('SearchUser', dynamicTags.value, types.value); + } else { + emit('SearchUser', dynamicTags.value[0], types.value); + } + dialogVisible.value = false; + }; + const handleSelectionChange = (val: any) => { + dynamicTags.value = val; + }; + // 重置 + const submitReset = () => { + listQuery.searchParams.teamName = ''; + listQuery.searchParams.id = ''; + radio1.value = ''; + dynamicTags.value[0] = ''; + onSubmit(); + }; + // 表格 + const tableData = ref(); + // 分页 + const pageIndex = ref(); + const pageSize = ref(); + const total = ref(); + const handleSizeChange = (val: number) => { + listQuery.pageSize = val; + onSubmit(); + }; + const handleCurrentChange = (val: number) => { + listQuery.pageIndex = val; + onSubmit(); + }; + // 右方点击添加后显示标签 + const dynamicTags = ref(['']); + const handleClose = (tag: string) => { + dynamicTags.value.splice(dynamicTags.value.indexOf(tag), 1); + radio1.value = ''; + }; + const radio1 = ref(''); + const radio = (event: any) => { + console.log(event); + dynamicTags.value[0] = event; + }; + onMounted(() => { + onSubmit(); + }); + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + return { + dialogVisible, + openDailog, + tableData, + pageSize, + pageIndex, + handleSizeChange, + handleCurrentChange, + dynamicTags, + handleClose, + Delete, + toggleFullscreen, + FullScreen, + full, + onSubmit, + listQuery, + submitReset, + total, + radio, + radio1, + submitForm, + types, + handleSelectionChange, + }; + }, +}); +</script> +<style scoped> +.el-form--inline .el-form-item { + margin-bottom: 0; + margin-right: 0; +} +/*分页*/ +.pages { + /*display: flex;*/ + /*justify-content: flex-end;*/ + margin-top: 15px; +} +::v-deep .el-pagination .el-pager li { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +::v-deep .el-pagination .el-pager li.is-active { + background-color: #409eff; + color: #fff; +} +::v-deep .el-pagination .btn-prev { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +::v-deep .el-pagination button:disabled { + color: #c0c4cc; +} +::v-deep .el-pagination .btn-next { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +</style> diff --git a/src/components/cropper/index.vue b/src/components/cropper/index.vue new file mode 100644 index 0000000..b23a266 --- /dev/null +++ b/src/components/cropper/index.vue @@ -0,0 +1,149 @@ +<template> + <div> + <el-dialog title="更换头像" v-model="isShowDialog" width="769px"> + <div class="cropper-warp"> + <div class="cropper-warp-left"> + <img :src="cropperImg" class="cropper-warp-left-img" /> + </div> + <div class="cropper-warp-right"> + <div class="cropper-warp-right-title">预览</div> + <div class="cropper-warp-right-item"> + <div class="cropper-warp-right-value"> + <img :src="cropperImgBase64" class="cropper-warp-right-value-img" /> + </div> + <div class="cropper-warp-right-label">100 x 100</div> + </div> + <div class="cropper-warp-right-item"> + <div class="cropper-warp-right-value"> + <img :src="cropperImgBase64" class="cropper-warp-right-value-img cropper-size" /> + </div> + <div class="cropper-warp-right-label">50 x 50</div> + </div> + </div> + </div> + <template #footer> + <span class="dialog-footer"> + <el-button @click="onCancel" size="default">取 消</el-button> + <el-button type="primary" @click="onSubmit" size="default">更 换</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script lang="ts"> +import { reactive, toRefs, nextTick, defineComponent } from 'vue'; +import Cropper from 'cropperjs'; +import 'cropperjs/dist/cropper.css'; + +export default defineComponent({ + name: 'cropperIndex', + setup() { + const state = reactive({ + isShowDialog: false, + cropperImg: '', + cropperImgBase64: '', + cropper: null, + }); + // 打开弹窗 + const openDialog = (imgs: any) => { + state.cropperImg = imgs; + state.isShowDialog = true; + nextTick(() => { + initCropper(); + }); + }; + // 关闭弹窗 + const closeDialog = () => { + state.isShowDialog = false; + }; + // 取消 + const onCancel = () => { + closeDialog(); + }; + // 更换 + const onSubmit = () => { + // state.cropperImgBase64 = state.cropper.getCroppedCanvas().toDataURL('image/jpeg'); + }; + // 初始化cropperjs图片裁剪 + const initCropper = () => { + const letImg: any = document.querySelector('.cropper-warp-left-img'); + (<any>state.cropper) = new Cropper(letImg, { + viewMode: 1, + dragMode: 'none', + initialAspectRatio: 1, + aspectRatio: 1, + preview: '.before', + background: false, + autoCropArea: 0.6, + zoomOnWheel: false, + crop: () => { + state.cropperImgBase64 = (<any>state.cropper).getCroppedCanvas().toDataURL('image/jpeg'); + }, + }); + }; + return { + openDialog, + closeDialog, + onCancel, + onSubmit, + initCropper, + ...toRefs(state), + }; + }, +}); +</script> + +<style scoped lang="scss"> +.cropper-warp { + display: flex; + .cropper-warp-left { + position: relative; + display: inline-block; + height: 350px; + flex: 1; + border: 1px solid var(--el-border-color); + background: var(--el-color-white); + overflow: hidden; + background-repeat: no-repeat; + cursor: move; + border-radius: var(--el-border-radius-base); + .cropper-warp-left-img { + width: 100%; + height: 100%; + } + } + .cropper-warp-right { + width: 150px; + height: 350px; + .cropper-warp-right-title { + text-align: center; + height: 20px; + line-height: 20px; + } + .cropper-warp-right-item { + margin: 15px 0; + .cropper-warp-right-value { + display: flex; + .cropper-warp-right-value-img { + width: 100px; + height: 100px; + border-radius: var(--el-border-radius-circle); + margin: auto; + } + .cropper-size { + width: 50px; + height: 50px; + } + } + .cropper-warp-right-label { + text-align: center; + font-size: 12px; + color: var(--el-text-color-primary); + height: 30px; + line-height: 30px; + } + } + } +} +</style> diff --git a/src/components/editor/index.vue b/src/components/editor/index.vue new file mode 100644 index 0000000..78e5726 --- /dev/null +++ b/src/components/editor/index.vue @@ -0,0 +1,115 @@ +<template> + <div class="editor-container"> + <div ref="editorToolbar"></div> + <div ref="editorContent" :style="{ height }"></div> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, onMounted, watch, defineComponent } from 'vue'; +import { createEditor, createToolbar, IEditorConfig, IToolbarConfig, IDomEditor } from '@wangeditor/editor'; +import '@wangeditor/editor/dist/css/style.css'; +import { toolbarKeys } from './toolbar'; + +// 定义接口来定义对象的类型 +interface WangeditorState { + editorToolbar: HTMLDivElement | null; + editorContent: HTMLDivElement | null; + editor: any; +} + +export default defineComponent({ + name: 'wngEditor', + props: { + // 节点 id + id: { + type: String, + default: () => 'wangeditor', + }, + // 是否禁用 + isDisable: { + type: Boolean, + default: () => false, + }, + // 内容框默认 placeholder + placeholder: { + type: String, + default: () => '请输入内容', + }, + // 双向绑定:双向绑定值,字段名为固定,改了之后将不生效 + // 参考:https://v3.cn.vuejs.org/guide/migration/v-model.html#%E8%BF%81%E7%A7%BB%E7%AD%96%E7%95%A5 + modelValue: String, + // https://www.wangeditor.com/v5/getting-started.html#mode-%E6%A8%A1%E5%BC%8F + // 模式,可选 <default|simple>,默认 default + mode: { + type: String, + default: () => 'default', + }, + // 高度 + height: { + type: String, + default: () => '310px', + }, + }, + setup(props, { emit }) { + const state = reactive<WangeditorState>({ + editorToolbar: null, + editor: null, + editorContent: null, + }); + // 富文本配置 + const wangeditorConfig = () => { + const editorConfig: Partial<IEditorConfig> = { MENU_CONF: {} }; + props.isDisable ? (editorConfig.readOnly = true) : (editorConfig.readOnly = false); + editorConfig.placeholder = props.placeholder; + editorConfig.onChange = (editor: IDomEditor) => { + // console.log('content', editor.children); + // console.log('html', editor.getHtml()); + emit('update:modelValue', editor.getHtml()); + }; + (<any>editorConfig).MENU_CONF['uploadImage'] = { + base64LimitSize: 10 * 1024 * 1024, + }; + return editorConfig; + }; + // + const toolbarConfig = () => { + const toolbarConfig: Partial<IToolbarConfig> = {}; + toolbarConfig.toolbarKeys = toolbarKeys; + return toolbarConfig; + }; + // 初始化富文本 + // https://www.wangeditor.com/ + const initWangeditor = () => { + state.editor = createEditor({ + html: props.modelValue, + selector: state.editorContent!, + config: wangeditorConfig(), + mode: props.mode, + }); + createToolbar({ + editor: state.editor, + selector: state.editorToolbar!, + mode: props.mode, + config: toolbarConfig(), + }); + }; + // 页面加载时 + onMounted(() => { + initWangeditor(); + }); + // 监听双向绑定值的改变 + // https://gitee.com/lyt-top/vue-next-admin/issues/I4LM7I + watch( + () => props.modelValue, + (value) => { + state.editor.clear(); + state.editor.dangerouslyInsertHtml(value); + } + ); + return { + ...toRefs(state), + }; + }, +}); +</script> diff --git a/src/components/editor/toolbar.ts b/src/components/editor/toolbar.ts new file mode 100644 index 0000000..14a9bf3 --- /dev/null +++ b/src/components/editor/toolbar.ts @@ -0,0 +1,60 @@ +/** + * 工具栏配置 + */ +export const toolbarKeys = [ + 'headerSelect', + 'blockquote', + '|', + 'bold', + 'underline', + 'italic', + { + key: 'group-more-style', + title: '更多', + iconSvg: + '<svg viewBox="0 0 1024 1024"><path d="M204.8 505.6m-76.8 0a76.8 76.8 0 1 0 153.6 0 76.8 76.8 0 1 0-153.6 0Z"></path><path d="M505.6 505.6m-76.8 0a76.8 76.8 0 1 0 153.6 0 76.8 76.8 0 1 0-153.6 0Z"></path><path d="M806.4 505.6m-76.8 0a76.8 76.8 0 1 0 153.6 0 76.8 76.8 0 1 0-153.6 0Z"></path></svg>', + menuKeys: ['through', 'code', 'sup', 'sub', 'clearStyle'], + }, + 'color', + 'bgColor', + '|', + 'fontSize', + 'fontFamily', + 'lineHeight', + '|', + 'bulletedList', + 'numberedList', + 'todo', + { + key: 'group-justify', + title: '对齐', + iconSvg: + '<svg viewBox="0 0 1024 1024"><path d="M768 793.6v102.4H51.2v-102.4h716.8z m204.8-230.4v102.4H51.2v-102.4h921.6z m-204.8-230.4v102.4H51.2v-102.4h716.8zM972.8 102.4v102.4H51.2V102.4h921.6z"></path></svg>', + menuKeys: ['justifyLeft', 'justifyRight', 'justifyCenter', 'justifyJustify'], + }, + { + key: 'group-indent', + title: '缩进', + iconSvg: + '<svg viewBox="0 0 1024 1024"><path d="M0 64h1024v128H0z m384 192h640v128H384z m0 192h640v128H384z m0 192h640v128H384zM0 832h1024v128H0z m0-128V320l256 192z"></path></svg>', + menuKeys: ['indent', 'delIndent'], + }, + '|', + 'emotion', + 'insertLink', + { + key: 'group-image', + title: '图片', + iconSvg: + '<svg viewBox="0 0 1024 1024"><path d="M959.877 128l0.123 0.123v767.775l-0.123 0.122H64.102l-0.122-0.122V128.123l0.122-0.123h895.775zM960 64H64C28.795 64 0 92.795 0 128v768c0 35.205 28.795 64 64 64h896c35.205 0 64-28.795 64-64V128c0-35.205-28.795-64-64-64zM832 288.01c0 53.023-42.988 96.01-96.01 96.01s-96.01-42.987-96.01-96.01S682.967 192 735.99 192 832 234.988 832 288.01zM896 832H128V704l224.01-384 256 320h64l224.01-192z"></path></svg>', + menuKeys: ['uploadImage'], + }, + 'insertTable', + 'codeBlock', + 'divider', + '|', + 'undo', + 'redo', + '|', + 'fullScreen', +]; diff --git a/src/components/emergencySupplies/index.vue b/src/components/emergencySupplies/index.vue new file mode 100644 index 0000000..8bb4aba --- /dev/null +++ b/src/components/emergencySupplies/index.vue @@ -0,0 +1,215 @@ +<template> + <el-dialog + v-model="dialogVisible" + title="选择应急物资" + width="900px" + draggable + :fullscreen="full" + > + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-row> + <el-col :span="18"> + <el-row> + <el-form ref="ruleFormRef" :model="ruleForm" :inline="true" status-icon> + <el-form-item> + <el-input size="default" v-model="listQuery.searchParams.name" placeholder="物资名称" style="max-width: 215px;margin-right: 12px;"/> + </el-form-item> + <el-form-item> + <el-button size="default" type="primary" @click="onSubmit">查询</el-button> + <el-button size="default" @click="submitReset">重置</el-button> + <el-button size="default" :icon="Delete">清除选择</el-button> + </el-form-item> + </el-form> + </el-row> + <el-table :data="tableData" style="width: 100%;margin-top:20px"> + <el-table-column width="55"> + <template #default="scope"> + <el-radio-group v-model="radio1"> + <el-radio :label="scope.row" @click="radio(scope.row)" size="large">{{ null }}</el-radio> + </el-radio-group> + </template> + </el-table-column> + <el-table-column align="center" prop="name" label="物资名称"/> + </el-table> + <div class="pages"> + <el-pagination + v-model:currentPage="pageIndex" + v-model:page-size="pageSize" + :page-sizes="[10, 20, 30]" + layout="total, sizes, prev, pager, next, jumper" + :total="total" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + </el-col> + <el-col :span="6"> + <div v-if="dynamicTags[0] == '' ? false : true"> + <el-tag + v-for="tag in dynamicTags" + :key="tag" + class="mx-1" + style="margin: 5px" + closable + :disable-transitions="false" + @close="handleClose(tag)" + > + {{ tag.name }} + </el-tag> + </div> + </el-col> + </el-row> + <template #footer> + <span class="dialog-footer"> + <el-button @click="dialogVisible = false" size="default">关闭</el-button> + <el-button type="primary" @click="submitForm" size="default">确定</el-button> + </span> + </template> + </el-dialog> +</template> +<script lang="ts"> +import { + defineComponent, + reactive, + ref +} from 'vue'; +import { + Delete, + FullScreen +} from '@element-plus/icons-vue'; +import { ElMessage } from 'element-plus'; +import {emergencySuppliesApi} from "/@/api/contingencyManagement/emergencyResources"; +export default defineComponent({ + setup(props, { emit }) { + const dialogVisible = ref<boolean>(false); + const openDailog = () => { + dialogVisible.value = true; + onSubmit() + }; + // 搜索条件 + const listQuery = reactive({ + pageIndex: 1, + pageSize: 10, + searchParams:{ + name: '', + } + }); + // 定义表格数据 + const tableData = ref([]); + // 列表请求数据 + const onSubmit = async () => { + let res = await emergencySuppliesApi().getEmergencySuppliesList(listQuery); + if (res.data.code === '200') { + tableData.value = res.data.data; + pageIndex.value = res.data.pageIndex; + pageSize.value = res.data.pageSize; + total.value = res.data.total; + } else { + ElMessage({ + showClose: true, + type: 'error', + message: res.data.msg, + }); + } + }; + // 重置 + const submitReset = () => { + listQuery.searchParams.name = ''; + onSubmit(); + }; + const pageIndex = ref(); + const pageSize = ref(); + const total = ref(); + const handleSizeChange = (val: number) => { + listQuery.pageSize = val; + }; + const handleCurrentChange = (val: number) => { + listQuery.pageIndex = val; + }; + // 右方点击添加后显示标签 + const dynamicTags = ref(['']); + const handleClose = (tag: string) => { + dynamicTags.value.splice(dynamicTags.value.indexOf(tag), 1); + radio1.value = ''; + }; + const radio1 = ref(''); + const radio = (event: any) => { + dynamicTags.value[0] = event; + }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + const submitForm = () => { + let obj = JSON.parse(JSON.stringify(dynamicTags.value)); + emit('SearchUser', obj[0]); + dialogVisible.value = false; + }; + return { + dialogVisible, + openDailog, + listQuery, + onSubmit, + tableData, + submitReset, + handleSizeChange, + handleCurrentChange, + dynamicTags, + handleClose, + Delete, + toggleFullscreen, + FullScreen, + full, + pageIndex, + pageSize, + radio1, + radio, + submitForm, + total, + }; + }, +}); +</script> +<style scoped> +.el-form--inline .el-form-item{ + margin-bottom: 0; + margin-right: 0; +} +/*分页*/ +.pages{ + margin-top: 15px; +} +::v-deep .el-pagination .el-pager li { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +::v-deep .el-pagination .el-pager li.is-active { + background-color: #409eff; + color: #fff; +} +::v-deep .el-pagination .btn-prev { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +::v-deep .el-pagination button:disabled{ + color: #c0c4cc; +} +::v-deep .el-pagination .btn-next{ + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +</style> diff --git a/src/components/equipmentDailog/Dailog.vue b/src/components/equipmentDailog/Dailog.vue new file mode 100644 index 0000000..9ed675f --- /dev/null +++ b/src/components/equipmentDailog/Dailog.vue @@ -0,0 +1,903 @@ +<template> + <el-dialog v-model="dialogVisible" :fullscreen="full" @close="resetForm(ruleFormRef)" draggable :title="titles" width="60%"> + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-form :model="form" ref="ruleFormRef" :rules="rules" :disabled="disabled" label-width="120px" class="formType"> + <el-form-item label="装置设施名称" size="default" prop="qName"> + <el-input v-model="form.qName" placeholder="请填写装置设施名称" /> + </el-form-item> + <el-form-item label="装置设施位号" size="default" prop="positionNum"> + <el-input disabled v-model="form.positionNum" placeholder="请填写装置设施位号" /> + </el-form-item> + <el-form-item label="装置设施用途" size="default" prop="qUsage"> + <el-input v-model="form.qUsage" placeholder="请填写装置设施用途" /> + </el-form-item> + <el-form-item label="装置设施型号" size="default" prop="model"> + <el-input v-model="form.model" placeholder="请填写装置设施型号" /> + </el-form-item> + <el-form-item label="类型/类别外键" size="default" prop="equipmentTypeName"> + <el-input v-model="form.equipmentTypeName" placeholder="请选择"> + <template #append> + <el-button :icon="Search" @click="opencategory"></el-button> + </template> + </el-input> + </el-form-item> + <!-- <el-form-item label="区域名称" size="default"> + <el-input v-model="form.name" placeholder="请选择"> + <template #append> + <el-button :icon="Search" @click="openRegion"></el-button> + </template> + </el-input> + </el-form-item> --> + <el-form-item label="单位部门" size="default" prop="departmentId"> + <el-tree-select v-model="form.departmentId" :data="data" check-strictly="true" class="w100" :props="propse" placeholder="请选择" /> + </el-form-item> + <el-form-item label="设置部位" size="default" prop="setPart"> + <el-input v-model="form.setPart" placeholder="请填写设置部位" /> + </el-form-item> + <el-form-item label="生产日期" size="default" prop="produceTime"> + <el-date-picker v-model="form.produceTime" format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss" type="datetime" placeholder="选择日期时间" style="width: 100%" /> + </el-form-item> + <el-form-item label="使用期限(天)" size="default" prop="useEndDay"> + <el-input v-model="form.useEndDay" placeholder="请填写使用期限" /> + </el-form-item> + <el-form-item label="生命周期" size="default" prop="lifeCycle"> + <el-select v-model="form.lifeCycle" placeholder="请选择" style="width: 100%"> + <el-option label="已投用" :value="1" /> + <el-option label="库存中" :value="2" /> + <el-option label="报废" :value="3" /> + </el-select> + </el-form-item> + <el-form-item label="投用日期" size="default" prop="useDate"> + <el-date-picker v-model="form.useDate" format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss" type="datetime" placeholder="选择日期时间" style="width: 100%" /> + </el-form-item> + <el-form-item label="维修状态" size="default" prop="repairStatus"> + <el-select v-model="form.repairStatus" placeholder="请选择" style="width: 100%"> + <el-option label="维修中" :value="1" /> + <el-option label="已修好" :value="2" /> + </el-select> + </el-form-item> + <el-form-item label="停用状态" size="default" prop="stopStatus"> + <el-select v-model="form.stopStatus" placeholder="请选择" style="width: 100%"> + <el-option label="停用" :value="1" /> + <el-option label="在用" :value="2" /> + <el-option label="维修" :value="3" /> + <el-option label="报废" :value="4" /> + </el-select> + </el-form-item> + <el-form-item label="上次检查日期" size="default" prop="previousCheckDate"> + <el-date-picker + v-model="form.previousCheckDate" + format="YYYY-MM-DD HH:mm:ss" + value-format="YYYY-MM-DD HH:mm:ss" + type="datetime" + placeholder="选择日期时间" + style="width: 100%" + /> + </el-form-item> + <el-form-item label="上次检测日期" size="default" prop="previousTestDate"> + <el-date-picker v-model="form.previousTestDate" format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss" type="datetime" placeholder="选择日期时间" style="width: 100%" /> + </el-form-item> + <el-form-item label="上次保养日期" size="default" prop="previousTakecareDate"> + <el-date-picker + v-model="form.previousTakecareDate" + format="YYYY-MM-DD HH:mm:ss" + value-format="YYYY-MM-DD HH:mm:ss" + type="datetime" + placeholder="选择日期时间" + style="width: 100%" + /> + </el-form-item> + <el-form-item label="下次检查日期" size="default" prop="nextCheckDate"> + <el-date-picker v-model="form.nextCheckDate" format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss" type="datetime" placeholder="选择日期时间" style="width: 100%" /> + </el-form-item> + <el-form-item label="下次检测日期" size="default" prop="nextTestDate"> + <el-date-picker v-model="form.nextTestDate" format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss" type="datetime" placeholder="选择日期时间" style="width: 100%" /> + </el-form-item> + <el-form-item label="下次保养日期" size="default" prop="nextTakecareDate"> + <el-date-picker v-model="form.nextTakecareDate" format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss" type="datetime" placeholder="选择日期时间" style="width: 100%" /> + </el-form-item> + <el-form-item label="负责人" size="default" prop="leadingPersonName"> + <el-input v-model="form.leadingPersonName" placeholder="请选择"> + <template #append> + <el-button :icon="Search" @click="openUser(1)"></el-button> + </template> + </el-input> + </el-form-item> + <el-form-item label="负责人部门" size="default" prop="leadingPersonDepartmentId"> + <el-tree-select + v-model="form.leadingPersonDepartmentId" + :data="data" + check-strictly="true" + class="w100" + :props="propse" + placeholder="请选择" + /> + </el-form-item> + <el-form-item label="供应商" size="default" prop="supplyName"> + <el-input v-model="form.supplyName" placeholder="请填写供应商" /> + </el-form-item> + <el-form-item label="使用说明" size="default" prop="useMemo"> + <el-input v-model="form.useMemo" placeholder="请填写使用说明" /> + </el-form-item> + <el-form-item label="是否检查" size="default" prop="isNeedCheck"> + <el-select v-model="form.isNeedCheck" placeholder="请选择" style="width: 100%"> + <el-option label="是" :value="1" /> + <el-option label="否" :value="2" /> + </el-select> + </el-form-item> + <el-form-item label="检查周期" size="default" prop="checkCycle"> + <el-input v-model="form.checkCycle" placeholder="请填写检查周期" /> + </el-form-item> + <el-form-item label="检查提前提醒" size="default" prop="checkWarn"> + <el-input v-model="form.checkWarn" placeholder="请填写检查提前提醒" /> + </el-form-item> + <el-form-item label="是否检测" size="default" prop="isNeedTest"> + <el-select v-model="form.isNeedTest" placeholder="请选择" style="width: 100%"> + <el-option label="是" :value="1" /> + <el-option label="否" :value="2" /> + </el-select> + </el-form-item> + <el-form-item label="检测周期" size="default" prop="testCycle"> + <el-input v-model="form.testCycle" placeholder="请填写检测周期" /> + </el-form-item> + <el-form-item label="检测提前提醒" size="default" prop="testWarn"> + <el-input v-model="form.testWarn" placeholder="请填写检测提前提醒" /> + </el-form-item> + <el-form-item label="是否保养" size="default" prop="isNeedTakecare"> + <el-select v-model="form.isNeedTakecare" placeholder="请选择" style="width: 100%"> + <el-option label="是" :value="1" /> + <el-option label="否" :value="2" /> + </el-select> + </el-form-item> + <el-form-item label="检查内容" size="default" prop="checkContent"> + <el-input v-model="form.checkContent" placeholder="请填写检查内容" /> + </el-form-item> + <el-form-item label="负责部门" size="default" prop="leadingDepartmentId"> + <el-tree-select v-model="form.leadingDepartmentId" :data="data" check-strictly="true" class="w100" :props="propse" placeholder="请选择" /> + </el-form-item> + <el-form-item label="检查指标" size="default" prop="checkPoint"> + <el-input v-model="form.checkPoint" placeholder="请填写检查指标" /> + </el-form-item> + <el-form-item label="预警值" size="default" prop="alertNum"> + <el-input v-model="form.alertNum" placeholder="请填写预警值" /> + </el-form-item> + <el-form-item label="联锁值" size="default" prop="lockNum"> + <el-input v-model="form.lockNum" placeholder="请填写联锁值" /> + </el-form-item> + <el-form-item label="停用理由" size="default" prop="stopReason"> + <el-input v-model="form.stopReason" placeholder="请填写停用理由" /> + </el-form-item> + <el-form-item label="停用后措施" size="default" prop="afterStopStep"> + <el-input v-model="form.afterStopStep" placeholder="请填写停用后措施" /> + </el-form-item> + <el-form-item label="实际停用日期" size="default" prop="actualStopDate"> + <el-date-picker v-model="form.actualStopDate" format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss" type="datetime" placeholder="选择日期时间" style="width: 100%" /> + </el-form-item> + <el-form-item label="停用提交人" size="default" prop="stopSubmitPersonName"> + <el-input v-model="form.stopSubmitPersonName" placeholder="请选择"> + <template #append> + <el-button :icon="Search" @click="openUser(2)"></el-button> + </template> + </el-input> + </el-form-item> + <el-form-item label="停用提交日期" size="default" prop="stopSubmitDate"> + <el-date-picker v-model="form.stopSubmitDate" format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss" type="datetime" placeholder="选择日期时间" style="width: 100%" /> + </el-form-item> + <el-form-item label="恢复理由" size="default" prop="recoveryReason"> + <el-input v-model="form.recoveryReason" placeholder="请填写恢复理由" /> + </el-form-item> + <el-form-item label="恢复填报日期" size="default" prop="recoverySubmitDate"> + <el-date-picker + v-model="form.recoverySubmitDate" + format="YYYY-MM-DD HH:mm:ss" + value-format="YYYY-MM-DD HH:mm:ss" + type="datetime" + placeholder="选择日期时间" + style="width: 100%" + /> + </el-form-item> + <el-form-item label="实际恢复日期" size="default" prop="actualRecoveryDate"> + <el-date-picker + v-model="form.actualRecoveryDate" + format="YYYY-MM-DD HH:mm:ss" + value-format="YYYY-MM-DD HH:mm:ss" + type="datetime" + placeholder="选择日期时间" + style="width: 100%" + /> + </el-form-item> + <el-form-item label="报废理由" size="default" prop="destoryReason"> + <el-input v-model="form.destoryReason" placeholder="请填写报废理由" /> + </el-form-item> + <el-form-item label="报废填报日期" size="default" prop="destorySubmitDate"> + <el-date-picker + v-model="form.destorySubmitDate" + format="YYYY-MM-DD HH:mm:ss" + value-format="YYYY-MM-DD HH:mm:ss" + type="datetime" + placeholder="选择日期时间" + style="width: 100%" + /> + </el-form-item> + <el-form-item label="实际报废日期" size="default" prop="actualDestoryDate"> + <el-date-picker + v-model="form.actualDestoryDate" + format="YYYY-MM-DD HH:mm:ss" + value-format="YYYY-MM-DD HH:mm:ss" + type="datetime" + placeholder="选择日期时间" + style="width: 100%" + /> + </el-form-item> + <el-form-item label="保养周期" size="default" prop="takecareCycle "> + <el-input v-model="form.takecareCycle" placeholder="请填写保养周期" /> + </el-form-item> + </el-form> + <el-tabs v-model="activeName" class="demo-tabs"> + <el-tab-pane label="设备保养" name="first"> + <el-button type="primary" size="default" :disabled="disabled" @click="openMaintenance('新增', '')">新增</el-button> + <el-table :data="form.takecareDetailList" style="width: 100%"> + <el-table-column align="center" prop="takecareMemo" label="保养情况" /> + <el-table-column align="center" prop="leadingPersonName" label="保养负责人" /> + <el-table-column align="center" prop="takecareDate" :formatter="timeDate" label="保养日期" /> + <el-table-column align="center" prop="leadingPersonDepartmentName" label="保养负责人单位" /> + <el-table-column align="center" label="操作"> + <template #default="scope"> + <el-button link type="primary" @click="openMaintenance('查看', scope.row)" size="small">查看</el-button> + <el-button link type="primary" @click="openMaintenance('修改', scope.row)" size="small">修改</el-button> + <el-button link type="primary" @click="deleteA(scope.row)" size="small">删除</el-button> + </template> + </el-table-column> + </el-table> + </el-tab-pane> + <el-tab-pane label="设备检测" name="second"> + <el-button type="primary" size="default" :disabled="disabled" @click="openDetect('新增', '')">新增</el-button> + <el-table :data="form.testDetailList" style="width: 100%"> + <el-table-column align="center" prop="testPersonName" label="检测人" /> + <el-table-column align="center" prop="testDate" :formatter="timeDate" label="检测日期" /> + <el-table-column align="center" prop="testPersonDepartmentName" label="检测人单位" /> + <el-table-column align="center" prop="testMemo" label="检测内容" /> + <el-table-column align="center" label="检测结果" > + <template #default="scope"> + <span v-if="scope.row.testResult==1">成功</span> + <span v-if="scope.row.testResult==2">失败</span> + </template> + </el-table-column> + <el-table-column align="center" prop="testStatus" label="检测状态" /> + <el-table-column align="center" label="操作"> + <template #default="scope"> + <el-button link type="primary" @click="openDetect('查看', scope.row)" size="small">查看</el-button> + <el-button link type="primary" @click="openDetect('修改', scope.row)" size="small">修改</el-button> + <el-button link type="primary" @click="deleteB(scope.row)" size="small">删除</el-button> + </template> + </el-table-column> + </el-table> + </el-tab-pane> + <el-tab-pane label="设备维修" name="third"> + <el-button type="primary" size="default" :disabled="disabled" @click="openRepair('新增', '')">新增</el-button> + <el-table :data="form.repaireDetailList" style="width: 100%"> + <el-table-column align="center" prop="exceptionInfo" label="设施异常项" /> + <el-table-column align="center" label="维修状态"> + <template #default="scope"> + <span v-if="scope.row.repairStatus==1">维修中</span> + <span v-if="scope.row.repairStatus==2">已修好</span> + </template> + </el-table-column> + <el-table-column align="center" prop="repairMemo" label="维修情况" /> + <el-table-column align="center" prop="repairPersonName" label="维修负责人" /> + <el-table-column align="center" prop="repairPersonDepartmentName" label="维修负责人单位" /> + <el-table-column align="center" prop="repairStartDate" :formatter="timeDate" label="维修开始日期" /> + <el-table-column align="center" prop="repairEndDate" :formatter="timeDate" label="维修结束日期" /> + <el-table-column align="center" label="操作"> + <template #default="scope"> + <el-button link type="primary" @click="openRepair('查看', scope.row)" size="small">查看</el-button> + <el-button link type="primary" @click="openRepair('修改', scope.row)" size="small">修改</el-button> + <el-button link type="primary" @click="deleteC(scope.row)" size="small">删除</el-button> + </template> + </el-table-column> + </el-table> + </el-tab-pane> + <el-tab-pane label="检查标准设置" name="fourth"> + <el-button type="primary" size="default" :disabled="disabled" @click="openStandard('新增', '')">新增</el-button> + <el-table :data="form.checkStandardeDetailList" style="width: 100%"> + <el-table-column align="center" prop="indexNum" label="序号" width="75" /> + <el-table-column align="center" prop="checkContent" label="检查内容" /> + <el-table-column align="center" prop="checkTarget" label="检查指标" /> + <el-table-column align="center" prop="unit" label="单位" /> + <el-table-column align="center" prop="checkPart" label="巡检部位" /> + <el-table-column align="center" prop="rate" label="频次" /> + <el-table-column align="center" label="操作"> + <template #default="scope"> + <el-button link type="primary" @click="openStandard('查看', scope.row)" size="small">查看</el-button> + <el-button link type="primary" @click="openStandard('修改', scope.row)" size="small">修改</el-button> + <el-button link type="primary" @click="deleteD(scope.row)" size="small">删除</el-button> + </template> + </el-table-column> + </el-table> + </el-tab-pane> + <el-tab-pane label="巡检记录" size="default" name="five"> + <el-table :data="name" style="width: 100%"> + <el-table-column align="center" type="selection" width="75" /> + <el-table-column align="center" sortable prop="name" label="任务编号" /> + <el-table-column align="center" sortable prop="address" label="任务名称" /> + <el-table-column align="center" sortable prop="address" label="点位类型" /> + <el-table-column align="center" sortable prop="address" label="检查频次" /> + <el-table-column align="center" sortable prop="address" :formatter="timeDate" label="巡检时间" /> + <el-table-column align="center" sortable prop="address" label="巡检人" /> + </el-table> + </el-tab-pane> + <el-tab-pane label="保养维修标准" name="six" v-if="Dailogtype"> + <uploaderFile :fileList="fileList" :systemName="'EQUIPMENT'" :disabled="disabled" + @successUploader="successUploader"></uploaderFile> + </el-tab-pane> + </el-tabs> + <template #footer> + <span class="dialog-footer"> + <el-button @click="resetForm(ruleFormRef)">关闭</el-button> + <el-button type="primary" @click="submitForm(ruleFormRef)">确定</el-button> + </span> + </template> + </el-dialog> + <categoryDailog ref="categoryShow"></categoryDailog> + <categoryDailog ref="categoryShow" @typeId="Tid"></categoryDailog> + <regionDailog ref="regionShow"></regionDailog> + <DailogSearchUser ref="UserShow" @SearchUser="userId"></DailogSearchUser> + <maintenanceDailog ref="maintenanceShow" @onMain="main"></maintenanceDailog> + <detectDailog ref="detectShow" @onDelect="delect"></detectDailog> + <repairDailog ref="repairShow" @onRepair="Repair"></repairDailog> + <standardDailog ref="standardShow" @onStand="Stand"></standardDailog> +</template> +<script lang="ts"> +import { defineComponent, ref, reactive } from 'vue'; +import { Search, FullScreen } from '@element-plus/icons-vue'; +import categoryDailog from './categoryDailog.vue'; +import regionDailog from './regionDailog.vue'; +import maintenanceDailog from './maintenanceDailog.vue'; +import detectDailog from './detectDailog.vue'; +import repairDailog from './repairDailog.vue'; +import { timeDate } from '/@/assets/index.ts'; +import standardDailog from './standardDailog.vue'; +import DailogSearchUser from '/@/components/DailogSearchUser/index.vue'; +import { ElMessage, ElMessageBox, FormInstance, FormRules } from 'element-plus'; +import type { UploadProps, UploadUserFile } from 'element-plus'; +import { facilityManagementApi } from '/@/api/facilityManagement'; +import { goalManagementApi } from '/@/api/goalManagement'; +import { deepClone } from '/@/utils/other'; +import uploaderFile from '/@/components/uploaderFile/index.vue'; +export default defineComponent({ + components: { categoryDailog, regionDailog, DailogSearchUser, maintenanceDailog, + detectDailog, repairDailog, standardDailog,uploaderFile }, + setup(props, { emit }) { + const dialogVisible = ref(false); + const ruleFormRef = ref<FormInstance>(); + const form = ref({ + supplyName: '', + + nextTestDate: '', + + qUsage: '', + + departmentId: '', + + produceTime: '', + + actualStopDate: '', + + takecareDetailList: [], + + infoType: '', + + leadingDepartmentId: '', + + useEndDay: '', + + previousTakecareDate: '', + + previousCheckDate: '', + + model: '', + + stopStatus: '', + + testWarn: '', + + stopSubmitDate: '', + + repairStatus: '', + + takecareStardardeDetailList: [ + ], + + nextCheckDate: '', + + checkCycle: '', + + checkPoint: '', + + leadingPersonId: '', + leadingPersonName: '', + + qName: '', + + nextTakecareDate: '', + + setPart: '', + + checkStandardeDetailList: [], + + actualDestoryDate: '', + + isNeedTest: '', + + alertNum: '', + + checkContent: '', + + useMemo: '', + + previousTestDate: '', + + isNeedTakecare: '', + + destoryReason: '', + + checkDetailList: [], + + positionNum: '', + + testCycle: '', + + recoveryReason: '', + + isNeedCheck: '', + + actualRecoveryDate: '', + + leadingPersonDepartmentId: '', + + stopReason: '', + + destorySubmitDate: '', + + testDetailList: [], + + checkWarn: '', + + repaireDetailList: [], + + equipmentTypeId: '', + + useDate: '', + + recoverySubmitDate: '', + takecareCycle:"", + + lockNum: '', + + stopSubmitPersonId: '', + stopSubmitPersonName: '', + afterStopStep: '', + + lifeCycle: '', + + delCheckStandardeDetails: '', + + delTakecareStardardeDetails: '', + + delTakecareDetails: '', + + delRepaireDetails: '', + + delTestDetails: '', + }); + const titles = ref(); + const titleT = ref(); + const disabled = ref(false); + const Dailogtype = ref(false); + const openDailog = (title: string, type: boolean, id: number, num: any) => { + dialogVisible.value = true; + titleT.value = title; + department(); + Dailogtype.value = type; + if (num == 0) { + titles.value = `${title}仪表信息`; + form.value.infoType = num; + } else if (num == 1) { + titles.value = `${title}设备设施`; + form.value.infoType = num; + } else if (num == 2) { + titles.value = `${title}设备设施`; + form.value.infoType = num; + } + + disabled.value = title == '查看' ? true : false; + if (title == '查看' || title == '修改') + facilityManagementApi() + .getequipmentInfoDetail(id) + .then((res) => { + if (res.data.code == 200) { + form.value = res.data.data; + + //初始化日期格式 + form.value.actualDestoryDate = timeC(form.value.actualDestoryDate); + form.value.actualRecoveryDate = timeC(form.value.actualRecoveryDate); + form.value.actualStopDate = timeC(form.value.actualStopDate); + form.value.destorySubmitDate = timeC(form.value.destorySubmitDate); + form.value.nextCheckDate = timeC(form.value.nextCheckDate); + form.value.nextTakecareDate = timeC(form.value.nextTakecareDate); + form.value.nextTestDate = timeC(form.value.nextTestDate); + form.value.previousCheckDate = timeC(form.value.previousCheckDate); + form.value.previousTakecareDate = timeC(form.value.previousTakecareDate); + form.value.previousTestDate = timeC(form.value.previousTestDate); + form.value.produceTime = timeC(form.value.produceTime); + form.value.recoverySubmitDate = timeC(form.value.recoverySubmitDate); + form.value.stopSubmitDate = timeC(form.value.stopSubmitDate); + form.value.useDate = timeC(form.value.useDate); + + fileList.value = (res.data.data.takecareStardardeDetailList?res.data.data.takecareStardardeDetailList:[]) + initFileListData() + } else { + ElMessage.error(res.data.msg); + } + }); + }; + const timeC = (timestamp: any) => { + let a = new Date(timestamp).getTime(); + const date = new Date(a); + const Y = date.getFullYear() + '-'; + const M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-'; + const D = (date.getDate() < 10 ? '0' + date.getDate() : date.getDate()) + ' '; + const h = (date.getHours() < 10 ? '0' + date.getHours() : date.getHours()) + ':'; + const m = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes(); + const s = date.getSeconds(); // 秒 + const dateString = Y + M + D + h + m +`:${s}`; + // console.log('dateString', dateString); // > dateString 2021-07-06 14:23 + return dateString; + }; + const initFileListData = async () => { + for(var a = 0;a<fileList.value.length;a++){ + fileList.value[a].name = fileList.value[a].filePath + } + } + // 上传成功组装数据 + const successUploader = (list) =>{ + fileList.value = list + const formFileList = [] + for(var a = 0;a<fileList.value.length;a++){ + formFileList.push( + { + filePath:fileList.value[a].fileName + } + ) + } + form.value.takecareStardardeDetailList = formFileList + } + const rules = reactive<FormRules>({ + qName: [], + positionNum: [], + qUsage: [], + model: [], + equipmentTypeId: [], + equipmentTypeName: [{ required: true, message: '类型/类别外键不能为空', trigger: 'change' }], + departmentId: [], + setPart: [], + produceTime: [], + useEndDay: [], + lifeCycle: [], + useDate: [], + repairStatus: [], + stopStatus: [], + previousCheckDate: [], + previousTestDate: [], + previousTakecareDate: [], + nextCheckDate: [], + nextTestDate: [], + nextTakecareDate: [], + leadingPersonName: [], + leadingPersonDepartmentId: [], + supplyName: [], + useMemo: [], + isNeedCheck: [], + checkCycle: [], + checkWarn: [], + isNeedTest: [], + testCycle: [], + testWarn: [], + isNeedTakecare: [], + checkContent: [], + leadingDepartmentId: [], + checkPoint: [], + alertNum: [], + lockNum: [], + stopReason: [], + afterStopStep: [], + actualStopDate: [], + stopSubmitPersonName: [], + stopSubmitDate: [], + recoveryReason: [], + recoverySubmitDate: [], + actualRecoveryDate: [], + destoryReason: [], + destorySubmitDate: [], + actualDestoryDate: [], + takecareCycle :[] + }); + // 提交 + const submitForm = async (formEl: FormInstance | undefined) => { + if (!formEl) return; + await formEl.validate((valid, fields) => { + if (valid) { + form.value.delTakecareDetails = deleteAId.value.toString(); + form.value.delTestDetails = deleteBId.value.toString(); + form.value.delRepaireDetails = deleteCId.value.toString(); + form.value.delCheckStandardeDetails = deleteDId.value.toString(); + dialogVisible.value = false; + delete form.value.equipmentTypeName; + delete form.value.departmentName; + delete form.value.leadingPersonDepartmentName; + delete form.value.leadingDepartmentName; + if (titleT.value == '新建') { + delete form.value.id; + } + facilityManagementApi() + .getequipmentInfoAddOrUpdate(form.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + message: res.data.msg, + type: 'success', + }); + emit('navAddorUpdata'); + } else { + ElMessage.error(res.data.msg); + } + }); + } + }); + form.value.takecareDetailList = []; + form.value.testDetailList = []; + form.value.repaireDetailList = []; + form.value.checkStandardeDetailList = []; + }; + // 取消 + const resetForm = (formEl: FormInstance | undefined) => { + if (!formEl) return; + formEl.resetFields(); + form.value.takecareDetailList = []; + form.value.testDetailList = []; + form.value.repaireDetailList = []; + form.value.checkStandardeDetailList = []; + fileList.value = [] + dialogVisible.value = false; + }; + const activeName = ref('first'); + const index = ref<any>(); + const categoryShow = ref(); + const opencategory = () => { + categoryShow.value.openDailog(); + }; + const regionShow = ref(); + const openRegion = () => { + regionShow.value.openDailog(); + }; + const UserShow = ref(); + const openUser = (type: any) => { + UserShow.value.openDailog(type); + }; + const maintenanceShow = ref(); + const openMaintenance = (title: string, data: any) => { + index.value = form.value.takecareDetailList.indexOf(data); + maintenanceShow.value.openDailog(title, data); + }; + const detectShow = ref(); + const openDetect = (title: string, data: any) => { + index.value = form.value.testDetailList.indexOf(data); + detectShow.value.openDailog(title, data); + }; + const repairShow = ref(); + const openRepair = (title: string, data: any) => { + index.value = form.value.repaireDetailList.indexOf(data); + repairShow.value.openDailog(title, data); + }; + const standardShow = ref(); + const openStandard = (title: string, data: any) => { + index.value = form.value.checkStandardeDetailList.indexOf(data); + standardShow.value.openDailog(title, data); + }; + // 上传 + const fileList = ref([]); + + const handleRemove: UploadProps['onRemove'] = (file, uploadFiles) => { + console.log(file, uploadFiles); + }; + + const handlePreview: UploadProps['onPreview'] = (uploadFile) => { + console.log(uploadFile); + }; + + const handleExceed: UploadProps['onExceed'] = (files, uploadFiles) => { + ElMessage.warning(`The limit is 3, you selected ${files.length} files this time, add up to ${files.length + uploadFiles.length} totally`); + }; + + const beforeRemove: UploadProps['beforeRemove'] = (uploadFile, uploadFiles) => { + return ElMessageBox.confirm(`Cancel the transfert of ${uploadFile.name} ?`).then( + () => true, + () => false + ); + }; + const deleteAId = ref([]); + const deleteBId = ref([]); + const deleteCId = ref([]); + const deleteDId = ref([]); + // 删除 + const deleteA = (tag: any) => { + form.value.takecareDetailList.splice(form.value.takecareDetailList.indexOf(tag), 1); + deleteAId.value.push(tag.id); + }; + const deleteB = (tag: any) => { + form.value.testDetailList.splice(form.value.testDetailList.indexOf(tag), 1); + deleteBId.value.push(tag.id); + }; + const deleteC = (tag: any) => { + form.value.repaireDetailList.splice(form.value.repaireDetailList.indexOf(tag), 1); + deleteCId.value.push(tag.id); + }; + const deleteD = (tag: any) => { + form.value.checkStandardeDetailList.splice(form.value.checkStandardeDetailList.indexOf(tag), 1); + deleteDId.value.push(tag.id); + }; + // 回传 + const main = (data: any) => { + const val = deepClone(data); + if (index.value == -1) { + form.value.takecareDetailList.push(val); + } else { + form.value.takecareDetailList[index.value] = val; + } + }; + const delect = (data: any) => { + const val = deepClone(data); + if (index.value == -1) { + form.value.testDetailList.push(val); + } else { + form.value.testDetailList[index.value] = val; + } + }; + const Repair = (data: any) => { + const val = deepClone(data); + if (index.value == -1) { + form.value.repaireDetailList.push(val); + } else { + form.value.repaireDetailList[index.value] = val; + } + }; + const Stand = (data: any) => { + const val = deepClone(data); + if (index.value == -1) { + form.value.checkStandardeDetailList.push(val); + } else { + form.value.checkStandardeDetailList[index.value] = val; + } + }; + const userId = (val: any, type: number) => { + console.log(val, type); + if (type == 1) { + form.value.leadingPersonId = val.uid; + form.value.leadingPersonName = val.realName; + } else if (type == 2) { + form.value.stopSubmitPersonId = val.uid; + form.value.stopSubmitPersonName = val.realName; + } + }; + const Tid = (data: any) => { + form.value.equipmentTypeId = data.id; + form.value.equipmentTypeName = data.typeName; + form.value.positionNum = data.sortNum; + }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + //部门树 + const department = () => { + goalManagementApi() + .getTreedepartment() + .then((res) => { + if (res.data.code == 200) { + data.value = res.data.data; + } else { + ElMessage.error(res.data.msg); + } + }); + }; + const propse = { + label: 'depName', + children: 'children', + value: 'depId', + }; + const data = ref(); + return { + Tid, + deepClone, + rules, + userId, + department, + propse, + data, + deleteAId, + deleteBId, + deleteCId, + deleteDId, + deleteA, + deleteB, + deleteC, + deleteD, + main, + index, + delect, + Repair, + Stand, + resetForm, + submitForm, + titles, + dialogVisible, + disabled, + Dailogtype, + form, + openDailog, + Search, + activeName, + categoryShow, + opencategory, + regionShow, + openRegion, + UserShow, + openUser, + maintenanceShow, + openMaintenance, + detectShow, + openDetect, + repairShow, + openRepair, + standardShow, + openStandard, + fileList, + handleRemove, + handlePreview, + handleExceed, + beforeRemove, + full, + toggleFullscreen, + FullScreen, + timeDate, + ruleFormRef, + successUploader, + initFileListData, + timeC + }; + }, +}); +</script> +<style scoped> +.el-form-item { + width: 25vw; +} +.formType:after { + content: ''; + width: 400px; +} +.formType { + padding: 20px 20px; + display: flex; + justify-content: space-between; + flex-wrap: wrap; +} +.el-form .el-form-item:last-of-type { + margin-bottom: 22px !important; +} +</style> diff --git a/src/components/equipmentDailog/DailogS.vue b/src/components/equipmentDailog/DailogS.vue new file mode 100644 index 0000000..db4c2a4 --- /dev/null +++ b/src/components/equipmentDailog/DailogS.vue @@ -0,0 +1,701 @@ +<template> + <el-dialog :fullscreen="full" v-model="dialogVisible" draggable :title="titles" width="60%" @close="resetForm(ruleFormRef)" > + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-form :model="form" ref="ruleFormRef" label-width="130px" :rules="rules" :disabled="disabled"> + <el-row> + <el-col :span="11"> + <el-form-item label="类型/类别外键" size="default" prop="equipmentTypeId"> + <el-input v-model="form.equipmentTypeName" placeholder="请选择"> + <template #append> + <el-button :icon="Search" @click="opencategory"></el-button> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="装置/部位名称" size="default"> + <el-input v-model="form.name" placeholder="请填写装置/部位名称" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="11"> + <el-form-item label="所属部门" size="default"> + <el-tree-select v-model="form.departmentId" :data="data" check-strictly="true" placeholder="请选择" :props="propse" style="width: 100%"> + </el-tree-select> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="具体位置" size="default"> + <el-input v-model="form.position" placeholder="请填写具体位置" /> + </el-form-item> + </el-col> + </el-row> + + <el-row> + <el-col :span="11"> + <el-form-item label="负责人姓名" size="default"> + <el-input v-model="form.leadingPersonName" placeholder="请填写负责人姓名" /> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="联系人" size="default" prop="connectPersonName"> + <el-input v-model="form.connectPersonName" placeholder="请选择"> + <template #append> + <el-button :icon="Search" @click="openUser(1)"></el-button> + </template> + </el-input> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="11"> + <el-form-item label="录入人" size="default" prop="inputPersonName"> + <el-input v-model="form.inputPersonName" placeholder="请选择"> + <template #append> + <el-button :icon="Search" @click="openUser(2)"></el-button> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="责任人" size="default" prop="responsibilityPersonName"> + <el-input v-model="form.responsibilityPersonName" placeholder="请选择"> + <template #append> + <el-button :icon="Search" @click="openUser(3)"></el-button> + </template> + </el-input> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="11"> + <el-form-item label="装置部位分类" size="default"> + <el-select v-model="form.partType" placeholder="请选择" style="width: 100%"> + <el-option label="关键装置" value="1" /> + <el-option label="重点部位" value="2" /> + </el-select> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="检查周期" size="default"> + <el-input v-model="form.checkCycle" placeholder="请填写检查周期" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="11"> + <el-form-item label="相关应急预案" size="default"> + <el-input v-model="form.emergencePlanName" placeholder="请选择"> + <template #append> + <el-button :icon="Search" @click="openPlan"></el-button> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="主要危险有害因素" size="default"> + <el-input v-model="form.dangerousElement" placeholder="请填写主要危险有害因素" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="11"> + <el-form-item label="易导致风险" size="default"> + <el-input v-model="form.toDangerous" placeholder="请填写易导致风险" /> + </el-form-item> + </el-col> + + <el-col :span="11" :offset="2"> + <el-form-item label="应急处置措施" size="default"> + <el-input v-model="form.treatment" placeholder="请填写应急处置措施" /> + </el-form-item> + </el-col> + </el-row> + + <el-row> + <el-col :span="24"> + <el-form-item label="现场图片"> + <el-upload + v-model="form.scenePic" + class="avatar-uploader" + action="https://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15" + :show-file-list="false" + :on-success="handleAvatarSuccess" + :before-upload="beforeAvatarUpload" + > + <img v-if="imageUrl" :src="imageUrl" class="avatar" /> + <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon> + </el-upload> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="11"> + <el-form-item label="备注信息" size="default"> <el-input v-model="form.memo" placeholder="请填写备注信息" /> </el-form-item> + </el-col> + </el-row> + </el-form> + <el-tabs v-model="activeName" class="demo-tabs"> + <el-tab-pane label="设备保养" name="first"> + <el-button type="primary" size="default" @click="openMaintenance('新增', '')" :disabled="disabled">新增</el-button> + <el-table :data="form.takecareDetailList" style="width: 100%"> + <el-table-column align="center" prop="takecareMemo" label="保养情况" /> + <el-table-column align="center" prop="leadingPersonName" label="保养负责人" /> + <el-table-column align="center" prop="takecareDate" :formatter="timeDate" label="保养日期" /> + <el-table-column align="center" prop="leadingPersonDepartmentName" label="保养负责人单位" /> + <el-table-column align="center" label="操作"> + <template #default="scope"> + <el-button link type="primary" @click="openMaintenance('查看', scope.row)" size="small" :disabled="disabled">查看</el-button> + <el-button link type="primary" @click="openMaintenance('修改', scope.row)" size="small" :disabled="disabled">修改</el-button> + <el-button link type="primary" @click="deleteA(scope.row)" size="small" :disabled="disabled">删除</el-button> + </template> + </el-table-column> + </el-table> + </el-tab-pane> + <el-tab-pane label="设备检测" name="second"> + <el-button type="primary" size="default" @click="openDetect('新增', '')" :disabled="disabled">新增</el-button> + <el-table :data="form.checkDetailList" style="width: 100%"> + <el-table-column align="center" prop="testPersonName" label="检测人" /> + <el-table-column align="center" prop="testDate" :formatter="timeDate" label="检测日期" /> + <el-table-column align="center" prop="testPersonDepartmentName" label="检测人单位" /> + <el-table-column align="center" prop="testMemo" label="检测内容" /> + <el-table-column align="center" prop="testResult" label="检测结果" > + <template #default="scope"> + <span v-if="scope.row.testResult == 1">成功</span> + <span v-if="scope.row.testResult == 2">失败</span> + </template> + </el-table-column> + <el-table-column align="center" prop="testStatus" label="检测状态" /> + <el-table-column align="center" label="操作"> + <template #default="scope"> + <el-button link type="primary" @click="openDetect('查看', scope.row)" size="small" :disabled="disabled">查看</el-button> + <el-button link type="primary" @click="openDetect('修改', scope.row)" size="small" :disabled="disabled">修改</el-button> + <el-button link type="primary" @click="deleteB(scope.row)" size="small" :disabled="disabled">删除</el-button> + </template> + </el-table-column> + </el-table> + </el-tab-pane> + <el-tab-pane label="设备维修" name="third"> + <el-button type="primary" size="default" @click="openRepair('新增', '')" :disabled="disabled">新增</el-button> + <el-table :data="form.repaireDetailList" style="width: 100%"> + <el-table-column align="center" prop="exceptionInfo" label="设施异常项" /> + <el-table-column align="center" prop="repairStatus" label="维修状态" > + <template #default="scope"> + <span v-if="scope.row.repairStatus == 1">维修中</span> + <span v-if="scope.row.repairStatus == 2">已维修</span> + </template> + </el-table-column> + <el-table-column align="center" prop="repairMemo" label="维修情况" /> + <el-table-column align="center" prop="repairPersonName" label="维修负责人" /> + <el-table-column align="center" prop="repairPersonDepartmentName" label="维修负责人单位" /> + <el-table-column align="center" prop="repairStartDate" :formatter="timeDate" label="维修开始日期" /> + <el-table-column align="center" prop="repairEndDate" :formatter="timeDate" label="维修结束日期" /> + <el-table-column align="center" label="操作"> + <template #default="scope"> + <el-button link type="primary" @click="openRepair('查看', scope.row)" size="small" :disabled="disabled">查看</el-button> + <el-button link type="primary" @click="openRepair('修改', scope.row)" size="small" :disabled="disabled">修改</el-button> + <el-button link type="primary" @click="deleteC(scope.row)" size="small" :disabled="disabled">删除</el-button> + </template> + </el-table-column> + </el-table> + </el-tab-pane> + <el-tab-pane label="检查标准设置" name="fourth"> + <el-button type="primary" size="default" @click="openStandard('新增', '')" :disabled="disabled">新增</el-button> + <el-table :data="form.checkStandardeDetailList" style="width: 100%"> + <el-table-column align="center" prop="indexNum" label="序号" width="75" /> + <el-table-column align="center" prop="checkContent" label="检查内容" /> + <el-table-column align="center" prop="checkTarget" label="检查指标" /> + <el-table-column align="center" prop="unit" label="单位" /> + <el-table-column align="center" prop="checkPart" label="巡检部位" /> + <el-table-column align="center" prop="rate" label="频次" /> + <el-table-column align="center" label="操作"> + <template #default="scope"> + <el-button link type="primary" @click="openStandard('查看', scope.row)" size="small" :disabled="disabled">查看</el-button> + <el-button link type="primary" @click="openStandard('修改', scope.row)" size="small" :disabled="disabled">修改</el-button> + <el-button link type="primary" @click="deleteD(scope.row)" size="small" :disabled="disabled">删除</el-button> + </template> + </el-table-column> + </el-table> + </el-tab-pane> + <el-tab-pane label="巡检记录" name="five"> + <el-table :data="name" style="width: 100%"> + <el-table-column align="center" type="selection" width="75" /> + <el-table-column align="center" sortable prop="name" label="任务编号" /> + <el-table-column align="center" sortable prop="address" label="任务名称" /> + <el-table-column align="center" sortable prop="address" label="点位类型" /> + <el-table-column align="center" sortable prop="address" label="检查频次" /> + <el-table-column align="center" sortable prop="address" :formatter="timeDate" label="巡检时间" /> + <el-table-column align="center" sortable prop="address" label="巡检人" /> + </el-table> + </el-tab-pane> + <el-tab-pane label="保养维修标准" name="six" v-if="Dailogtype"> + <el-upload + v-model:file-list="fileList" + class="upload-demo" + action="https://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15" + multiple + :on-preview="handlePreview" + :on-remove="handleRemove" + :before-remove="beforeRemove" + :limit="3" + :on-exceed="handleExceed" + > + <el-button type="primary">点击上传</el-button> + <template #tip> + <div class="el-upload__tip"></div> + </template> + </el-upload> + </el-tab-pane> + </el-tabs> + <template #footer> + <span class="dialog-footer"> + <el-button @click="resetForm(ruleFormRef)">关闭</el-button> + <el-button type="primary" @click="submitForm(ruleFormRef)">确定</el-button> + </span> + </template> + </el-dialog> + <categoryDailog ref="categoryShow" @typeId="Tid"></categoryDailog> + <RegionsDialog ref="planShow" @SearchUser="onUser"></RegionsDialog> + <DailogSearchUser ref="UserShow" @SearchUser="userId"></DailogSearchUser> + <maintenanceDailog ref="maintenanceShow" @onMain="main"></maintenanceDailog> + <detectDailog ref="detectShow" @onDelect="delect"></detectDailog> + <repairDailog ref="repairShow" @onRepair="Repair"></repairDailog> + <standardDailog ref="standardShow" @onStand="Stand"></standardDailog> +</template> +<script lang="ts"> +import { defineComponent, ref ,reactive} from 'vue'; +import { Search, Plus, FullScreen } from '@element-plus/icons-vue'; +import { timeDate } from '/@/assets/index.ts'; +import categoryDailog from './categoryDailog.vue'; +import RegionsDialog from '../../views/contingencyManagement/emergencyDrill/releaseOfDrillPlan/component/regionsDialog.vue'; +import maintenanceDailog from './maintenanceDailog.vue'; +import detectDailog from './detectDailog.vue'; +import repairDailog from './repairDailog.vue'; +import standardDailog from './standardDailog.vue'; +import DailogSearchUser from '/@/components/DailogSearchUser/index.vue'; +import { ElMessage, ElMessageBox ,FormInstance ,FormRules,} from 'element-plus'; +import type { UploadProps, UploadUserFile } from 'element-plus'; +import { facilityManagementApi } from '/@/api/facilityManagement'; +import { goalManagementApi } from '/@/api/goalManagement'; +import {deepClone} from '/@/utils/other' +export default defineComponent({ + components: { categoryDailog,Plus, RegionsDialog, DailogSearchUser, maintenanceDailog, detectDailog, repairDailog, standardDailog }, + setup(props, { emit }) { + const dialogVisible = ref(false); + const form = ref({ + equipmentTypeId: 1, + equipmentTypeName:"", + treatment: '', + + inputPersonId: '', + inputPersonName: '', + departmentId: '', + + // delRepaireDetailList: [], + + // delTestDetailList: [], + + takecareDetailList: [], + checkDetailList: [], + + responsibilityPersonId: '', + responsibilityPersonName: '', + // delTakecareStardardeDetailList: [], + + connectPersonId: '', + connectPersonName: '', + + scenePic: '', + + partType: '', + + toDangerous: '', + + dangerousElement: '', + memo:'', + + takecareStardardeDetailList: [ + { + filePath: '', + }, + ], + testDetailList: [], + checkCycle: '', + repaireDetailList: [], + // delCheckStandardeDetailList: [], + + leadingPersonName: '', + + name: '', + + // delTakecareDetailList: [], + + position: '', + + emergencePlanId: '', + emergencePlanName:'', + + checkStandardeDetailList: [], + infoTpe: '', + delCheckStandardeDetails: '', + + delTakecareStardardeDetails: '', + + delTakecareDetails: '', + + delRepaireDetails: '', + + delTestDetails: '', + }); + const ruleFormRef = ref<FormInstance>(); + const titles = ref(); + const titleT = ref(); + const disabled = ref(false); + const Dailogtype = ref(false); + const openDailog = (title: string, type: boolean, id: number, num: any) => { + dialogVisible.value = true; + titleT.value = title; + department(); + Dailogtype.value = type; + if (num == 0) { + titles.value = `${title}仪表信息`; + form.value.infoTpe = num; + } else if (num == 1) { + titles.value = `${title}设备设施`; + form.value.infoTpe = num; + } else if (num == 2) { + titles.value = `${title}设备设施`; + form.value.infoTpe = num; + } + + disabled.value = title == '查看' ? true : false; + if (title == '查看' || title == '修改') + facilityManagementApi() + .getkeypointEquipmentInfoDetail(id) + .then((res) => { + if (res.data.code == 200) { + form.value = res.data.data; + } else { + ElMessage.error(res.data.msg); + } + }); + }; + // 提交 + const submitForm = () => { + form.value.delTakecareDetails = deleteAId.value.toString(); + form.value.delTestDetails = deleteBId.value.toString(); + form.value.delRepaireDetails = deleteCId.value.toString(); + form.value.delCheckStandardeDetails = deleteDId.value.toString(); + dialogVisible.value = false; + if (titleT.value == '新建') { + delete form.value.id; + delete form.value.infoTpe + } + facilityManagementApi() + .getkeypointEquipmentInfoAddOrUpdate(form.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + message: res.data.msg, + type: 'success', + }); + emit('navAddorUpdata'); + } else { + ElMessage.error(res.data.msg); + } + }); + // form.value = null; + }; + // 取消 + const resetForm = (formEl: FormInstance | undefined) => { + if (!formEl) return; + formEl.resetFields(); + dialogVisible.value = false; + form.value={} + }; + const activeName = ref('first'); + const index = ref<any>(); + const categoryShow = ref(); + const opencategory = () => { + categoryShow.value.openDailog(); + }; + + // 应急预案弹窗 + const planShow = ref(); + const openPlan = () => { + planShow.value.openDailog(); + }; + const onUser = (e: any) => { + form.value.emergencePlanId = e.id; + form.value.emergencePlanName=e.name + }; + + const UserShow = ref(); + const openUser = (type: any) => { + UserShow.value.openDailog(type); + }; + const userId = (val: any, type: number) => { + if (type == 1) { + form.value.connectPersonId = val.uid; + form.value.connectPersonName = val.realName; + } else if (type == 2) { + form.value.inputPersonId = val.uid; + form.value.inputPersonName = val.realName; + } else if (type == 3) { + form.value.responsibilityPersonId = val.id; + form.value.responsibilityPersonName = val.realName; + } + }; + const Tid=(data:any)=>{ + form.value.equipmentTypeId=data.id + form.value.equipmentTypeName=data.typeName + } + const maintenanceShow = ref(); + const openMaintenance = (title: string, data: any) => { + index.value = form.value.takecareDetailList.indexOf(data); + maintenanceShow.value.openDailog(title, data); + }; + const detectShow = ref(); + const openDetect = (title: string, data: any) => { + index.value = form.value.testDetailList.indexOf(data); + detectShow.value.openDailog(title, data); + }; + const repairShow = ref(); + const openRepair = (title: string, data: any) => { + index.value = form.value.repaireDetailList.indexOf(data); + repairShow.value.openDailog(title, data); + }; + const standardShow = ref(); + const openStandard = (title: string, data: any) => { + index.value = form.value.checkStandardeDetailList.indexOf(data); + standardShow.value.openDailog(title, data); + }; + // 上传 + const fileList = ref<UploadUserFile[]>([ + { + name: 'element-plus-logo.svg', + url: 'https://element-plus.org/images/element-plus-logo.svg', + }, + { + name: 'element-plus-logo2.svg', + url: 'https://element-plus.org/images/element-plus-logo.svg', + }, + ]); + + const handleRemove: UploadProps['onRemove'] = (file, uploadFiles) => { + console.log(file, uploadFiles); + }; + + const handlePreview: UploadProps['onPreview'] = (uploadFile) => { + console.log(uploadFile); + }; + + const handleExceed: UploadProps['onExceed'] = (files, uploadFiles) => { + ElMessage.warning(`The limit is 3, you selected ${files.length} files this time, add up to ${files.length + uploadFiles.length} totally`); + }; + + const beforeRemove: UploadProps['beforeRemove'] = (uploadFile, uploadFiles) => { + return ElMessageBox.confirm(`Cancel the transfert of ${uploadFile.name} ?`).then( + () => true, + () => false + ); + }; + const deleteAId = ref([]); + const deleteBId = ref([]); + const deleteCId = ref([]); + const deleteDId = ref([]); + // 删除 + const deleteA = (tag: any) => { + form.value.takecareDetailList.splice(form.value.takecareDetailList.indexOf(tag), 1); + deleteAId.value.push(tag.id); + }; + const deleteB = (tag: any) => { + form.value.testDetailList.splice(form.value.testDetailList.indexOf(tag), 1); + deleteBId.value.push(tag.id); + }; + const deleteC = (tag: any) => { + form.value.repaireDetailList.splice(form.value.repaireDetailList.indexOf(tag), 1); + deleteCId.value.push(tag.id); + }; + const deleteD = (tag: any) => { + form.value.checkStandardeDetailList.splice(form.value.checkStandardeDetailList.indexOf(tag), 1); + deleteDId.value.push(tag.id); + }; + // 回传 + const main = (data: any) => { + let val=deepClone(data) + if (index.value == -1) { + form.value.takecareDetailList.push(val); + } else { + form.value.takecareDetailList[index.value] = val; + } + }; + const delect = (data: any) => { + let val=deepClone(data) + if (index.value == -1) { + form.value.testDetailList.push(val); + } else { + form.value.testDetailList[index.value] = val; + } + }; + const Repair = (data: any) => { + let val=deepClone(data) + if (index.value == -1) { + form.value.repaireDetailList.push(val); + } else { + form.value.repaireDetailList[index.value] = val; + } + }; + const Stand = (data: any) => { + let val=deepClone(data) + if (index.value == -1) { + form.value.checkStandardeDetailList.push(val); + } else { + form.value.checkStandardeDetailList[index.value] = val; + } + }; + const rules = reactive<FormRules>({ + equipmentTypeId: [], + equipmentTypeName:[], + }) + //图片提交 + const imageUrl = ref(''); + + const handleAvatarSuccess: UploadProps['onSuccess'] = (response, uploadFile) => { + imageUrl.value = URL.createObjectURL(uploadFile.raw!); + }; + + const beforeAvatarUpload: UploadProps['beforeUpload'] = (rawFile) => { + if (rawFile.type !== 'image/jpeg') { + ElMessage.error('Avatar picture must be JPG format!'); + return false; + } else if (rawFile.size / 1024 / 1024 > 2) { + ElMessage.error('Avatar picture size can not exceed 2MB!'); + return false; + } + return true; + }; + + //部门树 + const department = () => { + goalManagementApi() + .getTreedepartment() + .then((res) => { + if (res.data.code == 200) { + data.value = res.data.data; + } else { + ElMessage.error(res.data.msg); + } + }); + }; + const propse = { + label: 'depName', + children: 'children', + value: 'depId', + }; + const data = ref(); + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + return { + propse, + data, + submitForm, + dialogVisible, + Dailogtype, + form, + openDailog, + Search, + main, + delect, + Repair, + Stand, + ruleFormRef, + index, + activeName, + categoryShow, + opencategory, + planShow, + onUser, + openPlan, + UserShow, + openUser, + rules, + maintenanceShow, + openMaintenance, + detectShow, + openDetect, + repairShow, + openRepair, + standardShow, + userId, + openStandard, + fileList, + handleRemove, + handlePreview, + handleExceed, + disabled, + titles, + beforeRemove, + imageUrl, + handleAvatarSuccess, + beforeAvatarUpload, + Plus, + full, + toggleFullscreen, + FullScreen, + Tid, + resetForm, + deleteAId, + deleteBId, + deleteCId, + deleteDId, + deleteA, + deleteB, + deleteC, + deleteD, + timeDate, + titleT, + }; + }, +}); +</script> +<style scoped> +.el-row { + padding: 0 0 20px 0; +} +.avatar-uploader .avatar { + width: 178px; + height: 178px; + display: block; +} +</style> +<style> +.avatar-uploader .el-upload { + border: 1px dashed var(--el-border-color); + border-radius: 6px; + cursor: pointer; + position: relative; + overflow: hidden; + transition: var(--el-transition-duration-fast); +} + +.avatar-uploader .el-upload:hover { + border-color: var(--el-color-primary); +} + +.el-icon.avatar-uploader-icon { + font-size: 28px; + color: #8c939d; + width: 178px; + height: 178px; + text-align: center; +} +</style> \ No newline at end of file diff --git a/src/components/equipmentDailog/categoryDailog.vue b/src/components/equipmentDailog/categoryDailog.vue new file mode 100644 index 0000000..4a8bf12 --- /dev/null +++ b/src/components/equipmentDailog/categoryDailog.vue @@ -0,0 +1,147 @@ +<template> + <el-dialog v-model="dialogVisible" :fullscreen="full" title="选择类型/类别外键" width="50%" draggable> + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-row> + <el-col :span="17"> + <!-- <el-form ref="ruleFormRef" :model="ruleForm" status-icon> + <el-row> + <el-col :span="12"> + <el-form-item size="default"> + <el-input v-model="ruleForm.pass" placeholder="类别名称" /> + </el-form-item> + </el-col> + <el-col :span="6" :offset="1"> + <el-form-item> + <el-input v-model="ruleForm.checkPass" placeholder="目标指标编号" /> + </el-form-item> + </el-col> + <el-col :span="11" :offset="1"> + <el-form-item> + <el-button size="default" type="primary" @click="submitForm(ruleFormRef)">查询</el-button> + <el-button size="default" @click="resetForm(ruleFormRef)">重置</el-button> + </el-form-item> + </el-col> + </el-row> + </el-form> --> + <el-button size="default" :icon="Delete" @click="clear">清除选择</el-button> + <el-table :data="tableData" style="width: 100%; margin-top: 20px" row-key="id" :tree-props="propse"> + <el-table-column align="center" width="100px"> + <template #default="scope"> + <el-radio-group v-model="radio1"> + <el-radio :label="scope.row.id" @click="radio(scope.row)" size="large">{{ null }}</el-radio> + </el-radio-group> + </template> + </el-table-column> + <el-table-column align="center" prop="id" label="id" /> + <el-table-column align="center" prop="typeName" label="类别名称" /> + </el-table> + </el-col> + <el-col :span="7"> + <div v-if="dynamicTags[0]==''?false:true"> + <el-tag + v-for="tag in dynamicTags" + :key="tag" + class="mx-1" + style="margin: 5px" + closable + :disable-transitions="false" + @close="handleClose(tag)" + > + {{ tag.typeName }} + </el-tag> + </div> + </el-col> + </el-row> + <template #footer> + <span class="dialog-footer"> + <el-button @click="dialogVisible = false" size="default">关闭</el-button> + <el-button type="primary" @click="submitForm" size="default">确定</el-button> + </span> + </template> + </el-dialog> +</template> +<script lang="ts"> +import { defineComponent, reactive, ref } from 'vue'; +import { Delete, FullScreen } from '@element-plus/icons-vue'; +import { facilityManagementApi } from '/@/api/facilityManagement'; +import { ElMessage,ElMessageBox } from 'element-plus'; +export default defineComponent({ + setup(props,{emit}) { + const dialogVisible = ref<boolean>(false); + const openDailog = () => { + dialogVisible.value = true; + listApi() + }; + // 列表 + const listApi = () => { + facilityManagementApi() + .getequipmentTypeMngTreeData() + .then((res) => { + if (res.data.code == 200) { + tableData.value = res.data.data; + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + } + }); + }; + // 表格 + const tableData = ref([]) + const propse = { + children: 'childList', + }; + // 右方点击添加后显示标签 + const dynamicTags = ref(['']); + const handleClose = (tag: string) => { + dynamicTags.value.splice(dynamicTags.value.indexOf(tag), 1); + radio1.value = ''; + }; + const radio1 = ref(''); + const radio = (data: any) => { + dynamicTags.value[0] = data + }; + const clear=()=>{ + radio1.value="" + dynamicTags.value=[''] + } + const submitForm=()=>{ + emit('typeId',dynamicTags.value[0]) + dialogVisible.value=false + } + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + return { + submitForm, + clear, + dialogVisible, + openDailog, + listApi, + propse, + tableData, + dynamicTags, + handleClose, + radio1, + radio, + Delete, + full, + toggleFullscreen, + FullScreen, + }; + }, +}); +</script> +<style scoped> +.el-row { + padding: 0 0 20px 0; +} +</style> diff --git a/src/components/equipmentDailog/detectDailog.vue b/src/components/equipmentDailog/detectDailog.vue new file mode 100644 index 0000000..654f54c --- /dev/null +++ b/src/components/equipmentDailog/detectDailog.vue @@ -0,0 +1,194 @@ +<template> + <el-dialog v-model="dialogVisible" @close="resetForm(ruleFormRef)" :fullscreen="full" :title="titles" width="50%" draggable> + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-form :model="form" ref="ruleFormRef" :rules="rules" :disabled="disabled" label-width="120px"> + <el-row> + <el-col :span="11"> + <el-form-item label="检测人" size="default" prop="testPersonName"> + <el-input v-model="form.testPersonName"> + <template #append> <el-button :icon="Search" @click="openUser" /> </template + ></el-input> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="检测日期" size="default" prop="testDate"> + <el-date-picker v-model="form.testDate" format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss" type="datetime" placeholder="选择日期时间" style="width: 100%" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="11"> + <el-form-item label="检测人单位" size="default" prop="testPersonDepartmentId"> + <el-tree-select + v-model="form.testPersonDepartmentId" + :data="data" + check-strictly="true" + class="w100" + :props="propse" + placeholder="请选择" + /> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="检测内容" size="default" prop="testMemo"> + <el-input v-model="form.testMemo" placeholder="请填写检测内容" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="11"> + <el-form-item label="检测结果" size="default" prop="testResult"> + <el-select v-model="form.testResult" placeholder="请选择" style="width: 100%"> + <el-option label="成功" value="1" /> + <el-option label="失败" value="2" /> + </el-select> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="检测状态" size="default" prop="testStatus"> + <el-input v-model="form.testStatus" placeholder="请填写检测状态" /> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <!-- <el-button type="primary" @click="dialogVisible = false" size="default">继续添加</el-button> --> + <el-button @click="resetForm(ruleFormRef)" size="default">关闭</el-button> + <el-button type="primary" @click="submitForm(ruleFormRef)" :disabled="disabled" size="default">确定</el-button> + </span> + </template> + </el-dialog> + <DailogSearchUser ref="Show" @SearchUser="User"></DailogSearchUser> +</template> +<script lang="ts"> +import { defineComponent, ref, reactive } from 'vue'; +import { ElMessage, ElMessageBox } from 'element-plus'; +import type { FormInstance, FormRules } from 'element-plus'; +import { Search, FullScreen } from '@element-plus/icons-vue'; +import DailogSearchUser from '/@/components/DailogSearchUser/index.vue'; +import { goalManagementApi } from '/@/api/goalManagement'; +export default defineComponent({ + components: { DailogSearchUser }, + setup(props, { emit }) { + const ruleFormRef = ref<FormInstance>(); + const form = ref({ + testPersonId: '', + testPersonName: '', + testDate: '', + testPersonDepartmentId: '', + testMemo: '', + testResult: '', + testStatus: '', + }); + // 开启弹窗 + const titles = ref(); + const disabled = ref(false); + const dialogVisible = ref(false); + const openDailog = (title: string, data: any) => { + department(); + dialogVisible.value = true; + titles.value = `${title}设备检测`; + if (title == '查看') { + disabled.value = true; + form.value = data; + } else if (title == '修改') { + disabled.value = false; + form.value = data; + } + }; + // 开启用户弹窗 + const Show = ref(); + const openUser = () => { + Show.value.openDailog(); + }; + const User = (val: any) => { + form.value.testPersonId = val.uid; + form.value.testPersonName = val.realName; + }; + const rules = reactive<FormRules>({ + testPersonName: [{ required: true, message: '检测人不能为空', trigger: 'blur' }], + testDate:[{ required: true, message: '检测日期不能为空', trigger: 'blur' }], + testPersonDepartmentId:[], + testMemo:[{ required: true, message: '检测内容不能为空', trigger: 'blur' }], + testResult:[{ required: true, message: '检测结果不能为空', trigger: 'blur' }], + testStatus:[{ required: true, message: '检测状态不能为空', trigger: 'blur' }], + }); + // 提交 + const submitForm = async (formEl: FormInstance | undefined) => { + if (!formEl) return; + await formEl.validate((valid, fields) => { + if (valid) { + emit('onDelect', form.value); + dialogVisible.value = false; + } else { + console.log('error submit!', fields); + } + }); + + disabled.value = false; + }; + // 取消 + const resetForm = (formEl: FormInstance | undefined) => { + if (!formEl) return; + formEl.clearValidate(); + dialogVisible.value = false; + disabled.value = false; + form.value={} + }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + //部门树 + const department = () => { + goalManagementApi() + .getTreedepartment() + .then((res) => { + if (res.data.code == 200) { + data.value = res.data.data; + } else { + ElMessage.error(res.data.msg); + } + }); + }; + const propse = { + label: 'depName', + children: 'children', + value: 'depId', + }; + const data = ref(); + return { + ruleFormRef, + rules, + department, + propse, + data, + form, + titles, + User, + disabled, + dialogVisible, + openDailog, + submitForm, + resetForm, + Show, + openUser, + Search, + full, + toggleFullscreen, + FullScreen, + }; + }, +}); +</script> +<style scoped> +.el-row { + padding: 0 0 20px 0; +} +</style> diff --git a/src/components/equipmentDailog/maintenanceDailog.vue b/src/components/equipmentDailog/maintenanceDailog.vue new file mode 100644 index 0000000..3a22bc9 --- /dev/null +++ b/src/components/equipmentDailog/maintenanceDailog.vue @@ -0,0 +1,206 @@ +<template> + <el-dialog :fullscreen="full" v-model="dialogVisible" @close="resetForms(ruleFormRefs)" :title="titles" width="50%" draggable> + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-form :model="form" ref="ruleFormRefs" :rules="rules" :disabled="disabled" label-width="120px"> + <el-row> + <el-col :span="11"> + <el-form-item label="保养情况" size="default" prop="takecareMemo"> + <el-input v-model="form.takecareMemo" /> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="保养负责人" size="default" prop="leadingPersonName"> + <el-input v-model="form.leadingPersonName"> + <template #append> <el-button :icon="Search" @click="openUser" /> </template + ></el-input> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="11"> + <el-form-item label="保养日期" size="default" prop="takecareDate"> + <el-date-picker + v-model="form.takecareDate" + format="YYYY-MM-DD HH:mm:ss" + value-format="YYYY-MM-DD HH:mm:ss" + type="datetime" + style="width: 100%" + /> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="保养负责人单位" size="default" prop="leadingPersonDepartmentId"> + <el-tree-select + v-model="form.leadingPersonDepartmentId" + :data="data" + check-strictly="true" + class="w100" + :props="propse" + placeholder="请选择" + /> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <!-- <el-button type="primary" @click="dialogVisible = false" size="default">继续添加</el-button> --> + <el-button @click="resetForms(ruleFormRefs)" size="default">关闭</el-button> + <el-button type="primary" @click="submitForms(ruleFormRefs)" :disabled="disabled" size="default">确定</el-button> + </span> + </template> + </el-dialog> + <DailogSearchUser ref="Show" @SearchUser="User"></DailogSearchUser> +</template> +<script lang="ts"> +import { defineComponent, ref, reactive } from 'vue'; +import { ElMessage, ElMessageBox } from 'element-plus'; +import { Search, FullScreen } from '@element-plus/icons-vue'; +import type { FormInstance, FormRules } from 'element-plus'; +import DailogSearchUser from '/@/components/DailogSearchUser/index.vue'; +import { goalManagementApi } from '/@/api/goalManagement'; +export default defineComponent({ + components: { DailogSearchUser }, + setup(props, { emit }) { + const ruleFormRefs = ref<FormInstance>(); + const form = ref({ + takecareMemo: '', + leadingPersonId: '', + leadingPersonName: '', + takecareDate: '', + leadingPersonDepartmentId: '', + }); + // 开启弹窗 + const titles = ref(); + const disabled = ref(false); + const dialogVisible = ref(false); + const openDailog = (title: string, data: any) => { + department(); + dialogVisible.value = true; + titles.value = `${title}仪器仪表`; + if (title == '查看') { + disabled.value = true; + form.value = data; + } else if (title == '修改') { + disabled.value = false; + form.value = data; + } + }; + const rules = reactive<FormRules>({ + takecareMemo: [ + { + required: true, + message: '保养情况不能为空', + trigger: 'blur', + }, + ], + leadingPersonName: [ + { + required: true, + message: '保养负责人不能为空', + trigger: 'blur', + }, + ], + takecareDate: [ + { + required: true, + message: '保养日期不能为空', + trigger: 'blur', + }, + ], + leadingPersonDepartmentId: [ + { + required: true, + message: '保养负责人单位不能为空', + trigger: 'blur', + }, + ], + }); + // 开启用户弹窗 + const Show = ref(); + const openUser = () => { + Show.value.openDailog(); + }; + const User = (val: any) => { + form.value.leadingPersonId = val.uid; + form.value.leadingPersonName = val.realName; + }; + // 提交 + const submitForms = async (formEl: FormInstance | undefined) => { + if (!formEl) return; + await formEl.validate((valid, fields) => { + if (valid) { + dialogVisible.value = false; + emit('onMain', form.value); + } else { + console.log('error submit!', fields); + } + }); + disabled.value = false; + }; + // 取消 + const resetForms = (formEl: FormInstance | undefined) => { + if (!formEl) return; + formEl.clearValidate(); + + disabled.value = false; + form.value = {}; + + dialogVisible.value = false; + }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + //部门树 + const department = () => { + goalManagementApi() + .getTreedepartment() + .then((res) => { + if (res.data.code == 200) { + data.value = res.data.data; + } else { + ElMessage.error(res.data.msg); + } + }); + }; + const propse = { + label: 'depName', + children: 'children', + value: 'depId', + }; + const data = ref(); + return { + department, + propse, + data, + disabled, + rules, + titles, + submitForms, + resetForms, + form, + User, + dialogVisible, + openDailog, + ruleFormRefs, + Show, + openUser, + Search, + full, + toggleFullscreen, + FullScreen, + }; + }, +}); +</script> +<style scoped> +.el-row { + padding: 0 0 20px 0; +} +</style> diff --git a/src/components/equipmentDailog/planDailog.vue b/src/components/equipmentDailog/planDailog.vue new file mode 100644 index 0000000..d79f2d7 --- /dev/null +++ b/src/components/equipmentDailog/planDailog.vue @@ -0,0 +1,156 @@ +<template> + <el-dialog v-model="dialogVisible" :fullscreen="full" title="选择所属重大危险源单元" width="50%" draggable> + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-row> + <el-col :span="17"> + <el-form ref="ruleFormRef" :model="ruleForm" status-icon> + <el-row> + <el-col :span="12"> + <el-form-item size="default"> + <el-input v-model="ruleForm.pass" placeholder="预案名称" /> + </el-form-item> + </el-col> + <el-col :span="11" :offset="1"> + <el-form-item> + <el-button size="default" type="primary" @click="submitForm(ruleFormRef)">查询</el-button> + <el-button size="default" @click="resetForm(ruleFormRef)">重置</el-button> + </el-form-item> + </el-col> + </el-row> + </el-form> + <el-button size="default" :icon="Delete">清除选择</el-button> + <el-table :data="tableData" style="width: 100%; margin-top: 20px"> + <el-table-column align="center" width="80"> + <template #default="scope"> + <el-radio-group v-model="radio1" @change="radio"> + <el-radio :label="scope.row.date" size="large">{{ null }}</el-radio> + </el-radio-group> + </template> + </el-table-column> + <!-- <el-table-column align="center" prop="date" label="id"/> --> + <el-table-column align="center" prop="name" label="预案名称" /> + </el-table> + <el-pagination + style="padding: 20px 0; border-bottom: 1px solid #dedede" + v-model:currentPage="currentPage4" + v-model:page-size="pageSize4" + :page-sizes="[100, 200, 300, 400]" + :small="small" + :disabled="disabled" + :background="background" + layout="total, sizes, prev, pager, next, jumper" + :total="400" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </el-col> + <el-col :span="7"> + <el-tag + v-for="tag in dynamicTags" + :key="tag" + class="mx-1" + style="margin: 5px" + closable + :disable-transitions="false" + @close="handleClose(tag)" + > + {{ tag }} + </el-tag> + </el-col> + </el-row> + <template #footer> + <span class="dialog-footer"> + <el-button @click="dialogVisible = false" size="default">关闭</el-button> + <el-button type="primary" @click="dialogVisible = false" size="default">确定</el-button> + </span> + </template> + </el-dialog> +</template> +<script lang="ts"> +import { defineComponent, reactive, ref } from 'vue'; +import { Delete, FullScreen } from '@element-plus/icons-vue'; +export default defineComponent({ + setup() { + const dialogVisible = ref<boolean>(false); + const openDailog = () => { + dialogVisible.value = true; + }; + // 搜索条件 + const ruleForm = reactive({ + pass: '', + checkPass: '', + }); + // 表格 + const tableData = [ + { + date: '2016-05-03', + name: 'Tom', + address: 'No. 189, Grove St, Los Angeles', + }, + { + date: '2016-05-02', + name: 'Tom', + address: 'No. 189, Grove St, Los Angeles', + }, + { + date: '2016-05-04', + name: 'Tom', + address: 'No. 189, Grove St, Los Angeles', + }, + { + date: '2016-05-01', + name: 'Tom', + address: 'No. 189, Grove St, Los Angeles', + }, + ]; + const pageSize4 = ref(100); + const handleSizeChange = (val: number) => { + console.log(`${val} items per page`); + }; + const handleCurrentChange = (val: number) => { + console.log(`current page: ${val}`); + }; + // 右方点击添加后显示标签 + const dynamicTags = ref(['2016-05-03']); + const handleClose = (tag: string) => { + dynamicTags.value.splice(dynamicTags.value.indexOf(tag), 1); + radio1.value = ''; + }; + const radio1 = ref('2016-05-03'); + const radio = (event: any) => { + dynamicTags.value[0] = event; + }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + return { + dialogVisible, + openDailog, + ruleForm, + tableData, + pageSize4, + handleSizeChange, + handleCurrentChange, + dynamicTags, + handleClose, + radio1, + radio, + Delete, + full, + toggleFullscreen, + FullScreen, + }; + }, +}); +</script> +<style scoped> +.el-row { + padding: 0 0 20px 0; +} +</style> \ No newline at end of file diff --git a/src/components/equipmentDailog/regionDailog.vue b/src/components/equipmentDailog/regionDailog.vue new file mode 100644 index 0000000..66c37a4 --- /dev/null +++ b/src/components/equipmentDailog/regionDailog.vue @@ -0,0 +1,156 @@ +<template> + <el-dialog v-model="dialogVisible" :fullscreen="full" title="选择区域名称" width="50%" draggable> + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-row> + <el-col :span="17"> + <el-form ref="ruleFormRef" :model="ruleForm" status-icon> + <el-row> + <el-col :span="12"> + <el-form-item size="default"> + <el-input v-model="ruleForm.pass" placeholder="风险区域名称" /> + </el-form-item> + </el-col> + <el-col :span="11" :offset="1"> + <el-form-item> + <el-button size="default" type="primary" @click="submitForm(ruleFormRef)">查询</el-button> + <el-button size="default" @click="resetForm(ruleFormRef)">重置</el-button> + </el-form-item> + </el-col> + </el-row> + </el-form> + <el-button size="default" :icon="Delete">清除选择</el-button> + <el-table :data="tableData" style="width: 100%; margin-top: 20px"> + <el-table-column align="center" width="80"> + <template #default="scope"> + <el-radio-group v-model="radio1" @change="radio"> + <el-radio :label="scope.row.date" size="large">{{ null }}</el-radio> + </el-radio-group> + </template> + </el-table-column> + <!-- <el-table-column align="center" prop="date" label="id"/> --> + <el-table-column align="center" prop="name" label="风险区域名称" /> + </el-table> + <el-pagination + style="padding: 20px 0; border-bottom: 1px solid #dedede" + v-model:currentPage="currentPage4" + v-model:page-size="pageSize4" + :page-sizes="[100, 200, 300, 400]" + :small="small" + :disabled="disabled" + :background="background" + layout="total, sizes, prev, pager, next, jumper" + :total="400" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </el-col> + <el-col :span="7"> + <el-tag + v-for="tag in dynamicTags" + :key="tag" + class="mx-1" + style="margin: 5px" + closable + :disable-transitions="false" + @close="handleClose(tag)" + > + {{ tag }} + </el-tag> + </el-col> + </el-row> + <template #footer> + <span class="dialog-footer"> + <el-button @click="dialogVisible = false" size="default">关闭</el-button> + <el-button type="primary" @click="dialogVisible = false" size="default">确定</el-button> + </span> + </template> + </el-dialog> +</template> +<script lang="ts"> +import { defineComponent, reactive, ref } from 'vue'; +import { Delete, FullScreen } from '@element-plus/icons-vue'; +export default defineComponent({ + setup() { + const dialogVisible = ref<boolean>(false); + const openDailog = () => { + dialogVisible.value = true; + }; + // 搜索条件 + const ruleForm = reactive({ + pass: '', + checkPass: '', + }); + // 表格 + const tableData = [ + { + date: '2016-05-03', + name: 'Tom', + address: 'No. 189, Grove St, Los Angeles', + }, + { + date: '2016-05-02', + name: 'Tom', + address: 'No. 189, Grove St, Los Angeles', + }, + { + date: '2016-05-04', + name: 'Tom', + address: 'No. 189, Grove St, Los Angeles', + }, + { + date: '2016-05-01', + name: 'Tom', + address: 'No. 189, Grove St, Los Angeles', + }, + ]; + const pageSize4 = ref(100); + const handleSizeChange = (val: number) => { + console.log(`${val} items per page`); + }; + const handleCurrentChange = (val: number) => { + console.log(`current page: ${val}`); + }; + // 右方点击添加后显示标签 + const dynamicTags = ref(['2016-05-03']); + const handleClose = (tag: string) => { + dynamicTags.value.splice(dynamicTags.value.indexOf(tag), 1); + radio1.value = ''; + }; + const radio1 = ref('2016-05-03'); + const radio = (event: any) => { + dynamicTags.value[0] = event; + }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + return { + dialogVisible, + openDailog, + ruleForm, + tableData, + pageSize4, + handleSizeChange, + handleCurrentChange, + dynamicTags, + handleClose, + radio1, + radio, + Delete, + full, + toggleFullscreen, + FullScreen, + }; + }, +}); +</script> +<style scoped> +.el-row { + padding: 0 0 20px 0; +} +</style> \ No newline at end of file diff --git a/src/components/equipmentDailog/repairDailog.vue b/src/components/equipmentDailog/repairDailog.vue new file mode 100644 index 0000000..18e0663 --- /dev/null +++ b/src/components/equipmentDailog/repairDailog.vue @@ -0,0 +1,216 @@ +<template> + <el-dialog v-model="dialogVisible" :fullscreen="full" @close="resetForm(ruleFormRef)" :title="titles" width="50%" draggable> + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-form :model="form" ref="ruleFormRef" :rules="rules" :disabled="disabled" label-width="120px"> + <el-row> + <el-col :span="11"> + <el-form-item label="设施异常项" size="default" prop="exceptionInfo"> + <el-input v-model="form.exceptionInfo" placeholder="请填写设施异常项" /> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="维修状态" size="default" prop="repairStatus"> + <el-select v-model="form.repairStatus" placeholder="请选择" style="width: 100%"> + <el-option label="维修中" :value="1" /> + <el-option label="已修好" :value="2" /> + </el-select> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="11"> + <el-form-item label="维修情况" size="default" prop="repairMemo"> + <el-input v-model="form.repairMemo" placeholder="请填写维修情况" /> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="维修负责人" size="default" prop="repairPersonName"> + <el-input v-model="form.repairPersonName" placeholder="请选择"> + <template #append> <el-button :icon="Search" @click="openUser" /> </template + ></el-input> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="11"> + <el-form-item label="维修负责人单位" size="default" prop="repairPersonDepartmentId"> + <el-tree-select + v-model="form.repairPersonDepartmentId" + :data="data" + check-strictly="true" + class="w100" + :props="propse" + placeholder="请选择" + /> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="维修开始日期" size="default" prop="repairStartDate"> + <el-date-picker + v-model="form.repairStartDate" + format="YYYY-MM-DD HH:mm:ss" + value-format="YYYY-MM-DD HH:mm:ss" + type="datetime" + placeholder="选择日期时间" + style="width: 100%" + /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="11"> + <el-form-item label="维修结束日期" size="default" prop="repairEndDate"> + <el-date-picker + v-model="form.repairEndDate" + format="YYYY-MM-DD HH:mm:ss" + value-format="YYYY-MM-DD HH:mm:ss" + type="datetime" + placeholder="选择日期时间" + style="width: 100%" + /> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <!-- <el-button type="primary" @click="dialogVisible = false" size="default">继续添加</el-button> --> + <el-button @click="resetForm(ruleFormRef)" size="default">关闭</el-button> + <el-button type="primary" @click="submitForm(ruleFormRef)" :disabled="disabled" size="default">确定</el-button> + </span> + </template> + </el-dialog> + <DailogSearchUser ref="Show" @SearchUser="User"></DailogSearchUser> +</template> +<script lang="ts"> +import { defineComponent, ref, reactive } from 'vue'; +import { ElMessage, ElMessageBox } from 'element-plus'; +import type { FormInstance, FormRules } from 'element-plus'; +import { Search, FullScreen } from '@element-plus/icons-vue'; +import DailogSearchUser from '/@/components/DailogSearchUser/index.vue'; +import { goalManagementApi } from '/@/api/goalManagement'; +export default defineComponent({ + components: { DailogSearchUser }, + setup(props, { emit }) { + const ruleFormRef = ref<FormInstance>(); + const form = ref({ + exceptionInfo: '', + repairStatus: '', + repairMemo: '', + repairPersonId: '', + repairPersonName: '', + repairPersonDepartmentId: '', + repairStartDate: '', + repairEndDate: '', + }); + // 开启弹窗 + const titles = ref(); + const disabled = ref(false); + const dialogVisible = ref(false); + const openDailog = (title: string, data: any) => { + department(); + dialogVisible.value = true; + titles.value = `${title}设备维修`; + if (title == '查看') { + disabled.value = true; + form.value = data; + } else if (title == '修改') { + disabled.value = false; + form.value = data; + } + }; + // 开启用户弹窗 + const Show = ref(); + const openUser = () => { + Show.value.openDailog(); + }; + const User = (val: any) => { + form.value.repairPersonId = val.uid; + form.value.repairPersonName = val.realName; + }; + const rules = reactive<FormRules>({ + exceptionInfo: [{ required: true, message: '设施异常项不能为空', trigger: 'blur' }], + repairStatus: [{ required: true, message: '维修状态不能为空', trigger: 'blur' }], + repairMemo: [{ required: true, message: '维修情况不能为空', trigger: 'blur' }], + // repairPersonName: [{ required: true, message: '维修负责人不能为空', trigger: 'blur' }], + repairPersonDepartmentId: [{ required: true, message: '维修负责人单位不能为空', trigger: 'blur' }], + repairStartDate: [{ required: true, message: '维修开始日期不能为空', trigger: 'blur' }], + repairEndDate: [{ required: true, message: '维修结束日期不能为空', trigger: 'blur' }], + }); + // 提交 + const submitForm = async (formEl: FormInstance | undefined) => { + if (!formEl) return; + await formEl.validate((valid, fields) => { + if (valid) { + emit('onRepair', form.value); + dialogVisible.value = false; + } else { + console.log('error submit!', fields); + } + }); + disabled.value = false; + }; + // 取消 + const resetForm = (formEl: FormInstance | undefined) => { + if (!formEl) return; + formEl.clearValidate(); + disabled.value = false; + dialogVisible.value = false; + form.value = {}; + }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + //部门树 + const department = () => { + goalManagementApi() + .getTreedepartment() + .then((res) => { + if (res.data.code == 200) { + data.value = res.data.data; + } else { + ElMessage.error(res.data.msg); + } + }); + }; + const propse = { + label: 'depName', + children: 'children', + value: 'depId', + }; + const data = ref(); + return { + rules, + ruleFormRef, + department, + propse, + data, + form, + titles, + disabled, + dialogVisible, + openDailog, + Show, + User, + openUser, + submitForm, + resetForm, + Search, + full, + toggleFullscreen, + FullScreen, + }; + }, +}); +</script> +<style scoped> +.el-row { + padding: 0 0 20px 0; +} +</style> \ No newline at end of file diff --git a/src/components/equipmentDailog/standardDailog.vue b/src/components/equipmentDailog/standardDailog.vue new file mode 100644 index 0000000..7964ba0 --- /dev/null +++ b/src/components/equipmentDailog/standardDailog.vue @@ -0,0 +1,151 @@ +<template> + <el-dialog v-model="dialogVisible" :fullscreen="full" @close="resetForm(ruleFormRef)" :title="titles" width="50%" draggable> + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-form :model="form" ref="ruleFormRef" :rules="rules" label-width="120px" :disabled="disabled"> + <el-row> + <el-col :span="11"> + <el-form-item label="序号" size="default" prop="indexNum"> + <el-input v-model="form.indexNum" placeholder="请填写序号" /> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2" size="default" prop="checkContent"> + <el-form-item label="检查内容"> + <el-input v-model="form.checkContent" placeholder="请填写检查内容" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="11"> + <el-form-item label="检查指标" size="default" prop="checkTarget"> + <el-input v-model="form.checkTarget" placeholder="请填写检查指标" /> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="单位" size="default" prop="unit"> + <el-input v-model="form.unit" placeholder="请填写单位" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="11"> + <el-form-item label="巡检部位" size="default" prop="checkPart"> + <el-input v-model="form.checkPart" placeholder="请填写巡检部位" /> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="频次" size="default" prop="rate"> + <el-input v-model="form.rate" placeholder="请填写频次" /> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <!-- <el-button type="primary" @click="dialogVisible = false" size="default">继续添加</el-button> --> + <el-button @click="resetForm(ruleFormRef)" size="default">关闭</el-button> + <el-button type="primary" @click="submitForm(ruleFormRef)" size="default">确定</el-button> + </span> + </template> + </el-dialog> + <!-- <DailogSearchUser ref="Show"></DailogSearchUser> --> +</template> +<script lang="ts"> +import { defineComponent, ref, reactive } from 'vue'; +import type { FormInstance, FormRules } from 'element-plus'; +import { Search, FullScreen } from '@element-plus/icons-vue'; +import DailogSearchUser from '/@/components/DailogSearchUser/index.vue'; +export default defineComponent({ + components: { DailogSearchUser }, + setup(props, { emit }) { + const ruleFormRef = ref<FormInstance>(); + const form = ref({ + indexNum: '', + checkContent: '', + checkTarget: '', + unit: '', + checkPart: '', + rate: '', + }); + // 开启弹窗 + const titles = ref(); + const disabled = ref(false); + const dialogVisible = ref(false); + const openDailog = (title: string, data: any) => { + dialogVisible.value = true; + titles.value = `${title}检查标准设置`; + if (title == '查看') { + disabled.value = true; + form.value = data; + } else if (title == '修改') { + disabled.value = false; + form.value = data; + } + }; + // 开启用户弹窗 + const Show = ref(); + const openUser = () => { + Show.value.openDailog(); + }; + const rules = reactive<FormRules>({ + indexNum: [{ required: true, message: '序号不能为空', trigger: 'blur' }], + checkContent: [{ required: true, message: '检查内容不能为空', trigger: 'blur' }], + checkTarget: [{ required: true, message: '检查指标不能为空', trigger: 'blur' }], + unit: [{ required: true, message: '单位不能为空', trigger: 'blur' }], + checkPart: [{ required: true, message: '巡检部位不能为空', trigger: 'blur' }], + rate: [{ required: true, message: '频次不能为空', trigger: 'blur' }], + }); + // 提交 + const submitForm = async (formEl: FormInstance | undefined) => { + if (!formEl) return; + await formEl.validate((valid, fields) => { + if (valid) { + emit('onStand', form.value); + dialogVisible.value = false; + } else { + console.log('error submit!', fields); + } + }); + disabled.value = false; + }; + // 取消 + const resetForm = (formEl: FormInstance | undefined) => { + if (!formEl) return; + formEl.clearValidate(); + dialogVisible.value = false; + disabled.value = false; + form.value = {}; + }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + return { + rules, + ruleFormRef, + form, + titles, + disabled, + dialogVisible, + openDailog, + submitForm, + resetForm, + Show, + openUser, + Search, + full, + toggleFullscreen, + FullScreen, + }; + }, +}); +</script> +<style scoped> +.el-row { + padding: 0 0 20px 0; +} +</style> \ No newline at end of file diff --git a/src/components/iconSelector/index.vue b/src/components/iconSelector/index.vue new file mode 100644 index 0000000..07de786 --- /dev/null +++ b/src/components/iconSelector/index.vue @@ -0,0 +1,252 @@ +<template> + <div class="icon-selector w100 h100"> + <el-popover + placement="bottom" + :width="fontIconWidth" + trigger="click" + transition="el-zoom-in-top" + popper-class="icon-selector-popper" + @show="onPopoverShow" + > + <template #reference> + <el-input + v-model="fontIconSearch" + :placeholder="fontIconPlaceholder" + :clearable="clearable" + :disabled="disabled" + :size="size" + ref="inputWidthRef" + @clear="onClearFontIcon" + @focus="onIconFocus" + @blur="onIconBlur" + > + <template #prepend> + <SvgIcon + :name="fontIconPrefix === '' ? prepend : fontIconPrefix" + class="font14" + v-if="fontIconPrefix === '' ? prepend?.indexOf('ele-') > -1 : fontIconPrefix?.indexOf('ele-') > -1" + /> + <i v-else :class="fontIconPrefix === '' ? prepend : fontIconPrefix" class="font14"></i> + </template> + </el-input> + </template> + <template #default> + <div class="icon-selector-warp"> + <div class="icon-selector-warp-title flex"> + <div class="flex-auto">{{ title }}</div> + <div class="icon-selector-warp-title-tab" v-if="type === 'all'"> + <span :class="{ 'span-active': fontIconType === 'ali' }" @click="onIconChange('ali')" class="ml10" title="iconfont 图标">ali</span> + <span :class="{ 'span-active': fontIconType === 'ele' }" @click="onIconChange('ele')" class="ml10" title="elementPlus 图标">ele</span> + <span :class="{ 'span-active': fontIconType === 'awe' }" @click="onIconChange('awe')" class="ml10" title="fontawesome 图标">awe</span> + </div> + </div> + <div class="icon-selector-warp-row"> + <el-scrollbar ref="selectorScrollbarRef"> + <el-row :gutter="10" v-if="fontIconSheetsFilterList.length > 0"> + <el-col :xs="6" :sm="4" :md="4" :lg="4" :xl="4" @click="onColClick(v)" v-for="(v, k) in fontIconSheetsFilterList" :key="k"> + <div class="icon-selector-warp-item" :class="{ 'icon-selector-active': fontIconPrefix === v }"> + <div class="flex-margin"> + <div class="icon-selector-warp-item-value"> + <SvgIcon :name="v" /> + </div> + </div> + </div> + </el-col> + </el-row> + <el-empty :image-size="100" v-if="fontIconSheetsFilterList.length <= 0" :description="emptyDescription"></el-empty> + </el-scrollbar> + </div> + </div> + </template> + </el-popover> + </div> +</template> + +<script lang="ts"> +import { ref, toRefs, reactive, onMounted, nextTick, computed, watch, defineComponent } from 'vue'; +import initIconfont from '/@/utils/getStyleSheets'; + +export default defineComponent({ + name: 'iconSelector', + emits: ['update:modelValue', 'get', 'clear'], + props: { + // 输入框前置内容 + prepend: { + type: String, + default: () => 'ele-Pointer', + }, + // 输入框占位文本 + placeholder: { + type: String, + default: () => '请输入内容搜索图标或者选择图标', + }, + // 输入框占位文本 + size: { + type: String, + default: () => 'default', + }, + // 弹窗标题 + title: { + type: String, + default: () => '请选择图标', + }, + // icon 图标类型 + type: { + type: String, + default: () => 'ele', + }, + // 禁用 + disabled: { + type: Boolean, + default: () => false, + }, + // 是否可清空 + clearable: { + type: Boolean, + default: () => true, + }, + // 自定义空状态描述文字 + emptyDescription: { + type: String, + default: () => '无相关图标', + }, + // 双向绑定值,默认为 modelValue, + // 参考:https://v3.cn.vuejs.org/guide/migration/v-model.html#%E8%BF%81%E7%A7%BB%E7%AD%96%E7%95%A5 + // 参考:https://v3.cn.vuejs.org/guide/component-custom-events.html#%E5%A4%9A%E4%B8%AA-v-model-%E7%BB%91%E5%AE%9A + modelValue: String, + }, + setup(props, { emit }) { + const inputWidthRef = ref(); + const selectorScrollbarRef = ref(); + const state = reactive({ + fontIconPrefix: '', + fontIconWidth: 0, + fontIconSearch: '', + fontIconTabsIndex: 0, + fontIconSheetsList: [], + fontIconPlaceholder: '', + fontIconType: 'ali', + fontIconShow: true, + }); + // 处理 input 获取焦点时,modelValue 有值时,改变 input 的 placeholder 值 + const onIconFocus = () => { + if (!props.modelValue) return false; + state.fontIconSearch = ''; + state.fontIconPlaceholder = props.modelValue; + }; + // 处理 input 失去焦点时,为空将清空 input 值,为点击选中图标时,将取原先值 + const onIconBlur = () => { + setTimeout(() => { + const icon = state.fontIconSheetsList.filter((icon: string) => icon === state.fontIconSearch); + if (icon.length <= 0) state.fontIconSearch = ''; + }, 300); + }; + // 处理 icon 双向绑定数值回显 + const initModeValueEcho = () => { + if (props.modelValue === '') return ((<string | undefined>state.fontIconPlaceholder) = props.placeholder); + (<string | undefined>state.fontIconPlaceholder) = props.modelValue; + (<string | undefined>state.fontIconPrefix) = props.modelValue; + }; + // 处理 icon type 类型为 all 时,类型 ali、ele、awe 回显问题 + const initFontIconTypeEcho = () => { + if ((<any>props.modelValue)?.indexOf('iconfont') > -1) onIconChange('ali'); + else if ((<any>props.modelValue)?.indexOf('ele-') > -1) onIconChange('ele'); + else if ((<any>props.modelValue)?.indexOf('fa') > -1) onIconChange('awe'); + else onIconChange('ali'); + }; + // 图标搜索及图标数据显示 + const fontIconSheetsFilterList = computed(() => { + if (!state.fontIconSearch) return state.fontIconSheetsList; + let search = state.fontIconSearch.trim().toLowerCase(); + return state.fontIconSheetsList.filter((item: any) => { + if (item.toLowerCase().indexOf(search) !== -1) return item; + }); + }); + // 获取 input 的宽度 + const getInputWidth = () => { + nextTick(() => { + state.fontIconWidth = inputWidthRef.value.$el.offsetWidth; + }); + }; + // 监听页面宽度改变 + const initResize = () => { + window.addEventListener('resize', () => { + getInputWidth(); + }); + }; + // 初始化数据 + const initFontIconData = async (type: string) => { + state.fontIconSheetsList = []; + if (type === 'ali') { + await initIconfont.ali().then((res: any) => { + // 阿里字体图标使用 `iconfont xxx` + state.fontIconSheetsList = res.map((i: string) => `iconfont ${i}`); + }); + } else if (type === 'ele') { + await initIconfont.ele().then((res: any) => { + state.fontIconSheetsList = res; + }); + } else if (type === 'awe') { + await initIconfont.awe().then((res: any) => { + // fontawesome字体图标使用 `fa xxx` + state.fontIconSheetsList = res.map((i: string) => `fa ${i}`); + }); + } + // 初始化 input 的 placeholder + // 参考(单项数据流):https://cn.vuejs.org/v2/guide/components-props.html?#%E5%8D%95%E5%90%91%E6%95%B0%E6%8D%AE%E6%B5%81 + state.fontIconPlaceholder = props.placeholder; + // 初始化双向绑定回显 + initModeValueEcho(); + }; + // 图标点击切换 + const onIconChange = (type: string) => { + state.fontIconType = type; + initFontIconData(type); + }; + // 获取当前点击的 icon 图标 + const onColClick = (v: any) => { + state.fontIconPlaceholder = v; + state.fontIconPrefix = v; + emit('get', state.fontIconPrefix); + emit('update:modelValue', state.fontIconPrefix); + }; + // 清空当前点击的 icon 图标 + const onClearFontIcon = () => { + state.fontIconPrefix = ''; + emit('clear', state.fontIconPrefix); + emit('update:modelValue', state.fontIconPrefix); + }; + // 监听 Popover 打开,用于双向绑定值回显 + const onPopoverShow = () => { + initModeValueEcho(); + initFontIconTypeEcho(); + }; + // 页面加载时 + onMounted(() => { + initModeValueEcho(); + initResize(); + getInputWidth(); + }); + + // 监听双向绑定 modelValue 的变化 + watch( + () => props.modelValue, + () => { + initModeValueEcho(); + } + ); + return { + inputWidthRef, + selectorScrollbarRef, + fontIconSheetsFilterList, + onColClick, + onIconChange, + onClearFontIcon, + onIconFocus, + onIconBlur, + onPopoverShow, + ...toRefs(state), + }; + }, +}); +</script> diff --git a/src/components/noticeBar/index.vue b/src/components/noticeBar/index.vue new file mode 100644 index 0000000..6a81bfd --- /dev/null +++ b/src/components/noticeBar/index.vue @@ -0,0 +1,195 @@ +<template> + <div class="notice-bar" :style="{ background, height: `${height}px` }" v-show="!isMode"> + <div class="notice-bar-warp" :style="{ color, fontSize: `${size}px` }"> + <i v-if="leftIcon" class="notice-bar-warp-left-icon" :class="leftIcon"></i> + <div class="notice-bar-warp-text-box" ref="noticeBarWarpRef"> + <div class="notice-bar-warp-text" ref="noticeBarTextRef" v-if="!scrollable">{{ text }}</div> + <div class="notice-bar-warp-slot" v-else><slot /></div> + </div> + <SvgIcon :name="rightIcon" v-if="rightIcon" class="notice-bar-warp-right-icon" @click="onRightIconClick" /> + </div> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, defineComponent, ref, onMounted, nextTick } from 'vue'; + +export default defineComponent({ + name: 'noticeBar', + props: { + // 通知栏模式,可选值为 closeable link + mode: { + type: String, + default: () => '', + }, + // 通知文本内容 + text: { + type: String, + default: () => '', + }, + // 通知文本颜色 + color: { + type: String, + default: () => 'var(--el-color-warning)', + }, + // 通知背景色 + background: { + type: String, + default: () => 'var(--el-color-warning-light-9)', + }, + // 字体大小,单位px + size: { + type: [Number, String], + default: () => 14, + }, + // 通知栏高度,单位px + height: { + type: Number, + default: () => 40, + }, + // 动画延迟时间 (s) + delay: { + type: Number, + default: () => 1, + }, + // 滚动速率 (px/s) + speed: { + type: Number, + default: () => 100, + }, + // 是否开启垂直滚动 + scrollable: { + type: Boolean, + default: () => false, + }, + // 自定义左侧图标 + leftIcon: { + type: String, + default: () => '', + }, + // 自定义右侧图标 + rightIcon: { + type: String, + default: () => '', + }, + }, + setup(props, { emit }) { + const noticeBarWarpRef = ref(); + const noticeBarTextRef = ref(); + const state = reactive({ + order: 1, + oneTime: 0, + twoTime: 0, + warpOWidth: 0, + textOWidth: 0, + isMode: false, + }); + // 初始化 animation 各项参数 + const initAnimation = () => { + nextTick(() => { + state.warpOWidth = noticeBarWarpRef.value.offsetWidth; + state.textOWidth = noticeBarTextRef.value.offsetWidth; + document.styleSheets[0].insertRule(`@keyframes oneAnimation {0% {left: 0px;} 100% {left: -${state.textOWidth}px;}}`); + document.styleSheets[0].insertRule(`@keyframes twoAnimation {0% {left: ${state.warpOWidth}px;} 100% {left: -${state.textOWidth}px;}}`); + computeAnimationTime(); + setTimeout(() => { + changeAnimation(); + }, props.delay * 1000); + }); + }; + // 计算 animation 滚动时长 + const computeAnimationTime = () => { + state.oneTime = state.textOWidth / props.speed; + state.twoTime = (state.textOWidth + state.warpOWidth) / props.speed; + }; + // 改变 animation 动画调用 + const changeAnimation = () => { + if (state.order === 1) { + noticeBarTextRef.value.style.cssText = `animation: oneAnimation ${state.oneTime}s linear; opactity: 1;}`; + state.order = 2; + } else { + noticeBarTextRef.value.style.cssText = `animation: twoAnimation ${state.twoTime}s linear infinite; opacity: 1;`; + } + }; + // 监听 animation 动画的结束 + const listenerAnimationend = () => { + noticeBarTextRef.value.addEventListener( + 'animationend', + () => { + changeAnimation(); + }, + false + ); + }; + // 右侧 icon 图标点击 + const onRightIconClick = () => { + if (!props.mode) return false; + if (props.mode === 'closeable') { + state.isMode = true; + emit('close'); + } else if (props.mode === 'link') { + emit('link'); + } + }; + // 页面加载时 + onMounted(() => { + if (props.scrollable) return false; + initAnimation(); + listenerAnimationend(); + }); + return { + noticeBarWarpRef, + noticeBarTextRef, + onRightIconClick, + ...toRefs(state), + }; + }, +}); +</script> + +<style scoped lang="scss"> +.notice-bar { + padding: 0 15px; + width: 100%; + border-radius: 4px; + .notice-bar-warp { + display: flex; + align-items: center; + width: 100%; + height: inherit; + .notice-bar-warp-text-box { + flex: 1; + height: inherit; + display: flex; + align-items: center; + overflow: hidden; + position: relative; + .notice-bar-warp-text { + white-space: nowrap; + position: absolute; + left: 0; + } + .notice-bar-warp-slot { + width: 100%; + white-space: nowrap; + ::v-deep(.el-carousel__item) { + display: flex; + align-items: center; + } + } + } + .notice-bar-warp-left-icon { + width: 24px; + font-size: inherit !important; + } + .notice-bar-warp-right-icon { + width: 24px; + text-align: right; + font-size: inherit !important; + &:hover { + cursor: pointer; + } + } + } +} +</style> diff --git a/src/components/regionsDialog/index.vue b/src/components/regionsDialog/index.vue new file mode 100644 index 0000000..8ecb8ab --- /dev/null +++ b/src/components/regionsDialog/index.vue @@ -0,0 +1,129 @@ +<template> + <el-dialog v-model="dialogVisible" title="选择区域" width="900px" draggable :fullscreen="full"> + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-row> + <el-col :span="18"> + <el-form :inline="true" ref="ruleFormRef" :model="ruleForm" status-icon> + <el-form-item> + <el-input size="default" v-model="ruleForm.checkPass" placeholder="风险区域名称" style="max-width: 215px;" /> + </el-form-item> + <el-form-item> + <el-button size="default" type="primary" @click="submitForm(ruleFormRef)" style="margin-left: 12px;">查询</el-button> + <el-button size="default" @click="resetForm(ruleFormRef)">重置</el-button> + </el-form-item> + <el-button size="default" :icon="Delete" style="margin-left: 12px;">清除选择</el-button> + </el-form> + <el-table :data="tableData" style="width: 100%;margin-top:20px;"> + <el-table-column type="selection" width="55" /> + <el-table-column align="center" prop="name" label="风险区域名称"/> + </el-table> + <el-pagination + style="padding:20px 0;" + v-model:currentPage="currentPage4" + v-model:page-size="pageSize4" + :page-sizes="[100, 200, 300, 400]" + :small="small" + :disabled="disabled" + :background="background" + layout="total, sizes, prev, pager, next, jumper" + :total="400" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </el-col> + <el-col :span="6" style="padding-left: 15px;"> + <el-tag v-for="tag in dynamicTags" :key="tag" class="mx-1" style="margin:5px" closable :disable-transitions="false" @close="handleClose(tag)"> + {{ tag }} + </el-tag> + </el-col> + </el-row> + <template #footer> + <span class="dialog-footer"> + <el-button @click="dialogVisible = false" size="default">关闭</el-button> + <el-button type="primary" @click="dialogVisible = false" size="default">确定</el-button> + </span> + </template> + </el-dialog> +</template> +<script lang="ts"> +import { + defineComponent, + reactive, + ref +} from 'vue'; +import { + Delete, + FullScreen +} from '@element-plus/icons-vue'; +export default defineComponent({ + setup() { + const dialogVisible = ref<boolean>(false); + const openDailog = () => { + dialogVisible.value = true; + }; + // 搜索条件 + const ruleForm = reactive({ + checkPass: '', + }); + // 表格 + const tableData = [ + { + name: '1#LNG储罐单元', + }, + { + name: 'LNG装车区', + }, + { + name: '丙烷储罐区', + }, + { + name: '4#LNG储罐单元', + }, + ]; + const pageSize4 = ref(100); + const handleSizeChange = (val: number) => { + console.log(`${val} items per page`); + }; + const handleCurrentChange = (val: number) => { + console.log(`current page: ${val}`); + }; + // 右方点击添加后显示标签 + const dynamicTags = ref(['应急救援组', '工艺抢险组', '后勤保障组']); + const handleClose = (tag: string) => { + dynamicTags.value.splice(dynamicTags.value.indexOf(tag), 1); + }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + return { + dialogVisible, + openDailog, + ruleForm, + tableData, + pageSize4, + handleSizeChange, + handleCurrentChange, + dynamicTags, + handleClose, + Delete, + toggleFullscreen, + FullScreen, + full, + }; + }, +}); +</script> +<style scoped> +.el-row { + padding: 0 0 20px 0; +} +.el-form--inline .el-form-item{ + margin: 0; +} +</style> diff --git a/src/components/svgIcon/index.vue b/src/components/svgIcon/index.vue new file mode 100644 index 0000000..1fab298 --- /dev/null +++ b/src/components/svgIcon/index.vue @@ -0,0 +1,73 @@ +<template> + <i v-if="isShowIconSvg" class="el-icon" :style="setIconSvgStyle"> + <component :is="getIconName" /> + </i> + <div v-else-if="isShowIconImg" :style="setIconImgOutStyle"> + <img :src="getIconName" :style="setIconSvgInsStyle" /> + </div> + <i v-else :class="getIconName" :style="setIconSvgStyle" /> +</template> + +<script lang="ts"> +import { computed, defineComponent } from 'vue'; + +export default defineComponent({ + name: 'svgIcon', + props: { + // svg 图标组件名字 + name: { + type: String, + }, + // svg 大小 + size: { + type: Number, + default: () => 14, + }, + // svg 颜色 + color: { + type: String, + }, + }, + setup(props) { + // 在线链接、本地引入地址前缀 + const linesString = ['https', 'http', '/src', '/assets', import.meta.env.VITE_PUBLIC_PATH]; + + // 获取 icon 图标名称 + const getIconName = computed(() => { + return props?.name; + }); + // 用于判断 element plus 自带 svg 图标的显示、隐藏 + const isShowIconSvg = computed(() => { + return props?.name?.startsWith('ele-'); + }); + // 用于判断在线链接、本地引入等图标显示、隐藏 + const isShowIconImg = computed(() => { + return linesString.find((str) => props.name?.startsWith(str)); + }); + // 设置图标样式 + const setIconSvgStyle = computed(() => { + return `font-size: ${props.size}px;color: ${props.color};`; + }); + // 设置图片样式 + const setIconImgOutStyle = computed(() => { + return `width: ${props.size}px;height: ${props.size}px;display: inline-block;overflow: hidden;`; + }); + // 设置图片样式 + // https://gitee.com/lyt-top/vue-next-admin/issues/I59ND0 + const setIconSvgInsStyle = computed(() => { + const filterStyle: string[] = []; + const compatibles: string[] = ['-webkit', '-ms', '-o', '-moz']; + compatibles.forEach((j) => filterStyle.push(`${j}-filter: drop-shadow(${props.color} 30px 0);`)); + return `width: ${props.size}px;height: ${props.size}px;position: relative;left: -${props.size}px;${filterStyle.join('')}`; + }); + return { + getIconName, + isShowIconSvg, + isShowIconImg, + setIconSvgStyle, + setIconImgOutStyle, + setIconSvgInsStyle, + }; + }, +}); +</script> diff --git a/src/components/updata/updata.vue b/src/components/updata/updata.vue new file mode 100644 index 0000000..5031621 --- /dev/null +++ b/src/components/updata/updata.vue @@ -0,0 +1,89 @@ +<template> + <el-dialog v-model="dialogVisible" title="导入Excel" width="50%" :fullscreen="full" draggable> + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-upload + v-model:file-list="fileList" + class="upload-demo" + action="https://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15" + multiple + :on-preview="handlePreview" + :on-remove="handleRemove" + :before-remove="beforeRemove" + :limit="3" + :on-exceed="handleExceed" + > + <el-button>下载模板</el-button> + <el-button type="primary">点击上传</el-button> + <template #tip> + <div class="el-upload__tip">只允许导入“xls”或“xlsx”格式文件!</div> + </template> + </el-upload> + </el-dialog> +</template> +<script lang="ts"> +import { ref, toRefs, reactive, defineComponent, computed } from 'vue'; +import { ElMessage, ElMessageBox } from 'element-plus'; +import type { UploadProps, UploadUserFile } from 'element-plus'; +import { FullScreen } from '@element-plus/icons-vue'; +export default defineComponent({ + setup() { + let dialogVisible = ref<boolean>(false); + const fileList = ref<UploadUserFile[]>([ + { + name: 'element-plus-logo.svg', + url: 'https://element-plus.org/images/element-plus-logo.svg', + }, + { + name: 'element-plus-logo2.svg', + url: 'https://element-plus.org/images/element-plus-logo.svg', + }, + ]); + + const handleRemove: UploadProps['onRemove'] = (file, uploadFiles) => { + console.log(file, uploadFiles); + }; + + const handlePreview: UploadProps['onPreview'] = (uploadFile) => { + console.log(uploadFile); + }; + + const handleExceed: UploadProps['onExceed'] = (files, uploadFiles) => { + ElMessage.warning(`The limit is 3, you selected ${files.length} files this time, add up to ${files.length + uploadFiles.length} totally`); + }; + + const beforeRemove: UploadProps['beforeRemove'] = (uploadFile, uploadFiles) => { + return ElMessageBox.confirm(`Cancel the transfert of ${uploadFile.name} ?`).then( + () => true, + () => false + ); + }; + // 打开弹窗 + const openDialog = (type: string, value: any, projectList: any, projectId: string) => { + dialogVisible.value = true; + }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + }else{ + full.value = false; + } + }; + return { + dialogVisible, + fileList, + handleRemove, + handlePreview, + handleExceed, + beforeRemove, + openDialog, + full, + toggleFullscreen, + FullScreen + }; + }, +}); +</script> +<style scoped> +</style> \ No newline at end of file diff --git a/src/components/uploaderFile/index.vue b/src/components/uploaderFile/index.vue new file mode 100644 index 0000000..d747984 --- /dev/null +++ b/src/components/uploaderFile/index.vue @@ -0,0 +1,183 @@ +<template> + <el-upload + v-model:file-list="fileList" + multiple + :disabled="disabled" + class="upload-demo" + :http-request="uploadSectionFile" + :on-preview="handlePictureCardPreview" + :on-remove="handleRemove" + :on-success="successFile" + :on-error="errorFile" + > + <el-button type="primary">点击上传</el-button> + <template #tip> + <div class="el-upload__tip"> + 请上传文件 + <!--jpg/png files with a size less than 500KB.--> + </div> + <slot name="file"> + + </slot> + </template> + </el-upload> + + <!--<el-dialog v-model="dialogVisible">--> + <!--<img w-full :src="dialogImageUrl" alt="Preview Image" />--> + <!--</el-dialog>--> +</template> +<script lang="ts"> +import axios from 'axios'; +import { ref, defineComponent,onMounted,watch } from 'vue'; +import { Plus } from '@element-plus/icons-vue'; +import type { UploadProps, UploadUserFile } from 'element-plus'; +import { ElMessage } from 'element-plus'; +import { goalManagementApi } from '/@/api/goalManagement'; + +export default defineComponent({ + props: { + fileList: { + type: Array, + }, + disabled: { + type: Boolean, + default: () => false, + }, + systemName: { + type: String, + default: () => '', + }, + }, + components: { + Plus, + }, + setup(props, { emit }) { + const dialogImageUrl = ref(''); + const dialogVisible = ref(false); + + const handleRemove: UploadProps['onRemove'] = (uploadFile, uploadFiles) => { + console.log(uploadFile, uploadFiles); + emit('deleteFile',uploadFiles); + }; + + const handlePictureCardPreview: UploadProps['onPreview'] = (uploadFile) => { + console.log(uploadFile) + goalManagementApi() + .searchFile(uploadFile.name) + .then((res) => { + window.open(res.data, "_blank"); + }) + dialogImageUrl.value = uploadFile.url!; + // dialogVisible.value = true; + }; + + const successFile = (response: any, uploadFile: UploadFile, uploadFiles: UploadFiles) => { + console.log(response, uploadFile, uploadFiles); + }; + const errorFile = (error: Error, uploadFile: UploadFile, uploadFiles: UploadFiles) => { + console.log(error, uploadFile, uploadFiles); + }; + watch(props.fileList, (val) => { + viewList.value = val + // searchFile() + }); + onMounted(() => { + if(props.fileList){ + viewList.value = props.fileList + // searchFile() + }else { + viewList.value = [] + } + + }); + const newFileList = ref([]) + const viewList = ref([]) + const searchFile = async () => { + for(var a = 0;a<props.fileList.length;a++){ + await goalManagementApi() + .searchFile(props.fileList[a].fileName) + .then((res) => { + props.fileList[a].url = res.data + }) + } + }; + const uploadSectionFile = (param) => { + let form = new FormData(); + form.append('file', param.file); + //组装文件名(传入后缀名) + console.log(param) + var fileNameList = param.file.name.split('.') + var typeFile = param.file.name.split('.')[fileNameList.length-1] + var fileName1 = getFileName(param.file.type.split('/')[1], 1); + // var fileName2 = getFileName(param.file.type.split('/')[1], 2); + var fileName2 = '.'+typeFile; + goalManagementApi() + .beforeUploadFile(fileName1, fileName2) + .then((res) => { + // 转换形式 + const reader = new FileReader(); + reader.readAsArrayBuffer(param.file); + // 上传图片 + reader.onload = () => { // 上传图片接口 url:上传图片地址 修改请求头 + axios.put(res.data.uploadUrl, reader.result, + { + header: + { "Content-Type": "multipart/form-data" } + } + ) + .then(res1 => + { + props.fileList[props.fileList.length-1].fileName=res.data.fileName + props.fileList[props.fileList.length-1].name=res.data.fileName + props.fileList[props.fileList.length-1].fileUrl='' + emit('successUploader',props.fileList); + ElMessage({ + showClose: true, + message: '上传成功', + type: 'success', + }); + }) + }; + }); + }; + const getFileName = (suffix, type) => { + var projectName = props.systemName; + var date = getNowDate(); + var fileName1 = projectName + '/' + date + '_'; + var fileName2 = '.' + suffix; + if (type == 1) { + return fileName1; + } else if (type == 2) { + return fileName2; + } + return ''; + }; + + //获取当前年月日 + const getNowDate = () => { + var a = new Date().getTime(); //获取到当前时间戳 + var now = new Date(a); //创建一个指定的日期对象 + var year = now.getFullYear(); //年份 + var month = now.getMonth() + 1; //月份(0-11) + var date = now.getDate(); //天数(1到31) + return year + '-' + month + '-' + date; + }; + + return { + dialogImageUrl, + dialogVisible, + handleRemove, + handlePictureCardPreview, + successFile, + errorFile, + uploadSectionFile, + viewList + }; + }, +}); +</script> +<style scoped> + .upload-demo{ + width: 100%; + } +</style> diff --git a/src/components/uploaderImg/index.vue b/src/components/uploaderImg/index.vue new file mode 100644 index 0000000..f044082 --- /dev/null +++ b/src/components/uploaderImg/index.vue @@ -0,0 +1,158 @@ +<template> + <el-upload + v-model:file-list="fileList" + :disabled="disabled" + :http-request="uploadSectionFile" + list-type="picture-card" + :on-preview="handlePictureCardPreview" + :on-remove="handleRemove" + :on-success="successFile" + :on-error="errorFile" + > + <el-icon><Plus /></el-icon> + </el-upload> + + <el-dialog v-model="dialogVisible"> + <img w-full :src="dialogImageUrl" alt="Preview Image" /> + </el-dialog> +</template> +<script lang="ts"> +import axios from 'axios'; +import { ref, defineComponent,onMounted,watch } from 'vue'; +import { Plus } from '@element-plus/icons-vue'; +import type { UploadProps, UploadUserFile } from 'element-plus'; +import { ElMessage } from 'element-plus'; +import { goalManagementApi } from '/@/api/goalManagement'; + +export default defineComponent({ + props: { + // svg 图标组件名字 + fileList: { + type: Array, + }, + disabled: { + type: Boolean, + default: () => false, + }, + systemName: { + type: String, + default: () => '', + }, + }, + components: { + Plus, + }, + setup(props, { emit }) { + const dialogImageUrl = ref(''); + const dialogVisible = ref(false); + + const handleRemove: UploadProps['onRemove'] = (uploadFile, uploadFiles) => { + console.log(uploadFile, uploadFiles); + }; + + const handlePictureCardPreview: UploadProps['onPreview'] = (uploadFile) => { + alert(1) + dialogImageUrl.value = uploadFile.url; + dialogVisible.value = true; + }; + + const successFile = (response: any, uploadFile: UploadFile, uploadFiles: UploadFiles) => { + console.log(response, uploadFile, uploadFiles); + }; + const errorFile = (error: Error, uploadFile: UploadFile, uploadFiles: UploadFiles) => { + console.log(error, uploadFile, uploadFiles); + }; + watch(props.fileList, (val) => { + viewList.value = val + // searchFile() + }); + onMounted(() => { + if(props.fileList){ + viewList.value = props.fileList + // searchFile() + }else { + viewList.value = [] + } + + }); + const newFileList = ref([]) + const viewList = ref([]) + const searchFile = async () => { + for(var a = 0;a<props.fileList.length;a++){ + await goalManagementApi() + .searchFile(props.fileList[a].fileName) + .then((res) => { + props.fileList[a].url = res.data + }) + } + }; + const uploadSectionFile = (param) => { + let form = new FormData(); + form.append('file', param.file); + //组装文件名(传入后缀名) + var fileName1 = getFileName(param.file.type.split('/')[1], 1); + var fileName2 = getFileName(param.file.type.split('/')[1], 2); + goalManagementApi() + .beforeUploadFile(fileName1, fileName2) + .then((res) => { + // 转换形式 + const reader = new FileReader(); + reader.readAsArrayBuffer(param.file); + // 上传图片 + reader.onload = () => { // 上传图片接口 url:上传图片地址 修改请求头 + axios.put(res.data.uploadUrl, reader.result, + { + header: + { "Content-Type": "multipart/form-data" } + } + ) + .then(res1 => + { + props.fileList[props.fileList.length-1].fileName=res.data.fileName + props.fileList[props.fileList.length-1].fileUrl='' + emit('successUploader',props.fileList); + ElMessage({ + showClose: true, + message: '上传成功', + type: 'success', + }); + }) + }; + }); + }; + const getFileName = (suffix, type) => { + var projectName = props.systemName; + var date = getNowDate(); + var fileName1 = projectName + '/' + date + '_'; + var fileName2 = '.' + suffix; + if (type == 1) { + return fileName1; + } else if (type == 2) { + return fileName2; + } + return ''; + }; + + //获取当前年月日 + const getNowDate = () => { + var a = new Date().getTime(); //获取到当前时间戳 + var now = new Date(a); //创建一个指定的日期对象 + var year = now.getFullYear(); //年份 + var month = now.getMonth() + 1; //月份(0-11) + var date = now.getDate(); //天数(1到31) + return year + '-' + month + '-' + date; + }; + + return { + dialogImageUrl, + dialogVisible, + handleRemove, + handlePictureCardPreview, + successFile, + errorFile, + uploadSectionFile, + viewList + }; + }, +}); +</script> diff --git a/src/components/userCheckbox/index.vue b/src/components/userCheckbox/index.vue new file mode 100644 index 0000000..5fc0b7a --- /dev/null +++ b/src/components/userCheckbox/index.vue @@ -0,0 +1,422 @@ +<template> + <div class="system-edit-user-container"> + <el-dialog + title="用户选择" + v-model="isShowDialog" + width="1000px" + draggable + :fullscreen="full" + > + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-container class="layout-container-demo" style="height: 500px;overflow: auto;min-width: 960px"> + <el-aside width="200px"> + <el-input v-model="filterText" placeholder="请输入组织机构过滤" /> + <el-tree + ref="treeRef" + class="filter-tree" + :data="data" + :props="defaultProps" + default-expand-all + @node-click="handleNodeClick" + :filter-node-method="filterNode" + /> + </el-aside> + <el-container style="margin: 0 15px;min-width:560px;"> + <el-header style="font-size: 12px"> + <el-form :inline="true" :model="ruleForm" class="demo-form-inline"> + <el-form-item> + <el-input size="default" v-model="ruleForm.name" placeholder="登录名"> </el-input> + </el-form-item> + <el-form-item> + <el-button size="default" type="primary" class="ml10" @click="onSubmit"> + 查询 + </el-button> + <el-button size="default" class="ml10" @click="submitReset"> + 重置 + </el-button> + </el-form-item> + </el-form> + </el-header> + <el-main style="position: relative;"> + <el-table + :data="tableData" + :header-cell-style="{background:'#f6f7fa',color:'#909399',fontWeight:400}" + @cell-click="checkbox" + > + <el-table-column type="selection" width="55"> + <template #default="scope"> + <el-checkbox-group v-model="checkbox1"> + <el-checkbox :label="scope.row.uid" size="large">{{ null }}</el-checkbox> + </el-checkbox-group> + </template> + </el-table-column> + <el-table-column prop="realName" label="登录名" width="100" show-overflow-tooltip sortable /> + <el-table-column prop="username" label="用户名" width="100" show-overflow-tooltip sortable /> + <el-table-column prop="address" label="所属机构" width="115" show-overflow-tooltip sortable /> + <el-table-column prop="address" label="所属部门" width="115" show-overflow-tooltip sortable/> + <el-table-column align="center" prop="type" label="状态" /> +<!-- <el-table-column label="状态"--> +<!-- width="80"--> +<!-- prop="tag"--> +<!-- :filters="[--> +<!-- { text: '正常', value: 'Home' },--> +<!-- { text: '不正常', value: 'Office' },--> +<!-- ]"--> +<!-- :filter-method="filterTag"--> +<!-- filter-placement="bottom-end">--> +<!-- <template #default="scope">--> +<!-- <el-tag--> +<!-- :type="scope.row.tag === 'Home' ? '' : 'success'"--> +<!-- disable-transitions--> +<!-- >{{ scope.row.tag }}</el-tag--> +<!-- >--> +<!-- </template>--> +<!-- </el-table-column>--> + </el-table> + <div class="pages"> + <el-pagination + v-model:currentPage="pageIndex" + v-model:page-size="pageSize" + :page-sizes="[10, 20, 30]" + :pager-count="5" + layout="total, sizes, prev, pager, next, jumper" + :total="total" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + </el-main> + </el-container> + <div style="width: 200px;"> + <div v-if="dynamicTags[0]==''?false:true"> + <el-tag + v-for="tag in dynamicTags" + :key="tag" + class="mx-1" + style="margin: 5px" + closable + :disable-transitions="false" + @close="handleClose(tag)" + > + {{ tag.realName }} + </el-tag> + </div> + </div> + </el-container> + <template #footer> + <span class="dialog-footer"> + <el-button size="default" type="primary" @click="onCancel">确定</el-button> + <el-button size="default" @click="onCancel">关闭</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script lang="ts"> +import { + ref, + defineComponent, + watch, + reactive, + onMounted, +} from 'vue'; + +import type { + ElTree, + // ElTable, +} from 'element-plus' +import { + ElMessage, +} from 'element-plus'; +import { + FullScreen +} from '@element-plus/icons-vue' +import {goalManagementApi} from "/@/api/goalManagement"; +interface Tree { + id: number + label: string + children?: Tree[] +} +// interface User { +// date: string +// name: string +// address: string +// } +export default defineComponent({ + name: 'userSelections', + components: { + // Search, + }, + setup(props, { emit }) { + const isShowDialog = ref(false) + // 打开弹窗 + const openDialog = (type:any) => { + types.value=type + isShowDialog.value = true; + }; + // 关闭弹窗 + const closeDialog = () => { + isShowDialog.value = false; + }; + // 取消 + const onCancel = () => { + closeDialog(); + }; + + //部门树 + const department = () => { + goalManagementApi() + .getTreedepartment() + .then((res) => { + if (res.data.code == 200) { + data.value = res.data.data; + } else { + ElMessage.error(res.data.msg); + } + }); + }; + const defaultProps = { + label: 'depName', + children: 'children', + value: 'depId', + } + //部门树查询 + const filterText = ref('') + const treeRef = ref<InstanceType<typeof ElTree>>() //实例化 + watch(filterText, (val) => { + treeRef.value!.filter(val); + }); + // 节点过滤模糊搜索 + const filterNode = (depName: string, data: Tree) => { + if (!depName) return true + return data.depName.includes(depName) + } + onMounted(() => { + department(); + }); + //左边树形部分点击获取回调 + const names = ref<any>(); + const handleNodeClick = (data: Tree) => { + goalManagementApi() + .getManName(data.depId) + .then((res) => { + if (res.data.code == 200) { + tableData.value=res.data.data + }else{ + ElMessage.error(res.data.msg); + } + }); + }; + + + // 监听搜索关键字改变 + watch(filterText, (val) => { + treeRef.value!.filter(val) + }) + // 树形结构内容 + const data = ref() + + + + + // const item = { + // date: '孙刚', + // name: '龚赛健', + // address: '综合办公室', + // tag: '正常', + // } + // const tableData = ref(Array.from({ length: 7 }).fill(item)) + // 定义表单搜索 + const ruleForm = reactive({ + name: '', + }) + const types=ref() + // 搜索按钮 + const onSubmit = () => { + let obj = JSON.parse(JSON.stringify(dynamicTags.value)); + emit('SearchUser', obj[0],types.value); + isShowDialog.value = false; + } + + // const multipleTableRef = ref<InstanceType<typeof ElTable>>() + // 右方点击添加后显示标签 + const dynamicTags = ref(['']); + const handleClose = () => { + dynamicTags.value.push(checkbox1.value) + // dynamicTags.value.splice(dynamicTags.value.indexOf(tag), 1); + checkbox1.value = ''; + }; + const checkbox1 = ref(''); + const checkbox = (event: any) => { + dynamicTags.value[0] = event; + }; + const tableData = ref(); + // 分页 + const pageIndex = ref(4); + const pageSize = ref(10); + // 分页改变 + const handleSizeChange = (val: number) => { + console.log(`${val} items per page`); + }; + // 分页未改变 + const handleCurrentChange = (val: number) => { + console.log(`current page: ${val}`); + }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + return { + openDialog, + closeDialog, + isShowDialog, + onCancel, + defaultProps, + filterNode, + data, + tableData, + ruleForm, + onSubmit, + // multipleTableRef, + handleClose, + dynamicTags, + handleSizeChange, + handleCurrentChange, + pageIndex, + pageSize, + toggleFullscreen, + FullScreen, + full, + names, + handleNodeClick, + types, + checkbox1, + checkbox, + }; + }, +}); +</script> +<style scoped lang="scss"> +.layout-container-demo .el-header { + position: relative; + color: var(--el-text-color-primary); + line-height: 32px; + --el-header-height: 45px; + padding: 0; +} +.layout-container-demo .el-aside { + padding: 10px; + border: 1px solid #ebeef5; + color: var(--el-text-color-primary); +} +::v-deep .el-input--large .el-input__inner { + height: 32px!important; + line-height: 32px!important; +} +.layout-container-demo .el-menu { + border-right: none; +} +.layout-container-demo .el-main { + padding: 0; +} +.layout-container-demo .toolbar { + display: inline-flex; + align-items: center; + justify-content: center; + height: 100%; + right: 20px; +} +.el-input--large{ + //width: 178px; + height: 32px; +} +.el-tree{ + overflow: auto; +} +::-webkit-scrollbar { + height: 1px; + +} +::-webkit-scrollbar-thumb { + background-color: transparent; +} +// 鼠标悬浮样式 +:hover::-webkit-scrollbar-thumb { + border-radius: 15px; + background-color: #d8d9db; +} +::v-deep .el-input__wrapper{ + width: 215px; +} +::v-deep .el-form-item{ + margin-bottom: 0; + margin-right: 0; +} +//弹窗底部边框线 +::v-deep .el-dialog__footer{ + border-top: 1px solid #e8e8e8; + border-radius: 0 0 4px 4px; +} +//弹窗顶部边框线 +::v-deep .el-dialog__header { + border-bottom: 1px solid #e8e8e8; + margin-right: 0; + border-radius: 4px 4px 0 0; +} +//单选框圆形 +//::v-deep .el-table__header .el-table-column--selection .cell .el-checkbox { +// display:none +//} +//::v-deep .el-table-column--selection .cell{ +// text-align: center; +//} +//::v-deep .el-checkbox__input .el-checkbox__inner{ +// border-radius: 50%; +//} +/*分页*/ +.pages{ + display: flex; + justify-content: flex-end; + margin-top: 15px; + align-items: center; + //position: absolute; + //bottom: 0; +} +::v-deep .el-pagination{ + width: 100%; +} +::v-deep .el-pagination .el-pager li { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +::v-deep .el-pagination .el-pager li.is-active { + background-color: #409eff; + color: #fff; +} +::v-deep .el-pagination .btn-prev { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +::v-deep .el-pagination button:disabled{ + color: #c0c4cc; +} +::v-deep .el-pagination .btn-next{ + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +</style> \ No newline at end of file diff --git a/src/components/userSelections/index.vue b/src/components/userSelections/index.vue new file mode 100644 index 0000000..8fdbb3f --- /dev/null +++ b/src/components/userSelections/index.vue @@ -0,0 +1,446 @@ +<template> + <div class="system-edit-user-container"> + <el-dialog + title="用户选择" + v-model="isShowDialog" + width="1000px" + draggable + :fullscreen="full" + > + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-container class="layout-container-demo" style="height: 500px;overflow: auto;min-width: 960px"> + <el-aside width="200px"> + <el-input v-model="filterText" placeholder="请输入组织机构过滤" /> + <el-tree + ref="treeRef" + class="filter-tree" + :data="data" + :props="defaultProps" + default-expand-all + :filter-node-method="filterNode" + /> + </el-aside> + <el-container style="margin: 0 15px;min-width:560px;"> + <el-header style="font-size: 12px"> + <el-form :inline="true" :model="formInline" class="demo-form-inline"> + <el-form-item> + <el-input size="default" v-model="formInline.name" placeholder="登录名"> </el-input> + </el-form-item> + <el-form-item> + <el-button size="default" type="primary" class="ml10" @click="onSubmit"> + 查询 + </el-button> + <el-button size="default" class="ml10" @click="submitReset"> + 重置 + </el-button> + </el-form-item> + </el-form> + </el-header> + <el-main style="position: relative;"> + <el-table + :data="tableData" + :header-cell-style="{background:'#f6f7fa',color:'#909399',fontWeight:400}" + @cell-click="radio" + > + <el-table-column align="center" width="55"> + <template #default="scope"> + <el-radio-group v-model="radio1"> + <el-radio :label="scope.row.id" size="large">{{ null }}</el-radio> + </el-radio-group> + </template> + </el-table-column> + <el-table-column prop="date" label="登录名" width="100" show-overflow-tooltip sortable /> + <el-table-column prop="name" label="用户名" width="100" show-overflow-tooltip sortable /> + <el-table-column prop="address" label="所属机构" width="115" show-overflow-tooltip sortable /> + <el-table-column prop="department" label="所属部门" width="115" show-overflow-tooltip sortable/> + <el-table-column label="状态" + width="80" + prop="tag" + :filters="[ + { text: '正常', value: 'Home' }, + { text: '不正常', value: 'Office' }, + ]" + :filter-method="filterTag" + filter-placement="bottom-end"> + <template #default="scope"> + <el-tag + :type="scope.row.tag === 'Home' ? '' : 'success'" + disable-transitions + >{{ scope.row.tag }}</el-tag + > + </template> + </el-table-column> + </el-table> + <div class="pages"> + <el-pagination + v-model:currentPage="pageIndex" + v-model:page-size="pageSize" + :page-sizes="[10, 20, 30]" + :pager-count="5" + :small="small" + :disabled="disabled" + :background="background" + layout="total, sizes, prev, pager, next, jumper" + :total="40" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + </el-main> + </el-container> + <div style="width: 200px;"> + <el-tag + v-for="tag in dynamicTags" + :key="tag" + class="mx-1" + style="margin: 5px" + closable + :disable-transitions="false" + @close="handleClose(tag)" + > + {{ tag }} + </el-tag> + </div> + </el-container> + <template #footer> + <span class="dialog-footer"> + <el-button size="default" type="primary" @click="onCancel">确定</el-button> + <el-button size="default" @click="onCancel">关闭</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script lang="ts"> +import { + ref, + defineComponent, + watch, + reactive, +} from 'vue'; + +import type { + ElTree, + // ElTable, +} from 'element-plus' +import { + FullScreen +} from '@element-plus/icons-vue' +interface Tree { + id: number + label: string + children?: Tree[] +} +// interface User { +// date: string +// name: string +// address: string +// } +export default defineComponent({ + name: 'userSelections', + components: { + // Search, + }, + setup(props,{emit}) { + const isShowDialog = ref(false) + // 打开弹窗 + const openDialog = () => { + isShowDialog.value = true; + }; + // 关闭弹窗 + const closeDialog = () => { + isShowDialog.value = false; + }; + // 取消 + const onCancel = () => { + let obj=JSON.parse(JSON.stringify(dynamicTags.value)) + emit("SearchUser",obj[0]) + closeDialog(); + }; + + + const filterText = ref('') + const treeRef = ref<InstanceType<typeof ElTree>>() //实例化 + + const defaultProps = { + children: 'children', + label: 'label', + } + + // 监听搜索关键字改变 + watch(filterText, (val) => { + treeRef.value!.filter(val) + }) + + // 节点过滤模糊搜索 + const filterNode = (value: string, data: Tree) => { + if (!value) return true + return data.label.includes(value) + } + + // 树形结构内容 + const data: Tree[] = [ + { + id: 1, + label: '广汇能源综合物流发展有限责任公司', + children: [ + { + id: 4, + label: '经营班子', + children: [] + }, + ], + }, + { + id: 2, + label: '生产运行部', + children: [ + { + id: 5, + label: '工艺二班', + }, + { + id: 6, + label: '灌装一班', + }, + ], + }, + { + id: 3, + label: '设备部', + children: [ + { + id: 7, + label: '仪表班', + }, + { + id: 8, + label: '机修班', + }, + ], + }, + ] + // const item = { + // date: '孙刚', + // name: '龚赛健', + // address: '综合办公室', + // tag: '正常', + // } + // const tableData = ref(Array.from({ length: 7 }).fill(item)) + const tableData = [ + { + date: '孙刚', + name: '孙刚', + address: '', + department: '经营班子', + tag: '正常', + }, + { + date: '谭柏', + name: '谭柏', + address: '', + department: '经营班子', + tag: '正常', + }, + { + date: '倪威', + name: '倪威', + address: '', + department: '经营班子', + tag: '正常', + }, + { + date: '倪玲婕', + name: '倪玲婕', + address: '', + department: '经营班子', + tag: '正常', + }, + ]; + // 定义表单搜索 + const formInline = reactive({ + name: '', + }) + // 搜索按钮 + const onSubmit = () => { + console.log('submit!') + } + + // const multipleTableRef = ref<InstanceType<typeof ElTable>>() + // 右方点击添加后显示标签 + const dynamicTags = ref(['胡海涛']); + const handleClose = (tag: string) => { + dynamicTags.value.splice(dynamicTags.value.indexOf(tag), 1); + radio1.value="" + }; + const radio1=ref('') + const radio=(event:any)=>{ + dynamicTags.value[0]=event + } + + // 分页 + const pageIndex = ref(4); + const pageSize = ref(10); + // 分页改变 + const handleSizeChange = (val: number) => { + console.log(`${val} items per page`); + }; + // 分页未改变 + const handleCurrentChange = (val: number) => { + console.log(`current page: ${val}`); + }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + return { + openDialog, + closeDialog, + isShowDialog, + onCancel, + defaultProps, + filterNode, + data, + tableData, + formInline, + onSubmit, + // multipleTableRef, + handleClose, + dynamicTags, + handleSizeChange, + handleCurrentChange, + pageIndex, + pageSize, + radio1, + radio, + toggleFullscreen, + FullScreen, + full, + }; + }, +}); +</script> +<style scoped lang="scss"> +.layout-container-demo .el-header { + position: relative; + color: var(--el-text-color-primary); + line-height: 32px; + --el-header-height: 45px; + padding: 0; +} +.layout-container-demo .el-aside { + padding: 10px; + border: 1px solid #ebeef5; + color: var(--el-text-color-primary); +} +::v-deep .el-input--large .el-input__inner { + height: 32px!important; + line-height: 32px!important; +} +.layout-container-demo .el-menu { + border-right: none; +} +.layout-container-demo .el-main { + padding: 0; +} +.layout-container-demo .toolbar { + display: inline-flex; + align-items: center; + justify-content: center; + height: 100%; + right: 20px; +} +.el-input--large{ + //width: 178px; + height: 32px; +} +.el-tree{ + overflow: auto; +} +::-webkit-scrollbar { + height: 1px; + +} +::-webkit-scrollbar-thumb { + background-color: transparent; +} +// 鼠标悬浮样式 +:hover::-webkit-scrollbar-thumb { + border-radius: 15px; + background-color: #d8d9db; +} +::v-deep .el-input__wrapper{ + width: 215px; +} +::v-deep .el-form-item{ + margin-bottom: 0; + margin-right: 0; +} +//弹窗底部边框线 +::v-deep .el-dialog__footer{ + border-top: 1px solid #e8e8e8; + border-radius: 0 0 4px 4px; +} +//弹窗顶部边框线 +::v-deep .el-dialog__header { + border-bottom: 1px solid #e8e8e8; + margin-right: 0; + border-radius: 4px 4px 0 0; +} +//单选框圆形 +::v-deep .el-table__header .el-table-column--selection .cell .el-checkbox { + display:none +} +::v-deep .el-table-column--selection .cell{ + text-align: center; +} +::v-deep .el-checkbox__input .el-checkbox__inner{ + border-radius: 50%; +} +/*分页*/ +.pages{ + display: flex; + justify-content: flex-end; + margin-top: 15px; + align-items: center; + //position: absolute; + //bottom: 0; +} +::v-deep .el-pagination{ + width: 100%; +} +::v-deep .el-pagination .el-pager li { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +::v-deep .el-pagination .el-pager li.is-active { + background-color: #409eff; + color: #fff; +} +::v-deep .el-pagination .btn-prev { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +::v-deep .el-pagination button:disabled{ + color: #c0c4cc; +} +::v-deep .el-pagination .btn-next{ + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +</style> \ No newline at end of file diff --git a/src/i18n/index.ts b/src/i18n/index.ts new file mode 100644 index 0000000..a45e72c --- /dev/null +++ b/src/i18n/index.ts @@ -0,0 +1,67 @@ +import { createI18n } from 'vue-i18n'; +import pinia from '/@/stores/index'; +import { storeToRefs } from 'pinia'; +import { useThemeConfig } from '/@/stores/themeConfig'; +import zhcnLocale from 'element-plus/lib/locale/lang/zh-cn'; +import enLocale from 'element-plus/lib/locale/lang/en'; +import zhtwLocale from 'element-plus/lib/locale/lang/zh-tw'; + +import nextZhcn from '/@/i18n/lang/zh-cn'; +import nextEn from '/@/i18n/lang/en'; +import nextZhtw from '/@/i18n/lang/zh-tw'; + +import pagesLoginZhcn from '/@/i18n/pages/login/zh-cn'; +import pagesLoginEn from '/@/i18n/pages/login/en'; +import pagesLoginZhtw from '/@/i18n/pages/login/zh-tw'; +import pagesFormI18nZhcn from '/@/i18n/pages/formI18n/zh-cn'; +import pagesFormI18nEn from '/@/i18n/pages/formI18n/en'; +import pagesFormI18nZhtw from '/@/i18n/pages/formI18n/zh-tw'; + +// 定义语言国际化内容 +/** + * 说明: + * /src/i18n/lang 下的 ts 为框架的国际化内容 + * /src/i18n/pages 下的 ts 为各界面的国际化内容 + */ +const messages = { + [zhcnLocale.name]: { + ...zhcnLocale, + message: { + ...nextZhcn, + ...pagesLoginZhcn, + ...pagesFormI18nZhcn, + }, + }, + [enLocale.name]: { + ...enLocale, + message: { + ...nextEn, + ...pagesLoginEn, + ...pagesFormI18nEn, + }, + }, + [zhtwLocale.name]: { + ...zhtwLocale, + message: { + ...nextZhtw, + ...pagesLoginZhtw, + ...pagesFormI18nZhtw, + }, + }, +}; + +// 读取 pinia 默认语言 +const stores = useThemeConfig(pinia); +const { themeConfig } = storeToRefs(stores); + +// 导出语言国际化 +// https://vue-i18n.intlify.dev/guide/essentials/fallback.html#explicit-fallback-with-one-locale +export const i18n = createI18n({ + silentTranslationWarn: true, + missingWarn: false, + silentFallbackWarn: true, + fallbackWarn: false, + locale: themeConfig.value.globalI18n, + fallbackLocale: zhcnLocale.name, + messages, +}); diff --git a/src/i18n/lang/en.ts b/src/i18n/lang/en.ts new file mode 100644 index 0000000..46ae830 --- /dev/null +++ b/src/i18n/lang/en.ts @@ -0,0 +1,180 @@ +// 定义内容 +export default { + router: { + home: 'home', + system: 'system', + systemMenu: 'systemMenu', + systemRole: 'systemRole', + systemUser: 'systemUser', + systemDept: 'systemDept', + systemDic: 'systemDic', + limits: 'limits', + limitsFrontEnd: 'FrontEnd', + limitsFrontEndPage: 'FrontEndPage', + limitsFrontEndBtn: 'FrontEndBtn', + limitsBackEnd: 'BackEnd', + limitsBackEndEndPage: 'BackEndEndPage', + menu: 'menu', + menu1: 'menu1', + menu11: 'menu11', + menu12: 'menu12', + menu121: 'menu121', + menu122: 'menu122', + menu13: 'menu13', + menu2: 'menu2', + funIndex: 'function', + funTagsView: 'funTagsView', + funCountup: 'countup', + funWangEditor: 'wangEditor', + funCropper: 'cropper', + funQrcode: 'qrcode', + funEchartsMap: 'EchartsMap', + funPrintJs: 'PrintJs', + funClipboard: 'Copy cut', + funGridLayout: 'Drag layout', + funSplitpanes: 'Pane splitter', + funDragVerify: 'Validator', + pagesIndex: 'pages', + pagesFiltering: 'Filtering', + pagesFilteringDetails: 'FilteringDetails', + pagesFilteringDetails1: 'FilteringDetails1', + pagesIocnfont: 'iconfont icon', + pagesElement: 'element icon', + pagesAwesome: 'awesome icon', + pagesFormAdapt: 'FormAdapt', + pagesTableRules: 'pagesTableRules', + pagesFormI18n: 'FormI18n', + pagesFormRules: 'Multi form validation', + pagesDynamicForm: 'Dynamic complex form', + pagesWorkflow: 'Workflow', + pagesListAdapt: 'ListAdapt', + pagesWaterfall: 'Waterfall', + pagesSteps: 'Steps', + pagesPreview: 'Large preview', + pagesWaves: 'Wave effect', + pagesTree: 'tree alter table', + pagesDrag: 'Drag command', + pagesLazyImg: 'Image lazy loading', + makeIndex: 'makeIndex', + makeSelector: 'Icon selector', + makeNoticeBar: 'notification bar', + makeSvgDemo: 'Svgicon demo', + paramsIndex: 'Routing parameters', + paramsCommon: 'General routing', + paramsDynamic: 'Dynamic routing', + paramsCommonDetails: 'General routing details', + paramsDynamicDetails: 'Dynamic routing details', + chartIndex: 'chartIndex', + visualizingIndex: 'visualizingIndex', + visualizingLinkDemo1: 'visualizingLinkDemo1', + visualizingLinkDemo2: 'visualizingLinkDemo2', + personal: 'personal', + tools: 'tools', + layoutLinkView: 'LinkView', + layoutIfameView: 'IfameView', + }, + staticRoutes: { + signIn: 'signIn', + notFound: 'notFound', + noPower: 'noPower', + }, + user: { + title0: 'Component size', + title1: 'Language switching', + title2: 'Menu search', + title3: 'Layout configuration', + title4: 'news', + title5: 'Full screen on', + title6: 'Full screen off', + dropdownLarge: 'large', + dropdownDefault: 'default', + dropdownSmall: 'small', + dropdown1: 'home page', + dropdown2: 'Personal Center', + dropdown3: '404', + dropdown4: '401', + dropdown5: 'Log out', + dropdown6: 'Code warehouse', + searchPlaceholder: 'Menu search: support Chinese, routing path', + newTitle: 'notice', + newBtn: 'All read', + newGo: 'Go to the notification center', + newDesc: 'No notice', + logOutTitle: 'Tips', + logOutMessage: 'This operation will log out. Do you want to continue?', + logOutConfirm: 'determine', + logOutCancel: 'cancel', + logOutExit: 'Exiting', + }, + tagsView: { + refresh: 'refresh', + close: 'close', + closeOther: 'closeOther', + closeAll: 'closeAll', + fullscreen: 'fullscreen', + closeFullscreen: 'closeFullscreen', + }, + notFound: { + foundTitle: 'Wrong address input, please re-enter the address~', + foundMsg: 'You can check the web address first, and then re-enter or give us feedback.', + foundBtn: 'Back to home page', + }, + noAccess: { + accessTitle: 'You are not authorized to operate~', + accessMsg: 'Contact information: add QQ group discussion 665452019', + accessBtn: 'Reauthorization', + }, + layout: { + configTitle: 'Layout configuration', + oneTitle: 'Global Themes', + twoTopTitle: 'top bar set up', + twoMenuTitle: 'Menu set up', + twoColumnsTitle: 'Columns set up', + twoTopBar: 'Top bar background', + twoTopBarColor: 'Top bar default font color', + twoIsTopBarColorGradual: 'Top bar gradient', + twoMenuBar: 'Menu background', + twoMenuBarColor: 'Menu default font color', + twoIsMenuBarColorGradual: 'Menu gradient', + twoColumnsMenuBar: 'Column menu background', + twoColumnsMenuBarColor: 'Default font color bar menu', + twoIsColumnsMenuBarColorGradual: 'Column gradient', + threeTitle: 'Interface settings', + threeIsCollapse: 'Menu horizontal collapse', + threeIsUniqueOpened: 'Menu accordion', + threeIsFixedHeader: 'Fixed header', + threeIsClassicSplitMenu: 'Classic layout split menu', + threeIsLockScreen: 'Open the lock screen', + threeLockScreenTime: 'screen locking(s/s)', + fourTitle: 'Interface display', + fourIsShowLogo: 'Sidebar logo', + fourIsBreadcrumb: 'Open breadcrumb', + fourIsBreadcrumbIcon: 'Open breadcrumb icon', + fourIsTagsview: 'Open tagsview', + fourIsTagsviewIcon: 'Open tagsview Icon', + fourIsCacheTagsView: 'Enable tagsview cache', + fourIsSortableTagsView: 'Enable tagsview drag', + fourIsShareTagsView: 'Enable tagsview sharing', + fourIsFooter: 'Open footer', + fourIsGrayscale: 'Grey model', + fourIsInvert: 'Color weak mode', + fourIsDark: 'Dark Mode', + fourIsWartermark: 'Turn on watermark', + fourWartermarkText: 'Watermark copy', + fiveTitle: 'Other settings', + fiveTagsStyle: 'Tagsview style', + fiveAnimation: 'page animation', + fiveColumnsAsideStyle: 'Column style', + fiveColumnsAsideLayout: 'Column layout', + sixTitle: 'Layout switch', + sixDefaults: 'One', + sixClassic: 'Two', + sixTransverse: 'Three', + sixColumns: 'Four', + tipText: 'Click the button below to copy the layout configuration to `/src/stores/themeConfig.ts` It has been modified in.', + copyText: 'replication configuration', + resetText: 'restore default', + copyTextSuccess: 'Copy succeeded!', + copyTextError: 'Copy failed!', + }, +}; diff --git a/src/i18n/lang/zh-cn.ts b/src/i18n/lang/zh-cn.ts new file mode 100644 index 0000000..79ef328 --- /dev/null +++ b/src/i18n/lang/zh-cn.ts @@ -0,0 +1,180 @@ +// 定义内容 +export default { + router: { + home: '首页', + system: '系统设置', + systemMenu: '菜单管理', + systemRole: '角色管理', + systemUser: '用户管理', + systemDept: '部门管理', + systemDic: '字典管理', + limits: '权限管理', + limitsFrontEnd: '前端控制', + limitsFrontEndPage: '页面权限', + limitsFrontEndBtn: '按钮权限', + limitsBackEnd: '后端控制', + limitsBackEndEndPage: '页面权限', + menu: '菜单嵌套', + menu1: '菜单1', + menu11: '菜单11', + menu12: '菜单12', + menu121: '菜单121', + menu122: '菜单122', + menu13: '菜单13', + menu2: '菜单2', + funIndex: '功能', + funTagsView: 'tagsView 操作', + funCountup: '数字滚动', + funWangEditor: 'Editor 编辑器', + funCropper: '图片裁剪', + funQrcode: '二维码生成', + funEchartsMap: '地理坐标/地图', + funPrintJs: '页面打印', + funClipboard: '复制剪切', + funGridLayout: '拖拽布局', + funSplitpanes: '窗格拆分器', + funDragVerify: '验证器', + pagesIndex: '页面', + pagesFiltering: '过滤筛选组件', + pagesFilteringDetails: '过滤筛选组件详情', + pagesFilteringDetails1: '过滤筛选组件详情111', + pagesIocnfont: 'ali 字体图标', + pagesElement: 'ele 字体图标', + pagesAwesome: 'awe 字体图标', + pagesFormAdapt: '表单自适应', + pagesTableRules: '表单表格验证', + pagesFormI18n: '表单国际化', + pagesFormRules: '多表单验证', + pagesDynamicForm: '动态复杂表单', + pagesWorkflow: '工作流', + pagesListAdapt: '列表自适应', + pagesWaterfall: '瀑布屏', + pagesSteps: '步骤条', + pagesPreview: '大图预览', + pagesWaves: '波浪效果', + pagesTree: '树形改表格', + pagesDrag: '拖动指令', + pagesLazyImg: '图片懒加载', + makeIndex: '组件封装', + makeSelector: '图标选择器', + makeNoticeBar: '滚动通知栏', + makeSvgDemo: 'svgIcon 演示', + paramsIndex: '路由参数', + paramsCommon: '普通路由', + paramsDynamic: '动态路由', + paramsCommonDetails: '普通路由详情', + paramsDynamicDetails: '动态路由详情', + chartIndex: '大数据图表', + visualizingIndex: '数据可视化', + visualizingLinkDemo1: '数据可视化演示1', + visualizingLinkDemo2: '数据可视化演示2', + personal: '个人中心', + tools: '工具类集合', + layoutLinkView: '外链', + layoutIfameView: '内嵌 iframe', + }, + staticRoutes: { + signIn: '登录', + notFound: '找不到此页面', + noPower: '没有权限', + }, + user: { + title0: '组件大小', + title1: '语言切换', + title2: '菜单搜索', + title3: '布局配置', + title4: '消息', + title5: '开全屏', + title6: '关全屏', + dropdownLarge: '大型', + dropdownDefault: '默认', + dropdownSmall: '小型', + dropdown1: '首页', + dropdown2: '个人中心', + dropdown3: '404', + dropdown4: '401', + dropdown5: '退出登录', + dropdown6: '代码仓库', + searchPlaceholder: '菜单搜索:支持中文、路由路径', + newTitle: '通知', + newBtn: '全部已读', + newGo: '前往通知中心', + newDesc: '暂无通知', + logOutTitle: '提示', + logOutMessage: '此操作将退出登录, 是否继续?', + logOutConfirm: '确定', + logOutCancel: '取消', + logOutExit: '退出中', + }, + tagsView: { + refresh: '刷新', + close: '关闭', + closeOther: '关闭其它', + closeAll: '全部关闭', + fullscreen: '当前页全屏', + closeFullscreen: '关闭全屏', + }, + notFound: { + foundTitle: '地址输入错误,请重新输入地址~', + foundMsg: '您可以先检查网址,然后重新输入或给我们反馈问题。', + foundBtn: '返回首页', + }, + noAccess: { + accessTitle: '您未被授权,没有操作权限~', + accessMsg: '联系方式:加QQ群探讨 665452019', + accessBtn: '重新授权', + }, + layout: { + configTitle: '布局配置', + oneTitle: '全局主题', + twoTopTitle: '顶栏设置', + twoMenuTitle: '菜单设置', + twoColumnsTitle: '分栏设置', + twoTopBar: '顶栏背景', + twoTopBarColor: '顶栏默认字体颜色', + twoIsTopBarColorGradual: '顶栏背景渐变', + twoMenuBar: '菜单背景', + twoMenuBarColor: '菜单默认字体颜色', + twoIsMenuBarColorGradual: '菜单背景渐变', + twoColumnsMenuBar: '分栏菜单背景', + twoColumnsMenuBarColor: '分栏菜单默认字体颜色', + twoIsColumnsMenuBarColorGradual: '分栏菜单背景渐变', + threeTitle: '界面设置', + threeIsCollapse: '菜单水平折叠', + threeIsUniqueOpened: '菜单手风琴', + threeIsFixedHeader: '固定 Header', + threeIsClassicSplitMenu: '经典布局分割菜单', + threeIsLockScreen: '开启锁屏', + threeLockScreenTime: '自动锁屏(s/秒)', + fourTitle: '界面显示', + fourIsShowLogo: '侧边栏 Logo', + fourIsBreadcrumb: '开启 Breadcrumb', + fourIsBreadcrumbIcon: '开启 Breadcrumb 图标', + fourIsTagsview: '开启 Tagsview', + fourIsTagsviewIcon: '开启 Tagsview 图标', + fourIsCacheTagsView: '开启 TagsView 缓存', + fourIsSortableTagsView: '开启 TagsView 拖拽', + fourIsShareTagsView: '开启 TagsView 共用', + fourIsFooter: '开启 Footer', + fourIsGrayscale: '灰色模式', + fourIsInvert: '色弱模式', + fourIsDark: '深色模式', + fourIsWartermark: '开启水印', + fourWartermarkText: '水印文案', + fiveTitle: '其它设置', + fiveTagsStyle: 'Tagsview 风格', + fiveAnimation: '主页面切换动画', + fiveColumnsAsideStyle: '分栏高亮风格', + fiveColumnsAsideLayout: '分栏布局风格', + sixTitle: '布局切换', + sixDefaults: '默认', + sixClassic: '经典', + sixTransverse: '横向', + sixColumns: '分栏', + tipText: '点击下方按钮,复制布局配置去 `src/stores/themeConfig.ts` 中修改。', + copyText: '一键复制配置', + resetText: '一键恢复默认', + copyTextSuccess: '复制成功!', + copyTextError: '复制失败!', + }, +}; diff --git a/src/i18n/lang/zh-tw.ts b/src/i18n/lang/zh-tw.ts new file mode 100644 index 0000000..d900abb --- /dev/null +++ b/src/i18n/lang/zh-tw.ts @@ -0,0 +1,180 @@ +// 定义内容 +export default { + router: { + home: '首頁', + system: '系統設置', + systemMenu: '選單管理', + systemRole: '角色管理', + systemUser: '用戶管理', + systemDept: '部門管理', + systemDic: '字典管理', + limits: '許可權管理', + limitsFrontEnd: '前端控制', + limitsFrontEndPage: '頁面許可權', + limitsFrontEndBtn: '按鈕許可權', + limitsBackEnd: '後端控制', + limitsBackEndEndPage: '頁面許可權', + menu: '選單嵌套', + menu1: '選單1', + menu11: '選單11', + menu12: '選單12', + menu121: '選單121', + menu122: '選單122', + menu13: '選單13', + menu2: '選單2', + funIndex: '功能', + funTagsView: 'tagsView 操作', + funCountup: '數位滾動', + funWangEditor: 'Editor 編輯器', + funCropper: '圖片裁剪', + funQrcode: '二維碼生成', + funEchartsMap: '地理座標/地圖', + funPrintJs: '頁面列印', + funClipboard: '複製剪切', + funGridLayout: '拖拽佈局', + funSplitpanes: '窗格折開器', + funDragVerify: '驗證器', + pagesIndex: '頁面', + pagesFiltering: '過濾篩選組件', + pagesFilteringDetails: '過濾篩選組件詳情', + pagesFilteringDetails1: '過濾篩選組件詳情111', + pagesIocnfont: 'ali 字體圖標', + pagesElement: 'ele 字體圖標', + pagesAwesome: 'awe 字體圖標', + pagesFormAdapt: '表單自我調整', + pagesTableRules: '表單表格驗證', + pagesFormI18n: '表單國際化', + pagesFormRules: '多表單驗證', + pagesDynamicForm: '動態複雜表單', + pagesWorkflow: '工作流', + pagesListAdapt: '清單自我調整', + pagesWaterfall: '瀑布屏', + pagesSteps: '步驟條', + pagesPreview: '大圖預覽', + pagesWaves: '波浪效果', + pagesTree: '樹形改表格', + pagesDrag: '拖動指令', + pagesLazyImg: '圖片懶加載', + makeIndex: '組件封裝', + makeSelector: '圖標選擇器', + makeNoticeBar: '滾動通知欄', + makeSvgDemo: 'svgIcon 演示', + paramsIndex: '路由參數', + paramsCommon: '普通路由', + paramsDynamic: '動態路由', + paramsCommonDetails: '普通路由詳情', + paramsDynamicDetails: '動態路由詳情', + chartIndex: '大資料圖表', + visualizingIndex: '數據視覺化', + visualizingLinkDemo1: '數據視覺化演示1', + visualizingLinkDemo2: '數據視覺化演示2', + personal: '個人中心', + tools: '工具類集合', + layoutLinkView: '外鏈', + layoutIfameView: '内嵌 iframe', + }, + staticRoutes: { + signIn: '登入', + notFound: '找不到此頁面', + noPower: '沒有許可權', + }, + user: { + title0: '組件大小', + title1: '語言切換', + title2: '選單蒐索', + title3: '佈局配寘', + title4: '消息', + title5: '開全屏', + title6: '關全屏', + dropdownLarge: '大型', + dropdownDefault: '默認', + dropdownSmall: '小型', + dropdown1: '首頁', + dropdown2: '個人中心', + dropdown3: '404', + dropdown4: '401', + dropdown5: '登出', + dropdown6: '程式碼倉庫', + searchPlaceholder: '選單蒐索:支援中文、路由路徑', + newTitle: '通知', + newBtn: '全部已讀', + newGo: '前往通知中心', + newDesc: '暫無通知', + logOutTitle: '提示', + logOutMessage: '此操作將登出,是否繼續?', + logOutConfirm: '確定', + logOutCancel: '取消', + logOutExit: '退出中', + }, + tagsView: { + refresh: '重繪', + close: '關閉', + closeOther: '關閉其它', + closeAll: '全部關閉', + fullscreen: '當前頁全屏', + closeFullscreen: '關閉全屏', + }, + notFound: { + foundTitle: '地址輸入錯誤,請重新輸入地址~', + foundMsg: '您可以先檢查網址,然後重新輸入或給我們迴響問題。', + foundBtn: '返回首頁', + }, + noAccess: { + accessTitle: '您未被授權,沒有操作許可權~', + accessMsg: '聯繫方式:加QQ群探討665452019', + accessBtn: '重新授權', + }, + layout: { + configTitle: '佈局配寘', + oneTitle: '全域主題', + twoTopTitle: '頂欄設定', + twoMenuTitle: '選單設定', + twoColumnsTitle: '分欄設定', + twoTopBar: '頂欄背景', + twoTopBarColor: '頂欄默認字體顏色', + twoIsTopBarColorGradual: '頂欄背景漸變', + twoMenuBar: '選單背景', + twoMenuBarColor: '選單默認字體顏色', + twoIsMenuBarColorGradual: '選單背景漸變', + twoColumnsMenuBar: '分欄選單背景', + twoColumnsMenuBarColor: '分欄選單默認字體顏色', + twoIsColumnsMenuBarColorGradual: '分欄選單背景漸變', + threeTitle: '介面設定', + threeIsCollapse: '選單水准折疊', + threeIsUniqueOpened: '選單手風琴', + threeIsFixedHeader: '固定 Header', + threeIsClassicSplitMenu: '經典佈局分割選單', + threeIsLockScreen: '開啟鎖屏', + threeLockScreenTime: '自動鎖屏(s/秒)', + fourTitle: '介面顯示', + fourIsShowLogo: '側邊欄 Logo', + fourIsBreadcrumb: '開啟 Breadcrumb', + fourIsBreadcrumbIcon: '開啟 Breadcrumb 圖標', + fourIsTagsview: '開啟 Tagsview', + fourIsTagsviewIcon: '開啟 Tagsview 圖標', + fourIsCacheTagsView: '開啟 TagsView 緩存', + fourIsSortableTagsView: '開啟 TagsView 拖拽', + fourIsShareTagsView: '開啟 TagsView 共用', + fourIsFooter: '開啟 Footer', + fourIsGrayscale: '灰色模式', + fourIsInvert: '色弱模式', + fourIsDark: '深色模式', + fourIsWartermark: '開啟浮水印', + fourWartermarkText: '浮水印文案', + fiveTitle: '其它設定', + fiveTagsStyle: 'Tagsview 風格', + fiveAnimation: '主頁面切換動畫', + fiveColumnsAsideStyle: '分欄高亮風格', + fiveColumnsAsideLayout: '分欄佈局風格', + sixTitle: '佈局切換', + sixDefaults: '默認', + sixClassic: '經典', + sixTransverse: '橫向', + sixColumns: '分欄', + tipText: '點擊下方按鈕,複製佈局配寘去`src/stores/themeConfig.ts`中修改。', + copyText: '一鍵複製配寘', + resetText: '一鍵恢復默認', + copyTextSuccess: '複製成功!', + copyTextError: '複製失敗!', + }, +}; diff --git a/src/i18n/pages/formI18n/en.ts b/src/i18n/pages/formI18n/en.ts new file mode 100644 index 0000000..b3c54d6 --- /dev/null +++ b/src/i18n/pages/formI18n/en.ts @@ -0,0 +1,13 @@ +// 定义内容 +export default { + formI18nLabel: { + name: 'name', + email: 'email', + autograph: 'autograph', + }, + formI18nPlaceholder: { + name: 'Please enter your name', + email: 'Please enter the users Department', + autograph: 'Please enter the login account name', + }, +}; diff --git a/src/i18n/pages/formI18n/zh-cn.ts b/src/i18n/pages/formI18n/zh-cn.ts new file mode 100644 index 0000000..0bed3ec --- /dev/null +++ b/src/i18n/pages/formI18n/zh-cn.ts @@ -0,0 +1,13 @@ +// 定义内容 +export default { + formI18nLabel: { + name: '姓名', + email: '用户归属部门', + autograph: '登陆账户名', + }, + formI18nPlaceholder: { + name: '请输入姓名', + email: '请输入用户归属部门', + autograph: '请输入登陆账户名', + }, +}; diff --git a/src/i18n/pages/formI18n/zh-tw.ts b/src/i18n/pages/formI18n/zh-tw.ts new file mode 100644 index 0000000..393ac03 --- /dev/null +++ b/src/i18n/pages/formI18n/zh-tw.ts @@ -0,0 +1,13 @@ +// 定义内容 +export default { + formI18nLabel: { + name: '姓名', + email: '用戶歸屬部門', + autograph: '登入帳戶名', + }, + formI18nPlaceholder: { + name: '請輸入姓名', + email: '請輸入用戶歸屬部門', + autograph: '請輸入登入帳戶名', + }, +}; diff --git a/src/i18n/pages/login/en.ts b/src/i18n/pages/login/en.ts new file mode 100644 index 0000000..2654a18 --- /dev/null +++ b/src/i18n/pages/login/en.ts @@ -0,0 +1,29 @@ +// 定义内容 +export default { + label: { + one1: 'User name login', + two2: 'Mobile number', + }, + link: { + one3: 'Third party login', + two4: 'Links', + }, + account: { + accountPlaceholder1: 'The user name admin or not is common', + accountPlaceholder2: 'Password: 123456', + accountPlaceholder3: 'Please enter the verification code', + accountBtnText: 'Sign in', + }, + mobile: { + placeholder1: 'Please input mobile phone number', + placeholder2: 'Please enter the verification code', + codeText: 'Get code', + btnText: 'Sign in', + msgText: + 'Warm tip: it is recommended to use Google, Microsoft edge, version 79.0.1072.62 and above browsers, and 360 browser, please use speed mode', + }, + scan: { + text: 'Open the mobile phone to scan and quickly log in / register', + }, + signInText: 'welcome back!', +}; diff --git a/src/i18n/pages/login/zh-cn.ts b/src/i18n/pages/login/zh-cn.ts new file mode 100644 index 0000000..3367b53 --- /dev/null +++ b/src/i18n/pages/login/zh-cn.ts @@ -0,0 +1,28 @@ +// 定义内容 +export default { + label: { + one1: '用户名登录', + two2: '手机号登录', + }, + link: { + one3: '第三方登录', + two4: '友情链接', + }, + account: { + accountPlaceholder1: '用户名 admin 或不输均为 common', + accountPlaceholder2: '密码:123456', + accountPlaceholder3: '请输入验证码', + accountBtnText: '登 录', + }, + mobile: { + placeholder1: '请输入手机号', + placeholder2: '请输入验证码', + codeText: '获取验证码', + btnText: '登 录', + msgText: '* 温馨提示:建议使用谷歌、Microsoft Edge,版本 79.0.1072.62 及以上浏览器,360浏览器请使用极速模式', + }, + scan: { + text: '打开手机扫一扫,快速登录/注册', + }, + signInText: '欢迎回来!', +}; diff --git a/src/i18n/pages/login/zh-tw.ts b/src/i18n/pages/login/zh-tw.ts new file mode 100644 index 0000000..138e8c8 --- /dev/null +++ b/src/i18n/pages/login/zh-tw.ts @@ -0,0 +1,28 @@ +// 定义内容 +export default { + label: { + one1: '用戶名登入', + two2: '手機號登入', + }, + link: { + one3: '協力廠商登入', + two4: '友情連結', + }, + account: { + accountPlaceholder1: '用戶名admin或不輸均為common', + accountPlaceholder2: '密碼:123456', + accountPlaceholder3: '請輸入驗證碼', + accountBtnText: '登入', + }, + mobile: { + placeholder1: '請輸入手機號', + placeholder2: '請輸入驗證碼', + codeText: '獲取驗證碼', + btnText: '登入', + msgText: '* 溫馨提示:建議使用穀歌、Microsoft Edge,版本79.0.1072.62及以上瀏覽器,360瀏覽器請使用極速模式', + }, + scan: { + text: '打開手機掃一掃,快速登錄/注册', + }, + signInText: '歡迎回來!', +}; diff --git a/src/layout/component/aside.vue b/src/layout/component/aside.vue new file mode 100644 index 0000000..139364e --- /dev/null +++ b/src/layout/component/aside.vue @@ -0,0 +1,164 @@ +<template> + <div class="h100" v-show="!isTagsViewCurrenFull"> + <el-aside class="layout-aside" :class="setCollapseStyle"> +<!-- <Logo v-if="setShowLogo" />--> + <el-scrollbar class="flex-auto" ref="layoutAsideScrollbarRef" @mouseenter="onAsideEnterLeave(true)" @mouseleave="onAsideEnterLeave(false)"> + <Vertical :menuList="menuList" /> + </el-scrollbar> + <div style="font-size: 9px;color: rgba(255,255,255,.4);padding: 10px 20px">技术支持:<br/>苏州国科鸿宇智能科技有限公司</div> + </el-aside> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, computed, watch, getCurrentInstance, onBeforeMount, defineComponent } from 'vue'; +import { storeToRefs } from 'pinia'; +import pinia from '/@/stores/index'; +import { useRoutesList } from '/@/stores/routesList'; +import { useThemeConfig } from '/@/stores/themeConfig'; +import { useTagsViewRoutes } from '/@/stores/tagsViewRoutes'; +import Logo from '/@/layout/logo/index.vue'; +import Vertical from '/@/layout/navMenu/vertical.vue'; + +export default defineComponent({ + name: 'layoutAside', + components: { Logo, Vertical }, + setup() { + const { proxy } = <any>getCurrentInstance(); + const stores = useRoutesList(); + const storesThemeConfig = useThemeConfig(); + const storesTagsViewRoutes = useTagsViewRoutes(); + const { routesList } = storeToRefs(stores); + const { themeConfig } = storeToRefs(storesThemeConfig); + const { isTagsViewCurrenFull } = storeToRefs(storesTagsViewRoutes); + const state = reactive({ + menuList: [], + clientWidth: 0, + }); + // 设置菜单展开/收起时的宽度 + const setCollapseStyle = computed(() => { + const { layout, isCollapse, menuBar } = themeConfig.value; + const asideBrTheme = ['#FFFFFF', '#FFF', '#fff', '#ffffff']; + const asideBrColor = asideBrTheme.includes(menuBar) ? 'layout-el-aside-br-color' : ''; + // 判断是否是手机端 + if (state.clientWidth <= 1000) { + if (isCollapse) { + document.body.setAttribute('class', 'el-popup-parent--hidden'); + const asideEle = document.querySelector('.layout-container') as HTMLElement; + const modeDivs = document.createElement('div'); + modeDivs.setAttribute('class', 'layout-aside-mobile-mode'); + asideEle.appendChild(modeDivs); + modeDivs.addEventListener('click', closeLayoutAsideMobileMode); + return [asideBrColor, 'layout-aside-mobile', 'layout-aside-mobile-open']; + } else { + // 关闭弹窗 + closeLayoutAsideMobileMode(); + return [asideBrColor, 'layout-aside-mobile', 'layout-aside-mobile-close']; + } + } else { + if (layout === 'columns') { + // 分栏布局,菜单收起时宽度给 1px + if (isCollapse) return [asideBrColor, 'layout-aside-pc-1']; + else return [asideBrColor, 'layout-aside-pc-220']; + } else { + // 其它布局给 64px + if (isCollapse) return [asideBrColor, 'layout-aside-pc-64']; + else return [asideBrColor, 'layout-aside-pc-220']; + } + } + }); + // 关闭移动端蒙版 + const closeLayoutAsideMobileMode = () => { + const el = document.querySelector('.layout-aside-mobile-mode'); + el?.setAttribute('style', 'animation: error-img-two 0.3s'); + setTimeout(() => { + el?.parentNode?.removeChild(el); + }, 300); + const clientWidth = document.body.clientWidth; + if (clientWidth < 1000) themeConfig.value.isCollapse = false; + document.body.setAttribute('class', ''); + }; + // 设置显示/隐藏 logo + const setShowLogo = computed(() => { + let { layout, isShowLogo } = themeConfig.value; + return (isShowLogo && layout === 'defaults') || (isShowLogo && layout === 'columns'); + }); + // 设置/过滤路由(非静态路由/是否显示在菜单中) + const setFilterRoutes = () => { + if (themeConfig.value.layout === 'columns') return false; + (state.menuList as any) = filterRoutesFun(routesList.value); + }; + // 路由过滤递归函数 + const filterRoutesFun = (arr: Array<string>) => { + return arr + .filter((item: any) => !item.meta.isHide) + .map((item: any) => { + item = Object.assign({}, item); + if (item.children) item.children = filterRoutesFun(item.children); + return item; + }); + }; + // 设置菜单导航是否固定(移动端) + const initMenuFixed = (clientWidth: number) => { + state.clientWidth = clientWidth; + }; + // 鼠标移入、移出 + const onAsideEnterLeave = (bool: Boolean) => { + let { layout } = themeConfig.value; + if (layout !== 'columns') return false; + if (!bool) proxy.mittBus.emit('restoreDefault'); + stores.setColumnsMenuHover(bool); + }; + // 监听 themeConfig 配置文件的变化,更新菜单 el-scrollbar 的高度 + watch(themeConfig.value, (val) => { + if (val.isShowLogoChange !== val.isShowLogo) { + if (!proxy.$refs.layoutAsideScrollbarRef) return false; + proxy.$refs.layoutAsideScrollbarRef.update(); + } + }); + // 监听vuex值的变化,动态赋值给菜单中 + watch( + pinia.state, + (val) => { + let { layout, isClassicSplitMenu } = val.themeConfig.themeConfig; + if (layout === 'classic' && isClassicSplitMenu) return false; + setFilterRoutes(); + }, + { + deep: true, + } + ); + // 页面加载前 + onBeforeMount(() => { + initMenuFixed(document.body.clientWidth); + setFilterRoutes(); + // 此界面不需要取消监听(proxy.mittBus.off('setSendColumnsChildren)) + // 因为切换布局时有的监听需要使用,取消了监听,某些操作将不生效 + proxy.mittBus.on('setSendColumnsChildren', (res: any) => { + state.menuList = res.children; + }); + proxy.mittBus.on('setSendClassicChildren', (res: any) => { + let { layout, isClassicSplitMenu } = themeConfig.value; + if (layout === 'classic' && isClassicSplitMenu) { + state.menuList = []; + state.menuList = res.children; + } + }); + proxy.mittBus.on('getBreadcrumbIndexSetFilterRoutes', () => { + setFilterRoutes(); + }); + proxy.mittBus.on('layoutMobileResize', (res: any) => { + initMenuFixed(res.clientWidth); + closeLayoutAsideMobileMode(); + }); + }); + return { + setCollapseStyle, + setShowLogo, + isTagsViewCurrenFull, + onAsideEnterLeave, + ...toRefs(state), + }; + }, +}); +</script> diff --git a/src/layout/component/columnsAside.vue b/src/layout/component/columnsAside.vue new file mode 100644 index 0000000..7fd7806 --- /dev/null +++ b/src/layout/component/columnsAside.vue @@ -0,0 +1,292 @@ +<template> + <div class="layout-columns-aside"> + <el-scrollbar> + <ul @mouseleave="onColumnsAsideMenuMouseleave()"> + <li + v-for="(v, k) in columnsAsideList" + :key="k" + @click="onColumnsAsideMenuClick(v, k)" + @mouseenter="onColumnsAsideMenuMouseenter(v, k)" + :ref=" + (el) => { + if (el) columnsAsideOffsetTopRefs[k] = el; + } + " + :class="{ 'layout-columns-active': liIndex === k, 'layout-columns-hover': liHoverIndex === k }" + :title="$t(v.meta.title)" + > + <div :class="themeConfig.columnsAsideLayout" v-if="!v.meta.isLink || (v.meta.isLink && v.meta.isIframe)"> + <SvgIcon :name="v.meta.icon" /> + <div class="columns-vertical-title font12"> + {{ + $t(v.meta.title) && $t(v.meta.title).length >= 4 + ? $t(v.meta.title).substr(0, themeConfig.columnsAsideLayout === 'columns-vertical' ? 4 : 3) + : $t(v.meta.title) + }} + </div> + </div> + <div :class="themeConfig.columnsAsideLayout" v-else> + <a :href="v.meta.isLink" target="_blank"> + <SvgIcon :name="v.meta.icon" /> + <div class="columns-vertical-title font12"> + {{ + $t(v.meta.title) && $t(v.meta.title).length >= 4 + ? $t(v.meta.title).substr(0, themeConfig.columnsAsideLayout === 'columns-vertical' ? 4 : 3) + : $t(v.meta.title) + }} + </div> + </a> + </div> + </li> + <div ref="columnsAsideActiveRef" :class="themeConfig.columnsAsideStyle"></div> + </ul> + </el-scrollbar> + </div> +</template> + +<script lang="ts"> +import { reactive, toRefs, ref, onMounted, nextTick, getCurrentInstance, watch, onUnmounted, defineComponent } from 'vue'; +import { useRoute, useRouter, onBeforeRouteUpdate, RouteRecordRaw } from 'vue-router'; +import { storeToRefs } from 'pinia'; +import pinia from '/@/stores/index'; +import { useRoutesList } from '/@/stores/routesList'; +import { useThemeConfig } from '/@/stores/themeConfig'; + +// 定义接口来定义对象的类型 +interface ColumnsAsideState { + columnsAsideList: any[]; + liIndex: number; + liOldIndex: null | number; + liHoverIndex: null | number; + liOldPath: null | string; + difference: number; + routeSplit: string[]; +} + +export default defineComponent({ + name: 'layoutColumnsAside', + setup() { + const columnsAsideOffsetTopRefs: any = ref([]); + const columnsAsideActiveRef = ref(); + const { proxy } = <any>getCurrentInstance(); + const stores = useRoutesList(); + const storesThemeConfig = useThemeConfig(); + const { routesList, isColumnsMenuHover, isColumnsNavHover } = storeToRefs(stores); + const { themeConfig } = storeToRefs(storesThemeConfig); + const route = useRoute(); + const router = useRouter(); + const state = reactive<ColumnsAsideState>({ + columnsAsideList: [], + liIndex: 0, + liOldIndex: null, + liHoverIndex: null, + liOldPath: null, + difference: 0, + routeSplit: [], + }); + // 设置菜单高亮位置移动 + const setColumnsAsideMove = (k: number) => { + state.liIndex = k; + columnsAsideActiveRef.value.style.top = `${columnsAsideOffsetTopRefs.value[k].offsetTop + state.difference}px`; + }; + // 菜单高亮点击事件 + const onColumnsAsideMenuClick = (v: Object, k: number) => { + setColumnsAsideMove(k); + let { path, redirect } = v as any; + if (redirect) router.push(redirect); + else router.push(path); + }; + // 鼠标移入时,显示当前的子级菜单 + const onColumnsAsideMenuMouseenter = (v: RouteRecordRaw, k: number) => { + let { path } = v; + state.liOldPath = path; + state.liOldIndex = k; + state.liHoverIndex = k; + proxy.mittBus.emit('setSendColumnsChildren', setSendChildren(path)); + stores.setColumnsMenuHover(false); + stores.setColumnsNavHover(true); + }; + // 鼠标移走时,显示原来的子级菜单 + const onColumnsAsideMenuMouseleave = async () => { + await stores.setColumnsNavHover(false); + // 添加延时器,防止拿到的 store.state.routesList 值不是最新的 + setTimeout(() => { + if (!isColumnsMenuHover && !isColumnsNavHover) proxy.mittBus.emit('restoreDefault'); + }, 100); + }; + // 设置高亮动态位置 + const onColumnsAsideDown = (k: number) => { + nextTick(() => { + setColumnsAsideMove(k); + }); + }; + // 设置/过滤路由(非静态路由/是否显示在菜单中) + const setFilterRoutes = () => { + state.columnsAsideList = filterRoutesFun(routesList.value); + const resData: any = setSendChildren(route.path); + if (Object.keys(resData).length <= 0) return false; + onColumnsAsideDown(resData.item[0].k); + proxy.mittBus.emit('setSendColumnsChildren', resData); + }; + // 传送当前子级数据到菜单中 + const setSendChildren = (path: string) => { + const currentPathSplit = path.split('/'); + let currentData: any = {}; + state.columnsAsideList.map((v: any, k: number) => { + if (v.path === `/${currentPathSplit[1]}`) { + v['k'] = k; + currentData['item'] = [{ ...v }]; + currentData['children'] = [{ ...v }]; + if (v.children) currentData['children'] = v.children; + } + }); + return currentData; + }; + // 路由过滤递归函数 + const filterRoutesFun = (arr: Array<string>) => { + return arr + .filter((item: any) => !item.meta.isHide) + .map((item: any) => { + item = Object.assign({}, item); + if (item.children) item.children = filterRoutesFun(item.children); + return item; + }); + }; + // tagsView 点击时,根据路由查找下标 columnsAsideList,实现左侧菜单高亮 + const setColumnsMenuHighlight = (path: string) => { + state.routeSplit = path.split('/'); + state.routeSplit.shift(); + const routeFirst = `/${state.routeSplit[0]}`; + const currentSplitRoute = state.columnsAsideList.find((v: any) => v.path === routeFirst); + if (!currentSplitRoute) return false; + // 延迟拿值,防止取不到 + setTimeout(() => { + onColumnsAsideDown((<any>currentSplitRoute).k); + }, 0); + }; + // 监听布局配置信息的变化,动态增加菜单高亮位置移动像素 + watch( + pinia.state, + (val) => { + val.themeConfig.themeConfig.columnsAsideStyle === 'columnsRound' ? (state.difference = 3) : (state.difference = 0); + if (!val.routesList.isColumnsMenuHover && !val.routesList.isColumnsNavHover) { + state.liHoverIndex = null; + proxy.mittBus.emit('setSendColumnsChildren', setSendChildren(route.path)); + } else { + state.liHoverIndex = state.liOldIndex; + if (!state.liOldPath) return false; + proxy.mittBus.emit('setSendColumnsChildren', setSendChildren(state.liOldPath)); + } + }, + { + deep: true, + } + ); + // 页面加载时 + onMounted(() => { + setFilterRoutes(); + // 销毁变量,防止鼠标再次移入时,保留了上次的记录 + proxy.mittBus.on('restoreDefault', () => { + state.liOldIndex = null; + state.liOldPath = null; + }); + }); + // 页面卸载时 + onUnmounted(() => { + proxy.mittBus.off('restoreDefault', () => {}); + }); + // 路由更新时 + onBeforeRouteUpdate((to) => { + setColumnsMenuHighlight(to.path); + proxy.mittBus.emit('setSendColumnsChildren', setSendChildren(to.path)); + }); + return { + themeConfig, + columnsAsideOffsetTopRefs, + columnsAsideActiveRef, + onColumnsAsideDown, + onColumnsAsideMenuClick, + onColumnsAsideMenuMouseenter, + onColumnsAsideMenuMouseleave, + ...toRefs(state), + }; + }, +}); +</script> + +<style scoped lang="scss"> +.layout-columns-aside { + width: 70px; + height: 100%; + background: var(--next-bg-columnsMenuBar); + ul { + position: relative; + li { + color: var(--next-bg-columnsMenuBarColor); + width: 100%; + height: 50px; + text-align: center; + display: flex; + cursor: pointer; + position: relative; + z-index: 1; + .columns-vertical { + margin: auto; + .columns-vertical-title { + padding-top: 1px; + } + } + .columns-horizontal { + display: flex; + height: 50px; + width: 100%; + align-items: center; + padding: 0 5px; + i { + margin-right: 3px; + } + a { + display: flex; + .columns-horizontal-title { + padding-top: 1px; + } + } + } + a { + text-decoration: none; + color: var(--next-bg-columnsMenuBarColor); + } + } + .layout-columns-active { + color: var(--next-bg-columnsMenuBarColor) !important; + transition: 0.3s ease-in-out; + } + .layout-columns-hover { + color: var(--el-color-primary); + a { + color: var(--el-color-primary); + } + } + .columns-round { + background: var(--el-color-primary); + color: var(--el-color-white); + position: absolute; + left: 50%; + top: 2px; + height: 44px; + width: 65px; + transform: translateX(-50%); + z-index: 0; + transition: 0.3s ease-in-out; + border-radius: 5px; + } + .columns-card { + @extend .columns-round; + top: 0; + height: 50px; + width: 100%; + border-radius: 0; + } + } +} +</style> diff --git a/src/layout/component/header.vue b/src/layout/component/header.vue new file mode 100644 index 0000000..75a9410 --- /dev/null +++ b/src/layout/component/header.vue @@ -0,0 +1,34 @@ +<template> + <el-header class="layout-header" :height="setHeaderHeight" v-show="!isTagsViewCurrenFull"> + <NavBarsIndex /> + </el-header> +</template> + +<script lang="ts"> +import { computed, defineComponent } from 'vue'; +import { storeToRefs } from 'pinia'; +import { useThemeConfig } from '/@/stores/themeConfig'; +import { useTagsViewRoutes } from '/@/stores/tagsViewRoutes'; +import NavBarsIndex from '/@/layout/navBars/index.vue'; + +export default defineComponent({ + name: 'layoutHeader', + components: { NavBarsIndex }, + setup() { + const storesTagsViewRoutes = useTagsViewRoutes(); + const storesThemeConfig = useThemeConfig(); + const { themeConfig } = storeToRefs(storesThemeConfig); + const { isTagsViewCurrenFull } = storeToRefs(storesTagsViewRoutes); + // 设置 header 的高度 + const setHeaderHeight = computed(() => { + let { isTagsview, layout } = themeConfig.value; + if (isTagsview && layout !== 'classic') return '84px'; + else return '80px'; + }); + return { + setHeaderHeight, + isTagsViewCurrenFull, + }; + }, +}); +</script> diff --git a/src/layout/component/main.vue b/src/layout/component/main.vue new file mode 100644 index 0000000..18eba60 --- /dev/null +++ b/src/layout/component/main.vue @@ -0,0 +1,101 @@ +<template> + <el-main class="layout-main"> + <el-scrollbar + ref="layoutScrollbarRef" + :class="{ + 'layout-scrollbar': + (!isClassicOrTransverse && !currentRouteMeta.isLink && !currentRouteMeta.isIframe) || + (!isClassicOrTransverse && currentRouteMeta.isLink && !currentRouteMeta.isIframe), + }" + > + <LayoutParentView + :style="{ + padding: !isClassicOrTransverse || (currentRouteMeta.isLink && currentRouteMeta.isIframe) ? '0' : '15px', + transition: 'padding 0.3s ease-in-out', + }" + /> + <Footer v-if="themeConfig.isFooter" /> + </el-scrollbar> + </el-main> +</template> + +<script lang="ts"> +import { defineComponent, toRefs, reactive, getCurrentInstance, watch, onMounted, computed } from 'vue'; +import { useRoute } from 'vue-router'; +import { storeToRefs } from 'pinia'; +import { useThemeConfig } from '/@/stores/themeConfig'; +import { NextLoading } from '/@/utils/loading'; +import LayoutParentView from '/@/layout/routerView/parent.vue'; +import Footer from '/@/layout/footer/index.vue'; + +// 定义接口来定义对象的类型 +interface MainState { + headerHeight: string | number; + currentRouteMeta: any; +} + +export default defineComponent({ + name: 'layoutMain', + components: { LayoutParentView, Footer }, + setup() { + const { proxy } = <any>getCurrentInstance(); + const storesThemeConfig = useThemeConfig(); + const { themeConfig } = storeToRefs(storesThemeConfig); + const route = useRoute(); + const state = reactive<MainState>({ + headerHeight: '', + currentRouteMeta: {}, + }); + // 判断布局 + const isClassicOrTransverse = computed(() => { + const { layout } = themeConfig.value; + return layout === 'classic' || layout === 'transverse'; + }); + // 设置 main 的高度 + const initHeaderHeight = () => { + const bool = state.currentRouteMeta.isLink && state.currentRouteMeta.isIframe; + let { isTagsview } = themeConfig.value; + if (isTagsview) return (state.headerHeight = bool ? `86px` : `115px`); + else return (state.headerHeight = `80px`); + }; + // 初始化获取当前路由 meta,用于设置 iframes padding + const initGetMeta = () => { + state.currentRouteMeta = route.meta; + }; + // 页面加载前 + onMounted(async () => { + await initGetMeta(); + initHeaderHeight(); + NextLoading.done(); + }); + // 监听路由变化 + watch( + () => route.path, + () => { + state.currentRouteMeta = route.meta; + const bool = state.currentRouteMeta.isLink && state.currentRouteMeta.isIframe; + state.headerHeight = bool ? `86px` : `115px`; + proxy.$refs.layoutScrollbarRef.update(); + } + ); + // 监听 themeConfig 配置文件的变化,更新菜单 el-scrollbar 的高度 + watch( + themeConfig, + (val) => { + state.currentRouteMeta = route.meta; + const bool = state.currentRouteMeta.isLink && state.currentRouteMeta.isIframe; + state.headerHeight = val.isTagsview ? (bool ? `86px` : `115px`) : '51px'; + proxy.$refs?.layoutScrollbarRef?.update(); + }, + { + deep: true, + } + ); + return { + themeConfig, + isClassicOrTransverse, + ...toRefs(state), + }; + }, +}); +</script> diff --git a/src/layout/footer/index.vue b/src/layout/footer/index.vue new file mode 100644 index 0000000..ef00591 --- /dev/null +++ b/src/layout/footer/index.vue @@ -0,0 +1,47 @@ +<template> + <div class="layout-footer mt15" v-show="isDelayFooter"> + <div class="layout-footer-warp"> + <div>vue-next-admin,Made by lyt with ❤️</div> + <div class="mt5">深圳市 xxx 公司版权所有</div> + </div> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, defineComponent } from 'vue'; +import { onBeforeRouteUpdate } from 'vue-router'; + +export default defineComponent({ + name: 'layoutFooter', + setup() { + const state = reactive({ + isDelayFooter: true, + }); + // 路由改变时,等主界面动画加载完毕再显示 footer + onBeforeRouteUpdate(() => { + setTimeout(() => { + state.isDelayFooter = false; + setTimeout(() => { + state.isDelayFooter = true; + }, 800); + }, 0); + }); + return { + ...toRefs(state), + }; + }, +}); +</script> + +<style scoped lang="scss"> +.layout-footer { + width: 100%; + display: flex; + &-warp { + margin: auto; + color: var(--el-text-color-secondary); + text-align: center; + animation: error-num 1s ease-in-out; + } +} +</style> diff --git a/src/layout/index.vue b/src/layout/index.vue new file mode 100644 index 0000000..50643a4 --- /dev/null +++ b/src/layout/index.vue @@ -0,0 +1,54 @@ +<template> + <component :is="themeConfig.layout" /> +</template> + +<script lang="ts"> +import { onBeforeMount, onUnmounted, getCurrentInstance, defineComponent, defineAsyncComponent } from 'vue'; +import { storeToRefs } from 'pinia'; +import { useThemeConfig } from '/@/stores/themeConfig'; +import { Local } from '/@/utils/storage'; + +export default defineComponent({ + name: 'layout', + components: { + defaults: defineAsyncComponent(() => import('/@/layout/main/defaults.vue')), + classic: defineAsyncComponent(() => import('/@/layout/main/classic.vue')), + transverse: defineAsyncComponent(() => import('/@/layout/main/transverse.vue')), + columns: defineAsyncComponent(() => import('/@/layout/main/columns.vue')), + }, + setup() { + const { proxy } = <any>getCurrentInstance(); + const storesThemeConfig = useThemeConfig(); + const { themeConfig } = storeToRefs(storesThemeConfig); + // 窗口大小改变时(适配移动端) + const onLayoutResize = () => { + if (!Local.get('oldLayout')) Local.set('oldLayout', themeConfig.value.layout); + const clientWidth = document.body.clientWidth; + if (clientWidth < 1000) { + themeConfig.value.isCollapse = false; + proxy.mittBus.emit('layoutMobileResize', { + layout: 'defaults', + clientWidth, + }); + } else { + proxy.mittBus.emit('layoutMobileResize', { + layout: Local.get('oldLayout') ? Local.get('oldLayout') : themeConfig.value.layout, + clientWidth, + }); + } + }; + // 页面加载前 + onBeforeMount(() => { + onLayoutResize(); + window.addEventListener('resize', onLayoutResize); + }); + // 页面卸载时 + onUnmounted(() => { + window.removeEventListener('resize', onLayoutResize); + }); + return { + themeConfig, + }; + }, +}); +</script> diff --git a/src/layout/lockScreen/index.vue b/src/layout/lockScreen/index.vue new file mode 100644 index 0000000..10b8fed --- /dev/null +++ b/src/layout/lockScreen/index.vue @@ -0,0 +1,372 @@ +<template> + <div v-show="isShowLockScreen"> + <div class="layout-lock-screen-mask"></div> + <div class="layout-lock-screen-img" :class="{ 'layout-lock-screen-filter': isShowLoockLogin }"></div> + <div class="layout-lock-screen"> + <div + class="layout-lock-screen-date" + ref="layoutLockScreenDateRef" + @mousedown="onDown" + @mousemove="onMove" + @mouseup="onEnd" + @touchstart.stop="onDown" + @touchmove.stop="onMove" + @touchend.stop="onEnd" + > + <div class="layout-lock-screen-date-box"> + <div class="layout-lock-screen-date-box-time"> + {{ time.hm }}<span class="layout-lock-screen-date-box-minutes">{{ time.s }}</span> + </div> + <div class="layout-lock-screen-date-box-info">{{ time.mdq }}</div> + </div> + <div class="layout-lock-screen-date-top"> + <SvgIcon name="ele-Top" /> + <div class="layout-lock-screen-date-top-text">上滑解锁</div> + </div> + </div> + <transition name="el-zoom-in-center"> + <div v-show="isShowLoockLogin" class="layout-lock-screen-login"> + <div class="layout-lock-screen-login-box"> + <div class="layout-lock-screen-login-box-img"> + <img src="https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=1813762643,1914315241&fm=26&gp=0.jpg" /> + </div> + <div class="layout-lock-screen-login-box-name">Administrator</div> + <div class="layout-lock-screen-login-box-value"> + <el-input + placeholder="请输入密码" + ref="layoutLockScreenInputRef" + v-model="lockScreenPassword" + @keyup.enter.native.stop="onLockScreenSubmit()" + > + <template #append> + <el-button @click="onLockScreenSubmit"> + <el-icon class="el-input__icon"> + <ele-Right /> + </el-icon> + </el-button> + </template> + </el-input> + </div> + </div> + <div class="layout-lock-screen-login-icon"> + <SvgIcon name="ele-Microphone" :size="20" /> + <SvgIcon name="ele-AlarmClock" :size="20" /> + <SvgIcon name="ele-SwitchButton" :size="20" /> + </div> + </div> + </transition> + </div> + </div> +</template> + +<script lang="ts"> +import { nextTick, onMounted, reactive, toRefs, ref, onUnmounted, getCurrentInstance, defineComponent } from 'vue'; +import { formatDate } from '/@/utils/formatTime'; +import { Local } from '/@/utils/storage'; +import { storeToRefs } from 'pinia'; +import { useThemeConfig } from '/@/stores/themeConfig'; + +// 定义接口来定义对象的类型 +interface LockScreenState { + transparency: number; + downClientY: number; + moveDifference: number; + isShowLoockLogin: boolean; + isFlags: boolean; + querySelectorEl: HTMLElement | string; + time: { + hm: string; + s: string; + mdq: string; + }; + setIntervalTime: number; + isShowLockScreen: boolean; + isShowLockScreenIntervalTime: number; + lockScreenPassword: string; +} + +export default defineComponent({ + name: 'layoutLockScreen', + setup() { + const { proxy } = <any>getCurrentInstance(); + const layoutLockScreenInputRef = ref(); + const storesThemeConfig = useThemeConfig(); + const { themeConfig } = storeToRefs(storesThemeConfig); + const state = reactive<LockScreenState>({ + transparency: 1, + downClientY: 0, + moveDifference: 0, + isShowLoockLogin: false, + isFlags: false, + querySelectorEl: '', + time: { + hm: '', + s: '', + mdq: '', + }, + setIntervalTime: 0, + isShowLockScreen: false, + isShowLockScreenIntervalTime: 0, + lockScreenPassword: '', + }); + // 鼠标按下 + const onDown = (down: any) => { + state.isFlags = true; + state.downClientY = down.touches ? down.touches[0].clientY : down.clientY; + }; + // 鼠标移动 + const onMove = (move: any) => { + if (state.isFlags) { + const el = <HTMLElement>state.querySelectorEl; + const opacitys = (state.transparency -= 1 / 200); + if (move.touches) { + state.moveDifference = move.touches[0].clientY - state.downClientY; + } else { + state.moveDifference = move.clientY - state.downClientY; + } + if (state.moveDifference >= 0) return false; + el.setAttribute('style', `top:${state.moveDifference}px;cursor:pointer;opacity:${opacitys};`); + if (state.moveDifference < -400) { + el.setAttribute('style', `top:${-el.clientHeight}px;cursor:pointer;transition:all 0.3s ease;`); + state.moveDifference = -el.clientHeight; + setTimeout(() => { + el && el.parentNode?.removeChild(el); + }, 300); + } + if (state.moveDifference === -el.clientHeight) { + state.isShowLoockLogin = true; + layoutLockScreenInputRef.value.focus(); + } + } + }; + // 鼠标松开 + const onEnd = () => { + state.isFlags = false; + state.transparency = 1; + if (state.moveDifference >= -400) { + (<HTMLElement>state.querySelectorEl).setAttribute('style', `top:0px;opacity:1;transition:all 0.3s ease;`); + } + }; + // 获取要拖拽的初始元素 + const initGetElement = () => { + nextTick(() => { + state.querySelectorEl = proxy.$refs.layoutLockScreenDateRef; + }); + }; + // 时间初始化 + const initTime = () => { + state.time.hm = formatDate(new Date(), 'HH:MM'); + state.time.s = formatDate(new Date(), 'SS'); + state.time.mdq = formatDate(new Date(), 'mm月dd日,WWW'); + }; + // 时间初始化定时器 + const initSetTime = () => { + initTime(); + state.setIntervalTime = window.setInterval(() => { + initTime(); + }, 1000); + }; + // 锁屏时间定时器 + const initLockScreen = () => { + if (themeConfig.value.isLockScreen) { + state.isShowLockScreenIntervalTime = window.setInterval(() => { + if (themeConfig.value.lockScreenTime <= 1) { + state.isShowLockScreen = true; + setLocalThemeConfig(); + return false; + } + themeConfig.value.lockScreenTime--; + }, 1000); + } else { + clearInterval(state.isShowLockScreenIntervalTime); + } + }; + // 存储布局配置 + const setLocalThemeConfig = () => { + themeConfig.value.isDrawer = false; + Local.set('themeConfig', themeConfig.value); + }; + // 密码输入点击事件 + const onLockScreenSubmit = () => { + themeConfig.value.isLockScreen = false; + themeConfig.value.lockScreenTime = 30; + setLocalThemeConfig(); + }; + // 页面加载时 + onMounted(() => { + initGetElement(); + initSetTime(); + initLockScreen(); + }); + // 页面卸载时 + onUnmounted(() => { + window.clearInterval(state.setIntervalTime); + window.clearInterval(state.isShowLockScreenIntervalTime); + }); + return { + layoutLockScreenInputRef, + onDown, + onMove, + onEnd, + onLockScreenSubmit, + ...toRefs(state), + }; + }, +}); +</script> + +<style scoped lang="scss"> +.layout-lock-screen-fixed { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; +} +.layout-lock-screen-filter { + filter: blur(1px); +} +.layout-lock-screen-mask { + background: var(--el-color-white); + @extend .layout-lock-screen-fixed; + z-index: 9999990; +} +.layout-lock-screen-img { + @extend .layout-lock-screen-fixed; + background-image: url('https://img-blog.csdnimg.cn/afa9c317667f47d5bea34b85af45979e.png#pic_center'); + background-size: 100% 100%; + z-index: 9999991; +} +.layout-lock-screen { + @extend .layout-lock-screen-fixed; + z-index: 9999992; + &-date { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100%; + color: var(--el-color-white); + z-index: 9999993; + user-select: none; + &-box { + position: absolute; + left: 30px; + bottom: 50px; + &-time { + font-size: 100px; + color: var(--el-color-white); + } + &-info { + font-size: 40px; + color: var(--el-color-white); + } + &-minutes { + font-size: 16px; + } + } + &-top { + width: 40px; + height: 40px; + line-height: 40px; + border-radius: 100%; + border: 1px solid var(--el-border-color-light, #ebeef5); + background: rgba(255, 255, 255, 0.1); + color: var(--el-color-white); + opacity: 0.8; + position: absolute; + right: 30px; + bottom: 50px; + text-align: center; + overflow: hidden; + transition: all 0.3s ease; + i { + transition: all 0.3s ease; + } + &-text { + opacity: 0; + position: absolute; + top: 150%; + font-size: 12px; + color: var(--el-color-white); + left: 50%; + line-height: 1.2; + transform: translate(-50%, -50%); + transition: all 0.3s ease; + width: 35px; + } + &:hover { + border: 1px solid rgba(255, 255, 255, 0.5); + background: rgba(255, 255, 255, 0.2); + box-shadow: 0 0 12px 0 rgba(255, 255, 255, 0.5); + color: var(--el-color-white); + opacity: 1; + transition: all 0.3s ease; + i { + transform: translateY(-40px); + transition: all 0.3s ease; + } + .layout-lock-screen-date-top-text { + opacity: 1; + top: 50%; + transition: all 0.3s ease; + } + } + } + } + &-login { + position: relative; + z-index: 9999994; + width: 100%; + height: 100%; + left: 0; + top: 0; + display: flex; + flex-direction: column; + justify-content: center; + color: var(--el-color-white); + &-box { + text-align: center; + margin: auto; + &-img { + width: 180px; + height: 180px; + margin: auto; + img { + width: 100%; + height: 100%; + border-radius: 100%; + } + } + &-name { + font-size: 26px; + margin: 15px 0 30px; + } + } + &-icon { + position: absolute; + right: 30px; + bottom: 30px; + i { + font-size: 20px; + margin-left: 15px; + cursor: pointer; + opacity: 0.8; + &:hover { + opacity: 1; + } + } + } + } +} +::v-deep(.el-input-group__append) { + background: var(--el-color-white); + padding: 0px 15px; +} +::v-deep(.el-input__inner) { + border-right-color: var(--el-border-color-extra-light); + &:hover { + border-color: var(--el-border-color-extra-light); + } +} +</style> diff --git a/src/layout/logo/index.vue b/src/layout/logo/index.vue new file mode 100644 index 0000000..3d2b543 --- /dev/null +++ b/src/layout/logo/index.vue @@ -0,0 +1,85 @@ +<template> + <div class="layout-logo" v-if="setShowLogo" @click="onThemeConfigChange"> + <img :src="logoMini" class="layout-logo-medium-img" /> + <span>{{ themeConfig.globalTitle }}</span> + </div> + <div class="layout-logo-size" v-else @click="onThemeConfigChange"> + <img :src="logoMini" class="layout-logo-size-img" /> + </div> +</template> + +<script lang="ts"> +import { computed, defineComponent } from 'vue'; +import { storeToRefs } from 'pinia'; +import { useThemeConfig } from '/@/stores/themeConfig'; + +import logoMini from '/@/assets/logo-mini.svg'; + +export default defineComponent({ + name: 'layoutLogo', + setup() { + const storesThemeConfig = useThemeConfig(); + const { themeConfig } = storeToRefs(storesThemeConfig); + // 设置 logo 的显示。classic 经典布局默认显示 logo + const setShowLogo = computed(() => { + let { isCollapse, layout } = themeConfig.value; + return !isCollapse || layout === 'classic' || document.body.clientWidth < 1000; + }); + // logo 点击实现菜单展开/收起 + const onThemeConfigChange = () => { + if (themeConfig.value.layout === 'transverse') return false; + themeConfig.value.isCollapse = !themeConfig.value.isCollapse; + }; + return { + logoMini, + setShowLogo, + themeConfig, + onThemeConfigChange, + }; + }, +}); +</script> + +<style scoped lang="scss"> +.layout-logo { + width: 220px; + height: 50px; + display: flex; + align-items: center; + justify-content: center; + box-shadow: rgb(0 21 41 / 2%) 0px 1px 4px; + color: var(--el-color-primary); + font-size: 16px; + cursor: pointer; + animation: logoAnimation 0.3s ease-in-out; + span { + white-space: nowrap; + display: inline-block; + } + &:hover { + span { + color: var(--color-primary-light-2); + } + } + &-medium-img { + width: 20px; + margin-right: 5px; + } +} +.layout-logo-size { + width: 100%; + height: 50px; + display: flex; + cursor: pointer; + animation: logoAnimation 0.3s ease-in-out; + &-img { + width: 20px; + margin: auto; + } + &:hover { + img { + animation: logoAnimation 0.3s ease-in-out; + } + } +} +</style> diff --git a/src/layout/main/classic.vue b/src/layout/main/classic.vue new file mode 100644 index 0000000..b92290f --- /dev/null +++ b/src/layout/main/classic.vue @@ -0,0 +1,35 @@ +<template> + <el-container class="layout-container flex-center"> + <Header /> + <el-container class="layout-mian-height-50"> + <Aside /> + <div class="flex-center layout-backtop"> + <TagsView v-if="themeConfig.isTagsview" /> + <Main /> + </div> + </el-container> + <el-backtop target=".layout-backtop .el-main .el-scrollbar__wrap"></el-backtop> + </el-container> +</template> + +<script lang="ts"> +import { defineComponent } from 'vue'; +import { storeToRefs } from 'pinia'; +import { useThemeConfig } from '/@/stores/themeConfig'; +import Aside from '/@/layout/component/aside.vue'; +import Header from '/@/layout/component/header.vue'; +import Main from '/@/layout/component/main.vue'; +import TagsView from '/@/layout/navBars/tagsView/tagsView.vue'; + +export default defineComponent({ + name: 'layoutClassic', + components: { Aside, Header, Main, TagsView }, + setup() { + const storesThemeConfig = useThemeConfig(); + const { themeConfig } = storeToRefs(storesThemeConfig); + return { + themeConfig, + }; + }, +}); +</script> diff --git a/src/layout/main/columns.vue b/src/layout/main/columns.vue new file mode 100644 index 0000000..0aa1d31 --- /dev/null +++ b/src/layout/main/columns.vue @@ -0,0 +1,41 @@ +<template> + <el-container class="layout-container"> + <ColumnsAside /> + <div class="layout-columns-warp"> + <Aside /> + <el-container class="flex-center layout-backtop" :class="{ 'layout-backtop': !isFixedHeader }"> + <Header v-if="isFixedHeader" /> + <el-scrollbar :class="{ 'layout-backtop': isFixedHeader }"> + <Header v-if="!isFixedHeader" /> + <Main /> + </el-scrollbar> + </el-container> + </div> + <el-backtop target=".layout-backtop .el-scrollbar__wrap"></el-backtop> + </el-container> +</template> + +<script lang="ts"> +import { computed, defineComponent } from 'vue'; +import { storeToRefs } from 'pinia'; +import { useThemeConfig } from '/@/stores/themeConfig'; +import Aside from '/@/layout/component/aside.vue'; +import Header from '/@/layout/component/header.vue'; +import Main from '/@/layout/component/main.vue'; +import ColumnsAside from '/@/layout/component/columnsAside.vue'; + +export default defineComponent({ + name: 'layoutColumns', + components: { Aside, Header, Main, ColumnsAside }, + setup() { + const storesThemeConfig = useThemeConfig(); + const { themeConfig } = storeToRefs(storesThemeConfig); + const isFixedHeader = computed(() => { + return themeConfig.value.isFixedHeader; + }); + return { + isFixedHeader, + }; + }, +}); +</script> diff --git a/src/layout/main/defaults.vue b/src/layout/main/defaults.vue new file mode 100644 index 0000000..0cabb0c --- /dev/null +++ b/src/layout/main/defaults.vue @@ -0,0 +1,47 @@ +<template> + <el-container class="layout-container"> + <Aside /> + <el-container class="flex-center" :class="{ 'layout-backtop': !isFixedHeader }"> + <Header v-if="isFixedHeader" /> + <el-scrollbar ref="layoutDefaultsScrollbarRef" :class="{ 'layout-backtop': isFixedHeader }"> + <Header v-if="!isFixedHeader" /> + <Main /> + </el-scrollbar> + </el-container> + <el-backtop target=".layout-backtop .el-scrollbar__wrap"></el-backtop> + </el-container> +</template> + +<script lang="ts"> +import { computed, getCurrentInstance, watch, defineComponent } from 'vue'; +import { useRoute } from 'vue-router'; +import { storeToRefs } from 'pinia'; +import { useThemeConfig } from '/@/stores/themeConfig'; +import Aside from '/@/layout/component/aside.vue'; +import Header from '/@/layout/component/header.vue'; +import Main from '/@/layout/component/main.vue'; + +export default defineComponent({ + name: 'layoutDefaults', + components: { Aside, Header, Main }, + setup() { + const { proxy } = <any>getCurrentInstance(); + const route = useRoute(); + const storesThemeConfig = useThemeConfig(); + const { themeConfig } = storeToRefs(storesThemeConfig); + const isFixedHeader = computed(() => { + return themeConfig.value.isFixedHeader; + }); + // 监听路由的变化 + watch( + () => route.path, + () => { + proxy.$refs.layoutDefaultsScrollbarRef.wrap$.scrollTop = 0; + } + ); + return { + isFixedHeader, + }; + }, +}); +</script> diff --git a/src/layout/main/transverse.vue b/src/layout/main/transverse.vue new file mode 100644 index 0000000..538f911 --- /dev/null +++ b/src/layout/main/transverse.vue @@ -0,0 +1,17 @@ +<template> + <el-container class="layout-container flex-center layout-backtop"> + <Header /> + <Main /> + <el-backtop target=".layout-backtop .el-main .el-scrollbar__wrap"></el-backtop> + </el-container> +</template> + +<script lang="ts"> +import Header from '/@/layout/component/header.vue'; +import Main from '/@/layout/component/main.vue'; + +export default { + name: 'layoutTransverse', + components: { Header, Main }, +}; +</script> diff --git a/src/layout/navBars/breadcrumb/breadcrumb.vue b/src/layout/navBars/breadcrumb/breadcrumb.vue new file mode 100644 index 0000000..e66356e --- /dev/null +++ b/src/layout/navBars/breadcrumb/breadcrumb.vue @@ -0,0 +1,162 @@ +<template> + <div v-if="isShowBreadcrumb" class="layout-navbars-breadcrumb"> + <SvgIcon + class="layout-navbars-breadcrumb-icon" + :name="themeConfig.isCollapse ? 'ele-Expand' : 'ele-Fold'" + :size="16" + @click="onThemeConfigChange" + /> + <el-breadcrumb class="layout-navbars-breadcrumb-hide"> + <transition-group name="breadcrumb"> + <el-breadcrumb-item v-for="(v, k) in breadcrumbList" :key="!v.meta.tagsViewName ? v.meta.title : v.meta.tagsViewName"> + <span v-if="k === breadcrumbList.length - 1" class="layout-navbars-breadcrumb-span"> + <SvgIcon :name="v.meta.icon" class="layout-navbars-breadcrumb-iconfont" v-if="themeConfig.isBreadcrumbIcon" /> + <div v-if="!v.meta.tagsViewName">{{ $t(v.meta.title) }}</div> + <div v-else>{{ v.meta.tagsViewName }}</div> + </span> + <a v-else @click.prevent="onBreadcrumbClick(v)"> + <SvgIcon :name="v.meta.icon" class="layout-navbars-breadcrumb-iconfont" v-if="themeConfig.isBreadcrumbIcon" />{{ $t(v.meta.title) }} + </a> + </el-breadcrumb-item> + </transition-group> + </el-breadcrumb> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, computed, onMounted, defineComponent } from 'vue'; +import { onBeforeRouteUpdate, useRoute, useRouter } from 'vue-router'; +import { Local } from '/@/utils/storage'; +import other from '/@/utils/other'; +import { storeToRefs } from 'pinia'; +import { useThemeConfig } from '/@/stores/themeConfig'; +import { useRoutesList } from '/@/stores/routesList'; + +// 定义接口来定义对象的类型 +interface BreadcrumbState { + breadcrumbList: Array<any>; + routeSplit: Array<string>; + routeSplitFirst: string; + routeSplitIndex: number; +} + +export default defineComponent({ + name: 'layoutBreadcrumb', + setup() { + const stores = useRoutesList(); + const storesThemeConfig = useThemeConfig(); + const { themeConfig } = storeToRefs(storesThemeConfig); + const { routesList } = storeToRefs(stores); + const route = useRoute(); + const router = useRouter(); + const state = reactive<BreadcrumbState>({ + breadcrumbList: [], + routeSplit: [], + routeSplitFirst: '', + routeSplitIndex: 1, + }); + // 动态设置经典、横向布局不显示 + const isShowBreadcrumb = computed(() => { + initRouteSplit(route.path); + const { layout, isBreadcrumb } = themeConfig.value; + if (layout === 'classic' || layout === 'transverse') return false; + else return isBreadcrumb ? true : false; + }); + // 面包屑点击时 + const onBreadcrumbClick = (v: any) => { + const { redirect, path } = v; + if (redirect) router.push(redirect); + else router.push(path); + }; + // 展开/收起左侧菜单点击 + const onThemeConfigChange = () => { + themeConfig.value.isCollapse = !themeConfig.value.isCollapse; + setLocalThemeConfig(); + }; + // 存储布局配置 + const setLocalThemeConfig = () => { + Local.remove('themeConfig'); + Local.set('themeConfig', themeConfig.value); + }; + // 处理面包屑数据 + const getBreadcrumbList = (arr: Array<string>) => { + arr.forEach((item: any) => { + state.routeSplit.forEach((v: any, k: number, arrs: any) => { + if (state.routeSplitFirst === item.path) { + state.routeSplitFirst += `/${arrs[state.routeSplitIndex]}`; + state.breadcrumbList.push(item); + state.routeSplitIndex++; + if (item.children) getBreadcrumbList(item.children); + } + }); + }); + }; + // 当前路由字符串切割成数组,并删除第一项空内容 + const initRouteSplit = (path: string) => { + if (!themeConfig.value.isBreadcrumb) return false; + state.breadcrumbList = [routesList.value[0]]; + state.routeSplit = path.split('/'); + state.routeSplit.shift(); + state.routeSplitFirst = `/${state.routeSplit[0]}`; + state.routeSplitIndex = 1; + getBreadcrumbList(routesList.value); + if (route.name === 'home' || (route.name === 'notFound' && state.breadcrumbList.length > 1)) state.breadcrumbList.shift(); + if (state.breadcrumbList.length > 0) state.breadcrumbList[state.breadcrumbList.length - 1].meta.tagsViewName = other.setTagsViewNameI18n(route); + }; + // 页面加载时 + onMounted(() => { + initRouteSplit(route.path); + }); + // 路由更新时 + onBeforeRouteUpdate((to) => { + initRouteSplit(to.path); + }); + return { + onThemeConfigChange, + isShowBreadcrumb, + themeConfig, + onBreadcrumbClick, + ...toRefs(state), + }; + }, +}); +</script> + +<style scoped lang="scss"> +.layout-navbars-breadcrumb { + height: inherit; + display: flex; + align-items: center; + .layout-navbars-breadcrumb-icon { + cursor: pointer; + font-size: 18px; + color: var(--next-bg-topBarColor); + height: 100%; + width: 40px; + opacity: 0.8; + &:hover { + opacity: 1; + } + } + .layout-navbars-breadcrumb-span { + display: flex; + opacity: 0.7; + color: var(--next-bg-topBarColor); + } + .layout-navbars-breadcrumb-iconfont { + font-size: 14px; + margin-right: 5px; + } + ::v-deep(.el-breadcrumb__separator) { + opacity: 0.7; + color: var(--next-bg-topBarColor); + } + ::v-deep(.el-breadcrumb__inner a, .el-breadcrumb__inner.is-link) { + font-weight: unset !important; + color: var(--next-bg-topBarColor); + &:hover { + color: var(--el-color-primary) !important; + } + } +} +</style> diff --git a/src/layout/navBars/breadcrumb/closeFull.vue b/src/layout/navBars/breadcrumb/closeFull.vue new file mode 100644 index 0000000..a0f0525 --- /dev/null +++ b/src/layout/navBars/breadcrumb/closeFull.vue @@ -0,0 +1,61 @@ +<template> + <div class="layout-navbars-close-full" v-if="isTagsViewCurrenFull"> + <div class="layout-navbars-close-full-icon"> + <SvgIcon name="ele-Close" :title="$t('message.tagsView.closeFullscreen')" @click="onCloseFullscreen" /> + </div> + </div> +</template> + +<script lang="ts"> +import { defineComponent } from 'vue'; +import { storeToRefs } from 'pinia'; +import { useTagsViewRoutes } from '/@/stores/tagsViewRoutes'; + +export default defineComponent({ + name: 'layoutCloseFull', + setup() { + const stores = useTagsViewRoutes(); + const { isTagsViewCurrenFull } = storeToRefs(stores); + // 关闭当前全屏 + const onCloseFullscreen = () => { + stores.setCurrenFullscreen(false); + }; + return { + isTagsViewCurrenFull, + onCloseFullscreen, + }; + }, +}); +</script> + +<style scoped lang="scss"> +.layout-navbars-close-full { + position: fixed; + z-index: 9999999999; + right: -30px; + top: -30px; + .layout-navbars-close-full-icon { + width: 60px; + height: 60px; + border-radius: 100%; + cursor: pointer; + background: rgba(0, 0, 0, 0.1); + transition: all 0.3s ease; + position: relative; + ::v-deep(i) { + position: absolute; + left: 10px; + top: 35px; + color: #333333; + transition: all 0.3s ease; + } + } + &:hover { + transition: all 0.3s ease; + ::v-deep(i) { + color: var(--el-color-primary); + transition: all 0.3s ease; + } + } +} +</style> diff --git a/src/layout/navBars/breadcrumb/index.vue b/src/layout/navBars/breadcrumb/index.vue new file mode 100644 index 0000000..9ebcb7a --- /dev/null +++ b/src/layout/navBars/breadcrumb/index.vue @@ -0,0 +1,119 @@ +<template> + <div class="layout-navbars-breadcrumb-index"> + <Logo v-if="setIsShowLogo" /> + <Breadcrumb /> + <Horizontal :menuList="menuList" v-if="isLayoutTransverse" /> + <User /> + </div> +</template> + +<script lang="ts"> +import { computed, reactive, toRefs, onMounted, onUnmounted, getCurrentInstance, defineComponent } from 'vue'; +import { useRoute } from 'vue-router'; +import { storeToRefs } from 'pinia'; +import { useRoutesList } from '/@/stores/routesList'; +import { useThemeConfig } from '/@/stores/themeConfig'; +import Breadcrumb from '/@/layout/navBars/breadcrumb/breadcrumb.vue'; +import User from '/@/layout/navBars/breadcrumb/user.vue'; +import Logo from '/@/layout/logo/index.vue'; +import Horizontal from '/@/layout/navMenu/horizontal.vue'; + +// 定义接口来定义对象的类型 +interface IndexState { + menuList: object[]; +} + +export default defineComponent({ + name: 'layoutBreadcrumbIndex', + components: { Breadcrumb, User, Logo, Horizontal }, + setup() { + const { proxy } = <any>getCurrentInstance(); + const stores = useRoutesList(); + const storesThemeConfig = useThemeConfig(); + const { themeConfig } = storeToRefs(storesThemeConfig); + const { routesList } = storeToRefs(stores); + const route = useRoute(); + const state = reactive<IndexState>({ + menuList: [], + }); + // 设置 logo 显示/隐藏 + const setIsShowLogo = computed(() => { + let { isShowLogo, layout } = themeConfig.value; + return (isShowLogo && layout === 'classic') || (isShowLogo && layout === 'transverse'); + }); + // 设置是否显示横向导航菜单 + const isLayoutTransverse = computed(() => { + let { layout, isClassicSplitMenu } = themeConfig.value; + return layout === 'transverse' || (isClassicSplitMenu && layout === 'classic'); + }); + // 设置/过滤路由(非静态路由/是否显示在菜单中) + const setFilterRoutes = () => { + let { layout, isClassicSplitMenu } = themeConfig.value; + if (layout === 'classic' && isClassicSplitMenu) { + state.menuList = delClassicChildren(filterRoutesFun(routesList.value)); + const resData = setSendClassicChildren(route.path); + proxy.mittBus.emit('setSendClassicChildren', resData); + } else { + state.menuList = filterRoutesFun(routesList.value); + } + }; + // 设置了分割菜单时,删除底下 children + const delClassicChildren = (arr: Array<object>) => { + arr.map((v: any) => { + if (v.children) delete v.children; + }); + return arr; + }; + // 路由过滤递归函数 + const filterRoutesFun = (arr: Array<string>) => { + return arr + .filter((item: any) => !item.meta.isHide) + .map((item: any) => { + item = Object.assign({}, item); + if (item.children) item.children = filterRoutesFun(item.children); + return item; + }); + }; + // 传送当前子级数据到菜单中 + const setSendClassicChildren = (path: string) => { + const currentPathSplit = path.split('/'); + let currentData: any = {}; + filterRoutesFun(routesList.value).map((v, k) => { + if (v.path === `/${currentPathSplit[1]}`) { + v['k'] = k; + currentData['item'] = [{ ...v }]; + currentData['children'] = [{ ...v }]; + if (v.children) currentData['children'] = v.children; + } + }); + return currentData; + }; + // 页面加载时 + onMounted(() => { + setFilterRoutes(); + proxy.mittBus.on('getBreadcrumbIndexSetFilterRoutes', () => { + setFilterRoutes(); + }); + }); + // 页面卸载时 + onUnmounted(() => { + proxy.mittBus.off('getBreadcrumbIndexSetFilterRoutes', () => {}); + }); + return { + setIsShowLogo, + isLayoutTransverse, + ...toRefs(state), + }; + }, +}); +</script> + +<style scoped lang="scss"> +.layout-navbars-breadcrumb-index { + height: 80px; + display: flex; + align-items: center; + background: var(--next-bg-topBar); + border-bottom: 1px solid var(--next-border-color-light); +} +</style> diff --git a/src/layout/navBars/breadcrumb/search.vue b/src/layout/navBars/breadcrumb/search.vue new file mode 100644 index 0000000..431043c --- /dev/null +++ b/src/layout/navBars/breadcrumb/search.vue @@ -0,0 +1,138 @@ +<template> + <div class="layout-search-dialog"> + <el-dialog v-model="isShowSearch" width="300px" destroy-on-close :modal="false" fullscreen :show-close="false"> + <el-autocomplete + v-model="menuQuery" + :fetch-suggestions="menuSearch" + :placeholder="$t('message.user.searchPlaceholder')" + ref="layoutMenuAutocompleteRef" + @select="onHandleSelect" + @blur="onSearchBlur" + > + <template #prefix> + <el-icon class="el-input__icon"> + <ele-Search /> + </el-icon> + </template> + <template #default="{ item }"> + <div> + <SvgIcon :name="item.meta.icon" class="mr5" /> + {{ $t(item.meta.title) }} + </div> + </template> + </el-autocomplete> + </el-dialog> + </div> +</template> + +<script lang="ts"> +import { reactive, toRefs, defineComponent, ref, nextTick } from 'vue'; +import { useRouter } from 'vue-router'; +import { useI18n } from 'vue-i18n'; +import { storeToRefs } from 'pinia'; +import { useTagsViewRoutes } from '/@/stores/tagsViewRoutes'; + +// 定义接口来定义对象的类型 +interface SearchState { + isShowSearch: boolean; + menuQuery: string; + tagsViewList: object[]; +} +interface Restaurant { + path: string; + meta: { + title: string; + }; +} + +export default defineComponent({ + name: 'layoutBreadcrumbSearch', + setup() { + const storesTagsViewRoutes = useTagsViewRoutes(); + const { tagsViewRoutes } = storeToRefs(storesTagsViewRoutes); + const layoutMenuAutocompleteRef = ref(); + const { t } = useI18n(); + const router = useRouter(); + const state = reactive<SearchState>({ + isShowSearch: false, + menuQuery: '', + tagsViewList: [], + }); + // 搜索弹窗打开 + const openSearch = () => { + state.menuQuery = ''; + state.isShowSearch = true; + initTageView(); + nextTick(() => { + setTimeout(() => { + layoutMenuAutocompleteRef.value.focus(); + }); + }); + }; + // 搜索弹窗关闭 + const closeSearch = () => { + state.isShowSearch = false; + }; + // 菜单搜索数据过滤 + const menuSearch = (queryString: string, cb: Function) => { + let results = queryString ? state.tagsViewList.filter(createFilter(queryString)) : state.tagsViewList; + cb(results); + }; + // 菜单搜索过滤 + const createFilter: any = (queryString: string) => { + return (restaurant: Restaurant) => { + return ( + restaurant.path.toLowerCase().indexOf(queryString.toLowerCase()) > -1 || + restaurant.meta.title.toLowerCase().indexOf(queryString.toLowerCase()) > -1 || + t(restaurant.meta.title).indexOf(queryString.toLowerCase()) > -1 + ); + }; + }; + // 初始化菜单数据 + const initTageView = () => { + if (state.tagsViewList.length > 0) return false; + tagsViewRoutes.value.map((v: any) => { + if (!v.meta.isHide) state.tagsViewList.push({ ...v }); + }); + }; + // 当前菜单选中时 + const onHandleSelect = (item: any) => { + let { path, redirect } = item; + if (item.meta.isLink && !item.meta.isIframe) window.open(item.meta.isLink); + else if (redirect) router.push(redirect); + else router.push(path); + closeSearch(); + }; + // input 失去焦点时 + const onSearchBlur = () => { + closeSearch(); + }; + return { + layoutMenuAutocompleteRef, + openSearch, + closeSearch, + menuSearch, + onHandleSelect, + onSearchBlur, + ...toRefs(state), + }; + }, +}); +</script> + +<style scoped lang="scss"> +.layout-search-dialog { + ::v-deep(.el-dialog) { + box-shadow: unset !important; + border-radius: 0 !important; + background: rgba(0, 0, 0, 0.5); + } + ::v-deep(.el-autocomplete) { + width: 560px; + position: absolute; + top: 100px; + left: 50%; + transform: translateX(-50%); + } +} +</style> diff --git a/src/layout/navBars/breadcrumb/setings.vue b/src/layout/navBars/breadcrumb/setings.vue new file mode 100644 index 0000000..856f260 --- /dev/null +++ b/src/layout/navBars/breadcrumb/setings.vue @@ -0,0 +1,816 @@ +<template> + <div class="layout-breadcrumb-seting"> + <el-drawer + :title="$t('message.layout.configTitle')" + v-model="getThemeConfig.isDrawer" + direction="rtl" + destroy-on-close + size="260px" + @close="onDrawerClose" + > + <el-scrollbar class="layout-breadcrumb-seting-bar"> + <!-- 全局主题 --> + <el-divider content-position="left">{{ $t('message.layout.oneTitle') }}</el-divider> + <div class="layout-breadcrumb-seting-bar-flex"> + <div class="layout-breadcrumb-seting-bar-flex-label">primary</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-color-picker v-model="getThemeConfig.primary" size="default" @change="onColorPickerChange"> </el-color-picker> + </div> + </div> + <div class="layout-breadcrumb-seting-bar-flex mt15"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsDark') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-switch v-model="getThemeConfig.isIsDark" size="small" @change="onAddDarkChange"></el-switch> + </div> + </div> + + <!-- 顶栏设置 --> + <el-divider content-position="left">{{ $t('message.layout.twoTopTitle') }}</el-divider> + <div class="layout-breadcrumb-seting-bar-flex"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.twoTopBar') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-color-picker v-model="getThemeConfig.topBar" size="default" @change="onBgColorPickerChange('topBar')"> </el-color-picker> + </div> + </div> + <div class="layout-breadcrumb-seting-bar-flex"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.twoTopBarColor') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-color-picker v-model="getThemeConfig.topBarColor" size="default" @change="onBgColorPickerChange('topBarColor')"> </el-color-picker> + </div> + </div> + <div class="layout-breadcrumb-seting-bar-flex mt10"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.twoIsTopBarColorGradual') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-switch v-model="getThemeConfig.isTopBarColorGradual" size="small" @change="onTopBarGradualChange"></el-switch> + </div> + </div> + + <!-- 菜单设置 --> + <el-divider content-position="left">{{ $t('message.layout.twoMenuTitle') }}</el-divider> + <div class="layout-breadcrumb-seting-bar-flex"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.twoMenuBar') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-color-picker v-model="getThemeConfig.menuBar" size="default" @change="onBgColorPickerChange('menuBar')"> </el-color-picker> + </div> + </div> + <div class="layout-breadcrumb-seting-bar-flex"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.twoMenuBarColor') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-color-picker v-model="getThemeConfig.menuBarColor" size="default" @change="onBgColorPickerChange('menuBarColor')"> </el-color-picker> + </div> + </div> + <div class="layout-breadcrumb-seting-bar-flex mt14"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.twoIsMenuBarColorGradual') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-switch v-model="getThemeConfig.isMenuBarColorGradual" size="small" @change="onMenuBarGradualChange"></el-switch> + </div> + </div> + + <!-- 分栏设置 --> + <el-divider content-position="left" :style="{ opacity: getThemeConfig.layout !== 'columns' ? 0.5 : 1 }">{{ + $t('message.layout.twoColumnsTitle') + }}</el-divider> + <div class="layout-breadcrumb-seting-bar-flex" :style="{ opacity: getThemeConfig.layout !== 'columns' ? 0.5 : 1 }"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.twoColumnsMenuBar') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-color-picker + v-model="getThemeConfig.columnsMenuBar" + size="default" + @change="onBgColorPickerChange('columnsMenuBar')" + :disabled="getThemeConfig.layout !== 'columns'" + > + </el-color-picker> + </div> + </div> + <div class="layout-breadcrumb-seting-bar-flex" :style="{ opacity: getThemeConfig.layout !== 'columns' ? 0.5 : 1 }"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.twoColumnsMenuBarColor') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-color-picker + v-model="getThemeConfig.columnsMenuBarColor" + size="default" + @change="onBgColorPickerChange('columnsMenuBarColor')" + :disabled="getThemeConfig.layout !== 'columns'" + > + </el-color-picker> + </div> + </div> + <div class="layout-breadcrumb-seting-bar-flex mt14" :style="{ opacity: getThemeConfig.layout !== 'columns' ? 0.5 : 1 }"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.twoIsColumnsMenuBarColorGradual') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-switch + v-model="getThemeConfig.isColumnsMenuBarColorGradual" + size="small" + @change="onColumnsMenuBarGradualChange" + :disabled="getThemeConfig.layout !== 'columns'" + ></el-switch> + </div> + </div> + + <!-- 界面设置 --> + <el-divider content-position="left">{{ $t('message.layout.threeTitle') }}</el-divider> + <div class="layout-breadcrumb-seting-bar-flex" :style="{ opacity: getThemeConfig.layout === 'transverse' ? 0.5 : 1 }"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.threeIsCollapse') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-switch + v-model="getThemeConfig.isCollapse" + :disabled="getThemeConfig.layout === 'transverse'" + size="small" + @change="onThemeConfigChange" + ></el-switch> + </div> + </div> + <div class="layout-breadcrumb-seting-bar-flex mt15" :style="{ opacity: getThemeConfig.layout === 'transverse' ? 0.5 : 1 }"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.threeIsUniqueOpened') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-switch + v-model="getThemeConfig.isUniqueOpened" + :disabled="getThemeConfig.layout === 'transverse'" + size="small" + @change="setLocalThemeConfig" + ></el-switch> + </div> + </div> + <div class="layout-breadcrumb-seting-bar-flex mt15"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.threeIsFixedHeader') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-switch v-model="getThemeConfig.isFixedHeader" size="small" @change="onIsFixedHeaderChange"></el-switch> + </div> + </div> + <div class="layout-breadcrumb-seting-bar-flex mt15" :style="{ opacity: getThemeConfig.layout !== 'classic' ? 0.5 : 1 }"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.threeIsClassicSplitMenu') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-switch + v-model="getThemeConfig.isClassicSplitMenu" + :disabled="getThemeConfig.layout !== 'classic'" + size="small" + @change="onClassicSplitMenuChange" + > + </el-switch> + </div> + </div> + <div class="layout-breadcrumb-seting-bar-flex mt15"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.threeIsLockScreen') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-switch v-model="getThemeConfig.isLockScreen" size="small" @change="setLocalThemeConfig"></el-switch> + </div> + </div> + <div class="layout-breadcrumb-seting-bar-flex mt11"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.threeLockScreenTime') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-input-number + v-model="getThemeConfig.lockScreenTime" + controls-position="right" + :min="1" + :max="9999" + @change="setLocalThemeConfig" + size="default" + style="width: 90px" + > + </el-input-number> + </div> + </div> + + <!-- 界面显示 --> + <el-divider content-position="left">{{ $t('message.layout.fourTitle') }}</el-divider> + <div class="layout-breadcrumb-seting-bar-flex mt15"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsShowLogo') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-switch v-model="getThemeConfig.isShowLogo" size="small" @change="onIsShowLogoChange"></el-switch> + </div> + </div> + <div + class="layout-breadcrumb-seting-bar-flex mt15" + :style="{ opacity: getThemeConfig.layout === 'classic' || getThemeConfig.layout === 'transverse' ? 0.5 : 1 }" + > + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsBreadcrumb') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-switch + v-model="getThemeConfig.isBreadcrumb" + :disabled="getThemeConfig.layout === 'classic' || getThemeConfig.layout === 'transverse'" + size="small" + @change="onIsBreadcrumbChange" + ></el-switch> + </div> + </div> + <div class="layout-breadcrumb-seting-bar-flex mt15"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsBreadcrumbIcon') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-switch v-model="getThemeConfig.isBreadcrumbIcon" size="small" @change="setLocalThemeConfig"></el-switch> + </div> + </div> + <div class="layout-breadcrumb-seting-bar-flex mt15"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsTagsview') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-switch v-model="getThemeConfig.isTagsview" size="small" @change="setLocalThemeConfig"></el-switch> + </div> + </div> + <div class="layout-breadcrumb-seting-bar-flex mt15"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsTagsviewIcon') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-switch v-model="getThemeConfig.isTagsviewIcon" size="small" @change="setLocalThemeConfig"></el-switch> + </div> + </div> + <div class="layout-breadcrumb-seting-bar-flex mt15"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsCacheTagsView') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-switch v-model="getThemeConfig.isCacheTagsView" size="small" @change="setLocalThemeConfig"></el-switch> + </div> + </div> + <div class="layout-breadcrumb-seting-bar-flex mt15" :style="{ opacity: isMobile ? 0.5 : 1 }"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsSortableTagsView') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-switch + v-model="getThemeConfig.isSortableTagsView" + :disabled="isMobile ? true : false" + size="small" + @change="onSortableTagsViewChange" + ></el-switch> + </div> + </div> + <div class="layout-breadcrumb-seting-bar-flex mt15"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsShareTagsView') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-switch v-model="getThemeConfig.isShareTagsView" size="small" @change="onShareTagsViewChange"></el-switch> + </div> + </div> + <div class="layout-breadcrumb-seting-bar-flex mt15"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsFooter') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-switch v-model="getThemeConfig.isFooter" size="small" @change="setLocalThemeConfig"></el-switch> + </div> + </div> + <div class="layout-breadcrumb-seting-bar-flex mt15"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsGrayscale') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-switch v-model="getThemeConfig.isGrayscale" size="small" @change="onAddFilterChange('grayscale')"></el-switch> + </div> + </div> + <div class="layout-breadcrumb-seting-bar-flex mt15"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsInvert') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-switch v-model="getThemeConfig.isInvert" size="small" @change="onAddFilterChange('invert')"></el-switch> + </div> + </div> + <div class="layout-breadcrumb-seting-bar-flex mt15"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsWartermark') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-switch v-model="getThemeConfig.isWartermark" size="small" @change="onWartermarkChange"></el-switch> + </div> + </div> + <div class="layout-breadcrumb-seting-bar-flex mt14"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourWartermarkText') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-input v-model="getThemeConfig.wartermarkText" size="default" style="width: 90px" @input="onWartermarkTextInput($event)"></el-input> + </div> + </div> + + <!-- 其它设置 --> + <el-divider content-position="left">{{ $t('message.layout.fiveTitle') }}</el-divider> + <div class="layout-breadcrumb-seting-bar-flex mt15"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fiveTagsStyle') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-select v-model="getThemeConfig.tagsStyle" placeholder="请选择" size="default" style="width: 90px" @change="setLocalThemeConfig"> + <el-option label="风格1" value="tags-style-one"></el-option> + <el-option label="风格4" value="tags-style-four"></el-option> + <el-option label="风格5" value="tags-style-five"></el-option> + </el-select> + </div> + </div> + <div class="layout-breadcrumb-seting-bar-flex mt15"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fiveAnimation') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-select v-model="getThemeConfig.animation" placeholder="请选择" size="default" style="width: 90px" @change="setLocalThemeConfig"> + <el-option label="slide-right" value="slide-right"></el-option> + <el-option label="slide-left" value="slide-left"></el-option> + <el-option label="opacitys" value="opacitys"></el-option> + </el-select> + </div> + </div> + <div class="layout-breadcrumb-seting-bar-flex mt15" :style="{ opacity: getThemeConfig.layout !== 'columns' ? 0.5 : 1 }"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fiveColumnsAsideStyle') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-select + v-model="getThemeConfig.columnsAsideStyle" + placeholder="请选择" + size="default" + style="width: 90px" + :disabled="getThemeConfig.layout !== 'columns' ? true : false" + @change="setLocalThemeConfig" + > + <el-option label="圆角" value="columns-round"></el-option> + <el-option label="卡片" value="columns-card"></el-option> + </el-select> + </div> + </div> + <div class="layout-breadcrumb-seting-bar-flex mt15 mb27" :style="{ opacity: getThemeConfig.layout !== 'columns' ? 0.5 : 1 }"> + <div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fiveColumnsAsideLayout') }}</div> + <div class="layout-breadcrumb-seting-bar-flex-value"> + <el-select + v-model="getThemeConfig.columnsAsideLayout" + placeholder="请选择" + size="default" + style="width: 90px" + :disabled="getThemeConfig.layout !== 'columns' ? true : false" + @change="setLocalThemeConfig" + > + <el-option label="水平" value="columns-horizontal"></el-option> + <el-option label="垂直" value="columns-vertical"></el-option> + </el-select> + </div> + </div> + + <!-- 布局切换 --> + <el-divider content-position="left">{{ $t('message.layout.sixTitle') }}</el-divider> + <div class="layout-drawer-content-flex"> + <!-- defaults 布局 --> + <div class="layout-drawer-content-item" @click="onSetLayout('defaults')"> + <section class="el-container el-circular" :class="{ 'drawer-layout-active': getThemeConfig.layout === 'defaults' }"> + <aside class="el-aside" style="width: 20px"></aside> + <section class="el-container is-vertical"> + <header class="el-header" style="height: 10px"></header> + <main class="el-main"></main> + </section> + </section> + <div class="layout-tips-warp" :class="{ 'layout-tips-warp-active': getThemeConfig.layout === 'defaults' }"> + <div class="layout-tips-box"> + <p class="layout-tips-txt">{{ $t('message.layout.sixDefaults') }}</p> + </div> + </div> + </div> + <!-- classic 布局 --> + <div class="layout-drawer-content-item" @click="onSetLayout('classic')"> + <section class="el-container is-vertical el-circular" :class="{ 'drawer-layout-active': getThemeConfig.layout === 'classic' }"> + <header class="el-header" style="height: 10px"></header> + <section class="el-container"> + <aside class="el-aside" style="width: 20px"></aside> + <section class="el-container is-vertical"> + <main class="el-main"></main> + </section> + </section> + </section> + <div class="layout-tips-warp" :class="{ 'layout-tips-warp-active': getThemeConfig.layout === 'classic' }"> + <div class="layout-tips-box"> + <p class="layout-tips-txt">{{ $t('message.layout.sixClassic') }}</p> + </div> + </div> + </div> + <!-- transverse 布局 --> + <div class="layout-drawer-content-item" @click="onSetLayout('transverse')"> + <section class="el-container is-vertical el-circular" :class="{ 'drawer-layout-active': getThemeConfig.layout === 'transverse' }"> + <header class="el-header" style="height: 10px"></header> + <section class="el-container"> + <section class="el-container is-vertical"> + <main class="el-main"></main> + </section> + </section> + </section> + <div class="layout-tips-warp" :class="{ 'layout-tips-warp-active': getThemeConfig.layout === 'transverse' }"> + <div class="layout-tips-box"> + <p class="layout-tips-txt">{{ $t('message.layout.sixTransverse') }}</p> + </div> + </div> + </div> + <!-- columns 布局 --> + <div class="layout-drawer-content-item" @click="onSetLayout('columns')"> + <section class="el-container el-circular" :class="{ 'drawer-layout-active': getThemeConfig.layout === 'columns' }"> + <aside class="el-aside-dark" style="width: 10px"></aside> + <aside class="el-aside" style="width: 20px"></aside> + <section class="el-container is-vertical"> + <header class="el-header" style="height: 10px"></header> + <main class="el-main"></main> + </section> + </section> + <div class="layout-tips-warp" :class="{ 'layout-tips-warp-active': getThemeConfig.layout === 'columns' }"> + <div class="layout-tips-box"> + <p class="layout-tips-txt">{{ $t('message.layout.sixColumns') }}</p> + </div> + </div> + </div> + </div> + <div class="copy-config"> + <el-alert :title="$t('message.layout.tipText')" type="warning" :closable="false"> </el-alert> + <el-button size="default" class="copy-config-btn" type="primary" ref="copyConfigBtnRef" @click="onCopyConfigClick"> + <el-icon class="mr5"> + <ele-CopyDocument /> + </el-icon> + {{ $t('message.layout.copyText') }} + </el-button> + <el-button size="default" class="copy-config-btn-reset" type="info" @click="onResetConfigClick"> + <el-icon class="mr5"> + <ele-RefreshRight /> + </el-icon> + {{ $t('message.layout.resetText') }} + </el-button> + </div> + </el-scrollbar> + </el-drawer> + </div> +</template> + +<script lang="ts"> +import { nextTick, onUnmounted, onMounted, getCurrentInstance, defineComponent, computed, reactive, toRefs } from 'vue'; +import { ElMessage } from 'element-plus'; +import { storeToRefs } from 'pinia'; +import { useThemeConfig } from '/@/stores/themeConfig'; +import { getLightColor, getDarkColor } from '/@/utils/theme'; +import { verifyAndSpace } from '/@/utils/toolsValidate'; +import { Local } from '/@/utils/storage'; +import Watermark from '/@/utils/wartermark'; +import commonFunction from '/@/utils/commonFunction'; +import other from '/@/utils/other'; + +export default defineComponent({ + name: 'layoutBreadcrumbSeting', + setup() { + const { proxy } = <any>getCurrentInstance(); + const storesThemeConfig = useThemeConfig(); + const { themeConfig } = storeToRefs(storesThemeConfig); + const { copyText } = commonFunction(); + const state = reactive({ + isMobile: false, + }); + // 获取布局配置信息 + const getThemeConfig = computed(() => { + return themeConfig.value; + }); + // 1、全局主题 + const onColorPickerChange = () => { + if (!getThemeConfig.value.primary) return ElMessage.warning('全局主题 primary 颜色值不能为空'); + // 颜色加深 + document.documentElement.style.setProperty('--el-color-primary-dark-2', `${getDarkColor(getThemeConfig.value.primary, 0.1)}`); + document.documentElement.style.setProperty('--el-color-primary', getThemeConfig.value.primary); + // 颜色变浅 + for (let i = 1; i <= 9; i++) { + document.documentElement.style.setProperty(`--el-color-primary-light-${i}`, `${getLightColor(getThemeConfig.value.primary, i / 10)}`); + } + setDispatchThemeConfig(); + }; + // 2、菜单 / 顶栏 + const onBgColorPickerChange = (bg: string) => { + document.documentElement.style.setProperty(`--next-bg-${bg}`, (<any>getThemeConfig.value)[bg]); + if (bg === 'menuBar') { + document.documentElement.style.setProperty(`--next-bg-menuBar-light-1`, <any>getLightColor(getThemeConfig.value.menuBar, 0.05)); + } + onTopBarGradualChange(); + onMenuBarGradualChange(); + onColumnsMenuBarGradualChange(); + setDispatchThemeConfig(); + }; + // 2、菜单 / 顶栏 --> 顶栏背景渐变 + const onTopBarGradualChange = () => { + setGraduaFun('.layout-navbars-breadcrumb-index', getThemeConfig.value.isTopBarColorGradual, getThemeConfig.value.topBar); + }; + // 2、菜单 / 顶栏 --> 菜单背景渐变 + const onMenuBarGradualChange = () => { + setGraduaFun('.layout-container .el-aside', getThemeConfig.value.isMenuBarColorGradual, getThemeConfig.value.menuBar); + }; + // 2、菜单 / 顶栏 --> 分栏菜单背景渐变 + const onColumnsMenuBarGradualChange = () => { + setGraduaFun('.layout-container .layout-columns-aside', getThemeConfig.value.isColumnsMenuBarColorGradual, getThemeConfig.value.columnsMenuBar); + }; + // 2、菜单 / 顶栏 --> 背景渐变函数 + const setGraduaFun = (el: string, bool: boolean, color: string) => { + setTimeout(() => { + let els = document.querySelector(el); + if (!els) return false; + document.documentElement.style.setProperty('--el-menu-bg-color', document.documentElement.style.getPropertyValue('--next-bg-menuBar')); + if (bool) els.setAttribute('style', `background:linear-gradient(to bottom left , ${color}, ${getLightColor(color, 0.6)}) !important;`); + else els.setAttribute('style', ``); + setLocalThemeConfig(); + }, 200); + }; + // 3、界面设置 --> 菜单水平折叠 + const onThemeConfigChange = () => { + setDispatchThemeConfig(); + }; + // 3、界面设置 --> 固定 Header + const onIsFixedHeaderChange = () => { + getThemeConfig.value.isFixedHeaderChange = getThemeConfig.value.isFixedHeader ? false : true; + setLocalThemeConfig(); + }; + // 3、界面设置 --> 经典布局分割菜单 + const onClassicSplitMenuChange = () => { + getThemeConfig.value.isBreadcrumb = false; + setLocalThemeConfig(); + proxy.mittBus.emit('getBreadcrumbIndexSetFilterRoutes'); + }; + // 4、界面显示 --> 侧边栏 Logo + const onIsShowLogoChange = () => { + getThemeConfig.value.isShowLogoChange = getThemeConfig.value.isShowLogo ? false : true; + setLocalThemeConfig(); + }; + // 4、界面显示 --> 面包屑 Breadcrumb + const onIsBreadcrumbChange = () => { + if (getThemeConfig.value.layout === 'classic') { + getThemeConfig.value.isClassicSplitMenu = false; + } + setLocalThemeConfig(); + }; + // 4、界面显示 --> 开启 TagsView 拖拽 + const onSortableTagsViewChange = () => { + proxy.mittBus.emit('openOrCloseSortable'); + setLocalThemeConfig(); + }; + // 4、界面显示 --> 开启 TagsView 共用 + const onShareTagsViewChange = () => { + proxy.mittBus.emit('openShareTagsView'); + setLocalThemeConfig(); + }; + // 4、界面显示 --> 灰色模式/色弱模式 + const onAddFilterChange = (attr: string) => { + if (attr === 'grayscale') { + if (getThemeConfig.value.isGrayscale) getThemeConfig.value.isInvert = false; + } else { + if (getThemeConfig.value.isInvert) getThemeConfig.value.isGrayscale = false; + } + const cssAttr = + attr === 'grayscale' ? `grayscale(${getThemeConfig.value.isGrayscale ? 1 : 0})` : `invert(${getThemeConfig.value.isInvert ? '80%' : '0%'})`; + const appEle: any = document.body; + appEle.setAttribute('style', `filter: ${cssAttr}`); + setLocalThemeConfig(); + }; + // 4、界面显示 --> 深色模式 + const onAddDarkChange = () => { + const body = document.documentElement as HTMLElement; + if (getThemeConfig.value.isIsDark) body.setAttribute('data-theme', 'dark'); + else body.setAttribute('data-theme', ''); + }; + // 4、界面显示 --> 开启水印 + const onWartermarkChange = () => { + getThemeConfig.value.isWartermark ? Watermark.set(getThemeConfig.value.wartermarkText) : Watermark.del(); + setLocalThemeConfig(); + }; + // 4、界面显示 --> 水印文案 + const onWartermarkTextInput = (val: any) => { + getThemeConfig.value.wartermarkText = verifyAndSpace(val); + if (getThemeConfig.value.wartermarkText === '') return false; + if (getThemeConfig.value.isWartermark) Watermark.set(getThemeConfig.value.wartermarkText); + setLocalThemeConfig(); + }; + // 5、布局切换 + const onSetLayout = (layout: string) => { + Local.set('oldLayout', layout); + if (getThemeConfig.value.layout === layout) return false; + if (layout === 'transverse') getThemeConfig.value.isCollapse = false; + getThemeConfig.value.layout = layout; + getThemeConfig.value.isDrawer = false; + initLayoutChangeFun(); + }; + // 设置布局切换函数 + const initLayoutChangeFun = () => { + onBgColorPickerChange('menuBar'); + onBgColorPickerChange('menuBarColor'); + onBgColorPickerChange('topBar'); + onBgColorPickerChange('topBarColor'); + onBgColorPickerChange('columnsMenuBar'); + onBgColorPickerChange('columnsMenuBarColor'); + }; + // 关闭弹窗时,初始化变量。变量用于处理 proxy.$refs.layoutScrollbarRef.update() + const onDrawerClose = () => { + getThemeConfig.value.isFixedHeaderChange = false; + getThemeConfig.value.isShowLogoChange = false; + getThemeConfig.value.isDrawer = false; + setLocalThemeConfig(); + }; + // 布局配置弹窗打开 + const openDrawer = () => { + getThemeConfig.value.isDrawer = true; + }; + // 触发 store 布局配置更新 + const setDispatchThemeConfig = () => { + setLocalThemeConfig(); + setLocalThemeConfigStyle(); + }; + // 存储布局配置 + const setLocalThemeConfig = () => { + Local.remove('themeConfig'); + Local.set('themeConfig', getThemeConfig.value); + }; + // 存储布局配置全局主题样式(html根标签) + const setLocalThemeConfigStyle = () => { + Local.set('themeConfigStyle', document.documentElement.style.cssText); + }; + // 一键复制配置 + const onCopyConfigClick = () => { + let copyThemeConfig = Local.get('themeConfig'); + copyThemeConfig.isDrawer = false; + copyText(JSON.stringify(copyThemeConfig)).then(() => { + getThemeConfig.value.isDrawer = false; + }); + }; + // 一键恢复默认 + const onResetConfigClick = () => { + Local.clear(); + window.location.reload(); + }; + // 初始化菜单样式等 + const initSetStyle = () => { + // 2、菜单 / 顶栏 --> 顶栏背景渐变 + onTopBarGradualChange(); + // 2、菜单 / 顶栏 --> 菜单背景渐变 + onMenuBarGradualChange(); + // 2、菜单 / 顶栏 --> 分栏菜单背景渐变 + onColumnsMenuBarGradualChange(); + }; + onMounted(() => { + nextTick(() => { + // 判断当前布局是否不相同,不相同则初始化当前布局的样式,防止监听窗口大小改变时,布局配置logo、菜单背景等部分布局失效问题 + if (!Local.get('frequency')) initLayoutChangeFun(); + Local.set('frequency', 1); + // 监听窗口大小改变,非默认布局,设置成默认布局(适配移动端) + proxy.mittBus.on('layoutMobileResize', (res: any) => { + getThemeConfig.value.layout = res.layout; + getThemeConfig.value.isDrawer = false; + initLayoutChangeFun(); + state.isMobile = other.isMobile(); + }); + setTimeout(() => { + // 默认样式 + onColorPickerChange(); + // 灰色模式 + if (getThemeConfig.value.isGrayscale) onAddFilterChange('grayscale'); + // 色弱模式 + if (getThemeConfig.value.isInvert) onAddFilterChange('invert'); + // 深色模式 + if (getThemeConfig.value.isIsDark) onAddDarkChange(); + // 开启水印 + onWartermarkChange(); + // 语言国际化 + if (Local.get('themeConfig')) proxy.$i18n.locale = Local.get('themeConfig').globalI18n; + // 初始化菜单样式等 + initSetStyle(); + }, 100); + }); + }); + onUnmounted(() => { + proxy.mittBus.off('layoutMobileResize', () => {}); + }); + return { + openDrawer, + onColorPickerChange, + onBgColorPickerChange, + onTopBarGradualChange, + onMenuBarGradualChange, + onColumnsMenuBarGradualChange, + onThemeConfigChange, + onIsFixedHeaderChange, + onIsShowLogoChange, + getThemeConfig, + onDrawerClose, + onAddFilterChange, + onAddDarkChange, + onWartermarkChange, + onWartermarkTextInput, + onSetLayout, + setLocalThemeConfig, + onClassicSplitMenuChange, + onIsBreadcrumbChange, + onSortableTagsViewChange, + onShareTagsViewChange, + onCopyConfigClick, + onResetConfigClick, + ...toRefs(state), + }; + }, +}); +</script> + +<style scoped lang="scss"> +.layout-breadcrumb-seting-bar { + height: calc(100vh - 50px); + padding: 0 15px; + ::v-deep(.el-scrollbar__view) { + overflow-x: hidden !important; + } + .layout-breadcrumb-seting-bar-flex { + display: flex; + align-items: center; + margin-bottom: 5px; + &-label { + flex: 1; + color: var(--el-text-color-primary); + } + } + .layout-drawer-content-flex { + overflow: hidden; + display: flex; + flex-wrap: wrap; + align-content: flex-start; + margin: 0 -5px; + .layout-drawer-content-item { + width: 50%; + height: 70px; + cursor: pointer; + border: 1px solid transparent; + position: relative; + padding: 5px; + .el-container { + height: 100%; + .el-aside-dark { + background-color: var(--next-color-seting-header); + } + .el-aside { + background-color: var(--next-color-seting-aside); + } + .el-header { + background-color: var(--next-color-seting-header); + } + .el-main { + background-color: var(--next-color-seting-main); + } + } + .el-circular { + border-radius: 2px; + overflow: hidden; + border: 1px solid transparent; + transition: all 0.3s ease-in-out; + } + .drawer-layout-active { + border: 1px solid; + border-color: var(--el-color-primary); + } + .layout-tips-warp, + .layout-tips-warp-active { + transition: all 0.3s ease-in-out; + position: absolute; + left: 50%; + top: 50%; + transform: translate(-50%, -50%); + border: 1px solid; + border-color: var(--el-color-primary-light-5); + border-radius: 100%; + padding: 4px; + .layout-tips-box { + transition: inherit; + width: 30px; + height: 30px; + z-index: 9; + border: 1px solid; + border-color: var(--el-color-primary-light-5); + border-radius: 100%; + .layout-tips-txt { + transition: inherit; + position: relative; + top: 5px; + font-size: 12px; + line-height: 1; + letter-spacing: 2px; + white-space: nowrap; + color: var(--el-color-primary-light-5); + text-align: center; + transform: rotate(30deg); + left: -1px; + background-color: var(--next-color-seting-main); + width: 32px; + height: 17px; + line-height: 17px; + } + } + } + .layout-tips-warp-active { + border: 1px solid; + border-color: var(--el-color-primary); + .layout-tips-box { + border: 1px solid; + border-color: var(--el-color-primary); + .layout-tips-txt { + color: var(--el-color-primary) !important; + background-color: var(--next-color-seting-main) !important; + } + } + } + &:hover { + .el-circular { + transition: all 0.3s ease-in-out; + border: 1px solid; + border-color: var(--el-color-primary); + } + .layout-tips-warp { + transition: all 0.3s ease-in-out; + border-color: var(--el-color-primary); + .layout-tips-box { + transition: inherit; + border-color: var(--el-color-primary); + .layout-tips-txt { + transition: inherit; + color: var(--el-color-primary) !important; + background-color: var(--next-color-seting-main) !important; + } + } + } + } + } + } + .copy-config { + margin: 10px 0; + .copy-config-btn { + width: 100%; + margin-top: 15px; + } + .copy-config-btn-reset { + width: 100%; + margin: 10px 0 0; + } + } +} +</style> diff --git a/src/layout/navBars/breadcrumb/user.vue b/src/layout/navBars/breadcrumb/user.vue new file mode 100644 index 0000000..b838098 --- /dev/null +++ b/src/layout/navBars/breadcrumb/user.vue @@ -0,0 +1,430 @@ +<template> + <div class="layout-navbars-breadcrumb-user pr15" :style="{ flex: layoutUserFlexNum }"> + <div class="logo"> + <img @click="toHome" src="../../../assets/menu/companyLogo.png" /> + <span>{{ systemName }}</span> + </div> + <div style="display: flex; align-items: center; padding-right: 5px"> + <div @click="backToMenu()" class="backBtn">返回首页</div> + <el-dropdown :show-timeout="70" :hide-timeout="50" trigger="click" @command="onComponentSizeChange"> + <div class="layout-navbars-breadcrumb-user-icon"> + <i class="iconfont icon-ziti" :title="$t('message.user.title0')"></i> + </div> + <template #dropdown> + <el-dropdown-menu> + <el-dropdown-item command="large" :disabled="disabledSize === 'large'">{{ $t('message.user.dropdownLarge') }}</el-dropdown-item> + <el-dropdown-item command="default" :disabled="disabledSize === 'default'">{{ $t('message.user.dropdownDefault') }}</el-dropdown-item> + <el-dropdown-item command="small" :disabled="disabledSize === 'small'">{{ $t('message.user.dropdownSmall') }}</el-dropdown-item> + </el-dropdown-menu> + </template> + </el-dropdown> + <!-- <el-dropdown :show-timeout="70" :hide-timeout="50" trigger="click" @command="onLanguageChange">--> + <!-- <div class="layout-navbars-breadcrumb-user-icon">--> + <!-- <i class="iconfont" :class="disabledI18n === 'en' ? 'icon-fuhao-yingwen' : 'icon-fuhao-zhongwen'" :title="$t('message.user.title1')"></i>--> + <!-- </div>--> + <!-- <template #dropdown>--> + <!-- <el-dropdown-menu>--> + <!-- <el-dropdown-item command="zh-cn" :disabled="disabledI18n === 'zh-cn'">简体中文</el-dropdown-item>--> + <!-- <el-dropdown-item command="en" :disabled="disabledI18n === 'en'">English</el-dropdown-item>--> + <!-- <el-dropdown-item command="zh-tw" :disabled="disabledI18n === 'zh-tw'">繁體中文</el-dropdown-item>--> + <!-- </el-dropdown-menu>--> + <!-- </template>--> + <!-- </el-dropdown>--> + <!-- <div class="layout-navbars-breadcrumb-user-icon" @click="onSearchClick">--> + <!-- <el-icon :title="$t('message.user.title2')">--> + <!-- <ele-Search />--> + <!-- </el-icon>--> + <!-- </div>--> + <!-- <div class="layout-navbars-breadcrumb-user-icon" @click="onLayoutSetingClick">--> + <!-- <i class="icon-skin iconfont" :title="$t('message.user.title3')"></i>--> + <!-- </div>--> + <!-- <div class="layout-navbars-breadcrumb-user-icon">--> + <!-- <el-popover placement="bottom" trigger="click" transition="el-zoom-in-top" :width="300" :persistent="false">--> + <!-- <template #reference>--> + <!-- <el-badge :is-dot="true">--> + <!-- <el-icon :title="$t('message.user.title4')">--> + <!-- <ele-Bell />--> + <!-- </el-icon>--> + <!-- </el-badge>--> + <!-- </template>--> + <!-- <template #default>--> + <!-- <UserNews />--> + <!-- </template>--> + <!-- </el-popover>--> + <!-- </div>--> + <div class="layout-navbars-breadcrumb-user-icon mr10" @click="onScreenfullClick"> + <i class="iconfont" :title="isScreenfull ? $t('message.user.title6') : $t('message.user.title5')" :class="!isScreenfull ? 'icon-fullscreen' : 'icon-tuichuquanping'"></i> + </div> + <el-dropdown :show-timeout="70" :hide-timeout="50" @command="onHandleCommandClick"> + <span class="layout-navbars-breadcrumb-user-link"> + <img src="../../../assets/avator.png" class="layout-navbars-breadcrumb-user-link-photo mr5" style="width: 24px;height: 24px"/> + {{ userInfos.userName }} + <el-icon class="el-icon--right"> + <ele-ArrowDown /> + </el-icon> + </span> + <template #dropdown> + <el-dropdown-menu> + <el-dropdown-item command="/newMenu">{{ $t('message.user.dropdown1') }}</el-dropdown-item> + <!-- <el-dropdown-item command="wareHouse">{{ $t('message.user.dropdown6') }}</el-dropdown-item>--> + <!-- <el-dropdown-item command="/personal">{{ $t('message.user.dropdown2') }}</el-dropdown-item>--> + <!-- <el-dropdown-item command="/404">{{ $t('message.user.dropdown3') }}</el-dropdown-item>--> + <!-- <el-dropdown-item command="/401">{{ $t('message.user.dropdown4') }}</el-dropdown-item>--> + <el-dropdown-item divided command="logOut">{{ $t('message.user.dropdown5') }}</el-dropdown-item> + </el-dropdown-menu> + </template> + </el-dropdown> + <Search ref="searchRef" /> + </div> + </div> +</template> + +<script lang="ts"> +import { ref, getCurrentInstance, computed, reactive, toRefs, onMounted, defineComponent } from 'vue'; +import { useRouter } from 'vue-router'; +import { ElMessageBox, ElMessage } from 'element-plus'; +import screenfull from 'screenfull'; +import { useI18n } from 'vue-i18n'; +import { storeToRefs } from 'pinia'; +import { useUserInfo } from '/@/stores/userInfo'; +import { useThemeConfig } from '/@/stores/themeConfig'; +import other from '/@/utils/other'; +import { Session, Local } from '/@/utils/storage'; +import UserNews from '/@/layout/navBars/breadcrumb/userNews.vue'; +import Search from '/@/layout/navBars/breadcrumb/search.vue'; +import { useLoginApi } from '/@/api/login'; +import { useMenuApi } from '/@/api/systemManage/menu/index'; + +const menuApi = useMenuApi(); +import { backEndComponent, getBackEndControlRoutes, initBackEndControlRoutes, setAddRoute, setFilterMenuAndCacheTagsViewRoutes } from '../../../router/backEnd'; +import { NextLoading } from '/@/utils/loading'; +import { useRequestOldRoutes } from '/@/stores/requestOldRoutes'; +import { dynamicRoutes } from '/@/router/route'; +import Cookies from 'js-cookie'; +import {useRoutesList} from "/@/stores/routesList"; + +export default defineComponent({ + name: 'layoutBreadcrumbUser', + components: { UserNews, Search }, + setup() { + const { t } = useI18n(); + const { proxy } = <any>getCurrentInstance(); + const router = useRouter(); + const stores = useUserInfo(); + const routeList = storeToRefs(useRoutesList()) + const storesThemeConfig = useThemeConfig(); + const { userInfos } = storeToRefs(stores); + const { themeConfig } = storeToRefs(storesThemeConfig); + const searchRef = ref(); + const state = reactive({ + isScreenfull: false, + disabledI18n: 'zh-cn', + disabledSize: 'large', + systemName: '' + }); + // 设置分割样式 + const layoutUserFlexNum = computed(() => { + let num: string | number = ''; + const { layout, isClassicSplitMenu } = themeConfig.value; + const layoutArr: string[] = ['defaults', 'columns']; + if (layoutArr.includes(layout) || (layout === 'classic' && !isClassicSplitMenu)) num = '1'; + else num = ''; + return num; + }); + // 全屏点击时 + const onScreenfullClick = () => { + if (!screenfull.isEnabled) { + ElMessage.warning('暂不不支持全屏'); + return false; + } + screenfull.toggle(); + screenfull.on('change', () => { + if (screenfull.isFullscreen) state.isScreenfull = true; + else state.isScreenfull = false; + }); + }; + // 布局配置 icon 点击时 + const onLayoutSetingClick = () => { + proxy.mittBus.emit('openSetingsDrawer'); + }; + // 下拉菜单点击时 + const onHandleCommandClick = (path: string) => { + if (path === 'logOut') { + ElMessageBox({ + closeOnClickModal: false, + closeOnPressEscape: false, + title: t('message.user.logOutTitle'), + message: t('message.user.logOutMessage'), + showCancelButton: true, + confirmButtonText: t('message.user.logOutConfirm'), + cancelButtonText: t('message.user.logOutCancel'), + buttonSize: 'default', + beforeClose: (action, instance, done) => { + if (action === 'confirm') { + instance.confirmButtonLoading = true; + instance.confirmButtonText = t('message.user.logOutExit'); + setTimeout(() => { + done(); + setTimeout(() => { + instance.confirmButtonLoading = false; + }, 300); + }, 700); + } else { + done(); + } + } + }) + .then(async () => { + let res = await useLoginApi().signOut(); + if (res.data.code === '200') { + Session.clear(); // 清除缓存/token等 + // 使用 reload 时,不需要调用 resetRoute() 重置路由 + window.location.reload(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }) + .catch(() => {}); + } else if (path === 'wareHouse') { + window.open('https://gitee.com/lyt-top/vue-next-admin'); + } else { + router.push(path); + } + }; + // 菜单搜索点击 + const onSearchClick = () => { + searchRef.value.openSearch(); + }; + // 组件大小改变 + const onComponentSizeChange = (size: string) => { + Local.remove('themeConfig'); + themeConfig.value.globalComponentSize = size; + Local.set('themeConfig', themeConfig.value); + initComponentSize(); + window.location.reload(); + }; + // 语言切换 + const onLanguageChange = (lang: string) => { + Local.remove('themeConfig'); + themeConfig.value.globalI18n = lang; + Local.set('themeConfig', themeConfig.value); + proxy.$i18n.locale = lang; + initI18n(); + other.useTitle(); + }; + // 设置 element plus 组件的国际化 + const setI18nConfig = (locale: string) => { + proxy.mittBus.emit('getI18nConfig', proxy.$i18n.messages[locale]); + }; + // 初始化言语国际化 + const initI18n = () => { + switch (Local.get('themeConfig').globalI18n) { + case 'zh-cn': + state.disabledI18n = 'zh-cn'; + setI18nConfig('zh-cn'); + break; + case 'en': + state.disabledI18n = 'en'; + setI18nConfig('en'); + break; + case 'zh-tw': + state.disabledI18n = 'zh-tw'; + setI18nConfig('zh-tw'); + break; + } + }; + // 初始化全局组件大小 + const initComponentSize = () => { + switch (Local.get('themeConfig').globalComponentSize) { + case 'large': + state.disabledSize = 'large'; + break; + case 'default': + state.disabledSize = 'default'; + break; + case 'small': + state.disabledSize = 'small'; + break; + } + }; + + const getSysName = async () => { + if (window.nextLoading === undefined) NextLoading.start(); + if (!Cookies.get('token')) return false; + const res = await menuApi.getMenuAdmin(Cookies.get('projectId') === null ? '' : Cookies.get('projectId')); + if (res.data.code === '200') { + state.systemName = res.data.data[1].project.projectName; + console.log(state.systemName); + } else { + console.log('有问题'); + } + }; + const backToMenu = () => { + router.push({ path: 'newMenu' }).then(()=>{ + routeList.routesList.value = [] + console.log(routeList); + }); + }; + const toHome = () => { + router.push({ path: 'newMenu' }); + }; + // 页面加载时 + onMounted(() => { + if (Local.get('themeConfig')) { + initI18n(); + initComponentSize(); + } + getSysName(); + }); + return { + userInfos, + backToMenu, + toHome, + onLayoutSetingClick, + onHandleCommandClick, + onScreenfullClick, + onSearchClick, + onComponentSizeChange, + onLanguageChange, + searchRef, + layoutUserFlexNum, + ...toRefs(state) + }; + } +}); +</script> + +<style scoped lang="scss"> + @media screen and (min-width: 1400px) { + .logo{ + img { + height: 100%; + cursor: pointer; + } + span{ + font-size: 32px; + color: #409eff; + font-weight: bolder; + border-left: 2px solid #409eff; + padding-left: 10px + } + } + .backBtn { + font-size: 16px; + cursor: pointer; + margin-right: 20px; + + &:hover { + color: #409eff; + font-weight: bolder; + } + } + } + @media screen and (min-width: 1200px) and (max-width: 1400px) { + .logo{ + img { + height: 90%; + cursor: pointer; + } + span{ + font-size: 28px; + color: #409eff; + font-weight: bolder; + border-left: 2px solid #409eff; + padding-left: 10px + } + } + .backBtn { + font-size: 14px; + cursor: pointer; + margin-right: 20px; + + &:hover { + color: #409eff; + font-weight: bolder; + } + } + } + @media screen and (max-width: 1024px) { + .logo{ + img { + width: 60%; + height: auto; + cursor: pointer; + } + span{ + font-size: 22px; + color: #409eff; + font-weight: bolder; + border-left: 2px solid #409eff; + padding-left: 10px + } + } + .backBtn { + font-size: 12px; + cursor: pointer; + margin-right: 20px; + + &:hover { + color: #409eff; + font-weight: bolder; + } + } + } + .layout-navbars-breadcrumb-user { + display: flex; + align-items: center; + justify-content: space-between; + + .logo { + height: 75%; + padding: 5px 10px; + display: flex; + align-items: center; + overflow: hidden; + box-sizing: border-box; + } + &-link { + height: 100%; + display: flex; + align-items: center; + white-space: nowrap; + &-photo { + width: 25px; + height: 25px; + border-radius: 100%; + } + } + &-icon { + padding: 0 10px; + cursor: pointer; + color: var(--next-bg-topBarColor); + height: 80px; + line-height: 80px; + display: flex; + align-items: center; + &:hover { + background: var(--next-color-user-hover); + i { + display: inline-block; + animation: logoAnimation 0.3s ease-in-out; + } + } + } + ::v-deep(.el-dropdown) { + color: var(--next-bg-topBarColor); + } + ::v-deep(.el-badge) { + height: 40px; + line-height: 40px; + display: flex; + align-items: center; + } + ::v-deep(.el-badge__content.is-fixed) { + top: 12px; + } + } +</style> diff --git a/src/layout/navBars/breadcrumb/userNews.vue b/src/layout/navBars/breadcrumb/userNews.vue new file mode 100644 index 0000000..cae954a --- /dev/null +++ b/src/layout/navBars/breadcrumb/userNews.vue @@ -0,0 +1,115 @@ +<template> + <div class="layout-navbars-breadcrumb-user-news"> + <div class="head-box"> + <div class="head-box-title">{{ $t('message.user.newTitle') }}</div> + <div class="head-box-btn" v-if="newsList.length > 0" @click="onAllReadClick">{{ $t('message.user.newBtn') }}</div> + </div> + <div class="content-box"> + <template v-if="newsList.length > 0"> + <div class="content-box-item" v-for="(v, k) in newsList" :key="k"> + <div>{{ v.label }}</div> + <div class="content-box-msg"> + {{ v.value }} + </div> + <div class="content-box-time">{{ v.time }}</div> + </div> + </template> + <el-empty :description="$t('message.user.newDesc')" v-else></el-empty> + </div> + <div class="foot-box" @click="onGoToGiteeClick" v-if="newsList.length > 0">{{ $t('message.user.newGo') }}</div> + </div> +</template> + +<script lang="ts"> +import { reactive, toRefs, defineComponent } from 'vue'; + +export default defineComponent({ + name: 'layoutBreadcrumbUserNews', + setup() { + const state = reactive({ + newsList: [ + { + label: '关于版本发布的通知', + value: 'vue-next-admin,基于 vue3 + CompositionAPI + typescript + vite + element plus,正式发布时间:2021年02月28日!', + time: '2020-12-08', + }, + { + label: '关于学习交流的通知', + value: 'QQ群号码 665452019,欢迎小伙伴入群学习交流探讨!', + time: '2020-12-08', + }, + ], + }); + // 全部已读点击 + const onAllReadClick = () => { + state.newsList = []; + }; + // 前往通知中心点击 + const onGoToGiteeClick = () => { + window.open('https://gitee.com/lyt-top/vue-next-admin'); + }; + return { + onAllReadClick, + onGoToGiteeClick, + ...toRefs(state), + }; + }, +}); +</script> + +<style scoped lang="scss"> +.layout-navbars-breadcrumb-user-news { + .head-box { + display: flex; + border-bottom: 1px solid var(--el-border-color-lighter); + box-sizing: border-box; + color: var(--el-text-color-primary); + justify-content: space-between; + height: 35px; + align-items: center; + .head-box-btn { + color: var(--el-color-primary); + font-size: 13px; + cursor: pointer; + opacity: 0.8; + &:hover { + opacity: 1; + } + } + } + .content-box { + font-size: 13px; + .content-box-item { + padding-top: 12px; + &:last-of-type { + padding-bottom: 12px; + } + .content-box-msg { + color: var(--el-text-color-secondary); + margin-top: 5px; + margin-bottom: 5px; + } + .content-box-time { + color: var(--el-text-color-secondary); + } + } + } + .foot-box { + height: 35px; + color: var(--el-color-primary); + font-size: 13px; + cursor: pointer; + opacity: 0.8; + display: flex; + align-items: center; + justify-content: center; + border-top: 1px solid var(--el-border-color-lighter); + &:hover { + opacity: 1; + } + } + ::v-deep(.el-empty__description p) { + font-size: 13px; + } +} +</style> diff --git a/src/layout/navBars/index.vue b/src/layout/navBars/index.vue new file mode 100644 index 0000000..f41a0cf --- /dev/null +++ b/src/layout/navBars/index.vue @@ -0,0 +1,40 @@ +<template> + <div class="layout-navbars-container"> + <BreadcrumbIndex /> + <TagsView v-if="setShowTagsView" /> + </div> +</template> + +<script lang="ts"> +import { computed, defineComponent } from 'vue'; +import { storeToRefs } from 'pinia'; +import { useThemeConfig } from '/@/stores/themeConfig'; +import BreadcrumbIndex from '/@/layout/navBars/breadcrumb/index.vue'; +import TagsView from '/@/layout/navBars/tagsView/tagsView.vue'; + +export default defineComponent({ + name: 'layoutNavBars', + components: { BreadcrumbIndex, TagsView }, + setup() { + const storesThemeConfig = useThemeConfig(); + const { themeConfig } = storeToRefs(storesThemeConfig); + // 是否显示 tagsView + const setShowTagsView = computed(() => { + let { layout, isTagsview } = themeConfig.value; + return layout !== 'classic' && isTagsview; + }); + return { + setShowTagsView, + }; + }, +}); +</script> + +<style scoped lang="scss"> +.layout-navbars-container { + display: flex; + flex-direction: column; + width: 100%; + height: 100%; +} +</style> diff --git a/src/layout/navBars/tagsView/contextmenu.vue b/src/layout/navBars/tagsView/contextmenu.vue new file mode 100644 index 0000000..c717aae --- /dev/null +++ b/src/layout/navBars/tagsView/contextmenu.vue @@ -0,0 +1,138 @@ +<template> + <transition name="el-zoom-in-center"> + <div + aria-hidden="true" + class="el-dropdown__popper el-popper is-light is-pure custom-contextmenu" + role="tooltip" + data-popper-placement="bottom" + :style="`top: ${dropdowns.y + 5}px;left: ${dropdowns.x}px;`" + :key="Math.random()" + v-show="isShow" + > + <ul class="el-dropdown-menu"> + <template v-for="(v, k) in dropdownList"> + <li + class="el-dropdown-menu__item" + aria-disabled="false" + tabindex="-1" + :key="k" + v-if="!v.affix" + @click="onCurrentContextmenuClick(v.contextMenuClickId)" + > + <SvgIcon :name="v.icon" /> + <span>{{ $t(v.txt) }}</span> + </li> + </template> + </ul> + <div class="el-popper__arrow" :style="{ left: `${arrowLeft}px` }"></div> + </div> + </transition> +</template> + +<script lang="ts"> +import { computed, defineComponent, reactive, toRefs, onMounted, onUnmounted, watch } from 'vue'; + +export default defineComponent({ + name: 'layoutTagsViewContextmenu', + props: { + dropdown: { + type: Object, + default: () => { + return { + x: 0, + y: 0, + }; + }, + }, + }, + setup(props, { emit }) { + const state = reactive({ + isShow: false, + dropdownList: [ + { contextMenuClickId: 0, txt: 'message.tagsView.refresh', affix: false, icon: 'ele-RefreshRight' }, + { contextMenuClickId: 1, txt: 'message.tagsView.close', affix: false, icon: 'ele-Close' }, + { contextMenuClickId: 2, txt: 'message.tagsView.closeOther', affix: false, icon: 'ele-CircleClose' }, + { contextMenuClickId: 3, txt: 'message.tagsView.closeAll', affix: false, icon: 'ele-FolderDelete' }, + { + contextMenuClickId: 4, + txt: 'message.tagsView.fullscreen', + affix: false, + icon: 'iconfont icon-fullscreen', + }, + ], + item: {}, + arrowLeft: 10, + }); + // 父级传过来的坐标 x,y 值 + const dropdowns = computed(() => { + // 117 为 `Dropdown 下拉菜单` 的宽度 + if (props.dropdown.x + 117 > document.documentElement.clientWidth) { + return { + x: document.documentElement.clientWidth - 117 - 5, + y: props.dropdown.y, + }; + } else { + return props.dropdown; + } + }); + // 当前项菜单点击 + const onCurrentContextmenuClick = (contextMenuClickId: number) => { + emit('currentContextmenuClick', Object.assign({}, { contextMenuClickId }, state.item)); + }; + // 打开右键菜单:判断是否固定,固定则不显示关闭按钮 + const openContextmenu = (item: any) => { + state.item = item; + item.meta.isAffix ? (state.dropdownList[1].affix = true) : (state.dropdownList[1].affix = false); + closeContextmenu(); + setTimeout(() => { + state.isShow = true; + }, 10); + }; + // 关闭右键菜单 + const closeContextmenu = () => { + state.isShow = false; + }; + // 监听页面监听进行右键菜单的关闭 + onMounted(() => { + document.body.addEventListener('click', closeContextmenu); + }); + // 页面卸载时,移除右键菜单监听事件 + onUnmounted(() => { + document.body.removeEventListener('click', closeContextmenu); + }); + // 监听下拉菜单位置 + watch( + () => props.dropdown, + ({ x }) => { + if (x + 117 > document.documentElement.clientWidth) state.arrowLeft = 117 - (document.documentElement.clientWidth - x); + else state.arrowLeft = 10; + }, + { + deep: true, + } + ); + return { + dropdowns, + openContextmenu, + closeContextmenu, + onCurrentContextmenuClick, + ...toRefs(state), + }; + }, +}); +</script> + +<style scoped lang="scss"> +.custom-contextmenu { + transform-origin: center top; + z-index: 2190; + position: fixed; + .el-dropdown-menu__item { + font-size: 12px !important; + white-space: nowrap; + i { + font-size: 12px !important; + } + } +} +</style> diff --git a/src/layout/navBars/tagsView/tagsView.vue b/src/layout/navBars/tagsView/tagsView.vue new file mode 100644 index 0000000..d0558d5 --- /dev/null +++ b/src/layout/navBars/tagsView/tagsView.vue @@ -0,0 +1,734 @@ +<template> + <div class="layout-navbars-tagsview" :class="{ 'layout-navbars-tagsview-shadow': getThemeConfig.layout === 'classic' }"> + <el-scrollbar ref="scrollbarRef" @wheel.prevent="onHandleScroll"> + <ul class="layout-navbars-tagsview-ul" :class="setTagsStyle" ref="tagsUlRef"> + <li + v-for="(v, k) in tagsViewList" + :key="k" + class="layout-navbars-tagsview-ul-li" + :data-url="v.url" + :class="{ 'is-active': isActive(v) }" + @contextmenu.prevent="onContextmenu(v, $event)" + @click="onTagsClick(v, k)" + :ref=" + (el) => { + if (el) tagsRefs[k] = el; + } + " + > + <i class="iconfont icon-webicon318 layout-navbars-tagsview-ul-li-iconfont" v-if="isActive(v)"></i> + <SvgIcon :name="v.meta.icon" v-if="!isActive(v) && getThemeConfig.isTagsviewIcon" class="pr5" /> + <span>{{ setTagsViewNameI18n(v) }}</span> + <template v-if="isActive(v)"> + <SvgIcon + name="ele-RefreshRight" + class="ml5 layout-navbars-tagsview-ul-li-refresh" + @click.stop="refreshCurrentTagsView($route.fullPath)" + /> + <SvgIcon + name="ele-Close" + class="layout-navbars-tagsview-ul-li-icon layout-icon-active" + v-if="!v.meta.isAffix" + @click.stop="closeCurrentTagsView(getThemeConfig.isShareTagsView ? v.path : v.url)" + /> + </template> + <SvgIcon + name="ele-Close" + class="layout-navbars-tagsview-ul-li-icon layout-icon-three" + v-if="!v.meta.isAffix" + @click.stop="closeCurrentTagsView(getThemeConfig.isShareTagsView ? v.path : v.url)" + /> + </li> + </ul> + </el-scrollbar> + <Contextmenu :dropdown="dropdown" ref="contextmenuRef" @currentContextmenuClick="onCurrentContextmenuClick" /> + </div> +</template> + +<script lang="ts"> +import { + toRefs, + reactive, + onMounted, + computed, + ref, + nextTick, + onBeforeUpdate, + onBeforeMount, + onUnmounted, + getCurrentInstance, + watch, + defineComponent, +} from 'vue'; +import { useRoute, useRouter, onBeforeRouteUpdate } from 'vue-router'; +import Sortable from 'sortablejs'; +import { ElMessage } from 'element-plus'; +import { storeToRefs } from 'pinia'; +import pinia from '/@/stores/index'; +import { useTagsViewRoutes } from '/@/stores/tagsViewRoutes'; +import { useThemeConfig } from '/@/stores/themeConfig'; +import { useKeepALiveNames } from '/@/stores/keepAliveNames'; +import { Session } from '/@/utils/storage'; +import { isObjectValueEqual } from '/@/utils/arrayOperation'; +import other from '/@/utils/other'; +import Contextmenu from '/@/layout/navBars/tagsView/contextmenu.vue'; + +// 定义接口来定义对象的类型 +interface TagsViewState { + routeActive: string; + routePath: string | unknown; + dropdown: { + x: string | number; + y: string | number; + }; + sortable: any; + tagsRefsIndex: number; + tagsViewList: any[]; + tagsViewRoutesList: any[]; +} +interface RouteParams { + path: string; + url: string; + query: object; + params: object; +} +interface CurrentContextmenu { + meta: { + isDynamic: boolean; + }; + params: any; + query: any; + path: string; + contextMenuClickId: string | number; +} + +export default defineComponent({ + name: 'layoutTagsView', + components: { Contextmenu }, + setup() { + const { proxy } = <any>getCurrentInstance(); + const tagsRefs = ref<any[]>([]); + const scrollbarRef = ref(); + const contextmenuRef = ref(); + const tagsUlRef = ref(); + const stores = useTagsViewRoutes(); + const storesThemeConfig = useThemeConfig(); + const storesTagsViewRoutes = useTagsViewRoutes(); + const { themeConfig } = storeToRefs(storesThemeConfig); + const { tagsViewRoutes } = storeToRefs(storesTagsViewRoutes); + const storesKeepALiveNames = useKeepALiveNames(); + const route = useRoute(); + const router = useRouter(); + const state = reactive<TagsViewState>({ + routeActive: '', + routePath: route.path, + dropdown: { x: '', y: '' }, + sortable: '', + tagsRefsIndex: 0, + tagsViewList: [], + tagsViewRoutesList: [], + }); + // 动态设置 tagsView 风格样式 + const setTagsStyle = computed(() => { + return themeConfig.value.tagsStyle; + }); + // 获取布局配置信息 + const getThemeConfig = computed(() => { + return themeConfig.value; + }); + // 设置 自定义 tagsView 名称、 自定义 tagsView 名称国际化 + const setTagsViewNameI18n = computed(() => { + return (v: any) => { + return other.setTagsViewNameI18n(v); + }; + }); + // 设置 tagsView 高亮 + const isActive = (v: RouteParams) => { + if (getThemeConfig.value.isShareTagsView) { + return v.path === state.routePath; + } else { + if ((v.query && Object.keys(v.query).length) || (v.params && Object.keys(v.params).length)) { + // 普通传参 + return v.url ? v.url === state.routeActive : v.path === state.routeActive; + } else { + // 通过 name 传参,params 取值,刷新页面参数消失 + // https://gitee.com/lyt-top/vue-next-admin/issues/I51RS9 + return v.path === state.routePath; + } + } + }; + // 存储 tagsViewList 到浏览器临时缓存中,页面刷新时,保留记录 + const addBrowserSetSession = (tagsViewList: Array<object>) => { + Session.set('tagsViewList', tagsViewList); + }; + // 获取 vuex 中的 tagsViewRoutes 列表 + const getTagsViewRoutes = async () => { + state.routeActive = await setTagsViewHighlight(route); + state.routePath = (await route.meta.isDynamic) ? route.meta.isDynamicPath : route.path; + state.tagsViewList = []; + state.tagsViewRoutesList = tagsViewRoutes.value; + initTagsView(); + }; + // vuex 中获取路由信息:如果是设置了固定的(isAffix),进行初始化显示 + const initTagsView = async () => { + if (Session.get('tagsViewList') && getThemeConfig.value.isCacheTagsView) { + state.tagsViewList = await Session.get('tagsViewList'); + } else { + await state.tagsViewRoutesList.map((v: any) => { + if (v.meta.isAffix && !v.meta.isHide) { + v.url = setTagsViewHighlight(v); + state.tagsViewList.push({ ...v }); + storesKeepALiveNames.addCachedView(v); + } + }); + await addTagsView(route.path, route); + } + // 初始化当前元素(li)的下标 + getTagsRefsIndex(getThemeConfig.value.isShareTagsView ? state.routePath : state.routeActive); + }; + // 处理可开启多标签详情,单标签详情(动态路由(xxx/:id/:name"),普通路由处理) + const solveAddTagsView = async (path: string, to?: any) => { + let isDynamicPath = to.meta.isDynamic ? to.meta.isDynamicPath : path; + let current = state.tagsViewList.filter( + (v: any) => + v.path === isDynamicPath && + isObjectValueEqual( + to.meta.isDynamic ? (v.params ? v.params : null) : v.query ? v.query : null, + to.meta.isDynamic ? (to?.params ? to?.params : null) : to?.query ? to?.query : null + ) + ); + if (current.length <= 0) { + // 防止:Avoid app logic that relies on enumerating keys on a components instance. The keys will be empty in production mode to avoid performance overhead. + let findItem = state.tagsViewRoutesList.find((v: any) => v.path === isDynamicPath); + if (!findItem) return false; + if (findItem.meta.isAffix) return false; + if (findItem.meta.isLink && !findItem.meta.isIframe) return false; + to.meta.isDynamic ? (findItem.params = to.params) : (findItem.query = to.query); + findItem.url = setTagsViewHighlight(findItem); + state.tagsViewList.push({ ...findItem }); + await storesKeepALiveNames.addCachedView(findItem); + addBrowserSetSession(state.tagsViewList); + } + }; + // 处理单标签时,第二次的值未覆盖第一次的 tagsViewList 值(Session Storage) + const singleAddTagsView = (path: string, to?: any) => { + let isDynamicPath = to.meta.isDynamic ? to.meta.isDynamicPath : path; + state.tagsViewList.forEach((v) => { + if ( + v.path === isDynamicPath && + !isObjectValueEqual( + to.meta.isDynamic ? (v.params ? v.params : null) : v.query ? v.query : null, + to.meta.isDynamic ? (to?.params ? to?.params : null) : to?.query ? to?.query : null + ) + ) { + to.meta.isDynamic ? (v.params = to.params) : (v.query = to.query); + v.url = setTagsViewHighlight(v); + addBrowserSetSession(state.tagsViewList); + } + }); + }; + // 1、添加 tagsView:未设置隐藏(isHide)也添加到在 tagsView 中(可开启多标签详情,单标签详情) + const addTagsView = (path: string, to?: any) => { + // 防止拿取不到路由信息 + nextTick(async () => { + // 修复:https://gitee.com/lyt-top/vue-next-admin/issues/I3YX6G + let item: any = ''; + if (to && to.meta.isDynamic) { + // 动态路由(xxx/:id/:name"):参数不同,开启多个 tagsview + if (!getThemeConfig.value.isShareTagsView) await solveAddTagsView(path, to); + else await singleAddTagsView(path, to); + if (state.tagsViewList.some((v: any) => v.path === to.meta.isDynamicPath)) return false; + item = state.tagsViewRoutesList.find((v: any) => v.path === to.meta.isDynamicPath); + } else { + // 普通路由:参数不同,开启多个 tagsview + if (!getThemeConfig.value.isShareTagsView) await solveAddTagsView(path, to); + else await singleAddTagsView(path, to); + if (state.tagsViewList.some((v: any) => v.path === path)) return false; + item = state.tagsViewRoutesList.find((v: any) => v.path === path); + } + if (!item) return false; + if (item.meta.isLink && !item.meta.isIframe) return false; + if (to && to.meta.isDynamic) item.params = to?.params ? to?.params : route.params; + else item.query = to?.query ? to?.query : route.query; + item.url = setTagsViewHighlight(item); + await storesKeepALiveNames.addCachedView(item); + await state.tagsViewList.push({ ...item }); + await addBrowserSetSession(state.tagsViewList); + }); + }; + // 2、刷新当前 tagsView: + const refreshCurrentTagsView = async (fullPath: string) => { + const item = state.tagsViewList.find((v: any) => (getThemeConfig.value.isShareTagsView ? v.path === fullPath : v.url === fullPath)); + if (item != null) { + await storesKeepALiveNames.delCachedView(item); + proxy.mittBus.emit('onTagsViewRefreshRouterView', fullPath); + if (item.meta.isKeepAlive) storesKeepALiveNames.addCachedView(item); + } + }; + // 3、关闭当前 tagsView:如果是设置了固定的(isAffix),不可以关闭 + const closeCurrentTagsView = (path: string) => { + state.tagsViewList.map((v: any, k: number, arr: any) => { + if (!v.meta.isAffix) { + if (getThemeConfig.value.isShareTagsView ? v.path === path : v.url === path) { + storesKeepALiveNames.delCachedView(v); + state.tagsViewList.splice(k, 1); + setTimeout(() => { + if (state.tagsViewList.length === k && getThemeConfig.value.isShareTagsView ? state.routePath === path : state.routeActive === path) { + // 最后一个且高亮时 + if (arr[arr.length - 1].meta.isDynamic) { + // 动态路由(xxx/:id/:name") + if (k !== arr.length) router.push({ name: arr[k].name, params: arr[k].params }); + else router.push({ name: arr[arr.length - 1].name, params: arr[arr.length - 1].params }); + } else { + // 普通路由 + if (k !== arr.length) router.push({ path: arr[k].path, query: arr[k].query }); + else router.push({ path: arr[arr.length - 1].path, query: arr[arr.length - 1].query }); + } + } else { + // 非最后一个且高亮时,跳转到下一个 + if (state.tagsViewList.length !== k && getThemeConfig.value.isShareTagsView ? state.routePath === path : state.routeActive === path) { + if (arr[k].meta.isDynamic) { + // 动态路由(xxx/:id/:name") + router.push({ name: arr[k].name, params: arr[k].params }); + } else { + // 普通路由 + router.push({ path: arr[k].path, query: arr[k].query }); + } + } + } + }, 0); + } + } + }); + addBrowserSetSession(state.tagsViewList); + }; + // 4、关闭其它 tagsView:如果是设置了固定的(isAffix),不进行关闭 + const closeOtherTagsView = (path: string) => { + if (Session.get('tagsViewList')) { + state.tagsViewList = []; + Session.get('tagsViewList').map((v: any) => { + if (v.meta.isAffix && !v.meta.isHide) { + v.url = setTagsViewHighlight(v); + storesKeepALiveNames.delOthersCachedViews(v); + state.tagsViewList.push({ ...v }); + } + }); + addTagsView(path, route); + addBrowserSetSession(state.tagsViewList); + } + }; + // 5、关闭全部 tagsView:如果是设置了固定的(isAffix),不进行关闭 + const closeAllTagsView = () => { + if (Session.get('tagsViewList')) { + storesKeepALiveNames.delAllCachedViews(); + state.tagsViewList = []; + Session.get('tagsViewList').map((v: any) => { + if (v.meta.isAffix && !v.meta.isHide) { + v.url = setTagsViewHighlight(v); + state.tagsViewList.push({ ...v }); + router.push({ path: state.tagsViewList[state.tagsViewList.length - 1].path }); + } + }); + addBrowserSetSession(state.tagsViewList); + } + }; + // 6、开启当前页面全屏 + const openCurrenFullscreen = async (path: string) => { + const item = state.tagsViewList.find((v: any) => (getThemeConfig.value.isShareTagsView ? v.path === path : v.url === path)); + if (item.meta.isDynamic) await router.push({ name: item.name, params: item.params }); + else await router.push({ name: item.name, query: item.query }); + stores.setCurrenFullscreen(true); + }; + // 当前项右键菜单点击,拿当前点击的路由路径对比 浏览器缓存中的 tagsView 路由数组,取当前点击项的详细路由信息 + // 防止 tagsView 非当前页演示时,操作异常 + const getCurrentRouteItem = (path: string, cParams: any) => { + const itemRoute = Session.get('tagsViewList') ? Session.get('tagsViewList') : state.tagsViewList; + return itemRoute.find((v: any) => { + if ( + v.path === path && + isObjectValueEqual( + v.meta.isDynamic ? (v.params ? v.params : null) : v.query ? v.query : null, + cParams && Object.keys(cParams ? cParams : {}).length > 0 ? cParams : null + ) + ) { + return v; + } else if (v.path === path && Object.keys(cParams ? cParams : {}).length <= 0) { + return v; + } + }); + }; + // 当前项右键菜单点击 + const onCurrentContextmenuClick = async (item: CurrentContextmenu) => { + const cParams = item.meta.isDynamic ? item.params : item.query; + if (!getCurrentRouteItem(item.path, cParams)) return ElMessage({ type: 'warning', message: '请正确输入路径及完整参数(query、params)' }); + const { path, name, params, query, meta, url } = getCurrentRouteItem(item.path, cParams); + switch (item.contextMenuClickId) { + case 0: + // 刷新当前 + if (meta.isDynamic) await router.push({ name, params }); + else await router.push({ path, query }); + refreshCurrentTagsView(route.fullPath); + break; + case 1: + // 关闭当前 + closeCurrentTagsView(getThemeConfig.value.isShareTagsView ? path : url); + break; + case 2: + // 关闭其它 + if (meta.isDynamic) await router.push({ name, params }); + else await router.push({ path, query }); + closeOtherTagsView(path); + break; + case 3: + // 关闭全部 + closeAllTagsView(); + break; + case 4: + // 开启当前页面全屏 + openCurrenFullscreen(getThemeConfig.value.isShareTagsView ? path : url); + break; + } + }; + // 右键点击时:传 x,y 坐标值到子组件中(props) + const onContextmenu = (v: any, e: any) => { + const { clientX, clientY } = e; + state.dropdown.x = clientX; + state.dropdown.y = clientY; + contextmenuRef.value.openContextmenu(v); + }; + // 当前的 tagsView 项点击时 + const onTagsClick = (v: any, k: number) => { + state.tagsRefsIndex = k; + router.push(v); + }; + // 处理 tagsView 高亮(多标签详情时使用,单标签详情未使用) + const setTagsViewHighlight = (v: any) => { + let params = v.query && Object.keys(v.query).length > 0 ? v.query : v.params; + if (!params || Object.keys(params).length <= 0) return v.path; + let path = ''; + for (let i in params) { + path += params[i]; + } + // 判断是否是动态路由(xxx/:id/:name") + return `${v.meta.isDynamic ? v.meta.isDynamicPath : v.path}-${path}`; + }; + // 更新滚动条显示 + const updateScrollbar = () => { + proxy.$refs.scrollbarRef.update(); + }; + // 鼠标滚轮滚动 + const onHandleScroll = (e: any) => { + proxy.$refs.scrollbarRef.$refs.wrap$.scrollLeft += e.wheelDelta / 4; + }; + // tagsView 横向滚动 + const tagsViewmoveToCurrentTag = () => { + nextTick(() => { + if (tagsRefs.value.length <= 0) return false; + // 当前 li 元素 + let liDom = tagsRefs.value[state.tagsRefsIndex]; + // 当前 li 元素下标 + let liIndex = state.tagsRefsIndex; + // 当前 ul 下 li 元素总长度 + let liLength = tagsRefs.value.length; + // 最前 li + let liFirst: any = tagsRefs.value[0]; + // 最后 li + let liLast: any = tagsRefs.value[tagsRefs.value.length - 1]; + // 当前滚动条的值 + let scrollRefs = proxy.$refs.scrollbarRef.$refs.wrap$; + // 当前滚动条滚动宽度 + let scrollS = scrollRefs.scrollWidth; + // 当前滚动条偏移宽度 + let offsetW = scrollRefs.offsetWidth; + // 当前滚动条偏移距离 + let scrollL = scrollRefs.scrollLeft; + // 上一个 tags li dom + let liPrevTag: any = tagsRefs.value[state.tagsRefsIndex - 1]; + // 下一个 tags li dom + let liNextTag: any = tagsRefs.value[state.tagsRefsIndex + 1]; + // 上一个 tags li dom 的偏移距离 + let beforePrevL: any = ''; + // 下一个 tags li dom 的偏移距离 + let afterNextL: any = ''; + if (liDom === liFirst) { + // 头部 + scrollRefs.scrollLeft = 0; + } else if (liDom === liLast) { + // 尾部 + scrollRefs.scrollLeft = scrollS - offsetW; + } else { + // 非头/尾部 + if (liIndex === 0) beforePrevL = liFirst.offsetLeft - 5; + else beforePrevL = liPrevTag?.offsetLeft - 5; + if (liIndex === liLength) afterNextL = liLast.offsetLeft + liLast.offsetWidth + 5; + else afterNextL = liNextTag.offsetLeft + liNextTag.offsetWidth + 5; + if (afterNextL > scrollL + offsetW) { + scrollRefs.scrollLeft = afterNextL - offsetW; + } else if (beforePrevL < scrollL) { + scrollRefs.scrollLeft = beforePrevL; + } + } + // 更新滚动条,防止不出现 + updateScrollbar(); + }); + }; + // 获取 tagsView 的下标:用于处理 tagsView 点击时的横向滚动 + const getTagsRefsIndex = (path: string | unknown) => { + nextTick(async () => { + // await 使用该写法,防止拿取不到 tagsViewList 列表数据不完整 + let tagsViewList = await state.tagsViewList; + state.tagsRefsIndex = tagsViewList.findIndex((v: any) => { + if (getThemeConfig.value.isShareTagsView) { + return v.path === path; + } else { + return v.url === path; + } + }); + // 添加初始化横向滚动条移动到对应位置 + tagsViewmoveToCurrentTag(); + }); + }; + // 设置 tagsView 可以进行拖拽 + const initSortable = async () => { + const el = <HTMLElement>document.querySelector('.layout-navbars-tagsview-ul'); + if (!el) return false; + state.sortable.el && state.sortable.destroy(); + state.sortable = Sortable.create(el, { + animation: 300, + dataIdAttr: 'data-url', + disabled: getThemeConfig.value.isSortableTagsView ? false : true, + onEnd: () => { + const sortEndList: any = []; + state.sortable.toArray().map((val: any) => { + state.tagsViewList.map((v: any) => { + if (v.url === val) sortEndList.push({ ...v }); + }); + }); + addBrowserSetSession(sortEndList); + }, + }); + }; + // 拖动问题,https://gitee.com/lyt-top/vue-next-admin/issues/I3ZRRI + const onSortableResize = async () => { + await initSortable(); + if (other.isMobile()) state.sortable.el && state.sortable.destroy(); + }; + // 页面加载前 + onBeforeMount(() => { + // 初始化,防止手机端直接访问时还可以拖拽 + onSortableResize(); + // 拖动问题,https://gitee.com/lyt-top/vue-next-admin/issues/I3ZRRI + window.addEventListener('resize', onSortableResize); + // 监听非本页面调用 0 刷新当前,1 关闭当前,2 关闭其它,3 关闭全部 4 当前页全屏 + proxy.mittBus.on('onCurrentContextmenuClick', (data: CurrentContextmenu) => { + onCurrentContextmenuClick(data); + }); + // 监听布局配置界面开启/关闭拖拽 + proxy.mittBus.on('openOrCloseSortable', () => { + initSortable(); + }); + // 监听布局配置开启 TagsView 共用,为了演示还原默认值 + proxy.mittBus.on('openShareTagsView', () => { + if (getThemeConfig.value.isShareTagsView) { + router.push('/home'); + state.tagsViewList = []; + state.tagsViewRoutesList.map((v: any) => { + if (v.meta.isAffix && !v.meta.isHide) { + v.url = setTagsViewHighlight(v); + state.tagsViewList.push({ ...v }); + } + }); + } + }); + }); + // 页面卸载时 + onUnmounted(() => { + // 取消非本页面调用监听 + proxy.mittBus.off('onCurrentContextmenuClick', () => {}); + // 取消监听布局配置界面开启/关闭拖拽 + proxy.mittBus.off('openOrCloseSortable', () => {}); + // 取消监听布局配置开启 TagsView 共用 + proxy.mittBus.off('openShareTagsView', () => {}); + // 取消窗口 resize 监听 + window.removeEventListener('resize', onSortableResize); + }); + // 页面更新时 + onBeforeUpdate(() => { + tagsRefs.value = []; + }); + // 页面加载时 + onMounted(() => { + // 初始化 pinia 中的 tagsViewRoutes 列表 + getTagsViewRoutes(); + initSortable(); + }); + // 路由更新时(组件内生命钩子) + onBeforeRouteUpdate(async (to) => { + state.routeActive = setTagsViewHighlight(to); + state.routePath = to.meta.isDynamic ? to.meta.isDynamicPath : to.path; + await addTagsView(to.path, to); + getTagsRefsIndex(getThemeConfig.value.isShareTagsView ? state.routePath : state.routeActive); + }); + // 监听路由的变化,动态赋值给 tagsView + watch( + pinia.state, + (val) => { + if (val.tagsViewRoutes.tagsViewRoutes.length === state.tagsViewRoutesList.length) return false; + getTagsViewRoutes(); + }, + { + deep: true, + } + ); + return { + isActive, + onContextmenu, + onTagsClick, + tagsRefs, + contextmenuRef, + scrollbarRef, + tagsUlRef, + onHandleScroll, + getThemeConfig, + setTagsStyle, + setTagsViewNameI18n, + refreshCurrentTagsView, + closeCurrentTagsView, + onCurrentContextmenuClick, + ...toRefs(state), + }; + }, +}); +</script> + +<style scoped lang="scss"> +.layout-navbars-tagsview { + background-color: var(--el-color-white); + border-bottom: 1px solid var(--next-border-color-light); + position: relative; + z-index: 4; + ::v-deep(.el-scrollbar__wrap) { + overflow-x: auto !important; + } + &-ul { + list-style: none; + margin: 0; + padding: 0; + height: 34px; + display: flex; + align-items: center; + color: var(--el-text-color-regular); + font-size: 12px; + white-space: nowrap; + padding: 0 15px; + &-li { + height: 26px; + line-height: 26px; + display: flex; + align-items: center; + border: 1px solid var(--el-border-color-lighter); + padding: 0 15px; + margin-right: 5px; + border-radius: 2px; + position: relative; + z-index: 0; + cursor: pointer; + justify-content: space-between; + &:hover { + background-color: var(--el-color-primary-light-9); + color: var(--el-color-primary); + border-color: var(--el-color-primary-light-5); + } + &-iconfont { + position: relative; + left: -5px; + font-size: 12px; + } + &-icon { + border-radius: 100%; + position: relative; + height: 14px; + width: 14px; + text-align: center; + line-height: 14px; + right: -5px; + &:hover { + color: var(--el-color-white); + background-color: var(--el-color-primary-light-3); + } + } + .layout-icon-active { + display: block; + } + .layout-icon-three { + display: none; + } + } + .is-active { + color: var(--el-color-white); + background: var(--el-color-primary); + border-color: var(--el-color-primary); + transition: border-color 3s ease; + } + } + // 风格4 + .tags-style-four { + .layout-navbars-tagsview-ul-li { + margin-right: 0 !important; + border: none !important; + position: relative; + border-radius: 3px !important; + .layout-icon-active { + display: none; + } + .layout-icon-three { + display: block; + } + &:hover { + background: none !important; + } + } + .is-active { + background: none !important; + color: var(--el-color-primary) !important; + } + } + // 风格5 + .tags-style-five { + align-items: flex-end; + .tags-style-five-svg { + -webkit-mask-box-image: url("data:image/svg+xml,%3Csvg width='68' height='34' viewBox='0 0 68 34' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='m27,0c-7.99582,0 -11.95105,0.00205 -12,12l0,6c0,8.284 -0.48549,16.49691 -8.76949,16.49691l54.37857,-0.11145c-8.284,0 -8.60908,-8.10146 -8.60908,-16.38546l0,-6c0.11145,-12.08445 -4.38441,-12 -12,-12l-13,0z' fill='%23409eff'/%3E%3C/svg%3E") + 12 27 15; + } + .layout-navbars-tagsview-ul-li { + padding: 0 5px; + border-width: 15px 27px 15px; + border-style: solid; + border-color: transparent; + margin: 0 -15px; + .layout-icon-active, + .layout-navbars-tagsview-ul-li-iconfont, + .layout-navbars-tagsview-ul-li-refresh { + display: none; + } + .layout-icon-three { + display: block; + } + &:hover { + @extend .tags-style-five-svg; + background: var(--el-color-primary-light-9); + color: unset; + } + } + .is-active { + @extend .tags-style-five-svg; + background: var(--el-color-primary-light-9) !important; + color: var(--el-color-primary) !important; + z-index: 1; + } + } +} +.layout-navbars-tagsview-shadow { + box-shadow: rgb(0 21 41 / 4%) 0px 1px 4px; +} +</style> diff --git a/src/layout/navMenu/horizontal.vue b/src/layout/navMenu/horizontal.vue new file mode 100644 index 0000000..f738dd6 --- /dev/null +++ b/src/layout/navMenu/horizontal.vue @@ -0,0 +1,157 @@ +<template> + <div class="el-menu-horizontal-warp"> + <el-scrollbar @wheel.native.prevent="onElMenuHorizontalScroll" ref="elMenuHorizontalScrollRef"> + <el-menu router :default-active="defaultActive" :ellipsis="false" background-color="transparent" mode="horizontal"> + <template v-for="val in menuLists"> + <el-sub-menu :index="val.path" v-if="val.children && val.children.length > 0" :key="val.path"> + <template #title> + <SvgIcon :name="val.meta.icon" /> + <span>{{ $t(val.meta.title) }}</span> + </template> + <SubItem :chil="val.children" /> + </el-sub-menu> + <template v-else> + <el-menu-item :index="val.path" :key="val.path"> + <template #title v-if="!val.meta.isLink || (val.meta.isLink && val.meta.isIframe)"> + <SvgIcon :name="val.meta.icon" /> + {{ $t(val.meta.title) }} + </template> + <template #title v-else> + <a :href="val.meta.isLink" target="_blank" rel="opener" class="w100"> + <SvgIcon :name="val.meta.icon" /> + {{ $t(val.meta.title) }} + </a> + </template> + </el-menu-item> + </template> + </template> + </el-menu> + </el-scrollbar> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, computed, defineComponent, getCurrentInstance, onMounted, nextTick, onBeforeMount } from 'vue'; +import { useRoute, onBeforeRouteUpdate } from 'vue-router'; +import { storeToRefs } from 'pinia'; +import { useRoutesList } from '/@/stores/routesList'; +import { useThemeConfig } from '/@/stores/themeConfig'; +import SubItem from '/@/layout/navMenu/subItem.vue'; + +export default defineComponent({ + name: 'navMenuHorizontal', + components: { SubItem }, + props: { + menuList: { + type: Array, + default: () => [], + }, + }, + setup(props) { + const { proxy } = <any>getCurrentInstance(); + const stores = useRoutesList(); + const storesThemeConfig = useThemeConfig(); + const { routesList } = storeToRefs(stores); + const { themeConfig } = storeToRefs(storesThemeConfig); + const route = useRoute(); + const state = reactive({ + defaultActive: null, + }); + // 获取父级菜单数据 + const menuLists = computed(() => { + return <any>props.menuList; + }); + // 设置横向滚动条可以鼠标滚轮滚动 + const onElMenuHorizontalScroll = (e: any) => { + const eventDelta = e.wheelDelta || -e.deltaY * 40; + proxy.$refs.elMenuHorizontalScrollRef.$refs.wrap$.scrollLeft = proxy.$refs.elMenuHorizontalScrollRef.$refs.wrap$.scrollLeft + eventDelta / 4; + }; + // 初始化数据,页面刷新时,滚动条滚动到对应位置 + const initElMenuOffsetLeft = () => { + nextTick(() => { + let els: any = document.querySelector('.el-menu.el-menu--horizontal li.is-active'); + if (!els) return false; + proxy.$refs.elMenuHorizontalScrollRef.$refs.wrap$.scrollLeft = els.offsetLeft; + }); + }; + // 路由过滤递归函数 + const filterRoutesFun = (arr: Array<string>) => { + return arr + .filter((item: any) => !item.meta.isHide) + .map((item: any) => { + item = Object.assign({}, item); + if (item.children) item.children = filterRoutesFun(item.children); + return item; + }); + }; + // 传送当前子级数据到菜单中 + const setSendClassicChildren = (path: string) => { + const currentPathSplit = path.split('/'); + let currentData: any = {}; + filterRoutesFun(routesList.value).map((v, k) => { + if (v.path === `/${currentPathSplit[1]}`) { + v['k'] = k; + currentData['item'] = [{ ...v }]; + currentData['children'] = [{ ...v }]; + if (v.children) currentData['children'] = v.children; + } + }); + return currentData; + }; + // 设置页面当前路由高亮 + const setCurrentRouterHighlight = (currentRoute: any) => { + const { path, meta } = currentRoute; + if (themeConfig.value.layout === 'classic') { + (<any>state.defaultActive) = `/${path.split('/')[1]}`; + } else { + const pathSplit = meta.isDynamic ? meta.isDynamicPath.split('/') : path.split('/'); + if (pathSplit.length >= 4 && meta.isHide) state.defaultActive = pathSplit.splice(0, 3).join('/'); + else state.defaultActive = path; + } + }; + // 页面加载前 + onBeforeMount(() => { + setCurrentRouterHighlight(route); + }); + // 页面加载时 + onMounted(() => { + initElMenuOffsetLeft(); + }); + // 路由更新时 + onBeforeRouteUpdate((to) => { + // 修复:https://gitee.com/lyt-top/vue-next-admin/issues/I3YX6G + setCurrentRouterHighlight(to); + // 修复经典布局开启切割菜单时,点击tagsView后左侧导航菜单数据不变的问题 + let { layout, isClassicSplitMenu } = themeConfig.value; + if (layout === 'classic' && isClassicSplitMenu) { + proxy.mittBus.emit('setSendClassicChildren', setSendClassicChildren(to.path)); + } + }); + return { + menuLists, + onElMenuHorizontalScroll, + ...toRefs(state), + }; + }, +}); +</script> + +<style scoped lang="scss"> +.el-menu-horizontal-warp { + flex: 1; + overflow: hidden; + margin-right: 30px; + ::v-deep(.el-scrollbar__bar.is-vertical) { + display: none; + } + ::v-deep(a) { + width: 100%; + } + .el-menu.el-menu--horizontal { + display: flex; + height: 100%; + width: 100%; + box-sizing: border-box; + } +} +</style> diff --git a/src/layout/navMenu/subItem.vue b/src/layout/navMenu/subItem.vue new file mode 100644 index 0000000..3fcefd3 --- /dev/null +++ b/src/layout/navMenu/subItem.vue @@ -0,0 +1,48 @@ +<template> + <template v-for="val in chils"> + <el-sub-menu :index="val.path" :key="val.path" v-if="val.children && val.children.length > 0"> + <template #title> + <SvgIcon :name="val.meta.icon" /> + <span>{{ $t(val.meta.title) }}</span> + </template> + <sub-item :chil="val.children" /> + </el-sub-menu> + <template v-else> + <el-menu-item :index="val.path" :key="val.path"> + <template v-if="!val.meta.isLink || (val.meta.isLink && val.meta.isIframe)"> + <SvgIcon :name="val.meta.icon" /> + <span>{{ $t(val.meta.title) }}</span> + </template> + <template v-else> + <a :href="val.meta.isLink" target="_blank" rel="opener" class="w100"> + <SvgIcon :name="val.meta.icon" /> + {{ $t(val.meta.title) }} + </a> + </template> + </el-menu-item> + </template> + </template> +</template> + +<script lang="ts"> +import { computed, defineComponent } from 'vue'; + +export default defineComponent({ + name: 'navMenuSubItem', + props: { + chil: { + type: Array, + default: () => [], + }, + }, + setup(props) { + // 获取父级菜单数据 + const chils = computed(() => { + return <any>props.chil; + }); + return { + chils, + }; + }, +}); +</script> diff --git a/src/layout/navMenu/vertical.vue b/src/layout/navMenu/vertical.vue new file mode 100644 index 0000000..bfd7d2d --- /dev/null +++ b/src/layout/navMenu/vertical.vue @@ -0,0 +1,101 @@ +<template> + <el-menu + router + :default-active="defaultActive" + background-color="transparent" + :collapse="isCollapse" + :unique-opened="true" + :collapse-transition="false" + > + <template v-for="val in menuLists"> + <el-sub-menu :index="val.path" v-if="val.children && val.children.length > 0" :key="val.path"> + <template #title> + <SvgIcon :name="val.meta.icon" /> + <span>{{ $t(val.meta.title) }}</span> + </template> + <SubItem :chil="val.children" /> + </el-sub-menu> + <template v-else> + <el-menu-item :index="val.path" :key="val.path"> + <SvgIcon :name="val.meta.icon" /> + <template #title v-if="!val.meta.isLink || (val.meta.isLink && val.meta.isIframe)"> + <span>{{ $t(val.meta.title) }}</span> + </template> + <template #title v-else> + <a :href="val.meta.isLink" target="_blank" rel="opener" class="w100">{{ $t(val.meta.title) }}</a> + </template> + </el-menu-item> + </template> + </template> + </el-menu> +</template> + +<script lang="ts"> +import { toRefs, reactive, computed, defineComponent, onMounted, watch } from 'vue'; +import { useRoute, onBeforeRouteUpdate } from 'vue-router'; +import { storeToRefs } from 'pinia'; +import { useThemeConfig } from '/@/stores/themeConfig'; +import SubItem from '/@/layout/navMenu/subItem.vue'; + +export default defineComponent({ + name: 'navMenuVertical', + components: { SubItem }, + props: { + menuList: { + type: Array, + default: () => [], + }, + }, + setup(props) { + const storesThemeConfig = useThemeConfig(); + const { themeConfig } = storeToRefs(storesThemeConfig); + const route = useRoute(); + const state = reactive({ + // 修复:https://gitee.com/lyt-top/vue-next-admin/issues/I3YX6G + defaultActive: route.meta.isDynamic ? route.meta.isDynamicPath : route.path, + isCollapse: false, + }); + // 获取父级菜单数据 + const menuLists = computed(() => { + return <any>props.menuList; + }); + // 获取布局配置信息 + const getThemeConfig = computed(() => { + return themeConfig.value; + }); + // 菜单高亮(详情时,父级高亮) + const setParentHighlight = (currentRoute: any) => { + const { path, meta } = currentRoute; + const pathSplit = meta.isDynamic ? meta.isDynamicPath.split('/') : path.split('/'); + if (pathSplit.length >= 4 && meta.isHide) return pathSplit.splice(0, 3).join('/'); + else return path; + }; + // 设置菜单的收起/展开 + watch( + themeConfig.value, + () => { + document.body.clientWidth <= 1000 ? (state.isCollapse = false) : (state.isCollapse = themeConfig.value.isCollapse); + }, + { + immediate: true, + } + ); + // 页面加载时 + onMounted(() => { + state.defaultActive = setParentHighlight(route); + }); + // 路由更新时 + onBeforeRouteUpdate((to) => { + // 修复:https://gitee.com/lyt-top/vue-next-admin/issues/I3YX6G + state.defaultActive = setParentHighlight(to); + const clientWidth = document.body.clientWidth; + if (clientWidth < 1000) themeConfig.value.isCollapse = false; + }); + return { + menuLists, + getThemeConfig, + ...toRefs(state), + }; + }, +}); +</script> diff --git a/src/layout/routerView/iframes.vue b/src/layout/routerView/iframes.vue new file mode 100644 index 0000000..43e71c5 --- /dev/null +++ b/src/layout/routerView/iframes.vue @@ -0,0 +1,66 @@ +<template> + <div class="layout-view-bg-white flex mt1" :style="{ height: `calc(100vh - ${setIframeHeight}`, border: 'none' }" v-loading="iframeLoading"> + <iframe :src="iframeUrl" frameborder="0" height="100%" width="100%" ref="iframeDom" v-show="!iframeLoading"></iframe> + </div> +</template> + +<script lang="ts"> +import { defineComponent, reactive, toRefs, onMounted, nextTick, watch, computed } from 'vue'; +import { storeToRefs } from 'pinia'; +import { useRoute } from 'vue-router'; +import { useThemeConfig } from '/@/stores/themeConfig'; +import { useTagsViewRoutes } from '/@/stores/tagsViewRoutes'; + +export default defineComponent({ + name: 'layoutIfameView', + setup() { + const storesThemeConfig = useThemeConfig(); + const storesTagsViewRoutes = useTagsViewRoutes(); + const { themeConfig } = storeToRefs(storesThemeConfig); + const { isTagsViewCurrenFull } = storeToRefs(storesTagsViewRoutes); + const route = useRoute(); + const state = reactive({ + iframeDom: null as HTMLIFrameElement | null, + iframeLoading: true, + iframeUrl: '', + }); + // 初始化页面加载 loading + const initIframeLoad = () => { + state.iframeUrl = <any>route.meta.isLink; + nextTick(() => { + state.iframeLoading = true; + const iframe = state.iframeDom; + if (!iframe) return false; + iframe.onload = () => { + state.iframeLoading = false; + }; + }); + }; + // 设置 iframe 的高度 + const setIframeHeight = computed(() => { + let { isTagsview } = themeConfig.value; + if (isTagsViewCurrenFull.value) { + return `1px`; + } else { + if (isTagsview) return `86px`; + else return `51px`; + } + }); + // 页面加载时 + onMounted(() => { + initIframeLoad(); + }); + // 监听路由变化,多个 iframe 时使用 + watch( + () => route.path, + () => { + initIframeLoad(); + } + ); + return { + setIframeHeight, + ...toRefs(state), + }; + }, +}); +</script> diff --git a/src/layout/routerView/link.vue b/src/layout/routerView/link.vue new file mode 100644 index 0000000..ca1c5f9 --- /dev/null +++ b/src/layout/routerView/link.vue @@ -0,0 +1,59 @@ +<template> + <div class="layout-view-bg-white flex layout-view-link" :style="{ height: `calc(100vh - ${setLinkHeight}` }"> + <a :href="currentRouteMeta.isLink" target="_blank" rel="opener" class="flex-margin"> {{ $t(currentRouteMeta.title) }}:{{ currentRouteMeta.isLink }} </a> + </div> +</template> + +<script lang="ts"> +import { defineComponent, toRefs, reactive, computed, watch } from 'vue'; +import { useRoute, RouteMeta } from 'vue-router'; +import { storeToRefs } from 'pinia'; +import { useThemeConfig } from '/@/stores/themeConfig'; + +// 定义接口来定义对象的类型 +interface LinkViewState { + currentRouteMeta: { + isLink: string; + title: string; + }; +} +interface LinkViewRouteMeta extends RouteMeta { + isLink: string; + title: string; +} + +export default defineComponent({ + name: 'layoutLinkView', + setup() { + const storesThemeConfig = useThemeConfig(); + const { themeConfig } = storeToRefs(storesThemeConfig); + const route = useRoute(); + const state = reactive<LinkViewState>({ + currentRouteMeta: { + isLink: '', + title: '' + } + }); + // 设置 link 的高度 + const setLinkHeight = computed(() => { + let { isTagsview } = themeConfig.value; + if (isTagsview) return `115px`; + else return `80px`; + }); + // 监听路由的变化,设置内容 + watch( + () => route.path, + () => { + state.currentRouteMeta = <LinkViewRouteMeta>route.meta; + }, + { + immediate: true + } + ); + return { + setLinkHeight, + ...toRefs(state) + }; + } +}); +</script> diff --git a/src/layout/routerView/parent.vue b/src/layout/routerView/parent.vue new file mode 100644 index 0000000..db22141 --- /dev/null +++ b/src/layout/routerView/parent.vue @@ -0,0 +1,88 @@ +<template> + <div class="h100"> + <router-view v-slot="{ Component }"> + <transition :name="setTransitionName" mode="out-in"> + <keep-alive :include="getKeepAliveNames"> + <component :is="Component" :key="refreshRouterViewKey" class="w100" /> + </keep-alive> + </transition> + </router-view> + </div> +</template> + +<script lang="ts"> +import { computed, defineComponent, toRefs, reactive, getCurrentInstance, onBeforeMount, onUnmounted, nextTick, watch, onMounted } from 'vue'; +import { useRoute } from 'vue-router'; +import { storeToRefs } from 'pinia'; +import { useKeepALiveNames } from '/@/stores/keepAliveNames'; +import { useThemeConfig } from '/@/stores/themeConfig'; +import { Session } from '/@/utils/storage'; + +// 定义接口来定义对象的类型 +interface ParentViewState { + refreshRouterViewKey: null | string; + keepAliveNameList: string[]; +} + +export default defineComponent({ + name: 'layoutParentView', + setup() { + const { proxy } = <any>getCurrentInstance(); + const route = useRoute(); + const storesKeepAliveNames = useKeepALiveNames(); + const storesThemeConfig = useThemeConfig(); + const { keepAliveNames, cachedViews } = storeToRefs(storesKeepAliveNames); + const { themeConfig } = storeToRefs(storesThemeConfig); + const state = reactive<ParentViewState>({ + refreshRouterViewKey: null, + keepAliveNameList: [], + }); + // 设置主界面切换动画 + const setTransitionName = computed(() => { + return themeConfig.value.animation; + }); + // 获取组件缓存列表(name值) + const getKeepAliveNames = computed(() => { + return themeConfig.value.isTagsview ? cachedViews.value : state.keepAliveNameList; + }); + // 页面加载前,处理缓存,页面刷新时路由缓存处理 + onBeforeMount(() => { + state.keepAliveNameList = keepAliveNames.value; + proxy.mittBus.on('onTagsViewRefreshRouterView', (fullPath: string) => { + state.keepAliveNameList = keepAliveNames.value.filter((name: string) => route.name !== name); + state.refreshRouterViewKey = null; + nextTick(() => { + state.refreshRouterViewKey = fullPath; + state.keepAliveNameList = keepAliveNames.value; + }); + }); + }); + // 页面加载时 + onMounted(() => { + // https://gitee.com/lyt-top/vue-next-admin/issues/I58U75 + // https://gitee.com/lyt-top/vue-next-admin/issues/I59RXK + nextTick(() => { + setTimeout(() => { + if (themeConfig.value.isCacheTagsView) cachedViews.value = Session.get('tagsViewList')?.map((item: any) => item.name); + }, 0); + }); + }); + // 页面卸载时 + onUnmounted(() => { + proxy.mittBus.off('onTagsViewRefreshRouterView', () => {}); + }); + // 监听路由变化,防止 tagsView 多标签时,切换动画消失 + watch( + () => route.fullPath, + () => { + state.refreshRouterViewKey = decodeURI(route.fullPath); + } + ); + return { + setTransitionName, + getKeepAliveNames, + ...toRefs(state), + }; + }, +}); +</script> diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..a45931b --- /dev/null +++ b/src/main.ts @@ -0,0 +1,27 @@ +import { createApp } from 'vue'; +import pinia from '/@/stores/index'; +import App from './App.vue'; +import router from './router'; +import { directive } from '/@/utils/directive'; +import { i18n } from '/@/i18n/index'; +import other from '/@/utils/other'; +import '/@/assets/style/index.scss'; +import ElementPlus from 'element-plus'; +import * as ElementPlusIconsVue from '@element-plus/icons-vue'; +import 'element-plus/dist/index.css'; +import '/@/theme/index.scss'; +import mitt from 'mitt'; +import VueGridLayout from 'vue-grid-layout'; +import zhCn from 'element-plus/lib/locale/lang/zh-cn'; +import DataVVue3 from '@kjgl77/datav-vue3' + +const app = createApp(App); +for (const [key, component] of Object.entries(ElementPlusIconsVue)) { + app.component(key, component); +} +directive(app); +other.elSvg(app); + +app.use(pinia).use(router).use(ElementPlus, { i18n: i18n.global.t, locale: zhCn }).use(i18n).use(DataVVue3).use(VueGridLayout).mount('#app'); + +app.config.globalProperties.mittBus = mitt(); diff --git a/src/router/backEnd.ts b/src/router/backEnd.ts new file mode 100644 index 0000000..fcec8e0 --- /dev/null +++ b/src/router/backEnd.ts @@ -0,0 +1,98 @@ +import { RouteRecordRaw } from 'vue-router'; +import { storeToRefs } from 'pinia'; +import pinia from '/@/stores/index'; +import { useUserInfo } from '/@/stores/userInfo'; +import { useRequestOldRoutes } from '/@/stores/requestOldRoutes'; +import { NextLoading } from '/@/utils/loading'; +import { dynamicRoutes, notFoundAndNoPower } from '/@/router/route'; +import { formatTwoStageRoutes, formatFlatteningRoutes, router } from '/@/router/index'; +import { useRoutesList } from '/@/stores/routesList'; +import { useTagsViewRoutes } from '/@/stores/tagsViewRoutes'; +import { useMenuApi } from '/@/api/systemManage/menu/index'; +import { ElMessage } from 'element-plus'; +import Cookies from 'js-cookie'; + +const menuApi = useMenuApi(); + +const layouModules: any = import.meta.glob('../layout/routerView/*.{vue,tsx}'); +const viewsModules: any = import.meta.glob('../views/**/*.{vue,tsx}'); + +/** + * 获取目录下的 .vue、.tsx 全部文件 + * @method import.meta.glob + * @link 参考:https://cn.vitejs.dev/guide/features.html#json + */ +const dynamicViewsModules: Record<string, Function> = Object.assign({}, { ...layouModules }, { ...viewsModules }); + +export async function initBackEndControlRoutes() { + if (window.nextLoading === undefined) NextLoading.start(); + if (!Cookies.get('token')) return false; + const res = await getBackEndControlRoutes(Cookies.get('projectId') === null ? '' : Cookies.get('projectId')); + await useRequestOldRoutes().setRequestOldRoutes(JSON.parse(JSON.stringify(res.data.data))); + dynamicRoutes[0].children = await backEndComponent(res.data.data); + await setAddRoute(); + await setFilterMenuAndCacheTagsViewRoutes(); +} + +export function setFilterMenuAndCacheTagsViewRoutes() { + const storesRoutesList = useRoutesList(pinia); + storesRoutesList.setRoutesList(dynamicRoutes[0].children as any); + setCacheTagsViewRoutes(); +} + +export function setCacheTagsViewRoutes() { + const storesTagsView = useTagsViewRoutes(pinia); + storesTagsView.setTagsViewRoutes(formatTwoStageRoutes(formatFlatteningRoutes(dynamicRoutes))[0].children); +} + +export function setFilterRouteEnd() { + let filterRouteEnd: any = formatTwoStageRoutes(formatFlatteningRoutes(dynamicRoutes)); + filterRouteEnd[0].children = [...filterRouteEnd[0].children, ...notFoundAndNoPower]; + return filterRouteEnd; +} + +export async function setAddRoute() { + await setFilterRouteEnd().forEach((route: RouteRecordRaw) => { + router.addRoute(route); + }); +} + +export async function getBackEndControlRoutes(value: string) { + // const stores = useUserInfo(pinia); + // const { userInfos } = storeToRefs(stores); + // const auth = userInfos.value.roles[0]; + return menuApi.getMenuAdmin(value); +} + +/** + * 重新请求后端路由菜单接口 + * @description 用于菜单管理界面刷新菜单(未进行测试) + * @description 路径:/src/views/system/homeMenu/components/menuDialog.vue + */ +export function setBackEndControlRefreshRoutes() { + getBackEndControlRoutes(Cookies.get('projectId')); +} + +export function backEndComponent(routes: any) { + if (!routes) return; + return routes.map((item: any) => { + if (item.component) item.component = dynamicImport(dynamicViewsModules, item.component as string); + item.children && backEndComponent(item.children); + return item; + }); +} + +export function dynamicImport(dynamicViewsModules: Record<string, Function>, component: string) { + const keys = Object.keys(dynamicViewsModules); + const matchKeys = keys.filter((key) => { + const k = key.replace(/..\/views|../, ''); + return k.startsWith(`${component}`) || k.startsWith(`/${component}`); + }); + if (matchKeys?.length === 1) { + const matchKey = matchKeys[0]; + return dynamicViewsModules[matchKey]; + } + if (matchKeys?.length > 1) { + return false; + } +} diff --git a/src/router/frontEnd.ts b/src/router/frontEnd.ts new file mode 100644 index 0000000..f672db5 --- /dev/null +++ b/src/router/frontEnd.ts @@ -0,0 +1,97 @@ +import { RouteRecordRaw } from 'vue-router'; +import { storeToRefs } from 'pinia'; +import { formatTwoStageRoutes, formatFlatteningRoutes, router } from '/@/router/index'; +import { dynamicRoutes, notFoundAndNoPower } from '/@/router/route'; +import pinia from '/@/stores/index'; +import { Session } from '/@/utils/storage'; +import { useUserInfo } from '/@/stores/userInfo'; +import { useTagsViewRoutes } from '/@/stores/tagsViewRoutes'; +import { useRoutesList } from '/@/stores/routesList'; +import { NextLoading } from '/@/utils/loading'; + + +export async function initFrontEndControlRoutes() { + if (window.nextLoading === undefined) NextLoading.start(); + if (!Session.get('token')) return false; + // useUserInfo(pinia).setUserInfos(); + await setAddRoute(); + await setFilterMenuAndCacheTagsViewRoutes(); +} + + +export async function setAddRoute() { + await setFilterRouteEnd().forEach((route: RouteRecordRaw) => { + router.addRoute(route); + }); +} + + +export async function frontEndsResetRoute() { + await setFilterRouteEnd().forEach((route: RouteRecordRaw) => { + const routeName: any = route.name; + router.hasRoute(routeName) && router.removeRoute(routeName); + }); +} + + +export function setFilterRouteEnd() { + let filterRouteEnd: any = formatTwoStageRoutes(formatFlatteningRoutes(dynamicRoutes)); + filterRouteEnd[0].children = [...setFilterRoute(filterRouteEnd[0].children), ...notFoundAndNoPower]; + return filterRouteEnd; +} + + +export function setFilterRoute(chil: any) { + const stores = useUserInfo(pinia); + const { userInfos } = storeToRefs(stores); + let filterRoute: any = []; + chil.forEach((route: any) => { + if (route.meta.roles) { + route.meta.roles.forEach((metaRoles: any) => { + userInfos.value.roles.forEach((roles: any) => { + if (metaRoles === roles) filterRoute.push({ ...route }); + }); + }); + } + }); + return filterRoute; +} + + +export function setCacheTagsViewRoutes() { + // 获取有权限的路由,否则 tagsView、菜单搜索中无权限的路由也将显示 + const stores = useUserInfo(pinia); + const storesTagsView = useTagsViewRoutes(pinia); + const { userInfos } = storeToRefs(stores); + let rolesRoutes = setFilterHasRolesMenu(dynamicRoutes, userInfos.value.roles); + // 添加到 pinia setTagsViewRoutes 中 + storesTagsView.setTagsViewRoutes(formatTwoStageRoutes(formatFlatteningRoutes(rolesRoutes))[0].children); +} + + +export function setFilterMenuAndCacheTagsViewRoutes() { + const stores = useUserInfo(pinia); + const storesRoutesList = useRoutesList(pinia); + const { userInfos } = storeToRefs(stores); + storesRoutesList.setRoutesList(setFilterHasRolesMenu(dynamicRoutes[0].children, userInfos.value.roles)); + setCacheTagsViewRoutes(); +} + + +export function hasRoles(roles: any, route: any) { + if (route.meta && route.meta.roles) return roles.some((role: any) => route.meta.roles.includes(role)); + else return true; +} + + +export function setFilterHasRolesMenu(routes: any, roles: any) { + const menu: any = []; + routes.forEach((route: any) => { + const item = { ...route }; + if (hasRoles(roles, item)) { + if (item.children) item.children = setFilterHasRolesMenu(item.children, roles); + menu.push(item); + } + }); + return menu; +} diff --git a/src/router/index.ts b/src/router/index.ts new file mode 100644 index 0000000..322d85c --- /dev/null +++ b/src/router/index.ts @@ -0,0 +1,106 @@ +import { createRouter, createWebHashHistory } from 'vue-router'; +import NProgress from 'nprogress'; +import 'nprogress/nprogress.css'; +import pinia from '/@/stores/index'; +import { storeToRefs } from 'pinia'; +import { useKeepALiveNames } from '/@/stores/keepAliveNames'; +import { useRoutesList } from '/@/stores/routesList'; +import { useThemeConfig } from '/@/stores/themeConfig'; +import { Session } from '/@/utils/storage'; +import { staticRoutes } from '/@/router/route'; +import { initFrontEndControlRoutes } from '/@/router/frontEnd'; +import { initBackEndControlRoutes } from '/@/router/backEnd'; +import { useUserInfo } from '/@/stores/userInfo'; +import { nextTick } from 'vue'; + +// 读取 `/src/stores/themeConfig.ts` 是否开启后端控制路由配置 +const storesThemeConfig = useThemeConfig(pinia); +const { themeConfig } = storeToRefs(storesThemeConfig); +const { isRequestRoutes } = themeConfig.value; +if (isRequestRoutes) staticRoutes.splice(0, 1); + +export const router = createRouter({ + history: createWebHashHistory(), + routes: staticRoutes +}); + +export function formatFlatteningRoutes(arr: any) { + if (arr.length <= 0) return false; + for (let i = 0; i < arr.length; i++) { + if (arr[i].children) { + arr = arr.slice(0, i + 1).concat(arr[i].children, arr.slice(i + 1)); + } + } + return arr; +} + +export function formatTwoStageRoutes(arr: any) { + if (arr.length <= 0) return false; + const newArr: any = []; + const cacheList: Array<string> = []; + arr.forEach((v: any) => { + if (v.path === '/') { + newArr.push({ component: v.component, name: v.name, path: v.path, redirect: v.redirect, meta: v.meta, children: [] }); + } else { + // 判断是否是动态路由(xx/:id/:name),用于 tagsView 等中使用 + // 修复:https://gitee.com/lyt-top/vue-next-admin/issues/I3YX6G + if (v.path.indexOf('/:') > -1) { + v.meta['isDynamic'] = true; + v.meta['isDynamicPath'] = v.path; + } + newArr[0].children.push({ ...v }); + // 存 name 值,keep-alive 中 include 使用,实现路由的缓存 + // 路径:/@/layout/routerView/parent.vue + if (newArr[0].meta.isKeepAlive && v.meta.isKeepAlive) { + cacheList.push(v.name); + const stores = useKeepALiveNames(pinia); + stores.setCacheKeepAlive(cacheList); + } + } + }); + return newArr; +} + +// // isRequestRoutes 为 true,则开启后端控制路由,路径:`/src/stores/themeConfig.ts` +// if (!isRequestRoutes) initFrontEndControlRoutes(); + +// 路由加载前 +router.beforeEach(async (to, from, next) => { + NProgress.configure({ showSpinner: false }); + if (to.meta.title) NProgress.start(); + const token = Session.get('token'); + if (to.path === '/login' && !token) { + next(); + NProgress.done(); + } else { + if (!token) { + next(`/login?redirect=${to.path}¶ms=${JSON.stringify(to.query ? to.query : to.params)}`); + Session.clear(); + NProgress.done(); + } else if (token && to.path === '/login') { + next('/home'); + NProgress.done(); + } else { + const storesRoutesList = useRoutesList(pinia); + const { routesList } = storeToRefs(storesRoutesList); + if (routesList.value.length === 0) { + + // 后端控制路由:路由数据初始化,防止刷新时丢失 + await initBackEndControlRoutes(); + // 动态添加路由:防止非首页刷新时跳转回首页的问题 + // 确保 addRoute() 时动态添加的路由已经被完全加载上去 + next({ ...to, replace: true }); + } else { + next(); + } + } + } +}); + +// 路由加载后 +router.afterEach(() => { + NProgress.done(); +}); + +// 导出路由 +export default router; diff --git a/src/router/route.ts b/src/router/route.ts new file mode 100644 index 0000000..afa1cda --- /dev/null +++ b/src/router/route.ts @@ -0,0 +1,115 @@ +import { RouteRecordRaw } from 'vue-router'; + +export const dynamicRoutes: Array<RouteRecordRaw> = [ + { + path: '/', + name: '/', + component: () => import('/@/layout/index.vue'), + redirect: '/home', + meta: { + isKeepAlive: false + }, + children: [ + { + path: '/home', + name: 'home', + component: () => import('/@/views/newHome/index.vue'), + meta: { + title: '首页', + isLink: '', + isHide: false, + isKeepAlive: true, + isAffix: true, + isIframe: false, + roles: ['admin', 'common'], + icon: 'iconfont icon-shouye' + } + } + ] + } +]; + +export const notFoundAndNoPower = [ + { + path: '/:path(.*)*', + name: 'notFound', + component: () => import('/@/views/error/404.vue'), + meta: { + title: 'message.staticRoutes.notFound', + isHide: true + } + }, + { + path: '/401', + name: 'noPower', + component: () => import('/@/views/error/401.vue'), + meta: { + title: 'message.staticRoutes.noPower', + isHide: true + } + } +]; + +export const staticRoutes: Array<RouteRecordRaw> = [ + { + path: '/', + name: '/', + component: () => import('/@/layout/index.vue'), + meta: { + title: '布局界面' + }, + children: [ + // 请不要往这里 `children` 中添加内容,此内容为了防止 No match found for location with path "xxx" 问题 + ...notFoundAndNoPower + ] + }, + { + path: '/login', + name: 'login', + component: () => import('/@/views/loginPage/loginPage.vue'), + meta: { + title: '登录' + } + }, + { + path: '/newMenu', + name: 'newMenu', + component: () => import('/@/views/newHome/index.vue'), + meta: { + title: '首页', + isKeepAlive: false + } + }, + { + path: '/warningScreen', + name: 'warningScreen', + component: () => import('/@/views/riskWarningSys/warningBigScreen/index.vue'), + meta: { + title: '预警预报' + } + }, + { + path: '/msgDetail', + name: 'msgDetail', + component: () => import('/@/views/riskWarningSys/warningBigScreen/indexs/msgDetail.vue'), + meta: { + title: 'spi报告详情' + } + }, + { + path: '/screenPage', + name: 'screenPage', + component: () => import('/@/views/riskWarningSys/warningBigScreen/indexs/index.vue'), + meta: { + title: '预警预报' + } + }, + { + path: '/securities', + name: 'securities', + component: () => import('/@/views/facilityManagement/securities/index.vue'), + meta: { + title: '安全物资与设备' + } + } +]; diff --git a/src/stores/index.ts b/src/stores/index.ts new file mode 100644 index 0000000..d9c4034 --- /dev/null +++ b/src/stores/index.ts @@ -0,0 +1,15 @@ +// https://pinia.vuejs.org/ +import { createPinia } from 'pinia'; +import { createPersistedState } from 'pinia-plugin-persistedstate' + +// 创建 +const pinia = createPinia(); +pinia.use(createPersistedState({ + serializer:{ + serialize:JSON.stringify, + deserialize:JSON.parse, + } +})) + +// 导出 +export default pinia; diff --git a/src/stores/interface/index.ts b/src/stores/interface/index.ts new file mode 100644 index 0000000..9ace21a --- /dev/null +++ b/src/stores/interface/index.ts @@ -0,0 +1,109 @@ +/** + * 定义接口来定义对象的类型 + * `stores` 全部类型定义在这里 + */ + +// 用户信息 +export interface UserInfosState { + authBtnList: string[]; + photo: string; + roles: string[]; + time: number; + userName: string; + uid: string; + depId: null | number; + projectId: string; + dataList: []; +} +export interface UserInfosStates { + userInfos: UserInfosState; +} + +// 路由缓存列表 +export interface KeepAliveNamesState { + keepAliveNames: string[]; + cachedViews: string[]; +} + +// 后端返回原始路由(未处理时) +export interface RequestOldRoutesState { + requestOldRoutes: string[]; +} + +// TagsView 路由列表 +export interface TagsViewRoutesState { + tagsViewRoutes: string[]; + isTagsViewCurrenFull: Boolean; +} + +// 路由列表 +export interface RoutesListState { + routesList: string[]; + isColumnsMenuHover: Boolean; + isColumnsNavHover: Boolean; + projectId: string; +} + +export interface loginInfoState { + loginUser: { + projectId: string; + token: string; + uid: string; + }; +} + +export interface screenThemeState { + screenTheme: { + isDark: boolean + } +} + +// 布局配置 +export interface ThemeConfigState { + isDrawer: boolean; + primary: string; + topBar: string; + topBarColor: string; + isTopBarColorGradual: boolean; + menuBar: string; + menuBarColor: string; + isMenuBarColorGradual: boolean; + columnsMenuBar: string; + columnsMenuBarColor: string; + isColumnsMenuBarColorGradual: boolean; + isCollapse: boolean; + isUniqueOpened: boolean; + isFixedHeader: boolean; + isFixedHeaderChange: boolean; + isClassicSplitMenu: boolean; + isLockScreen: boolean; + lockScreenTime: number; + isShowLogo: boolean; + isShowLogoChange: boolean; + isBreadcrumb: boolean; + isTagsview: boolean; + isBreadcrumbIcon: boolean; + isTagsviewIcon: boolean; + isCacheTagsView: boolean; + isSortableTagsView: boolean; + isShareTagsView: boolean; + isFooter: boolean; + isGrayscale: boolean; + isInvert: boolean; + isIsDark: boolean; + isWartermark: boolean; + wartermarkText: string; + tagsStyle: string; + animation: string; + columnsAsideStyle: string; + columnsAsideLayout: string; + layout: string; + isRequestRoutes: boolean; + globalTitle: string; + globalViceTitle: string; + globalI18n: string; + globalComponentSize: string; +} +export interface ThemeConfigStates { + themeConfig: ThemeConfigState; +} diff --git a/src/stores/keepAliveNames.ts b/src/stores/keepAliveNames.ts new file mode 100644 index 0000000..32e0389 --- /dev/null +++ b/src/stores/keepAliveNames.ts @@ -0,0 +1,37 @@ +import { defineStore } from 'pinia'; +import { KeepAliveNamesState } from './interface'; + +/** + * 路由缓存列表 + * @methods setCacheKeepAlive 设置要缓存的路由 names(开启 Tagsview) + * @methods addCachedView 添加要缓存的路由 names(关闭 Tagsview) + * @methods delCachedView 删除要缓存的路由 names(关闭 Tagsview) + * @methods delOthersCachedViews 右键菜单`关闭其它`,删除要缓存的路由 names(关闭 Tagsview) + * @methods delAllCachedViews 右键菜单`全部关闭`,删除要缓存的路由 names(关闭 Tagsview) + */ +export const useKeepALiveNames = defineStore('keepALiveNames', { + state: (): KeepAliveNamesState => ({ + keepAliveNames: [], + cachedViews: [], + }), + actions: { + async setCacheKeepAlive(data: Array<string>) { + this.keepAliveNames = data; + }, + async addCachedView(view: any) { + if (this.cachedViews.includes(view.name)) return; + if (view.meta.isKeepAlive) this.cachedViews.push(view.name); + }, + async delCachedView(view: any) { + const index = this.cachedViews.indexOf(view.name); + index > -1 && this.cachedViews.splice(index, 1); + }, + async delOthersCachedViews(view: any) { + if (view.meta.isKeepAlive) this.cachedViews = [view.name]; + else this.cachedViews = []; + }, + async delAllCachedViews() { + this.cachedViews = []; + }, + }, +}); diff --git a/src/stores/loginInfo.ts b/src/stores/loginInfo.ts new file mode 100644 index 0000000..4cc51ce --- /dev/null +++ b/src/stores/loginInfo.ts @@ -0,0 +1,20 @@ +import { defineStore } from 'pinia'; +import { loginInfoState } from './interface'; + +/** + * 路由列表 + * @methods setRoutesList 设置路由数据 + * @methods setColumnsMenuHover 设置分栏布局菜单鼠标移入 boolean + * @methods setColumnsNavHover 设置分栏布局最左侧导航鼠标移入 boolean + */ +export const useLoginInfo = defineStore('loginInfo', { + state: (): loginInfoState => ({ + loginUser:{ + projectId:'', + token:'', + uid:'', + } + }), + actions: { + }, +}); diff --git a/src/stores/requestOldRoutes.ts b/src/stores/requestOldRoutes.ts new file mode 100644 index 0000000..be9b5cd --- /dev/null +++ b/src/stores/requestOldRoutes.ts @@ -0,0 +1,17 @@ +import { defineStore } from 'pinia'; +import { RequestOldRoutesState } from './interface'; + +/** + * 后端返回原始路由(未处理时) + * @methods setCacheKeepAlive 设置接口原始路由数据 + */ +export const useRequestOldRoutes = defineStore('requestOldRoutes', { + state: (): RequestOldRoutesState => ({ + requestOldRoutes: [], + }), + actions: { + async setRequestOldRoutes(routes: Array<string>) { + this.requestOldRoutes = routes; + }, + }, +}); diff --git a/src/stores/routesList.ts b/src/stores/routesList.ts new file mode 100644 index 0000000..5b23b15 --- /dev/null +++ b/src/stores/routesList.ts @@ -0,0 +1,28 @@ +import { defineStore } from 'pinia'; +import { RoutesListState } from './interface'; + +/** + * 路由列表 + * @methods setRoutesList 设置路由数据 + * @methods setColumnsMenuHover 设置分栏布局菜单鼠标移入 boolean + * @methods setColumnsNavHover 设置分栏布局最左侧导航鼠标移入 boolean + */ +export const useRoutesList = defineStore('routesList', { + state: (): RoutesListState => ({ + routesList: [], + isColumnsMenuHover: false, + isColumnsNavHover: false, + projectId:'', + }), + actions: { + async setRoutesList(data: Array<string>) { + this.routesList = data; + }, + async setColumnsMenuHover(bool: Boolean) { + this.isColumnsMenuHover = bool; + }, + async setColumnsNavHover(bool: Boolean) { + this.isColumnsNavHover = bool; + }, + }, +}); diff --git a/src/stores/screenTheme.ts b/src/stores/screenTheme.ts new file mode 100644 index 0000000..13c3592 --- /dev/null +++ b/src/stores/screenTheme.ts @@ -0,0 +1,21 @@ +import { defineStore } from 'pinia'; +import { screenThemeState } from './interface'; + +/** + * 路由列表 + * @methods setRoutesList 设置路由数据 + * @methods setColumnsMenuHover 设置分栏布局菜单鼠标移入 boolean + * @methods setColumnsNavHover 设置分栏布局最左侧导航鼠标移入 boolean + */ +export const useScreenTheme = defineStore('screenTheme', { + state: (): screenThemeState => ({ + screenTheme:{ + isDark: true + } + }), + actions: { + async setScreenTheme(value: any) { + this.screenTheme.isDark = value; + } + }, +}); diff --git a/src/stores/tagsViewRoutes.ts b/src/stores/tagsViewRoutes.ts new file mode 100644 index 0000000..7a5e6f4 --- /dev/null +++ b/src/stores/tagsViewRoutes.ts @@ -0,0 +1,24 @@ +import { defineStore } from 'pinia'; +import { TagsViewRoutesState } from './interface'; +import { Session } from '/@/utils/storage'; + +/** + * TagsView 路由列表 + * @methods setTagsViewRoutes 设置 TagsView 路由列表 + * @methods setCurrenFullscreen 设置开启/关闭全屏时的 boolean 状态 + */ +export const useTagsViewRoutes = defineStore('tagsViewRoutes', { + state: (): TagsViewRoutesState => ({ + tagsViewRoutes: [], + isTagsViewCurrenFull: false, + }), + actions: { + async setTagsViewRoutes(data: Array<string>) { + this.tagsViewRoutes = data; + }, + setCurrenFullscreen(bool: Boolean) { + Session.set('isTagsViewCurrenFull', bool); + this.isTagsViewCurrenFull = bool; + }, + }, +}); diff --git a/src/stores/themeConfig.ts b/src/stores/themeConfig.ts new file mode 100644 index 0000000..fd74bd9 --- /dev/null +++ b/src/stores/themeConfig.ts @@ -0,0 +1,146 @@ +import { defineStore } from 'pinia'; +import { ThemeConfigStates, ThemeConfigState } from './interface'; + +/** + * 布局配置 + * 修复:https://gitee.com/lyt-top/vue-next-admin/issues/I567R1,感谢@lanbao123 + * 2020.05.28 by lyt 优化。开发时配置不生效问题 + * 修改配置时: + * 1、需要每次都清理 `window.localStorage` 浏览器永久缓存 + * 2、或者点击布局配置最底部 `一键恢复默认` 按钮即可看到效果 + */ +export const useThemeConfig = defineStore('themeConfig', { + state: (): ThemeConfigStates => ({ + themeConfig: { + // 是否开启布局配置抽屉 + isDrawer: false, + + /** + * 全局主题 + */ + // 默认 primary 主题颜色 + primary: '#409eff', + // 是否开启深色模式 + isIsDark: false, + + /** + * 菜单 / 顶栏 + * 注意:v1.0.17 版本去除设置布局切换,重置主题样式(initSetLayoutChange), + * 切换布局需手动设置样式,设置的样式自动同步各布局, + * 代码位置:/@/layout/navBars/breadcrumb/setings.vue + */ + // 默认顶栏导航背景颜色 + topBar: '#ffffff', + // 默认顶栏导航字体颜色 + topBarColor: '#606266', + // 是否开启顶栏背景颜色渐变 + isTopBarColorGradual: false, + // 默认菜单导航背景颜色 + menuBar: '#545c64', + // 默认菜单导航字体颜色 + menuBarColor: '#eaeaea', + // 是否开启菜单背景颜色渐变 + isMenuBarColorGradual: false, + // 默认分栏菜单背景颜色 + columnsMenuBar: '#545c64', + // 默认分栏菜单字体颜色 + columnsMenuBarColor: '#e6e6e6', + // 是否开启分栏菜单背景颜色渐变 + isColumnsMenuBarColorGradual: false, + + /** + * 界面设置 + */ + // 是否开启菜单水平折叠效果 + isCollapse: false, + // 是否开启菜单手风琴效果 + isUniqueOpened: false, + // 是否开启固定 Header + isFixedHeader: false, + // 初始化变量,用于更新菜单 el-scrollbar 的高度,请勿删除 + isFixedHeaderChange: false, + // 是否开启经典布局分割菜单(仅经典布局生效) + isClassicSplitMenu: false, + // 是否开启自动锁屏 + isLockScreen: false, + // 开启自动锁屏倒计时(s/秒) + lockScreenTime: 30, + + /** + * 界面显示 + */ + // 是否开启侧边栏 Logo + isShowLogo: false, + // 初始化变量,用于 el-scrollbar 的高度更新,请勿删除 + isShowLogoChange: false, + // 是否开启 Breadcrumb,强制经典、横向布局不显示 + isBreadcrumb: true, + // 是否开启 Tagsview + isTagsview: true, + // 是否开启 Breadcrumb 图标 + isBreadcrumbIcon: false, + // 是否开启 Tagsview 图标 + isTagsviewIcon: false, + // 是否开启 TagsView 缓存 + isCacheTagsView: false, + // 是否开启 TagsView 拖拽 + isSortableTagsView: true, + // 是否开启 TagsView 共用 + isShareTagsView: false, + // 是否开启 Footer 底部版权信息 + isFooter: false, + // 是否开启灰色模式 + isGrayscale: false, + // 是否开启色弱模式 + isInvert: false, + // 是否开启水印 + isWartermark: false, + // 水印文案 + wartermarkText: 'small@小柒', + + /** + * 其它设置 + */ + // Tagsview 风格:可选值"<tags-style-one|tags-style-four|tags-style-five>",默认 tags-style-five + // 定义的值与 `/src/layout/navBars/tagsView/tagsView.vue` 中的 class 同名 + tagsStyle: 'tags-style-five', + // 主页面切换动画:可选值"<slide-right|slide-left|opacitys>",默认 slide-right + animation: 'slide-right', + // 分栏高亮风格:可选值"<columns-round|columns-card>",默认 columns-round + columnsAsideStyle: 'columns-round', + // 分栏布局风格:可选值"<columns-horizontal|columns-vertical>",默认 columns-horizontal + columnsAsideLayout: 'columns-vertical', + + /** + * 布局切换 + * 注意:为了演示,切换布局时,颜色会被还原成默认,代码位置:/@/layout/navBars/breadcrumb/setings.vue + * 中的 `initSetLayoutChange(设置布局切换,重置主题样式)` 方法 + */ + // 布局切换:可选值"<defaults|classic|transverse|columns>",默认 defaults + layout: 'classic', + + /** + * 后端控制路由 + */ + // 是否开启后端控制路由 + isRequestRoutes: true, + + /** + * 全局网站标题 / 副标题 + */ + // 网站主标题(菜单导航、浏览器当前网页标题) + globalTitle: 'vue-next-admin', + // 网站副标题(登录页顶部文字) + globalViceTitle: 'vueNextAdmin', + // 默认初始语言,可选值"<zh-cn|en|zh-tw>",默认 zh-cn + globalI18n: 'zh-cn', + // 默认全局组件大小,可选值"<large|'default'|small>",默认 'large' + globalComponentSize: 'large' + } + }), + actions: { + setThemeConfig(data: ThemeConfigState) { + this.themeConfig = data; + } + } +}); diff --git a/src/stores/userInfo.ts b/src/stores/userInfo.ts new file mode 100644 index 0000000..edbe1ed --- /dev/null +++ b/src/stores/userInfo.ts @@ -0,0 +1,73 @@ +import { defineStore } from 'pinia'; +import Cookies from 'js-cookie'; +import { UserInfosStates } from './interface'; + +/** + * 用户信息 + * @methods setUserInfos 设置用户信息 + */ +export const useUserInfo = defineStore('userInfo', { + state: (): UserInfosStates => ({ + userInfos: { + userName: '', + photo: 'https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=317673774,2961727727&fm=26&gp=0.jpg', + time: 0, + roles: [], + authBtnList: [], + uid: '', + depId: null, + projectId: '', + dataList: [] + } + }), + persist:true, + actions: { + async setUserInfos(value: any) { + this.userInfos.userName = value.realName; + this.userInfos.uid = value.uid; + this.userInfos.roles = value.role; + this.userInfos.depId = value.depId + // const userName = Cookies.get('userName'); + // // 模拟数据 + // let defaultRoles: Array<string> = []; + // let defaultAuthBtnList: Array<string> = []; + // // admin 页面权限标识,对应路由 meta.roles,用于控制路由的显示/隐藏 + // let adminRoles: Array<string> = ['admin']; + // // admin 按钮权限标识 + // let adminAuthBtnList: Array<string> = ['btn.add', 'btn.del', 'btn.edit', 'btn.link']; + // // test 页面权限标识,对应路由 meta.roles,用于控制路由的显示/隐藏 + // let testRoles: Array<string> = ['common']; + // // test 按钮权限标识 + // let testAuthBtnList: Array<string> = ['btn.add', 'btn.link']; + // // 不同用户模拟不同的用户权限 + // if (userName === 'admin') { + // defaultRoles = adminRoles; + // defaultAuthBtnList = adminAuthBtnList; + // } else { + // defaultRoles = testRoles; + // defaultAuthBtnList = testAuthBtnList; + // } + // // 用户信息模拟数据 + // const userInfos = { + // userName: userName, + // photo: + // userName === 'admin' + // ? 'https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=1813762643,1914315241&fm=26&gp=0.jpg' + // : 'https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=317673774,2961727727&fm=26&gp=0.jpg', + // time: new Date().getTime(), + // roles: defaultRoles, + // authBtnList: defaultAuthBtnList, + // uid:'', + // projectId:'', + // }; + // // 存储用户信息到浏览器缓存 + // Session.set('userInfo', userInfos); + // + // if (Session.get('userInfo')) { + // this.userInfos = Session.get('userInfo'); + // } else { + // this.userInfos = userInfos; + // } + } + } +}); diff --git a/src/theme/app.scss b/src/theme/app.scss new file mode 100644 index 0000000..4c75296 --- /dev/null +++ b/src/theme/app.scss @@ -0,0 +1,281 @@ +/* 初始化样式 +------------------------------- */ +* { + margin: 0; + padding: 0; + box-sizing: border-box; + outline: none !important; +} + +:root { + --next-color-white: #ffffff; + --next-bg-main-color: #f8f8f8; + --next-bg-color: #f5f5ff; + --next-border-color-light: #f1f2f3; + --next-color-primary-lighter: #ecf5ff; + --next-color-success-lighter: #f0f9eb; + --next-color-warning-lighter: #fdf6ec; + --next-color-danger-lighter: #fef0f0; + --next-color-dark-hover: #0000001a; + --next-color-menu-hover: rgba(0, 0, 0, 0.2); + --next-color-user-hover: rgba(0, 0, 0, 0.04); + --next-color-seting-main: #e9eef3; + --next-color-seting-aside: #d3dce6; + --next-color-seting-header: #b3c0d1; +} + +html, +body, +#app { + margin: 0; + padding: 0; + width: 100%; + height: 100%; + font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, SimSun, sans-serif; + font-weight: 400; + -webkit-font-smoothing: antialiased; + -webkit-tap-highlight-color: transparent; + background-color: var(--next-bg-main-color); + font-size: 14px; + overflow: hidden; + position: relative; +} + +/* 主布局样式 +------------------------------- */ +.layout-container { + width: 100%; + height: 100%; + .layout-aside { + background: var(--next-bg-menuBar); + box-shadow: 2px 0 6px rgb(0 21 41 / 1%); + height: inherit; + position: relative; + z-index: 1; + display: flex; + flex-direction: column; + overflow-x: hidden !important; + .el-scrollbar__view { + overflow: hidden; + } + } + .layout-header { + padding: 0 !important; + } + .layout-main { + padding: 0 !important; + overflow: hidden; + width: 100%; + background-color: var(--next-bg-main-color); + } + .el-scrollbar { + width: 100%; + } + // 此字段多次用到,建议不删除,如需修改,请重写覆盖样式 + .layout-view-bg-white { + background: var(--el-color-white); + width: 100%; + height: 100%; + border-radius: 4px; + border: 1px solid var(--el-border-color-light, #ebeef5); + } + .layout-el-aside-br-color { + border-right: 1px solid var(--el-border-color-light, #ebeef5); + } + // pc端左侧导航样式 + .layout-aside-pc-220 { + width: 220px !important; + transition: width 0.3s ease; + } + .layout-aside-pc-64 { + width: 64px !important; + transition: width 0.3s ease; + } + .layout-aside-pc-1 { + width: 1px !important; + transition: width 0.3s ease; + } + // 手机端左侧导航样式 + .layout-aside-mobile { + position: fixed; + top: 0; + left: -220px; + width: 220px; + z-index: 9999999; + } + .layout-aside-mobile-close { + left: -220px; + transition: all 0.3s cubic-bezier(0.39, 0.58, 0.57, 1); + } + .layout-aside-mobile-open { + left: 0; + transition: all 0.3s cubic-bezier(0.22, 0.61, 0.36, 1); + } + .layout-aside-mobile-mode { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + height: 100%; + background-color: rgba(0, 0, 0, 0.5); + z-index: 9999998; + animation: error-img 0.3s; + } + .layout-scrollbar { + @extend .el-scrollbar; + padding: 15px; + } + .layout-mian-height-50 { + height: calc(100vh - 50px); + } + .layout-columns-warp { + flex: 1; + display: flex; + overflow: hidden; + } + .layout-hide { + display: none; + } +} + +/* element plus 全局样式 +------------------------------- */ +.layout-breadcrumb-seting { + .el-divider { + background-color: rgb(230, 230, 230); + } +} + +/* nprogress 进度条跟随主题颜色 +------------------------------- */ +#nprogress { + .bar { + background: var(--el-color-primary) !important; + z-index: 9999999 !important; + } +} + +/* flex 弹性布局 +------------------------------- */ +.flex { + display: flex; +} +.flex-auto { + flex: 1; + overflow: hidden; +} +.flex-center { + @extend .flex; + flex-direction: column; + width: 100%; + overflow: hidden; +} +.flex-margin { + margin: auto; +} +.flex-warp { + display: flex; + flex-wrap: wrap; + align-content: flex-start; + margin: 0 -5px; + .flex-warp-item { + padding: 5px; + .flex-warp-item-box { + width: 100%; + height: 100%; + } + } +} + +/* cursor 鼠标形状 +------------------------------- */ +// 默认 +.cursor-default { + cursor: default !important; +} +// 帮助 +.cursor-help { + cursor: help !important; +} +// 手指 +.cursor-pointer { + cursor: pointer !important; +} +// 移动 +.cursor-move { + cursor: move !important; +} + +/* 宽高 100% +------------------------------- */ +.w100 { + width: 100% !important; +} +.h100 { + height: 100% !important; +} +.vh100 { + height: 100vh !important; +} +.max100vh { + max-height: 100vh !important; +} +.min100vh { + min-height: 100vh !important; +} + +/* 颜色值 +------------------------------- */ +.color-primary { + color: var(--el-color-primary); +} +.color-success { + color: var(--el-color-success); +} +.color-warning { + color: var(--el-color-warning); +} +.color-danger { + color: var(--el-color-danger); +} +.color-info { + color: var(--el-color-info); +} + +/* 字体大小全局样式 +------------------------------- */ +@for $i from 10 through 32 { + .font#{$i} { + font-size: #{$i}px !important; + } +} + +/* 外边距、内边距全局样式 +------------------------------- */ +@for $i from 1 through 35 { + .mt#{$i} { + margin-top: #{$i}px !important; + } + .mr#{$i} { + margin-right: #{$i}px !important; + } + .mb#{$i} { + margin-bottom: #{$i}px !important; + } + .ml#{$i} { + margin-left: #{$i}px !important; + } + .pt#{$i} { + padding-top: #{$i}px !important; + } + .pr#{$i} { + padding-right: #{$i}px !important; + } + .pb#{$i} { + padding-bottom: #{$i}px !important; + } + .pl#{$i} { + padding-left: #{$i}px !important; + } +} diff --git a/src/theme/bigScreen.css b/src/theme/bigScreen.css new file mode 100644 index 0000000..acbd111 --- /dev/null +++ b/src/theme/bigScreen.css @@ -0,0 +1,22 @@ +html{font-size:12px; font-size:62.5%; /* 10÷16=62.5% */} +@media screen and (max-width: 1920px) { + html { font-size: 100%;} +} +@media screen and (max-width: 1336px) { + html { font-size: 80%;} +} +@media screen and (max-width: 1200px) { + html { font-size: 62.5%;} +} +@media screen and (max-width: 1000px) { + html { font-size: 10px;} +} +@media screen and (max-width: 800px) { + html { font-size: 8px;} +} +@media screen and (max-width: 700px) { + html { font-size: 7px;} +} +@media screen and (max-width: 600px) { + html { font-size: 6px;} +} \ No newline at end of file diff --git a/src/theme/common/transition.scss b/src/theme/common/transition.scss new file mode 100644 index 0000000..a03a7bb --- /dev/null +++ b/src/theme/common/transition.scss @@ -0,0 +1,94 @@ +/* 页面切换动画 +------------------------------- */ +.slide-right-enter-active, +.slide-right-leave-active, +.slide-left-enter-active, +.slide-left-leave-active { + will-change: transform; + transition: all 0.3s ease; +} +// slide-right +.slide-right-enter-from { + opacity: 0; + transform: translateX(-20px); +} +.slide-right-leave-to { + opacity: 0; + transform: translateX(20px); +} +// slide-left +.slide-left-enter-from { + @extend .slide-right-leave-to; +} +.slide-left-leave-to { + @extend .slide-right-enter-from; +} +// opacitys +.opacitys-enter-active, +.opacitys-leave-active { + will-change: transform; + transition: all 0.3s ease; +} +.opacitys-enter-from, +.opacitys-leave-to { + opacity: 0; +} + +/* Breadcrumb 面包屑过渡动画 +------------------------------- */ +.breadcrumb-enter-active, +.breadcrumb-leave-active { + transition: all 0.5s ease; +} +.breadcrumb-enter-from, +.breadcrumb-leave-active { + opacity: 0; + transform: translateX(20px); +} +.breadcrumb-leave-active { + position: absolute; + z-index: -1; +} + +/* logo 过渡动画 +------------------------------- */ +@keyframes logoAnimation { + 0% { + transform: scale(0); + } + 80% { + transform: scale(1.2); + } + 100% { + transform: scale(1); + } +} + +/* 404、401 过渡动画 +------------------------------- */ +@keyframes error-num { + 0% { + transform: translateY(60px); + opacity: 0; + } + 100% { + transform: translateY(0); + opacity: 1; + } +} +@keyframes error-img { + 0% { + opacity: 0; + } + 100% { + opacity: 1; + } +} +@keyframes error-img-two { + 0% { + opacity: 1; + } + 100% { + opacity: 0; + } +} diff --git a/src/theme/dark.scss b/src/theme/dark.scss new file mode 100644 index 0000000..6a2f5e3 --- /dev/null +++ b/src/theme/dark.scss @@ -0,0 +1,236 @@ +/* 深色模式样式 +------------------------------- */ +[data-theme='dark'] { + // 变量(自定义时,只需修改这里的值) + --next-bg-main: #1f1f1f; + --next-color-white: #ffffff; + --next-color-disabled: #191919; + --next-color-bar: #dadada; + --next-color-primary: #303030; + --next-border-color: #424242; + --next-border-black: #333333; + --next-border-columns: #2a2a2a; + --next-color-seting: #505050; + --next-text-color-regular: #9b9da1; + --next-text-color-placeholder: #7a7a7a; + --next-color-hover: #3c3c3c; + --next-color-hover-rgba: rgba(0, 0, 0, 0.3); + + // root + --next-bg-main-color: var(--next-bg-main) !important; + --next-bg-topBar: var(--next-color-disabled) !important; + --next-bg-topBarColor: var(--next-color-bar) !important; + --next-bg-menuBar: var(--next-color-disabled) !important; + --next-bg-menuBarColor: var(--next-color-bar) !important; + --next-bg-columnsMenuBar: var(--next-color-disabled) !important; + --next-bg-columnsMenuBarColor: var(--next-color-bar) !important; + --next-border-color-light: var(--next-border-black) !important; + --next-color-primary-lighter: var(--next-color-primary) !important; + --next-color-success-lighter: var(--next-color-primary) !important; + --next-color-warning-lighter: var(--next-color-primary) !important; + --next-color-danger-lighter: var(--next-color-primary) !important; + --next-bg-color: var(--next-color-primary) !important; + --next-color-dark-hover: var(--next-color-hover) !important; + --next-color-menu-hover: var(--next-color-hover-rgba) !important; + --next-color-user-hover: var(--next-color-hover-rgba) !important; + --next-color-seting-main: var(--next-color-seting) !important; + --next-color-seting-aside: var(--next-color-hover) !important; + --next-color-seting-header: var(--next-color-primary) !important; + + // element plus + --el-color-white: var(--next-color-disabled) !important; + --el-text-color-primary: var(--next-color-bar) !important; + --el-border-color: var(--next-border-black) !important; + --el-border-color-light: var(--next-border-black) !important; + --el-border-color-lighter: var(--next-border-black) !important; + --el-border-color-extra-light: var(--el-color-primary-light-8) !important; + --el-text-color-regular: var(--next-text-color-regular) !important; + --el-bg-color: var(--next-color-disabled) !important; + --el-color-primary-light-9: var(--next-color-hover) !important; + --el-text-color-disabled: var(--next-text-color-placeholder) !important; + --el-text-color-disabled-base: var(--el-color-primary) !important; + --el-text-color-placeholder: var(--next-text-color-placeholder) !important; + --el-disabled-bg-color: var(--next-color-disabled) !important; + --el-fill-base: var(--next-color-white) !important; + --el-fill-colo: var(--next-color-hover-rgba) !important; + --el-fill-color: var(--next-color-hover-rgba) !important; + --el-fill-color-blank: var(--next-color-disabled) !important; + --el-fill-color-light: var(--next-color-hover-rgba) !important; + --el-bg-color-overlay: var(--el-color-primary-light-9) !important; + --el-mask-color: rgb(42 42 42 / 80%); + + // button + .el-button { + &:hover { + border-color: var(--next-border-color) !important; + } + } + .el-button--primary, + .el-button--info, + .el-button--danger, + .el-button--success, + .el-button--warning { + --el-button-text-color: var(--next-color-white) !important; + --el-button-hover-text-color: var(--next-color-white) !important; + --el-button-disabled-text-color: var(--next-color-white) !important; + &:hover { + border-color: var(--el-button-hover-border-color, var(--el-button-hover-bg-color)) !important; + } + } + + // drawer + .el-divider__text { + background-color: var(--el-color-white) !important; + } + .el-drawer { + border-left: 1px solid var(--next-border-color-light) !important; + } + + // tabs + .el-tabs--border-card { + background-color: var(--el-color-white) !important; + } + .el-tabs--border-card > .el-tabs__header .el-tabs__item.is-active { + background: var(--next-color-primary-lighter); + } + + // alert / notice-bar + .home-card-item { + border: 1px solid var(--next-border-color-light) !important; + } + .el-alert, + .notice-bar { + border: 1px solid var(--next-border-color) !important; + background-color: var(--next-color-disabled) !important; + } + + // homeMenu + .layout-aside { + border-right: 1px solid var(--next-border-color-light) !important; + } + + // colorPicker + .el-color-picker__mask { + background: unset !important; + } + .el-color-picker__trigger { + border: 1px solid var(--next-border-color-light) !important; + } + + // popper / dropdown + .el-popper { + border: 1px solid var(--next-border-color) !important; + color: var(--el-text-color-primary) !important; + .el-popper__arrow:before { + background: var(--el-color-white) !important; + border: 1px solid var(--next-border-color); + } + a { + color: var(--el-text-color-primary) !important; + } + } + .el-popper, + .el-dropdown-menu { + background: var(--el-color-white) !important; + } + .el-dropdown-menu__item:hover:not(.is-disabled) { + background: var(--el-bg-color) !important; + } + .el-dropdown-menu__item.is-disabled { + font-weight: 700 !important; + } + + // input + .el-input-group__append, + .el-input-group__prepend { + border: var(--el-input-border) !important; + border-right: none !important; + background: var(--next-color-disabled) !important; + border-left: 0 !important; + } + .el-input-number__decrease, + .el-input-number__increase { + background: var(--next-color-disabled) !important; + } + + // tag + .el-select .el-select__tags .el-tag { + background-color: var(--next-bg-color) !important; + } + + // pagination + .el-pagination.is-background .el-pager li:not(.disabled).active { + color: var(--next-color-white) !important; + } + .el-pagination.is-background .btn-next, + .el-pagination.is-background .btn-prev, + .el-pagination.is-background .el-pager li { + background-color: var(--next-bg-color); + } + + // radio + .el-radio-button:not(.is-active) .el-radio-button__inner { + border: 1px solid var(--next-border-color-light) !important; + border-left: 0 !important; + } + .el-radio-button.is-active .el-radio-button__inner { + color: var(--next-color-white) !important; + } + + // countup + .countup-card-item-flex { + color: var(--el-text-color-primary) !important; + } + + // editor + .editor-container { + .w-e-toolbar { + background: var(--el-color-white) !important; + border: 1px solid var(--next-border-color-light) !important; + .w-e-menu:hover { + background: var(--next-color-user-hover) !important; + i { + color: var(--el-text-color-primary) !important; + } + } + } + .w-e-text-container { + border: 1px solid var(--next-border-color-light) !important; + border-top: none !important; + .w-e-text { + background: var(--el-color-white) !important; + } + } + } + + // date-picker + .el-picker-panel { + background: var(--el-color-white) !important; + } + + // dialog + .el-dialog { + border: 1px solid var(--el-border-color-lighter); + .el-dialog__header { + color: var(--el-text-color-primary) !important; + } + } + + // columns + .layout-columns-aside ul .layout-columns-active { + color: var(--next-color-white) !important; + } + .layout-columns-aside { + border-right: 1px solid var(--next-border-columns); + } + + // tagsView + .tags-style-one { + .is-active { + color: var(--el-text-color-primary) !important; + } + .layout-navbars-tagsview-ul-li:hover { + border-color: var(--el-border-color-lighter) !important; + } + } +} diff --git a/src/theme/element.scss b/src/theme/element.scss new file mode 100644 index 0000000..6e71c98 --- /dev/null +++ b/src/theme/element.scss @@ -0,0 +1,282 @@ +@import 'mixins/index.scss'; + +/* Button 按钮 +------------------------------- */ +// 第三方字体图标大小 +.el-button i.el-icon, +.el-button i.iconfont, +.el-button i.fa, +.el-button--default i.iconfont, +.el-button--default i.fa { + font-size: 14px !important; + //margin-right: 5px; +} +.el-button--small i.iconfont, +.el-button--small i.fa { + font-size: 12px !important; + margin-right: 5px; +} + +/* Input 输入框、InputNumber 计数器 +------------------------------- */ +.el-input { + height: 100%; +} +// 菜单搜索 +.el-autocomplete-suggestion__wrap { + max-height: 280px !important; +} + +/* Form 表单 +------------------------------- */ +.el-form { + .el-form-item:last-of-type { + margin-bottom: 0 !important; + } +} + +/* Alert 警告 +------------------------------- */ +.el-alert { + border: 1px solid; +} +.el-alert__title { + word-break: break-all; +} + +/* Message 消息提示 +------------------------------- */ +.el-message { + min-width: unset !important; + padding: 15px !important; + box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.02); +} + +/* NavMenu 导航菜单 +------------------------------- */ +// 鼠标 hover 时颜色 +.el-menu-hover-bg-color { + background-color: var(--next-color-menu-hover) !important; +} +// 默认样式修改 +.el-menu { + border-right: none !important; + width: 220px; +} +.el-menu-item { + height: 56px !important; + line-height: 56px !important; +} +.el-menu-item, +.el-sub-menu__title { + color: var(--next-bg-menuBarColor); +} +// 修复点击左侧菜单折叠再展开时,宽度不跟随问题 +.el-menu--collapse { + width: 64px !important; +} +// 外部链接时 +.el-menu-item a, +.el-menu-item a:hover, +.el-menu-item i, +.el-sub-menu__title i { + color: inherit; + text-decoration: none; +} +// 第三方图标字体间距/大小设置 +.el-menu-item .iconfont, +.el-sub-menu .iconfont, +.el-menu-item .fa, +.el-sub-menu .fa { + @include generalIcon; +} +// 水平菜单、横向菜单高亮 背景色,鼠标 hover 时,有子级菜单的背景色 +.el-menu-item.is-active, +.el-sub-menu.is-active .el-sub-menu__title, +.el-sub-menu:not(.is-opened):hover .el-sub-menu__title { + @extend .el-menu-hover-bg-color; +} +.el-sub-menu.is-active.is-opened .el-sub-menu__title { + background-color: unset !important; +} +// 子级菜单背景颜色 +// .el-homeMenu--inline { +// background: var(--next-bg-menuBar-light-1); +// } +// 水平菜单、横向菜单折叠 a 标签 +.el-popper.is-dark a { + color: var(--el-color-white) !important; + text-decoration: none; +} +// 水平菜单、横向菜单折叠背景色 +.el-popper.is-pure.is-light { + // 水平菜单 + .el-menu--vertical { + background: var(--next-bg-menuBar); + .el-sub-menu.is-active .el-sub-menu__title { + color: var(--el-menu-active-color); + } + .el-popper.is-pure.is-light { + .el-menu--vertical { + .el-sub-menu .el-sub-menu__title { + background-color: unset !important; + color: var(--next-bg-menuBarColor); + } + .el-sub-menu.is-active .el-sub-menu__title { + color: var(--el-menu-active-color); + } + } + } + } + // 横向菜单 + .el-menu--horizontal { + background: var(--next-bg-topBar); + .el-menu-item, + .el-sub-menu { + height: 50px !important; + line-height: 50px !important; + color: var(--next-bg-topBarColor); + .el-sub-menu__title { + height: 50px !important; + line-height: 50px !important; + color: var(--next-bg-topBarColor); + } + .el-popper.is-pure.is-light { + .el-menu--horizontal { + .el-sub-menu .el-sub-menu__title { + background-color: unset !important; + color: var(--next-bg-topBarColor); + } + .el-sub-menu.is-active .el-sub-menu__title { + color: var(--el-menu-active-color); + } + } + } + } + .el-menu-item.is-active, + .el-sub-menu.is-active .el-sub-menu__title { + color: var(--el-menu-active-color); + } + } +} +// 横向菜单(经典、横向)布局 +.el-menu.el-menu--horizontal { + border-bottom: none !important; + width: 100% !important; + .el-menu-item, + .el-sub-menu__title { + height: 50px !important; + color: var(--next-bg-topBarColor); + } + .el-menu-item:not(.is-active):hover, + .el-sub-menu:not(.is-active):hover .el-sub-menu__title { + color: var(--next-bg-topBarColor); + } +} + +/* Tabs 标签页 +------------------------------- */ +.el-tabs__nav-wrap::after { + height: 1px !important; +} + +/* Dropdown 下拉菜单 +------------------------------- */ +.el-dropdown-menu { + list-style: none !important; /*修复 Dropdown 下拉菜单样式问题 2022.03.04*/ +} +.el-dropdown-menu .el-dropdown-menu__item { + white-space: nowrap; + &:not(.is-disabled):hover { + background-color: var(--el-dropdown-menuItem-hover-fill); + color: var(--el-dropdown-menuItem-hover-color); + } +} + +/* Steps 步骤条 +------------------------------- */ +.el-step__icon-inner { + font-size: 30px !important; + font-weight: 400 !important; +} +.el-step__title { + font-size: 14px; +} + +/* Dialog 对话框 +------------------------------- */ +.el-overlay { + overflow: hidden; + .el-overlay-dialog { + display: flex; + align-items: center; + justify-content: center; + position: unset !important; + width: 100%; + height: 100%; + .el-dialog { + margin: 0 auto !important; + position: absolute; + .el-dialog__body { + padding: 20px !important; + } + } + } +} +.el-dialog__body { + max-height: calc(90vh - 111px) !important; + overflow-y: auto; + overflow-x: hidden; +} + +/* Card 卡片 +------------------------------- */ +.el-card__header { + padding: 15px 20px; +} + +/* Table 表格 element plus 2.2.0 版本 +------------------------------- */ +.el-table { + .el-button.is-text { + padding: 0; + } +} + +/* scrollbar +------------------------------- */ +.el-scrollbar__bar { + z-index: 4; +} +.el-scrollbar__wrap { + max-height: 100%; /*防止页面切换时,滚动条高度不变的问题(滚动条高度非滚动条滚动高度)*/ +} +.el-select-dropdown .el-scrollbar__wrap { + overflow-x: scroll !important; +} +.el-select-dropdown__wrap { + max-height: 274px !important; /*修复Select 选择器高度问题*/ +} +.el-cascader-menu__wrap.el-scrollbar__wrap { + height: 204px !important; /*修复Cascader 级联选择器高度问题*/ +} + +/* Drawer 抽屉 +------------------------------- */ +.el-drawer { + --el-drawer-padding-primary: unset !important; + .el-drawer__header { + padding: 0 15px !important; + height: 50px; + display: flex; + align-items: center; + margin-bottom: 0 !important; + border-bottom: 1px solid var(--el-border-color); + color: var(--el-text-color-primary); + } + .el-drawer__body { + width: 100%; + height: 100%; + overflow: auto; + } +} diff --git a/src/theme/iconSelector.scss b/src/theme/iconSelector.scss new file mode 100644 index 0000000..970201e --- /dev/null +++ b/src/theme/iconSelector.scss @@ -0,0 +1,70 @@ +/* Popover 弹出框(图标选择器) +------------------------------- */ +.icon-selector-popper { + padding: 0 !important; + .icon-selector-warp { + height: 260px; + overflow: hidden; + .icon-selector-warp-title { + height: 40px; + line-height: 40px; + padding: 0 15px; + .icon-selector-warp-title-tab { + span { + cursor: pointer; + &:hover { + color: var(--el-color-primary); + text-decoration: underline; + } + } + .span-active { + color: var(--el-color-primary); + text-decoration: underline; + } + } + } + .icon-selector-warp-row { + height: 230px; + overflow: hidden; + border-top: 1px solid var(--el-border-color); + .el-row { + padding: 15px; + } + .el-scrollbar__bar.is-horizontal { + display: none; + } + .icon-selector-warp-item { + display: flex; + border: 1px solid var(--el-border-color); + padding: 5px; + border-radius: 5px; + margin-bottom: 10px; + .icon-selector-warp-item-value { + i { + font-size: 20px; + color: var(--el-text-color-regular); + } + } + &:hover { + cursor: pointer; + background-color: var(--el-color-primary-light-9); + border: 1px solid var(--el-color-primary-light-5); + .icon-selector-warp-item-value { + i { + color: var(--el-color-primary); + } + } + } + } + .icon-selector-active { + background-color: var(--el-color-primary-light-9); + border: 1px solid var(--el-color-primary-light-5); + .icon-selector-warp-item-value { + i { + color: var(--el-color-primary); + } + } + } + } + } +} diff --git a/src/theme/index.scss b/src/theme/index.scss new file mode 100644 index 0000000..c574e00 --- /dev/null +++ b/src/theme/index.scss @@ -0,0 +1,8 @@ +@import './app.scss'; +@import 'common/transition.scss'; +@import './other.scss'; +@import './element.scss'; +@import './iconSelector.scss'; +@import './media/media.scss'; +@import './waves.scss'; +@import './dark.scss'; diff --git a/src/theme/loading.scss b/src/theme/loading.scss new file mode 100644 index 0000000..c28c7b9 --- /dev/null +++ b/src/theme/loading.scss @@ -0,0 +1,51 @@ +.loading-next { + width: 100%; + height: 100%; +} +.loading-next .loading-next-box { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); +} +.loading-next .loading-next-box-warp { + width: 80px; + height: 80px; +} +.loading-next .loading-next-box-warp .loading-next-box-item { + width: 33.333333%; + height: 33.333333%; + background: var(--el-color-primary); + float: left; + animation: loading-next-animation 1.2s infinite ease; + border-radius: 1px; +} +.loading-next .loading-next-box-warp .loading-next-box-item:nth-child(7) { + animation-delay: 0s; +} +.loading-next .loading-next-box-warp .loading-next-box-item:nth-child(4), +.loading-next .loading-next-box-warp .loading-next-box-item:nth-child(8) { + animation-delay: 0.1s; +} +.loading-next .loading-next-box-warp .loading-next-box-item:nth-child(1), +.loading-next .loading-next-box-warp .loading-next-box-item:nth-child(5), +.loading-next .loading-next-box-warp .loading-next-box-item:nth-child(9) { + animation-delay: 0.2s; +} +.loading-next .loading-next-box-warp .loading-next-box-item:nth-child(2), +.loading-next .loading-next-box-warp .loading-next-box-item:nth-child(6) { + animation-delay: 0.3s; +} +.loading-next .loading-next-box-warp .loading-next-box-item:nth-child(3) { + animation-delay: 0.4s; +} +@keyframes loading-next-animation { + 0%, + 70%, + 100% { + transform: scale3D(1, 1, 1); + } + 35% { + transform: scale3D(0, 0, 1); + } +} diff --git a/src/theme/media/chart.scss b/src/theme/media/chart.scss new file mode 100644 index 0000000..8485e39 --- /dev/null +++ b/src/theme/media/chart.scss @@ -0,0 +1,94 @@ +@import './index.scss'; + +/* 页面宽度小于768px +------------------------------- */ +@media screen and (max-width: $sm) { + .big-data-down-left { + width: 100% !important; + flex-direction: unset !important; + flex-wrap: wrap; + .flex-warp-item { + min-height: 196.24px; + padding: 0 7.5px 15px 15px !important; + .flex-warp-item-box { + border: none !important; + border-bottom: 1px solid #ebeef5 !important; + } + } + } + .big-data-down-center { + width: 100% !important; + .big-data-down-center-one, + .big-data-down-center-two { + min-height: 196.24px; + padding-left: 15px !important; + .big-data-down-center-one-content { + border: none !important; + border-bottom: 1px solid #ebeef5 !important; + } + .flex-warp-item-box { + @extend .big-data-down-center-one-content; + } + } + } + .big-data-down-right { + .flex-warp-item { + .flex-warp-item-box { + border: none !important; + border-bottom: 1px solid #ebeef5 !important; + } + &:nth-of-type(2) { + padding-left: 15px !important; + } + &:last-of-type { + .flex-warp-item-box { + border: none !important; + } + } + } + } +} + +/* 页面宽度大于768px小于1200px +------------------------------- */ +@media screen and (min-width: $sm) and (max-width: $lg) { + .chart-warp-bottom { + .big-data-down-left { + width: 50% !important; + } + .big-data-down-center { + width: 50% !important; + } + .big-data-down-right { + .flex-warp-item { + width: 50% !important; + &:nth-of-type(2) { + padding-left: 7.5px !important; + } + } + } + } +} + +/* 页面宽度小于1200px +------------------------------- */ +@media screen and (max-width: $lg) { + .chart-warp-top { + .up-left { + display: none; + } + } + .chart-warp-bottom { + overflow-y: auto !important; + flex-wrap: wrap; + .big-data-down-right { + width: 100% !important; + flex-direction: unset !important; + flex-wrap: wrap; + .flex-warp-item { + min-height: 196.24px; + padding: 0 7.5px 15px 15px !important; + } + } + } +} diff --git a/src/theme/media/cityLinkage.scss b/src/theme/media/cityLinkage.scss new file mode 100644 index 0000000..1394156 --- /dev/null +++ b/src/theme/media/cityLinkage.scss @@ -0,0 +1,10 @@ +@import './index.scss'; + +/* 页面宽度小于576px +------------------------------- */ +@media screen and (max-width: $xs) { + .el-cascader__dropdown.el-popper { + overflow: auto; + max-width: 100%; + } +} diff --git a/src/theme/media/date.scss b/src/theme/media/date.scss new file mode 100644 index 0000000..1a50397 --- /dev/null +++ b/src/theme/media/date.scss @@ -0,0 +1,25 @@ +@import './index.scss'; + +/* 页面宽度小于768px +------------------------------- */ +@media screen and (max-width: $sm) { + // 时间选择器适配 + .el-date-range-picker { + width: 100vw; + .el-picker-panel__body { + min-width: 100%; + .el-date-range-picker__content { + .el-date-range-picker__header div { + margin-left: 22px; + margin-right: 0px; + } + & + .el-date-range-picker__content { + .el-date-range-picker__header div { + margin-left: 0px; + margin-right: 22px; + } + } + } + } + } +} diff --git a/src/theme/media/dialog.scss b/src/theme/media/dialog.scss new file mode 100644 index 0000000..023ccae --- /dev/null +++ b/src/theme/media/dialog.scss @@ -0,0 +1,12 @@ +@import './index.scss'; + +/* 页面宽度小于800px +------------------------------- */ +@media screen and (max-width: 800px) { + .el-dialog { + width: 90% !important; + } + .el-dialog.is-fullscreen { + width: 100% !important; + } +} diff --git a/src/theme/media/error.scss b/src/theme/media/error.scss new file mode 100644 index 0000000..f35015f --- /dev/null +++ b/src/theme/media/error.scss @@ -0,0 +1,45 @@ +@import './index.scss'; + +/* 页面宽度小于768px +------------------------------- */ +@media screen and (max-width: $sm) { + .error { + .error-flex { + flex-direction: column-reverse !important; + height: auto !important; + width: 100% !important; + } + .right, + .left { + flex: unset !important; + display: flex !important; + } + .left-item { + margin: auto !important; + } + .right img { + max-width: 450px !important; + @extend .left-item; + } + } +} + +/* 页面宽度大于768px小于992px +------------------------------- */ +@media screen and (min-width: $sm) and (max-width: $md) { + .error { + .error-flex { + padding-left: 30px !important; + } + } +} + +/* 页面宽度小于1200px +------------------------------- */ +@media screen and (max-width: $lg) { + .error { + .error-flex { + padding: 0 30px; + } + } +} diff --git a/src/theme/media/form.scss b/src/theme/media/form.scss new file mode 100644 index 0000000..098300b --- /dev/null +++ b/src/theme/media/form.scss @@ -0,0 +1,16 @@ +@import './index.scss'; + +/* 页面宽度小于576px +------------------------------- */ +@media screen and (max-width: $xs) { + .el-form-item__label { + width: 100% !important; + text-align: left !important; + } + .el-form-item__content { + margin-left: 0 !important; + } + .el-form-item { + display: unset !important; + } +} diff --git a/src/theme/media/home.scss b/src/theme/media/home.scss new file mode 100644 index 0000000..5a2417e --- /dev/null +++ b/src/theme/media/home.scss @@ -0,0 +1,23 @@ +@import './index.scss'; + +/* 页面宽度小于768px +------------------------------- */ +@media screen and (max-width: $sm) { + .home-media, + .home-media-sm { + margin-top: 15px; + } +} + +/* 页面宽度小于1200px +------------------------------- */ +@media screen and (max-width: $lg) { + .home-media-lg { + margin-top: 15px; + } + .home-monitor { + .flex-warp-item { + width: 33.33% !important; + } + } +} diff --git a/src/theme/media/index.scss b/src/theme/media/index.scss new file mode 100644 index 0000000..4761c0c --- /dev/null +++ b/src/theme/media/index.scss @@ -0,0 +1,15 @@ +/* 栅格布局(媒体查询变量) +* https://developer.mozilla.org/zh-CN/docs/Learn/CSS/CSS_layout/Media_queries +* $us ≥376px 响应式栅格 +* $xs ≥576px 响应式栅格 +* $sm ≥768px 响应式栅格 +* $md ≥992px 响应式栅格 +* $lg ≥1200px 响应式栅格 +* $xl ≥1920px 响应式栅格 +------------------------------- */ +$us: 376px; +$xs: 576px; +$sm: 768px; +$md: 992px; +$lg: 1200px; +$xl: 1920px; diff --git a/src/theme/media/layout.scss b/src/theme/media/layout.scss new file mode 100644 index 0000000..77cbec0 --- /dev/null +++ b/src/theme/media/layout.scss @@ -0,0 +1,55 @@ +@import './index.scss'; + +/* 页面宽度小于576px +------------------------------- */ +@media screen and (max-width: $xs) { + // MessageBox 弹框 + .el-message-box { + width: 80% !important; + } +} + +/* 页面宽度小于768px +------------------------------- */ +@media screen and (max-width: $sm) { + // Breadcrumb 面包屑 + .layout-navbars-breadcrumb-hide { + display: none; + } + // 外链视图 + .layout-view-link { + a { + max-width: 80%; + text-align: center; + } + } + // 菜单搜索 + .layout-search-dialog { + .el-autocomplete { + width: 80% !important; + } + } +} + +/* 页面宽度小于1000px +------------------------------- */ +@media screen and (max-width: 1000px) { + // 布局配置 + .layout-drawer-content-flex { + position: relative; + &::after { + content: '手机版不支持切换布局'; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1; + text-align: center; + height: 140px; + line-height: 140px; + background: rgba(255, 255, 255, 0.9); + color: #666666; + } + } +} diff --git a/src/theme/media/login.scss b/src/theme/media/login.scss new file mode 100644 index 0000000..41a0159 --- /dev/null +++ b/src/theme/media/login.scss @@ -0,0 +1,63 @@ +@import './index.scss'; + +/* 页面宽度小于992px +------------------------------- */ +@media screen and (max-width: $lg) { + .login-container { + .login-icon-group { + &::before { + content: ''; + height: 70% !important; + transition: all 0.3s ease; + } + &::after { + content: ''; + width: 100px !important; + height: 200px !important; + transition: all 0.3s ease; + } + } + } +} + +/* 页面宽度小于992px +------------------------------- */ +@media screen and (max-width: $md) { + .login-content { + right: unset !important; + left: 50% !important; + transform: translate(-50%, -50%) translate3d(0, 0, 0) !important; + } +} + +/* 页面宽度小于576px +------------------------------- */ +@media screen and (max-width: $xs) { + .login-container { + .login-icon-group { + display: none !important; + } + .login-content { + width: 100% !important; + height: 100% !important; + padding: 20px 0 !important; + border-radius: 0 !important; + box-shadow: unset !important; + border: none !important; + } + .el-form-item { + display: flex !important; + } + } +} + +/* 页面宽度小于375px +------------------------------- */ +@media screen and (max-width: $us) { + .login-container { + .login-content-title { + font-size: 18px !important; + transition: all 0.3s ease; + } + } +} diff --git a/src/theme/media/media.scss b/src/theme/media/media.scss new file mode 100644 index 0000000..bed1c35 --- /dev/null +++ b/src/theme/media/media.scss @@ -0,0 +1,13 @@ +@import './login.scss'; +@import './error.scss'; +@import './layout.scss'; +@import './personal.scss'; +@import './tagsView.scss'; +@import './home.scss'; +@import './chart.scss'; +@import './form.scss'; +@import './scrollbar.scss'; +@import './pagination.scss'; +@import './dialog.scss'; +@import './cityLinkage.scss'; +@import './date.scss'; diff --git a/src/theme/media/pagination.scss b/src/theme/media/pagination.scss new file mode 100644 index 0000000..400ebaa --- /dev/null +++ b/src/theme/media/pagination.scss @@ -0,0 +1,15 @@ +@import './index.scss'; + +/* 页面宽度小于576px +------------------------------- */ +@media screen and (max-width: $xs) { + .el-pager, + .el-pagination__jump { + display: none !important; + } +} + +// 默认居中对齐 +.el-pagination { + text-align: center !important; +} diff --git a/src/theme/media/personal.scss b/src/theme/media/personal.scss new file mode 100644 index 0000000..7ec0d4a --- /dev/null +++ b/src/theme/media/personal.scss @@ -0,0 +1,16 @@ +@import './index.scss'; + +/* 页面宽度小于768px +------------------------------- */ +@media screen and (max-width: $sm) { + .personal-info { + padding-left: 0 !important; + margin-top: 15px; + } + .personal-recommend-col { + margin-bottom: 15px; + &:last-of-type { + margin-bottom: 0; + } + } +} diff --git a/src/theme/media/scrollbar.scss b/src/theme/media/scrollbar.scss new file mode 100644 index 0000000..968a79d --- /dev/null +++ b/src/theme/media/scrollbar.scss @@ -0,0 +1,56 @@ +@import './index.scss'; + +/* 页面宽度小于768px +------------------------------- */ +@media screen and (max-width: $sm) { + // 滚动条的宽度 + ::-webkit-scrollbar { + width: 3px !important; + height: 3px !important; + } + ::-webkit-scrollbar-track-piece { + background-color: var(--next-bg-main-color); + } + // 滚动条的设置 + ::-webkit-scrollbar-thumb { + background-color: rgba(144, 147, 153, 0.3); + background-clip: padding-box; + min-height: 28px; + border-radius: 5px; + transition: 0.3s background-color; + } + ::-webkit-scrollbar-thumb:hover { + background-color: rgba(144, 147, 153, 0.5); + } + // element plus scrollbar + .el-scrollbar__bar.is-vertical { + width: 2px !important; + } + .el-scrollbar__bar.is-horizontal { + height: 2px !important; + } +} + +/* 页面宽度大于768px +------------------------------- */ +@media screen and (min-width: 769px) { + // 滚动条的宽度 + ::-webkit-scrollbar { + width: 7px; + height: 7px; + } + ::-webkit-scrollbar-track-piece { + background-color: var(--next-bg-main-color); + } + // 滚动条的设置 + ::-webkit-scrollbar-thumb { + background-color: rgba(144, 147, 153, 0.3); + background-clip: padding-box; + min-height: 28px; + border-radius: 5px; + transition: 0.3s background-color; + } + ::-webkit-scrollbar-thumb:hover { + background-color: rgba(144, 147, 153, 0.5); + } +} diff --git a/src/theme/media/tagsView.scss b/src/theme/media/tagsView.scss new file mode 100644 index 0000000..b71674e --- /dev/null +++ b/src/theme/media/tagsView.scss @@ -0,0 +1,11 @@ +@import './index.scss'; + +/* 页面宽度小于768px +------------------------------- */ +@media screen and (max-width: $sm) { + .tags-view-form { + .tags-view-form-col { + margin-bottom: 20px; + } + } +} diff --git a/src/theme/mixins/index.scss b/src/theme/mixins/index.scss new file mode 100644 index 0000000..61f3c6b --- /dev/null +++ b/src/theme/mixins/index.scss @@ -0,0 +1,56 @@ +/* 第三方图标字体间距/大小设置 +------------------------------- */ +@mixin generalIcon { + font-size: 14px !important; + display: inline-block; + vertical-align: middle; + margin-right: 5px; + width: 24px; + text-align: center; + justify-content: center; +} + +/* 文本不换行 +------------------------------- */ +@mixin text-no-wrap() { + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; +} + +/* 多行文本溢出 + ------------------------------- */ +@mixin text-ellipsis($line: 2) { + overflow: hidden; + word-break: break-all; + text-overflow: ellipsis; + display: -webkit-box; + -webkit-line-clamp: $line; + -webkit-box-orient: vertical; +} + +/* 滚动条(页面未使用) div 中使用: + ------------------------------- */ +// .test { +// @include scrollBar; +// } +@mixin scrollBar { + // 滚动条凹槽的颜色,还可以设置边框属性 + &::-webkit-scrollbar-track-piece { + background-color: #f8f8f8; + } + // 滚动条的宽度 + &::-webkit-scrollbar { + width: 9px; + height: 9px; + } + // 滚动条的设置 + &::-webkit-scrollbar-thumb { + background-color: #dddddd; + background-clip: padding-box; + min-height: 28px; + } + &::-webkit-scrollbar-thumb:hover { + background-color: #bbb; + } +} diff --git a/src/theme/other.scss b/src/theme/other.scss new file mode 100644 index 0000000..a0451b8 --- /dev/null +++ b/src/theme/other.scss @@ -0,0 +1,36 @@ +/* wangeditor富文本编辑器 +------------------------------- */ +.editor-container { + z-index: 9999; + .w-e-toolbar { + border: 1px solid var(--el-border-color-light, #ebeef5) !important; + border-bottom: 1px solid var(--el-border-color-light, #ebeef5) !important; + border-top-left-radius: 3px; + border-top-right-radius: 3px; + z-index: 2 !important; + } + .w-e-text-container { + border: 1px solid var(--el-border-color-light, #ebeef5) !important; + border-top: none !important; + border-bottom-left-radius: 3px; + border-bottom-right-radius: 3px; + z-index: 1 !important; + } +} + +[data-theme='dark'] { + // textarea - css vars + --w-e-textarea-bg-color: var(--el-color-white) !important; + --w-e-textarea-color: var(--el-text-color-primary) !important; + + // toolbar - css vars + --w-e-toolbar-color: var(--el-text-color-primary) !important; + --w-e-toolbar-bg-color: var(--el-color-white) !important; + --w-e-toolbar-active-color: var(--el-text-color-primary) !important; + --w-e-toolbar-active-bg-color: var(--next-color-menu-hover) !important; + --w-e-toolbar-border-color: var(--el-border-color-light, #ebeef5) !important; + + // modal - css vars + --w-e-modal-button-bg-color: var(--el-color-primary) !important; + --w-e-modal-button-border-color: var(--el-color-primary) !important; +} diff --git a/src/theme/waves.scss b/src/theme/waves.scss new file mode 100644 index 0000000..23add2c --- /dev/null +++ b/src/theme/waves.scss @@ -0,0 +1,101 @@ +/* Waves v0.6.0 +* http://fian.my.id/Waves +* +* Copyright 2014 Alfiana E. Sibuea and other contributors +* Released under the MIT license +* https://github.com/fians/Waves/blob/master/LICENSE +*/ +.waves-effect { + position: relative; + cursor: pointer; + display: inline-block; + overflow: hidden; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + -webkit-tap-highlight-color: transparent; + vertical-align: middle; + z-index: 1; + will-change: opacity, transform; + transition: all 0.3s ease-out; +} +.waves-effect .waves-ripple { + position: absolute; + border-radius: 50%; + width: 20px; + height: 20px; + margin-top: -10px; + margin-left: -10px; + opacity: 0; + background: rgba(0, 0, 0, 0.2); + transition: all 0.7s ease-out; + transition-property: opacity, -webkit-transform; + transition-property: transform, opacity; + transition-property: transform, opacity, -webkit-transform; + -webkit-transform: scale(0); + transform: scale(0); + pointer-events: none; +} +.waves-effect.waves-light .waves-ripple { + background-color: rgba(255, 255, 255, 0.45); +} +.waves-effect.waves-red .waves-ripple { + background-color: rgba(244, 67, 54, 0.7); +} +.waves-effect.waves-yellow .waves-ripple { + background-color: rgba(255, 235, 59, 0.7); +} +.waves-effect.waves-orange .waves-ripple { + background-color: rgba(255, 152, 0, 0.7); +} +.waves-effect.waves-purple .waves-ripple { + background-color: rgba(156, 39, 176, 0.7); +} +.waves-effect.waves-green .waves-ripple { + background-color: rgba(76, 175, 80, 0.7); +} +.waves-effect.waves-teal .waves-ripple { + background-color: rgba(0, 150, 136, 0.7); +} +.waves-effect input[type='button'], +.waves-effect input[type='reset'], +.waves-effect input[type='submit'] { + border: 0; + font-style: normal; + font-size: inherit; + text-transform: inherit; + background: none; +} +.waves-notransition { + transition: none !important; +} +.waves-circle { + -webkit-transform: translateZ(0); + transform: translateZ(0); + -webkit-mask-image: -webkit-radial-gradient(circle, #fff 100%, #000 100%); +} +.waves-input-wrapper { + border-radius: 0.2em; + vertical-align: bottom; +} +.waves-input-wrapper .waves-button-input { + position: relative; + top: 0; + left: 0; + z-index: 1; +} +.waves-circle { + text-align: center; + width: 2.5em; + height: 2.5em; + line-height: 2.5em; + border-radius: 50%; + -webkit-mask-image: none; +} +.waves-block { + display: block; +} +a.waves-effect .waves-ripple { + z-index: -1; +} diff --git a/src/utils/arrayOperation.ts b/src/utils/arrayOperation.ts new file mode 100644 index 0000000..a85deee --- /dev/null +++ b/src/utils/arrayOperation.ts @@ -0,0 +1,66 @@ +/** + * 判断两数组字符串是否相同(用于按钮权限验证),数组字符串中存在相同时会自动去重(按钮权限标识不会重复) + * @param news 新数据 + * @param old 源数据 + * @returns 两数组相同返回 `true`,反之则反 + */ +export function judementSameArr(newArr: unknown[] | string[], oldArr: string[]): boolean { + const news = removeDuplicate(newArr); + const olds = removeDuplicate(oldArr); + let count = 0; + const leng = olds.length; + for (let i in olds) { + for (let j in news) { + if (olds[i] === news[j]) count++; + } + } + return count === leng ? true : false; +} + +/** + * 判断两个对象是否相同 + * @param a 要比较的对象一 + * @param b 要比较的对象二 + * @returns 相同返回 true,反之则反 + */ +export function isObjectValueEqual(a: { [key: string]: any }, b: { [key: string]: any }) { + if (!a || !b) return false; + let aProps = Object.getOwnPropertyNames(a); + let bProps = Object.getOwnPropertyNames(b); + if (aProps.length != bProps.length) return false; + for (let i = 0; i < aProps.length; i++) { + let propName = aProps[i]; + let propA = a[propName]; + let propB = b[propName]; + if (!b.hasOwnProperty(propName)) return false; + if (propA instanceof Object) { + if (!isObjectValueEqual(propA, propB)) return false; + } else if (propA !== propB) { + return false; + } + } + return true; +} + +/** + * 数组、数组对象去重 + * @param arr 数组内容 + * @param attr 需要去重的键值(数组对象) + * @returns + */ +export function removeDuplicate(arr: any, attr?: string) { + if (!arr && !arr.length) { + return arr; + } else { + if (attr) { + const obj: any = {}; + const newArr = arr.reduce((cur: any, item: any) => { + obj[item[attr]] ? '' : (obj[item[attr]] = true && item[attr] && cur.push(item)); + return cur; + }, []); + return newArr; + } else { + return Array.from(new Set([...arr])); + } + } +} diff --git a/src/utils/authDirective.ts b/src/utils/authDirective.ts new file mode 100644 index 0000000..5971e64 --- /dev/null +++ b/src/utils/authDirective.ts @@ -0,0 +1,40 @@ +import type { App } from 'vue'; +import { useUserInfo } from '/@/stores/userInfo'; +import { judementSameArr } from '/@/utils/arrayOperation'; + +/** + * 用户权限指令 + * @directive 单个权限验证(v-auth="xxx") + * @directive 多个权限验证,满足一个则显示(v-auths="[xxx,xxx]") + * @directive 多个权限验证,全部满足则显示(v-auth-all="[xxx,xxx]") + */ +export function authDirective(app: App) { + // 单个权限验证(v-auth="xxx") + app.directive('auth', { + mounted(el, binding) { + const stores = useUserInfo(); + if (!stores.userInfos.authBtnList.some((v: string) => v === binding.value)) el.parentNode.removeChild(el); + }, + }); + // 多个权限验证,满足一个则显示(v-auths="[xxx,xxx]") + app.directive('auths', { + mounted(el, binding) { + let flag = false; + const stores = useUserInfo(); + stores.userInfos.authBtnList.map((val: string) => { + binding.value.map((v: string) => { + if (val === v) flag = true; + }); + }); + if (!flag) el.parentNode.removeChild(el); + }, + }); + // 多个权限验证,全部满足则显示(v-auth-all="[xxx,xxx]") + app.directive('auth-all', { + mounted(el, binding) { + const stores = useUserInfo(); + const flag = judementSameArr(binding.value, stores.userInfos.authBtnList); + if (!flag) el.parentNode.removeChild(el); + }, + }); +} diff --git a/src/utils/authFunction.ts b/src/utils/authFunction.ts new file mode 100644 index 0000000..84c0ab4 --- /dev/null +++ b/src/utils/authFunction.ts @@ -0,0 +1,38 @@ +import { useUserInfo } from '/@/stores/userInfo'; +import { judementSameArr } from '/@/utils/arrayOperation'; + +/** + * 单个权限验证 + * @param value 权限值 + * @returns 有权限,返回 `true`,反之则反 + */ +export function auth(value: string): boolean { + const stores = useUserInfo(); + return stores.userInfos.authBtnList.some((v: string) => v === value); +} + +/** + * 多个权限验证,满足一个则为 true + * @param value 权限值 + * @returns 有权限,返回 `true`,反之则反 + */ +export function auths(value: Array<string>): boolean { + let flag = false; + const stores = useUserInfo(); + stores.userInfos.authBtnList.map((val: string) => { + value.map((v: string) => { + if (val === v) flag = true; + }); + }); + return flag; +} + +/** + * 多个权限验证,全部满足则为 true + * @param value 权限值 + * @returns 有权限,返回 `true`,反之则反 + */ +export function authAll(value: Array<string>): boolean { + const stores = useUserInfo(); + return judementSameArr(value, stores.userInfos.authBtnList); +} diff --git a/src/utils/commonFunction.ts b/src/utils/commonFunction.ts new file mode 100644 index 0000000..1c069e6 --- /dev/null +++ b/src/utils/commonFunction.ts @@ -0,0 +1,65 @@ +// 通用函数 +import useClipboard from 'vue-clipboard3'; +import { ElMessage } from 'element-plus'; +import { formatDate } from '/@/utils/formatTime'; +import { useI18n } from 'vue-i18n'; + +export default function () { + const { t } = useI18n(); + const { toClipboard } = useClipboard(); + //百分比格式化 + const percentFormat = (row: any, column: number, cellValue: any) => { + return cellValue ? `${cellValue}%` : '-'; + }; + //列表日期时间格式化 + const dateFormatYMD = (row: any, column: number, cellValue: any) => { + if (!cellValue) return '-'; + return formatDate(new Date(cellValue), 'YYYY-mm-dd'); + }; + //列表日期时间格式化 + const dateFormatYMDHMS = (row: any, column: number, cellValue: any) => { + if (!cellValue) return '-'; + return formatDate(new Date(cellValue), 'YYYY-mm-dd HH:MM:SS'); + }; + //列表日期时间格式化 + const dateFormatHMS = (row: any, column: number, cellValue: any) => { + if (!cellValue) return '-'; + let time = 0; + if (typeof row === 'number') time = row; + if (typeof cellValue === 'number') time = cellValue; + return formatDate(new Date(time * 1000), 'HH:MM:SS'); + }; + // 小数格式化 + const scaleFormat = (value: any = 0, scale: number = 4) => { + return Number.parseFloat(value).toFixed(scale); + }; + // 小数格式化 + const scale2Format = (value: any = 0) => { + return Number.parseFloat(value).toFixed(2); + }; + // 点击复制文本 + const copyText = (text: string) => { + return new Promise((resolve, reject) => { + try { + //复制 + toClipboard(text); + //下面可以设置复制成功的提示框等操作 + ElMessage.success(t('message.layout.copyTextSuccess')); + resolve(text); + } catch (e) { + //复制失败 + ElMessage.error(t('message.layout.copyTextError')); + reject(e); + } + }); + }; + return { + percentFormat, + dateFormatYMD, + dateFormatYMDHMS, + dateFormatHMS, + scaleFormat, + scale2Format, + copyText, + }; +} diff --git a/src/utils/customDirective.ts b/src/utils/customDirective.ts new file mode 100644 index 0000000..c67350f --- /dev/null +++ b/src/utils/customDirective.ts @@ -0,0 +1,178 @@ +import type { App } from 'vue'; + +/** + * 按钮波浪指令 + * @directive 默认方式:v-waves,如 `<div v-waves></div>` + * @directive 参数方式:v-waves=" |light|red|orange|purple|green|teal",如 `<div v-waves="'light'"></div>` + */ +export function wavesDirective(app: App) { + app.directive('waves', { + mounted(el, binding) { + el.classList.add('waves-effect'); + binding.value && el.classList.add(`waves-${binding.value}`); + function setConvertStyle(obj: { [key: string]: unknown }) { + let style: string = ''; + for (let i in obj) { + if (obj.hasOwnProperty(i)) style += `${i}:${obj[i]};`; + } + return style; + } + function onCurrentClick(e: { [key: string]: unknown }) { + let elDiv = document.createElement('div'); + elDiv.classList.add('waves-ripple'); + el.appendChild(elDiv); + let styles = { + left: `${e.layerX}px`, + top: `${e.layerY}px`, + opacity: 1, + transform: `scale(${(el.clientWidth / 100) * 10})`, + 'transition-duration': `750ms`, + 'transition-timing-function': `cubic-bezier(0.250, 0.460, 0.450, 0.940)`, + }; + elDiv.setAttribute('style', setConvertStyle(styles)); + setTimeout(() => { + elDiv.setAttribute( + 'style', + setConvertStyle({ + opacity: 0, + transform: styles.transform, + left: styles.left, + top: styles.top, + }) + ); + setTimeout(() => { + elDiv && el.removeChild(elDiv); + }, 750); + }, 450); + } + el.addEventListener('mousedown', onCurrentClick, false); + }, + unmounted(el) { + el.addEventListener('mousedown', () => {}); + }, + }); +} + +/** + * 自定义拖动指令 + * @description 使用方式:v-drag="[dragDom,dragHeader]",如 `<div v-drag="['.drag-container .el-dialog', '.drag-container .el-dialog__header']"></div>` + * @description dragDom 要拖动的元素,dragHeader 要拖动的 Header 位置 + * @link 注意:https://github.com/element-plus/element-plus/issues/522 + * @lick 参考:https://blog.csdn.net/weixin_46391323/article/details/105228020?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_title-10&spm=1001.2101.3001.4242 + */ +export function dragDirective(app: App) { + app.directive('drag', { + mounted(el, binding) { + if (!binding.value) return false; + + const dragDom = document.querySelector(binding.value[0]) as HTMLElement; + const dragHeader = document.querySelector(binding.value[1]) as HTMLElement; + + dragHeader.onmouseover = () => (dragHeader.style.cursor = `move`); + + function down(e: any, type: string) { + // 鼠标按下,计算当前元素距离可视区的距离 + const disX = type === 'pc' ? e.clientX - dragHeader.offsetLeft : e.touches[0].clientX - dragHeader.offsetLeft; + const disY = type === 'pc' ? e.clientY - dragHeader.offsetTop : e.touches[0].clientY - dragHeader.offsetTop; + + // body当前宽度 + const screenWidth = document.body.clientWidth; + // 可见区域高度(应为body高度,可某些环境下无法获取) + const screenHeight = document.documentElement.clientHeight; + + // 对话框宽度 + const dragDomWidth = dragDom.offsetWidth; + // 对话框高度 + const dragDomheight = dragDom.offsetHeight; + + const minDragDomLeft = dragDom.offsetLeft; + const maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth; + + const minDragDomTop = dragDom.offsetTop; + const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomheight; + + // 获取到的值带px 正则匹配替换 + let styL: any = getComputedStyle(dragDom).left; + let styT: any = getComputedStyle(dragDom).top; + + // 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px + if (styL.includes('%')) { + styL = +document.body.clientWidth * (+styL.replace(/\%/g, '') / 100); + styT = +document.body.clientHeight * (+styT.replace(/\%/g, '') / 100); + } else { + styL = +styL.replace(/\px/g, ''); + styT = +styT.replace(/\px/g, ''); + } + + return { + disX, + disY, + minDragDomLeft, + maxDragDomLeft, + minDragDomTop, + maxDragDomTop, + styL, + styT, + }; + } + + function move(e: any, type: string, obj: any) { + let { disX, disY, minDragDomLeft, maxDragDomLeft, minDragDomTop, maxDragDomTop, styL, styT } = obj; + + // 通过事件委托,计算移动的距离 + let left = type === 'pc' ? e.clientX - disX : e.touches[0].clientX - disX; + let top = type === 'pc' ? e.clientY - disY : e.touches[0].clientY - disY; + + // 边界处理 + if (-left > minDragDomLeft) { + left = -minDragDomLeft; + } else if (left > maxDragDomLeft) { + left = maxDragDomLeft; + } + + if (-top > minDragDomTop) { + top = -minDragDomTop; + } else if (top > maxDragDomTop) { + top = maxDragDomTop; + } + + // 移动当前元素 + dragDom.style.cssText += `;left:${left + styL}px;top:${top + styT}px;`; + } + + /** + * pc端 + * onmousedown 鼠标按下触发事件 + * onmousemove 鼠标按下时持续触发事件 + * onmouseup 鼠标抬起触发事件 + */ + dragHeader.onmousedown = (e) => { + const obj = down(e, 'pc'); + document.onmousemove = (e) => { + move(e, 'pc', obj); + }; + document.onmouseup = () => { + document.onmousemove = null; + document.onmouseup = null; + }; + }; + + /** + * 移动端 + * ontouchstart 当按下手指时,触发ontouchstart + * ontouchmove 当移动手指时,触发ontouchmove + * ontouchend 当移走手指时,触发ontouchend + */ + dragHeader.ontouchstart = (e) => { + const obj = down(e, 'app'); + document.ontouchmove = (e) => { + move(e, 'app', obj); + }; + document.ontouchend = () => { + document.ontouchmove = null; + document.ontouchend = null; + }; + }; + }, + }); +} diff --git a/src/utils/directive.ts b/src/utils/directive.ts new file mode 100644 index 0000000..ccac511 --- /dev/null +++ b/src/utils/directive.ts @@ -0,0 +1,21 @@ +import type { App } from 'vue'; +import { authDirective } from '/@/utils/authDirective'; +import { wavesDirective, dragDirective } from '/@/utils/customDirective'; +import { preventClick } from '/@/utils/throttle'; + +/** + * 导出指令方法:v-xxx + * @methods authDirective 用户权限指令,用法:v-auth + * @methods wavesDirective 按钮波浪指令,用法:v-waves + * @methods dragDirective 自定义拖动指令,用法:v-drag + */ +export function directive(app: App) { + // 用户权限指令 + authDirective(app); + // 按钮波浪指令 + wavesDirective(app); + // 自定义拖动指令 + dragDirective(app); + + preventClick(app); +} diff --git a/src/utils/formatTime.ts b/src/utils/formatTime.ts new file mode 100644 index 0000000..441e30c --- /dev/null +++ b/src/utils/formatTime.ts @@ -0,0 +1,137 @@ +/** + * 时间日期转换 + * @param date 当前时间,new Date() 格式 + * @param format 需要转换的时间格式字符串 + * @description format 字符串随意,如 `YYYY-mm、YYYY-mm-dd` + * @description format 季度:"YYYY-mm-dd HH:MM:SS QQQQ" + * @description format 星期:"YYYY-mm-dd HH:MM:SS WWW" + * @description format 几周:"YYYY-mm-dd HH:MM:SS ZZZ" + * @description format 季度 + 星期 + 几周:"YYYY-mm-dd HH:MM:SS WWW QQQQ ZZZ" + * @returns 返回拼接后的时间字符串 + */ +export function formatDate(date: Date, format: string): string { + let we = date.getDay(); // 星期 + let z = getWeek(date); // 周 + let qut = Math.floor((date.getMonth() + 3) / 3).toString(); // 季度 + const opt: { [key: string]: string } = { + 'Y+': date.getFullYear().toString(), // 年 + 'm+': (date.getMonth() + 1).toString(), // 月(月份从0开始,要+1) + 'd+': date.getDate().toString(), // 日 + 'H+': date.getHours().toString(), // 时 + 'M+': date.getMinutes().toString(), // 分 + 'S+': date.getSeconds().toString(), // 秒 + 'q+': qut, // 季度 + }; + // 中文数字 (星期) + const week: { [key: string]: string } = { + '0': '日', + '1': '一', + '2': '二', + '3': '三', + '4': '四', + '5': '五', + '6': '六', + }; + // 中文数字(季度) + const quarter: { [key: string]: string } = { + '1': '一', + '2': '二', + '3': '三', + '4': '四', + }; + if (/(W+)/.test(format)) + format = format.replace(RegExp.$1, RegExp.$1.length > 1 ? (RegExp.$1.length > 2 ? '星期' + week[we] : '周' + week[we]) : week[we]); + if (/(Q+)/.test(format)) format = format.replace(RegExp.$1, RegExp.$1.length == 4 ? '第' + quarter[qut] + '季度' : quarter[qut]); + if (/(Z+)/.test(format)) format = format.replace(RegExp.$1, RegExp.$1.length == 3 ? '第' + z + '周' : z + ''); + for (let k in opt) { + let r = new RegExp('(' + k + ')').exec(format); + // 若输入的长度不为1,则前面补零 + if (r) format = format.replace(r[1], RegExp.$1.length == 1 ? opt[k] : opt[k].padStart(RegExp.$1.length, '0')); + } + return format; +} + +/** + * 获取当前日期是第几周 + * @param dateTime 当前传入的日期值 + * @returns 返回第几周数字值 + */ +export function getWeek(dateTime: Date): number { + let temptTime = new Date(dateTime.getTime()); + // 周几 + let weekday = temptTime.getDay() || 7; + // 周1+5天=周六 + temptTime.setDate(temptTime.getDate() - weekday + 1 + 5); + let firstDay = new Date(temptTime.getFullYear(), 0, 1); + let dayOfWeek = firstDay.getDay(); + let spendDay = 1; + if (dayOfWeek != 0) spendDay = 7 - dayOfWeek + 1; + firstDay = new Date(temptTime.getFullYear(), 0, 1 + spendDay); + let d = Math.ceil((temptTime.valueOf() - firstDay.valueOf()) / 86400000); + let result = Math.ceil(d / 7); + return result; +} + +/** + * 将时间转换为 `几秒前`、`几分钟前`、`几小时前`、`几天前` + * @param param 当前时间,new Date() 格式或者字符串时间格式 + * @param format 需要转换的时间格式字符串 + * @description param 10秒: 10 * 1000 + * @description param 1分: 60 * 1000 + * @description param 1小时: 60 * 60 * 1000 + * @description param 24小时:60 * 60 * 24 * 1000 + * @description param 3天: 60 * 60* 24 * 1000 * 3 + * @returns 返回拼接后的时间字符串 + */ +export function formatPast(param: string | Date, format: string = 'YYYY-mm-dd'): string { + // 传入格式处理、存储转换值 + let t: any, s: number; + // 获取js 时间戳 + let time: number = new Date().getTime(); + // 是否是对象 + typeof param === 'string' || 'object' ? (t = new Date(param).getTime()) : (t = param); + // 当前时间戳 - 传入时间戳 + time = Number.parseInt(`${time - t}`); + if (time < 10000) { + // 10秒内 + return '刚刚'; + } else if (time < 60000 && time >= 10000) { + // 超过10秒少于1分钟内 + s = Math.floor(time / 1000); + return `${s}秒前`; + } else if (time < 3600000 && time >= 60000) { + // 超过1分钟少于1小时 + s = Math.floor(time / 60000); + return `${s}分钟前`; + } else if (time < 86400000 && time >= 3600000) { + // 超过1小时少于24小时 + s = Math.floor(time / 3600000); + return `${s}小时前`; + } else if (time < 259200000 && time >= 86400000) { + // 超过1天少于3天内 + s = Math.floor(time / 86400000); + return `${s}天前`; + } else { + // 超过3天 + let date = typeof param === 'string' || 'object' ? new Date(param) : param; + return formatDate(date, format); + } +} + +/** + * 时间问候语 + * @param param 当前时间,new Date() 格式 + * @description param 调用 `formatAxis(new Date())` 输出 `上午好` + * @returns 返回拼接后的时间字符串 + */ +export function formatAxis(param: Date): string { + let hour: number = new Date(param).getHours(); + if (hour < 6) return '凌晨好'; + else if (hour < 9) return '早上好'; + else if (hour < 12) return '上午好'; + else if (hour < 14) return '中午好'; + else if (hour < 17) return '下午好'; + else if (hour < 19) return '傍晚好'; + else if (hour < 22) return '晚上好'; + else return '夜里好'; +} diff --git a/src/utils/getStyleSheets.ts b/src/utils/getStyleSheets.ts new file mode 100644 index 0000000..81c80e0 --- /dev/null +++ b/src/utils/getStyleSheets.ts @@ -0,0 +1,93 @@ +import { nextTick } from 'vue'; +import * as svg from '@element-plus/icons-vue'; + +// 获取阿里字体图标 +const getAlicdnIconfont = () => { + return new Promise((resolve, reject) => { + nextTick(() => { + const styles: any = document.styleSheets; + let sheetsList = []; + let sheetsIconList = []; + for (let i = 0; i < styles.length; i++) { + if (styles[i].href && styles[i].href.indexOf('at.alicdn.com') > -1) { + sheetsList.push(styles[i]); + } + } + for (let i = 0; i < sheetsList.length; i++) { + for (let j = 0; j < sheetsList[i].cssRules.length; j++) { + if (sheetsList[i].cssRules[j].selectorText && sheetsList[i].cssRules[j].selectorText.indexOf('.icon-') > -1) { + sheetsIconList.push(`${sheetsList[i].cssRules[j].selectorText.substring(1, sheetsList[i].cssRules[j].selectorText.length).replace(/\:\:before/gi, '')}`); + } + } + } + if (sheetsIconList.length > 0) resolve(sheetsIconList); + else reject('未获取到值,请刷新重试'); + }); + }); +}; + +// 初始化获取 css 样式,获取 element plus 自带 svg 图标,增加了 ele- 前缀,使用时:ele-Aim +const getElementPlusIconfont = () => { + return new Promise((resolve, reject) => { + nextTick(() => { + const icons = svg as any; + const sheetsIconList = []; + for (const i in icons) { + sheetsIconList.push(`ele-${icons[i].name}`); + } + if (sheetsIconList.length > 0) resolve(sheetsIconList); + else reject('未获取到值,请刷新重试'); + }); + }); +}; + +// 初始化获取 css 样式,这里使用 fontawesome 的图标 +const getAwesomeIconfont = () => { + return new Promise((resolve, reject) => { + nextTick(() => { + const styles: any = document.styleSheets; + let sheetsList = []; + let sheetsIconList = []; + for (let i = 0; i < styles.length; i++) { + if (styles[i].href && styles[i].href.indexOf('netdna.bootstrapcdn.com') > -1) { + sheetsList.push(styles[i]); + } + } + for (let i = 0; i < sheetsList.length; i++) { + for (let j = 0; j < sheetsList[i].cssRules.length; j++) { + if (sheetsList[i].cssRules[j].selectorText && sheetsList[i].cssRules[j].selectorText.indexOf('.fa-') === 0 && sheetsList[i].cssRules[j].selectorText.indexOf(',') === -1) { + if (/::before/.test(sheetsList[i].cssRules[j].selectorText)) { + sheetsIconList.push(`${sheetsList[i].cssRules[j].selectorText.substring(1, sheetsList[i].cssRules[j].selectorText.length).replace(/\:\:before/gi, '')}`); + } + } + } + } + if (sheetsIconList.length > 0) resolve(sheetsIconList.reverse()); + else reject('未获取到值,请刷新重试'); + }); + }); +}; + +/** + * 获取字体图标 `document.styleSheets` + * @method ali 获取阿里字体图标 `<i class="iconfont 图标类名"></i>` + * @method ele 获取 element plus 自带图标 `<i class="图标类名"></i>` + * @method ali 获取 fontawesome 的图标 `<i class="fa 图标类名"></i>` + */ +const initIconfont = { + // iconfont + ali: () => { + return getAlicdnIconfont(); + }, + // element plus + ele: () => { + return getElementPlusIconfont(); + }, + // fontawesome + awe: () => { + return getAwesomeIconfont(); + } +}; + +// 导出方法 +export default initIconfont; diff --git a/src/utils/loading.ts b/src/utils/loading.ts new file mode 100644 index 0000000..c23fb77 --- /dev/null +++ b/src/utils/loading.ts @@ -0,0 +1,42 @@ +import { nextTick } from 'vue'; +import '/@/theme/loading.scss'; + +/** + * 页面全局 Loading + * @method start 创建 loading + * @method done 移除 loading + */ +export const NextLoading = { + // 创建 loading + start: () => { + const bodys: Element = document.body; + const div = <HTMLElement>document.createElement('div'); + div.setAttribute('class', 'loading-next'); + const htmls = ` + <div class="loading-next-box"> + <div class="loading-next-box-warp"> + <div class="loading-next-box-item"></div> + <div class="loading-next-box-item"></div> + <div class="loading-next-box-item"></div> + <div class="loading-next-box-item"></div> + <div class="loading-next-box-item"></div> + <div class="loading-next-box-item"></div> + <div class="loading-next-box-item"></div> + <div class="loading-next-box-item"></div> + <div class="loading-next-box-item"></div> + </div> + </div> + `; + div.innerHTML = htmls; + bodys.insertBefore(div, bodys.childNodes[0]); + window.nextLoading = true; + }, + // 移除 loading + done: () => { + nextTick(() => { + window.nextLoading = false; + const el = <HTMLElement>document.querySelector('.loading-next'); + el?.parentNode?.removeChild(el); + }); + }, +}; diff --git a/src/utils/other.ts b/src/utils/other.ts new file mode 100644 index 0000000..6bb4fbd --- /dev/null +++ b/src/utils/other.ts @@ -0,0 +1,200 @@ +import { nextTick } from 'vue'; +import type { App } from 'vue'; +import * as svg from '@element-plus/icons-vue'; +import router from '/@/router/index'; +import pinia from '/@/stores/index'; +import { storeToRefs } from 'pinia'; +import { useThemeConfig } from '/@/stores/themeConfig'; +import { i18n } from '/@/i18n/index'; +import { Local } from '/@/utils/storage'; +import SvgIcon from '/@/components/svgIcon/index.vue'; + +/** + * 导出全局注册 element plus svg 图标 + * @param app vue 实例 + * @description 使用:https://element-plus.gitee.io/zh-CN/component/icon.html + */ +export function elSvg(app: App) { + const icons = svg as any; + for (const i in icons) { + app.component(`ele-${icons[i].name}`, icons[i]); + } + app.component('SvgIcon', SvgIcon); +} + +/** + * 设置浏览器标题国际化 + * @method const title = useTitle(); ==> title() + */ +export function useTitle() { + const stores = useThemeConfig(pinia); + const { themeConfig } = storeToRefs(stores); + nextTick(() => { + let webTitle = ''; + let globalTitle: string = themeConfig.value.globalTitle; + const { path, meta } = router.currentRoute.value; + if (path === '/login') { + webTitle = <any>meta.title; + } else { + webTitle = setTagsViewNameI18n(router.currentRoute.value); + } + document.title = `${webTitle} - ${globalTitle}` || globalTitle; + }); +} + +/** + * 设置 自定义 tagsView 名称、 自定义 tagsView 名称国际化 + * @param params 路由 query、params 中的 tagsViewName + * @returns 返回当前 tagsViewName 名称 + */ +export function setTagsViewNameI18n(item: any) { + let tagsViewName: any = ''; + const { query, params, meta } = item; + if (query?.tagsViewName || params?.tagsViewName) { + if (/\/zh-cn|en|zh-tw\//.test(query?.tagsViewName) || /\/(zh-cn|en|zh-tw)\//.test(params?.tagsViewName)) { + // 国际化 + const urlTagsParams = (query?.tagsViewName && JSON.parse(query?.tagsViewName)) || (params?.tagsViewName && JSON.parse(params?.tagsViewName)); + tagsViewName = urlTagsParams[i18n.global.locale]; + } else { + // 非国际化 + tagsViewName = query?.tagsViewName || params?.tagsViewName; + } + } else { + // 非自定义 tagsView 名称 + tagsViewName = i18n.global.t(<any>meta.title); + } + return tagsViewName; +} + +/** + * 图片懒加载 + * @param el dom 目标元素 + * @param arr 列表数据 + * @description data-xxx 属性用于存储页面或应用程序的私有自定义数据 + */ +export const lazyImg = (el: any, arr: any) => { + const io = new IntersectionObserver((res) => { + res.forEach((v: any) => { + if (v.isIntersecting) { + const { img, key } = v.target.dataset; + v.target.src = img; + v.target.onload = () => { + io.unobserve(v.target); + arr[key]['loading'] = false; + }; + } + }); + }); + nextTick(() => { + document.querySelectorAll(el).forEach((img) => io.observe(img)); + }); +}; + +/** + * 全局组件大小 + * @returns 返回 `window.localStorage` 中读取的缓存值 `globalComponentSize` + */ +export const globalComponentSize = (): string => { + const stores = useThemeConfig(pinia); + const { themeConfig } = storeToRefs(stores); + return Local.get('themeConfig')?.globalComponentSize || themeConfig.value?.globalComponentSize; +}; + +/** + * 对象深克隆 + * @param obj 源对象 + * @returns 克隆后的对象 + */ +export function deepClone(obj: any) { + let newObj: any; + try { + newObj = obj.push ? [] : {}; + } catch (error) { + newObj = {}; + } + for (let attr in obj) { + if (obj[attr] && typeof obj[attr] === 'object') { + newObj[attr] = deepClone(obj[attr]); + } else { + newObj[attr] = obj[attr]; + } + } + return newObj; +} + +/** + * 判断是否是移动端 + */ +export function isMobile() { + if ( + navigator.userAgent.match( + /('phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone')/i + ) + ) { + return true; + } else { + return false; + } +} + +/** + * 判断数组对象中所有属性是否为空,为空则删除当前行对象 + * @description @感谢大黄 + * @param list 数组对象 + * @returns 删除空值后的数组对象 + */ +export function handleEmpty(list: any) { + const arr = []; + for (const i in list) { + const d = []; + for (const j in list[i]) { + d.push(list[i][j]); + } + const leng = d.filter((item) => item === '').length; + if (leng !== d.length) { + arr.push(list[i]); + } + } + return arr; +} + +/** + * 统一批量导出 + * @method elSvg 导出全局注册 element plus svg 图标 + * @method useTitle 设置浏览器标题国际化 + * @method setTagsViewNameI18n 设置 自定义 tagsView 名称、 自定义 tagsView 名称国际化 + * @method lazyImg 图片懒加载 + * @method globalComponentSize() element plus 全局组件大小 + * @method deepClone 对象深克隆 + * @method isMobile 判断是否是移动端 + * @method handleEmpty 判断数组对象中所有属性是否为空,为空则删除当前行对象 + */ +const other = { + elSvg: (app: App) => { + elSvg(app); + }, + useTitle: () => { + useTitle(); + }, + setTagsViewNameI18n(route: any) { + return setTagsViewNameI18n(route); + }, + lazyImg: (el: any, arr: any) => { + lazyImg(el, arr); + }, + globalComponentSize: () => { + return globalComponentSize(); + }, + deepClone: (obj: any) => { + return deepClone(obj); + }, + isMobile: () => { + return isMobile(); + }, + handleEmpty: (list: any) => { + return handleEmpty(list); + }, +}; + +// 统一批量导出 +export default other; diff --git a/src/utils/request.ts b/src/utils/request.ts new file mode 100644 index 0000000..ed8cf58 --- /dev/null +++ b/src/utils/request.ts @@ -0,0 +1,119 @@ +import axios from 'axios'; +import { ElMessage, ElMessageBox } from 'element-plus'; +import JSONbig from 'json-bigint'; +import Cookies from 'js-cookie'; +import { useLoginApi } from '/@/api/login'; +import { Session } from '/@/utils/storage'; + +// var jsonBig = require('json-bigint')({ "storeAsString": true }); +// 配置新建一个 axios 实例 +const service = axios.create({ + // baseURL: import.meta.env.VITE_API_URL as any, + timeout: 50000, + headers: { 'Content-Type': 'application/json' } +}); + +service.interceptors.request.use( + (config) => { + for (let key in config.data) { + if (config.data[key] == '' && config.data[key] !== 0) { + config.data[key] = null; + } + } + if (Cookies.get('token')) { + (<any>config.headers).common['Authorization'] = `${Cookies.get('token')}`; + (<any>config.headers).common['uid'] = `${Cookies.get('uid')}`; + } + return config; + }, + (error) => { + // 对请求错误做些什么 + return Promise.reject(error); + } +); + +service.defaults.transformResponse = [ + function (data) { + try { + // 正常同通过return JSON.parse(data)对数据进行转换 + // 但是转化完成的数据可能超出安全数据长度 + // 因此我们定制使用第三包来转化 + // if(data.indexOf('http://') === -1){ + // return data + // }else{ + // if(typeof JSON.parse(data) === 'object'){ + // return JSONbig.parse(data); + // }; + return JSONbig.parse(data); + } catch (err) { + // 转换失败返回一个空对象 + return data + } + } +]; + +service.interceptors.response.use( + (response) => { + // 对响应数据做点什么 + if (response.data.code && response.data.code === 'A0213') { + ElMessage.error('用户uid不存在'); + useLoginApi() + .signOut() + .then(() => { + Session.clear(); + window.location.href = '/'; + }); + } else if (response.data.code && response.data.code === 'A0215') { + ElMessage.error('token失效'); + // logOut; + useLoginApi() + .signOut() + .then(() => { + Session.clear(); + window.location.href = '/'; + }); + } + // if(response.data.code && response.data.code !== '200'){ + return Promise.resolve(response); + // } + // Session.clear() + // window.location.href = '/' + // return Promise.reject(response) + // const res = response.data; + // if (res.code && res.code !== 0) { + // // `token` 过期或者账号已在别处登录 + // if (res.code === 401 || res.code === 4001) { + // Session.clear(); // 清除浏览器全部临时缓存 + // window.location.href = '/'; // 去登录页 + // ElMessageBox.alert('你已被登出,请重新登录', '提示', {}) + // .then(() => {}) + // .catch(() => {}); + // } + // return Promise.reject(service.interceptors.response); + // } else { + // return response.data; + // } + }, + (error) => { + // 对响应错误做点什么 + if (error.message.indexOf('timeout') != -1) { + ElMessage.error('网络超时'); + setTimeout(() => { + Session.clear(); + window.location.href = '/'; + }, 1000); + } else if (error.message == 'Network Error') { + ElMessage.error('网络连接错误'); + setTimeout(() => { + Session.clear(); + window.location.href = '/'; + }, 1000); + } else { + if (error.response.data) ElMessage.error(error.response.data.error); + else ElMessage.error('接口路径找不到'); + } + return Promise.reject(error); + } +); + +export default service; diff --git a/src/utils/setIconfont.ts b/src/utils/setIconfont.ts new file mode 100644 index 0000000..b048dc8 --- /dev/null +++ b/src/utils/setIconfont.ts @@ -0,0 +1,48 @@ +// 字体图标 url +const cssCdnUrlList: Array<string> = [ + '//at.alicdn.com/t/font_2298093_y6u00apwst.css', + // '//netdna.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css', +]; +// 第三方 js url +const jsCdnUrlList: Array<string> = []; + +// 动态批量设置字体图标 +export function setCssCdn() { + if (cssCdnUrlList.length <= 0) return false; + cssCdnUrlList.map((v) => { + let link = document.createElement('link'); + link.rel = 'stylesheet'; + link.href = v; + link.crossOrigin = 'anonymous'; + document.getElementsByTagName('head')[0].appendChild(link); + }); +} + +// 动态批量设置第三方js +export function setJsCdn() { + if (jsCdnUrlList.length <= 0) return false; + jsCdnUrlList.map((v) => { + let link = document.createElement('script'); + link.src = v; + document.body.appendChild(link); + }); +} + +/** + * 批量设置字体图标、动态js + * @method cssCdn 动态批量设置字体图标 + * @method jsCdn 动态批量设置第三方js + */ +const setIntroduction = { + // 设置css + cssCdn: () => { + setCssCdn(); + }, + // 设置js + jsCdn: () => { + setJsCdn(); + }, +}; + +// 导出函数方法 +export default setIntroduction; diff --git a/src/utils/storage.ts b/src/utils/storage.ts new file mode 100644 index 0000000..a983f80 --- /dev/null +++ b/src/utils/storage.ts @@ -0,0 +1,59 @@ +import Cookies from 'js-cookie'; + +/** + * window.localStorage 浏览器永久缓存 + * @method set 设置永久缓存 + * @method get 获取永久缓存 + * @method remove 移除永久缓存 + * @method clear 移除全部永久缓存 + */ +export const Local = { + // 设置永久缓存 + set(key: string, val: any) { + window.localStorage.setItem(key, JSON.stringify(val)); + }, + // 获取永久缓存 + get(key: string) { + let json: any = window.localStorage.getItem(key); + return JSON.parse(json); + }, + // 移除永久缓存 + remove(key: string) { + window.localStorage.removeItem(key); + }, + // 移除全部永久缓存 + clear() { + window.localStorage.clear(); + }, +}; + +/** + * window.sessionStorage 浏览器临时缓存 + * @method set 设置临时缓存 + * @method get 获取临时缓存 + * @method remove 移除临时缓存 + * @method clear 移除全部临时缓存 + */ +export const Session = { + // 设置临时缓存 + set(key: string, val: any) { + if (key === 'token') return Cookies.set(key, val); + window.sessionStorage.setItem(key, JSON.stringify(val)); + }, + // 获取临时缓存 + get(key: string) { + if (key === 'token') return Cookies.get(key); + let json: any = window.sessionStorage.getItem(key); + return JSON.parse(json); + }, + // 移除临时缓存 + remove(key: string) { + if (key === 'token') return Cookies.remove(key); + window.sessionStorage.removeItem(key); + }, + // 移除全部临时缓存 + clear() { + Cookies.remove('token'); + window.sessionStorage.clear(); + }, +}; diff --git a/src/utils/theme.ts b/src/utils/theme.ts new file mode 100644 index 0000000..5561e64 --- /dev/null +++ b/src/utils/theme.ts @@ -0,0 +1,59 @@ +import { ElMessage } from 'element-plus'; + +/** + * hex颜色转rgb颜色 + * @param str 颜色值字符串 + * @returns 返回处理后的颜色值 + */ +export function hexToRgb(str: any) { + let hexs: any = ''; + let reg = /^\#?[0-9A-Fa-f]{6}$/; + if (!reg.test(str)) return ElMessage.warning('输入错误的hex'); + str = str.replace('#', ''); + hexs = str.match(/../g); + for (let i = 0; i < 3; i++) hexs[i] = parseInt(hexs[i], 16); + return hexs; +} + +/** + * rgb颜色转Hex颜色 + * @param r 代表红色 + * @param g 代表绿色 + * @param b 代表蓝色 + * @returns 返回处理后的颜色值 + */ +export function rgbToHex(r: any, g: any, b: any) { + let reg = /^\d{1,3}$/; + if (!reg.test(r) || !reg.test(g) || !reg.test(b)) return ElMessage.warning('输入错误的rgb颜色值'); + let hexs = [r.toString(16), g.toString(16), b.toString(16)]; + for (let i = 0; i < 3; i++) if (hexs[i].length == 1) hexs[i] = `0${hexs[i]}`; + return `#${hexs.join('')}`; +} + +/** + * 加深颜色值 + * @param color 颜色值字符串 + * @param level 加深的程度,限0-1之间 + * @returns 返回处理后的颜色值 + */ +export function getDarkColor(color: string, level: number) { + let reg = /^\#?[0-9A-Fa-f]{6}$/; + if (!reg.test(color)) return ElMessage.warning('输入错误的hex颜色值'); + let rgb = hexToRgb(color); + for (let i = 0; i < 3; i++) rgb[i] = Math.floor(rgb[i] * (1 - level)); + return rgbToHex(rgb[0], rgb[1], rgb[2]); +} + +/** + * 变浅颜色值 + * @param color 颜色值字符串 + * @param level 加深的程度,限0-1之间 + * @returns 返回处理后的颜色值 + */ +export function getLightColor(color: string, level: number) { + let reg = /^\#?[0-9A-Fa-f]{6}$/; + if (!reg.test(color)) return ElMessage.warning('输入错误的hex颜色值'); + let rgb = hexToRgb(color); + for (let i = 0; i < 3; i++) rgb[i] = Math.floor((255 - rgb[i]) * level + rgb[i]); + return rgbToHex(rgb[0], rgb[1], rgb[2]); +} diff --git a/src/utils/throttle.ts b/src/utils/throttle.ts new file mode 100644 index 0000000..52e9528 --- /dev/null +++ b/src/utils/throttle.ts @@ -0,0 +1,36 @@ +import { App } from 'vue'; + +export function preventClick(app: App) { + app.directive('throttle', { + mounted(el: any, binding: any) { + el.addEventListener('click', () => { + if (!el.disabled) { + el.disabled = true; + setTimeout(() => { + el.disabled = false; + }, binding.value || 2000); + } + }); + } + + // mounted(el, binding) { + // let timer : NodeJS.Timeout | null = null + // el.addEventListener('click', () => { + // debugger + // let firstClick: Boolean = !timer; + // if(firstClick){ + // binding.value + // } + // if(timer){ + // clearTimeout(timer) + // } + // timer = setTimeout(() => { + // timer = null + // if(!firstClick){ + // binding.value + // } + // },3000); + // }) + // } + }); +} diff --git a/src/utils/toolsValidate.ts b/src/utils/toolsValidate.ts new file mode 100644 index 0000000..434466e --- /dev/null +++ b/src/utils/toolsValidate.ts @@ -0,0 +1,368 @@ +/** + * 2020.11.29 lyt 整理 + * 工具类集合,适用于平时开发 + * 新增多行注释信息,鼠标放到方法名即可查看 + */ + +/** + * 验证百分比(不可以小数) + * @param val 当前值字符串 + * @returns 返回处理后的字符串 + */ +export function verifyNumberPercentage(val: string): string { + // 匹配空格 + let v = val.replace(/(^\s*)|(\s*$)/g, ''); + // 只能是数字和小数点,不能是其他输入 + v = v.replace(/[^\d]/g, ''); + // 不能以0开始 + v = v.replace(/^0/g, ''); + // 数字超过100,赋值成最大值100 + v = v.replace(/^[1-9]\d\d{1,3}$/, '100'); + // 返回结果 + return v; +} + +/** + * 验证百分比(可以小数) + * @param val 当前值字符串 + * @returns 返回处理后的字符串 + */ +export function verifyNumberPercentageFloat(val: string): string { + let v = verifyNumberIntegerAndFloat(val); + // 数字超过100,赋值成最大值100 + v = v.replace(/^[1-9]\d\d{1,3}$/, '100'); + // 超过100之后不给再输入值 + v = v.replace(/^100\.$/, '100'); + // 返回结果 + return v; +} + +/** + * 小数或整数(不可以负数) + * @param val 当前值字符串 + * @returns 返回处理后的字符串 + */ +export function verifyNumberIntegerAndFloat(val: string) { + // 匹配空格 + let v = val.replace(/(^\s*)|(\s*$)/g, ''); + // 只能是数字和小数点,不能是其他输入 + v = v.replace(/[^\d.]/g, ''); + // 以0开始只能输入一个 + v = v.replace(/^0{2}$/g, '0'); + // 保证第一位只能是数字,不能是点 + v = v.replace(/^\./g, ''); + // 小数只能出现1位 + v = v.replace('.', '$#$').replace(/\./g, '').replace('$#$', '.'); + // 小数点后面保留2位 + v = v.replace(/^(\-)*(\d+)\.(\d\d).*$/, '$1$2.$3'); + // 返回结果 + return v; +} + +/** + * 0到9 + * @param val 当前值字符串 + * @returns 返回处理后的字符串 + */ +export function verifyString(val: string) { + let v = val.replace(/(^\s*)|(\s*$)/g, ''); + // 只能是数字和小数点,不能是其他输入 + v = v.replace(/[^\d.]/g, ''); + // 以0开始只能输入一个 + v = v.replace(/^\./g, ''); + // 小数只能出现1位 + v = v.replace('.', '$#$').replace(/\./g, '').replace('$#$', '.'); + // 小数点后面保留2位 + v = v.replace(/^(\-)*(\d+)\.(\d\d).*$/, '$1$2.$3'); + // 返回结果 + return v; +} + + +/** + * 正整数验证 + * @param val 当前值字符串 + * @returns 返回处理后的字符串 + */ +export function verifiyNumberInteger(val: string) { + // 匹配空格 + let v = val.replace(/(^\s*)|(\s*$)/g, ''); + // 去掉 '.' , 防止贴贴的时候出现问题 如 0.1.12.12 + v = v.replace(/[\.]*/g, ''); + // 去掉以 0 开始后面的数, 防止贴贴的时候出现问题 如 00121323 + v = v.replace(/(^0[\d]*)$/g, '0'); + // 首位是0,只能出现一次 + v = v.replace(/^0\d$/g, '0'); + // 只匹配数字 + v = v.replace(/[^\d]/g, ''); + // 返回结果 + return v; +} + +/** + * 去掉中文及空格 + * @param val 当前值字符串 + * @returns 返回处理后的字符串 + */ +export function verifyCnAndSpace(val: string) { + // 匹配中文与空格 + let v = val.replace(/[\u4e00-\u9fa5\s]+/g, ''); + // 匹配空格 + v = v.replace(/(^\s*)|(\s*$)/g, ''); + // 返回结果 + return v; +} + +/** + * 去掉英文及空格 + * @param val 当前值字符串 + * @returns 返回处理后的字符串 + */ +export function verifyEnAndSpace(val: string) { + // 匹配英文与空格 + let v = val.replace(/[a-zA-Z]+/g, ''); + // 匹配空格 + v = v.replace(/(^\s*)|(\s*$)/g, ''); + // 返回结果 + return v; +} + +/** + * 禁止输入空格 + * @param val 当前值字符串 + * @returns 返回处理后的字符串 + */ +export function verifyAndSpace(val: string) { + // 匹配空格 + let v = val.replace(/(^\s*)|(\s*$)/g, ''); + // 返回结果 + return v; +} + +/** + * 金额用 `,` 区分开 + * @param val 当前值字符串 + * @returns 返回处理后的字符串 + */ +export function verifyNumberComma(val: string) { + // 调用小数或整数(不可以负数)方法 + let v: any = verifyNumberIntegerAndFloat(val); + // 字符串转成数组 + v = v.toString().split('.'); + // \B 匹配非单词边界,两边都是单词字符或者两边都是非单词字符 + v[0] = v[0].replace(/\B(?=(\d{3})+(?!\d))/g, ','); + // 数组转字符串 + v = v.join('.'); + // 返回结果 + return v; +} + +/** + * 匹配文字变色(搜索时) + * @param val 当前值字符串 + * @param text 要处理的字符串值 + * @param color 搜索到时字体高亮颜色 + * @returns 返回处理后的字符串 + */ +export function verifyTextColor(val: string, text = '', color = 'red') { + // 返回内容,添加颜色 + let v = text.replace(new RegExp(val, 'gi'), `<span style='color: ${color}'>${val}</span>`); + // 返回结果 + return v; +} + +/** + * 数字转中文大写 + * @param val 当前值字符串 + * @param unit 默认:仟佰拾亿仟佰拾万仟佰拾元角分 + * @returns 返回处理后的字符串 + */ +export function verifyNumberCnUppercase(val: any, unit = '仟佰拾亿仟佰拾万仟佰拾元角分', v = '') { + // 当前内容字符串添加 2个0,为什么?? + val += '00'; + // 返回某个指定的字符串值在字符串中首次出现的位置,没有出现,则该方法返回 -1 + let lookup = val.indexOf('.'); + // substring:不包含结束下标内容,substr:包含结束下标内容 + if (lookup >= 0) val = val.substring(0, lookup) + val.substr(lookup + 1, 2); + // 根据内容 val 的长度,截取返回对应大写 + unit = unit.substr(unit.length - val.length); + // 循环截取拼接大写 + for (let i = 0; i < val.length; i++) { + v += '零壹贰叁肆伍陆柒捌玖'.substr(val.substr(i, 1), 1) + unit.substr(i, 1); + } + // 正则处理 + v = v + .replace(/零角零分$/, '整') + .replace(/零[仟佰拾]/g, '零') + .replace(/零{2,}/g, '零') + .replace(/零([亿|万])/g, '$1') + .replace(/零+元/, '元') + .replace(/亿零{0,3}万/, '亿') + .replace(/^元/, '零元'); + // 返回结果 + return v; +} + +/** + * 手机号码 + * @param val 当前值字符串 + * @returns 返回 true: 手机号码正确 + */ +export function verifyPhone(val: string) { + // false: 手机号码不正确 + if (!/^((12[0-9])|(13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(18[0|1,5-9]))\d{8}$/.test(val)) return false; + // true: 手机号码正确 + else return true; +} + +/** + * 国内电话号码 + * @param val 当前值字符串 + * @returns 返回 true: 国内电话号码正确 + */ +export function verifyTelPhone(val: string) { + // false: 国内电话号码不正确 + if (!/\d{3}-\d{8}|\d{4}-\d{7}/.test(val)) return false; + // true: 国内电话号码正确 + else return true; +} + +/** + * 登录账号 (字母开头,允许5-16字节,允许字母数字下划线) + * @param val 当前值字符串 + * @returns 返回 true: 登录账号正确 + */ +export function verifyAccount(val: string) { + // false: 登录账号不正确 + if (!/^[a-zA-Z][a-zA-Z0-9_]{4,15}$/.test(val)) return false; + // true: 登录账号正确 + else return true; +} + +/** + * 密码 (以字母开头,长度在6~16之间,只能包含字母、数字和下划线) + * @param val 当前值字符串 + * @returns 返回 true: 密码正确 + */ +export function verifyPassword(val: string) { + // false: 密码不正确 + if (!/^[a-zA-Z]\w{5,15}$/.test(val)) return false; + // true: 密码正确 + else return true; +} + +/** + * 强密码 (字母+数字+特殊字符,长度在6-16之间) + * @param val 当前值字符串 + * @returns 返回 true: 强密码正确 + */ +export function verifyPasswordPowerful(val: string) { + // false: 强密码不正确 + if (!/^(?![a-zA-z]+$)(?!\d+$)(?![!@#$%^&\.*]+$)(?![a-zA-z\d]+$)(?![a-zA-z!@#$%^&\.*]+$)(?![\d!@#$%^&\.*]+$)[a-zA-Z\d!@#$%^&\.*]{6,16}$/.test(val)) return false; + // true: 强密码正确 + else return true; +} + +/** + * 密码强度 + * @param val 当前值字符串 + * @description 弱:纯数字,纯字母,纯特殊字符 + * @description 中:字母+数字,字母+特殊字符,数字+特殊字符 + * @description 强:字母+数字+特殊字符 + * @returns 返回处理后的字符串:弱、中、强 + */ +export function verifyPasswordStrength(val: string) { + let v = ''; + // 弱:纯数字,纯字母,纯特殊字符 + if (/^(?:\d+|[a-zA-Z]+|[!@#$%^&\.*]+){6,16}$/.test(val)) v = '弱'; + // 中:字母+数字,字母+特殊字符,数字+特殊字符 + if (/^(?![a-zA-z]+$)(?!\d+$)(?![!@#$%^&\.*]+$)[a-zA-Z\d!@#$%^&\.*]{6,16}$/.test(val)) v = '中'; + // 强:字母+数字+特殊字符 + if (/^(?![a-zA-z]+$)(?!\d+$)(?![!@#$%^&\.*]+$)(?![a-zA-z\d]+$)(?![a-zA-z!@#$%^&\.*]+$)(?![\d!@#$%^&\.*]+$)[a-zA-Z\d!@#$%^&\.*]{6,16}$/.test(val)) v = '强'; + // 返回结果 + return v; +} + +/** + * IP地址 + * @param val 当前值字符串 + * @returns 返回 true: IP地址正确 + */ +export function verifyIPAddress(val: string) { + // false: IP地址不正确 + if (!/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/.test(val)) return false; + // true: IP地址正确 + else return true; +} + +/** + * 邮箱 + * @param val 当前值字符串 + * @returns 返回 true: 邮箱正确 + */ +export function verifyEmail(val: string) { + // false: 邮箱不正确 + if (!/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(val)) return false; + // true: 邮箱正确 + else return true; +} + +/** + * 身份证 + * @param val 当前值字符串 + * @returns 返回 true: 身份证正确 + */ +export function verifyIdCard(val: string) { + // false: 身份证不正确 + if (!/^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/.test(val)) return false; + // true: 身份证正确 + else return true; +} + +/** + * 姓名 + * @param val 当前值字符串 + * @returns 返回 true: 姓名正确 + */ +export function verifyFullName(val: string) { + // false: 姓名不正确 + if (!/^[\u4e00-\u9fa5]{1,6}(·[\u4e00-\u9fa5]{1,6}){0,2}$/.test(val)) return false; + // true: 姓名正确 + else return true; +} + +/** + * 邮政编码 + * @param val 当前值字符串 + * @returns 返回 true: 邮政编码正确 + */ +export function verifyPostalCode(val: string) { + // false: 邮政编码不正确 + if (!/^[1-9][0-9]{5}$/.test(val)) return false; + // true: 邮政编码正确 + else return true; +} + +/** + * url 处理 + * @param val 当前值字符串 + * @returns 返回 true: url 正确 + */ +export function verifyUrl(val: string) { + // false: url不正确 + if (!/^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/i.test(val)) return false; + // true: url正确 + else return true; +} + +/** + * 车牌号 + * @param val 当前值字符串 + * @returns 返回 true:车牌号正确 + */ +export function verifyCarNum(val: string) { + // false: 车牌号不正确 + if (!/^(([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z](([0-9]{5}[DF])|([DF]([A-HJ-NP-Z0-9])[0-9]{4})))|([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z][A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳使领]))$/.test(val)) return false; + // true:车牌号正确 + else return true; +} diff --git a/src/utils/wartermark.ts b/src/utils/wartermark.ts new file mode 100644 index 0000000..b897ed1 --- /dev/null +++ b/src/utils/wartermark.ts @@ -0,0 +1,47 @@ +// 页面添加水印效果 +const setWatermark = (str: string) => { + const id = '1.23452384164.123412416'; + if (document.getElementById(id) !== null) document.body.removeChild(<HTMLElement>document.getElementById(id)); + const can = document.createElement('canvas'); + can.width = 200; + can.height = 130; + const cans: any = can.getContext('2d'); + cans.rotate((-20 * Math.PI) / 180); + cans.font = '12px Vedana'; + cans.fillStyle = 'rgba(200, 200, 200, 0.30)'; + cans.textBaseline = 'Middle'; + cans.fillText(str, can.width / 10, can.height / 2); + const div = document.createElement('div'); + div.id = id; + div.style.pointerEvents = 'none'; + div.style.top = '15px'; + div.style.left = '0px'; + div.style.position = 'fixed'; + div.style.zIndex = '10000000'; + div.style.width = `${document.documentElement.clientWidth}px`; + div.style.height = `${document.documentElement.clientHeight}px`; + div.style.background = `url(${can.toDataURL('image/png')}) left top repeat`; + document.body.appendChild(div); + return id; +}; + +/** + * 页面添加水印效果 + * @method set 设置水印 + * @method del 删除水印 + */ +const watermark = { + // 设置水印 + set: (str: string) => { + let id = setWatermark(str); + if (document.getElementById(id) === null) id = setWatermark(str); + }, + // 删除水印 + del: () => { + let id = '1.23452384164.123412416'; + if (document.getElementById(id) !== null) document.body.removeChild(<HTMLElement>document.getElementById(id)); + }, +}; + +// 导出方法 +export default watermark; diff --git a/src/views/accidentManagementSystem/accidentCases/component/DailogCases.vue b/src/views/accidentManagementSystem/accidentCases/component/DailogCases.vue new file mode 100644 index 0000000..3bcf4a6 --- /dev/null +++ b/src/views/accidentManagementSystem/accidentCases/component/DailogCases.vue @@ -0,0 +1,187 @@ +<template> + <el-dialog v-model="dialogVisible" @close="resetForm(ruleFormRef)" :fullscreen="full" :title="titles" width="50%" draggable> + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-form :model="form" ref="ruleFormRef" :rules="rules" :disabled="disabled" label-width="120px"> + <el-row> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="标题" size="default" prop="caseTitle"> + <el-input v-model="form.caseTitle" /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="11" :md="11" :lg="11" :xl="11" class="mb20"> + <el-form-item label="发布时间" size="default" prop="caseTime"> + <el-date-picker + v-model="form.caseTime" + format="YYYY-MM-DD HH:mm:ss" + value-format="YYYY-MM-DD HH:mm:ss" + type="datetime" + placeholder="请选择" + style="width: 100%" + /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="23" :md="23" :lg="23" :xl="23" class="mb20"> + <el-form-item label="内容" size="default" prop="caseContent"> + <Wangeditor v-if="dialogVisible" style="width: 100%" :value="form.caseContent" + @change="changeCaseContent" showTop=""></Wangeditor> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="resetForm(ruleFormRef)" size="default">关闭</el-button> + <el-button type="primary" v-if="disabled == false" @click="submitForm(ruleFormRef)" size="default">确定</el-button> + </span> + </template> + </el-dialog> +</template> +<script lang="ts"> +import { defineComponent, ref, reactive } from 'vue'; +import { timeDate } from '/@/assets/index.ts'; +import type { FormInstance, FormRules } from 'element-plus'; +import { Search, FullScreen } from '@element-plus/icons-vue'; +import { ElMessageBox, ElMessage, ElButton, ElInput, TabsPaneContext } from 'element-plus'; +import { accidentManagementSystemApi } from '/@/api/accidentManagementSystem'; +import Wangeditor from './wangEditor/index.vue'; + + +export default defineComponent({ + components: {Wangeditor}, + setup(props, { emit }) { + const getWangEditorValue = (str:string) => { + console.log(str); + } + const ruleFormRef = ref<FormInstance>(); + const dialogVisible = ref<boolean>(false); + const form = ref({ + caseTitle: '',///案例标题 + caseContent: '',///案例内容 + caseTime: '', + }); + const changeCaseContent = (e) => { + form.value.caseContent = e + } + const targetType = ref(); + const disabled = ref(false); + const titles = ref(); + const titleT = ref(); + const openDailog = (title: string, id: number) => { + dialogVisible.value = true; + titles.value = `${title}事故案例`; + titleT.value = title; + // targetType.value = type; + disabled.value = title == '查看' ? true : false; + if (title == '查看' || title == '修改') { + accidentManagementSystemApi() + .getaccidentCaseDetail(id) + .then((res) => { + if (res.data.code == 200) { + form.value = res.data.data; + } else { + ElMessage.error(res.data.msg); + } + }); + } + }; + const rules = reactive<FormRules>({ + caseTitle: [ + { + required: true, + message: '案例标题不能为空', + trigger: 'blur', + }, + ], + caseTime: [ + { + required: true, + message: '发布时间不能为空', + trigger: 'blur', + }, + ], + }); + const submitForm = async (formEl: FormInstance | undefined) => { + if (!formEl) return; + await formEl.validate((valid, fields) => { + if (valid) { + if (titleT.value == '新建') { + delete form.value.id; + dialogVisible.value = false; + accidentManagementSystemApi() + .getaccidentCaseAdd(form.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + message: res.data.msg, + type: 'success', + }); + emit('onAdd'); + } else { + ElMessage.error(res.data.msg); + } + }); + }else{ + dialogVisible.value = false; + accidentManagementSystemApi() + .getaccidentCaseUpdata(form.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + message: res.data.msg, + type: 'success', + }); + emit('onAdd'); + } else { + ElMessage.error(res.data.msg); + } + }); + } + + } else { + console.log('error submit!', fields); + } + }); + }; + const resetForm = (formEl: FormInstance | undefined) => { + if (!formEl) return; + formEl.resetFields(); + form.value = {} + console.log(form.value) + dialogVisible.value = false; + }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + return { + timeDate, + ruleFormRef, + titleT, + rules, + submitForm, + resetForm, + form, + dialogVisible, + openDailog, + Search, + full, + toggleFullscreen, + FullScreen, + targetType, + disabled, + titles, + changeCaseContent + }; + }, +}); +</script> +<style scoped> +.el-row { + padding: 0 0 20px 0; +} +</style> \ No newline at end of file diff --git a/src/views/accidentManagementSystem/accidentCases/component/wangEditor/index.vue b/src/views/accidentManagementSystem/accidentCases/component/wangEditor/index.vue new file mode 100644 index 0000000..3953efc --- /dev/null +++ b/src/views/accidentManagementSystem/accidentCases/component/wangEditor/index.vue @@ -0,0 +1,174 @@ +<template> + <div class="editor"> + <div ref="toolbar" class="toolbar" :class="showTop"> + </div> + <div ref="editor" class="text"> + </div> + </div> +</template> + +<script> + import E from 'wangeditor' + // import {uploadNew,downloadNew} from '@/api/upload'; + // import defaultUrl from "@/api/defaultUrl"; + export default { + name: 'editoritem', + data() { + return { + // uploadPath, + editor: null, + info_: null, + // defaultUrl:defaultUrl, + defaultUrl:'', + } + }, + model: { + prop: 'value', + event: 'change' + }, + props: { + value: { + type: String, + default: '' + }, + isClear: { + type: Boolean, + default: false + }, + showTop: { + type: String, + default: '' + }, + }, + watch: { + isClear(val) { + // 触发清除文本域内容 + if (val) { + this.editor.txt.clear() + this.info_ = null + } + }, + value: function(value) { + if (value !== this.editor.txt.html()) { + this.editor.txt.html(this.value) + } + } + //value为编辑框输入的内容,这里我监听了一下值,当父组件调用得时候,如果给value赋值了,子组件将会显示父组件赋给的值 + }, + mounted() { + var that =this + that.setEditor() + that.editor.txt.html(that.value) + }, + methods: { + setEditor() { + var that =this + this.editor = new E(this.$refs.toolbar, this.$refs.editor) + // 配置菜单 + this.editor.config.menus = [ + 'head', // 标题 + 'bold', // 粗体 + 'fontSize', // 字号 + 'fontName', // 字体 + 'italic', // 斜体 + 'underline', // 下划线 + 'strikeThrough', // 删除线 + 'foreColor', // 文字颜色 + 'backColor', // 背景颜色 + 'link', // 插入链接 + 'list', // 列表 + 'justify', // 对齐方式 + 'quote', // 引用 + 'emoticon', // 表情 + // 'image', // 插入图片 + 'table', // 表格 + // 'video', // 插入视频 + 'code', // 插入代码 + 'undo', // 撤销 + 'redo' // 重复 + ] + + //配置上传图片 + this.editor.config.uploadImgShowBase64 = false // base 64 存储图片 + this.editor.config.uploadImgServer = 'http://otp.cdinfotech.top/file/upload_images'// 配置服务器端地址 + this.editor.config.uploadImgHeaders = { }// 自定义 header + this.editor.config.uploadFileName = 'file' // 后端接受上传文件的参数名 + this.editor.config.uploadImgMaxSize = 2 * 1024 * 1024 // 将图片大小限制为 2M + this.editor.config.uploadImgMaxLength = 1 // 限制一次最多上传 3 张图片 + this.editor.config.uploadImgTimeout = 3 * 60 * 1000 // 设置超时时间 + this.editor.config.uploadImgHooks = { + fail: (xhr, editor, result) => { + // 插入图片失败回调 + }, + success: (xhr, editor, result) => { + // 图片上传成功回调 + }, + timeout: (xhr, editor) => { + // 网络超时的回调 + }, + error: (xhr, editor) => { + // 图片上传错误的回调 + }, + customInsert: (insertImg, result, editor) => { + // 图片上传成功,插入图片的回调 + //result为上传图片成功的时候返回的数据,这里我打印了一下发现后台返回的是data:[{url:"路径的形式"},...] + // console.log(result.data[0].url) + //insertImg()为插入图片的函数 + //循环插入图片 + // for (let i = 0; i < 1; i++) { + // console.log(result) + let url = "http://otp.cdinfotech.top"+result.url + insertImg(url) + // } + } + } + this.editor.config.customUploadImg = function (files, insert) { + let form = new FormData(); + form.append('file', files[0]); + form.append('dir', 'temp1') + // uploadNew(form).then(res=>{ + // if(res.result){ + // let url = that.defaultUrl+`/upload/downloadNew?path=`+encodeURI(res.data.fileUrl) + // insert(url) + // that.$message("上传成功", 'success'); + // }else { + // that.$message.error("上传失败"); + // } + // + // }) + } + + this.editor.config.onchange = (html) => { + this.info_ = html // 绑定当前逐渐地值 + this.$emit('change', this.info_) // 将内容同步到父组件中 + } + // 创建富文本编辑器 + this.editor.create() + //是否可编辑 + if (this.showTop=='hiddenClass'){ + this.editor.disable() + } + } + } + } +</script> + +<style scoped> + .editor { + /*margin: 0 auto;*/ + position: relative; + z-index: 100; + } + .toolbar { + width: 100%; + border: 1px solid #ccc; + } + .text { + border: 1px solid #ccc; + min-height: 250px; + } + .hiddenClass{ + display: none; + + } +</style> diff --git a/src/views/accidentManagementSystem/accidentCases/index.vue b/src/views/accidentManagementSystem/accidentCases/index.vue new file mode 100644 index 0000000..38728a1 --- /dev/null +++ b/src/views/accidentManagementSystem/accidentCases/index.vue @@ -0,0 +1,274 @@ +<template> + <div> + <el-form :model="ruleForm" status-icon label-width="20px" class="topTitle"> + <el-row> + <el-col :span="4"> + <el-form-item> + <el-input v-model="ruleForm.searchParams.caseTitle" size="default" placeholder="请输入关键词" /> + </el-form-item> + </el-col> + <!-- <el-col :span="4"> + <el-form-item> + <el-input v-model="ruleForm.searchParams.indexNum" size="default" placeholder="目标指标编号" /> + </el-form-item> + </el-col> --> + <el-col :span="16"> + <el-form-item> + <el-button type="primary" size="default" @click="listApi">查询</el-button> + <el-button size="default" @click="resetForm">重置</el-button> + </el-form-item> + </el-col> + </el-row> + </el-form> + <div class="minCenter"> + <div class="btns"> + <div> + <el-button size="default" type="primary" :icon="Plus" @click="openD('新建')">新建</el-button> + <!-- <el-button size="default" type="warning" :disabled="warning" :icon="EditPen" plain @click="openD('修改', deletAll[0])">修改</el-button> --> + <el-button size="default" type="danger" :disabled="danger" :icon="Delete" plain @click="onDeleteAll">删除</el-button> + </div> + </div> + <el-table ref="multipleTableRef" :data="tableData" @selection-change="handleSelectionChange" style="width: 100%"> + <el-table-column type="selection" align="center" width="55" /> + <el-table-column label="序号" align="center" type="index" width="70" /> + <el-table-column label="标题" align="center" property="caseTitle" sortable /> + <el-table-column property="caseTime" align="center" label="发布时间" sortable /> + <!-- <el-table-column property="year" label="年度" align="center" sortable show-overflow-tooltip /> + <el-table-column property="value" label="指标值" align="center" sortable show-overflow-tooltip /> --> + <el-table-column label="操作" align="center" sortable show-overflow-tooltip> + <template #default="scope"> + <el-button link type="primary" size="small" :icon="View" @click="jump(scope.row.id)">查看</el-button> + <el-button link type="primary" size="small" :icon="EditPen" @click="openD('修改', scope.row.id)">编辑</el-button> + <el-button link type="primary" size="small" :icon="Delete" @click="onDelete(scope.row.id)">删除</el-button> + </template> + </el-table-column> + </el-table> + <div class="pages"> + <el-pagination + v-model:currentPage="currentPage4" + v-model:page-size="pageSize4" + :page-sizes="[10, 20, 30, 40]" + layout="total, sizes, prev, pager, next, jumper" + :total="total" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + </div> + <DailogCases ref="Show" @onAdd="add"></DailogCases> + </div> +</template> +<script lang="ts"> +import DailogCases from './component/DailogCases.vue'; +import { ref, toRefs, reactive, onMounted, defineComponent } from 'vue'; +import { ElMessageBox, ElMessage, ElButton, ElInput, TabsPaneContext, FormInstance } from 'element-plus'; +import { Plus, Delete, Upload, Download, Refresh, View, EditPen } from '@element-plus/icons-vue'; +import { accidentManagementSystemApi } from '/@/api/accidentManagementSystem'; +import { useRouter } from 'vue-router'; +export default defineComponent({ + components: { ElButton, ElInput, DailogCases }, + setup() { + // 搜索条件 + const ruleForm = reactive({ + pageSize: 10, + pageIndex: 1, + searchParams: { + caseTitle: '', + }, + }); + // 下方导航与表格 + const tableData = ref([]); + const currentPage4 = ref(); + const pageSize4 = ref(); + const total = ref(); + const resetForm = () => { + ruleForm.searchParams.caseTitle = ''; + listApi(); + }; + const listApi = () => { + accidentManagementSystemApi() + .getaccidentCaseList(ruleForm) + .then((res) => { + if (res.data.code == 200) { + tableData.value = res.data.data; + currentPage4.value = res.data.pageIndex; + pageSize4.value = res.data.pageSize; + total.value = res.data.total; + } else { + ElMessage.error(res.data.msg); + } + }); + }; + onMounted(() => { + listApi(); + }); + + const handleSizeChange = (val: number) => { + // console.log(`${val} items per page`); + ruleForm.pageSize = val; + listApi(); + }; + const handleCurrentChange = (val: number) => { + // console.log(`current page: ${val}`); + ruleForm.pageIndex = val; + listApi(); + }; + const activeNames = ref('1'); + // 打开弹窗 + const Show = ref(); + const openD = (title: String, id: number) => { + Show.value.openDailog(title, id); + }; + // 删除 + const onDelete = (id: number) => { + let arr = []; + arr.push(id); + ElMessageBox.confirm('确定删除所选项吗?', 'Warning', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + console.log(arr); + accidentManagementSystemApi() + .getaccidentCaseDelete(arr) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + message: res.data.msg, + type: 'success', + }); + listApi(); + } else { + ElMessage.error(res.data.msg); + } + }); + }) + .catch(() => { + // ElMessage({ + // type: 'info', + // message: 'Delete canceled', + // }); + }); + }; + // 批量删除 + const warning = ref(true); + const danger = ref(true); + const deletAll = ref(); + const handleSelectionChange = (val: any) => { + let valId = JSON.parse(JSON.stringify(val)); + let arr = []; + for (let i = 0; i < valId.length; i++) { + arr.push(valId[i].id); + } + deletAll.value = arr; + if (val.length == 1) { + warning.value = false; + danger.value = false; + } else if (val.length == 0) { + warning.value = true; + danger.value = true; + } else { + warning.value = true; + danger.value = false; + } + }; + const onDeleteAll = () => { + ElMessageBox.confirm('确定删除所选项吗?', 'Warning', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + accidentManagementSystemApi() + .getaccidentCaseDelete(deletAll.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + message: res.data.msg, + type: 'success', + }); + listApi(); + } else { + ElMessage.error(res.data.msg); + } + }); + }) + .catch(() => { + ElMessage({ + type: 'info', + message: 'Delete canceled', + }); + }); + }; + const add = () => { + listApi(); + }; + let router = useRouter(); + let jump = (id:any) => { + router.push({ + path: '/accidentCasesCop' , + query:{ + id:id, + } + }); + }; + + return { + jump, + router, + listApi, + add, + resetForm, + tableData, + currentPage4, + pageSize4, + total, + ruleForm, + handleSizeChange, + handleCurrentChange, + Show, + openD, + activeNames, + onDelete, + warning, + danger, + deletAll, + handleSelectionChange, + onDeleteAll, + Plus, + Delete, + Upload, + Download, + Refresh, + View, + EditPen, + }; + }, +}); +</script> +<style scoped> +.topTitle { + background-color: #fff; + padding: 20px 0px 20px 0px; +} +.minCenter { + width: 100%; + background-color: #fff; + margin-top: 10px; + padding: 0 20px; +} +.btns { + padding: 20px 0px 10px 0px; + display: flex; + justify-content: space-between; +} +.pages { + padding: 20px 0; + display: flex; + justify-content: right; +} +.tableC { + margin: 0 10%; +} +</style> \ No newline at end of file diff --git a/src/views/accidentManagementSystem/accidentCasesCop/component/wangEditor/index.vue b/src/views/accidentManagementSystem/accidentCasesCop/component/wangEditor/index.vue new file mode 100644 index 0000000..3953efc --- /dev/null +++ b/src/views/accidentManagementSystem/accidentCasesCop/component/wangEditor/index.vue @@ -0,0 +1,174 @@ +<template> + <div class="editor"> + <div ref="toolbar" class="toolbar" :class="showTop"> + </div> + <div ref="editor" class="text"> + </div> + </div> +</template> + +<script> + import E from 'wangeditor' + // import {uploadNew,downloadNew} from '@/api/upload'; + // import defaultUrl from "@/api/defaultUrl"; + export default { + name: 'editoritem', + data() { + return { + // uploadPath, + editor: null, + info_: null, + // defaultUrl:defaultUrl, + defaultUrl:'', + } + }, + model: { + prop: 'value', + event: 'change' + }, + props: { + value: { + type: String, + default: '' + }, + isClear: { + type: Boolean, + default: false + }, + showTop: { + type: String, + default: '' + }, + }, + watch: { + isClear(val) { + // 触发清除文本域内容 + if (val) { + this.editor.txt.clear() + this.info_ = null + } + }, + value: function(value) { + if (value !== this.editor.txt.html()) { + this.editor.txt.html(this.value) + } + } + //value为编辑框输入的内容,这里我监听了一下值,当父组件调用得时候,如果给value赋值了,子组件将会显示父组件赋给的值 + }, + mounted() { + var that =this + that.setEditor() + that.editor.txt.html(that.value) + }, + methods: { + setEditor() { + var that =this + this.editor = new E(this.$refs.toolbar, this.$refs.editor) + // 配置菜单 + this.editor.config.menus = [ + 'head', // 标题 + 'bold', // 粗体 + 'fontSize', // 字号 + 'fontName', // 字体 + 'italic', // 斜体 + 'underline', // 下划线 + 'strikeThrough', // 删除线 + 'foreColor', // 文字颜色 + 'backColor', // 背景颜色 + 'link', // 插入链接 + 'list', // 列表 + 'justify', // 对齐方式 + 'quote', // 引用 + 'emoticon', // 表情 + // 'image', // 插入图片 + 'table', // 表格 + // 'video', // 插入视频 + 'code', // 插入代码 + 'undo', // 撤销 + 'redo' // 重复 + ] + + //配置上传图片 + this.editor.config.uploadImgShowBase64 = false // base 64 存储图片 + this.editor.config.uploadImgServer = 'http://otp.cdinfotech.top/file/upload_images'// 配置服务器端地址 + this.editor.config.uploadImgHeaders = { }// 自定义 header + this.editor.config.uploadFileName = 'file' // 后端接受上传文件的参数名 + this.editor.config.uploadImgMaxSize = 2 * 1024 * 1024 // 将图片大小限制为 2M + this.editor.config.uploadImgMaxLength = 1 // 限制一次最多上传 3 张图片 + this.editor.config.uploadImgTimeout = 3 * 60 * 1000 // 设置超时时间 + this.editor.config.uploadImgHooks = { + fail: (xhr, editor, result) => { + // 插入图片失败回调 + }, + success: (xhr, editor, result) => { + // 图片上传成功回调 + }, + timeout: (xhr, editor) => { + // 网络超时的回调 + }, + error: (xhr, editor) => { + // 图片上传错误的回调 + }, + customInsert: (insertImg, result, editor) => { + // 图片上传成功,插入图片的回调 + //result为上传图片成功的时候返回的数据,这里我打印了一下发现后台返回的是data:[{url:"路径的形式"},...] + // console.log(result.data[0].url) + //insertImg()为插入图片的函数 + //循环插入图片 + // for (let i = 0; i < 1; i++) { + // console.log(result) + let url = "http://otp.cdinfotech.top"+result.url + insertImg(url) + // } + } + } + this.editor.config.customUploadImg = function (files, insert) { + let form = new FormData(); + form.append('file', files[0]); + form.append('dir', 'temp1') + // uploadNew(form).then(res=>{ + // if(res.result){ + // let url = that.defaultUrl+`/upload/downloadNew?path=`+encodeURI(res.data.fileUrl) + // insert(url) + // that.$message("上传成功", 'success'); + // }else { + // that.$message.error("上传失败"); + // } + // + // }) + } + + this.editor.config.onchange = (html) => { + this.info_ = html // 绑定当前逐渐地值 + this.$emit('change', this.info_) // 将内容同步到父组件中 + } + // 创建富文本编辑器 + this.editor.create() + //是否可编辑 + if (this.showTop=='hiddenClass'){ + this.editor.disable() + } + } + } + } +</script> + +<style scoped> + .editor { + /*margin: 0 auto;*/ + position: relative; + z-index: 100; + } + .toolbar { + width: 100%; + border: 1px solid #ccc; + } + .text { + border: 1px solid #ccc; + min-height: 250px; + } + .hiddenClass{ + display: none; + + } +</style> diff --git a/src/views/accidentManagementSystem/accidentCasesCop/index.vue b/src/views/accidentManagementSystem/accidentCasesCop/index.vue new file mode 100644 index 0000000..52831de --- /dev/null +++ b/src/views/accidentManagementSystem/accidentCasesCop/index.vue @@ -0,0 +1,82 @@ +<template> + <div style="background-color:#fff;height: 800px;"> + <el-form :model="form" label-width="120px"> + <el-row> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="标题" size="default" prop="caseTitle"> + <el-input v-model="form.caseTitle" /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="11" :md="11" :lg="11" :xl="11" class="mb20"> + <el-form-item label="发布时间" size="default" prop="caseTime"> + <el-date-picker + v-model="form.caseTime" + format="YYYY-MM-DD HH:mm:ss" + value-format="YYYY-MM-DD HH:mm:ss" + type="datetime" + placeholder="请选择" + style="width: 100%" + /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="23" :md="23" :lg="23" :xl="23" class="mb20"> + <el-form-item label="内容" size="default" prop="caseContent"> + <Wangeditor style="width: 100%" :value="form.caseContent" + showTop=""></Wangeditor> + </el-form-item> + </el-col> + </el-row> + </el-form> + </div> +</template> +<script lang="ts"> +import { defineComponent, ref, reactive, onMounted } from 'vue'; +import { timeDate } from '/@/assets/index.ts'; +import type { FormInstance, FormRules } from 'element-plus'; +import { Search, FullScreen } from '@element-plus/icons-vue'; +import { ElMessageBox, ElMessage, ElButton, ElInput, TabsPaneContext } from 'element-plus'; +import { accidentManagementSystemApi } from '/@/api/accidentManagementSystem'; +import Wangeditor from './component/wangEditor/index.vue'; +import {useRoute} from 'vue-router' +export default defineComponent({ + components: {Wangeditor}, + setup(props, { emit }) { + const route = useRoute(); + const num = route.query.id; + const dialogVisible = ref<boolean>(false); + const form = ref({ + caseTitle: '',///案例标题 + caseContent: '',///案例内容 + caseTime: '', + }); + onMounted(()=>{ + listApi(num) + }) + const listApi=(id:any)=>{ + accidentManagementSystemApi() + .getaccidentCaseDetail(id) + .then((res) => { + if (res.data.code == 200) { + form.value = res.data.data; + } else { + ElMessage.error(res.data.msg); + } + }); + } + + return { + timeDate, + form, + dialogVisible, + Search, + route, + num + }; + }, +}); +</script> +<style scoped> +.el-col { + padding: 20px 0 0 0; +} +</style> \ No newline at end of file diff --git a/src/views/accidentManagementSystem/accidentExpress/component/numberOfCasualties.vue b/src/views/accidentManagementSystem/accidentExpress/component/numberOfCasualties.vue new file mode 100644 index 0000000..c586c23 --- /dev/null +++ b/src/views/accidentManagementSystem/accidentExpress/component/numberOfCasualties.vue @@ -0,0 +1,461 @@ +<template> + <div class="system-edit-user-container"> + <el-dialog + title="编辑伤亡人员" + v-model="isShowDialog" + width="769px" + draggable + :fullscreen="full" + > + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-form + ref="ruleFormRef" + :model="ruleForm" + size="default" + label-width="120px" + > + <el-row :gutter="35"> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="姓名" prop="name"> + <el-input v-model="ruleForm.name" placeholder="请输入姓名"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="性别" prop="sex"> + <el-select v-model="ruleForm.gender" class="w100" placeholder="请选择人员性别"> + <el-option label="男" value="false"></el-option> + <el-option label="女" value="true"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="身份证号码" prop="teamName"> + <el-input v-model="ruleForm.card" placeholder="请输入身份证号码"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="伤害描述"> + <el-input v-model="ruleForm.injuryDesc" type="textarea" placeholder="请输入内容" + maxlength="150"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="受损描述"> + <el-input v-model="ruleForm.damageDesc" type="textarea" placeholder="请输入内容" + maxlength="150"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-button v-if="!disabled" size="default" type="primary" @click="onAdd()">添加</el-button> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-table :data="tableData" style="width: 100%"> + <el-table-column prop="name" label="姓名"/> + <el-table-column prop="gender" label="性别"> + <template #default="scope"> + <div v-if="scope.row.gender==false"> + 男 + </div> + <div v-else> + 女 + </div> + </template> + </el-table-column> + <el-table-column prop="card" label="身份证"/> + <el-table-column prop="injuryDesc" label="伤害描述"/> + <el-table-column prop="damageDesc" label="受损描述"/> + <el-table-column v-if="!disabled" label="操作" width="60" align="center" fixed="right"> + <template #default="scope"> + <el-button size="small" text type="primary" @click="onDelete(scope.row.id)"> + 删除 + </el-button> + </template> + </el-table-column> + </el-table> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="onCancel" size="default">关闭</el-button> + <el-button size="default" type="primary" @click="submitForm(ruleFormRef)">确定</el-button> + </span> + </template> + </el-dialog> + <CheckTemplate ref="Shows"/> + <userSelections ref="userRef"/> + <RegionsDialog ref="openRef"/> + </div> +</template> + +<script lang="ts"> + import { + reactive, + ref, + defineComponent + } from 'vue'; + + import type { + UploadUserFile, + FormInstance, + // FormRules, + } from 'element-plus' + import {ElMessage} from 'element-plus'; + import { + Search, + FullScreen + } from '@element-plus/icons-vue' + import UserSelections from "/@/components/userSelections/index.vue" + import CheckTemplate from '/@/components/checkTemplate/index.vue' + import RegionsDialog from '/@/components/regionsDialog/index.vue' + import {accidentManagementSystemApi} from '/@/api/accidentManagementSystem'; + + export default defineComponent({ + name: 'openEdit', + components: { + CheckTemplate, + UserSelections, + RegionsDialog, + }, + setup() { + const isShowDialog = ref(false) + + const ruleFormRef = ref<FormInstance>() + //定义表单 + const accidentExpressId = ref() + const ruleForm = reactive({ + accidentExpressId: accidentExpressId, + name: '', // 姓名 + gender: '', //性别 + card: '', // 身份证 + injuryDesc: '', // 伤害描述 + damageDesc: '', // 受损描述 + }); + const tableData = ref([]) + const disabled = ref([]) + // 打开弹窗 + const openDialog = (id, type) => { + accidentExpressId.value = id + isShowDialog.value = true; + disabled.value = type + onList() + }; + // 一览 + const onList = () => { + accidentManagementSystemApi() + .casualtyList(accidentExpressId.value) + .then((res) => { + if (res.data.code == '200') { + tableData.value = res.data.data + console.log('伤亡人员一览', tableData.value) + } + }) + }; + // 添加 + const onAdd = () => { + if (accidentExpressId.value != null && accidentExpressId.value != '') { + accidentManagementSystemApi() + .casualtyAdd(ruleForm) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: '添加成功', + type: 'success', + }); + onList() + } + }) + } else { + ElMessage({ + showClose: true, + message: '请先添加事故快报', + type: 'error', + }); + } + }; + // 删除 + const onDelete = (id) => { + accidentManagementSystemApi() + .casualtyDel(id) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: '删除成功', + type: 'success', + }); + onList() + } + }) + }; + // 关闭弹窗 + const closeDialog = () => { + isShowDialog.value = false; + }; + // 取消 + const onCancel = () => { + closeDialog(); + }; + //日期选择器 + const value1 = ref('') + // 上传附件 + const fileList = ref<UploadUserFile[]>([]) + // 可选择树 + const treeSelect = ref() + const tree = [ + { + value: '1', + label: 'Level one 1', + children: [ + { + value: '1-1', + label: 'Level two 1-1', + children: [ + { + value: '1-1-1', + label: 'Level three 1-1-1', + }, + ], + }, + ], + }, + { + value: '2', + label: 'Level one 2', + children: [ + { + value: '2-1', + label: 'Level two 2-1', + children: [ + { + value: '2-1-1', + label: 'Level three 2-1-1', + }, + ], + }, + { + value: '2-2', + label: 'Level two 2-2', + children: [ + { + value: '2-2-1', + label: 'Level three 2-2-1', + }, + ], + }, + ], + }, + { + value: '3', + label: 'Level one 3', + children: [ + { + value: '3-1', + label: 'Level two 3-1', + children: [ + { + value: '3-1-1', + label: 'Level three 3-1-1', + }, + ], + }, + { + value: '3-2', + label: 'Level two 3-2', + children: [ + { + value: '3-2-1', + label: 'Level three 3-2-1', + }, + ], + }, + ], + }, + ] + //定义树形下拉框 + const responsibleDepartment = ref() + const data = [ + { + value: '1', + label: '广汇能源综合物流发展有限责任公司', + children: [ + { + value: '1-1', + label: '经营班子', + children: [], + }, + ], + }, + { + value: '2', + label: '生产运行部', + children: [ + { + value: '2-1', + label: '灌装一班', + children: [] + }, + { + value: '2-2', + label: '工艺四班', + children: [], + }, + ], + }, + { + value: '3', + label: '设备部', + children: [ + { + value: '3-1', + label: '仪表班', + children: [], + }, + { + value: '3-2', + label: '机修班', + children: [], + }, + ], + }, + ] + // 必填项提示 + // const rules = reactive<FormRules>({ + // teamName: [ + // { + // required: true, + // message: '队伍名称不能为空', + // trigger: 'change', + // }, + // ], + // teamLevel: [ + // { + // required: true, + // message: '队伍级别不能为空', + // trigger: 'change', + // }, + // ], + // teamLeader: [ + // { + // required: true, + // message: '队伍负责人不能为空', + // trigger: 'change', + // }, + // ], + // responsibleDepartment: [ + // { + // required: true, + // message: '负责人部门不能为空', + // trigger: 'change', + // }, + // ], + // teamPhone: [ + // { + // required: true, + // message: '负责人手机不能为空', + // trigger: 'change', + // }, + // ], + // telephone: [ + // { + // required: true, + // message: '固定电话不能为空', + // trigger: 'change', + // }, + // ], + // }) + // 表单提交验证必填项 + const submitForm = async (formEl: FormInstance | undefined) => { + if (!formEl) return + await formEl.validate((valid, fields) => { + if (valid) { + console.log('submit!') + closeDialog(); + } else { + console.log('error submit!', fields) + } + }) + + } + // 应急队伍弹窗 + const Shows = ref() + const daiInpt = () => { + Shows.value.openDailog() + } + // 选择区域弹窗 + const openRef = ref() + const regionsDialog = () => { + openRef.value.openDailog() + } + // 打开用户选择弹窗 + const userRef = ref(); + const openUser = () => { + userRef.value.openDialog(); + }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + return { + openDialog, + closeDialog, + isShowDialog, + onCancel, + fileList, + responsibleDepartment, + data, + Search, + ruleForm, + value1, + treeSelect, + tree, + daiInpt, + Shows, + ruleFormRef, + submitForm, + // rules, + openUser, + userRef, + regionsDialog, + openRef, + toggleFullscreen, + FullScreen, + full, + tableData, + onAdd, + onDelete, + accidentExpressId, + disabled + }; + }, + }); +</script> +<style scoped lang="scss"> + .textarea { + height: 168px !important; + } + + .textarea ::v-deep .el-textarea__inner { + height: 168px !important; + } + + ::v-deep .el-table__cell { + font-weight: 400; + } + + .el-divider--horizontal { + height: 0; + margin: 0; + border-top: transparent; + } + + .el-select { + width: 100%; + } +</style> \ No newline at end of file diff --git a/src/views/accidentManagementSystem/accidentExpress/component/openAdd.vue b/src/views/accidentManagementSystem/accidentExpress/component/openAdd.vue new file mode 100644 index 0000000..f72d850 --- /dev/null +++ b/src/views/accidentManagementSystem/accidentExpress/component/openAdd.vue @@ -0,0 +1,534 @@ +<template> + <div class="system-edit-user-container"> + <el-dialog :title="titles" v-model="isShowDialog" width="50%" draggable :fullscreen="full" + destroy-on-close @close="closeDialog(ruleFormRef)"> + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-form ref="ruleFormRef" :model="ruleForm" :rules="rules" size="default" label-width="140px"> + <el-row :gutter="35"> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="事故名称" prop="accidentName"> + <el-input v-model="ruleForm.accidentName" :disabled="disabled" placeholder="请填写事故名称"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="事故部门" placeholder="请选择" prop="accidentDepartmentId"> + <el-tree-select + v-model="ruleForm.accidentDepartmentId" + :disabled="disabled" + :props="propse" + :data="newTreeList" + class="w100" + placeholder="请选择" + /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="发生地点" prop="occurrencePlace"> + <el-input v-model="ruleForm.occurrencePlace" :disabled="disabled" placeholder="请填写发生地点"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="发生时间" prop="occurrenceTime"> + <!--<el-input v-model="ruleForm.occurrenceTime" :disabled="disabled" placeholder="请填写发生时间"></el-input>--> + <el-date-picker + :disabled="disabled" + v-model="ruleForm.occurrenceTime" + value-format="YYYY-MM-DD HH:mm:ss" + type="datetime" + class="w100" + placeholder="选择日期时间" + /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="事故原因" prop="accidentCause"> + <el-select v-model="ruleForm.accidentCause" :disabled="disabled" class="w100" placeholder="请选择"> + <el-option label="人的不安全行为" value="1"></el-option> + <el-option label="物的不安全状态" value="2"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="是否有伤亡" prop="casualties"> + <el-radio-group v-model="ruleForm.casualties" :disabled="disabled" @change="typeChang"> + <el-radio :label="true">是</el-radio> + <el-radio :label="false">否</el-radio> + </el-radio-group> + <el-button v-if="ruleForm.casualties" type="primary" style="margin-left: 20px" + :icon="Edit" @click="openDai(ruleFormRef)" round plain /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="事故简要经过" prop="accidentBriefProcess"> + <el-input + v-model="ruleForm.accidentBriefProcess" + :disabled="disabled" + type="textarea" + placeholder="请填写事故简要经过" + maxlength="150" + ></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="事故原因初步分析" prop="accidentCausesPreliminaryAnalysis"> + <el-input + v-model="ruleForm.accidentCausesPreliminaryAnalysis" + :disabled="disabled" + type="textarea" + placeholder="请填写事故原因初步分析" + maxlength="150" + ></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="应急防范措施" prop="emergencyPrecautions"> + <el-input + v-model="ruleForm.emergencyPrecautions" + :disabled="disabled" + type="textarea" + placeholder="请填写应急防范措施" + maxlength="150" + ></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="事故照片" prop="fileList"> + <!--<el-input v-model="ruleForm.fileList" :disabled="disabled"--> + <!--type="textarea" placeholder="请填写应急防范措施" maxlength="150"></el-input>--> + <uploaderImg :fileList="fileList" :disabled="disabled" + :systemName="'INCIDENT_MANAGE'" @successUploader="successUploader"></uploaderImg> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="resetForm(ruleFormRef)" size="default">关闭</el-button> + <el-button size="default" v-if="disabled == true ? false : true" type="primary" + @click="submitForm(titles, ruleFormRef)">确定</el-button> + </span> + </template> + </el-dialog> + <NumberOfCasualties ref="ShowUser"></NumberOfCasualties> + <CheckTemplate ref="Shows" /> + <userSelections ref="userRef" /> + <RegionsDialog ref="openRef" /> + </div> +</template> + +<script lang="ts"> +import { reactive, ref, defineComponent, defineEmits, onMounted } from 'vue'; + +import type { UploadUserFile, FormInstance, FormRules } from 'element-plus'; +import { ElMessage,ElMessageBox, } from 'element-plus'; +import { Search, FullScreen, Edit } from '@element-plus/icons-vue'; +import NumberOfCasualties from '/@/views/accidentManagementSystem/accidentExpress/component/numberOfCasualties.vue'; +import UserSelections from '/@/components/userSelections/index.vue'; +import CheckTemplate from '/@/components/checkTemplate/index.vue'; +import uploaderImg from '/@/components/uploaderImg/index.vue'; +import RegionsDialog from '/@/components/regionsDialog/index.vue'; +import { accidentManagementSystemApi } from '/@/api/accidentManagementSystem'; +import { goalManagementApi } from '/@/api/goalManagement'; +export default defineComponent({ + name: 'openAdd', + components: { + CheckTemplate, + UserSelections, + RegionsDialog, + NumberOfCasualties, + uploaderImg, + }, + setup(props, { emit }) { + const isShowDialog = ref(false); + + const ruleFormRef = ref<FormInstance>(); + //定义表单 + const ruleForm = ref({ + emergencyPrecautions: '', + accidentCausesPreliminaryAnalysis: '', + accidentBriefProcess: '', + casualties: '', + accidentCause: '', + occurrenceTime: '', + occurrencePlace: '', + accidentDepartmentId: '', + accidentName: '', + fileList: [], + id: '', + }); + const titles = ref(); + const disabled = ref(); + // 打开弹窗 + const openDialog = async (title: string, id: number, type: boolean) => { + isShowDialog.value = true; + titles.value = title; + disabled.value = type; + if (title == '查看事故快报' || title == '修改事故快报') { + accidentManagementSystemApi() + .accidentScarh(id) + .then((res) => { + if (res.data.code == 200) { + ruleForm.value = res.data.data; + fileList.value = (res.data.data.fileList?res.data.data.fileList:[]) + initFileListData() + } + }); + } + }; + const initFileListData = async () => { + for(var a = 0;a<fileList.value.length;a++){ + await goalManagementApi() + .searchFile(fileList.value[a].fileName) + .then((res) => { + fileList.value[a].url = res.data + }) + } + } + //日期选择器 + const value1 = ref(''); + // 上传附件 + const fileList = ref([]); + // 上传成功组装数据 + const successUploader = (list) =>{ + fileList.value = list + const formFileList = [] + for(var a = 0;a<fileList.value.length;a++){ + formFileList.push( + { + fileName:fileList.value[a].fileName, + fileUrl:'' + } + ) + } + ruleForm.value.fileList = formFileList + } + // 可选择树 + const treeSelect = ref(); + + //定义树形下拉框 + const responsibleDepartment = ref(); + const data = []; + //el-tree-select回显 + const propse = { + label: 'depName', + children: 'children', + }; + const newTreeList = []; + //得到部门树 + const department = async () => { + await goalManagementApi() + .getTreedepartment() + .then((res) => { + if (res.data.code == 200) { + data.value = res.data.data; + getTreeList(res.data.data, newTreeList); + } else { + ElMessage.error(res.data.msg); + } + }); + }; + // 递归树状数据且修改字段名 + const getTreeList = (treeList, newTreeList) => { + treeList.map((c) => { + let tempData = { + depName: c.depName, + value: c.depId, + children: [], + }; + if (c.children && c.children.length > 0) { + tempData.children = []; + getTreeList(c.children, tempData.children); + } + newTreeList.push(tempData); + }); + }; + onMounted(() => { + department(); + }); + // 必填项提示 + const rules = reactive<FormRules>({ + accidentName: [ + { + required: true, + message: '事故名称不能为空', + trigger: 'change', + }, + ], + accidentDepartmentId: [ + { + required: true, + message: '事故部门不能为空', + trigger: 'change', + }, + ], + occurrencePlace: [ + { + required: true, + message: '发生地点不能为空', + trigger: 'change', + }, + ], + occurrenceTime: [{ type: 'date', required: true, message: '发生时间不能为空', trigger: 'blur' }], + accidentCause: [ + { + required: true, + message: '事故原因不能为空', + trigger: 'change', + }, + ], + casualties: [ + { + required: true, + message: '是否有伤亡不能为空', + trigger: 'change', + }, + ], + accidentBriefProcess: [ + { + required: true, + message: '事故简要经过不能为空', + trigger: 'change', + }, + ], + accidentCausesPreliminaryAnalysis: [ + { + required: true, + message: '事故原因初步分析不能为空', + trigger: 'change', + }, + ], + emergencyPrecautions: [ + { + required: true, + message: '应急防范措施不能为空', + trigger: 'change', + }, + ], + }); + // 子传父 + // const emit=defineEmits(['myAdd']) + // 表单提交验证必填项 + const submitForm = async (title: string, formEl: FormInstance | undefined) => { + if(!ruleForm.value.fileList){ + ruleForm.value.fileList = [] + } + if (title == '新建事故快报') { + if (!formEl) return; + await formEl.validate((valid, fields) => { + if (valid) { + isShowDialog.value = false; + if(ruleForm.value.id==null||ruleForm.value.id==''){ + ruleForm.value.id = null; + accidentManagementSystemApi() + .accidentAdd(ruleForm.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'success', + }); + emit('myAdd', true); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + emit('myAdd', true); + } + formEl.resetFields(); + }); + }else { + ElMessage({ + showClose: true, + message: '添加成功', + type: 'success', + }); + emit('myAdd', true); + } + + } else { + console.log('error submit!', fields); + } + }); + } else if (title == '修改事故快报') { + if (!formEl) return; + await formEl.validate((valid, fields) => { + if (valid) { + isShowDialog.value = false; + accidentManagementSystemApi() + .accidentView(ruleForm.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: '修改成功', + type: 'success', + }); + emit('myAdd', true); + formEl.resetFields(); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + emit('myAdd', true); + } + }); + } else { + console.log('error submit!', fields); + } + }); + } + }; + const resetForm = (formEl: FormInstance | undefined) => { + isShowDialog.value = false; + if (!formEl) return; + formEl.resetFields(); + }; + const closeDialog = (formEl: FormInstance | undefined) => { + formEl.resetFields(); + fileList.value = [] + console.log(ruleForm); + isShowDialog.value = false; + }; + // 是否有伤亡弹窗 + const typeChang = () => { + console.log('tag', ruleForm); + }; + const ShowUser = ref(); + const openDai = async (formEl: FormInstance | undefined) => { + if(ruleForm.value.id==null||ruleForm.value.id==''){ + if(!ruleForm.value.fileList){ + ruleForm.value.fileList = [] + } + if (!formEl) return; + await formEl.validate((valid, fields) => { + if (valid) { + // isShowDialog.value = false; + ElMessageBox.confirm('确认添加此事故快报?', '提示', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + accidentManagementSystemApi() + .accidentAdd(ruleForm.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'success', + }); + ruleForm.value.id = res.data.data.id + ShowUser.value.openDialog(ruleForm.value.id, disabled.value); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + } + }); + }) + .catch(() => {}); + } else { + console.log('error submit!', fields); + } + }); + // ElMessage({ + // showClose: true, + // message: '请先添加事故快报', + // type: 'info', + // }); + }else { + ShowUser.value.openDialog(ruleForm.value.id, disabled.value); + } + + }; + // 应急队伍弹窗 + const Shows = ref(); + const daiInpt = () => { + Shows.value.openDailog(); + }; + // 选择区域弹窗 + const openRef = ref(); + const regionsDialog = () => { + openRef.value.openDailog(); + }; + // 打开用户选择弹窗 + const userRef = ref(); + const openUser = () => { + userRef.value.openDialog(); + }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + return { + ShowUser, + typeChang, + openDialog, + isShowDialog, + fileList, + responsibleDepartment, + data, + Search, + Edit, + ruleForm, + value1, + treeSelect, + daiInpt, + Shows, + ruleFormRef, + submitForm, + resetForm, + rules, + openUser, + userRef, + regionsDialog, + openDai, + openRef, + toggleFullscreen, + FullScreen, + full, + titles, + disabled, + emit, + propse, + department, + getTreeList, + newTreeList, + closeDialog, + successUploader + }; + }, +}); +</script> +<style scoped lang="scss"> +.textarea { + height: 168px !important; +} +.textarea ::v-deep .el-textarea__inner { + height: 168px !important; +} +::v-deep .el-table__cell { + font-weight: 400; +} +.el-divider--horizontal { + height: 0; + margin: 0; + border-top: transparent; +} +.el-select { + width: 100%; +} +</style> diff --git a/src/views/accidentManagementSystem/accidentExpress/index.vue b/src/views/accidentManagementSystem/accidentExpress/index.vue new file mode 100644 index 0000000..b6e134b --- /dev/null +++ b/src/views/accidentManagementSystem/accidentExpress/index.vue @@ -0,0 +1,359 @@ +<template> + <div class="system-user-container"> + <el-card shadow="hover"> + <div class="system-user-search mb15"> + <el-input size="default" v-model="listQuery.searchParams.accidentName" placeholder="事故名称" style="max-width: 215px" /> + <el-button size="default" type="primary" class="ml10" @click="listApi"> 查询 </el-button> + <el-button size="default" class="ml10" @click="submitReset"> 重置 </el-button> + </div> + <div class="button_Line"> + <div class="button_Left"> + <el-button size="default" type="primary" @click="onOpenAdd"> + <el-icon> <Plus /> </el-icon>新建 + </el-button> + <el-button size="default" type="warning" plain :disabled="warning" @click="onEdit('修改', deletAll[0])"> + <el-icon> <Edit /> </el-icon>修改 + </el-button> + <el-button size="default" type="danger" @click="onDeleteAll" plain :disabled="danger"> + <el-icon> <Delete /> </el-icon>删除 + </el-button> + </div> + <div class="button_Right"> + <!-- <el-button @click="upButton"> + <el-icon> + <Upload /> + </el-icon> + </el-button> + <el-button> + <el-icon> + <Download /> + </el-icon> + </el-button> + <el-button> + <el-icon> + <Refresh /> + </el-icon> + </el-button> --> + </div> + </div> + <el-table :data="tableData" style="width: 100%" ref="multipleTableRef" @selection-change="handleSelectionChange"> + <el-table-column align="center" type="selection" width="55" /> + <el-table-column align="center" prop="accidentName" label="事故名称" show-overflow-tooltip sortable></el-table-column> + <el-table-column align="center" prop="deptName" label="事故部门" show-overflow-tooltip sortable></el-table-column> + <el-table-column align="center" prop="occurrencePlace" label="发生地点" show-overflow-tooltip sortable></el-table-column> + <el-table-column align="center" prop="occurrenceTime" label="发生时间" show-overflow-tooltip sortable + :formatter="dateFormat"></el-table-column> + <el-table-column align="center" prop="accidentCause" label="事故原因" show-overflow-tooltip sortable> + <template #default="scope"> + <div v-if="scope.row.accidentCause=='1'">人的不安全行为</div> + <div v-if="scope.row.accidentCause=='2'">物的不安全状态</div> + </template> + </el-table-column> + <el-table-column align="center" prop="createName" label="创建人" show-overflow-tooltip sortable></el-table-column> + <el-table-column align="center" prop="gmtModitify" label="更新时间" show-overflow-tooltip sortable + :formatter="dateFormat"></el-table-column> + <el-table-column label="操作" width="260" align="center" fixed="right"> + <template #default="scope"> + <!-- <el-button size="small" text disabled> + <el-icon style="margin-right: 5px"> <Upload /> </el-icon>上报 + </el-button> --> + <el-button size="small" text type="primary" @click="onEdit('修改', scope.row.id)"> + <el-icon style="margin-right: 5px"> <EditPen /> </el-icon>修改 + </el-button> + <el-button size="small" text type="primary" @click="onEdit('详情', scope.row.id)"> + <el-icon style="margin-right: 5px"> <View /> </el-icon>详情 + </el-button> + <el-button size="small" text type="primary" @click="onDelete(scope.row.id)"> + <el-icon style="margin-right: 5px"> <Delete /> </el-icon>删除 + </el-button> + </template> + </el-table-column> + </el-table> + <div class="pages"> + <el-pagination + v-if="tableData.length == 0 ? false : true" + v-model:currentPage="pageIndex" + v-model:page-size="pageSize" + :page-sizes="[10, 20, 30]" + :pager-count="5" + layout="total, sizes, prev, pager, next, jumper" + :total="total" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + </el-card> + <OpenAdd ref="addRef" @myAdd="onMyAdd" /> + <upData ref="upShow"></upData> + </div> +</template> + +<script lang="ts"> +import { reactive, onMounted, ref, defineComponent } from 'vue'; +import { ElTable, ElMessage, ElMessageBox } from 'element-plus'; +import { Plus, View, Download, Refresh, EditPen, Edit, Delete, Upload } from '@element-plus/icons-vue'; +import OpenAdd from '/@/views/accidentManagementSystem/accidentExpress/component/openAdd.vue'; +import UpData from '/@/views/contingencyManagement/panManagement/component/upData.vue'; +import { accidentManagementSystemApi } from '/@/api/accidentManagementSystem'; +export default defineComponent({ + name: 'index', + components: { + EditPen, + Plus, + Upload, + Download, + Refresh, + Edit, + Delete, + UpData, + OpenAdd, + View, + }, + + setup() { + // 列表参数 + const listQuery = reactive({ + pageIndex: 1, + pageSize: 10, + searchParams: { + accidentName: '', + }, + }); + // 定义表格数据 + const tableData = ref([]); + // 列表数据请求 + const listApi = async () => { + let res = await accidentManagementSystemApi().accidentList(listQuery); + if (res.data.code == 200) { + tableData.value = res.data.data; + pageIndex.value = res.data.pageIndex; + pageSize.value = res.data.pageSize; + total.value = res.data.total; + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + } + }; + onMounted(() => { + listApi(); + }); + // 重置 + const submitReset = () => { + listQuery.searchParams.accidentName = ''; + listApi(); + }; + // 分页 + const pageIndex = ref(); + const pageSize = ref(); + const total = ref(); + // 分页改变 + const handleSizeChange = (val: number) => { + // console.log(`${val} items per page`); + listQuery.pageSize = val; + listApi(); + }; + // 分页未改变 + const handleCurrentChange = (val: number) => { + // console.log(`current page: ${val}`); + listQuery.pageIndex = val; + listApi(); + }; + const warning = ref(true); + const danger = ref(true); + const deletAll = ref(); + const handleSelectionChange = (val: any) => { + let valId = JSON.parse(JSON.stringify(val)); + let arr = []; + for (let i = 0; i < valId.length; i++) { + arr.push(valId[i].id); + } + deletAll.value = arr; + console.log(deletAll.value) + if (val.length == 1) { + warning.value = false; + danger.value = false; + } else if (val.length == 0) { + warning.value = true; + danger.value = true; + } else { + warning.value = true; + danger.value = false; + } + }; + + // 打开新增弹窗 + const addRef = ref(); + const onOpenAdd = () => { + addRef.value.openDialog('新建事故快报',false); + }; + // 新增后刷新 + const onMyAdd = (e: boolean) => { + if (e) { + listApi(); + } else { + listApi(); + } + }; + // 删除 + const onDelete = (data: any) => { + ElMessageBox.confirm('确定删除所选项吗?', '提示', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + accidentManagementSystemApi() + .accidentDele([data]) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'success', + }); + listApi(); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + listApi(); + } + }); + }) + .catch(() => {}); + }; + // 多选删除 + const onDeleteAll = () => { + ElMessageBox.confirm('确定删除所选项吗?', '提示', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + accidentManagementSystemApi() + .accidentDele(deletAll.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'success', + }); + listApi(); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + listApi(); + } + }); + }) + .catch(() => {}); + }; + // 上传 + const upShow = ref(); + const upButton = () => { + upShow.value.openDialog(); + }; + + // 打开修改用户弹窗 + const onEdit = (val: string, row: object) => { + if (val == '详情') { + addRef.value.openDialog('查看事故快报',row,true); + } else { + addRef.value.openDialog('修改事故快报',row,false); + } + }; +//格式化表格时间 + const dateFormat = (row,column) => { + // 获取单元格数据 + let data = row[column.property]; + if(data == null) { + return null; + } + let dt = new Date(data) + return dt.getFullYear() + '-' + (dt.getMonth() + 1) + '-' + dt.getDate() + ' ' + dt.getHours() + ':' + dt.getMinutes() + ':' + dt.getSeconds() + }; + return { + upButton, + upShow, + tableData, + pageIndex, + pageSize, + total, + handleSizeChange, + handleCurrentChange, + onEdit, + onOpenAdd, + addRef, + listQuery, + listApi, + submitReset, + warning, + danger, + handleSelectionChange, + onMyAdd, + onDelete, + deletAll, + onDeleteAll, + dateFormat + }; + }, +}); +</script> +<style scoped lang="scss"> +.table_Box { + padding: 20px; + background-color: #fff; +} +.tableForm { + margin-top: 10px; +} +/*按钮行*/ +.button_Line { + display: flex; + flex-direction: row; + justify-content: space-between; +} +//分页 +.pages { + display: flex; + justify-content: flex-end; + margin-top: 15px; +} +::v-deep .el-pagination .el-pager li { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +::v-deep .el-pagination .el-pager li.is-active { + background-color: #409eff; + color: #fff; +} +::v-deep .el-pagination .btn-prev { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +::v-deep .el-pagination button:disabled { + color: #c0c4cc; +} +::v-deep .el-pagination .btn-next { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +</style> \ No newline at end of file diff --git a/src/views/accidentManagementSystem/accidentReport/component/openAdd.vue b/src/views/accidentManagementSystem/accidentReport/component/openAdd.vue new file mode 100644 index 0000000..11591fe --- /dev/null +++ b/src/views/accidentManagementSystem/accidentReport/component/openAdd.vue @@ -0,0 +1,723 @@ +<template> + <div class="system-edit-user-container"> + <el-dialog :title="titles" v-model="isShowDialog" width="800px" draggable :fullscreen="full" @close="resetForm(ruleFormRef)"> + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-form ref="ruleFormRef" :model="ruleForm" size="default" :rules="rules" label-width="140px"> + <el-row :gutter="35"> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="事故快报" prop="accidentExpressId"> + <el-input v-model="accidentName" :disabled="true" placeholder="请选择" class="input-with-select"> + <template #append> + <el-button :icon="Search" @click="daiInpt" /> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="事故部门" placeholder="请选择" prop="accidentDepartmentId"> + <!--<el-input v-model="ruleForm.accidentDepartmentName" class="input-with-select" />--> + <el-tree-select v-model="accidentDepartmentId" :disabled="true" :data="newTreeList" :props="propse" class="w100" placeholder="请选择" /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="事故发生地点" prop="occurrencePlace"> + <el-input v-model="occurrencePlace" :disabled="true" placeholder="请填写发生地点"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="发生时间" prop="occurrenceTime"> + <el-date-picker + v-model="occurrenceTime" + :disabled="true" + value-format="YYYY-MM-DD HH:mm:ss" + type="datetime" + class="w100" + placeholder="选择日期时间" + /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="事故类别" prop="accidentType"> + <el-select v-model="ruleForm.accidentType" :disabled="disabled" class="w100" placeholder="请选择"> + <el-option label="人员伤亡事故" value="1"></el-option> + <el-option label="火灾爆炸事故" value="2"></el-option> + <el-option label="危险品泄露事故" value="3"></el-option> + <el-option label="设备事故" value="4"></el-option> + <el-option label="工艺事故" value="5"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="事故等级" prop="accidentGrade"> + <el-select v-model="ruleForm.accidentGrade" :disabled="disabled" class="w100" placeholder="请选择"> + <el-option label="一级" value="1"></el-option> + <el-option label="二级" value="2"></el-option> + <el-option label="三级" value="3"></el-option> + <el-option label="四级" value="4"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="经济损失" prop="economicLoss"> + <el-input v-model="ruleForm.economicLoss" :disabled="disabled" placeholder="请填写经济损失"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="轻伤人数" prop="minorInjuryNum"> + <el-input v-model="ruleForm.minorInjuryNum" :disabled="disabled" placeholder="请填写轻伤人数"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="重伤人数" prop="seriousInjuryNum"> + <el-input v-model="ruleForm.seriousInjuryNum" :disabled="disabled" placeholder="请填写重伤人数"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="死亡人数" prop="deathNum"> + <el-input v-model="ruleForm.deathNum" :disabled="disabled" placeholder="请填写死亡人数"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="事故原因" prop="accidentCause"> + <el-input v-model="ruleForm.accidentCause" :disabled="disabled" placeholder="请填写事故原因"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="要求报告完成期限" prop="reportDeadline"> + <el-date-picker + v-model="ruleForm.reportDeadline" + :disabled="disabled" + type="datetime" + class="w100" + placeholder="选择日期时间" + value-format="YYYY-MM-DD HH:mm:ss" + /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="事故级别" prop="accidentLevel"> + <el-select v-model="ruleForm.accidentLevel" :disabled="disabled" class="w100" placeholder="请选择"> + <el-option label="特大事故" value="1"></el-option> + <el-option label="重大事故" value="2"></el-option> + <el-option label="较大事故" value="3"></el-option> + <el-option label="一般事故" value="4"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="事故延期申请" prop="accidentDelayApply"> + <el-input v-model="ruleForm.accidentDelayApply" :disabled="disabled" placeholder="请填写事故延期申请"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="原因综合分析(直接分析)" prop="comprehensiveAnalysisDirect"> + <el-input + v-model="ruleForm.comprehensiveAnalysisDirect" + :disabled="disabled" + type="textarea" + placeholder="请填写原因综合分析(直接分析)" + maxlength="150" + ></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="原因综合分析(间接分析)" prop="comprehensiveAnalysisIndirect"> + <el-input + v-model="ruleForm.comprehensiveAnalysisIndirect" + :disabled="disabled" + type="textarea" + placeholder="请填写原因综合分析(间接分析)" + maxlength="150" + ></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="整改措施" prop="rectificationMeasures"> + <el-input + v-model="ruleForm.rectificationMeasures" + :disabled="disabled" + type="textarea" + placeholder="请填写整改措施" + maxlength="150" + ></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="事故处理" prop="accidentHandling"> + <el-input + v-model="ruleForm.accidentHandling" + :disabled="disabled" + type="textarea" + placeholder="请填写事故处理" + maxlength="150" + ></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="填写人" prop="fillInUserName"> + <el-input v-model="ruleForm.fillInUserName" :disabled="true" placeholder="请选择" class="input-with-select"> + <template #append> + <el-button :icon="Search" @click="openUser" /> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="填写日期" prop="fillInTime"> + <el-date-picker + v-model="ruleForm.fillInTime" + :disabled="disabled" + type="datetime" + class="w100" + placeholder="选择日期时间" + value-format="YYYY-MM-DD HH:mm:ss" + /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="事故照片"> + <uploaderImg :fileList="ruleForm.expressFileList" :disabled="true"></uploaderImg> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="相关人员笔录" prop="relevantPersonnelRecords"> + <el-input + v-model="ruleForm.relevantPersonnelRecords" + :disabled="disabled" + type="textarea" + placeholder="请填写相关人员笔录" + maxlength="150" + ></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="事故状态" prop="status"> + <el-select v-model="ruleForm.status" :disabled="statusDisabled" class="w100" placeholder="请选择"> + <el-option label="处理中" :value="1"></el-option> + <el-option label="已处理" :value="2"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="事故分析会议纪要"> + <uploaderFile + :fileList="fileList" + :systemName="'INCIDENT_MANAGE'" + :disabled="disabled" + @successUploader="successUploader" + ></uploaderFile> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="其他材料" prop="otherMaterials"> + <el-input + v-model="ruleForm.otherMaterials" + :disabled="disabled" + type="textarea" + placeholder="请填写其他材料" + maxlength="150" + ></el-input> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="resetForm(ruleFormRef)" size="default">关闭</el-button> + <el-button size="default" type="primary" v-if="disabled == true ? false : true" @click="submitForm(titles, ruleFormRef)">确定</el-button> + </span> + </template> + </el-dialog> + <AccidentName @selectItem="onSelectItem" ref="Shows" /> + <DailogSearchUserManger @SearchUser="onUser" ref="userRef" /> + <RegionsDialog ref="openRef" /> + </div> +</template> + +<script lang="ts"> +import { reactive, ref, defineComponent, onMounted } from 'vue'; + +import type { UploadUserFile, FormInstance, FormRules } from 'element-plus'; +import { ElMessage } from 'element-plus'; +import { Search, FullScreen } from '@element-plus/icons-vue'; +import DailogSearchUserManger from '/@/components/DailogSearchUserManger/index.vue'; +import AccidentName from '/@/views/accidentManagementSystem/workInjuryDeclaration/component/accidentName.vue'; +import RegionsDialog from '/@/components/regionsDialog/index.vue'; +import uploaderImg from '/@/components/uploaderImg/index.vue'; +import uploaderFile from '/@/components/uploaderFile/index.vue'; +import { emergencySuppliesApi } from '/@/api/contingencyManagement/emergencyResources'; +import { accidentManagementSystemApi } from '/@/api/workInjuryDeclaration'; +import { goalManagementApi } from '/@/api/goalManagement'; + +export default defineComponent({ + name: 'openAdd', + components: { + AccidentName, + DailogSearchUserManger, + RegionsDialog, + uploaderImg, + uploaderFile, + }, + setup(props, { emit }) { + const isShowDialog = ref(false); + + const ruleFormRef = ref<FormInstance>(); + //定义表单 + const ruleForm = ref({ + accidentExpressId: '', + + accidentType: '', + accidentGrade: '', + economicLoss: '', + minorInjuryNum: '', + seriousInjuryNum: '', + deathNum: '', + accidentCause: '', + reportDeadline: '', + accidentLevel: '', + accidentDelayApply: '', + comprehensiveAnalysisDirect: '', + comprehensiveAnalysisIndirect: '', + rectificationMeasures: '', + accidentHandling: '', + fillInUserUid: '', + fillInUserName: '', + fillInTime: '', + relevantPersonnelRecords: '', + otherMaterials: '', + fileList: [], + status: '', + }); + const titles = ref(); + const disabled = ref(); + const statusDisabled = ref(true); + // 上传附件 + const fileList = ref([]); + // 打开弹窗 + const openDialog = (title: string, id: number, type: boolean, statusDisabledFlag: string) => { + isShowDialog.value = true; + titles.value = title; + disabled.value = type; + if (statusDisabledFlag.value == 'first') { + ruleForm.value.status = 1; + } else if (statusDisabledFlag.value == 'second') { + ruleForm.value.status = 2; + } + if (title == '修改事故报告') { + statusDisabled.value = false; + } else { + statusDisabled.value = true; + } + if (title == '查看事故报告' || title == '修改事故报告') { + accidentManagementSystemApi() + .seeAccidentReport(id) + .then((res) => { + if (res.data.code == 200) { + ruleForm.value = res.data.data; + accidentName.value = res.data.data.accidentName; + accidentDepartmentId.value = res.data.data.accidentDepartmentId; + occurrencePlace.value = res.data.data.occurrencePlace; + occurrenceTime.value = res.data.data.occurrenceTime; + fileList.value = res.data.data.fileList ? res.data.data.fileList : []; + initFileListData(); + } + }); + } + }; + const initFileListData = async () => { + //事故照片 + if (ruleForm.value.expressFileList) { + for (var a = 0; a < ruleForm.value.expressFileList.length; a++) { + await goalManagementApi() + .searchFile(ruleForm.value.expressFileList[a].fileName) + .then((res) => { + ruleForm.value.expressFileList[a].url = res.data; + console.log('ruleForm', ruleForm); + }); + } + } else { + ruleForm.value.expressFileList = []; + } + + // 事故分析会议纪要 + for (var a = 0; a < fileList.value.length; a++) { + fileList.value[a].name = fileList.value[a].fileName; + } + }; + // 上传成功组装数据 + const successUploader = (list) => { + fileList.value = list; + const formFileList = []; + for (var a = 0; a < fileList.value.length; a++) { + formFileList.push({ + fileName: fileList.value[a].fileName, + fileUrl: '', + }); + } + ruleForm.value.fileList = formFileList; + }; + // 取消 + const onCancel = (formEl: FormInstance | undefined) => { + resetForm(formEl); + }; + //日期选择器 + const value1 = ref(''); + + // 可选择树 + const treeSelect = ref(); + //定义树形下拉框 + const responsibleDepartment = ref(); + const data = []; + // 必填项提示 + const rules = reactive<FormRules>({ + accidentExpressId: [ + { + required: true, + message: '快报不能为空', + trigger: 'change', + }, + ], + accidentType: [ + { + required: true, + message: '事故类别不能为空', + trigger: 'change', + }, + ], + accidentGrade: [ + { + required: true, + message: '事故等级不能为空', + trigger: 'change', + }, + ], + economicLoss: [ + { + required: true, + message: '经济损失不能为空', + trigger: 'change', + }, + ], + reportDeadline: [ + { + required: true, + message: '要求报告完成期限不能为空', + trigger: 'blur', + }, + ], + accidentLevel: [ + { + required: true, + message: '事故级别不能为空', + trigger: 'change', + }, + ], + comprehensiveAnalysisDirect: [ + { + required: true, + message: '原因综合分析(直接分析)不能为空', + trigger: 'blur', + }, + ], + comprehensiveAnalysisIndirect: [ + { + required: true, + message: '原因综合分析(间接分析)不能为空', + trigger: 'blur', + }, + ], + rectificationMeasures: [ + { + required: true, + message: '整改措施不能为空', + trigger: 'blur', + }, + ], + accidentHandling: [ + { + required: true, + message: '事故处理不能为空', + trigger: 'change', + }, + ], + fillInUserName: [ + { + required: true, + message: '填写人不能为空', + trigger: 'change', + }, + ], + fillInTime: [ + { + type: 'date', + required: true, + message: '填写日期不能为空', + trigger: 'blur', + }, + ], + status: [ + { + required: true, + message: '事故状态不能为空', + trigger: 'change', + }, + ], + }); + const accidentDepartmentId = ref(); + const occurrencePlace = ref(); + const occurrenceTime = ref(); + const accidentName = ref(); + //事故快报回填 + const onSelectItem = (item: any) => { + console.log('item', item[0]); + ruleForm.value.accidentExpressId = item[0].id; + accidentName.value = item[0].accidentName; + accidentDepartmentId.value = item[0].accidentDepartmentId; + occurrencePlace.value = item[0].occurrencePlace; + occurrenceTime.value = item[0].occurrenceTime; + }; + // 表单提交验证必填项 + const submitForm = async (title: string, formEl: FormInstance | undefined) => { + delete ruleForm.value.accidentName; + delete ruleForm.value.accidentDepartmentId; + delete ruleForm.value.occurrencePlace; + delete ruleForm.value.occurrenceTime; + if (!ruleForm.value.fileList) { + ruleForm.value.fileList = []; + } + if (title == '新建事故报告') { + if (!formEl) return; + await formEl.validate((valid, fields) => { + if (valid) { + isShowDialog.value = false; + accidentManagementSystemApi() + .addAccidentReport(ruleForm.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'success', + }); + emit('myAdd', true); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + emit('myAdd', true); + } + formEl.resetFields(); + }); + } else { + console.log('error submit!', fields); + } + }); + } else if (title == '修改事故报告') { + if (!formEl) return; + await formEl.validate((valid, fields) => { + if (valid) { + //TODO 上传组件待定 + isShowDialog.value = false; + accidentManagementSystemApi() + .editAccidentReport(ruleForm.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: '修改成功', + type: 'success', + }); + emit('myAdd', true); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + emit('myAdd', true); + } + formEl.resetFields(); + }); + } else { + console.log('error submit!', fields); + } + }); + formEl.resetFields(); + ruleForm.value = { + accidentExpressId: '', + + accidentType: '', + accidentGrade: '', + economicLoss: '', + minorInjuryNum: '', + seriousInjuryNum: '', + deathNum: '', + accidentCause: '', + reportDeadline: '', + accidentLevel: '', + accidentDelayApply: '', + comprehensiveAnalysisDirect: '', + comprehensiveAnalysisIndirect: '', + rectificationMeasures: '', + accidentHandling: '', + fillInUserUid: '', + fillInUserName: '', + fillInTime: '', + relevantPersonnelRecords: '', + otherMaterials: '', + fileList: [], + status: '', + }; + } + }; + + const resetForm = (formEl: FormInstance | undefined) => { + isShowDialog.value = false; + if (!formEl) return; + formEl.resetFields(); + // ruleForm.value.accidentExpressId = item[0].id + ruleForm.value = {}; + fileList.value = []; + accidentName.value = ''; + accidentDepartmentId.value = ''; + occurrencePlace.value = ''; + occurrenceTime.value = ''; + }; + const handleChange = (val: number) => { + console.log(val); + }; + // 应急队伍弹窗 + const Shows = ref(); + const daiInpt = () => { + Shows.value.openDailog(); + }; + // 选择区域弹窗 + const openRef = ref(); + const regionsDialog = () => { + openRef.value.openDailog(); + }; + // 打开用户选择弹窗 + const userRef = ref(); + const openUser = () => { + userRef.value.openDailog(); + }; + const onUser = (userItem: any) => { + ruleForm.value.fillInUserUid = userItem[0].uid; + ruleForm.value.fillInUserName = userItem[0].realName; + }; + //el-tree-select回显 + const propse = { + label: 'depName', + children: 'children', + }; + const newTreeList = []; + //得到部门树 + const department = async () => { + await goalManagementApi() + .getTreedepartment() + .then((res) => { + if (res.data.code == 200) { + data.value = res.data.data; + getTreeList(res.data.data, newTreeList); + } else { + ElMessage.error(res.data.msg); + } + }); + }; + // 递归树状数据且修改字段名 + const getTreeList = (treeList, newTreeList) => { + treeList.map((c) => { + let tempData = { + depName: c.depName, + value: c.depId, + children: [], + }; + if (c.children && c.children.length > 0) { + tempData.children = []; + getTreeList(c.children, tempData.children); + } + newTreeList.push(tempData); + }); + }; + onMounted(() => { + department(); + }); + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + return { + openDialog, + isShowDialog, + onCancel, + fileList, + responsibleDepartment, + data, + Search, + ruleForm, + value1, + treeSelect, + daiInpt, + Shows, + ruleFormRef, + submitForm, + rules, + openUser, + userRef, + regionsDialog, + openRef, + toggleFullscreen, + FullScreen, + full, + onUser, + resetForm, + titles, + disabled, + emit, + handleChange, + onSelectItem, + newTreeList, + department, + getTreeList, + propse, + statusDisabled, + accidentDepartmentId, + occurrencePlace, + occurrenceTime, + accidentName, + successUploader, + initFileListData, + }; + }, +}); +</script> +<style scoped lang="scss"> +.textarea { + height: 168px !important; +} +.textarea ::v-deep .el-textarea__inner { + height: 168px !important; +} +::v-deep .el-table__cell { + font-weight: 400; +} +.el-divider--horizontal { + height: 0; + margin: 0; + border-top: transparent; +} +.el-select { + width: 100%; +} +::v-deep .el-form-item--default .el-form-item__label { + height: 100%; + text-align: right; +} +</style> diff --git a/src/views/accidentManagementSystem/accidentReport/index.vue b/src/views/accidentManagementSystem/accidentReport/index.vue new file mode 100644 index 0000000..57010f2 --- /dev/null +++ b/src/views/accidentManagementSystem/accidentReport/index.vue @@ -0,0 +1,404 @@ +<template> + <div class="system-user-container"> + <el-card shadow="hover"> + <el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick"> + <el-tab-pane + v-for="item in editableTabs" + :key="item.name" + :label="item.title" + :name="item.name" + > + <div class="button_Line"> + <div class="button_Left"> + <el-button size="default" type="primary" @click="onOpenAdd"> + <el-icon> + <Plus /> + </el-icon>新建 + </el-button> + <el-button size="default" type="warning" plain :disabled="warning" @click="onEdit('修改', deletAll[0])"> + <el-icon> + <Edit /> + </el-icon>修改 + </el-button> + <el-button size="default" type="danger" plain @click="onDeleteAll" :disabled="danger"> + <el-icon> + <Delete /> + </el-icon>删除 + </el-button> + </div> + <div class="button_Right"> + <el-button @click="upButton"> + <el-icon> + <Upload /> + </el-icon> + </el-button> + <el-button> + <el-icon> + <Download /> + </el-icon> + </el-button> + <el-button> + <el-icon> + <Refresh /> + </el-icon> + </el-button> + </div> + </div> + <el-table + :data="tableData" + style="width: 100%" + ref="multipleTableRef" + @selection-change="handleSelectionChange" + > + <el-table-column + type="selection" + width="55" + /> + <el-table-column prop="accidentName" label="事故名称" show-overflow-tooltip sortable></el-table-column> + <el-table-column prop="deptName" label="事故部门" show-overflow-tooltip sortable></el-table-column> + <el-table-column label="事故类别" show-overflow-tooltip sortable> + <template #default="scope"> + <span v-if="scope.row.accidentType==1">人员伤亡事故</span> + <span v-if="scope.row.accidentType==2">火灾爆炸事故</span> + <span v-if="scope.row.accidentType==3">危险品泄露事故</span> + <span v-if="scope.row.accidentType==4">设备事故</span> + <span v-if="scope.row.accidentType==5">工艺事故</span> + </template> + </el-table-column> + <el-table-column label="事故等级" show-overflow-tooltip sortable> + <template #default="scope"> + <span v-if="scope.row.accidentGrade==1">一级</span> + <span v-if="scope.row.accidentGrade==2">二级</span> + <span v-if="scope.row.accidentGrade==3">三级</span> + <span v-if="scope.row.accidentGrade==4">四级</span> + </template> + </el-table-column> + <el-table-column prop="occurrencePlace" label="发生地点" show-overflow-tooltip sortable></el-table-column> + <el-table-column prop="occurrenceTime" label="发生时间" show-overflow-tooltip sortable></el-table-column> + <el-table-column label="操作" width="260" align="center" fixed="right"> + <template #default="scope"> + <el-button size="small" text type="primary" @click="onEdit('详情',scope.row.id)"> + <el-icon style="margin-right: 5px"> <View /> </el-icon>查看 + </el-button> + <el-button size="small" text type="primary" @click="onEdit('修改',scope.row.id)"> + <el-icon style="margin-right: 5px"> <EditPen /> </el-icon>修改 + </el-button> + <el-button size="small" text type="primary" @click="onRowDel(scope.row.id)"> 删除 </el-button> + </template> + </el-table-column> + </el-table> + <div class="pages"> + <el-pagination + v-if="tableData.length == 0 ? false : true" + v-model:currentPage="pageIndex" + v-model:page-size="pageSize" + :page-sizes="[10, 20, 30]" + :pager-count="5" + layout="total, sizes, prev, pager, next, jumper" + :total="total" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + </el-tab-pane> + <!--<el-tab-pane label="已处理" name="second"></el-tab-pane>--> + </el-tabs> + </el-card> + <OpenAdd ref="addRef" @myAdd="onMyAdd" /> +<!-- <upData ref="upShow"></upData>--> + </div> +</template> + +<script lang="ts"> +import { + // toRefs, + reactive, + onMounted, + ref, + defineComponent +} from 'vue'; +import { + // ElTable, + ElMessageBox, + ElMessage, + TabsPaneContext, +} from 'element-plus'; +import { + Plus, + Upload, + Download, + Refresh, + EditPen, + View, + Delete, + Edit, +} from '@element-plus/icons-vue' +import OpenAdd from '/@/views/accidentManagementSystem/accidentReport/component/openAdd.vue' +import UpData from '/@/views/contingencyManagement/panManagement/component/upData.vue'; +import {accidentManagementSystemApi} from "/@/api/workInjuryDeclaration"; + + +export default defineComponent({ + name: 'systemUser', + components: { + EditPen, + Plus, + Upload, + Download, + Refresh, + UpData, + Edit, + Delete, + OpenAdd, + View, + }, + setup() { + const activeName = ref('first') + const statusDisabledFlag = ref('first')//控制弹窗中的事件状态是否可以修改 + const handleClick = (tab: TabsPaneContext, event: Event) => { + if(tab.props.name=='first'){ + listQuery.searchParams.status=1 + statusDisabledFlag.value = 'first' + listApi() + }else if(tab.props.name=='second'){ + listQuery.searchParams.status=2 + statusDisabledFlag.value = 'second' + listApi() + } + } + + const editableTabs = ref([ + { + title: '处理中', + name: 'first', + }, + { + title: '已处理', + name: 'second', + }, + ]) + // 列表参数 + const listQuery = reactive({ + pageIndex: 1, + pageSize: 10, + searchParams: { + status: 1, + }, + }); + // 定义表格数据 + const tableData = ref([]); + // 请求列表数据 + const listApi = async () => { + let res = await accidentManagementSystemApi().getAccidentReportList(listQuery); + // console.log(res); + if (res.data.code == 200) { + tableData.value = res.data.data; + pageIndex.value = res.data.pageIndex; + pageSize.value = res.data.pageSize; + total.value = res.data.total; + } else { + ElMessage.error(res.data.msg); + } + }; + const warning = ref(true); + const danger = ref(true); + const deletAll = ref(); + const handleSelectionChange = (val: any) => { + let valId = JSON.parse(JSON.stringify(val)); + let arr = []; + for (let i = 0; i < valId.length; i++) { + arr.push(valId[i].id); + } + deletAll.value = arr; + console.log(deletAll.value); + if (val.length == 1) { + warning.value = false; + danger.value = false; + } else if (val.length == 0) { + warning.value = true; + danger.value = true; + } else { + warning.value = true; + danger.value = false; + } + }; + // 页面加载时 + onMounted(() => { + listApi(); + }); + // 打开新建用户弹窗 + const addRef = ref(); + const onOpenAdd = () => { + addRef.value.openDialog('新建事故报告','',false,statusDisabledFlag); + }; + // 新增后刷新 + const onMyAdd = (e: boolean) => { + if (e) { + listApi(); + } else { + listApi(); + } + }; + // 打开修改用户弹窗 + const onEdit = (val: string, row: object) => { + if (val == '详情') { + addRef.value.openDialog('查看事故报告',row,true,statusDisabledFlag); + } else { + addRef.value.openDialog('修改事故报告',row,false,statusDisabledFlag); + } + }; + // 上传 + // const upShow=ref() + // const upButton=()=>{ + // upShow.value.openDialog() + // } + // 删除用户 + const onRowDel = (data: any) => { + var deleteList = [data] + ElMessageBox.confirm('确定删除所选项吗?', '提示', { + confirmButtonText: '确认', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + accidentManagementSystemApi() + .deleteAccidentReport(deleteList) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'success', + }); + listApi(); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + listApi(); + } + }); + }) + .catch(() => {}); + }; + // 多选删除 + const onDeleteAll = () => { + ElMessageBox.confirm('确定删除所选项吗?', '提示', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + accidentManagementSystemApi() + .deleteAccidentReport(deletAll.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'success', + }); + listApi(); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + listApi(); + } + }); + }) + .catch(() => {}); + }; + // 分页 + const pageIndex = ref(); + const pageSize = ref(); + const total = ref(); + // 分页改变 + const handleSizeChange = (val: number) => { + listQuery.pageSize = val; + }; + // 分页未改变 + const handleCurrentChange = (val: number) => { + listQuery.pageIndex = val; + }; + return { + onOpenAdd, + addRef, + activeName, + handleClick, + // upButton, + // upShow, + tableData, + pageIndex, + pageSize, + handleSizeChange, + handleCurrentChange, + listApi, + handleSelectionChange, + warning, + danger, + listQuery, + onRowDel, + total, + onMyAdd, + onDeleteAll, + onEdit, + editableTabs, + deletAll + }; + }, +}); +</script> +<style scoped lang="scss"> +.table_Box{ + padding: 20px; + background-color: #fff; +} +.tableForm{ + margin-top: 10px; +} +/*按钮行*/ +.button_Line{ + display: flex; + flex-direction: row; + justify-content: space-between; +} +//分页 +.pages{ + display: flex; + justify-content: flex-end; + margin-top: 15px; +} +::v-deep .el-pagination .el-pager li { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +::v-deep .el-pagination .el-pager li.is-active { + background-color: #409eff; + color: #fff; +} +::v-deep .el-pagination .btn-prev { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +::v-deep .el-pagination button:disabled{ + color: #c0c4cc; +} +::v-deep .el-pagination .btn-next{ + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +</style> \ No newline at end of file diff --git a/src/views/accidentManagementSystem/accidentStatistics/index.vue b/src/views/accidentManagementSystem/accidentStatistics/index.vue new file mode 100644 index 0000000..f543f1a --- /dev/null +++ b/src/views/accidentManagementSystem/accidentStatistics/index.vue @@ -0,0 +1,183 @@ +<template> + <div class="system-user-container"> + <el-card shadow="hover"> + <div class="system-user-search mb15"> + <el-form ref="ruleFormRef" size="default" label-width="80px" :inline="true"> + <el-row > + <el-col :span="5"> + <el-form-item prop="telephone" label="选择年月"> + <el-radio-group v-model="params.type" style="width:100%"> + <el-radio :label="2">年</el-radio> + <el-radio :label="1">月</el-radio> + </el-radio-group> + </el-form-item> + </el-col> + <el-col :span="6"> + <el-form-item v-if="params.type==2" prop="telephone" label="选择年"> + <el-date-picker + v-model="params.year" + :disabled="disabled" + type="year" + style="width:100%" + value-format="YYYY" + placeholder="选择日期时间" + /> + </el-form-item> + <el-form-item v-if="params.type==1" prop="telephone" label="选择月"> + <el-date-picker + v-model="params.realMonth" + :disabled="disabled" + type="month" + class="w100" + style="width:100%" + value-format="YYYY-MM" + placeholder="选择日期时间" + /> + </el-form-item> + </el-col> + <el-col :span="3"> + <el-button size="default" type="primary" class="ml10" @click="emergencySuppliesCount"> 查询</el-button> + </el-col> + </el-row> + </el-form> + <div class="echarts" ref="echarts1"> + + </div> + </div> + + </el-card> + + </div> +</template> +<script lang="ts"> + import { defineComponent, onMounted, ref } from 'vue'; + import * as echarts from 'echarts'; + import { ElMessage } from 'element-plus'; + import { goalManagementApi } from '/@/api/goalManagement'; + import { toNamespacedPath } from 'path/posix'; + export default defineComponent({ + setup() { + const params = ref({ + level:'', + type:2, + year:'2022', + month:'', + realMonth:'' + }) + const list = ref([]) +//加载数据 + const emergencySuppliesCount = () => { + if(params.value.type==2){ + params.value.month='' + } + if(params.value.type==1){ + params.value.year=params.value.realMonth.split('-')[0] + params.value.month=params.value.realMonth.split('-')[1] + } + goalManagementApi() + .accidentReportCount(params.value) + .then((res) => { + if (res.data.code == 200) { + var newList = [] + for(var a = 0;a<res.data.data.length;a++){ + newList.push( + { + name:res.data.data[a].name+":"+res.data.data[a].num, + value:res.data.data[a].num, + deathNum: res.data.data[a].deathNum, + economicLoss: res.data.data[a].economicLoss, + minorInjuryNum: res.data.data[a].minorInjuryNum, + seriousInjuryNum: res.data.data[a].seriousInjuryNum + } + ) + } + list.value = newList; + initPies() + } else { + ElMessage.error(res.data.msg); + } + }); + }; + const echarts1 = ref() + const initPies = () => { + var myChart = echarts.init(echarts1.value); + myChart.clear() + var option = { + tooltip: { + trigger: 'item', + textStyle:{ + fontSize:18 + }, + formatter(params){ + for(var x in params){ + return params.data.name.split(':')[0] +":"+params.data.value+'<br />'+ + '死亡人数:'+params.data.deathNum+'<br />'+ + '轻伤人数:'+params.data.minorInjuryNum+'<br />'+ + '重伤人数:'+params.data.seriousInjuryNum+'<br />'+ + '经济损失:'+params.data.economicLoss+'<br />' + } + + } + }, + legend: { + top: '5%', + left: 'center', + icon: "circle", + formatter: function(param){ + param=param.split(":"); + return [param[0]+':'+param[1]].join(""); + }, + }, + series: [ + { + name: '事故等级分布', + type: 'pie', + radius: ['40%', '70%'], + avoidLabelOverlap: false, + itemStyle: { + borderRadius: 10, + borderColor: '#fff', + borderWidth: 2 + }, + label: { + show: false, + position: 'center' + }, + emphasis: { + label: { + show: false, + fontSize: '40', + fontWeight: 'bold' + } + }, + labelLine: { + show: false + }, + data: list.value + } + ] + }; + + myChart.setOption(option, true); + + }; + onMounted(() => { + emergencySuppliesCount() + }); + return { + params, + list, + emergencySuppliesCount, + initPies, + echarts1 + } + } + + }) +</script> +<style scoped> +.echarts{ + width: 500px; + height: 400px; +} +</style> \ No newline at end of file diff --git a/src/views/accidentManagementSystem/workInjuryDeclaration/component/accidentName.vue b/src/views/accidentManagementSystem/workInjuryDeclaration/component/accidentName.vue new file mode 100644 index 0000000..86cd9a6 --- /dev/null +++ b/src/views/accidentManagementSystem/workInjuryDeclaration/component/accidentName.vue @@ -0,0 +1,246 @@ +<template> + <div> + <el-dialog v-model="dialogVisible" title="选择事故名称" width="900px" draggable :fullscreen="full" @close="handleClose"> + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-row> + <el-col :span="18"> + <el-row> + <el-form ref="ruleFormRef" :model="ruleForm" :inline="true" status-icon> + <!--<el-form-item>--> + <!--<el-input size="default" v-model="listQuery.searchParams.id" placeholder="id" style="min-width: 215px;"/>--> + <!--</el-form-item>--> + <el-form-item> + <el-input size="default" v-model="listQuery.searchParams.accidentName" placeholder="事故名称" style="min-width: 215px" /> + </el-form-item> + <!--<el-form-item>--> + <!--<el-input size="default" v-model="listQuery.searchParams.deptName" placeholder="事故部门" style="min-width: 215px;"/>--> + <!--</el-form-item>--> + <!--<el-form-item>--> + <!--<el-input size="default" v-model="listQuery.searchParams.occurrencePlace" placeholder="发生地点" style="min-width: 215px;"/>--> + <!--</el-form-item>--> + <!--<el-form-item>--> + <!--<el-input size="default" v-model="listQuery.searchParams.occurrenceTime" placeholder="发生时间" style="min-width: 215px;"/>--> + <!--</el-form-item>--> + <el-form-item> + <el-button size="default" type="primary" @click="listApi">查询</el-button> + <el-button size="default" @click="submitReset">重置</el-button> + <el-button size="default" :icon="Delete" @click="handleClose">清除选择</el-button> + </el-form-item> + </el-form> + </el-row> + <!--<el-table :data="tableData" style="width: 100%;margin-top:20px">--> + <!--<el-table-column type="selection" width="55" />--> + <!--<el-table-column align="center" prop="date" label="id" />--> + <!--<el-table-column align="center" prop="name" label="事故名称"/>--> + <!--<el-table-column align="center" prop="date" label="事故部门" />--> + <!--<el-table-column align="center" prop="name" label="发生地点"/>--> + <!--<el-table-column align="center" prop="name" label="发生时间"/>--> + <!--</el-table>--> + <!--<div class="pages">--> + <!--<el-pagination--> + <!--v-model:currentPage="currentPage4"--> + <!--v-model:page-size="pageSize4"--> + <!--:page-sizes="[100, 200, 300, 400]"--> + <!--:small="small"--> + <!--:disabled="disabled"--> + <!--:background="background"--> + <!--layout="total, sizes, prev, pager, next, jumper"--> + <!--:total="400"--> + <!--@size-change="handleSizeChange"--> + <!--@current-change="handleCurrentChange"--> + <!--/>--> + <!--</div>--> + <el-table :data="tableData" style="width: 100%" ref="multipleTableRef"> + <el-table-column align="center"> + <template #default="scope"> + <el-radio-group v-model="radio1"> + <el-radio :label="scope.row.id" size="large" @click="checkedItem(scope.row)">{{ null }}</el-radio> + </el-radio-group> + </template> + </el-table-column> + <!--<el-table-column prop="id" label="id" show-overflow-tooltip></el-table-column>--> + <el-table-column prop="accidentName" label="事故名称" show-overflow-tooltip></el-table-column> + <el-table-column prop="deptName" label="事故部门" show-overflow-tooltip></el-table-column> + <el-table-column prop="occurrencePlace" label="发生地点" show-overflow-tooltip></el-table-column> + <el-table-column prop="occurrenceTime" label="发生时间" show-overflow-tooltip></el-table-column> + </el-table> + <div class="pages"> + <el-pagination + v-model:currentPage="pageIndex" + v-model:page-size="pageSize" + :page-sizes="[10, 20, 30]" + :pager-count="5" + layout="total, sizes, prev, pager, next, jumper" + :total="total" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + </el-col> + <el-col :span="6"> + <el-tag v-for="tag in dynamicTags" :key="tag" class="mx-1" style="margin: 5px" closable :disable-transitions="false" @close="handleClose()"> + {{ tag.accidentName }} + </el-tag> + </el-col> + </el-row> + <template #footer> + <span class="dialog-footer"> + <el-button @click="closeDialog()" size="default">关闭</el-button> + <el-button type="primary" @click="submitForm" size="default">确定</el-button> + </span> + </template> + </el-dialog> + </div> +</template> +<script lang="ts"> +import { defineComponent, reactive, ref } from 'vue'; +import { Delete, FullScreen } from '@element-plus/icons-vue'; +import { + // ElTable, + ElMessage, +} from 'element-plus'; +import { accidentManagementSystemApi } from '/@/api/workInjuryDeclaration'; +export default defineComponent({ + setup(props, { emit }) { + const dialogVisible = ref<boolean>(false); + const openDailog = () => { + dialogVisible.value = true; + listApi(); + }; + // 搜索条件 + const ruleForm = reactive({ + pass: '', + }); + // 定义表格数据 + const tableData = ref([]); + // 列表参数 + const listQuery = reactive({ + pageIndex: 1, + pageSize: 10, + searchParams: { + accidentName: '', + }, + }); + //单选按钮 + const radio1 = ref(''); + // 分页 + const pageIndex = ref(); + const pageSize = ref(); + const total = ref(); + // 分页改变 + const handleSizeChange = (val: number) => { + listQuery.pageSize = val; + }; + // 分页未改变 + const handleCurrentChange = (val: number) => { + listQuery.pageIndex = val; + }; + const checkedItem = (row: object) => { + dynamicTags.value = [row]; + }; + // 重置 + const submitReset = () => { + listQuery.searchParams = {}; + listApi(); + }; + const submitForm = () => { + emit('selectItem', dynamicTags.value); + dialogVisible.value = false; + radio1.value='' + }; + //查询list数据 + const listApi = async () => { + let res = await accidentManagementSystemApi().accidentList(listQuery); + if (res.data.code == 200) { + tableData.value = res.data.data; + pageIndex.value = res.data.pageIndex; + pageSize.value = res.data.pageSize; + total.value = res.data.total; + } else { + ElMessage.error(res.data.msg); + } + }; + // 右方点击添加后显示标签 + const dynamicTags = ref([]); + const closeDialog=()=>{ + dialogVisible.value = false + handleClose() + }; + const handleClose = () => { + dynamicTags.value = []; + radio1.value = ''; + }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + return { + dialogVisible, + openDailog, + ruleForm, + tableData, + handleSizeChange, + handleCurrentChange, + dynamicTags, + handleClose, + Delete, + toggleFullscreen, + FullScreen, + full, + pageIndex, + pageSize, + total, + listApi, + listQuery, + radio1, + checkedItem, + submitReset, + submitForm, + closeDialog + }; + }, +}); +</script> +<style scoped> +.el-form--inline .el-form-item { + margin-bottom: 18px !important; + margin-right: 12px; +} +/*分页*/ +.pages { + margin-top: 15px; +} +::v-deep .el-pagination .el-pager li { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +::v-deep .el-pagination .el-pager li.is-active { + background-color: #409eff; + color: #fff; +} +::v-deep .el-pagination .btn-prev { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +::v-deep .el-pagination button:disabled { + color: #c0c4cc; +} +::v-deep .el-pagination .btn-next { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +</style> diff --git a/src/views/accidentManagementSystem/workInjuryDeclaration/component/openAdd.vue b/src/views/accidentManagementSystem/workInjuryDeclaration/component/openAdd.vue new file mode 100644 index 0000000..cccc214 --- /dev/null +++ b/src/views/accidentManagementSystem/workInjuryDeclaration/component/openAdd.vue @@ -0,0 +1,547 @@ +<template> + <div class="system-edit-user-container"> + <el-dialog :title="titles" v-model="isShowDialog" width="769px" draggable :fullscreen="full" @close="closeDialog(ruleFormRef)"> + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-form ref="ruleFormRef" :model="ruleForm" size="default" label-width="120px" :rules="rules"> + <el-row :gutter="35"> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="申报人姓名" prop="declareUserName"> + <el-input v-model="ruleForm.declareUserName" :disabled="disabled" placeholder="请填写申报人姓名"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="申报人性别" prop="declareUserGender"> + <el-radio-group v-model="ruleForm.declareUserGender" :disabled="disabled"> + <el-radio :label="false">男</el-radio> + <el-radio :label="true">女</el-radio> + </el-radio-group> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="申报人部门" placeholder="请选择" prop="declareDepartmentId"> + <el-tree-select v-model="ruleForm.declareDepartmentId" :disabled="disabled" + :data="newTreeList" :props="propse" class="w100" placeholder="请选择" /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="事故名称" prop="accidentName"> + <el-input v-model="ruleForm.accidentName" :disabled="true" placeholder="请选择" class="input-with-select"> + <template #append> + <el-button :icon="Search" @click="daiInpt" /> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="事故发生时间" prop="occurrenceTime"> + <el-date-picker + v-model="ruleForm.occurrenceTime" + :disabled="true" + type="datetime" + class="w100" + placeholder="选择日期时间" + value-format="YYYY-MM-DD HH:mm:ss" + /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="工伤类型" prop="workInjuryType"> + <el-select v-model="ruleForm.workInjuryType" :disabled="disabled" class="w100" placeholder="请选择"> + <el-option label="轻微伤" value="1"></el-option> + <el-option label="轻伤" value="2"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="申报日期" prop="declareDate"> + <el-date-picker + v-model="ruleForm.declareDate" + :disabled="disabled" + type="datetime" + class="w100" + placeholder="选择日期时间" + value-format="YYYY-MM-DD HH:mm:ss" + /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="损失工时" prop="lostTime"> + <el-input v-model="ruleForm.lostTime" :disabled="disabled" placeholder="请填写损失工时"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="就诊医院" prop="visitHospital"> + <el-input v-model="ruleForm.visitHospital" :disabled="disabled" placeholder="请填写就诊医院"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="就诊结果" prop="visitResult"> + <el-input v-model="ruleForm.visitResult" :disabled="disabled" placeholder="请填写就诊结果"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="相关附件"> + <uploaderImg :fileList="fileList" :name="INCIDENT_MANAGE" + @successUploader="successUploader" :disabled="disabled"></uploaderImg> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="注意事项" prop="mattersNeedingAttention"> + <el-input v-model="ruleForm.mattersNeedingAttention" :disabled="disabled" placeholder="请填写注意事项"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="材料是否齐全" prop="completeMaterials"> + <el-radio-group v-model="ruleForm.completeMaterials" :disabled="disabled"> + <el-radio :label="false">否</el-radio> + <el-radio :label="true">是</el-radio> + </el-radio-group> + </el-form-item> + </el-col> + + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="备注" prop="remark"> + <el-input v-model="ruleForm.remark" :disabled="disabled" type="textarea" placeholder="请填写备注" maxlength="150"></el-input> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="resetForm(ruleFormRef)" size="default">关闭</el-button> + <el-button size="default" type="primary" v-if="disabled == true ? false : true" @click="submitForm(titles, ruleFormRef)">确定</el-button> + </span> + </template> + </el-dialog> + <AccidentName @selectItem="onSelectItem" ref="showRef" /> + <userSelections ref="userRef" /> + <RegionsDialog ref="openRef" /> + </div> +</template> + +<script lang="ts"> +import { + reactive, + ref, + defineComponent, + onMounted +} from 'vue'; + +import type { UploadUserFile, FormInstance,FormRules } from 'element-plus'; +import { ElMessage } from 'element-plus'; +import { Search, FullScreen } from '@element-plus/icons-vue'; +import UserSelections from '/@/components/userSelections/index.vue'; +import AccidentName from '/@/views/accidentManagementSystem/workInjuryDeclaration/component/accidentName.vue'; +import RegionsDialog from '/@/components/regionsDialog/index.vue'; +import uploaderImg from '/@/components/uploaderImg/index.vue'; +import { emergencySuppliesApi } from '/@/api/contingencyManagement/emergencyResources'; +import { accidentManagementSystemApi } from '/@/api/workInjuryDeclaration'; +import { goalManagementApi } from '/@/api/goalManagement'; + +export default defineComponent({ + name: 'openAdd', + components: { + AccidentName, + UserSelections, + RegionsDialog, + uploaderImg + }, + setup(props, { emit }) { + const isShowDialog = ref(false); + + const ruleFormRef = ref<FormInstance>(); + //定义表单 + const ruleForm = ref({ + declareUserName: '', + declareUserGender: '', + declareDepartmentId: '', + accidentName:'', + accidentExpressId: '', + workInjuryType: '', + declareDate: '', + lostTime: '', + visitHospital: '', + visitResult: '', + mattersNeedingAttention: '', + completeMaterials: '', + remark: '', + fileList: [ + { + fileName: '', + fileUrl: '', + }, + ], + }); + const titles = ref(); + const disabled = ref(); + // 打开弹窗 + const openDialog = (title: string, id: number, type: boolean) => { + isShowDialog.value = true; + titles.value = title; + disabled.value = type; + if (title == '查看工伤申报' || title == '修改工伤申报') { + accidentManagementSystemApi() + .seeAccidentManagementSystem(id) + .then((res) => { + if (res.data.code == 200) { + ruleForm.value = res.data.data; + fileList.value = (res.data.data.fileList?res.data.data.fileList:[]) + initFileListData() + } + }); + } + }; + const initFileListData = async () => { + for(var a = 0;a<fileList.value.length;a++){ + await goalManagementApi() + .searchFile(fileList.value[a].fileName) + .then((res) => { + fileList.value[a].url = res.data + }) + } + } + // 上传成功组装数据 + const successUploader = (list) =>{ + fileList.value = list + const formFileList = [] + for(var a = 0;a<fileList.value.length;a++){ + formFileList.push( + { + fileName:fileList.value[a].fileName, + fileUrl:'' + } + ) + } + ruleForm.value.fileList = formFileList + } + //日期选择器 + const value1 = ref(''); + // 上传附件 + const fileList = ref<UploadUserFile[]>([]); + // 可选择树 + const treeSelect = ref(); + const tree = [ + ]; + //定义树形下拉框 + const responsibleDepartment = ref(); + const data = [ + + ]; + //el-tree-select回显 + const propse = { + label: 'depName', + children: 'children', + }; + const newTreeList = []; + //得到部门树 + const department = async () => { + await goalManagementApi() + .getTreedepartment() + .then((res) => { + if (res.data.code == 200) { + data.value = res.data.data; + getTreeList(res.data.data, newTreeList); + } else { + ElMessage.error(res.data.msg); + } + }); + }; + // 递归树状数据且修改字段名 + const getTreeList = (treeList, newTreeList) => { + treeList.map((c) => { + let tempData = { + depName: c.depName, + value: c.depId, + children: [], + }; + if (c.children && c.children.length > 0) { + tempData.children = []; + getTreeList(c.children, tempData.children); + } + newTreeList.push(tempData); + }); + }; + onMounted(() => { + department(); + }); + // 关闭弹窗 + const closeDialog = (formEl: FormInstance | undefined) => { + formEl.resetFields(); + fileList.value=[] + isShowDialog.value = false; + }; + // 必填项提示 + const rules = reactive<FormRules>({ + declareUserName: [ + { + required: true, + message: '申报人姓名不能为空', + trigger: 'change', + }, + ], + declareUserGender: [ + { + required: true, + message: '申报人性别不能为空', + trigger: 'change', + }, + ], + declareDepartmentId: [ + { + required: true, + message: '申报人部门不能为空', + trigger: 'change', + }, + ], + accidentName: [ + { + required: true, + message: '事故名称不能为空', + trigger: 'change', + }, + ], + workInjuryType: [ + { + required: true, + message: '工伤类型不能为空', + trigger: 'change', + }, + ], + declareDate: [ + { + required: true, + message: '申报日期不能为空', + trigger: 'blur', + }, + ], + lostTime: [ + { + required: true, + message: '损失工时不能为空', + trigger: 'change', + }, + ], + visitHospital: [ + { + required: true, + message: '就诊医院不能为空', + trigger: 'change', + }, + ], + visitResult: [ + { + required: true, + message: '就诊结果不能为空', + trigger: 'change', + }, + ], + mattersNeedingAttention: [ + { + required: true, + message: '注意事项不能为空', + trigger: 'change', + }, + ], + completeMaterials: [ + { + required: true, + message: '材料状态不能为空', + trigger: 'change', + }, + ], + remark: [ + { + required: true, + message: '备注不能为空', + trigger: 'change', + }, + ] + }) + + // 事故名称弹窗 + const showRef = ref(); + const daiInpt = () => { + showRef.value.openDailog(); + }; + //事故快报回填 + const onSelectItem = (item: any) => { + console.log('item', item); + ruleForm.value.accidentExpressId = item[0].id + ruleForm.value.accidentName = item[0].accidentName + ruleForm.value.occurrenceTime = item[0].occurrenceTime + + }; + // 表单提交验证必填项 + const submitForm = async (title: string, formEl: FormInstance | undefined) => { + if(!ruleForm.value.fileList){ + ruleForm.value.fileList = [] + } + if (title == '新建工伤申报') { + if (!formEl) return; + await formEl.validate((valid, fields) => { + if (valid) { + isShowDialog.value = false; + delete ruleForm.value.accidentName + delete ruleForm.value.occurrenceTime + delete ruleForm.value.id + accidentManagementSystemApi() + .workAdd(ruleForm.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'success', + }); + emit('myAdd', true); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + emit('myAdd', true); + } + formEl.resetFields(); + }); + } else { + console.log('error submit!', fields); + } + }); + } else if (title == '修改工伤申报') { + if (!formEl) return; + await formEl.validate((valid, fields) => { + if (valid) { + isShowDialog.value = false; + delete ruleForm.value.accidentName + delete ruleForm.value.occurrenceTime + accidentManagementSystemApi() + .workView(ruleForm.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: '修改成功', + type: 'success', + }); + emit('myAdd', true); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + emit('myAdd', true); + } + formEl.resetFields(); + }); + } else { + console.log('error submit!', fields); + } + }); + formEl.resetFields(); + ruleForm.value = { + declareUserName: '', + declareUserGender: '', + declareDepartmentId: '', + accidentExpressId: '', + workInjuryType: '', + declareDate: '', + lostTime: '', + visitHospital: '', + visitResult: '', + mattersNeedingAttention: '', + completeMaterials: '', + remark: '', + fileList: [ + { + fileName: '', + fileUrl: '', + }, + ], + }; + } + }; + const resetForm = (formEl: FormInstance | undefined) => { + isShowDialog.value = false; + if (!formEl) return; + formEl.resetFields(); + }; + // 选择区域弹窗 + const openRef = ref(); + const regionsDialog = () => { + openRef.value.openDailog(); + }; + // 打开用户选择弹窗 + const userRef = ref(); + const openUser = () => { + userRef.value.openDialog(); + }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + return { + daiInpt, + openDialog, + isShowDialog, + fileList, + responsibleDepartment, + data, + Search, + ruleForm, + value1, + treeSelect, + tree, + showRef, + ruleFormRef, + submitForm, + rules, + openUser, + userRef, + regionsDialog, + openRef, + toggleFullscreen, + FullScreen, + full, + resetForm, + titles, + disabled, + emit, + onSelectItem, + department, + getTreeList, + newTreeList, + propse, + closeDialog, + uploaderImg, + successUploader, + initFileListData + }; + }, +}); +</script> +<style scoped lang="scss"> +.textarea { + height: 168px !important; +} +.textarea ::v-deep(.el-textarea__inner) { + height: 168px !important; +} +::v-deep(.el-table__cell) { + font-weight: 400; +} +.el-divider--horizontal { + height: 0; + margin: 0; + border-top: transparent; +} +.el-select { + width: 100%; +} +</style> diff --git a/src/views/accidentManagementSystem/workInjuryDeclaration/component/openEdit.vue b/src/views/accidentManagementSystem/workInjuryDeclaration/component/openEdit.vue new file mode 100644 index 0000000..302da1e --- /dev/null +++ b/src/views/accidentManagementSystem/workInjuryDeclaration/component/openEdit.vue @@ -0,0 +1,400 @@ +<template> + <div class="system-edit-user-container"> + <el-dialog + title="新建事故快报" + v-model="isShowDialog" + width="769px" + draggable + :fullscreen="full" + > + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-form + ref="ruleFormRef" + :model="ruleForm" + size="default" + label-width="120px" + > + <el-row :gutter="35"> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="事故名称" prop="teamName"> + <el-input v-model="ruleForm.teamName" placeholder="请填写队伍名称"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="事故部门" placeholder="请选择"> + <el-tree-select + v-model="ruleForm.responsibleDepartment" + :data="data" class="w100" + placeholder="请选择"/> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="发生地点" prop="teamLeader"> + <el-input v-model="ruleForm.teamName" placeholder="请填写发生地点"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="发生时间" prop="telephone"> + <el-date-picker + v-model="value1" + type="datetime" + class="w100" + placeholder="选择日期时间" + /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="事故原因" prop="teamLevel"> + <el-select v-model="ruleForm.teamLevel" class="w100" placeholder="请选择"> + <el-option label="人的不安全行为" value="1"></el-option> + <el-option label="物的不安全状态" value="2"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="是否有伤亡"> + <el-radio-group v-model="ruleForm.resource"> + <el-radio label="是" /> + <el-radio label="否" /> + </el-radio-group> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="事故简要经过"> + <el-input v-model="ruleForm.describe" type="textarea" placeholder="请填写事故简要经过" maxlength="150"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="事故原因初步分析"> + <el-input v-model="ruleForm.describe" type="textarea" placeholder="请填写事故原因初步分析" maxlength="150"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="应急防范措施"> + <el-input v-model="ruleForm.describe" type="textarea" placeholder="请填写应急防范措施" maxlength="150"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="事故照片"> + <el-input v-model="ruleForm.describe" type="textarea" placeholder="请填写应急防范措施" maxlength="150"></el-input> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="onCancel" size="default">关闭</el-button> + <el-button size="default" type="primary" @click="submitForm(ruleFormRef)">确定</el-button> + </span> + </template> + </el-dialog> + <CheckTemplate ref="Shows"/> + <userSelections ref="userRef"/> + <RegionsDialog ref="openRef"/> + </div> +</template> + +<script lang="ts"> +import { + reactive, + ref, + defineComponent +} from 'vue'; + +import type { + UploadUserFile, + FormInstance, + // FormRules, +} from 'element-plus' + +import { + Search, + FullScreen +} from '@element-plus/icons-vue' +import UserSelections from "/@/components/userSelections/index.vue" +import CheckTemplate from '/@/components/checkTemplate/index.vue' +import RegionsDialog from '/@/components/regionsDialog/index.vue' + +export default defineComponent({ + name: 'openEdit', + components: { + CheckTemplate, + UserSelections, + RegionsDialog, + }, + setup() { + const isShowDialog = ref(false) + + const ruleFormRef = ref<FormInstance>() + //定义表单 + const ruleForm = reactive({ + teamName: '', // 队伍名称 + teamLeader: '', //队伍负责人 + department: [], // 负责人部门 + phone: '', // 负责人手机 + telephone: '', // 固定电话 + }); + // 打开弹窗 + const openDialog = () => { + // state.ruleForm = row; + isShowDialog.value = true; + }; + // 关闭弹窗 + const closeDialog = () => { + isShowDialog.value = false; + }; + // 取消 + const onCancel = () => { + closeDialog(); + }; + //日期选择器 + const value1 = ref('') + // 上传附件 + const fileList = ref<UploadUserFile[]>([]) + // 可选择树 + const treeSelect = ref() + const tree = [ + { + value: '1', + label: 'Level one 1', + children: [ + { + value: '1-1', + label: 'Level two 1-1', + children: [ + { + value: '1-1-1', + label: 'Level three 1-1-1', + }, + ], + }, + ], + }, + { + value: '2', + label: 'Level one 2', + children: [ + { + value: '2-1', + label: 'Level two 2-1', + children: [ + { + value: '2-1-1', + label: 'Level three 2-1-1', + }, + ], + }, + { + value: '2-2', + label: 'Level two 2-2', + children: [ + { + value: '2-2-1', + label: 'Level three 2-2-1', + }, + ], + }, + ], + }, + { + value: '3', + label: 'Level one 3', + children: [ + { + value: '3-1', + label: 'Level two 3-1', + children: [ + { + value: '3-1-1', + label: 'Level three 3-1-1', + }, + ], + }, + { + value: '3-2', + label: 'Level two 3-2', + children: [ + { + value: '3-2-1', + label: 'Level three 3-2-1', + }, + ], + }, + ], + }, + ] + //定义树形下拉框 + const responsibleDepartment = ref() + const data = [ + { + value: '1', + label: '广汇能源综合物流发展有限责任公司', + children: [ + { + value: '1-1', + label: '经营班子', + children: [], + }, + ], + }, + { + value: '2', + label: '生产运行部', + children: [ + { + value: '2-1', + label: '灌装一班', + children: [] + }, + { + value: '2-2', + label: '工艺四班', + children: [], + }, + ], + }, + { + value: '3', + label: '设备部', + children: [ + { + value: '3-1', + label: '仪表班', + children: [], + }, + { + value: '3-2', + label: '机修班', + children: [], + }, + ], + }, + ] + // 必填项提示 + // const rules = reactive<FormRules>({ + // teamName: [ + // { + // required: true, + // message: '队伍名称不能为空', + // trigger: 'change', + // }, + // ], + // teamLevel: [ + // { + // required: true, + // message: '队伍级别不能为空', + // trigger: 'change', + // }, + // ], + // teamLeader: [ + // { + // required: true, + // message: '队伍负责人不能为空', + // trigger: 'change', + // }, + // ], + // responsibleDepartment: [ + // { + // required: true, + // message: '负责人部门不能为空', + // trigger: 'change', + // }, + // ], + // teamPhone: [ + // { + // required: true, + // message: '负责人手机不能为空', + // trigger: 'change', + // }, + // ], + // telephone: [ + // { + // required: true, + // message: '固定电话不能为空', + // trigger: 'change', + // }, + // ], + // }) + // 表单提交验证必填项 + const submitForm = async (formEl: FormInstance | undefined) => { + if (!formEl) return + await formEl.validate((valid, fields) => { + if (valid) { + console.log('submit!') + } else { + console.log('error submit!', fields) + } + }) + } + // 应急队伍弹窗 + const Shows=ref() + const daiInpt=()=>{ + Shows.value.openDailog() + } + // 选择区域弹窗 + const openRef=ref() + const regionsDialog=()=>{ + openRef.value.openDailog() + } + // 打开用户选择弹窗 + const userRef = ref(); + const openUser = () => { + userRef.value.openDialog(); + }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + return { + openDialog, + closeDialog, + isShowDialog, + onCancel, + fileList, + responsibleDepartment, + data, + Search, + ruleForm, + value1, + treeSelect, + tree, + daiInpt, + Shows, + ruleFormRef, + submitForm, + // rules, + openUser, + userRef, + regionsDialog, + openRef, + toggleFullscreen, + FullScreen, + full, + }; + }, +}); +</script> +<style scoped lang="scss"> +.textarea{ + height: 168px!important; +} +.textarea ::v-deep .el-textarea__inner{ + height: 168px!important; +} +::v-deep .el-table__cell { + font-weight: 400; +} +.el-divider--horizontal{ + height: 0; + margin: 0; + border-top: transparent; +} +.el-select{ + width: 100%; +} +</style> \ No newline at end of file diff --git a/src/views/accidentManagementSystem/workInjuryDeclaration/index.vue b/src/views/accidentManagementSystem/workInjuryDeclaration/index.vue new file mode 100644 index 0000000..00a7afa --- /dev/null +++ b/src/views/accidentManagementSystem/workInjuryDeclaration/index.vue @@ -0,0 +1,397 @@ +<template> + <div class="system-user-container"> + <el-card shadow="hover"> + <div class="system-user-search mb15"> + <el-form ref="ruleFormRef" size="default" label-width="80px" :inline="true"> + <el-form-item prop="telephone"> + <el-input v-model="accidentName" placeholder="请选择事故快报" :disabled="true" class="input-with-select"> + <template #append> + <el-button :icon="Search" @click="daiInpt" /> + </template> + </el-input> + </el-form-item> + <el-button size="default" type="primary" class="ml10" @click="listApi"> 查询</el-button> + <el-button size="default" class="ml10" @click="submitReset"> 重置</el-button> + </el-form> + </div> + <div class="button_Line"> + <div class="button_Left"> + <el-button size="default" type="primary" @click="onOpenAdd"> + <el-icon> + <Plus /> + </el-icon> + 新建 + </el-button> + <el-button size="default" type="warning" plain :disabled="warning" @click="onEdit('修改', deletAll[0])"> + <el-icon> + <Edit /> + </el-icon> + 修改 + </el-button> + <el-button size="default" type="danger" plain @click="onDeleteAll" :disabled="danger"> + <el-icon> + <Delete /> + </el-icon> + 删除 + </el-button> + </div> + <div class="button_Right"> + <el-button @click="upButton"> + <el-icon> + <Upload /> + </el-icon> + </el-button> + <el-button> + <el-icon> + <Download /> + </el-icon> + </el-button> + <el-button> + <el-icon> + <Refresh /> + </el-icon> + </el-button> + </div> + </div> + <el-table :data="tableData" style="width: 100%" ref="multipleTableRef" @selection-change="handleSelectionChange"> + <el-table-column type="selection" width="55" /> + <el-table-column prop="declareUserName" label="申报人名称" show-overflow-tooltip sortable></el-table-column> + <el-table-column prop="deptName" label="申报人部门" show-overflow-tooltip sortable></el-table-column> + <el-table-column prop="accidentName" label="事故名称" show-overflow-tooltip sortable></el-table-column> + <el-table-column label="工伤类型" show-overflow-tooltip sortable> + <template #default="scope"> + <span v-if="scope.row.workInjuryType==1">轻微伤</span> + <span v-if="scope.row.workInjuryType==2">轻伤</span> + </template> + </el-table-column> + <el-table-column prop="declareDate" label="申报日期" show-overflow-tooltip sortable></el-table-column> + <el-table-column prop="visitHospital" label="就诊医院" show-overflow-tooltip sortable></el-table-column> + <el-table-column label="操作" width="260" align="center" fixed="right"> + <template #default="scope"> + <!--<el-button size="small" text disabled>--> + <!--<el-icon style="margin-right: 5px"> <Upload /> </el-icon>上报--> + <!--</el-button>--> + <el-button size="small" text type="primary" @click="onEdit('详情', scope.row.id)"> + <el-icon style="margin-right: 5px"> + <View /> + </el-icon> + 查看 + </el-button> + <el-button size="small" text type="primary" @click="onEdit('修改', scope.row.id)"> + <el-icon style="margin-right: 5px"> + <EditPen /> + </el-icon> + 修改 + </el-button> + <el-button size="small" text type="primary" @click="onRowDel(scope.row.id)"> 删除</el-button> + </template> + </el-table-column> + </el-table> + <div class="pages"> + <el-pagination + v-if="tableData.length == 0 ? false : true" + v-model:currentPage="pageIndex" + v-model:page-size="pageSize" + :page-sizes="[10, 20, 30]" + :pager-count="5" + layout="total, sizes, prev, pager, next, jumper" + :total="total" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + </el-card> + <AccidentName ref="showRef" @selectItem="onSelectItem" /> + <OpenAdd ref="addRef" @myAdd="onMyAdd" /> + <!-- <OpenEdit ref="editRef" />--> + <upData ref="upShow"></upData> + </div> +</template> + +<script lang="ts"> +import { + // toRefs, + reactive, + // onMounted, + ref, + defineComponent, + onMounted, +} from 'vue'; +import { ElMessageBox, ElMessage } from 'element-plus'; +import { Plus, Download, Refresh, View, EditPen, Edit, Delete, Search, Upload } from '@element-plus/icons-vue'; +import AccidentName from '/@/views/accidentManagementSystem/workInjuryDeclaration/component/accidentName.vue'; +import OpenAdd from '/@/views/accidentManagementSystem/workInjuryDeclaration/component/openAdd.vue'; +import OpenEdit from '/@/views/accidentManagementSystem/workInjuryDeclaration/component/openEdit.vue'; +import UpData from '/@/views/contingencyManagement/panManagement/component/upData.vue'; +import { accidentManagementSystemApi } from '/@/api/accidentManagementSystem'; + +export default defineComponent({ + name: 'index', + components: { + OpenEdit, + EditPen, + Plus, + Upload, + Download, + Refresh, + Edit, + View, + Delete, + UpData, + OpenAdd, + AccidentName, + }, + setup() { + //列表参数 + const listQuery = reactive({ + pageIndex: 1, + pageSize: 10, + searchParams: { + accidentExpressId: '', + }, + }); + //搜索条件回填 + const onSelectItem = (item: any) => { + console.log('item', item[0].accidentName); + listQuery.searchParams.accidentExpressId = item[0].id; + accidentName.value = item[0].accidentName; + }; + // 定义表格数据 + const tableData = ref([]); + // 请求列表数据 + const listApi = async () => { + let res = await accidentManagementSystemApi().workList(listQuery); + if (res.data.code == 200) { + tableData.value = res.data.data; + pageIndex.value = res.data.pageIndex; + pageSize.value = res.data.pageSize; + total.value = res.data.total; + } else { + ElMessage.error(res.data.msg); + } + }; + onMounted(() => { + listApi(); + }); + const accidentName = ref(); + // 重置 + const submitReset = () => { + listQuery.searchParams.accidentExpressId = ''; + accidentName.value = ''; + listApi(); + }; + const warning = ref(true); + const danger = ref(true); + const deletAll = ref(); + const handleSelectionChange = (val: any) => { + let valId = JSON.parse(JSON.stringify(val)); + let arr = []; + for (let i = 0; i < valId.length; i++) { + arr.push(valId[i].id); + } + deletAll.value = arr; + if (val.length == 1) { + warning.value = false; + danger.value = false; + } else if (val.length == 0) { + warning.value = true; + danger.value = true; + } else { + warning.value = true; + danger.value = false; + } + }; + // 事故名称弹窗 + const showRef = ref(); + const daiInpt = () => { + showRef.value.openDailog(); + }; + // 打开新增弹窗 + const addRef = ref(); + const onOpenAdd = () => { + addRef.value.openDialog('新建工伤申报', false); + }; + // 新增后刷新 + const onMyAdd = (e: boolean) => { + if (e) { + listApi(); + } else { + listApi(); + } + }; + // 上传 + const upShow = ref(); + const upButton = () => { + upShow.value.openDialog(); + }; + + // 打开修改用户弹窗 + // const editRef = ref(); + const onEdit = (val: string, row: object) => { + if (val == '详情') { + addRef.value.openDialog('查看工伤申报', row, true); + } else { + addRef.value.openDialog('修改工伤申报', row, false); + } + }; + // 删除用户 + const onRowDel = (data: any) => { + ElMessageBox.confirm('确定删除所选项吗?', '提示', { + confirmButtonText: '确认', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + accidentManagementSystemApi() + .workDelete([data]) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'success', + }); + listApi(); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + listApi(); + } + }); + }) + .catch(() => {}); + }; + // 多选删除 + const onDeleteAll = () => { + ElMessageBox.confirm('确定删除所选项吗?', '提示', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + accidentManagementSystemApi() + .workDelete(deletAll.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'success', + }); + listApi(); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + listApi(); + } + }); + }) + .catch(() => {}); + }; + // 分页 + const pageIndex = ref(); + const pageSize = ref(); + const total = ref(); + // 分页改变 + const handleSizeChange = (val: number) => { + listQuery.pageSize = val; + }; + // 分页未改变 + const handleCurrentChange = (val: number) => { + listQuery.pageIndex = val; + }; + return { + accidentName, + daiInpt, + showRef, + upButton, + upShow, + tableData, + pageIndex, + pageSize, + handleSizeChange, + handleCurrentChange, + onEdit, + onOpenAdd, + addRef, + // editRef, + listApi, + Search, + submitReset, + onDeleteAll, + handleSelectionChange, + warning, + danger, + listQuery, + onRowDel, + total, + onMyAdd, + onSelectItem, + deletAll, + }; + }, +}); +</script> +<style scoped lang="scss"> +.table_Box { + padding: 20px; + background-color: #fff; +} + +.tableForm { + margin-top: 10px; +} + +/*按钮行*/ +.button_Line { + display: flex; + flex-direction: row; + justify-content: space-between; +} + +//分页 +.pages { + display: flex; + justify-content: flex-end; + margin-top: 15px; +} + +::v-deep .el-pagination .el-pager li { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} + +::v-deep .el-pagination .el-pager li.is-active { + background-color: #409eff; + color: #fff; +} + +::v-deep .el-pagination .btn-prev { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} + +::v-deep .el-pagination button:disabled { + color: #c0c4cc; +} + +::v-deep .el-pagination .btn-next { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +</style> \ No newline at end of file diff --git a/src/views/contingencyManagement/abolishDialog/abolishDialog.vue b/src/views/contingencyManagement/abolishDialog/abolishDialog.vue new file mode 100644 index 0000000..69dba30 --- /dev/null +++ b/src/views/contingencyManagement/abolishDialog/abolishDialog.vue @@ -0,0 +1,139 @@ +<template> + <div class="system-user-container"> + <h4 class="title">胡海涛2022-07-01 16:08:42发起了目标检查上报(检查)--检查</h4> + <div class="box"> + <el-menu + :default-active="activeIndex" + class="el-menu-demo" + background-color="#ebeef5" + text-color="#fff" + active-text-color="#fff" + mode="horizontal" + @select="handleSelect" + > + <el-menu-item index="1">表单信息</el-menu-item> + <el-menu-item index="2">流程图</el-menu-item> + </el-menu> + <div v-if="activeIndex == 1" class="navType"> + <formInformationTop v-if="false"></formInformationTop> + <formInformationTops></formInformationTops> + </div> + <div v-if="activeIndex == 2" class="navType" style="padding:20px 20px 0 20px"> + <div class="title2">流程图 + <!-- <img src=""> --> + </div> + <div style="width:100%;height:400px"></div> + </div> + </div> + <lowerPlate></lowerPlate> + <div class="btns"> + <el-button type="primary">启动</el-button> + </div> + </div> +</template> +<script lang="ts"> +import { defineComponent, reactive, ref,onMounted } from 'vue'; +import { useRouter } from 'vue-router'; +import formInformationTop from './component/formInformationTop.vue' +import formInformationTops from './component/formInformationTops.vue' +import lowerPlate from './component/lowerPlate.vue' +export default defineComponent({ + components:{lowerPlate,formInformationTop,formInformationTops}, + setup() { + const activeIndex = ref<any>('1'); + const handleSelect = (key: string, keyPath: string[]) => { + // console.log(key, keyPath); + activeIndex.value = key; + }; + const form = reactive({ + name: '', + region: '', + date1: '', + date2: '', + delivery: false, + type: [], + resource: '', + desc: '', + }); + + const router=useRouter() + const Type=onMounted(()=>{ + // console.log("xxxxxxx",router) + }) + + return { + activeIndex, + handleSelect, + form, + router, + Type + }; + }, +}); +</script> +<style scoped> +.title { + text-align: center; + font-size: 16px; + margin-bottom: 20px; +} +.box{ + border: 1px solid #dcdfe6; + box-shadow: 0 2px 4px 0 rgb(0 0 0 / 12%), 0 0 6px 0 rgb(0 0 0 / 4%); +} +.navType { + background-color: #fff; + padding: 15px; +} +.tiao{ + width: 100%; + height: 1px; + background-color: #dcdfe6; + margin: 30px 0 ; + position: relative; +} +.typeS{ + width: 80px; + background-color: #fff; + position: absolute; + left: 30px; + top: -9px; + font-size: 14px; + text-align: center; +} +.logoColor{ + background-color: #67c23a; + color: #fff; + padding: 5px 8px; + border-radius: 5px; + margin-right: 5px; +} +.btns{ + width: 100%; + padding:20px 0; + background-color: #fff; + position: fixed; + bottom: 0px; + left: 0px; + text-align: center; + box-shadow: 0 -3px 5px 0 rgb(0 0 0 / 12%); + +} +.title2{ + padding: 20px 0 20px 10px; + width: 100%; + border: 1px solid #dcdfe6; +} + +/*弹窗底部边框线*/ +::v-deep .el-dialog__footer{ + border-top: 1px solid #e8e8e8; + border-radius: 0 0 4px 4px; +} +/*弹窗顶部边框线*/ +::v-deep .el-dialog__header { + border-bottom: 1px solid #e8e8e8; + margin-right: 0; + border-radius: 4px 4px 0 0; +} +</style> diff --git a/src/views/contingencyManagement/abolishDialog/component/formInformationTop.vue b/src/views/contingencyManagement/abolishDialog/component/formInformationTop.vue new file mode 100644 index 0000000..ef75063 --- /dev/null +++ b/src/views/contingencyManagement/abolishDialog/component/formInformationTop.vue @@ -0,0 +1,144 @@ +<template> + <el-form ref="form" :model="form" label-width="120px"> + <el-row> + <el-col :span="11"> + <el-form-item label="安全目标指标"> + <el-input v-model="form.name"></el-input> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="目标指标编号"> + <el-input v-model="form.name"></el-input> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="11"> + <el-form-item label="年度"> + <el-input v-model="form.name"></el-input> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="指标值"> + <el-input v-model="form.name"></el-input> + </el-form-item> + </el-col> + </el-row> + </el-form> + <el-tabs v-model="activeName" style="padding: 0 20px"> + <el-tab-pane label="考核指标" name="1"> + <el-table :data="tableData" style="width: 100%"> + <el-table-column align="center" type="index" label="序号" width="70" /> + <el-table-column align="center" prop="date" label="责任部门" /> + <el-table-column align="center" prop="name" label="考核指标" /> + <el-table-column align="center" prop="address" label="制定部门" /> + <el-table-column align="center" prop="address" label="制定日期" /> + <el-table-column align="center" label="检查值"> + <template #default> + <el-input v-model="form.name" placeholder=""></el-input> + </template> + </el-table-column> + <el-table-column align="center" prop="address" label="检查人" /> + <el-table-column align="center" prop="address" label="检查时间" /> + </el-table> + <div class="tiao"> + <div class="typeS">审批</div> + </div> + <el-row style="padding:20px 0"> + <el-col :span="6" style="text-align:right">一级审批:</el-col> + <el-col :span="18">同意</el-col> + </el-row> + <el-row style="padding:0 0 20px 0"> + <el-col :span="6"></el-col> + <el-col :span="18"><span class="logoColor">同意</span><span style="margin-right: 8px;">杜建喜</span><span>2021-05-24 04:47:42</span></el-col> + </el-row> + </el-tab-pane> + </el-tabs> +</template> +<script lang="ts"> +import { defineComponent,ref,reactive } from 'vue' + +export default defineComponent({ + setup() { + const form = reactive({ + name: '', + region: '', + date1: '', + date2: '', + delivery: false, + type: [], + resource: '', + desc: '', + }); + const tableData = [ + { + date: '2016-05-03', + name: 'Tom', + address: 'No. 189, Grove St, Los Angeles', + }, + ]; + const activeName = ref('1'); + return{ + form, + tableData, + activeName + } + }, +}) +</script> +<style scoped> +.title { + text-align: center; + font-size: 16px; + margin-bottom: 20px; +} +.box{ + border: 1px solid #dcdfe6; + box-shadow: 0 2px 4px 0 rgb(0 0 0 / 12%), 0 0 6px 0 rgb(0 0 0 / 4%); +} +.navType { + background-color: #fff; +} +.tiao{ + width: 100%; + height: 1px; + background-color: #dcdfe6; + margin: 30px 0 ; + position: relative; +} +.typeS{ + width: 80px; + background-color: #fff; + position: absolute; + left: 30px; + top: -9px; + font-size: 14px; + text-align: center; +} +.logoColor{ + background-color: #67c23a; + color: #fff; + padding: 5px 8px; + border-radius: 5px; + margin-right: 5px; +} +.btns{ + width: 100%; + padding:20px 0; + background-color: #fff; + position: fixed; + bottom: 0px; + left: 0px; + text-align: center; + box-shadow: 0 -3px 5px 0 rgb(0 0 0 / 12%); + +} +.title2{ + padding: 20px 0 20px 10px; + width: 100%; + border: 1px solid #dcdfe6; +} +.el-row{ + padding:0 0 20px 0 ; +} +</style> diff --git a/src/views/contingencyManagement/abolishDialog/component/formInformationTops.vue b/src/views/contingencyManagement/abolishDialog/component/formInformationTops.vue new file mode 100644 index 0000000..68ae8a6 --- /dev/null +++ b/src/views/contingencyManagement/abolishDialog/component/formInformationTops.vue @@ -0,0 +1,318 @@ +<template> + <el-form ref="form" :model="form" label-width="120px"> + <el-row> + <el-col :span="12"> + <el-form-item label="预案名称"> + <el-input v-model="form.name" disabled placeholder="请填写预案名称"></el-input> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="适用部门"> + <el-tree-select + class="select" + placeholder="请选择" + v-model="value" + :data="data" + :render-after-expand="false" + show-checkbox + multiple + clearable + disabled + /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="预案类型"> + <el-select class="select" v-model="form.region" disabled placeholder="请选择"> + <el-option label="综合应急预案" value="shanghai" /> + <el-option label="现场处置方案" value="beijing" /> + <el-option label="专项应急预案" value="shanghai" /> + <el-option label="其它预案" value="beijing" /> + </el-select> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="危险源关联"> + <el-select class="select" v-model="form.region" disabled placeholder="请选择"> + <el-option label="是" value="shanghai" /> + <el-option label="否" value="beijing" /> + </el-select> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="预案级别"> + <el-select class="select" v-model="form.region" disabled placeholder="请选择"> + <el-option label="公司及" value="shanghai" /> + <el-option label="分厂级" value="beijing" /> + <el-option label="车间级" value="beijing" /> + </el-select> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="编写人"> + <el-input + v-model="form.teamLeader" + placeholder="请选择" + class="input-with-select" + disabled + > + <template #append> + <el-button :icon="Search" @click="openUser" disabled/> + </template> + </el-input> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="编写部门" disabled placeholder="请选择"> + <el-tree-select + class="select" + v-model="value2" + :data="dataSelect" + :render-after-expand="false" + multiple + check-strictly + check-on-click-node + clearable + disabled + /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="发布实施日期"> + <el-date-picker v-model="datetime" type="datetime" disabled placeholder="选择日期时间" style="width: 100%" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="应急队伍" prop="telephone" @click="daiInpt" > + <el-input + v-model="form.teamLeader" + placeholder="请选择" + class="input-with-select" + disabled + > + <template #append> + <el-button :icon="Search" disabled/> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="预案附件"> + <el-upload + v-model:file-list="fileList" + class="upload-demo" + action="https://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15" + :on-change="handleChange" + disabled + > + <el-button type="primary" disabled + >点击上传</el-button> + <template #tip> + <div class="el-upload__tip"> + 添加相关附件 + </div> + </template> + </el-upload> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="区域名称" prop="telephone"> + <el-input + v-model="form.teamLeader" + placeholder="请选择" + class="input-with-select" + disabled + > + <template #append> + <el-button :icon="Search" disabled @click="regionsDialog"/> + </template> + </el-input> + </el-form-item> + </el-col> + </el-row> + </el-form> + <checkTemplate ref="ShowRef"/> + <userSelections ref="userRef"/> + <RegionsDialog ref="openRef"/> +</template> +<script lang="ts"> +import { + defineComponent, + ref, + reactive +} from 'vue'; +import { + Search +} from '@element-plus/icons-vue' +import UserSelections from "/@/components/userSelections/index.vue" +import CheckTemplate from "/@/components/checkTemplate/index.vue" +import RegionsDialog from "/@/components/regionsDialog/index.vue"; +export default defineComponent({ + components: { + CheckTemplate, + UserSelections, + RegionsDialog, + }, + setup() { + const form = reactive({ + name: '', + value: '', + value2: '', + teamLeader: '', + + // data: '', + // dataSelect: '', + date1: '', + date2: '', + delivery: false, + type: [], + resource: '', + desc: '', + }); + + // 可选择树形选择框 + const value = ref() + + const data = [ + { + value: '1', + label: '广汇能源综合物流发展有限责任公司', + children: [ + { + value: '1-1', + label: '生产运行部', + children: [ + { + value: '1-1-1', + label: '工艺二班', + }, + ], + }, + ], + } + ] + // 树形选择框 + const value2 = ref() + + const dataSelect = [ + { + value: '1', + label: '广汇能源综合物流发展有限责任公司', + children: [ + { + value: '1-1', + label: '生产运行部', + children: [ + { + value: '1-1-1', + label: '工艺二班', + }, + ], + }, + ], + } + ] + // 应急队伍弹窗 + const ShowRef=ref() + const daiInpt=()=>{ + ShowRef.value.openDailog() + } + // 选择区域弹窗 + const openRef=ref() + const regionsDialog=()=>{ + openRef.value.openDailog() + } + // 打开编写人选择用户弹窗 + const userRef = ref(); + const openUser = () => { + userRef.value.openDialog(); + }; + // 日期选择 + const datetime = ref('') + return { + form, + value, + data, + value2, + dataSelect, + openUser, + userRef, + Search, + ShowRef, + daiInpt, + openRef, + datetime, + regionsDialog, + }; + }, +}); +</script> +<style scoped> +.title { + text-align: center; + font-size: 16px; + margin-bottom: 20px; +} +.box { + border: 1px solid #dcdfe6; + box-shadow: 0 2px 4px 0 rgb(0 0 0 / 12%), 0 0 6px 0 rgb(0 0 0 / 4%); +} +.navType { + background-color: #fff; +} +.tiao { + width: 100%; + height: 1px; + background-color: #dcdfe6; + margin: 30px 0; + position: relative; +} +.typeS { + width: 80px; + background-color: #fff; + position: absolute; + left: 30px; + top: -9px; + font-size: 14px; + text-align: center; +} +.logoColor { + background-color: #67c23a; + color: #fff; + padding: 5px 8px; + border-radius: 5px; + margin-right: 5px; +} +.btns { + width: 100%; + padding: 20px 0; + background-color: #fff; + position: fixed; + bottom: 0px; + left: 0px; + text-align: center; + box-shadow: 0 -3px 5px 0 rgb(0 0 0 / 12%); +} +.title2 { + padding: 20px 0 20px 10px; + width: 100%; + border: 1px solid #dcdfe6; +} +.el-row{ + padding:0 0 20px 0; +} +.select{ + width: 100%; +} +.select ::v-deep .el-select{ + width: 100%; +} +</style> diff --git a/src/views/contingencyManagement/abolishDialog/component/lowerPlate.vue b/src/views/contingencyManagement/abolishDialog/component/lowerPlate.vue new file mode 100644 index 0000000..cbb82fb --- /dev/null +++ b/src/views/contingencyManagement/abolishDialog/component/lowerPlate.vue @@ -0,0 +1,120 @@ +<template> + <div class="box"> + <el-form ref="formS" :model="form" :rules="rules" label-width="120px"> + <el-row> + <el-col :span="15"> + <el-form-item label="流程标题"> + <el-input v-model="form.names" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="15"> + <el-form-item label="下级审批日期"> + <el-date-picker v-model="form.date1" type="date" placeholder="下级审批日期" style="width: 100%" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="15"> + <el-form-item label=""> + <el-checkbox v-model="form.delivery" label="是否抄送" @change="typeChang"/> + </el-form-item> + </el-col> + </el-row> + <el-row v-if="form.delivery"> + <el-col :span="15"> + <el-form-item label="抄送给" prop="resource"> + <el-input v-model="form.resource" placeholder=""> + <template #append> <el-button :icon="Search" @click="openDai" /> </template + ></el-input> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="15"> + <el-form-item label=""> + <el-checkbox v-model="form.type" label="指定下一步处理者(不设置就使用默认处理人)"/> + </el-form-item> + </el-col> + </el-row> + <el-row v-if="form.type"> + <el-col :span="15"> + <el-form-item label="指定" prop="desc"> + <el-input v-model="form.desc" placeholder=""> + <template #append> <el-button :icon="Search" @click="openDai" /> </template + ></el-input> + </el-form-item> + </el-col> + </el-row> + </el-form> + </div> + <DailogSearchUser ref="ShowUser"></DailogSearchUser> +</template> +<script lang="ts"> +import { defineComponent, ref, reactive } from 'vue'; +import DailogSearchUser from '/@/components/DailogSearchUser/index.vue' +import { Search } from '@element-plus/icons-vue'; +import type { FormInstance, FormRules } from 'element-plus' +export default defineComponent({ + components:{DailogSearchUser}, + setup() { + const formS=ref<FormInstance>() + let form = reactive({ + names: '', + region: '', + date1: '', + date2: '', + delivery: "", + type: "", + resource: '', + desc: '', + }); + const typeChang=()=>{ + console.log('tag',form) + } + const rules = reactive<FormRules>({ + resource: [ + { + type: 'array', + required: true, + message: '用户不能为空', + trigger: 'change', + }, + ], + desc: [ + { + required: true, + message: '用户不能为空', + trigger: 'change', + }, + ]}) + const ShowUser=ref() + const openDai =()=>{ + ShowUser.value.openDailog() + } + return { + form, + rules, + formS, + typeChang, + ShowUser, + openDai, + Search, + }; + }, +}); +</script> + +<style scoped> +.box { + margin: 30px 0 100px 0; + background-color: #fff; + border: 1px solid #dcdfe6; + box-shadow: 0 2px 4px 0 rgb(0 0 0 / 12%), 0 0 6px 0 rgb(0 0 0 / 4%); + padding: 20px; +} +.el-row { + padding: 0 0 20px 0; +} +</style> \ No newline at end of file diff --git a/src/views/contingencyManagement/contingency/component/addEmergencyPersonnel.vue b/src/views/contingencyManagement/contingency/component/addEmergencyPersonnel.vue new file mode 100644 index 0000000..cafe13e --- /dev/null +++ b/src/views/contingencyManagement/contingency/component/addEmergencyPersonnel.vue @@ -0,0 +1,305 @@ +<template> + <div class="system-edit-user-container"> + <el-dialog + :title="titles" + v-model="isShowDialog" + width="40%" + draggable + :fullscreen="full" + @close="resetForm(ruleFormRef)" + > + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-form + ref="ruleFormRef" + :model="ruleForm" + size="default" + :rules="rules" + :disabled="disabled" + label-width="90px"> + <el-row :gutter="35"> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="选择人员" prop="name"> + <el-input + v-model="ruleForm.name" + placeholder="请选择" + class="input-with-select" + > + <template #append> + <el-button :icon="Search" @click="openUser"/> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="人员工号" prop="jobNumber"> + <el-input v-model="ruleForm.jobNumber" placeholder="请填写人员工号"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="人员名称" prop="name"> + <el-input v-model="ruleForm.name" placeholder="请填写人员名称"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="人员性别" prop="gender"> + <el-radio-group v-model="ruleForm.gender"> + <el-radio :label="false">男</el-radio> + <el-radio :label="true">女</el-radio> + </el-radio-group> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="手机号码" prop="phone"> + <el-input v-model="ruleForm.phone" placeholder="请填写手机号码"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="职位" prop="position"> + <el-input v-model="ruleForm.position" placeholder="请填写职位"></el-input> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> +<!-- <el-button size="default" type="primary" @click="addForm(ruleFormRef)">继续添加</el-button>--> + <el-button size="default" @click="resetForm(ruleFormRef)">关闭</el-button> + <el-button size="default" type="primary" v-if="disabled == true ? false : true" @click="submitForm(titles, ruleFormRef)" >确定</el-button> + </span> + </template> + </el-dialog> + <DailogSearchUserManger ref="userRef" @SearchUser="onUser"/> + </div> +</template> + +<script lang="ts"> +import { + ref, + reactive, + defineComponent +} from 'vue'; + +import type { + FormRules, + FormInstance, +} from 'element-plus' +import { ElMessage } from 'element-plus'; +import { + Search, + FullScreen, +} from '@element-plus/icons-vue' +import DailogSearchUserManger from "/@/components/DailogSearchUserManger/index.vue" +import {contingencyApi} from "/@/api/contingencyManagement/contingency"; + +export default defineComponent({ + name: 'addTeamLeader', + components: { + // Search, + DailogSearchUserManger + }, + setup(props, { emit }) { + const isShowDialog = ref(false) + const ruleFormRef = ref<FormInstance>() + const ruleForm = ref ({ + teamId: '', + userUid: '', + gender: '', + jobNumber: '', // 人员工号 + name: '', // 人员名称 + phone: '', // 手机号码 + position: '', // 职位 + }); + const rules = reactive<FormRules>({ + jobNumber: [ + { + required: true, + message: '人员工号不能为空', + trigger: 'change', + }, + ], + personnelName: [ + { + required: true, + message: '人员名称不能为空', + trigger: 'change', + }, + ], + personnelGender: [ + { + required: true, + message: '人员性别不能为空', + trigger: 'change', + }, + ], + phone: [ + { + required: true, + message: '手机号码不能为空', + trigger: 'change', + }, + ], + position: [ + { + required: true, + message: '职位不能为空', + trigger: 'change', + }, + ], + }) + const titles = ref(); + const disabled = ref(); + const submitForm = async (title: string, formEl: FormInstance | undefined) => { + if (title == '新建应急队伍人员') { + if (!formEl) return; + await formEl.validate((valid, fields) => { + if (valid) { + isShowDialog.value = false; + // console.log('-------',ruleForm.value) + // emit('myAdd', ruleForm.value); + contingencyApi() + .addEmergencyTeamPersonnel(ruleForm.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'success', + }); + emit('myAdd', true); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + emit('myAdd', true); + } + formEl.resetFields(); + }); + } else { + console.log('error submit!', fields); + } + }); + } + else if (title == '修改应急队伍人员') { + if (!formEl) return; + await formEl.validate((valid, fields) => { + if (valid) { + isShowDialog.value = false; + contingencyApi() + .editEmergencyTeamPersonnel(ruleForm.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: '修改成功', + type: 'success', + }); + emit('myAdd', true); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + emit('myAdd', true); + } + formEl.resetFields(); + }); + } else { + console.log('error submit!', fields); + } + }); + formEl.resetFields(); + ruleForm.value = { + teamId: '', + userUid: '', + gender: '', + jobNumber: '', // 人员工号 + name: '', // 人员名称 + phone: '', // 手机号码 + position: '', // 职位 + }; + } + } + const resetForm = (formEl: FormInstance | undefined) => { + isShowDialog.value = false; + if (!formEl) return; + formEl.resetFields(); + }; + + // 打开弹窗 + const openDialog = (title: string, id: number,teamId:number, type: boolean) => { + isShowDialog.value = true; + titles.value = title; + disabled.value = type; + ruleForm.value.teamId = teamId + + if (title == '查看应急队伍人员' || title == '修改应急队伍人员') { + contingencyApi() + .seeEmergencyTeamPersonnel(id) + .then((res) => { + if (res.data.code == 200) { + ruleForm.value = res.data.data; + } + }); + } + }; + // 打开用户选择弹窗 + const userRef = ref(); + const openUser = () => { + userRef.value.openDailog(); + }; + const onUser = (e:any) => { + ruleForm.value.userUid=e[0].uid + ruleForm.value.gender=e[0].sex + ruleForm.value.name=e[0].realName + ruleForm.value.jobNumber=e[0].jobNumber + ruleForm.value.phone=e[0].phone + ruleForm.value.position=e[0].position + }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + return { + openDialog, + // closeDialog, + isShowDialog, + ruleFormRef, + // submitForm, + // onCancel, + ruleForm, + rules, + Search, + toggleFullscreen, + FullScreen, + full, + resetForm, + titles, + disabled, + emit, + openUser, + userRef, + onUser, + submitForm, + }; + }, +}); +</script> +<style scoped lang="scss"> +.textarea{ + height: 168px!important; +} +.textarea ::v-deep .el-textarea__inner{ + height: 168px!important; +} +::v-deep .el-table__cell { + font-weight: 400; +} +</style> \ No newline at end of file diff --git a/src/views/contingencyManagement/contingency/component/openAdd.vue b/src/views/contingencyManagement/contingency/component/openAdd.vue new file mode 100644 index 0000000..2d9e986 --- /dev/null +++ b/src/views/contingencyManagement/contingency/component/openAdd.vue @@ -0,0 +1,569 @@ +<template> + <div class="system-edit-user-container"> + <el-dialog :title="titles" v-model="isShowDialog" width="50%" draggable :fullscreen="full" @close="resetForm(ruleFormRef)"> + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-form ref="ruleFormRef" :model="ruleForm" size="default" :rules="rules" label-width="120px" + :disabled="disabled"> + <el-row :gutter="35"> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="队伍名称" prop="teamName"> + <el-input v-model="ruleForm.teamName" placeholder="请填写队伍名称"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="队伍级别" prop="teamLevel"> + <el-select v-model="ruleForm.teamLevel" class="w100" placeholder="请选择"> + <el-option label="公司" value="1"></el-option> + <el-option label="分厂-车间" value="2"></el-option> + <el-option label="工序-班组等" value="3"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="队伍负责人" prop="principalName"> + <el-input v-model="ruleForm.principalName" placeholder="请选择" class="input-with-select"> + <template #append> + <el-button :icon="Search" @click="openUser"/> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="负责人部门" prop="principalDepartmentId"> + <el-tree-select v-model="ruleForm.principalDepartmentId" :data="newTreeList" class="w100" + :props="propse" clearable placeholder="请选择"/> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="负责人手机" prop="principalPhone"> + <el-input v-model="ruleForm.principalPhone" placeholder="请填写负责人手机"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="固定电话" prop="telephoneNumber"> + <el-input v-model="ruleForm.telephoneNumber" placeholder="请填写固定电话"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="队伍描述" prop="teamDesc"> + <el-input class="textarea" v-model="ruleForm.teamDesc" type="textarea" maxlength="150" + placeholder="请填写队伍描述"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="相关附件" prop="fileList"> + <uploaderFile :fileList="fileList" :systemName="'EMERGENCY'" :disabled="disabled" + @successUploader="successUploader"></uploaderFile> + </el-form-item> + </el-col> + </el-row> + </el-form> + <el-row :gutter="35"> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick"> + <el-tab-pane label="应急队伍人员" name="first" > + <el-button type="primary" size="default" @click="onAddEmergencyPersonnel(ruleFormRef)" :disabled="disabled">新增 + </el-button> + <el-table + :data="tableData" + style="width: 100%; margin-top: 15px" + ref="multipleTableRef" + :header-cell-style="{ background: '#f6f7fa', color: '#909399' }" + :disabled="disabled" + > + <el-table-column prop="jobNumber" label="人员工号" show-overflow-tooltip></el-table-column> + <el-table-column prop="name" label="人员名称" show-overflow-tooltip></el-table-column> + <el-table-column prop="phone" label="手机号码" show-overflow-tooltip></el-table-column> + <el-table-column prop="position" label="职位" show-overflow-tooltip></el-table-column> + <el-table-column label="操作" width="250" align="center"> + <template #default="scope"> + <el-button :disabled="disabled" size="small" @click="onEdit('查看应急队伍人员',scope.row.id)">查看 + </el-button> + <el-button :disabled="disabled" size="small" @click="onEdit('修改应急队伍人员',scope.row.id)" + style="margin-right: 5px">编辑 + </el-button> + <el-button :disabled="disabled" size="small" @click="onRowDel(scope.row.id)" + style="margin-right: 5px">删除 + </el-button> + </template> + </el-table-column> + </el-table> + </el-tab-pane> + </el-tabs> + </el-col> + </el-row> + <template #footer> + <span class="dialog-footer"> + <el-button @click="resetForm(ruleFormRef)" size="default">关闭</el-button> + <el-button size="default" v-if="disabled == true ? false : true" type="primary" + @click="onSubmit(titles, ruleFormRef)">确定</el-button> + </span> + </template> + </el-dialog> + <AddEmergencyPersonnel ref="addRef" @myAdd="onMyAdd"/> + <DailogSearchUserManger ref="userRef" @SearchUser="onUser"/> + </div> +</template> + +<script lang="ts"> + import { + reactive, + ref, + defineComponent, + onMounted, + // toRefs, + } from 'vue'; + import { + ElMessage, + ElMessageBox, + } from 'element-plus'; + + import type { + UploadUserFile, + TabsPaneContext, + FormInstance, + FormRules, + } from 'element-plus' + + import { + Search, + FullScreen + } from '@element-plus/icons-vue' + import AddEmergencyPersonnel from "/@/views/contingencyManagement/contingency/component/addEmergencyPersonnel.vue"; + import DailogSearchUserManger from "/@/components/DailogSearchUserManger/index.vue" + import {contingencyApi} from "/@/api/contingencyManagement/contingency"; + import {goalManagementApi} from "/@/api/goalManagement"; + import uploaderFile from '/@/components/uploaderFile/index.vue'; + // import {releaseDrillPlanApi} from "/@/api/releaseDrillPlan"; + + + export default defineComponent({ + name: 'openAdd', + components: { + AddEmergencyPersonnel, + DailogSearchUserManger, + uploaderFile + }, + setup(prop, {emit}) { + const isShowDialog = ref(false); + const ruleFormRef = ref<FormInstance>(); + const ruleForm = ref({ + teamName: '', // 队伍名称 + teamLevel: '', // 队伍级别 + principalUid: '', // 队伍负责人 + principalName: '', + principalDepartmentId: '', //负责人部门 + principalPhone: '', // 负责人手机 + telephoneNumber: '', // 固定电话 + teamDesc: '', //队伍描述 + fileList: [], + memberList: [] + }); + const titles = ref(); + const disabled = ref(); + const teamId = ref() + // 打开弹窗 + const openDialog = (title: string, id: number, type: boolean) => { + isShowDialog.value = true; + titles.value = title; + disabled.value = type; + teamId.value = id + if (title == '查看应急队伍管理' || title == '修改应急队伍管理') { + contingencyApi() + .seeEmergencyTeam(id) + .then((res) => { + if (res.data.code == 200) { + ruleForm.value = res.data.data; + fileList.value = (res.data.data.fileList?res.data.data.fileList:[]) + initFileListData() + listApi() + } + }); + } + } + // 上传附件 + const fileList = ref([]) + const initFileListData = async () => { + for(var a = 0;a<fileList.value.length;a++){ + fileList.value[a].name = fileList.value[a].fileName + } + } + // 上传成功组装数据 + const successUploader = (list) =>{ + fileList.value = list + const formFileList = [] + for(var a = 0;a<fileList.value.length;a++){ + formFileList.push( + { + fileName:fileList.value[a].fileName, + fileUrl:'' + } + ) + } + ruleForm.value.fileList = formFileList + } + //定义树形下拉框 + const principalDepartmentId = ref() + const data = ref() + + + + //el-tree-select回显 + const propse = { + label: 'depName', + children: 'children', + }; + const newTreeList = []; + //得到部门树 + const department = async () => { + await goalManagementApi() + .getTreedepartment() + .then((res) => { + if (res.data.code == 200) { + data.value = res.data.data; + getTreeList(res.data.data, newTreeList); + } else { + ElMessage.error(res.data.msg); + } + }); + }; + // 递归树状数据且修改字段名 + const getTreeList = (treeList, newTreeList) => { + treeList.map((c) => { + let tempData = { + depName: c.depName, + value: c.depId, + children: [], + }; + if (c.children && c.children.length > 0) { + tempData.children = []; + getTreeList(c.children, tempData.children); + } + newTreeList.push(tempData); + }); + }; + onMounted(() => { + department(); + }); + + + + + // 打开用户选择弹窗 + const userRef = ref(); + const openUser = () => { + userRef.value.openDailog(); + }; + const onUser = (e: any) => { + ruleForm.value.principalUid = e[0].uid + ruleForm.value.principalName = e[0].realName + }; + //定义tabs切换 + const activeName = ref('first') + const handleClick = (tab: TabsPaneContext, event: Event) => { + console.log(tab, event) + } + + // 必填项提示 + const rules = reactive<FormRules>({ + teamName: [ + { + required: true, + message: '队伍名称不能为空', + trigger: 'change', + }, + ], + teamLevel: [ + { + required: true, + message: '队伍级别不能为空', + trigger: 'change', + }, + ], + principalUid: [ + { + required: true, + message: '队伍负责人不能为空', + trigger: 'change', + }, + ], + principalDepartmentId: [ + { + required: true, + message: '负责人部门不能为空', + trigger: 'change', + }, + ], + principalPhone: [ + { + required: true, + message: '负责人手机不能为空', + trigger: 'change', + }, + ], + telephoneNumber: [ + { + required: true, + message: '固定电话不能为空', + trigger: 'change', + }, + ], + }) + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + const onSubmit = async (title: string, formEl: FormInstance | undefined) => { + if(!ruleForm.value.fileList){ + ruleForm.value.fileList = [] + } + if (title == '新建应急队伍管理') { + if (!formEl) return; + await formEl.validate((valid, fields) => { + if (valid) { + isShowDialog.value = false; + if(teamId.value==null||teamId.value==''){ + contingencyApi() + .addEmergencyTeam(ruleForm.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'success', + }); + emit('myAdd', true); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + emit('myAdd', true); + } + formEl.resetFields(); + }); + }else { + ElMessage({ + showClose: true, + message: '添加成功', + type: 'success', + }); + emit('myAdd', true); + } + } else { + console.log('error submit!', fields); + } + }); + } else if (title == '修改应急队伍管理') { + if (!formEl) return; + await formEl.validate((valid, fields) => { + if (valid) { + isShowDialog.value = false; + contingencyApi() + .editEmergencyTeam(ruleForm.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: '修改成功', + type: 'success', + }); + emit('myAdd', true); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + emit('myAdd', true); + } + formEl.resetFields(); + }); + } else { + console.log('error submit!', fields); + } + }); + formEl.resetFields(); + ruleForm.value = { + teamName: '', // 队伍名称 + teamLevel: '', // 队伍级别 + principalUid: '', // 队伍负责人 + principalDepartmentId: '', //负责人部门 + principalPhone: '', // 负责人手机 + telephoneNumber: '', // 固定电话 + teamDesc: '', //队伍描述 + fileList: [], + memberList: [] + }; + } + }; + const resetForm = (formEl: FormInstance | undefined) => { + isShowDialog.value = false; + if (!formEl) return; + formEl.resetFields(); + fileList.value = [] + tableData.value=[] + ruleForm.value = {} + }; + // 定义表格数据 + const tableData = ref([]); + //添加队伍负责人弹窗 + const addRef = ref(); + const onAddEmergencyPersonnel = async (formEl: FormInstance | undefined) => { + if(!ruleForm.value.fileList){ + ruleForm.value.fileList = [] + } + if (!formEl) return; + await formEl.validate((valid, fields) => { + if (valid) { + // isShowDialog.value = false; + if(teamId.value == ''||teamId.value==null){ + ElMessageBox.confirm('确认添加此应急队伍?', '提示', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + contingencyApi() + .addEmergencyTeam(ruleForm.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'success', + }); + teamId.value = res.data.data.id + addRef.value.openDialog('新建应急队伍人员','',teamId.value); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + } + }); + }) + .catch(() => {}); + + }else { + addRef.value.openDialog('新建应急队伍人员','',teamId.value); + } + + + } else { + console.log('error submit!', fields); + } + }); + }; + // 请求列表数据 + const listApi = async () => { + let res = await contingencyApi().getEmergencyTeamPersonnelList(teamId.value); + if (res.data.code == 200) { + tableData.value = res.data.data; + } else { + ElMessage.error(res.data.msg); + } + }; + // 新增后刷新 + const onMyAdd = (e: object) => { + listApi(); + }; + // 打开修改弹窗 + const onEdit = (val: string, row: object) => { + if (val == '查看应急队伍人员') { + addRef.value.openDialog('查看应急队伍人员', row,teamId.value, true); + } else { + addRef.value.openDialog('修改应急队伍人员', row,teamId.value, false); + } + }; + // 删除 + const onRowDel = (data: any) => { + ElMessageBox.confirm('确定删除所选项吗?', '提示', { + confirmButtonText: '确认', + cancelButtonText: '取消', + type: 'warning', + }).then(() => { + contingencyApi() + .deleteEmergencyTeamPersonnel(data) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'success', + }); + listApi() + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + listApi() + } + }); + }) + .catch(() => { + }); + }; + return { + openDialog, + fileList, + principalDepartmentId, + data, + activeName, + handleClick, + tableData, + Search, + resetForm, + isShowDialog, + ruleFormRef, + ruleForm, + rules, + addRef, + userRef, + titles, + disabled, + propse, + emit, + onSubmit, + openUser, + onAddEmergencyPersonnel, + toggleFullscreen, + FullScreen, + full, + onUser, + onMyAdd, + listApi, + onEdit, + onRowDel, + department, + teamId, + newTreeList, + successUploader, + initFileListData + }; + }, + }); +</script> +<style scoped lang="scss"> + .textarea { + height: 168px !important; + } + + .textarea ::v-deep .el-textarea__inner { + height: 168px !important; + } + + ::v-deep .el-table__cell { + font-weight: 400; + } +</style> + diff --git a/src/views/contingencyManagement/contingency/component/upData.vue b/src/views/contingencyManagement/contingency/component/upData.vue new file mode 100644 index 0000000..cc3e2d0 --- /dev/null +++ b/src/views/contingencyManagement/contingency/component/upData.vue @@ -0,0 +1,125 @@ +<template> + <el-dialog + v-model="dialogVisible" + title="导入Excel" + width="50%" + draggable + :fullscreen="full" + > + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-upload + v-model:file-list="fileList" + class="upload-demo" + action="https://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15" + multiple + :on-preview="handlePreview" + :on-remove="handleRemove" + :before-remove="beforeRemove" + :limit="3" + :on-exceed="handleExceed" + > + <el-button size="default">下载模板</el-button> + <el-button size="default" type="primary">点击上传</el-button> + <template #tip> + <div class="el-upload__tip"> + 只允许导入“xls”或“xlsx”格式文件! + </div> + </template> + </el-upload> + </el-dialog> +</template> +<script lang="ts"> +import { ref, + defineComponent, +} from "vue"; +import { + ElMessage, + ElMessageBox +} from "element-plus"; +import type { + UploadProps, + UploadUserFile, +} from "element-plus"; +import { + FullScreen +} from '@element-plus/icons-vue' +export default defineComponent({ + setup() { + let dialogVisible =ref<boolean>(false) + const fileList = ref<UploadUserFile[]>([ + // { + // name: "element-plus-logo.svg", + // url: "https://element-plus.org/images/element-plus-logo.svg", + // }, + // { + // name: "element-plus-logo2.svg", + // url: "https://element-plus.org/images/element-plus-logo.svg", + // }, + ]); + + const handleRemove: UploadProps["onRemove"] = (file, uploadFiles) => { + console.log(file, uploadFiles); + }; + + const handlePreview: UploadProps["onPreview"] = (uploadFile) => { + console.log(uploadFile); + }; + + const handleExceed: UploadProps["onExceed"] = (files, uploadFiles) => { + ElMessage.warning( + `The limit is 3, you selected ${ + files.length + } files this time, add up to ${ + files.length + uploadFiles.length + } totally` + ); + }; + + const beforeRemove: UploadProps["beforeRemove"] = ( + uploadFile, + uploadFiles + ) => { + return ElMessageBox.confirm( + `Cancel the transfert of ${uploadFile.name} ?` + ).then( + () => true, + () => false + ); + }; + // 打开弹窗 + const openDialog = (type:string,value:any,projectList: any,projectId:string) => { + dialogVisible.value=true + } + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + return { + dialogVisible, + fileList, + handleRemove, + handlePreview, + handleExceed, + beforeRemove, + openDialog, + toggleFullscreen, + FullScreen, + full, + }; + }, +}); +</script> +<style scoped lang="scss"> +.el-upload__tip{ + margin-left: 100px; + margin-top: 20px; +} +::v-deep .el-dialog__header{ + border-bottom: 1px solid #e8e8e8; +} +</style> \ No newline at end of file diff --git a/src/views/contingencyManagement/contingency/index.vue b/src/views/contingencyManagement/contingency/index.vue new file mode 100644 index 0000000..8083231 --- /dev/null +++ b/src/views/contingencyManagement/contingency/index.vue @@ -0,0 +1,401 @@ +<template> + <div class="system-user-container"> + <el-card shadow="hover"> + <div class="system-user-search mb15"> + <el-form :inline="true" class="demo-form-inline"> + <el-form-item> + <el-input size="default" v-model="listQuery.searchParams.teamName" placeholder="队伍名称"> </el-input> + </el-form-item> + <el-form-item> + <el-select size="default" v-model="listQuery.searchParams.teamLevel" placeholder="请选择队伍级别"> + <el-option label="公司" value="1"></el-option> + <el-option label="分厂-车间" value="2"></el-option> + <el-option label="工序-班组等" value="3"></el-option> + </el-select> + </el-form-item> + <el-form-item> + <el-button size="default" type="primary" class="ml10" @click="onSubmit"> + 查询 + </el-button> + <el-button size="default" class="ml10" @click="submitReset"> + 重置 + </el-button> + </el-form-item> + </el-form> + </div> + <div class="button_Line"> + <div class="button_Left"> + <el-button size="default" type="primary" @click="onOpenAdd"> + <el-icon> + <Plus /> + </el-icon>新建 + </el-button> + <el-button size="default" type="warning" plain :disabled="warning" @click="onEdit('修改', deleteAll[0])"> + <el-icon> + <Edit /> + </el-icon>修改 + </el-button> + <el-button size="default" type="danger" plain :disabled="danger" @click="onDeleteAll"> + <el-icon> + <Delete /> + </el-icon>删除 + </el-button> + </div> +<!-- <div class="button_Right">--> +<!-- <el-button size="default" @click="upButton">--> +<!-- <el-icon>--> +<!-- <Upload />--> +<!-- </el-icon>--> +<!-- </el-button>--> +<!-- <el-button size="default">--> +<!-- <el-icon>--> +<!-- <Download />--> +<!-- </el-icon>--> +<!-- </el-button>--> +<!-- <el-button size="default">--> +<!-- <el-icon>--> +<!-- <Refresh />--> +<!-- </el-icon>--> +<!-- </el-button>--> +<!-- </div>--> + </div> + <el-table + :data="tableData" + style="width: 100%" + ref="multipleTableRef" + @selection-change="handleSelectionChange" + > + <el-table-column + type="selection" + width="55" + /> + <el-table-column prop="teamName" label="队伍名称" show-overflow-tooltip sortable></el-table-column> + <el-table-column prop="teamLevel" label="队伍级别" show-overflow-tooltip sortable> + <template #default="scope"> + <span v-if="scope.row.teamLevel == 1">公司</span> + <span v-if="scope.row.teamLevel == 2">分厂-车间</span> + <span v-if="scope.row.teamLevel == 3">工序-班组等</span> + </template> + </el-table-column> + <el-table-column prop="teamDesc" label="队伍描述" show-overflow-tooltip sortable></el-table-column> + <el-table-column prop="principalPhone" label="负责人手机" show-overflow-tooltip sortable></el-table-column> + <el-table-column prop="fileList" label="相关附件" show-overflow-tooltip sortable> + + </el-table-column> + <el-table-column label="操作" width="200" align="center" fixed="right"> + <template #default="scope"> + <el-button size="small" text type="primary" @click="onEdit('详情',scope.row.id)"> + <el-icon style="margin-right: 5px;"> + <View /> + </el-icon>查看 + </el-button> + <el-button size="small" text type="primary" @click="onEdit('修改',scope.row.id)"> + <el-icon style="margin-right: 5px;"> + <EditPen /> + </el-icon>修改 + </el-button> + <el-button size="small" text type="primary" @click="onRowDel(scope.row.id)"> + <el-icon> + <Delete /> + </el-icon>删除 + </el-button> + </template> + </el-table-column> + </el-table> + <div class="pages"> + <el-pagination + v-if="tableData.length == 0 ? false : true" + @size-change="onHandleSizeChange" + @current-change="onHandleCurrentChange" + class="mt15" + :pager-count="5" + :page-sizes="[10, 20, 30]" + v-model:currentPage="pageIndex" + background + v-model:page-size="pageSize" + layout="total, sizes, prev, pager, next, jumper" + :total="total" + > + </el-pagination> + </div> + </el-card> + <OpenAdd ref="addRef" @myAdd="onMyAdd" /> + <upData ref="upShow"></upData> + </div> +</template> + +<script lang="ts"> +import { + // toRefs, + reactive, + onMounted, + ref, + defineComponent +} from 'vue'; +import { + ElMessageBox, + ElMessage, +} from 'element-plus'; +import { + Plus, + Delete, + // Upload, + // Download, + // Refresh, + Edit, + View, + EditPen, +} from '@element-plus/icons-vue' + +import OpenAdd from '../../contingencyManagement/contingency/component/openAdd.vue' +import UpData from '../../contingencyManagement/contingency/component/upData.vue'; +import {contingencyApi} from "../../../api/contingencyManagement/contingency"; + +export default defineComponent({ + name: 'systemUser', + components: { + OpenAdd, + View, + Edit, + EditPen, + Plus, + Delete, + // Upload, + // Download, + // Refresh, + UpData, + contingencyApi + }, + setup() { + // 列表参数 + const listQuery = reactive({ + pageIndex: 1, + pageSize: 10, + searchParams: { + teamName: "", + teamLevel: "", + } + }) + // 定义表格数据 + const tableData = ref([]); + // 列表数据请求 + const onSubmit = async () => { + let res = await contingencyApi().getTeamManagementList(listQuery) + if(res.data.code === '200'){ + tableData.value = res.data.data; + for(var a = 0;a<tableData.value.length;a++){ + if(tableData.value[a].fileList!=null&&tableData.value[a].fileList!=''&&tableData.value[a].fileList.length!=0){ + tableData.value[a].fileList = tableData.value[a].fileList[0].fileName + } + } + pageIndex.value = res.data.pageIndex; + pageSize.value = res.data.pageSize; + total.value = res.data.total; + }else{ + ElMessage({ + showClose: true, + type:'error', + message:res.data.msg + }) + } + } + // 重置 + const submitReset = () => { + listQuery.searchParams.teamName = ''; + listQuery.searchParams.teamLevel = ''; + onSubmit(); + }; + const warning = ref(true); + const danger = ref(true); + const deleteAll = ref(); + const handleSelectionChange = (val: any) => { + let valId = JSON.parse(JSON.stringify(val)); + let arr = []; + for (let i = 0; i < valId.length; i++) { + arr.push(valId[i].id); + } + deleteAll.value = arr; + if (val.length == 1) { + warning.value = false; + danger.value = false; + } else if (val.length == 0) { + warning.value = true; + danger.value = true; + } else { + warning.value = true; + danger.value = false; + } + }; + + // 上传 + // const upShow=ref() + // const upButton=()=>{ + // upShow.value.openDialog() + // } + // 打开新增应急队伍弹窗 + const addRef = ref(); + const onOpenAdd = () => { + addRef.value.openDialog('新建应急队伍管理'); + }; + // 新增后刷新 + const onMyAdd = (e: boolean) => { + if (e) { + onSubmit(); + } else { + onSubmit(); + } + }; + // 打开修改应急队伍弹窗 + const onEdit = (val: string, row: object) => { + if (val == '详情') { + addRef.value.openDialog('查看应急队伍管理',row,true); + } else { + addRef.value.openDialog('修改应急队伍管理',row,false); + } + }; + // 删除用户 + const onRowDel = (data: any) => { + ElMessageBox.confirm('确定删除所选项吗?', '提示', { + confirmButtonText: '确认', + cancelButtonText: '取消', + type: 'warning', + }).then(() => { + contingencyApi() + .deleteEmergencyTeam([data]) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'success', + }); + onSubmit(); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + onSubmit(); + } + }); + }).catch(() => {}); + }; + // 多选删除 + const onDeleteAll = () => { + ElMessageBox.confirm('确定删除所选项吗?', '提示', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + contingencyApi() + .deleteEmergencyTeam(deleteAll.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'success', + }); + onSubmit(); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + onSubmit(); + } + }); + }) + .catch(() => {}); + }; + // 分页 + const pageIndex = ref(); + const pageSize = ref(); + const total = ref(); + // 分页改变 + const onHandleSizeChange = (val: number) => { + listQuery.pageSize = val; + onSubmit(); + }; + const onHandleCurrentChange = (val: number) => { + listQuery.pageIndex = val; + onSubmit(); + }; + // 页面加载时 + onMounted(() => { + onSubmit(); + }); + return { + listQuery, + onSubmit, + // upButton, + // upShow, + onOpenAdd, //新增 + addRef, + pageIndex, + pageSize, + total, + onEdit, + handleSelectionChange, + submitReset, + onRowDel, + onMyAdd, + tableData, + onDeleteAll, + onHandleSizeChange, + onHandleCurrentChange, + deleteAll, + warning, + danger, + }; + }, +}); +</script> +<style scoped lang="scss"> +.table_Box{ + padding: 20px; + background-color: #fff; +} +.tableForm{ + margin-top: 10px; +} +/*按钮行*/ + .button_Line{ + display: flex; + flex-direction: row; + justify-content: space-between; + margin-bottom: 10px; + } +//分页 +.pages{ + display: flex; + justify-content: flex-end; + margin-top: 15px; +} +.el-form .el-form-item{ + margin-bottom: 0px!important; +} +//弹窗底部边框线 +::v-deep .el-dialog__footer{ + border-top: 1px solid #e8e8e8; + border-radius: 0 0 4px 4px; +} +//弹窗顶部边框线 +::v-deep .el-dialog__header { + border-bottom: 1px solid #e8e8e8; + margin-right: 0; + border-radius: 4px 4px 0 0; +} +//表头 +::v-deep .el-table th.el-table__cell { + background-color: #f6f7fa; + font-weight: 400; + color: #909399; +} +.el-table .sort-caret.ascending{ + border-bottom-color: #c0c4cc; +} +</style> \ No newline at end of file diff --git a/src/views/contingencyManagement/emergencyDrill/drillImplementationEvaluation/component/approvalProgress.vue b/src/views/contingencyManagement/emergencyDrill/drillImplementationEvaluation/component/approvalProgress.vue new file mode 100644 index 0000000..327405b --- /dev/null +++ b/src/views/contingencyManagement/emergencyDrill/drillImplementationEvaluation/component/approvalProgress.vue @@ -0,0 +1,925 @@ +<template> + <div class="system-edit-user-container"> + <el-dialog + :title="titles" + v-model="isShowDialog" + width="900px" + draggable + :fullscreen="full" + @close="resetForm(ruleFormRef)" + > + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-form + ref="ruleFormRef" + :model="ruleForm" + size="default" + label-width="120px" + > + <el-row :gutter="35"> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="演练名称" prop="emergencyPlanName"> + <el-input :disabled="true" v-model="ruleForm.emergencyPlanName" placeholder="请填写队伍名称"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="演练地点" prop="drillAddress"> + <el-input :disabled="true" v-model="ruleForm.drillAddress" placeholder="请填写队伍名称"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="主办部门" placeholder="请选择" prop="departmentId"> + <!--<el-tree-select--> + <!--v-model="ruleForm.departmentId"--> + <!--:data="data" class="w100"--> + <!--placeholder="请选择"/>--> + + <el-tree-select :disabled="true" v-model="ruleForm.departmentId" + :data="newTreeList" :props="propse" class="w100" placeholder="请选择" /> + </el-form-item> + + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="演练方式" prop="drillWay"> + <el-select :disabled="true" v-model="ruleForm.drillWay" class="w100" placeholder="请选择"> + <el-option label="综合" value="0"></el-option> + <el-option label="桌面" value="1"></el-option> + <el-option label="专项" value="2"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="应急预案" prop="drillName" > + <el-input + :disabled="true" + v-model="ruleForm.drillName" + placeholder="请选择" + class="input-with-select" + > + <template #append> + <el-button :disabled="true" :icon="Search" @click="daiInpt"/> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="演练级别" prop="drillLevel"> + <el-select :disabled="true" v-model="ruleForm.drillLevel" class="w100" placeholder="请选择"> + <el-option label="公司级" value="1"></el-option> + <el-option label="分厂级" value="2"></el-option> + <el-option label="车间级" value="3"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="计划定制日期" prop="makingPlanDate"> + <el-date-picker :disabled="true" v-model="ruleForm.makingPlanDate" + value-format="YYYY-MM-DD HH:mm:ss" type="datetime" placeholder="选择日期时间" style="width: 100%" /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="计划演练日期" prop="drillPlanDate"> + <el-date-picker :disabled="true" v-model="ruleForm.drillPlanDate" + value-format="YYYY-MM-DD HH:mm:ss" type="datetime" placeholder="选择日期时间" style="width: 100%" /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="修改时间" prop="updateDate"> + <el-date-picker :disabled="true" v-model="ruleForm.updateDate" value-format="YYYY-MM-DD HH:mm:ss" type="datetime" placeholder="选择日期时间" style="width: 100%" /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="计划定制人" prop="makingUserUid"> + <el-input :disabled="true" v-model="ruleForm.makingUserName" placeholder="请填写计划定制人"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="制定部门" prop="makingDepartmentId"> + <!--<el-tree-select--> + <!--v-model="ruleForm.makingDepartmentId"--> + <!--:data="data" class="w100"--> + <!--placeholder="请选择"/>--> + + <el-tree-select :disabled="true" v-model="ruleForm.makingDepartmentId" + :data="newTreeList" :props="propse" class="w100" placeholder="请选择" /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="演练人员" prop="planUserListString" > + <el-input + :disabled="true" + v-model="ruleForm.planUserListString" + placeholder="请选择" + class="input-with-select" + > + <template #append> + <el-button :disabled="true" :icon="Search" @click="openUser"/> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="演练目的" prop="purpose"> + <el-input + :disabled="true" + v-model="ruleForm.purpose" + placeholder="请填写演练目的" + class="input-with-select textarea" + type="textarea" + > + </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="演练负责人" prop="chargeUserListString" > + <el-input + :disabled="true" + v-model="ruleForm.chargeUserListString" + placeholder="请选择" + class="input-with-select" + > + <template #append> + <el-button :disabled="true" :icon="Search" @click="openUser"/> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="保险措施" prop="insuranceMeasures"> + <el-input :disabled="true" v-model="ruleForm.insuranceMeasures" placeholder="请填写保险措施"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="演练经费" prop="drillExpense"> + <el-input :disabled="true" v-model="ruleForm.drillExpense" placeholder="请填写演练经费"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="备注信息" prop="remark"> + <el-input + :disabled="true" + v-model="ruleForm.remark" + placeholder="请填写备注信息" + class="input-with-select textarea" + type="textarea" + > + </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20" style="margin-bottom: 0!important;"> + <el-form-item label="预案附件"> + <uploaderFile :fileList="ruleForm.planFileList" :disabled="true"></uploaderFile> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="实际到场人员" prop="executeUserListString" > + <el-input + v-model="ruleForm.executeUserListString" + placeholder="请选择" + class="input-with-select" + :disabled="true" + > + <template #append> + <el-button :icon="Search" @click="openUser"/> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="演练过程描述" prop="processDesc"> + <el-input :disabled="true" v-model="ruleForm.processDesc" class="textarea" type="textarea" placeholder="请填写演练过程描述"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="演练记录人" prop="recordUserName" > + <el-input + v-model="ruleForm.recordUserName" + placeholder="请选择" + class="input-with-select" + :disabled="true" + > + <template #append> + <el-button :icon="Search" @click="openUser"/> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="演练记录时间" prop="drillRecordDate"> + <el-date-picker + v-model="ruleForm.drillRecordDate" + class="w100" + type="datetime" + placeholder="选择日期时间" + :disabled="true" + /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <div class="el-divider--horizontal"> + <div class="el-divider__text"> + <h3>评价</h3> + </div> + </div> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="演练负责人" prop="evaluationUserListString" > + <el-input + v-model="ruleForm.evaluationUserListString" + placeholder="请选择" + class="input-with-select" + :disabled="disabled" + > + <template #append> + <el-button :icon="Search" @click="openUser"/> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="预案评审-适宜性" prop="suitable"> + <el-select :disabled="disabled" v-model="ruleForm.suitable" class="w100" placeholder="请选择"> + <el-option label="全部能够执行" value="1"></el-option> + <el-option label="全部不能够执行" value="2"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="预案评审-充分性" prop="sufficient"> + <el-select :disabled="disabled" v-model="ruleForm.sufficient" class="w100" placeholder="请选择"> + <el-option label="完全满足应急要求" value="1"></el-option> + <el-option label="不完全满足应急要求" value="2"></el-option> + <el-option label="完全不满足应急要求" value="3"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="人员到位情况" prop="arrival"> + <el-select :disabled="disabled" v-model="ruleForm.arrival" class="w100" placeholder="请选择"> + <el-option label="迅速准确,基本按时到位" value="1"></el-option> + <el-option label="未按时到位" value="2"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="物资到位情况-现场物资" prop="supplies"> + <el-select :disabled="disabled" v-model="ruleForm.supplies" class="w100" placeholder="请选择"> + <el-option label="现场物资充分,全部有效" value="1"></el-option> + <el-option label="现场物资不充分" value="2"></el-option> + <el-option label="现场没有物资" value="3"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="物资到位情况-个人防护" prop="protection"> + <el-select :disabled="disabled" v-model="ruleForm.protection" class="w100" placeholder="请选择"> + <el-option label="全部人员防护到位" value="1"></el-option> + <el-option label="人员未防护到位" value="2"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="协调组织情况-整体组织" prop="whole"> + <el-select :disabled="disabled" v-model="ruleForm.whole" class="w100" placeholder="请选择"> + <el-option label="协调基本顺利,能够满足要求" value="1"></el-option> + <el-option label="协调不顺利" value="2"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="协调组织情况-疏散组分工" prop="division"> + <el-select :disabled="disabled" v-model="ruleForm.division" class="w100" placeholder="请选择"> + <el-option label="安全,快速" value="1"></el-option> + <el-option label="安全,不快速" value="2"></el-option> + <el-option label="不安全,快速" value="3"></el-option> + <el-option label="不安全,不快速" value="4"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="实战效果评价" prop="effect"> + <el-select :disabled="disabled" v-model="ruleForm.effect" class="w100" placeholder="请选择"> + <el-option label="基本达到目的,部分环节有待改进" value="1"></el-option> + <el-option label="未达到目的" value="2"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="支援部门和协作有效性-报告上级" prop="report"> + <el-select :disabled="disabled" v-model="ruleForm.report" class="w100" placeholder="请选择"> + <el-option label="报告及时" value="1"></el-option> + <el-option label="报告不及时" value="2"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="支援部门和协作有效性-安全部门" prop="safety"> + <el-select :disabled="disabled" v-model="ruleForm.safety" class="w100" placeholder="请选择"> + <el-option label="按要求协作" value="1"></el-option> + <el-option label="未按要求协作" value="2"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="支援部门和协作有效性-救援后勤部门" prop="rescue"> + <el-select :disabled="disabled" v-model="ruleForm.rescue" class="w100" placeholder="请选择"> + <el-option label="按要求协作" value="1"></el-option> + <el-option label="未按要求协作" value="2"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="支援部门和协作有效性-警戒撤离配合" prop="evacuate"> + <el-select :disabled="disabled" v-model="ruleForm.evacuate" class="w100" placeholder="请选择"> + <el-option label="按要求配合" value="1"></el-option> + <el-option label="未按要求配合" value="2"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="是否需要修改应急预案" prop="needModify"> + <el-select :disabled="disabled" v-model="ruleForm.needModify" class="w100" placeholder="请选择"> + <el-option label="是" :value="true"></el-option> + <el-option label="否" :value="false"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="存在问题和改进措施" prop="questionAndImprove"> + <el-input :disabled="disabled" v-model="ruleForm.questionAndImprove" class="textarea" type="textarea" placeholder="请填写备注信息"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="修改内容" prop="modifyContent"> + <el-input :disabled="disabled" v-model="ruleForm.modifyContent" class="textarea" type="textarea" placeholder="请填写修改内容"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="附件列表"> + <uploaderFile :fileList="fileList" :systemName="'EMERGENCY'" :disabled="disabled" + @successUploader="successUploader"></uploaderFile> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="resetForm(ruleFormRef)" size="default">关闭</el-button> + <el-button v-if="!disabled" size="default" type="primary" @click="submitForm(titles, ruleFormRef)">确定</el-button> + </span> + </template> + </el-dialog> + <RegionsDialog ref="Shows" @SearchUser="onUser"/> + <DailogSearchUser ref="userRef" @SearchUser="selectUser"/> +<!-- <RegionsDialog ref="openRef"/>--> + </div> +</template> + +<script lang="ts"> +import { + reactive, + ref, + defineComponent, + onMounted, +} from 'vue'; + +import { + UploadUserFile, + FormInstance, + ElMessage +} from 'element-plus' +import { + Search, + FullScreen +} from '@element-plus/icons-vue' +import UserSelections from "/@/components/userSelections/index.vue" +import RegionsDialog from "/@/views/contingencyManagement/emergencyDrill/releaseOfDrillPlan/component/regionsDialog.vue" +import DailogSearchUser from "/@/components/DailogSearchUser/index.vue" +import {emergencyDrillEvaluationApi} from "/@/api/contingencyManagement/emergencyDrillEvaluation"; +import {goalManagementApi} from "/@/api/goalManagement"; +import uploaderFile from '/@/components/uploaderFile/index.vue'; +export default defineComponent({ + name: 'approvalProgress', + components: { + UserSelections, + RegionsDialog, + DailogSearchUser, + uploaderFile + }, + setup(props, { emit }) { + const isShowDialog = ref(false) + + const ruleFormRef = ref<FormInstance>() + //定义表单 + const ruleForm = ref ({ + drillExecuteId: '', + suitable: '', + sufficient: '', + arrival: '', + supplies: '', + protection: '', + whole: '', + division: '', + effect: '', + report: '', + safety: '', + rescue: '', + evacuate: '', + needModify: '', + questionAndImprove: '', + modifyContent: '', + fileList: [ + ], + userList: [ + ] + }); + //定义表单 + const realRuleForm = ref ({ + drillExecuteId: '', + suitable: '', + sufficient: '', + arrival: '', + supplies: '', + protection: '', + whole: '', + division: '', + effect: '', + report: '', + safety: '', + rescue: '', + evacuate: '', + needModify: '', + questionAndImprove: '', + modifyContent: '', + fileList: [ + ], + userList: [ + ] + }); + const titles = ref(); + const disabled = ref(); + // 打开弹窗 + const openDialog = (title: string, id: number, type: boolean) => { + isShowDialog.value = true; + titles.value = title; + disabled.value = type; + if (title == '查看演练实施评价') { + emergencyDrillEvaluationApi() + .seeEmergencyDrillEvaluation(id) + .then((res) => { + if (res.data.code == 200) { + ruleForm.value = res.data.data; + ruleForm.value.planUserListString='' + ruleForm.value.chargeUserListString='' + ruleForm.value.executeUserListString='' + ruleForm.value.evaluationUserListString='' + //演练人员 + for(var a = 0;a<res.data.data.planUserList.length;a++){ + ruleForm.value.planUserListString += res.data.data.planUserList[a].userName+';' + } + //演练负责人员 + for(var a = 0;a<res.data.data.planChargeUserList.length;a++){ + ruleForm.value.chargeUserListString += res.data.data.planChargeUserList[a].userName+';' + } + //实际到场人员 + for(var a = 0;a<res.data.data.executeUserList.length;a++){ + ruleForm.value.executeUserListString += res.data.data.executeUserList[a].userName+';' + } + //演练负责人(评价) + for(var a = 0;a<res.data.data.evaluationUserList.length;a++){ + ruleForm.value.evaluationUserListString += res.data.data.evaluationUserList[a].userName+';' + } + } + fileList.value = (res.data.data.evaluationFileList?res.data.data.evaluationFileList:[]) + initFileListData() + }); + } + if(title=='演练实施评价'){ + emergencyDrillEvaluationApi() + .seeEmergencyDrillEvaluation(id) + .then((res) => { + if (res.data.code == 200) { + ruleForm.value = res.data.data; + ruleForm.value.planUserListString='' + ruleForm.value.chargeUserListString='' + ruleForm.value.executeUserListString='' + ruleForm.value.evaluationUserListString='' + if(res.data.data.planUserList){ + for(var a = 0;a<res.data.data.planUserList.length;a++){ + ruleForm.value.planUserListString += res.data.data.planUserList[a].userName+';' + } + } + + if(res.data.data.planChargeUserList){ + for(var a = 0;a<res.data.data.planChargeUserList.length;a++){ + ruleForm.value.chargeUserListString += res.data.data.planChargeUserList[a].userName+';' + } + } + + if(res.data.data.executeUserList){ + for(var a = 0;a<res.data.data.executeUserList.length;a++){ + ruleForm.value.executeUserListString += res.data.data.executeUserList[a].userName+';' + } + } + //演练负责人(评价) + if(res.data.data.evaluationUserList){ + for(var a = 0;a<res.data.data.evaluationUserList.length;a++){ + ruleForm.value.evaluationUserListString += res.data.data.evaluationUserList[a].userName+';' + } + } + } + fileList.value = (res.data.data.evaluationFileList?res.data.data.evaluationFileList:[]) + initFileListData() + }); + } + if(title=='演练实施查看评价'){ + emergencyDrillEvaluationApi() + .seeEmergencyDrillEvaluation(id) + .then((res) => { + if (res.data.code == 200) { + ruleForm.value = res.data.data; + ruleForm.value.planUserListString='' + ruleForm.value.chargeUserListString='' + ruleForm.value.executeUserListString='' + ruleForm.value.evaluationUserListString='' + + if(res.data.data.planUserList){ + for(var a = 0;a<res.data.data.planUserList.length;a++){ + ruleForm.value.planUserListString += res.data.data.planUserList[a].userName+';' + } + } + + if(res.data.data.planChargeUserList){ + for(var a = 0;a<res.data.data.planChargeUserList.length;a++){ + ruleForm.value.chargeUserListString += res.data.data.planChargeUserList[a].userName+';' + } + } + + if(res.data.data.executeUserList){ + for(var a = 0;a<res.data.data.executeUserList.length;a++){ + ruleForm.value.executeUserListString += res.data.data.executeUserList[a].userName+';' + } + } + //演练负责人(评价) + if(res.data.data.evaluationUserList){ + for(var a = 0;a<res.data.data.evaluationUserList.length;a++){ + ruleForm.value.evaluationUserListString += res.data.data.evaluationUserList[a].userName+';' + } + } + fileList.value = (res.data.data.evaluationFileList?res.data.data.evaluationFileList:[]) + initFileListData() + } + }); + } + + }; + const initFileListData = async () => { + for(var a = 0;a<ruleForm.value.planFileList.length;a++){ + ruleForm.value.planFileList[a].name = ruleForm.value.planFileList[a].fileName + } + // 事故分析会议纪要 + for(var a = 0;a<fileList.value.length;a++){ + fileList.value[a].name = fileList.value[a].fileName + } + } + // 上传成功组装数据 + const successUploader = (list) =>{ + fileList.value = list + const formFileList = [] + for(var a = 0;a<fileList.value.length;a++){ + formFileList.push( + { + fileName:fileList.value[a].fileName, + fileUrl:'' + } + ) + } + ruleForm.value.fileList = formFileList + } + const resetForm = (formEl: FormInstance | undefined) => { + isShowDialog.value = false; + if (!formEl) return; + formEl.resetFields(); + fileList.value = [] + }; + // 关闭弹窗 + const closeDialog = () => { + isShowDialog.value = false; + }; + // 取消 + const onCancel = () => { + closeDialog(); + }; + //日期选择器 + const value1 = ref('') + // 上传附件 + const fileList = ref([]) + // 可选择树 + const treeSelect = ref() + const tree = [ + , + ] + //定义树形下拉框 + const responsibleDepartment = ref() + const data = [ + + ] + // 必填项提示 + // const rules = reactive<FormRules>({ + // teamName: [ + // { + // required: true, + // message: '队伍名称不能为空', + // trigger: 'change', + // }, + // ], + // teamLevel: [ + // { + // required: true, + // message: '队伍级别不能为空', + // trigger: 'change', + // }, + // ], + // teamLeader: [ + // { + // required: true, + // message: '队伍负责人不能为空', + // trigger: 'change', + // }, + // ], + // responsibleDepartment: [ + // { + // required: true, + // message: '负责人部门不能为空', + // trigger: 'change', + // }, + // ], + // teamPhone: [ + // { + // required: true, + // message: '负责人手机不能为空', + // trigger: 'change', + // }, + // ], + // telephone: [ + // { + // required: true, + // message: '固定电话不能为空', + // trigger: 'change', + // }, + // ], + // }) + + const submitForm = async (title: string, formEl: FormInstance | undefined) => { + if(!ruleForm.value.fileList){ + ruleForm.value.fileList = [] + } + //演练负责人(评价) + ruleForm.value.userList = ruleForm.value.evaluationUserList + + + + realRuleForm.value.drillExecuteId=ruleForm.value.drillExecuteId + realRuleForm.value.suitable=ruleForm.value.suitable + realRuleForm.value.sufficient=ruleForm.value.sufficient + realRuleForm.value.arrival=ruleForm.value.arrival + realRuleForm.value.supplies=ruleForm.value.supplies + realRuleForm.value.protection=ruleForm.value.protection + realRuleForm.value.whole=ruleForm.value.whole + realRuleForm.value.division=ruleForm.value.division + realRuleForm.value.effect=ruleForm.value.effect + realRuleForm.value.report=ruleForm.value.report + realRuleForm.value.safety=ruleForm.value.safety + realRuleForm.value.rescue=ruleForm.value.rescue + realRuleForm.value.evacuate=ruleForm.value.evacuate + realRuleForm.value.needModify=ruleForm.value.needModify + realRuleForm.value.questionAndImprove=ruleForm.value.questionAndImprove + realRuleForm.value.modifyContent=ruleForm.value.modifyContent + realRuleForm.value.fileList=ruleForm.value.fileList + if(ruleForm.value.userList){ + for(var a = 0;a<ruleForm.value.userList.length;a++){ + realRuleForm.value.userList.push({ + userUid:ruleForm.value.userList[a].userUid, + userName:ruleForm.value.userList[a].userName + }) + } + } + // console.log(ruleForm.value.evaluationUserList) + // ruleForm.value.userList=[] + // for(var a = 0;a<ruleForm.value.evaluationUserList.length;a++){ + // // += res.data.data.evaluationUserList[a].userName+';' + // } + if (title == '演练实施评价') { + if (!formEl) return; + await formEl.validate((valid, fields) => { + if (valid) { + // console.log(ruleForm.value) + emergencyDrillEvaluationApi() + .editEmergencyDrillEvaluation(realRuleForm.value) + // emergencyDrillExecuteApi() + // .editEmergencyDrillExecute(ruleForm.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: '评价成功', + type: 'success', + }); + emit('myAdd', true); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + emit('myAdd', true); + } + formEl.resetFields(); + }); + } else { + console.log('error submit!', fields); + } + }); + isShowDialog.value = false; + formEl.resetFields(); + ruleForm.value = { + drillRecordDate: '', // 演练记录时间 + drillPlanId: '', //演练计划ID + drillName:'', + recordUserUid: '', // 记录人ID + processDesc: '', // 演练过程描述 + userList: [ + { + userUid: '', + }, + { + userUid: '', + } + ] + }; + } + } + // 应急队伍弹窗 + const Shows=ref() + const daiInpt=()=>{ + Shows.value.openDailog() + } + const onUser = (e:any) => { + ruleForm.value.drillPlanId=e.id + }; + // 选择区域弹窗 + const openRef=ref() + const regionsDialog=()=>{ + openRef.value.openDailog() + } + // 打开用户选择弹窗 + const userRef = ref(); + const openUser = () => { + userRef.value.openDailog(0); + }; + + const selectUser = (e) =>{ + ruleForm.value.evaluationUserListString='' + ruleForm.value.evaluationUserList=[] + for(var a = 0;a<e.length;a++){ + ruleForm.value.evaluationUserList.push( + { + userName: e[a].realName, + userUid: e[a].uid, + } + ) + ruleForm.value.evaluationUserListString+=e[a].realName+';' + } + console.log(ruleForm.value.evaluationUserList) + } + //el-tree-select回显 + const propse = { + label: 'depName', + children: 'children', + }; + const newTreeList = []; + //得到部门树 + const department = async () => { + await goalManagementApi() + .getTreedepartment() + .then((res) => { + if (res.data.code == 200) { + data.value = res.data.data; + getTreeList(res.data.data, newTreeList); + } else { + ElMessage.error(res.data.msg); + } + }); + }; + // 递归树状数据且修改字段名 + const getTreeList = (treeList, newTreeList) => { + treeList.map((c) => { + let tempData = { + depName: c.depName, + value: c.depId, + children: [], + }; + if (c.children && c.children.length > 0) { + tempData.children = []; + getTreeList(c.children, tempData.children); + } + newTreeList.push(tempData); + }); + }; + onMounted(() => { + department(); + }); + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + return { + openDialog, + closeDialog, + isShowDialog, + onCancel, + fileList, + responsibleDepartment, + data, + Search, + ruleForm, + value1, + treeSelect, + tree, + daiInpt, + Shows, + onUser, + ruleFormRef, + // rules, + openUser, + userRef, + regionsDialog, + openRef, + toggleFullscreen, + FullScreen, + full, + resetForm, + titles, + disabled, + emit, + propse, + department, + newTreeList, + selectUser, + submitForm, + realRuleForm, + successUploader, + initFileListData + }; + }, +}); +</script> +<style scoped lang="scss"> +.el-form .el-form-item{ + margin-bottom: 18px !important; + display: flex; + align-items: flex-start; +} +::v-deep .el-form-item--default .el-form-item__label{ + text-align: right; + height: 100%; +} +.textarea{ + height: 90px!important; +} +.textarea ::v-deep .el-textarea__inner{ + height: 90px!important; +} +::v-deep .el-table__cell { + font-weight: 400; +} +.el-divider--horizontal{ + height: 0; + margin: 0; + border-top: transparent; +} +.el-select{ + width: 100%; +} +.el-divider--horizontal { + display: block; + height: 1px; + width: 100%; + margin: 24px 0; + background-color: #dcdfe6; + position: relative; +} +.el-divider__text { + position: absolute; + background-color: #fff; + padding: 0 20px; + color: #303133; + left: 50%; + font-weight: 500; + font-size: 14px; +} +</style> \ No newline at end of file diff --git a/src/views/contingencyManagement/emergencyDrill/drillImplementationEvaluation/component/flowChart.vue b/src/views/contingencyManagement/emergencyDrill/drillImplementationEvaluation/component/flowChart.vue new file mode 100644 index 0000000..6469b53 --- /dev/null +++ b/src/views/contingencyManagement/emergencyDrill/drillImplementationEvaluation/component/flowChart.vue @@ -0,0 +1,307 @@ +<template> + <div class="system-edit-user-container"> + <el-dialog title="应急演练计划--修改审批进度" v-model="isShowDialog" width="769px" draggable :fullscreen="full"> + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <!-- <img class="process-status-img" src=""> --> + <el-tabs type="border-card"> + <el-tab-pane label="流转记录"> + <el-card class="box-card" shadow="hover"> + <template #header> + <div class="card-header"> + <span>流转记录</span> + </div> + </template> + <div> + <el-steps :active="2"> + <el-step title="开始" description="胡海涛,2022-07-09 20:41:50" /> + <el-step title="一级审批" description="管理员,2022-07-09 20:41:50" /> + </el-steps> + </div> + <el-table :data="tableData" stripe style="width: 100%"> + <el-table-column prop="date" label="执行环节" width="120" /> + <el-table-column prop="name" label="执行人" width="120" /> + <el-table-column prop="address" label="开始时间" width="100" /> + <el-table-column prop="address" label="结束时间" width="100" /> + <el-table-column prop="address" label="办理状态" width="100" /> + <el-table-column prop="address" label="审批意见" width="100" /> + <el-table-column prop="address" label="任务历时" width="100" /> + </el-table> + </el-card> + </el-tab-pane> + <el-tab-pane label="流程信息"> + <el-card class="box-card" shadow="hover"> + <template #header> + <div class="card-header"> + <span>流程信息</span> + </div> + </template> + <div> + <el-timeline> + <el-timeline-item timestamp="2018/4/12" placement="top" color="rgb(63, 158, 255)"> + <el-card> + <h4 style="margin: 10px 0; padding-bottom: 10px">一级审批</h4> + <el-row> + <el-col class="tip" :span="22" :offset="1"> + <div class="item"> + <span class="label">审批人:</span> + <span class="value">管理员</span> + </div> + <div class="item"> + <span class="label">办理状态:</span> + <span class="value"> + <!-- <el-tag--> + <!-- v-for="item in items"--> + <!-- :key="item.label"--> + <!-- :type="item.type"--> + <!-- class="mx-1"--> + <!-- effect="dark"--> + <!-- >--> + <!-- {{ item.label }}--> + <!-- </el-tag>--> + <p class="text">等待审核</p> + </span> + </div> + <div class="item"> + <span class="label">审批意见:</span> + <span class="value">等待审核</span> + </div> + <div class="item"> + <span class="label">开始时间:</span> + <span class="value">2022-07-09 20:41:50</span> + </div> + <div class="item"> + <span class="label">结束时间:</span> + <span class="value">2022-07-09 20:41:50</span> + </div> + <div class="item"> + <span class="label">用时:</span> + <span class="value">0秒</span> + </div> + </el-col> + </el-row> + </el-card> + </el-timeline-item> + <el-timeline-item timestamp="2018/4/3" placement="top" color="rgb(63, 158, 255)"> + <el-card> + <h4>开始</h4> + <el-row> + <el-col class="tip" :span="22" :offset="1"> + <div class="item"> + <span class="label">审批人:</span> + <span class="value">胡海涛</span> + </div> + <div class="item"> + <span class="label">办理状态:</span> + <span class="value"> + <p class="text">开始</p> + </span> + </div> + <div class="item"> + <span class="label">审批意见:</span> + <span class="value">等待审核</span> + </div> + <div class="item"> + <span class="label">开始时间:</span> + <span class="value">2022-07-09 20:41:50</span> + </div> + <div class="item"> + <span class="label">结束时间:</span> + <span class="value">2022-07-09 20:41:50</span> + </div> + <div class="item"> + <span class="label">用时:</span> + <span class="value">0秒</span> + </div> + </el-col> + </el-row> + </el-card> + </el-timeline-item> + </el-timeline> + </div> + </el-card> + </el-tab-pane> + <el-tab-pane label="流程图"> + <el-card class="box-card" shadow="hover"> + <template #header> + <div class="card-header"> + <span>流程图</span> + </div> + </template> + <div></div> + </el-card> + </el-tab-pane> + </el-tabs> + </el-dialog> + <RegionsDialog ref="Shows" /> + <UserCheckbox ref="userRef" /> + </div> +</template> + +<script lang="ts"> +import { ref, defineComponent } from 'vue'; + +import type { TagProps } from 'element-plus'; + +import { Search, FullScreen } from '@element-plus/icons-vue'; +import UserCheckbox from '/@/components/userCheckbox/index.vue'; +import RegionsDialog from '/@/views/contingencyManagement/emergencyDrill/releaseOfDrillPlan/component/regionsDialog.vue'; + +export default defineComponent({ + name: 'openAdd', + components: { + RegionsDialog, + UserCheckbox, + }, + setup() { + const isShowDialog = ref(false); + // 打开弹窗 + const openDialog = () => { + // state.ruleForm = row; + isShowDialog.value = true; + }; + // 关闭弹窗 + const closeDialog = () => { + isShowDialog.value = false; + }; + const tableData = [ + { + date: '2016-05-03', + name: 'Tom', + address: '2022-07-09 20:41:50', + }, + { + date: '2016-05-02', + name: 'Tom', + address: '2022-07-09 20:41:50', + }, + { + date: '2016-05-04', + name: 'Tom', + address: '2022-07-09 20:41:50', + }, + { + date: '2016-05-01', + name: 'Tom', + address: '2022-07-09 20:41:50', + }, + ]; + + type Item = { type: TagProps['type']; label: string }; + + const items = ref<Array<Item>>([{ type: '', label: '等待审核' }]); + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + return { + openDialog, + closeDialog, + isShowDialog, + Search, + tableData, + items, + toggleFullscreen, + FullScreen, + full, + }; + }, +}); +</script> +<style scoped lang="scss"> +.process-status-img { + width: 128px; + height: auto; + position: absolute; + right: 10px; + top: 60px; + z-index: 999; +} +//弹窗底部边框线 +::v-deep .el-dialog__footer { + border-top: 1px solid #e8e8e8; + border-radius: 0 0 4px 4px; +} +//弹窗顶部边框线 +::v-deep .el-dialog__header { + border-bottom: 1px solid #e8e8e8; + margin-right: 0; + border-radius: 4px 4px 0 0; +} +//tabs字体颜色 +::v-deep .el-tabs--border-card > .el-tabs__header .el-tabs__item.is-active { + color: #a9d86e !important; +} +.card-header { + display: flex; + justify-content: space-between; + align-items: center; +} +//.box-card { +// width: 480px; +//} +//步骤条字体大小 +::v-deep .el-step__icon-inner { + font-size: 14px !important; +} +//步骤条颜色 +::v-deep .el-step__line { + background-color: #409eff; +} +//表头 +::v-deep .el-table th.el-table__cell { + background-color: #f6f7fa; + font-weight: 400; + color: #909399; +} +.el-table .sort-caret.ascending { + border-bottom-color: #c0c4cc; +} + +.tip { + padding: 8px 16px; + background-color: #ecf8ff; + border-radius: 4px; + border-left: 5px solid #50bfff; + margin: 20px 0; +} +.item { + height: 32px; + line-height: 32px; + margin-bottom: 8px; +} +.item .label { + display: inline-block; + height: 100%; + width: 70px; + font-size: 14px; + color: #5e6d82; + text-align: end; + vertical-align: top; +} +.item .value { + padding-left: 10px; + font-size: 14px; + max-width: calc(100% - 90px); + color: #5e6d82; + display: inline-block; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} +.text { + background-color: #409eff; + color: #fff; + border-width: 1px; + border-style: solid; + border-radius: 4px; + height: 24px; + padding: 0 8px; + line-height: 22px; + display: inline-block; +} +</style> \ No newline at end of file diff --git a/src/views/contingencyManagement/emergencyDrill/drillImplementationEvaluation/component/rectificationDialog.vue b/src/views/contingencyManagement/emergencyDrill/drillImplementationEvaluation/component/rectificationDialog.vue new file mode 100644 index 0000000..bc66e00 --- /dev/null +++ b/src/views/contingencyManagement/emergencyDrill/drillImplementationEvaluation/component/rectificationDialog.vue @@ -0,0 +1,775 @@ +<template> + <div class="system-edit-user-container"> + <el-dialog + :title="titles" + v-model="isShowDialog" + width="769px" + draggable + :fullscreen="full" + > + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-form + ref="ruleFormRef" + :model="ruleForm" + size="default" + label-width="120px" + :disabled="disabled" + > + <el-row :gutter="35"> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="整改标题" prop="emergencyPlanName"> + <el-input v-model="ruleForm.emergencyPlanName" placeholder="请填写队伍名称"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="整改单编号" prop="teamName"> + <el-input v-model="ruleForm.teamName" placeholder="请填写队伍名称"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="整改来源" prop="teamLeader"> + <el-select v-model="ruleForm.teamLevel" class="w100" placeholder="请选择"> + <el-option label="演练评价等" value="admin"></el-option> + <el-option label="现场处置方案" value="common"></el-option> + <el-option label="专项应急预案" value="common"></el-option> + <el-option label="其他预案" value="common"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="整改对象名称" prop="teamLeader"> + <el-input v-model="ruleForm.teamName" placeholder="请填写整改对象名称"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="不合格因素" prop="teamLevel"> + <el-input v-model="ruleForm.name" class="textarea" type="textarea"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="整改要求" prop="teamLevel"> + <el-input v-model="ruleForm.name" class="textarea" type="textarea"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="隐患等级" prop="teamLeader"> + <el-select v-model="ruleForm.teamLevel" class="w100" placeholder="请选择"> + <el-option label="一般">一般</el-option> + <el-option label="重大">重大</el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="隐患后果" prop="teamLeader"> + <el-select v-model="ruleForm.teamLevel" class="w100" placeholder="请选择"> + <el-option label="死亡">死亡</el-option> + <el-option label="重伤">重伤</el-option> + <el-option label="轻伤">轻伤</el-option> + <el-option label="火灾">火灾</el-option> + <el-option label="交通事故">交通事故</el-option> + <el-option label="财产损失">财产损失</el-option> + <el-option label="其它">其它</el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="隐患类型" prop="teamLeader"> + <el-select v-model="ruleForm.teamLevel" class="w100" placeholder="请选择"> + <el-option label="化学品管理" value="admin"></el-option> + <el-option label="管理制度缺陷" value="common"></el-option> + <el-option label="设计缺陷" value="admin"></el-option> + <el-option label="其它" value="common"></el-option> + <el-option label="现场管理" value="admin"></el-option> + <el-option label="消防安全" value="common"></el-option> + <el-option label="消防安全" value="common"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="区域名称" prop="telephone"> + <el-input + v-model="ruleForm.teamLeader" + placeholder="请选择" + class="input-with-select" + > + <template #append> + <el-button :icon="Search" @click="regionsDialog"/> + </template> + </el-input> + </el-form-item> + </el-col> +<!-- <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">--> +<!-- <el-form-item label="隐患照片" prop="telephone">--> +<!-- <el-upload--> +<!-- class="avatar-uploader"--> +<!-- action="https://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15"--> +<!-- :show-file-list="false"--> +<!-- :on-success="handleAvatarSuccess"--> +<!-- :before-upload="beforeAvatarUpload"--> +<!-- >--> +<!-- <img v-if="imageUrl" :src="imageUrl" class="avatar" />--> +<!-- <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>--> +<!-- </el-upload>--> +<!-- </el-form-item>--> +<!-- </el-col>--> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="发现人" prop="telephone" > + <el-input + v-model="ruleForm.teamLeader" + placeholder="请选择" + class="input-with-select" + > + <template #append> + <el-button :icon="Search" @click="openUser"/> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="发现日期" prop="telephone"> + <el-date-picker + v-model="value1" + class="w100" + type="datetime" + placeholder="选择日期时间" + /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="填报人" prop="telephone" > + <el-input + v-model="ruleForm.teamLeader" + placeholder="请选择" + class="input-with-select" + > + <template #append> + <el-button :icon="Search" @click="openUser"/> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="填报日期" prop="telephone"> + <el-date-picker + v-model="value1" + class="w100" + type="datetime" + placeholder="选择日期时间" + /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="填报人部门" placeholder="请选择"> + <el-tree-select + v-model="ruleForm.responsibleDepartment" + :data="data" class="w100" + placeholder="请选择"/> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="现场整改" prop="teamPhone"> + <el-select v-model="ruleForm.teamLevel" class="w100" placeholder="请选择"> + <el-option label="是" value="admin"></el-option> + <el-option label="否" value="common"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="责任部门" placeholder="请选择"> + <el-tree-select + v-model="ruleForm.responsibleDepartment" + :data="data" class="w100" + placeholder="请选择"/> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick"> + <el-tab-pane label="组织整改" name="first"> + <el-row style="margin: 0"> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20" style="padding-left: 17.5px;padding-right: 17.5px;"> + <el-form-item label="整改意见" prop="teamLevel"> + <el-input v-model="ruleForm.name" class="textarea" type="textarea" placeholder="请填写整改意见"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20" style="padding-left: 17.5px;padding-right: 17.5px;"> + <el-form-item label="整改期限" prop="telephone"> + <el-date-picker + v-model="value1" + class="w100" + type="datetime" + placeholder="选择日期时间" + /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20" style="padding-left: 17.5px;padding-right: 17.5px;"> + <el-form-item label="填报人" prop="telephone" > + <el-input + v-model="ruleForm.teamLeader" + placeholder="请选择" + class="input-with-select" + > + <template #append> + <el-button :icon="Search" @click="openUser"/> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20" style="padding-left: 17.5px;padding-right: 17.5px;"> + <el-form-item label="填报日期" prop="telephone"> + <el-date-picker + v-model="value1" + class="w100" + type="datetime" + placeholder="选择日期时间" + /> + </el-form-item> + </el-col> + </el-row> + </el-tab-pane> + </el-tabs> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="resetForm(ruleFormRef)" size="default">关闭</el-button> + <el-button size="default" v-if="disabled == true ? false : true" type="primary" @click="submitForm(titles, ruleFormRef)">确定</el-button> + </span> + </template> + </el-dialog> + <CheckTemplate ref="Shows"/> + <userSelections ref="userRef"/> + <RegionsDialog ref="openRef"/> + </div> +</template> + +<script lang="ts"> +import { + reactive, + ref, + defineComponent +} from 'vue'; +import { + ElMessage +} +from 'element-plus' +import type { + TabsPaneContext, + FormInstance, + UploadProps, +} from 'element-plus' +import { + Search, + Plus, + FullScreen +} from '@element-plus/icons-vue' +import UserSelections from "/@/components/userSelections/index.vue" +import CheckTemplate from '/@/components/checkTemplate/index.vue' +import RegionsDialog from '/@/components/regionsDialog/index.vue' +import {releaseDrillPlanApi} from "/@/api/contingencyManagement/emergencyDrillPlan"; +import {emergencyDrillEvaluationApi} from "/@/api/contingencyManagement/emergencyDrillEvaluation"; + +export default defineComponent({ + name: 'rectificationDialog', + components: { + CheckTemplate, + UserSelections, + RegionsDialog, + }, + setup(props, { emit }) { + const isShowDialog = ref(false) + + const ruleFormRef = ref<FormInstance>() + //定义表单 + const ruleForm = reactive({ + id: '', + drillPlanId: '', + suitable: '', + sufficient: '', + arrival: '', + supplies: '', + protection: '', + whole: '', + division: '', + effect: '', + report: '', + safety: '', + rescue: '', + evacuate: '', + needModify: '', + questionAndImprove: '', + modifyContent: '', + fileList: [ + { + fileName: 'name', + fileUrl: 'url', + } + ], + userList: [ + { + userUid: '' + }, + { + userUid: '' + } + ] + }); + const titles = ref(); + const disabled = ref(); + // 打开弹窗 + const openDialog = (title: string, id: number, type: boolean) => { + isShowDialog.value = true; + titles.value = title; + disabled.value = type; + // if (title == '查看演练实施评价' || title == '修改演练实施评价') { + // releaseDrillPlanApi() + // .seeReleaseDrillPlan(id) + // .then((res) => { + // if (res.data.code == 200) { + // ruleForm.value = res.data.data; + // } + // }); + // } + }; + // 关闭弹窗 + const closeDialog = () => { + isShowDialog.value = false; + }; + // 取消 + const onCancel = () => { + closeDialog(); + }; + //日期选择器 + const value1 = ref('') + // 可选择树 + const treeSelect = ref() + const tree = [ + { + value: '1', + label: 'Level one 1', + children: [ + { + value: '11', + label: 'Level two 1-1', + children: [ + { + value: '111', + label: 'Level three 1-1-1', + }, + ], + }, + ], + }, + { + value: '2', + label: 'Level one 2', + children: [ + { + value: '21', + label: 'Level two 2-1', + children: [ + { + value: '211', + label: 'Level three 2-1-1', + }, + ], + }, + { + value: '22', + label: 'Level two 2-2', + children: [ + { + value: '221', + label: 'Level three 2-2-1', + }, + ], + }, + ], + }, + { + value: '3', + label: 'Level one 3', + children: [ + { + value: '31', + label: 'Level two 3-1', + children: [ + { + value: '311', + label: 'Level three 3-1-1', + }, + ], + }, + { + value: '32', + label: 'Level two 3-2', + children: [ + { + value: '321', + label: 'Level three 3-2-1', + }, + ], + }, + ], + }, + ] + //定义树形下拉框 + const responsibleDepartment = ref() + const data = [ + { + value: '1', + label: '广汇能源综合物流发展有限责任公司', + children: [ + { + value: '11', + label: '经营班子', + children: [], + }, + ], + }, + { + value: '2', + label: '生产运行部', + children: [ + { + value: '21', + label: '灌装一班', + children: [] + }, + { + value: '22', + label: '工艺四班', + children: [], + }, + ], + }, + { + value: '3', + label: '设备部', + children: [ + { + value: '31', + label: '仪表班', + children: [], + }, + { + value: '32', + label: '机修班', + children: [], + }, + ], + }, + ] + // 必填项提示 + // const rules = reactive<FormRules>({ + // teamName: [ + // { + // required: true, + // message: '队伍名称不能为空', + // trigger: 'change', + // }, + // ], + // teamLevel: [ + // { + // required: true, + // message: '队伍级别不能为空', + // trigger: 'change', + // }, + // ], + // teamLeader: [ + // { + // required: true, + // message: '队伍负责人不能为空', + // trigger: 'change', + // }, + // ], + // responsibleDepartment: [ + // { + // required: true, + // message: '负责人部门不能为空', + // trigger: 'change', + // }, + // ], + // teamPhone: [ + // { + // required: true, + // message: '负责人手机不能为空', + // trigger: 'change', + // }, + // ], + // telephone: [ + // { + // required: true, + // message: '固定电话不能为空', + // trigger: 'change', + // }, + // ], + // }) + // 应急队伍弹窗 + // 表单提交验证必填项 + const submitForm = async (title: string, formEl: FormInstance | undefined) => { + if (title == '查看演练实施评价') { + if (!formEl) return; + await formEl.validate((valid, fields) => { + if (valid) { + isShowDialog.value = false; + emergencyDrillEvaluationApi() + .addEmergencyDrillEvaluation(ruleForm.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'success', + }); + emit('myAdd', true); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + emit('myAdd', true); + } + formEl.resetFields(); + }); + } else { + console.log('error submit!', fields); + } + }); + } + else if (title == '修改演练实施评价') { + if (!formEl) return; + await formEl.validate((valid, fields) => { + if (valid) { + isShowDialog.value = false; + emergencyDrillEvaluationApi() + .editEmergencyDrillEvaluation(ruleForm.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: '修改成功', + type: 'success', + }); + emit('myAdd', true); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + emit('myAdd', true); + } + formEl.resetFields(); + }); + } else { + console.log('error submit!', fields); + } + }); + formEl.resetFields(); + ruleForm.value = { + id: '', + drillPlanId: '', + suitable: '', + sufficient: '', + arrival: '', + supplies: '', + protection: '', + whole: '', + division: '', + effect: '', + report: '', + safety: '', + rescue: '', + evacuate: '', + needModify: '', + questionAndImprove: '', + modifyContent: '', + fileList: [ + { + fileName: 'name', + fileUrl: 'url', + } + ], + userList: [ + { + userUid: '' + }, + { + userUid: '' + } + ] + }; + } + } + const resetForm = (formEl: FormInstance | undefined) => { + isShowDialog.value = false; + if (!formEl) return; + formEl.resetFields(); + }; + const Shows=ref() + const daiInpt=()=>{ + Shows.value.openDailog() + } + // 选择区域弹窗 + const openRef=ref() + const regionsDialog=()=>{ + openRef.value.openDailog() + } + // 打开用户选择弹窗 + const userRef = ref(); + const openUser = () => { + userRef.value.openDialog(); + }; + const activeName = ref('first') + + const handleClick = (tab: TabsPaneContext, event: Event) => { + console.log(tab, event) + } + // 上传图片 + const imageUrl = ref('') + + const handleAvatarSuccess: UploadProps['onSuccess'] = ( + response, + uploadFile + ) => { + imageUrl.value = URL.createObjectURL(uploadFile.raw!) + } + + const beforeAvatarUpload: UploadProps['beforeUpload'] = (rawFile) => { + if (rawFile.type !== 'image/jpeg') { + ElMessage.error('Avatar picture must be JPG format!') + return false + } else if (rawFile.size / 1024 / 1024 > 2) { + ElMessage.error('Avatar picture size can not exceed 2MB!') + return false + } + return true + } + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + return { + openDialog, + closeDialog, + isShowDialog, + onCancel, + responsibleDepartment, + data, + Search, + ruleForm, + value1, + treeSelect, + tree, + daiInpt, + Shows, + ruleFormRef, + // rules, + openUser, + userRef, + regionsDialog, + openRef, + activeName, + handleClick, + handleAvatarSuccess, + beforeAvatarUpload, + Plus, + toggleFullscreen, + FullScreen, + full, + submitForm, + emit, + titles, + disabled, + resetForm, + }; + }, +}); +</script> +<style scoped lang="scss"> +.el-form .el-form-item{ + margin-bottom: 18px !important; +} +::v-deep .el-form-item--default .el-form-item__label{ + text-align: right; + height: 100%; +} +.textarea{ + height: 50px!important; +} +.textarea ::v-deep .el-textarea__inner{ + height: 50px!important; +} +::v-deep .el-table__cell { + font-weight: 400; +} +.el-divider--horizontal{ + height: 0; + margin: 0; + border-top: transparent; +} +.el-select{ + width: 100%; +} +.el-divider--horizontal { + display: block; + height: 1px; + width: 100%; + margin: 24px 0; + background-color: #dcdfe6; + position: relative; +} +.el-divider__text { + position: absolute; + background-color: #fff; + padding: 0 20px; + color: #303133; + left: 50%; + font-weight: 500; + font-size: 14px; +} +////上传图片 +//.avatar-uploader .avatar { +// width: 178px; +// height: 178px; +// display: block; +//} + +</style> + +<!--<style scoped>--> +<!--.avatar-uploader .avatar {--> +<!-- width: 178px;--> +<!-- height: 178px;--> +<!-- display: block;--> +<!--}--> +<!--</style>--> +<!--<style>--> +<!--.avatar-uploader .el-upload {--> +<!-- border: 1px dashed var(--el-border-color);--> +<!-- border-radius: 6px;--> +<!-- cursor: pointer;--> +<!-- position: relative;--> +<!-- overflow: hidden;--> +<!-- transition: var(--el-transition-duration-fast);--> +<!--}--> + +<!--.avatar-uploader .el-upload:hover {--> +<!-- border-color: var(--el-color-primary);--> +<!--}--> + +<!--.el-icon.avatar-uploader-icon {--> +<!-- font-size: 28px;--> +<!-- color: #8c939d;--> +<!-- width: 178px;--> +<!-- height: 178px;--> +<!-- text-align: center;--> +<!--}--> +<!--</style>--> \ No newline at end of file diff --git a/src/views/contingencyManagement/emergencyDrill/drillImplementationEvaluation/index.vue b/src/views/contingencyManagement/emergencyDrill/drillImplementationEvaluation/index.vue new file mode 100644 index 0000000..bba7134 --- /dev/null +++ b/src/views/contingencyManagement/emergencyDrill/drillImplementationEvaluation/index.vue @@ -0,0 +1,502 @@ +<template> + <div class="system-user-container"> + <el-card shadow="hover"> + <el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick"> + <el-tab-pane label="待评价" name="first"> + <div class="button_Line mb15"> + <div class="button_Left"> + <!--<el-button size="default" type="danger" plain :disabled="danger" @click="onDeleteAll">--> + <!--<el-icon>--> + <!--<Delete />--> + <!--</el-icon>删除--> + <!--</el-button>--> + </div> +<!-- <div class="button_Right">--> +<!-- <el-button @click="upButton">--> +<!-- <el-icon>--> +<!-- <Upload />--> +<!-- </el-icon>--> +<!-- </el-button>--> +<!-- <el-button>--> +<!-- <el-icon>--> +<!-- <Download />--> +<!-- </el-icon>--> +<!-- </el-button>--> +<!-- <el-button>--> +<!-- <el-icon>--> +<!-- <Refresh />--> +<!-- </el-icon>--> +<!-- </el-button>--> +<!-- </div>--> + </div> + <el-table + :data="tableData" + style="width: 100%" + ref="multipleTableRef" + @selection-change="handleSelectionChange" + > + <el-table-column + type="selection" + width="55" + /> + <el-table-column prop="drillName" label="演练名称" show-overflow-tooltip sortable></el-table-column> + <el-table-column prop="drillAddress" label="演练地点" show-overflow-tooltip sortable></el-table-column> + <el-table-column prop="drillWay" label="演练方式" show-overflow-tooltip sortable> + <template #default="scope"> + <div v-if="scope.row.drillWay=='0'">综合</div> + <div v-if="scope.row.drillWay=='1'">桌面</div> + <div v-if="scope.row.drillWay=='2'">专项</div> + </template> + </el-table-column> + <el-table-column prop="drillLevel" label="演练级别" show-overflow-tooltip sortable> + <template #default="scope"> + <div v-if="scope.row.drillLevel=='1'">公司级</div> + <div v-if="scope.row.drillLevel=='2'">分厂级</div> + <div v-if="scope.row.drillLevel=='3'">车间级</div> + </template> + </el-table-column> + <el-table-column prop="drillPlanDate" label="计划演练日期" show-overflow-tooltip sortable></el-table-column> + <el-table-column prop="drillRecordDate" label="演练记录日期" show-overflow-tooltip sortable></el-table-column> +<!-- <el-table-column prop="attachments" label="应急预案" show-overflow-tooltip sortable></el-table-column>--> + <el-table-column label="操作" width="260" align="center" fixed="right"> + <template #default="scope"> + <!--<el-button size="small" text disabled>--> + <!--<el-icon style="margin-right: 5px;">--> + <!--<EditPen />--> + <!--</el-icon>评价--> + <!--</el-button>--> +<!-- <el-button size="small" text type="primary" @click="onFlowChart(scope.row.id)">--> +<!-- 审批进度--> +<!-- </el-button>--> + <!--<el-button size="small" text type="primary" @click="onApprovalProgress('详情',scope.row.id)">--> + <!--<el-icon style="margin-right: 5px;">--> + <!--<EditPen />--> + <!--</el-icon>查看评价--> + <!--</el-button>--> + + <el-button size="small" text type="primary" @click="onApprovalProgress('评价',scope.row.id)"> + <el-icon style="margin-right: 5px;"> + <EditPen /> + </el-icon>评价 + </el-button> + + <!--<el-button size="small" text type="primary" @click="onEdit('修改',scope.row.id)">--> + <!--<el-icon style="margin-right: 5px;">--> + <!--<EditPen />--> + <!--</el-icon>整改--> + <!--</el-button>--> + <!--<el-button size="small" text disabled @click="onOpenEdit(scope.row)">--> + <!--查看整改--> + <!--</el-button>--> + </template> + </el-table-column> + </el-table> + <div class="pages"> + <el-pagination + v-if="tableData.length == 0 ? false : true" + v-model:currentPage="pageIndex" + v-model:page-size="pageSize" + :page-sizes="[10, 20, 30]" + :pager-count="5" + layout="total, sizes, prev, pager, next, jumper" + :total="total" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + </el-tab-pane> + <el-tab-pane label="已评价" name="second"> + <div class="button_Line mb15"> + <div class="button_Left"> + <el-button size="default" type="danger" plain :disabled="danger" @click="onDeleteAll"> + <el-icon> + <Delete /> + </el-icon>删除 + </el-button> + </div> + <!-- <div class="button_Right">--> + <!-- <el-button @click="upButton">--> + <!-- <el-icon>--> + <!-- <Upload />--> + <!-- </el-icon>--> + <!-- </el-button>--> + <!-- <el-button>--> + <!-- <el-icon>--> + <!-- <Download />--> + <!-- </el-icon>--> + <!-- </el-button>--> + <!-- <el-button>--> + <!-- <el-icon>--> + <!-- <Refresh />--> + <!-- </el-icon>--> + <!-- </el-button>--> + <!-- </div>--> + </div> + <el-table + :data="tableData" + style="width: 100%" + ref="multipleTableRef" + @selection-change="handleSelectionChange" + > + <el-table-column + type="selection" + width="55" + /> + <el-table-column prop="drillName" label="演练名称" show-overflow-tooltip sortable></el-table-column> + <el-table-column prop="drillAddress" label="演练地点" show-overflow-tooltip sortable></el-table-column> + <el-table-column prop="drillWay" label="演练方式" show-overflow-tooltip sortable> + <template #default="scope"> + <div v-if="scope.row.drillWay=='0'">综合</div> + <div v-if="scope.row.drillWay=='1'">桌面</div> + <div v-if="scope.row.drillWay=='2'">专项</div> + </template> + </el-table-column> + <el-table-column prop="drillLevel" label="演练级别" show-overflow-tooltip sortable> + <template #default="scope"> + <div v-if="scope.row.drillLevel=='1'">公司级</div> + <div v-if="scope.row.drillLevel=='2'">分厂级</div> + <div v-if="scope.row.drillLevel=='3'">车间级</div> + </template> + </el-table-column> + <el-table-column prop="drillPlanDate" label="计划演练日期" show-overflow-tooltip sortable></el-table-column> + <el-table-column prop="drillRecordDate" label="演练记录日期" show-overflow-tooltip sortable></el-table-column> + <!-- <el-table-column prop="attachments" label="应急预案" show-overflow-tooltip sortable></el-table-column>--> + <el-table-column label="操作" width="260" align="center" fixed="right"> + <template #default="scope"> + <!--<el-button size="small" text disabled>--> + <!--<el-icon style="margin-right: 5px;">--> + <!--<EditPen />--> + <!--</el-icon>评价--> + <!--</el-button>--> + <!-- <el-button size="small" text type="primary" @click="onFlowChart(scope.row.id)">--> + <!-- 审批进度--> + <!-- </el-button>--> + <el-button size="small" text type="primary" @click="onApprovalProgress('查看评价',scope.row.id)"> + <el-icon style="margin-right: 5px;"> + <EditPen /> + </el-icon>查看评价 + </el-button> + <!--<el-button size="small" text type="primary" @click="onEdit('修改',scope.row.id)">--> + <!--<el-icon style="margin-right: 5px;">--> + <!--<EditPen />--> + <!--</el-icon>整改--> + <!--</el-button>--> + <!--<el-button size="small" text disabled @click="onOpenEdit(scope.row)">--> + <!--查看整改--> + <!--</el-button>--> + </template> + </el-table-column> + </el-table> + <div class="pages"> + <el-pagination + v-if="tableData.length == 0 ? false : true" + v-model:currentPage="pageIndex" + v-model:page-size="pageSize" + :page-sizes="[10, 20, 30]" + :pager-count="5" + layout="total, sizes, prev, pager, next, jumper" + :total="total" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + </el-tab-pane> + </el-tabs> + </el-card> + <ApprovalProgress ref="approvalRef" @myAdd="onMyAdd" /> +<!-- <FlowChart ref="flowRef" />--> + <RectificationDialog ref="rectificationRef" @myAdd="onMyAdds" /> +<!-- <upData ref="upShow"></upData>--> + </div> +</template> + +<script lang="ts"> +import { + // toRefs, + reactive, + onMounted, + ref, + defineComponent +} from 'vue'; +import { + ElMessage, + ElMessageBox, + TabsPaneContext, +} from 'element-plus'; +import { + Plus, + // Upload, + // Download, + // Refresh, + Delete, + EditPen, +} from '@element-plus/icons-vue' +// import FlowChart from '/@/views/contingencyManagement/emergencyDrill/drillImplementationEvaluation/component/flowChart.vue' +import ApprovalProgress from '/@/views/contingencyManagement/emergencyDrill/drillImplementationEvaluation/component/approvalProgress.vue'; +// import UpData from '/@/views/contingencyManagement/panManagement/component/upData.vue'; +import RectificationDialog from '/@/views/contingencyManagement/emergencyDrill/drillImplementationEvaluation/component/rectificationDialog.vue'; +import {emergencyDrillEvaluationApi} from '/@/api/contingencyManagement/emergencyDrillEvaluation' +import {emergencyDrillExecuteApi} from "/@/api/contingencyManagement/emergencyDrillExecute"; + + +// 定义接口来定义对象的类型 +// interface TableDataRow { +// } +export default defineComponent({ + name: 'systemUser', + components: { + EditPen, + Plus, + // Upload, + // Download, + // Refresh, + // UpData, + Delete, + ApprovalProgress, + RectificationDialog, + // FlowChart + }, + setup() { + const activeName = ref('first') + const handleClick = (tab: TabsPaneContext, event: Event) => { + console.log(tab, event) + if(tab.props.name=='first'){ + listQuery.searchParams.status=false + listApi() + }else if(tab.props.name=='second'){ + listQuery.searchParams.status=true + listApi() + } + } + // 列表参数 + const listQuery = reactive({ + pageIndex: 1, + pageSize: 10, + searchParams: { + status:false + }, + }); + // 定义表格数据 + const tableData = ref([]); + + // 列表数据请求 + const listApi = async () => { + // let res = await emergencyDrillEvaluationApi().getEmergencyDrillEvaluationList(listQuery); + let res = await emergencyDrillExecuteApi().getEmergencyDrillExecuteList(listQuery); + if (res.data.code == 200) { + tableData.value = res.data.data; + pageIndex.value = res.data.pageIndex; + pageSize.value = res.data.pageSize; + total.value = res.data.total; + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + } + }; + + // 上传 + // const upShow=ref() + // const upButton=()=>{ + // upShow.value.openDialog() + // } + + // 审批进度弹窗 + // const flowRef = ref(); + // const onFlowChart = (row: TableDataRow) => { + // flowRef.value.openDialog(row); + // }; + // 打开修改弹窗 + const rectificationRef = ref(); + const onEdit = (val: string, row: object) => { + if (val == '修改') { + rectificationRef.value.openDialog('修改演练实施评价',row,false); + } else { + // rectificationRef.value.openDialog('修改演练实施评价',row,false); + } + }; + const onMyAdds = (e: boolean) => { + if (e) { + listApi(); + } else { + listApi(); + } + }; + // 审批进度弹窗 + const approvalRef = ref(); + const onApprovalProgress = (val: string, row: object) => { + if (val == '详情') { + approvalRef.value.openDialog('查看演练实施评价', row, true); + } + if (val == '评价') { + approvalRef.value.openDialog('演练实施评价', row, false); + } + if (val == '查看评价') { + approvalRef.value.openDialog('演练实施查看评价', row, true); + } + }; + // 新增后刷新 + const onMyAdd = (e: boolean) => { + if (e) { + listApi(); + } else { + listApi(); + } + }; + // 整改弹窗 + // const rectificationRef = ref(); + // const onEdit = () => { + // rectificationRef.value.openDialog(); + // }; + // 多选删除 + const onDeleteAll = () => { + ElMessageBox.confirm('确定删除所选项吗?', '提示', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + emergencyDrillEvaluationApi() + .deleteEmergencyDrillEvaluation(deletAll.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'success', + }); + listApi(); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + listApi(); + } + }); + }) + .catch(() => {}); + }; + // 分页 + const pageIndex = ref(); + const pageSize = ref(); + const total = ref(); + // 分页改变 + const handleSizeChange = (val: number) => { + listQuery.pageSize = val; + listApi(); + }; + // 分页未改变 + const handleCurrentChange = (val: number) => { + listQuery.pageIndex = val; + listApi(); + }; + const danger = ref(true); + const deletAll = ref(); + const handleSelectionChange = (val: any) => { + let valId = JSON.parse(JSON.stringify(val)); + let arr = []; + for (let i = 0; i < valId.length; i++) { + arr.push(valId[i].id); + } + deletAll.value = arr; + // console.log(deletAll.value); + if (val.length == 1) { + danger.value = false; + } else if (val.length == 0) { + danger.value = true; + } else { + danger.value = false; + } + }; + onMounted(() => { + listApi(); + }); + return { + activeName, + handleClick, + // upButton, + // upShow, + tableData, + // onOpenEdit, //编辑 + pageIndex, + pageSize, + handleSizeChange, + handleCurrentChange, + onApprovalProgress, + approvalRef, + onEdit, + rectificationRef, + // onFlowChart, + // flowRef, + onDeleteAll, + danger, + total, + handleSelectionChange, + onMyAdd, + onMyAdds, + }; + }, +}); +</script> +<style scoped lang="scss"> +.table_Box{ + padding: 20px; + background-color: #fff; +} +.tableForm{ + margin-top: 10px; +} +/*按钮行*/ +.button_Line{ + display: flex; + flex-direction: row; + justify-content: space-between; +} +//表头 +::v-deep .el-table th.el-table__cell { + background-color: #f6f7fa; + font-weight: 400; + color: #909399; +} +.el-table .sort-caret.ascending{ + border-bottom-color: #c0c4cc; +} +//分页 +.pages{ + display: flex; + justify-content: flex-end; + margin-top: 15px; +} +::v-deep .el-pagination .el-pager li { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +::v-deep .el-pagination .el-pager li.is-active { + background-color: #409eff; + color: #fff; +} +::v-deep .el-pagination .btn-prev { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +::v-deep .el-pagination button:disabled{ + color: #c0c4cc; +} +::v-deep .el-pagination .btn-next{ + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +</style> \ No newline at end of file diff --git a/src/views/contingencyManagement/emergencyDrill/implementationOfEmergencyDrill/component/openAdd.vue b/src/views/contingencyManagement/emergencyDrill/implementationOfEmergencyDrill/component/openAdd.vue new file mode 100644 index 0000000..3b85b4a --- /dev/null +++ b/src/views/contingencyManagement/emergencyDrill/implementationOfEmergencyDrill/component/openAdd.vue @@ -0,0 +1,629 @@ +<template> + <div class="system-edit-user-container"> + <el-dialog + :title="titles" + v-model="isShowDialog" + width="769px" + draggable + :fullscreen="full" + @close="resetForm(ruleFormRef)" + > + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-form + ref="ruleFormRef" + :model="ruleForm" + size="default" + label-width="120px" + :disabled="disabled" + > + <el-row :gutter="35"> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="演练名称" prop="drillName"> + <el-input + v-model="ruleForm.drillName" + placeholder="请选择" + class="input-with-select" + > + <template #append> + <el-button :icon="Search" @click="regionsDialog"/> + </template> + </el-input> + </el-form-item> + </el-col> + </el-row> + + + <el-row :gutter="35"> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="演练地点" prop="drillAddress"> + <el-input :disabled="true" v-model="drillRuleForm.drillAddress" placeholder="请填写演练地点"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="主办部门" placeholder="请选择" prop="departmentId"> + <el-tree-select + :disabled="true" + v-model="drillRuleForm.departmentId" + :data="deptData" + check-strictly + class="w100" + :props="propse" + clearable + placeholder="请选择"/> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="演练方式" prop="drillWay"> + <el-select :disabled="true" v-model="drillRuleForm.drillWay" class="w100" placeholder="请选择"> + <el-option label="综合" value="0"></el-option> + <el-option label="桌面" value="1"></el-option> + <el-option label="专项" value="2"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="应急预案" prop="planName" > + <el-input + :disabled="true" + v-model="drillRuleForm.planName" + placeholder="请选择" + class="input-with-select" + > + <template #append> + <el-button :disabled="true" :icon="Search" @click="daiInpt"/> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="演练级别" prop="drillLevel"> + <el-select :disabled="true" v-model="drillRuleForm.drillLevel" class="w100" placeholder="请选择"> + <el-option label="公司级" value="1"></el-option> + <el-option label="分厂级" value="2"></el-option> + <el-option label="车间级" value="3"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="计划定制日期" prop="makingPlanDate"> + <el-date-picker :disabled="true" v-model="drillRuleForm.makingPlanDate" + value-format="YYYY-MM-DD HH:mm:ss" type="datetime" placeholder="选择日期时间" style="width: 100%" /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="计划演练日期" prop="drillPlanDate"> + <el-date-picker :disabled="true" v-model="drillRuleForm.drillPlanDate" + value-format="YYYY-MM-DD HH:mm:ss" type="datetime" placeholder="选择日期时间" style="width: 100%" /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="修改时间" prop="gmtModitify"> + <el-date-picker :disabled="true" v-model="drillRuleForm.gmtModitify" + value-format="YYYY-MM-DD HH:mm:ss" type="datetime" placeholder="选择日期时间" style="width: 100%" /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="计划定制人" prop="makingUserName"> + <el-input :disabled="true" v-model="drillRuleForm.makingUserName" placeholder="请填写计划定制人"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="制定部门" prop="makingDepartmentId"> + <el-tree-select + :disabled="true" + v-model="drillRuleForm.makingDepartmentId" + check-strictly + :data="deptData" + class="w100" + :props="propse" + clearable + placeholder="请选择"/> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="演练人员" prop="userListString" > + <el-input + :disabled="true" + v-model="drillRuleForm.userListString" + placeholder="请选择" + class="input-with-select" + > + <template #append> + <el-button :disabled="true" :icon="Search" @click="openUser(0)"/> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="演练目的" prop="purpose"> + <el-input + :disabled="true" + v-model="drillRuleForm.purpose" + placeholder="请填写演练目的" + class="input-with-select textarea" + type="textarea" + > + </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="演练负责人" prop="chargeUserListString" > + <el-input + :disabled="true" + v-model="drillRuleForm.chargeUserListString" + placeholder="请选择" + class="input-with-select" + > + <template #append> + <el-button :disabled="true" :icon="Search" @click="openUser(1)"/> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="保险措施" prop="insuranceMeasures"> + <el-input :disabled="true" v-model="drillRuleForm.insuranceMeasures" placeholder="请填写保险措施"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="演练经费" prop="drillExpense"> + <el-input :disabled="true" v-model="drillRuleForm.drillExpense" placeholder="请填写演练经费"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="备注信息" prop="remark"> + <el-input + :disabled="true" + v-model="drillRuleForm.remark" + placeholder="请填写备注信息" + class="input-with-select textarea" + type="textarea" + > + </el-input> + </el-form-item> + </el-col> + </el-row> + + + + + <el-row :gutter="35"> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="实际到场人员" prop="autualUserListString" > + <el-input + v-model="ruleForm.autualUserListString" + placeholder="请选择" + class="input-with-select" + > + <template #append> + <el-button :icon="Search" @click="openUser"/> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="演练过程描述" prop="processDesc"> + <el-input + v-model="ruleForm.processDesc" + placeholder="请填写演练过程描述" + class="textarea" + type="textarea" + /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="演练记录人" prop="recordUserName" > + <el-input + v-model="ruleForm.recordUserName" + placeholder="请选择" + class="input-with-select" + > + <template #append> + <el-button :icon="Search" @click="daiInpt"/> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="演练记录时间" prop="drillRecordDate"> + <el-date-picker + class="w100" + v-model="ruleForm.drillRecordDate" + type="datetime" + placeholder="选择日期时间" + value-format="YYYY-MM-DD HH:mm:ss" + /> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="resetForm(ruleFormRef)" size="default">关闭</el-button> + <el-button size="default" v-if="disabled == true ? false : true" type="primary" @click="submitForm(titles, ruleFormRef)">确定</el-button> + </span> + </template> + </el-dialog> + <!--记录人--> + <DailogSearchUser ref="Shows" @SearchUser="onUser"/> + <!--到场人员--> + <DailogSearchUser ref="userRef" @SearchUser="selectDCuser"/> + <RegionsDialog ref="openRef" @SearchUser="onUsers"/> + </div> +</template> + +<script lang="ts"> +import { + // reactive, + ref, + defineComponent, + onMounted, +} from 'vue'; + +import type { + FormInstance, + // FormRules, +} from 'element-plus' +import { ElMessage } from 'element-plus'; +import { + Search, + FullScreen +} from '@element-plus/icons-vue' +import UserCheckbox from "/@/components/userCheckbox/index.vue" +import DailogSearchUser from '/@/components/DailogSearchUser/index.vue' +import RegionsDialog from '/@/views/contingencyManagement/emergencyDrill/implementationOfEmergencyDrill/component/regionsDialog.vue' +import {emergencyDrillExecuteApi} from "/@/api/contingencyManagement/emergencyDrillExecute"; +import {releaseDrillPlanApi} from "/@/api/contingencyManagement/emergencyDrillPlan"; +import {goalManagementApi} from "/@/api/goalManagement"; + +export default defineComponent({ + name: 'openAdd', + components: { + DailogSearchUser, + UserCheckbox, + RegionsDialog, + }, + setup(props, { emit }) { + const isShowDialog = ref(false) + + const ruleFormRef = ref<FormInstance>() + //定义表单 + const ruleForm = ref ({ + drillRecordDate: '', // 演练记录时间 + drillPlanId: '', //演练计划ID + drillName:'', + recordUserUid: '', // 记录人ID + recordUserName:'', + processDesc: '', // 演练过程描述 + + autualUserListString:'', + userList: [ + { + userUid: '', + }, + { + userUid: '', + } + ] + }); + const titles = ref(); + const disabled = ref(); + // 打开弹窗 + const openDialog = (title: string, id: number, type: boolean) => { + isShowDialog.value = true; + titles.value = title; + disabled.value = type; + if (title == '查看应急演练实施' || title == '修改应急演练实施') { + emergencyDrillExecuteApi() + .seeEmergencyDrillExecute(id) + .then((res) => { + if (res.data.code == 200) { + ruleForm.value = res.data.data; + ruleForm.value.autualUserListString='' + for(var a = 0;a<res.data.data.userList.length;a++){ + ruleForm.value.autualUserListString += res.data.data.userList[a].userName+';' + } + + releaseDrillPlanApi() + .seeReleaseDrillPlan(res.data.data.drillPlanId) + .then((res1) => { + if (res1.data.code == 200) { + drillRuleForm.value = res1.data.data; + + drillRuleForm.value.userListString='' + drillRuleForm.value.chargeUserListString='' + for(var a = 0;a<res1.data.data.userList.length;a++){ + if(res1.data.data.userList[a].type==1){ + drillRuleForm.value.userListString += res1.data.data.userList[a].userName+';' + } + // if(res.data.data.userList[a].type==2){ + // ruleForm.value.chargeUserListString += res.data.data.userList[a].userName+';' + // } + } + // alert(res.data.data.chargeUserList.length) + for(var a = 0;a<res1.data.data.chargeUserList.length;a++){ + drillRuleForm.value.chargeUserListString += res1.data.data.chargeUserList[a].userName+';' + } + } + }) + } + }); + } + }; + const data = []; + const deptData = [] + //部门树 + // const department = () => { + // goalManagementApi() + // .getTreedepartment() + // .then((res) => { + // if (res.data.code == 200) { + // deptData.value = res.data.data; + // console.log('-------',deptData.value) + // } else { + // ElMessage.error(res.data.msg); + // } + // }); + // }; + // + // const propse = { + // label: 'depName', + // children: 'children', + // value: 'depId', + // }; + //el-tree-select回显 + const propse = { + label: 'depName', + children: 'children', + }; + //得到部门树 + const department = async () => { + await goalManagementApi() + .getTreedepartment() + .then((res) => { + if (res.data.code == 200) { + data.value = res.data.data; + getTreeList(res.data.data, deptData); + console.log('deptData',deptData) + } else { + ElMessage.error(res.data.msg); + } + }); + }; + // 递归树状数据且修改字段名 + const getTreeList = (treeList, deptData) => { + treeList.map((c) => { + let tempData = { + depName: c.depName, + value: c.depId, + children: [], + }; + if (c.children && c.children.length > 0) { + tempData.children = []; + getTreeList(c.children, tempData.children); + } + deptData.push(tempData); + }); + }; + onMounted(() => { + department(); + }); + //日期选择器 + const drillRecordDate = ref('') + // 表单提交验证必填项 + const submitForm = async (title: string, formEl: FormInstance | undefined) => { + delete ruleForm.value.drillName + delete ruleForm.value.autualUserListString + if (title == '新建应急演练实施') { + if (!formEl) return; + await formEl.validate((valid, fields) => { + if (valid) { + isShowDialog.value = false; + emergencyDrillExecuteApi() + .addEmergencyDrillExecute(ruleForm.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'success', + }); + emit('myAdd', true); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + emit('myAdd', true); + } + formEl.resetFields(); + }); + } else { + console.log('error submit!', fields); + } + }); + } + else if (title == '修改应急演练实施') { + if (!formEl) return; + await formEl.validate((valid, fields) => { + if (valid) { + isShowDialog.value = false; + emergencyDrillExecuteApi() + .editEmergencyDrillExecute(ruleForm.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: '修改成功', + type: 'success', + }); + emit('myAdd', true); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + emit('myAdd', true); + } + formEl.resetFields(); + }); + } else { + console.log('error submit!', fields); + } + }); + formEl.resetFields(); + ruleForm.value = { + drillRecordDate: '', // 演练记录时间 + drillPlanId: '', //演练计划ID + drillName:'', + recordUserUid: '', // 记录人ID + processDesc: '', // 演练过程描述 + userList: [ + { + userUid: '', + }, + { + userUid: '', + } + ] + }; + } + } + const resetForm = (formEl: FormInstance | undefined) => { + isShowDialog.value = false; + if (!formEl) return; + drillRuleForm.value={} + formEl.resetFields(); + }; + + // 演练名称弹窗 + const openRef=ref() + const regionsDialog = () => { + openRef.value.openDailog() + } + //定义表单 + const drillRuleForm = ref ({}) + const onUsers = (e:any) => { + console.log(e) + releaseDrillPlanApi() + .seeReleaseDrillPlan(e.id) + .then((res) => { + if (res.data.code == 200) { + drillRuleForm.value = res.data.data; + + drillRuleForm.value.userListString='' + drillRuleForm.value.chargeUserListString='' + for(var a = 0;a<res.data.data.userList.length;a++){ + if(res.data.data.userList[a].type==1){ + drillRuleForm.value.userListString += res.data.data.userList[a].userName+';' + } + // if(res.data.data.userList[a].type==2){ + // ruleForm.value.chargeUserListString += res.data.data.userList[a].userName+';' + // } + } + // alert(res.data.data.chargeUserList.length) + for(var a = 0;a<res.data.data.chargeUserList.length;a++){ + drillRuleForm.value.chargeUserListString += res.data.data.chargeUserList[a].userName+';' + } + } + }) + ruleForm.value.drillPlanId=e.id + ruleForm.value.drillName=e.drillName + }; + // 实际到场人员弹窗 + const userRef = ref(); + const openUser = () => { + userRef.value.openDailog(0); + }; + const selectDCuser = (e) => { + ruleForm.value.autualUserListString='' + ruleForm.value.userList=[] + for(var a = 0;a<e.length;a++){ + ruleForm.value.userList.push( + { + userName: e[a].realName, + userUid: e[a].uid, + } + ) + ruleForm.value.autualUserListString+=e[a].realName+';' + } + } + // 演练记录人弹窗 + const Shows=ref() + const daiInpt=()=>{ + Shows.value.openDailog() + } + const onUser = (e:any) => { + ruleForm.value.recordUserUid=e.uid + ruleForm.value.recordUserName=e.realName + }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + return { + openDialog, + isShowDialog, + Search, + ruleForm, + drillRecordDate, + daiInpt, + Shows, + ruleFormRef, + submitForm, + // rules, + openUser, + userRef, + regionsDialog, + onUsers, + onUser, + openRef, + toggleFullscreen, + FullScreen, + full, + resetForm, + titles, + disabled, + emit, + selectDCuser, + drillRuleForm, + deptData, + propse, + data, + department + }; + }, +}); +</script> +<style scoped lang="scss"> +.textarea{ + height: 168px!important; +} +.textarea ::v-deep .el-textarea__inner{ + height: 168px!important; +} +::v-deep .el-table__cell { + font-weight: 400; +} +.el-divider--horizontal{ + height: 0; + margin: 0; + border-top: transparent; +} +.el-select{ + width: 100%; +} +.textarea{ + height: 90px!important; +} +.textarea ::v-deep .el-textarea__inner{ + height: 90px!important; +} +</style> \ No newline at end of file diff --git a/src/views/contingencyManagement/emergencyDrill/implementationOfEmergencyDrill/component/regionsDialog.vue b/src/views/contingencyManagement/emergencyDrill/implementationOfEmergencyDrill/component/regionsDialog.vue new file mode 100644 index 0000000..a6cdd4e --- /dev/null +++ b/src/views/contingencyManagement/emergencyDrill/implementationOfEmergencyDrill/component/regionsDialog.vue @@ -0,0 +1,221 @@ +<template> + <el-dialog v-model="dialogVisible" title="选择演练计划" width="900px" draggable :fullscreen="full"> + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-row> + <el-col :span="18"> + <el-row> + <el-col :span="24"> + <el-form ref="ruleFormRef" :inline="true" :model="ruleForm" status-icon> + <el-form-item> + <el-input size="default" v-model="listQuery.searchParams.drillName" placeholder="演练名称" style="max-width: 215px;margin-right: 12px;" /> + </el-form-item> + <el-form-item> + <el-button size="default" type="primary" @click="onSubmit">查询</el-button> + <el-button size="default" @click="submitReset">重置</el-button> + </el-form-item> + </el-form> + </el-col> + <el-col :span="24"> + <el-button size="default" :icon="Delete" style="margin-top: 15px">清除选择</el-button> + </el-col> + </el-row> + <el-table + :data="tableData" + style="width: 100%; + margin-top: 20px" + @cell-click="radio" + > + <el-table-column width="55"> + <template #default="scope"> + <el-radio-group v-model="radio1"> + <el-radio :label="scope.row" size="large">{{ null }}</el-radio> + </el-radio-group> + </template> + </el-table-column> + <el-table-column align="center" prop="drillName" label="演练名称" /> + </el-table> + <div class="pages"> + <el-pagination + v-model:currentPage="pageIndex" + v-model:page-size="pageSize" + :page-sizes="[10, 20, 30]" + layout="total, sizes, prev, pager, next, jumper" + :total="total" + @size-change="onHandleSizeChange" + @current-change="onHandleCurrentChange" + /> + </div> + </el-col> + <el-col :span="6"> + <div v-if="dynamicTags[0] == '' ? false : true"> + <el-tag + v-for="tag in dynamicTags" + :key="tag" + class="mx-1" + style="margin: 5px" + closable + :disable-transitions="false" + @close="handleClose(tag)" + > + {{ tag.drillName }} + </el-tag> + </div> + </el-col> + </el-row> + <template #footer> + <span class="dialog-footer"> + <el-button @click="dialogVisible = false" size="default">关闭</el-button> + <el-button type="primary" @click="submitForm" size="default">确定</el-button> + </span> + </template> + </el-dialog> +</template> +<script lang="ts"> +import { defineComponent, reactive, ref, onMounted } from 'vue'; +import { ElMessage } from 'element-plus'; +import { Delete, FullScreen } from '@element-plus/icons-vue'; +import { emergencyPlanLogApi } from '/@/api/contingencyManagement/emergencyPlanLog'; +import { emergencyPlanApi } from '/@/api/contingencyManagement/emergencyPlan'; +import {releaseDrillPlanApi} from "/@/api/contingencyManagement/emergencyDrillPlan"; +export default defineComponent({ + setup(props, { emit }) { + const dialogVisible = ref<boolean>(false); + const openDailog = () => { + dialogVisible.value = true; + onSubmit() + }; + // 搜索条件 + const listQuery = reactive({ + pageIndex: 1, + pageSize: 10, + searchParams: { + drillName: '' + }, + }); + // 列表请求数据 + const onSubmit = async () => { + let res = await releaseDrillPlanApi().getReleaseDrillPlanList(listQuery); + if (res.data.code === '200') { + tableData.value = res.data.data; + pageIndex.value = res.data.pageIndex; + pageSize.value = res.data.pageSize; + total.value = res.data.total; + } else { + ElMessage({ + showClose: true, + type: 'error', + message: res.data.msg, + }); + } + }; + // 定义表格数据 + const tableData = ref([]); + // 重置 + const submitReset = () => { + listQuery.searchParams.drillName = ''; + onSubmit(); + }; + // 分页 + const pageIndex = ref(); + const pageSize = ref(); + const total = ref(); + // 分页改变 + const onHandleSizeChange = (val: number) => { + listQuery.pageSize = val; + }; + // 分页未改变 + const onHandleCurrentChange = (val: number) => { + listQuery.pageIndex = val; + }; + // 右方点击添加后显示标签 + const dynamicTags = ref(['']); + const handleClose = (tag: string) => { + dynamicTags.value.splice(dynamicTags.value.indexOf(tag), 1); + radio1.value = ''; + }; + const radio1 = ref(''); + const radio = (event: any) => { + dynamicTags.value[0] = event; + }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + + const submitForm = () => { + let obj = JSON.parse(JSON.stringify(dynamicTags.value)); + emit('SearchUser', obj[0]); + dialogVisible.value = false; + }; + onMounted(() => { + onSubmit(); + }); + return { + dialogVisible, + openDailog, + tableData, + pageSize, + pageIndex, + onHandleSizeChange, + onHandleCurrentChange, + dynamicTags, + handleClose, + Delete, + radio1, + radio, + toggleFullscreen, + FullScreen, + full, + submitReset, + onMounted, + listQuery, + submitForm, + onSubmit, + total, + }; + }, +}); +</script> +<style scoped> +.el-form--inline .el-form-item { + margin-bottom: 0; + margin-right: 0; +} +/*分页*/ +.pages { + margin-top: 15px; +} +::v-deep .el-pagination .el-pager li { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +::v-deep .el-pagination .el-pager li.is-active { + background-color: #409eff; + color: #fff; +} +::v-deep .el-pagination .btn-prev { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +::v-deep .el-pagination button:disabled { + color: #c0c4cc; +} +::v-deep .el-pagination .btn-next { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +</style> diff --git a/src/views/contingencyManagement/emergencyDrill/implementationOfEmergencyDrill/component/userSelect.vue b/src/views/contingencyManagement/emergencyDrill/implementationOfEmergencyDrill/component/userSelect.vue new file mode 100644 index 0000000..c3a4156 --- /dev/null +++ b/src/views/contingencyManagement/emergencyDrill/implementationOfEmergencyDrill/component/userSelect.vue @@ -0,0 +1,443 @@ +<template> + <div class="system-edit-user-container"> + <el-dialog + title="用户选择" + v-model="isShowDialog" + width="1000px" + draggable + :fullscreen="full" + > + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-container class="layout-container-demo" style="height: 500px;overflow: auto;min-width: 960px"> + <el-aside width="200px"> + <el-input v-model="filterText" placeholder="请输入组织机构过滤" /> + <el-tree + ref="treeRef" + class="filter-tree" + :data="data" + :props="defaultProps" + default-expand-all + :filter-node-method="filterNode" + /> + </el-aside> + <el-container style="margin: 0 15px;min-width:560px;"> + <el-header style="font-size: 12px"> + <el-form :inline="true" :model="formInline" class="demo-form-inline"> + <el-form-item> + <el-input size="default" v-model="formInline.name" placeholder="登录名"> </el-input> + </el-form-item> + <el-form-item> + <el-button size="default" type="primary" class="ml10" @click="onSubmit"> + 查询 + </el-button> + <el-button size="default" class="ml10" @click="submitReset"> + 重置 + </el-button> + </el-form-item> + </el-form> + </el-header> + <el-main style="position: relative;"> + <el-table + :data="tableData" + :header-cell-style="{background:'#f6f7fa',color:'#909399',fontWeight:400}" + > + <el-table-column align="center" width="55"> + <template #default="scope"> + <el-radio-group v-model="radio1" @change="radio"> + <el-radio :label="scope.row.date" size="large">{{null}}</el-radio> + </el-radio-group> + </template> + </el-table-column> + <el-table-column prop="date" label="登录名" width="100" show-overflow-tooltip sortable /> + <el-table-column prop="name" label="用户名" width="100" show-overflow-tooltip sortable /> + <el-table-column prop="address" label="所属机构" width="115" show-overflow-tooltip sortable /> + <el-table-column prop="department" label="所属部门" width="115" show-overflow-tooltip sortable/> + <el-table-column label="状态" + width="80" + prop="tag" + :filters="[ + { text: '正常', value: 'Home' }, + { text: '不正常', value: 'Office' }, + ]" + :filter-method="filterTag" + filter-placement="bottom-end"> + <template #default="scope"> + <el-tag + :type="scope.row.tag === 'Home' ? '' : 'success'" + disable-transitions + >{{ scope.row.tag }}</el-tag + > + </template> + </el-table-column> + </el-table> + <div class="pages"> + <el-pagination + v-model:currentPage="pageIndex" + v-model:page-size="pageSize" + :page-sizes="[10, 20, 30]" + :pager-count="5" + :small="small" + :disabled="disabled" + :background="background" + layout="total, sizes, prev, pager, next, jumper" + :total="40" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + </el-main> + </el-container> + <div style="width: 200px;"> + <el-tag + v-for="tag in dynamicTags" + :key="tag" + class="mx-1" + style="margin: 5px" + closable + :disable-transitions="false" + @close="handleClose(tag)" + > + {{ tag }} + </el-tag> + </div> + </el-container> + <template #footer> + <span class="dialog-footer"> + <el-button size="default" type="primary" @click="onCancel">确定</el-button> + <el-button size="default" @click="onCancel">关闭</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script lang="ts"> +import { + ref, + defineComponent, + watch, + reactive, +} from 'vue'; + +import type { + ElTree, + // ElTable, +} from 'element-plus' +import { + FullScreen +} from '@element-plus/icons-vue' +interface Tree { + id: number + label: string + children?: Tree[] +} +// interface User { +// date: string +// name: string +// address: string +// } +export default defineComponent({ + name: 'userSelections', + components: { + // Search, + }, + setup() { + const isShowDialog = ref(false) + // 打开弹窗 + const openDialog = () => { + isShowDialog.value = true; + }; + // 关闭弹窗 + const closeDialog = () => { + isShowDialog.value = false; + }; + // 取消 + const onCancel = () => { + closeDialog(); + }; + + + const filterText = ref('') + const treeRef = ref<InstanceType<typeof ElTree>>() //实例化 + + const defaultProps = { + children: 'children', + label: 'label', + } + + // 监听搜索关键字改变 + watch(filterText, (val) => { + treeRef.value!.filter(val) + }) + + // 节点过滤模糊搜索 + const filterNode = (value: string, data: Tree) => { + if (!value) return true + return data.label.includes(value) + } + + // 树形结构内容 + const data: Tree[] = [ + { + id: 1, + label: '广汇能源综合物流发展有限责任公司', + children: [ + { + id: 4, + label: '经营班子', + children: [] + }, + ], + }, + { + id: 2, + label: '生产运行部', + children: [ + { + id: 5, + label: '工艺二班', + }, + { + id: 6, + label: '灌装一班', + }, + ], + }, + { + id: 3, + label: '设备部', + children: [ + { + id: 7, + label: '仪表班', + }, + { + id: 8, + label: '机修班', + }, + ], + }, + ] + // const item = { + // date: '孙刚', + // name: '龚赛健', + // address: '综合办公室', + // tag: '正常', + // } + // const tableData = ref(Array.from({ length: 7 }).fill(item)) + const tableData = [ + { + date: '孙刚', + name: '孙刚', + address: '', + department: '经营班子', + tag: '正常', + }, + { + date: '谭柏', + name: '谭柏', + address: '', + department: '经营班子', + tag: '正常', + }, + { + date: '倪威', + name: '倪威', + address: '', + department: '经营班子', + tag: '正常', + }, + { + date: '倪玲婕', + name: '倪玲婕', + address: '', + department: '经营班子', + tag: '正常', + }, + ]; + // 定义表单搜索 + const formInline = reactive({ + name: '', + }) + // 搜索按钮 + const onSubmit = () => { + console.log('submit!') + } + + // const multipleTableRef = ref<InstanceType<typeof ElTable>>() + // 右方点击添加后显示标签 + const dynamicTags = ref(['胡海涛']); + const handleClose = (tag: string) => { + dynamicTags.value.splice(dynamicTags.value.indexOf(tag), 1); + radio1.value="" + }; + const radio1=ref('谭柏') + const radio=(event:any)=>{ + dynamicTags.value[0]=event + } + + // 分页 + const pageIndex = ref(4); + const pageSize = ref(10); + // 分页改变 + const handleSizeChange = (val: number) => { + console.log(`${val} items per page`); + }; + // 分页未改变 + const handleCurrentChange = (val: number) => { + console.log(`current page: ${val}`); + }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + return { + openDialog, + closeDialog, + isShowDialog, + onCancel, + defaultProps, + filterNode, + data, + tableData, + formInline, + onSubmit, + // multipleTableRef, + handleClose, + dynamicTags, + handleSizeChange, + handleCurrentChange, + pageIndex, + pageSize, + radio1, + radio, + toggleFullscreen, + FullScreen, + full, + }; + }, +}); +</script> +<style scoped lang="scss"> +.layout-container-demo .el-header { + position: relative; + color: var(--el-text-color-primary); + line-height: 32px; + --el-header-height: 45px; + padding: 0; +} +.layout-container-demo .el-aside { + padding: 10px; + border: 1px solid #ebeef5; + color: var(--el-text-color-primary); +} +::v-deep .el-input--large .el-input__inner { + height: 32px!important; + line-height: 32px!important; +} +.layout-container-demo .el-menu { + border-right: none; +} +.layout-container-demo .el-main { + padding: 0; +} +.layout-container-demo .toolbar { + display: inline-flex; + align-items: center; + justify-content: center; + height: 100%; + right: 20px; +} +.el-input--large{ + //width: 178px; + height: 32px; +} +.el-tree{ + overflow: auto; +} +::-webkit-scrollbar { + height: 1px; + +} +::-webkit-scrollbar-thumb { + background-color: transparent; +} +// 鼠标悬浮样式 +:hover::-webkit-scrollbar-thumb { + border-radius: 15px; + background-color: #d8d9db; +} +::v-deep .el-input__wrapper{ + width: 215px; +} +::v-deep .el-form-item{ + margin-bottom: 0; + margin-right: 0; +} +//弹窗底部边框线 +::v-deep .el-dialog__footer{ + border-top: 1px solid #e8e8e8; + border-radius: 0 0 4px 4px; +} +//弹窗顶部边框线 +::v-deep .el-dialog__header { + border-bottom: 1px solid #e8e8e8; + margin-right: 0; + border-radius: 4px 4px 0 0; +} +//单选框圆形 +::v-deep .el-table__header .el-table-column--selection .cell .el-checkbox { + display:none +} +::v-deep .el-table-column--selection .cell{ + text-align: center; +} +::v-deep .el-checkbox__input .el-checkbox__inner{ + border-radius: 50%; +} +/*分页*/ +.pages{ + display: flex; + justify-content: flex-end; + margin-top: 15px; + align-items: center; + //position: absolute; + //bottom: 0; +} +::v-deep .el-pagination{ + width: 100%; +} +::v-deep .el-pagination .el-pager li { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +::v-deep .el-pagination .el-pager li.is-active { + background-color: #409eff; + color: #fff; +} +::v-deep .el-pagination .btn-prev { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +::v-deep .el-pagination button:disabled{ + color: #c0c4cc; +} +::v-deep .el-pagination .btn-next{ + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +</style> \ No newline at end of file diff --git a/src/views/contingencyManagement/emergencyDrill/implementationOfEmergencyDrill/index.vue b/src/views/contingencyManagement/emergencyDrill/implementationOfEmergencyDrill/index.vue new file mode 100644 index 0000000..767809d --- /dev/null +++ b/src/views/contingencyManagement/emergencyDrill/implementationOfEmergencyDrill/index.vue @@ -0,0 +1,375 @@ +<template> + <div class="system-user-container"> + <el-card shadow="hover"> + <div class="button_Line mb15"> + <div class="button_Left"> + <el-button size="default" type="primary" @click="onOpenAdd"> + <el-icon> + <Plus /> + </el-icon>新建 + </el-button> + <el-button size="default" type="danger" plain :disabled="danger" @click="onDeleteAll"> + <el-icon> + <Delete /> + </el-icon>删除 + </el-button> + </div> + <div class="button_Right"> +<!-- <el-button @click="upButton">--> +<!-- <el-icon>--> +<!-- <Upload />--> +<!-- </el-icon>--> +<!-- </el-button>--> +<!-- <el-button>--> +<!-- <el-icon>--> +<!-- <Download />--> +<!-- </el-icon>--> +<!-- </el-button>--> +<!-- <el-button>--> +<!-- <el-icon>--> +<!-- <Refresh />--> +<!-- </el-icon>--> +<!-- </el-button>--> + </div> + </div> + <el-table + :data="tableData" + style="width: 100%" + ref="" + @selection-change="handleSelectionChange" + > + <el-table-column + type="selection" + width="55" + /> + <el-table-column prop="drillName" label="演练名称" show-overflow-tooltip sortable></el-table-column> + <el-table-column prop="drillAddress" label="演练地点" show-overflow-tooltip sortable></el-table-column> + <el-table-column prop="drillWay" label="演练方式" show-overflow-tooltip sortable> + <template #default="scope"> + <div v-if="scope.row.drillWay=='0'">综合</div> + <div v-if="scope.row.drillWay=='1'">桌面</div> + <div v-if="scope.row.drillWay=='2'">专项</div> + </template> + </el-table-column> + <el-table-column prop="drillLevel" label="演练级别" show-overflow-tooltip sortable> + <template #default="scope"> + <div v-if="scope.row.drillLevel=='1'">公司级</div> + <div v-if="scope.row.drillLevel=='2'">分厂级</div> + <div v-if="scope.row.drillLevel=='3'">车间级</div> + </template> + </el-table-column> + <el-table-column prop="drillPlanDate" label="计划演练日期" show-overflow-tooltip sortable></el-table-column> + <el-table-column prop="drillRecordDate" label="演练记录时间" show-overflow-tooltip sortable></el-table-column> + <el-table-column prop="emergencyPlanName" label="应急预案" show-overflow-tooltip sortable></el-table-column> + <el-table-column label="操作" width="260" align="center" fixed="right"> + <template #default="scope"> + <el-button size="small" text type="primary" @click="onEdit('详情',scope.row.id)"> + <el-icon style="margin-right: 5px;"> + <View /> + </el-icon>查看 + </el-button> + <el-button size="small" text type="primary" @click="onEdit('修改',scope.row.id)"> + <el-icon style="margin-right: 5px;"> + <EditPen /> + </el-icon>修改 + </el-button> + <el-button size="small" text type="primary" @click="onRowDel(scope.row.id)"> + <el-icon> + <Delete /> + </el-icon>删除 + </el-button> + </template> + </el-table-column> + </el-table> + <div class="pages"> + <el-pagination + v-if="tableData.length == 0 ? false : true" + v-model:currentPage="pageIndex" + v-model:page-size="pageSize" + :page-sizes="[10, 20, 30]" + :pager-count="5" + background + layout="total, sizes, prev, pager, next, jumper" + :total="total" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + </el-card> + <OpenAdd ref="addRef" @myAdd="onMyAdd"/> +<!-- <upData ref="upShow"></upData>--> + </div> +</template> + +<script lang="ts"> +import { + // toRefs, + reactive, + onMounted, + ref, + defineComponent +} from 'vue'; +import { + ElMessageBox, + ElMessage, + // ElTable, +} from 'element-plus'; +import { Plus, + // Edit, + Delete, + // Upload, + // Download, + View, + Refresh, + VideoPause, + EditPen, +} from '@element-plus/icons-vue' +import OpenAdd from '/@/views/contingencyManagement/emergencyDrill/implementationOfEmergencyDrill/component/openAdd.vue'; +import UpData from '/@/views/contingencyManagement/panManagement/component/upData.vue'; +import {emergencyDrillExecuteApi} from "/@/api/contingencyManagement/emergencyDrillExecute"; + +export default defineComponent({ + name: 'systemUser', + components: { + OpenAdd, + EditPen, + Plus, + // Edit, + Delete, + View, + // Upload, + // Download, + Refresh, + VideoPause, + UpData + }, + setup() { + // 列表参数 + const listQuery = reactive({ + pageIndex: 1, + pageSize: 10, + searchParams: { + }, + }); + // 定义表格数据 + const tableData = ref([]); + // 列表数据请求 + const listApi = async () => { + let res = await emergencyDrillExecuteApi().getEmergencyDrillExecuteList(listQuery); + if (res.data.code == 200) { + tableData.value = res.data.data; + pageIndex.value = res.data.pageIndex; + pageSize.value = res.data.pageSize; + total.value = res.data.total; + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + } + }; + + // 上传 + // const upShow=ref() + // const upButton=()=>{ + // upShow.value.openDialog() + // } + // 打开新增用户弹窗 + const addRef = ref(); + const onOpenAdd = () => { + addRef.value.openDialog('新建应急演练实施',false); + }; + // 新增后刷新 + const onMyAdd = (e: boolean) => { + if (e) { + listApi(); + } else { + listApi(); + } + }; + // 打开修改用户弹窗 + const onEdit = (val: string, row: object) => { + if (val == '详情') { + addRef.value.openDialog('查看应急演练实施',row,true); + } else { + addRef.value.openDialog('修改应急演练实施',row,false); + } + }; + // 删除用户 + const onRowDel = (id: number) => { + let arr = []; + arr.push(id) + ElMessageBox.confirm('确定删除所选项吗?', '提示',{ + confirmButtonText: '确认', + cancelButtonText: '取消', + type: 'warning', + }).then(() => { + emergencyDrillExecuteApi() + .deleteEmergencyDrillExecute(arr) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'success', + }); + listApi(); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + listApi(); + } + }); + }) + .catch(() => {}); + }; + const danger = ref(true); + const deletAll = ref(); + const handleSelectionChange = (val: any) => { + let valId = JSON.parse(JSON.stringify(val)); + let arr = []; + for (let i = 0; i < valId.length; i++) { + arr.push(valId[i].id); + } + deletAll.value = arr; + if (val.length == 1) { + danger.value = false; + } else if (val.length == 0) { + danger.value = true; + } else { + danger.value = false; + } + }; + // 多选删除 + const onDeleteAll = () => { + ElMessageBox.confirm('确定删除所选项吗?', '提示', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + emergencyDrillExecuteApi() + .deleteEmergencyDrillExecute(deletAll.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'success', + }); + listApi(); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + listApi(); + } + }); + }) + .catch(() => {}); + }; + // 分页 + const pageIndex = ref(); + const pageSize = ref(); + const total = ref(); + // 分页改变 + const handleSizeChange = (val: number) => { + listQuery.pageSize = val; + listApi(); + }; + // 分页未改变 + const handleCurrentChange = (val: number) => { + listQuery.pageIndex = val; + listApi(); + }; + + onMounted(() => { + listApi(); + }); + return { + // upButton, + // upShow, + tableData, + onOpenAdd, //新增 + addRef, + onRowDel, + pageIndex, + pageSize, + handleSizeChange, + handleCurrentChange, + onMyAdd, + total, + onDeleteAll, + handleSelectionChange, + danger, + deletAll, + onEdit, + }; + }, +}); +</script> +<style scoped lang="scss"> +.table_Box{ + padding: 20px; + background-color: #fff; +} +.tableForm{ + margin-top: 10px; +} +/*按钮行*/ +.button_Line{ + display: flex; + flex-direction: row; + justify-content: space-between; +} +//表头 +::v-deep .el-table th.el-table__cell { + background-color: #f6f7fa; + font-weight: 400; + color: #909399; +} +.el-table .sort-caret.ascending{ + border-bottom-color: #c0c4cc; +} +//分页开始 +.pages{ + display: flex; + justify-content: flex-end; + margin-top: 15px; +} +::v-deep .el-pagination .el-pager li { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +::v-deep .el-pagination .el-pager li.is-active { + background-color: #409eff; + color: #fff; +} +::v-deep .el-pagination .btn-prev { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +::v-deep .el-pagination button:disabled{ + color: #c0c4cc; +} +::v-deep .el-pagination .btn-next{ + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +//分页结束 +</style> \ No newline at end of file diff --git a/src/views/contingencyManagement/emergencyDrill/releaseOfDrillPlan/component/flowChart.vue b/src/views/contingencyManagement/emergencyDrill/releaseOfDrillPlan/component/flowChart.vue new file mode 100644 index 0000000..5dad014 --- /dev/null +++ b/src/views/contingencyManagement/emergencyDrill/releaseOfDrillPlan/component/flowChart.vue @@ -0,0 +1,325 @@ +<template> + <div class="system-edit-user-container"> + <el-dialog + title="应急演练计划--修改审批进度" + v-model="isShowDialog" + width="769px" + draggable + :fullscreen="full" + > + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <!-- <img class="process-status-img" src="src/assets/icon.png"> --> + <el-tabs type="border-card"> + <el-tab-pane label="流转记录"> + <el-card class="box-card" shadow="hover"> + <template #header> + <div class="card-header"> + <span>流转记录</span> + </div> + </template> + <div> + <el-steps :active="2"> + <el-step title="开始" description="胡海涛,2022-07-09 20:41:50" /> + <el-step title="一级审批" description="管理员,2022-07-09 20:41:50" /> + </el-steps> + </div> + <el-table :data="tableData" stripe style="width: 100%"> + <el-table-column prop="date" label="执行环节" width="120" /> + <el-table-column prop="name" label="执行人" width="120" /> + <el-table-column prop="address" label="开始时间" width="100" /> + <el-table-column prop="address" label="结束时间" width="100" /> + <el-table-column prop="address" label="办理状态" width="100" /> + <el-table-column prop="address" label="审批意见" width="100" /> + <el-table-column prop="address" label="任务历时" width="100" /> + </el-table> + </el-card> + </el-tab-pane> + <el-tab-pane label="流程信息"> + <el-card class="box-card" shadow="hover"> + <template #header> + <div class="card-header"> + <span>流程信息</span> + </div> + </template> + <div> + <el-timeline> + <el-timeline-item timestamp="2018/4/12" placement="top" color="rgb(63, 158, 255)"> + <el-card> + <h4 style="margin: 10px 0;padding-bottom: 10px;">一级审批</h4> + <el-row> + <el-col class="tip" :span="22" :offset="1"> + <div class="item"> + <span class="label">审批人:</span> + <span class="value">管理员</span> + </div> + <div class="item"> + <span class="label">办理状态:</span> + <span class="value"> +<!-- <el-tag--> +<!-- v-for="item in items"--> +<!-- :key="item.label"--> +<!-- :type="item.type"--> +<!-- class="mx-1"--> +<!-- effect="dark"--> +<!-- >--> +<!-- {{ item.label }}--> +<!-- </el-tag>--> + <p class="text">等待审核</p> + </span> + </div> + <div class="item"> + <span class="label">审批意见:</span> + <span class="value">等待审核</span> + </div> + <div class="item"> + <span class="label">开始时间:</span> + <span class="value">2022-07-09 20:41:50</span> + </div> + <div class="item"> + <span class="label">结束时间:</span> + <span class="value">2022-07-09 20:41:50</span> + </div> + <div class="item"> + <span class="label">用时:</span> + <span class="value">0秒</span> + </div> + </el-col> + </el-row> + </el-card> + </el-timeline-item> + <el-timeline-item timestamp="2018/4/3" placement="top" color="rgb(63, 158, 255)"> + <el-card> + <h4>开始</h4> + <el-row> + <el-col class="tip" :span="22" :offset="1"> + <div class="item"> + <span class="label">审批人:</span> + <span class="value">胡海涛</span> + </div> + <div class="item"> + <span class="label">办理状态:</span> + <span class="value"> + <p class="text">开始</p> + </span> + </div> + <div class="item"> + <span class="label">审批意见:</span> + <span class="value">等待审核</span> + </div> + <div class="item"> + <span class="label">开始时间:</span> + <span class="value">2022-07-09 20:41:50</span> + </div> + <div class="item"> + <span class="label">结束时间:</span> + <span class="value">2022-07-09 20:41:50</span> + </div> + <div class="item"> + <span class="label">用时:</span> + <span class="value">0秒</span> + </div> + </el-col> + </el-row> + </el-card> + </el-timeline-item> + </el-timeline> + </div> + </el-card> + </el-tab-pane> + <el-tab-pane label="流程图"> + <el-card class="box-card" shadow="hover"> + <template #header> + <div class="card-header"> + <span>流程图</span> + </div> + </template> + <div> + </div> + </el-card> + </el-tab-pane> + </el-tabs> + </el-dialog> + <RegionsDialog ref="Shows"/> + <UserCheckbox ref="userRef"/> + </div> +</template> + +<script lang="ts"> +import { + + ref, + defineComponent +} from 'vue'; + +import type { + TagProps, +} from 'element-plus' + +import { + Search, + FullScreen +} from '@element-plus/icons-vue' +import UserCheckbox from "/@/components/userCheckbox/index.vue" +import RegionsDialog from "/@/views/contingencyManagement/emergencyDrill/releaseOfDrillPlan/component/regionsDialog.vue" + +export default defineComponent({ + name: 'openAdd', + components: { + RegionsDialog, + UserCheckbox, + }, + setup() { + const isShowDialog = ref(false) + // 打开弹窗 + const openDialog = () => { + // state.ruleForm = row; + isShowDialog.value = true; + }; + // 关闭弹窗 + const closeDialog = () => { + isShowDialog.value = false; + }; + const tableData = [ + { + date: '2016-05-03', + name: 'Tom', + address: '2022-07-09 20:41:50', + }, + { + date: '2016-05-02', + name: 'Tom', + address: '2022-07-09 20:41:50', + }, + { + date: '2016-05-04', + name: 'Tom', + address: '2022-07-09 20:41:50', + }, + { + date: '2016-05-01', + name: 'Tom', + address: '2022-07-09 20:41:50', + }, + ] + + type Item = { type: TagProps['type']; label: string } + + const items = ref<Array<Item>>([ + { type: '', label: '等待审核' }, + ]) + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + return { + openDialog, + closeDialog, + isShowDialog, + Search, + tableData, + items, + toggleFullscreen, + FullScreen, + full, + }; + }, +}); +</script> +<style scoped lang="scss"> +.process-status-img{ + width: 128px; + height: auto; + position: absolute; + right: 10px; + top: 60px; + z-index: 999; +} +//弹窗底部边框线 +::v-deep .el-dialog__footer{ + border-top: 1px solid #e8e8e8; + border-radius: 0 0 4px 4px; +} +//弹窗顶部边框线 +::v-deep .el-dialog__header { + border-bottom: 1px solid #e8e8e8; + margin-right: 0; + border-radius: 4px 4px 0 0; +} +//tabs字体颜色 +::v-deep .el-tabs--border-card>.el-tabs__header .el-tabs__item.is-active{ + color: #a9d86e!important; +} +.card-header { + display: flex; + justify-content: space-between; + align-items: center; +} +//.box-card { +// width: 480px; +//} +//步骤条字体大小 +::v-deep .el-step__icon-inner{ + font-size: 14px!important; +} +//步骤条颜色 +::v-deep .el-step__line{ + background-color: #409eff; +} +//表头 +::v-deep .el-table th.el-table__cell { + background-color: #f6f7fa; + font-weight: 400; + color: #909399; +} +.el-table .sort-caret.ascending{ + border-bottom-color: #c0c4cc; +} + +.tip { + padding: 8px 16px; + background-color: #ecf8ff; + border-radius: 4px; + border-left: 5px solid #50bfff; + margin: 20px 0; +} +.item{ + height: 32px; + line-height: 32px; + margin-bottom: 8px; +} +.item .label { + display: inline-block; + height: 100%; + width: 70px; + font-size: 14px; + color: #5e6d82; + text-align: end; + vertical-align: top; +} +.item .value { + padding-left: 10px; + font-size: 14px; + max-width: calc(100% - 90px); + color: #5e6d82; + display: inline-block; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} +.text{ + background-color: #409eff; + color: #fff; + border-width: 1px; + border-style: solid; + border-radius: 4px; + height: 24px; + padding: 0 8px; + line-height: 22px; + display: inline-block; +} +</style> \ No newline at end of file diff --git a/src/views/contingencyManagement/emergencyDrill/releaseOfDrillPlan/component/openAdd.vue b/src/views/contingencyManagement/emergencyDrill/releaseOfDrillPlan/component/openAdd.vue new file mode 100644 index 0000000..8f988a3 --- /dev/null +++ b/src/views/contingencyManagement/emergencyDrill/releaseOfDrillPlan/component/openAdd.vue @@ -0,0 +1,591 @@ +<template> + <div class="system-edit-user-container"> + <el-dialog + :title="titles" + v-model="isShowDialog" + width="769px" + draggable + :fullscreen="full" + @close="resetForm(ruleFormRef)" + > + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-form + ref="ruleFormRef" + :model="ruleForm" + size="default" + label-width="120px" + :disabled="disabled" + > + <el-row :gutter="35"> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="演练名称" prop="drillName"> + <el-input v-model="ruleForm.drillName" placeholder="请填写演练名称"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="演练地点" prop="drillAddress"> + <el-input v-model="ruleForm.drillAddress" placeholder="请填写演练地点"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="主办部门" placeholder="请选择" prop="departmentId"> + <el-tree-select + v-model="ruleForm.departmentId" + :data="data" + check-strictly + class="w100" + :props="propse" + clearable + placeholder="请选择"/> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="演练方式" prop="drillWay"> + <el-select v-model="ruleForm.drillWay" class="w100" placeholder="请选择"> + <el-option label="综合" value="1"></el-option> + <el-option label="桌面" value="2"></el-option> + <el-option label="专项" value="3"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="应急预案" prop="planName" > + <el-input + v-model="ruleForm.planName" + placeholder="请选择" + class="input-with-select" + > + <template #append> + <el-button :icon="Search" @click="daiInpt"/> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="演练级别" prop="drillLevel"> + <el-select v-model="ruleForm.drillLevel" class="w100" placeholder="请选择"> + <el-option label="公司级" value="1"></el-option> + <el-option label="分厂级" value="2"></el-option> + <el-option label="车间级" value="3"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="计划定制日期" prop="makingPlanDate"> + <el-date-picker v-model="ruleForm.makingPlanDate" value-format="YYYY-MM-DD HH:mm:ss" type="datetime" placeholder="选择日期时间" style="width: 100%" /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="计划演练日期" prop="drillPlanDate"> + <el-date-picker v-model="ruleForm.drillPlanDate" value-format="YYYY-MM-DD HH:mm:ss" type="datetime" placeholder="选择日期时间" style="width: 100%" /> + </el-form-item> + </el-col> + <!--<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">--> + <!--<el-form-item label="修改时间" prop="gmtModitify">--> + <!--<el-date-picker v-model="ruleForm.gmtModitify" value-format="YYYY-MM-DD HH:mm:ss" type="datetime" placeholder="选择日期时间" style="width: 100%" />--> + <!--</el-form-item>--> + <!--</el-col>--> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="计划定制人" prop="makingUserName"> + <el-input v-model="ruleForm.makingUserName" placeholder="请填写计划定制人" disabled></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="制定部门" prop="makingDepartmentId"> + <el-tree-select + v-model="ruleForm.makingDepartmentId" + check-strictly + :data="data" + class="w100" + :props="propse" + clearable + placeholder="请选择"/> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="演练人员" prop="userListString" > + <el-input + v-model="ruleForm.userListString" + placeholder="请选择" + class="input-with-select" + > + <template #append> + <el-button :icon="Search" @click="openUser(0)"/> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="演练目的" prop="purpose"> + <el-input + v-model="ruleForm.purpose" + placeholder="请填写演练目的" + class="input-with-select textarea" + type="textarea" + > + </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="演练负责人" prop="chargeUserListString" > + <el-input + v-model="ruleForm.chargeUserListString" + placeholder="请选择" + class="input-with-select" + > + <template #append> + <el-button :icon="Search" @click="openUser(1)"/> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="保险措施" prop="insuranceMeasures"> + <el-input v-model="ruleForm.insuranceMeasures" placeholder="请填写保险措施"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="演练经费" prop="drillExpense"> + <el-input v-model="ruleForm.drillExpense" placeholder="请填写演练经费"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="备注信息" prop="remark"> + <el-input + v-model="ruleForm.remark" + placeholder="请填写备注信息" + class="input-with-select textarea" + type="textarea" + > + </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20" style="margin-bottom: 0!important;"> + <el-form-item label="预案附件"> + <uploaderFile :fileList="fileList" :systemName="'EMERGENCY'" :disabled="disabled" + @successUploader="successUploader"></uploaderFile> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="resetForm(ruleFormRef)" size="default">关闭</el-button> + <el-button size="default" v-if="disabled == true ? false : true" type="primary" @click="submitForm(titles, ruleFormRef)">确定</el-button> + </span> + </template> + </el-dialog> + <RegionsDialog ref="Shows" @SearchUser="onUser" /> + <DailogSearchUser ref="userRef" @SearchUser="SearchUser" /> + <DailogSearchUser ref="userFZRef" @SearchUser="SearchFZUser" /> + </div> +</template> + +<script lang="ts"> +import { + // reactive, + ref, + defineComponent, + onMounted, +} from 'vue'; + +import type { + UploadUserFile, + FormInstance, +} from 'element-plus' +import { ElMessage } from 'element-plus'; +import { + Search, + FullScreen +} from '@element-plus/icons-vue' +import DailogSearchUser from "/@/components/DailogSearchUser/index.vue" +import RegionsDialog from "/@/views/contingencyManagement/emergencyDrill/releaseOfDrillPlan/component/regionsDialog.vue" +import {releaseDrillPlanApi} from "/@/api/contingencyManagement/emergencyDrillPlan"; +import {goalManagementApi} from "/@/api/goalManagement"; +import { Session } from '/@/utils/storage'; +import uploaderFile from '/@/components/uploaderFile/index.vue'; +export default defineComponent({ + name: 'openAdd', + components: { + RegionsDialog, + DailogSearchUser, + uploaderFile + }, + setup(props, { emit }) { + const isShowDialog = ref(false) + + const ruleFormRef = ref<FormInstance>() + //定义表单 + const ruleForm = ref ({ + makingPlanDate: '', // 计划制定日期 + drillPlanDate: '', //计划演练日期 + makingUserUid: '', //计划制定人ID + makingUserName: '', //计划制定人Name + makingDepartmentId: '', // 计划制定部门ID + planId: '', // 应急预案ID + planName: '', // 应急预案name + departmentId: '', // 主办部门ID + drillExpense: '', // 演练经费 + drillLevel: '', //演练级别 + drillAddress: '', //演练地点 + drillName: '', // 演练名称 + drillWay: '', // 演练方式 + insuranceMeasures: '', // 保险措施 + remark: '', // 备注 + purpose: '', // 演练目的 + fileList: [ + ], + userList: [ + ], + chargeUserList:[], + userListString:'',//演练人员字段(回填使用) + chargeUserListString:'',//演练负责人字段(回填使用) + }); + const titles = ref(); + const disabled = ref(); + // 打开弹窗 + const openDialog = (title: string, id: number, type: boolean) => { + ruleForm.value.makingUserUid = Session.get('uid'); + ruleForm.value.makingUserName = Session.get('realName'); + isShowDialog.value = true; + titles.value = title; + disabled.value = type; + if (title == '查看应急演练计划发布' || title == '修改应急演练计划发布') { + releaseDrillPlanApi() + .seeReleaseDrillPlan(id) + .then((res) => { + if (res.data.code == 200) { + ruleForm.value = res.data.data; + ruleForm.value.userListString='' + ruleForm.value.chargeUserListString='' + for(var a = 0;a<res.data.data.userList.length;a++){ + if(res.data.data.userList[a].type==1){ + ruleForm.value.userListString += res.data.data.userList[a].userName+';' + } + // if(res.data.data.userList[a].type==2){ + // ruleForm.value.chargeUserListString += res.data.data.userList[a].userName+';' + // } + } + // alert(res.data.data.chargeUserList.length) + for(var a = 0;a<res.data.data.chargeUserList.length;a++){ + ruleForm.value.chargeUserListString += res.data.data.chargeUserList[a].userName+';' + } + fileList.value = (res.data.data.fileList?res.data.data.fileList:[]) + initFileListData() + } + }); + } + }; + const initFileListData = async () => { + for(var a = 0;a<fileList.value.length;a++){ + fileList.value[a].name = fileList.value[a].fileName + } + } + // 上传成功组装数据 + const successUploader = (list) =>{ + fileList.value = list + const formFileList = [] + for(var a = 0;a<fileList.value.length;a++){ + formFileList.push( + { + fileName:fileList.value[a].fileName, + fileUrl:'' + } + ) + } + ruleForm.value.fileList = formFileList + } + //日期选择器 + const value1 = ref('') + // 上传附件 + const fileList = ref([]) + // 可选择树 + const treeSelect = ref() + const tree = [ + ] + //部门树 + const department = () => { + goalManagementApi() + .getTreedepartment() + .then((res) => { + if (res.data.code == 200) { + data.value = res.data.data; + } else { + ElMessage.error(res.data.msg); + } + }); + }; + //定义树形下拉框 + const responsibleDepartment = ref() + const data = ref() + const propse = { + label: 'depName', + children: 'children', + value: 'depId', + }; + onMounted(() => { + department(); + }); + // 表单提交验证必填项 + const submitForm = async (title: string, formEl: FormInstance | undefined) => { + if(!ruleForm.value.fileList){ + ruleForm.value.fileList = [] + } + ruleForm.value.userList = ruleForm.value.userList.concat(ruleForm.value.chargeUserList) + delete ruleForm.value.planName + delete ruleForm.value.chargeUserListString + delete ruleForm.value.userListString + delete ruleForm.value.chargeUserList + delete ruleForm.value.gmtModitify + if (title == '新建应急演练计划发布') { + if (!formEl) return; + await formEl.validate((valid, fields) => { + if (valid) { + isShowDialog.value = false; + releaseDrillPlanApi() + .addReleaseDrillPlan(ruleForm.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'success', + }); + emit('myAdd', true); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + emit('myAdd', true); + } + formEl.resetFields(); + }); + } else { + console.log('error submit!', fields); + } + }); + } + else if (title == '修改应急演练计划发布') { + if (!formEl) return; + await formEl.validate((valid, fields) => { + if (valid) { + isShowDialog.value = false; + releaseDrillPlanApi() + .editReleaseDrillPlan(ruleForm.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: '修改成功', + type: 'success', + }); + emit('myAdd', true); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + emit('myAdd', true); + } + formEl.resetFields(); + }); + } else { + console.log('error submit!', fields); + } + }); + formEl.resetFields(); + ruleForm.value = { + makingPlanDate: '', // 计划制定日期 + drillPlanDate: '', //计划演练日期 + makingUserUid: '', //计划制定人ID + makingDepartmentId: '', // 计划制定部门ID + planId: '', // 应急预案ID + planName: '', // 应急预案name + departmentId: '', // 主办部门ID + drillExpense: '', // 演练经费 + drillLevel: '', //演练级别 + drillAddress: '', //演练地点 + drillName: '', // 演练名称 + drillWay: '', // 演练方式 + insuranceMeasures: '', // 保险措施 + remark: '', // 备注 + purpose: '', // 演练目的 + fileList: [ + ], + userList: [ + ], + chargeUserList:[], + userListString:'',//演练人员字段(回填使用) + chargeUserListString:'',//演练负责人字段(回填使用) + }; + } + } + const resetForm = (formEl: FormInstance | undefined) => { + isShowDialog.value = false; + fileList.value=[] + if (!formEl) return; + ruleForm.value = { + makingPlanDate: '', // 计划制定日期 + drillPlanDate: '', //计划演练日期 + makingUserUid: '', //计划制定人ID + makingDepartmentId: '', // 计划制定部门ID + planId: '', // 应急预案ID + planName: '', // 应急预案name + departmentId: '', // 主办部门ID + drillExpense: '', // 演练经费 + drillLevel: '', //演练级别 + drillAddress: '', //演练地点 + drillName: '', // 演练名称 + drillWay: '', // 演练方式 + insuranceMeasures: '', // 保险措施 + remark: '', // 备注 + purpose: '', // 演练目的 + fileList: [ + ], + userList: [ + ], + chargeUserList:[], + userListString:'',//演练人员字段(回填使用) + chargeUserListString:'',//演练负责人字段(回填使用) + }; + formEl.resetFields(); + }; + // 应急队伍弹窗 + const Shows=ref() + const daiInpt = () => { + Shows.value.openDailog() + } + const onUser = (e:any) => { + ruleForm.value.planId=e.id + ruleForm.value.planName=e.name + }; + // 打开用户选择弹窗 + const userRef = ref(); + const userFZRef = ref(); + //打开演练人员和演练负责人弹窗 type 0 演练人员 1 演练负责人 + const openUser = (type:number) => { + if(type==0){ + userRef.value.openDailog(0); + }else if(type==1){ + userFZRef.value.openDailog(0); + } + }; + const SearchUser = (e:any) => { + console.log('演练人员',e) + ruleForm.value.userListString='' + ruleForm.value.userList=[] + for(var a = 0;a<e.length;a++){ + ruleForm.value.userList.push( + { + type: 1, + userName: e[a].realName, + userUid: e[a].uid, + } + ) + ruleForm.value.userListString+=e[a].realName+';' + } + }; + const SearchFZUser = (e:any) => { + console.log('演练负责人员',e[0].userName) + ruleForm.value.chargeUserListString='' + ruleForm.value.chargeUserList=[] + // ruleForm.value.chargeUserList = [] + for(var a = 0;a<e.length;a++){ + ruleForm.value.chargeUserList.push( + { + type: 2, + userName: e[a].realName, + userUid: e[a].uid, + } + ) + ruleForm.value.chargeUserListString+=e[a].realName+';' + } + }; + // 计划定制日期 + const datetime = ref(''); + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + return { + openDialog, + isShowDialog, + fileList, + responsibleDepartment, + data, + department, + propse, + Search, + ruleForm, + value1, + treeSelect, + tree, + daiInpt, + Shows, + ruleFormRef, + submitForm, + openUser, + userRef, + datetime, + toggleFullscreen, + FullScreen, + full, + titles, + disabled, + resetForm, + emit, + onUser, + userFZRef, + SearchUser, + SearchFZUser, + successUploader, + initFileListData + }; + }, +}); +</script> +<style scoped lang="scss"> +.textarea{ + height: 168px!important; +} +.textarea ::v-deep .el-textarea__inner{ + height: 168px!important; +} +::v-deep .el-table__cell { + font-weight: 400; +} +.el-divider--horizontal{ + height: 0; + margin: 0; + border-top: transparent; +} +.el-select{ + width: 100%; +} +//多行文本框 +.textarea{ + height: 70px!important; +} +.textarea ::v-deep .el-textarea__inner{ + height: 70px!important; +} +//弹窗底部边框线 +::v-deep .el-dialog__footer{ + border-top: 1px solid #e8e8e8; + border-radius: 0 0 4px 4px; +} +//弹窗顶部边框线 +::v-deep .el-dialog__header { + border-bottom: 1px solid #e8e8e8; + margin-right: 0; + border-radius: 4px 4px 0 0; +} +</style> \ No newline at end of file diff --git a/src/views/contingencyManagement/emergencyDrill/releaseOfDrillPlan/component/regionsDialog.vue b/src/views/contingencyManagement/emergencyDrill/releaseOfDrillPlan/component/regionsDialog.vue new file mode 100644 index 0000000..07a7b7b --- /dev/null +++ b/src/views/contingencyManagement/emergencyDrill/releaseOfDrillPlan/component/regionsDialog.vue @@ -0,0 +1,223 @@ +<template> + <el-dialog v-model="dialogVisible" title="选择应急预案" width="900px" draggable :fullscreen="full" @close="closeDialog"> + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-row> + <el-col :span="18"> + <el-row> + <el-col :span="24"> + <el-form ref="ruleFormRef" :inline="true" :model="ruleForm" status-icon> + <el-form-item> + <el-input size="default" v-model="listQuery.searchParams.name" placeholder="预案名称" style="max-width: 215px;margin-right: 12px;" /> + </el-form-item> + <el-form-item> + <el-button size="default" type="primary" @click="onSubmit">查询</el-button> + <el-button size="default" @click="submitReset">重置</el-button> + </el-form-item> + </el-form> + </el-col> + <el-col :span="24"> + <el-button size="default" :icon="Delete" style="margin-top: 15px">清除选择</el-button> + </el-col> + </el-row> + <el-table + :data="tableData" + style="width: 100%; + margin-top: 20px" + @cell-click="radio" + > + <el-table-column width="55"> + <template #default="scope"> + <el-radio-group v-model="radio1"> + <el-radio :label="scope.row" size="large">{{ null }}</el-radio> + </el-radio-group> + </template> + </el-table-column> + <el-table-column align="center" prop="name" label="预案名称" /> + </el-table> + <div class="pages"> + <el-pagination + v-model:currentPage="pageIndex" + v-model:page-size="pageSize" + :page-sizes="[10, 20, 30]" + layout="total, sizes, prev, pager, next, jumper" + :total="total" + @size-change="onHandleSizeChange" + @current-change="onHandleCurrentChange" + /> + </div> + </el-col> + <el-col :span="6"> + <div v-if="dynamicTags[0] == '' ? false : true"> + <el-tag + v-for="tag in dynamicTags" + :key="tag" + class="mx-1" + style="margin: 5px" + closable + :disable-transitions="false" + @close="handleClose(tag)" + > + {{ tag.name }} + </el-tag> + </div> + </el-col> + </el-row> + <template #footer> + <span class="dialog-footer"> + <el-button @click="dialogVisible = false" size="default">关闭</el-button> + <el-button type="primary" @click="submitForm" size="default">确定</el-button> + </span> + </template> + </el-dialog> +</template> +<script lang="ts"> +import { defineComponent, reactive, ref, onMounted } from 'vue'; +import { ElMessage } from 'element-plus'; +import { Delete, FullScreen } from '@element-plus/icons-vue'; +import { emergencyPlanApi } from '/@/api/contingencyManagement/emergencyPlan'; +export default defineComponent({ + setup(props, { emit }) { + const dialogVisible = ref<boolean>(false); + const openDailog = () => { + dialogVisible.value = true; + onSubmit() + }; + // 搜索条件 + const listQuery = reactive({ + pageIndex: 1, + pageSize: 10, + searchParams: { + name: "", type: "", abolishStatus: false + }, + }); + // 定义表格数据 + const tableData = ref([]); + // 重置 + const submitReset = () => { + listQuery.searchParams.name = ''; + onSubmit(); + }; + + // 列表请求数据 + const onSubmit = async () => { + let res = await emergencyPlanApi().getEmergencyPlanList(listQuery); + if (res.data.code === '200') { + tableData.value = res.data.data; + pageIndex.value = res.data.pageIndex; + pageSize.value = res.data.pageSize; + total.value = res.data.total; + } else { + ElMessage({ + showClose: true, + type: 'error', + message: res.data.msg, + }); + } + }; + // 分页 + const pageIndex = ref(); + const pageSize = ref(); + const total = ref(); + // 分页改变 + const onHandleSizeChange = (val: number) => { + listQuery.pageSize = val; + }; + // 分页未改变 + const onHandleCurrentChange = (val: number) => { + listQuery.pageIndex = val; + }; + // 右方点击添加后显示标签 + const dynamicTags = ref(['']); + const handleClose = (tag: string) => { + dynamicTags.value.splice(dynamicTags.value.indexOf(tag), 1); + radio1.value = ''; + }; + const closeDialog = () =>{ + handleClose('') + } + const radio1 = ref(''); + const radio = (event: any) => { + dynamicTags.value[0] = event; + }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + + const submitForm = () => { + let obj = JSON.parse(JSON.stringify(dynamicTags.value)); + emit('SearchUser', obj[0]); + dialogVisible.value = false; + }; + onMounted(() => { + onSubmit(); + }); + return { + dialogVisible, + openDailog, + tableData, + pageSize, + pageIndex, + onHandleSizeChange, + onHandleCurrentChange, + dynamicTags, + handleClose, + Delete, + radio1, + radio, + toggleFullscreen, + FullScreen, + full, + submitReset, + onMounted, + listQuery, + onSubmit, + submitForm, + closeDialog + }; + }, +}); +</script> +<style scoped> +.el-form--inline .el-form-item { + margin-bottom: 0; + margin-right: 0; +} +/*分页*/ +.pages { + margin-top: 15px; +} +::v-deep .el-pagination .el-pager li { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +::v-deep .el-pagination .el-pager li.is-active { + background-color: #409eff; + color: #fff; +} +::v-deep .el-pagination .btn-prev { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +::v-deep .el-pagination button:disabled { + color: #c0c4cc; +} +::v-deep .el-pagination .btn-next { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +</style> diff --git a/src/views/contingencyManagement/emergencyDrill/releaseOfDrillPlan/index.vue b/src/views/contingencyManagement/emergencyDrill/releaseOfDrillPlan/index.vue new file mode 100644 index 0000000..b1a7099 --- /dev/null +++ b/src/views/contingencyManagement/emergencyDrill/releaseOfDrillPlan/index.vue @@ -0,0 +1,404 @@ +<template> + <div class="system-user-container"> + <el-card shadow="hover"> + <div class="button_Line"> + <div class="button_Left mb15"> + <el-button size="default" type="primary" @click="onOpenAdd"> + <el-icon> + <Plus /> + </el-icon>新建 + </el-button> + <el-button size="default" type="danger" plain :disabled="danger" @click="onDeleteAll"> + <el-icon> + <Delete /> + </el-icon>删除 + </el-button> + </div> + <div class="button_Right"> +<!-- <el-button @click="upButton">--> +<!-- <el-icon>--> +<!-- <Upload />--> +<!-- </el-icon>--> +<!-- </el-button>--> +<!-- <el-button>--> +<!-- <el-icon>--> +<!-- <Download />--> +<!-- </el-icon>--> +<!-- </el-button>--> +<!-- <el-button>--> +<!-- <el-icon>--> +<!-- <Refresh />--> +<!-- </el-icon>--> +<!-- </el-button>--> + </div> + </div> + <el-table + :data="tableData" + style="width: 100%" + ref="multipleTableRef" + @selection-change="handleSelectionChange" + > + <el-table-column + type="selection" + width="55" + /> + <el-table-column prop="drillName" label="演练名称" show-overflow-tooltip sortable></el-table-column> + <el-table-column prop="drillAddress" label="演练地点" show-overflow-tooltip sortable></el-table-column> + <el-table-column prop="drillWay" label="演练方式" show-overflow-tooltip sortable> + <template #default="scope"> + <span v-if="scope.row.drillWay == 1">综合</span> + <span v-if="scope.row.drillWay == 2">桌面</span> + <span v-if="scope.row.drillWay == 3">专项</span> + </template> + </el-table-column> + <el-table-column prop="drillLevel" label="演练级别" show-overflow-tooltip sortable> + <template #default="scope"> + <span v-if="scope.row.drillLevel == 1">公司级</span> + <span v-if="scope.row.drillLevel == 2">分厂级</span> + <span v-if="scope.row.drillLevel == 3">车间级</span> + </template> + </el-table-column> + <el-table-column prop="drillPlanDate" label="计划演练日期" show-overflow-tooltip sortable></el-table-column> + <el-table-column prop="gmtModitify" label="修改时间" show-overflow-tooltip sortable></el-table-column> + <el-table-column label="操作" width="260" align="center"> + <template #default="scope"> + <!--<el-button size="small" text type="primary" @click="releaseOfDrillPlan(0)">--> + <!--<el-icon style="margin-right: 5px;">--> + <!--<VideoPlay />--> + <!--</el-icon>启动--> + <!--</el-button>--> + <el-button size="small" text type="primary" @click="onEdit('详情',scope.row.id)"> + <el-icon style="margin-right: 5px;"> + <View /> + </el-icon>查看 + </el-button> + <el-button size="small" text type="primary" @click="onEdit('修改',scope.row.id)"> + <el-icon style="margin-right: 5px;"> + <EditPen /> + </el-icon>修改 + </el-button> + <el-button size="small" text type="primary" @click="onRowDel(scope.row.id)"> + <el-icon> + <Delete /> + </el-icon>删除 + </el-button> + </template> + </el-table-column> + </el-table> + <div class="pages"> + <el-pagination + v-if="tableData.length == 0 ? false : true" + v-model:currentPage="pageIndex" + v-model:page-size="pageSize" + :page-sizes="[10, 20, 30]" + :pager-count="5" + layout="total, sizes, prev, pager, next, jumper" + :total="total" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + </el-card> + <OpenAdd ref="addRef" @myAdd="onMyAdd"/> +<!-- <FlowChart ref="flowRef"></FlowChart>--> + <upData ref="upShow"></upData> + </div> +</template> + +<script lang="ts"> +import { + // toRefs, + reactive, + onMounted, + ref, + defineComponent +} from 'vue'; +import { + ElMessageBox, + ElMessage, + // ElTable, +} from 'element-plus'; +import { + Plus, + Delete, + // Upload, + // Download, + // Refresh, + View, + VideoPlay, + EditPen, +} from '@element-plus/icons-vue' +import {useRouter} from "vue-router" +import OpenAdd from '/@/views/contingencyManagement/emergencyDrill/releaseOfDrillPlan/component/openAdd.vue'; +// import FlowChart from '/@/views/contingencyManagement/emergencyDrill/releaseOfDrillPlan/component/flowChart.vue'; +import UpData from '/@/views/contingencyManagement/panManagement/component/upData.vue'; +import { releaseDrillPlanApi } from '/@/api/contingencyManagement/emergencyDrillPlan'; + +export default defineComponent({ + name: 'systemUser', + components: { + OpenAdd, + EditPen, + Plus, + View, + Delete, + // Upload, + // Download, + // Refresh, + VideoPlay, + UpData, + // FlowChart, + }, + setup() { + // 列表参数 + const listQuery = reactive({ + pageIndex: 1, + pageSize: 10, + searchParams: { + drillName: '' + }, + }); + // 定义表格数据 + const tableData = ref([]); + // 列表数据请求 + const listApi = async () => { + let res = await releaseDrillPlanApi().getReleaseDrillPlanList(listQuery); + if (res.data.code == 200) { + tableData.value = res.data.data; + pageIndex.value = res.data.pageIndex; + pageSize.value = res.data.pageSize; + total.value = res.data.total; + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + } + }; + onMounted(() => { + listApi(); + }); + // 上传 + // const upShow=ref() + // const upButton=()=>{ + // upShow.value.openDialog() + // } + + // 打开新增弹窗 + const addRef = ref(); + const onOpenAdd = () => { + addRef.value.openDialog('新建应急演练计划发布',false); + }; + // 新增后刷新 + const onMyAdd = (e: boolean) => { + if (e) { + listApi(); + } else { + listApi(); + } + }; + // 打开修改用户弹窗 + const onEdit = (val: string, row: object) => { + if (val == '详情') { + addRef.value.openDialog('查看应急演练计划发布',row,true); + } else { + addRef.value.openDialog('修改应急演练计划发布',row,false); + } + }; + // 打开修改用户弹窗 + // const flowRef = ref(); + // const onflowChart = (row: TableDataRow) => { + // flowRef.value.openDialog(row); + // }; + // 删除 + const onRowDel = (id: number) => { + let arr = []; + arr.push(id) + ElMessageBox.confirm('确定删除所选项吗?', '提示',{ + confirmButtonText: '确认', + cancelButtonText: '取消', + type: 'warning', + }).then(() => { + releaseDrillPlanApi() + .deleteReleaseDrillPlan(arr) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'success', + }); + listApi(); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + listApi(); + } + }); + }) + .catch(() => {}); + }; + // 多选删除 + const onDeleteAll = () => { + ElMessageBox.confirm('确定删除所选项吗?', '提示', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + releaseDrillPlanApi() + .deleteReleaseDrillPlan(deletAll.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'success', + }); + listApi(); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + listApi(); + } + }); + }) + .catch(() => {}); + }; + // 分页 + const pageIndex = ref(); + const pageSize = ref(); + const total = ref(); + // 分页改变 + const handleSizeChange = (val: number) => { + listQuery.pageSize = val; + listApi(); + }; + // 分页未改变 + const handleCurrentChange = (val: number) => { + listQuery.pageIndex = val; + listApi(); + }; + const danger = ref(true); + const deletAll = ref(); + const handleSelectionChange = (val: any) => { + let valId = JSON.parse(JSON.stringify(val)); + let arr = []; + for (let i = 0; i < valId.length; i++) { + arr.push(valId[i].id); + } + deletAll.value = arr; + // console.log(deletAll.value); + if (val.length == 1) { + danger.value = false; + } else if (val.length == 0) { + danger.value = true; + } else { + danger.value = false; + } + }; + + // 启动跳转 + const router=useRouter() + const releaseOfDrillPlan=(data:string)=>{ + router.push({ + path:"/releaseOfDrillStart", + query:{ + type:data + } + }) + } + return { + // upButton, + // upShow, + tableData, + // onflowChart, + // flowRef, + onOpenAdd, //新增 + addRef, + onRowDel, + View , + pageIndex, + listQuery, + pageSize, + handleSizeChange, + handleCurrentChange, + router, + releaseOfDrillPlan, + listApi, + danger, + deletAll, + handleSelectionChange, + onMyAdd, + onDeleteAll, + onEdit, + total, + }; + }, +}); +</script> +<style scoped lang="scss"> +.table_Box{ + padding: 20px; + background-color: #fff; +} +.tableForm{ + margin-top: 10px; +} +/*按钮行*/ +.button_Line{ + display: flex; + flex-direction: row; + justify-content: space-between; +} +//表头 +::v-deep .el-table th.el-table__cell { + background-color: #f6f7fa; + font-weight: 400; + color: #909399; +} +.el-table .sort-caret.ascending{ + border-bottom-color: #c0c4cc; +} +//分页 +.pages{ + display: flex; + justify-content: flex-end; + margin-top: 15px; +} +::v-deep .el-pagination .el-pager li { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +::v-deep .el-pagination .el-pager li.is-active { + background-color: #409eff; + color: #fff; +} +::v-deep .el-pagination .btn-prev { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +::v-deep .el-pagination button:disabled{ + color: #c0c4cc; +} +::v-deep .el-pagination .btn-next{ + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +</style> \ No newline at end of file diff --git a/src/views/contingencyManagement/emergencyDrillStatistics/index.vue b/src/views/contingencyManagement/emergencyDrillStatistics/index.vue new file mode 100644 index 0000000..a219fea --- /dev/null +++ b/src/views/contingencyManagement/emergencyDrillStatistics/index.vue @@ -0,0 +1,359 @@ +<template> + <div> + <div class="echart"> + <h2 class="title">距上次应急演练结束{{day}}天</h2> + <el-form :model="form" label-width="20px"> + <el-row> + <el-col :span="4" :offset="15"> + <el-form-item size="default"> + <el-tree-select v-model="form.deptId" :data="data" @change="eaclick" placeholder="选择部门" :props="propse" style="width: 100%" /> + </el-form-item> + </el-col> + <el-col :span="4"> + <el-form-item size="default"> + <el-select v-model="form.type" placeholder="年/月" @change="eaclick" style="width:100%"> + <el-option label="年" :value="1" /> + <el-option label="月" :value="2" /> + </el-select> + </el-form-item> + </el-col> + </el-row> + </el-form> + <div ref="main" style="width: 100%; height: 300px"></div> + <div style="width: 100%; padding-left: 20px"> + <el-select v-model="params.searchParams.classification" style="width: 200px" + placeholder="请选择物资分类" @change="emergencySuppliesCount"> + <el-option label="事故气体吸收装置" value="1"></el-option> + <el-option label="通讯设施" value="2"></el-option> + <el-option label="交通运输工具" value="3"></el-option> + <el-option label="照明装置" value="4"></el-option> + <el-option label="防护器材" value="5"></el-option> + <el-option label="其它" value="6"></el-option> + </el-select> + <div class="pie-body"> + <div class="pie-item" ref="echarts0"> + </div> + <div class="pie-item" ref="echarts1"> + </div> + <div class="pie-item" ref="echarts2"> + </div> + <div class="pie-item" ref="echarts3"> + </div> + <div class="pie-item" ref="echarts4"> + </div> + <ArrowLeftBold class="pie-left" :class="disabledLeft" @click="leftClick" /> + <ArrowRightBold class="pie-right" :class="disabledRight" @click="rightClick" /> + </div> + </div> + </div> + </div> +</template> +<script lang="ts"> +import { defineComponent, onMounted, ref } from 'vue'; +import * as echarts from 'echarts'; +import { ElMessage } from 'element-plus'; +import { ArrowLeftBold, ArrowRightBold } from '@element-plus/icons-vue'; +import { goalManagementApi } from '/@/api/goalManagement'; +import { toNamespacedPath } from 'path/posix'; +import { deepClone } from '/@/utils/other'; +export default defineComponent({ + components: { + ArrowLeftBold, + ArrowRightBold, + }, + setup() { + const params = ref({ + pageIndex:1, + pageSize:5, + searchParams:{ + classification:'' + } + }) + const list = ref([]) + + const leftClick = () => { + params.value.pageIndex-- + emergencySuppliesCount() + initPies() + } + const rightClick = () => { + params.value.pageIndex++ + emergencySuppliesCount() + initPies() + } + const disabledLeft = ref() + const disabledRight = ref() + //加载数据 + const emergencySuppliesCount = () => { + goalManagementApi() + .emergencySuppliesCount(params.value) + .then((res) => { + if (res.data.code == 200) { + list.value = res.data.data; + initPies() + //禁用左右按钮 + if(res.data.pageIndex==1){ + disabledLeft.value = 'disabled-pie' + }else{ + disabledLeft.value = '' + } + if(res.data.pageIndex==res.data.pages){ + disabledRight.value = 'disabled-pie' + }else{ + disabledRight.value = '' + } + } else { + ElMessage.error(res.data.msg); + } + }); + }; + const echarts0 = ref() + const echarts1 = ref() + const echarts2 = ref() + const echarts3 = ref() + const echarts4 = ref() + const initPies = () => { + var myChart0 = echarts.init(echarts0.value); + var myChart1 = echarts.init(echarts1.value); + var myChart2 = echarts.init(echarts2.value); + var myChart3 = echarts.init(echarts3.value); + var myChart4 = echarts.init(echarts4.value); + myChart0.clear() + myChart1.clear() + myChart2.clear() + myChart3.clear() + myChart4.clear() + for(var a = 0;a<list.value.length;a++){ + var option = { + tooltip: { + trigger: 'item', + show:false + }, + color:['#24c548'], + title: { + text: list.value[a].name+'\n\n'+list.value[a].totalNum, + x: '49%', + y: '35%', + textAlign:'center', + textStyle: { + color: '#24c548', + fontSize: 19, + fontWeight: "bold", + fontFamily:'D-DIN', + textShadowColor:'red' + }, + }, + series: [ + { + name: null, + type: 'pie', + radius: ['80%', '90%'], + avoidLabelOverlap: false, + itemStyle: { + borderRadius: 10, + borderColor: '#fff', + borderWidth: 0 + }, + label: { + show: false, + position: 'center' + }, + labelLine: { + show: false + }, + data: [ + { value: list.value[a].totalNum, name: list.value[a].name }, + ] + } + ] + }; + + + if(a==0){ + var option0 = deepClone(option) + option0.color = ['#24c548'] + option0.title.textStyle.color = '#24c548' + myChart0.setOption(option0, true); + } + if(a==1){ + var option1 = deepClone(option) + option1.color = ['#e7bd27'] + option1.title.textStyle.color = '#e7bd27' + myChart1.setOption(option1, true); + } + if(a==2){ + var option2 = deepClone(option) + option2.color = ['#e65c3e'] + option2.title.textStyle.color = '#e65c3e' + myChart2.setOption(option2, true); + } + if(a==3){ + var option3 = deepClone(option) + option3.color = ['#8e66e7'] + option3.title.textStyle.color = '#8e66e7' + myChart3.setOption(option3, true); + } + if(a==4){ + var option4 = deepClone(option) + option4.color = ['#28b8d6'] + option4.title.textStyle.color = '#28b8d6' + myChart4.setOption(option4, true); + } + } + + }; + + const form = ref({ + type:1, + deptId:1 + }); + //部门 + const department = () => { + goalManagementApi() + .getTreedepartment() + .then((res) => { + if (res.data.code == 200) { + data.value = res.data.data; + } else { + ElMessage.error(res.data.msg); + } + }); + }; + const propse = { + label: 'depName', + children: 'children', + value: 'depId', + }; + const eaclick=()=>{ + listApi() + } + onMounted(() => { + listApi() + department(); + emergencySuppliesCount() + }); + const day=ref(0) + const listApi=()=>{ + goalManagementApi().emergencyStat(form.value).then(res=>{ + if(res.data.code==200){ + day.value=res.data.data.days + let date=[] + let names=[] + res.data.data.dataList.forEach(item => { + date.push(item.num) + names.push(item.name) + }); + init(date,names) + } + }) + } + const main = ref(); + const init = (data: any,names:any) => { + var myChart = echarts.init(main.value); + var option = { + tooltip: {}, + grid: { + left: '3%', + right: '4%', + bottom: '5%', + containLabel: true, + }, + xAxis: { + type: 'category', + data: names, + }, + yAxis: { + type: 'value', + name: '次数', + nameTextStyle: { + color: '#aaa', + nameLocation: 'start', + }, + }, + color: ['#6394f9'], + series: [ + { + data: data, + barWidth : 40, + type: 'bar', + }, + ], + }; + + myChart.setOption(option); + }; + const data = ref([]) + return { + form, + main, + init, + data, + department, + propse, + listApi, + eaclick, + day, + list, + emergencySuppliesCount, + params, + initPies, + leftClick, + rightClick, + echarts0, + echarts1, + echarts2, + echarts3, + echarts4, + disabledRight, + disabledLeft + }; + }, +}); +</script> +<style scoped> +.title{ + text-align: center; + padding: 20px 0; +} +.echart { + background-color: #fff; + border-radius: 5px; +} +.el-form { + padding: 20px 0; +} + .pie-body{ + width: 50%; + height: 370px; + display: flex; + justify-content: space-around; + flex-wrap: wrap; + position: relative; + } + .pie-item{ + width: 32%; + height: 48%; + margin-right: 1%; + margin-bottom: 1%; + } + .pie-left{ + position: absolute; + width: 30px; + height: 30px; + left: 0; + top: 48%; + cursor: pointer; + } + .pie-right{ + position: absolute; + width: 30px; + height: 30px; + right: 0; + top: 48%; + cursor: pointer; + } + .disabled-pie{ + pointer-events:none; + color: #9b9da1; + } +</style> diff --git a/src/views/contingencyManagement/emergencyPlanStartRecord/component/openSee.vue b/src/views/contingencyManagement/emergencyPlanStartRecord/component/openSee.vue new file mode 100644 index 0000000..e550b77 --- /dev/null +++ b/src/views/contingencyManagement/emergencyPlanStartRecord/component/openSee.vue @@ -0,0 +1,195 @@ +<template> + <div class="system-edit-user-container"> + <el-dialog + :title="titles" + v-model="isShowDialog" + width="769px" + draggable + :fullscreen="full" + > + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-form + ref="ruleFormRef" + :model="ruleForm" + size="default" + label-width="120px" + :disabled="disabled" + > + <el-row :gutter="35"> + <el-col :xs="12" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="应急预案" prop="planName" > + <el-input + v-model="ruleForm.planName" + placeholder="请选择" + class="input-with-select" + disabled + > + <template #append> + <el-button :icon="Search" disabled @click="openUser"/> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :xs="12" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="备注"> + <el-input + class="textarea" + v-model="ruleForm.remark" + type="textarea" + maxlength="150" + placeholder="请填写备注" + ></el-input> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button size="default" @click="resetForm(ruleFormRef)">关闭</el-button> + <el-button size="default" v-if="disabled == true ? false : true" type="primary" @click="submitForm(titles, ruleFormRef)">确定</el-button> + </span> + </template> + </el-dialog> + <DailogSearchUser ref="userRef" @SearchUser="onUser"/> + <AddEmergencyPersonnel ref="addRef" /> + </div> +</template> + +<script lang="ts"> +import { + ref, + defineComponent +} from 'vue'; +import type { + FormInstance, +} from 'element-plus' +import { ElMessage } from 'element-plus'; +import { + Search, + FullScreen +} from '@element-plus/icons-vue' +import DailogSearchUser from "/@/components/DailogSearchUser/index.vue" +import AddEmergencyPersonnel from "/@/views/contingencyManagement/contingency/component/addEmergencyPersonnel.vue"; +import {emergencyPlanLogApi} from "/@/api/contingencyManagement/emergencyPlanLog"; + +export default defineComponent({ + name: 'openEdit', + components: { + DailogSearchUser, + AddEmergencyPersonnel, + }, + setup(props, { emit }) { + const isShowDialog = ref(false); + + const ruleFormRef = ref<FormInstance>(); + const ruleForm= ref({ + planId: '', //应急预案人员 + remark: '', // 备注 + }) + const titles = ref(); + const disabled = ref(); + + // 打开用户选择弹窗 + const userRef = ref(); + const openUser = () => { + userRef.value.openDailog(); + }; + const onUser = (e:any) => { + ruleForm.value.planId=e.id + }; + // 打开弹窗 + const openDialog = (title: string, id: number, type: boolean) => { + isShowDialog.value = true; + titles.value = title; + disabled.value = type; + if (title == '查看应急预案启动记录' || title == '修改应急预案启动记录') { + emergencyPlanLogApi() + .seeEmergencyPlanLog(id) + .then((res) => { + if (res.data.code == 200) { + ruleForm.value = res.data.data; + } + }); + } + }; + // 表单提交验证必填项 + const submitForm = async (title: string, formEl: FormInstance | undefined) => { + if (title == '修改应急预案启动记录') { + if (!formEl) return; + await formEl.validate((valid, fields) => { + if (valid) { + isShowDialog.value = false; + emergencyPlanLogApi() + .editEmergencyPlanLog(ruleForm.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: '修改成功', + type: 'success', + }); + emit('myAdd', true); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + emit('myAdd', true); + } + formEl.resetFields(); + }); + } else { + console.log('error submit!', fields); + } + }); + formEl.resetFields(); + ruleForm.value = { + planId: '', //应急预案人员 + remark: '', // 备注 + }; + } + }; + const resetForm = (formEl: FormInstance | undefined) => { + isShowDialog.value = false; + if (!formEl) return; + formEl.resetFields(); + }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + return { + openDialog, + Search, + ruleFormRef, + openUser, + userRef, + toggleFullscreen, + FullScreen, + full, + titles, + disabled, + emit, + ruleForm, + submitForm, + resetForm, + isShowDialog, + onUser, + }; + }, +}); +</script> +<style scoped lang="scss"> +.textarea{ + height: 50px!important; +} +.textarea ::v-deep .el-textarea__inner{ + height: 50px!important; +} +</style> \ No newline at end of file diff --git a/src/views/contingencyManagement/emergencyPlanStartRecord/component/selectEmergencyPlan.vue b/src/views/contingencyManagement/emergencyPlanStartRecord/component/selectEmergencyPlan.vue new file mode 100644 index 0000000..9fe5f86 --- /dev/null +++ b/src/views/contingencyManagement/emergencyPlanStartRecord/component/selectEmergencyPlan.vue @@ -0,0 +1,246 @@ +<template> + <el-dialog v-model="dialogVisible" title="选择应急预案" width="900px" draggable :fullscreen="full" @close="closeDialog"> + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-row> + <el-col :span="18"> + <el-row> + <el-col :span="24"> + <el-form ref="ruleFormRef" :inline="true" :model="ruleForm" status-icon> + <el-form-item> + <el-input size="default" v-model="listQuery.searchParams.name" placeholder="预案名称" style="max-width: 215px" /> + </el-form-item> + <el-form-item> + <el-select + size="default" + v-model="listQuery.searchParams.type" + placeholder="请选择预案类型" + class="ml10" + style="max-width: 215px; margin-right: 12px" + > + <el-option label="综合应急预案" value="1"></el-option> + <el-option label="现场处置方案" value="2"></el-option> + <el-option label="专项应急预案" value="3"></el-option> + <el-option label="其他预案" value="4"></el-option> + </el-select> + </el-form-item> + <el-form-item> + <el-button size="default" type="primary" @click="onSubmit">查询</el-button> + <el-button size="default" @click="submitReset">重置</el-button> + </el-form-item> + </el-form> + </el-col> + <el-col :span="24"> + <el-button size="default" :icon="Delete" @click="submitReset" style="margin-top: 15px">清除选择</el-button> + </el-col> + </el-row> + <el-table :data="tableData" style="width: 100%; margin-top: 20px" @cell-click="radio"> + <el-table-column width="55"> + <template #default="scope"> + <el-radio-group v-model="radio1"> + <el-radio :label="scope.row" size="large">{{ null }}</el-radio> + </el-radio-group> + </template> + </el-table-column> + <el-table-column align="center" prop="name" label="预案名称" /> + <el-table-column align="center" prop="type" label="预案类型"> + <template #default="scope"> + <span v-if="scope.row.type == '1'">综合应急预案</span> + <span v-if="scope.row.type == '2'">现场处置方案</span> + <span v-if="scope.row.type == '3'">专项应急预案</span> + <span v-if="scope.row.type == '4'">其他预案</span> + </template> + </el-table-column> + </el-table> + <div class="pages"> + <el-pagination + v-model:currentPage="pageIndex" + v-model:page-size="pageSize" + :page-sizes="[10, 20, 30]" + layout="total, sizes, prev, pager, next, jumper" + :total="total" + @size-change="onHandleSizeChange" + @current-change="onHandleCurrentChange" + /> + </div> + </el-col> + <el-col :span="6"> + <div v-if="dynamicTags[0] == '' ? false : true"> + <el-tag + v-for="tag in dynamicTags" + :key="tag" + class="mx-1" + style="margin: 5px" + closable + :disable-transitions="false" + @close="handleClose(tag)" + > + {{ tag.name }} + </el-tag> + </div> + </el-col> + </el-row> + <template #footer> + <span class="dialog-footer"> + <el-button @click="dialogVisible = false" size="default">关闭</el-button> + <el-button type="primary" @click="submitForm" size="default">确定</el-button> + </span> + </template> + </el-dialog> +</template> +<script lang="ts"> +import { defineComponent, reactive, ref, onMounted } from 'vue'; +import { ElMessage } from 'element-plus'; +import { Delete, FullScreen } from '@element-plus/icons-vue'; +import { emergencyPlanLogApi } from '/@/api/contingencyManagement/emergencyPlanLog'; +import { emergencyPlanApi } from '/@/api/contingencyManagement/emergencyPlan'; +export default defineComponent({ + setup(props, { emit }) { + const dialogVisible = ref<boolean>(false); + const openDailog = () => { + dialogVisible.value = true; + onSubmit(); + }; + // 搜索条件 + const listQuery = reactive({ + pageIndex: 1, + pageSize: 10, + searchParams: { + name: '', + type: '', + abolishStatus: false, + }, + }); + // 定义表格数据 + const tableData = ref([]); + // 请求列表数据 + const onSubmit = async () => { + let res = await emergencyPlanApi().getEmergencyPlanList(listQuery); + if (res.data.code === '200') { + tableData.value = res.data.data; + pageIndex.value = res.data.pageIndex; + pageSize.value = res.data.pageSize; + total.value = res.data.total; + } else { + ElMessage({ + showClose: true, + type: 'error', + message: res.data.msg, + }); + } + }; + // 重置 + const submitReset = () => { + listQuery.searchParams.name = ''; + listQuery.searchParams.type = ''; + radio1.value="" + dynamicTags.value[0]="" + onSubmit(); + }; + // 分页 + const pageIndex = ref(); + const pageSize = ref(); + const total = ref(); + // 分页改变 + const onHandleSizeChange = (val: number) => { + listQuery.pageSize = val; + }; + // 分页未改变 + const onHandleCurrentChange = (val: number) => { + listQuery.pageIndex = val; + }; + // 右方点击添加后显示标签 + const dynamicTags = ref(['']); + const handleClose = (tag: string) => { + dynamicTags.value.splice(dynamicTags.value.indexOf(tag), 1); + radio1.value = ''; + }; + const closeDialog = () => { + handleClose('') + } + const radio1 = ref(''); + const radio = (event: any) => { + dynamicTags.value[0] = event; + }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + + const submitForm = () => { + let obj = JSON.parse(JSON.stringify(dynamicTags.value)); + emit('SearchUser', obj[0]); + dialogVisible.value = false; + }; + onMounted(() => { + onSubmit(); + }); + return { + dialogVisible, + openDailog, + tableData, + pageSize, + pageIndex, + onHandleSizeChange, + onHandleCurrentChange, + dynamicTags, + handleClose, + Delete, + radio1, + radio, + toggleFullscreen, + FullScreen, + full, + submitReset, + onMounted, + listQuery, + onSubmit, + submitForm, + total, + closeDialog + }; + }, +}); +</script> +<style scoped> +.el-form--inline .el-form-item { + margin-bottom: 0; + margin-right: 0; +} +/*分页*/ +.pages { + margin-top: 15px; +} +::v-deep .el-pagination .el-pager li { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +::v-deep .el-pagination .el-pager li.is-active { + background-color: #409eff; + color: #fff; +} +::v-deep .el-pagination .btn-prev { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +::v-deep .el-pagination button:disabled { + color: #c0c4cc; +} +::v-deep .el-pagination .btn-next { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +</style> diff --git a/src/views/contingencyManagement/emergencyPlanStartRecord/index.vue b/src/views/contingencyManagement/emergencyPlanStartRecord/index.vue new file mode 100644 index 0000000..1ce636f --- /dev/null +++ b/src/views/contingencyManagement/emergencyPlanStartRecord/index.vue @@ -0,0 +1,408 @@ +<template> + <div class="system-user-container"> + <el-card shadow="hover"> + <div class="system-user-search mb15"> + <el-form + size="default" + label-width="80px" + :inline="true" + > + <el-form-item prop="telephone" > + <el-input + v-model="listQuery.searchParams.planName" + placeholder="请选择应急预案" + class="input-with-select" + > + <template #append> + <el-button :icon="Search" @click="daiInpt"/> + </template> + </el-input> + </el-form-item> + <el-button size="default" type="primary" class="ml10" @click="onSubmit"> + 查询 + </el-button> + <el-button size="default" class="ml10" @click="submitReset"> + 重置 + </el-button> + </el-form> + </div> + <div class="button_Line"> + <div class="button_Left"> + <el-button size="default" type="warning" plain :disabled="warning" @click="onEdit('修改',deleteAll[0])"> + <el-icon> + <Edit /> + </el-icon>修改 + </el-button> + <el-button size="default" type="danger" plain :disabled="danger" @click="onDeleteAll"> + <el-icon> + <Delete /> + </el-icon>删除 + </el-button> + </div> + <div class="button_Right"> + <el-button> + <el-icon> + <Download /> + </el-icon> + </el-button> + <el-button> + <el-icon> + <Refresh /> + </el-icon> + </el-button> + </div> + </div> + <el-table + :data="tableData" + style="width: 100%" + @selection-change="handleSelectionChange" + > + <el-table-column + type="selection" + width="55" + /> + <el-table-column prop="planName" label="应急预案" min-width="120" show-overflow-tooltip sortable></el-table-column> + <el-table-column prop="userName" label="启动人" min-width="120" show-overflow-tooltip sortable></el-table-column> + <el-table-column prop="startCreate" label="启动时间" min-width="120" show-overflow-tooltip sortable></el-table-column> + <el-table-column prop="remark" label="备注" min-width="120" show-overflow-tooltip sortable></el-table-column> + <el-table-column label="操作" width="200" align="center" fixed="right"> + <template #default="scope"> + <el-button size="small" text type="primary" @click="onEdit('详情',scope.row.id)"> + <el-icon style="margin-right: 5px;"> + <View /> + </el-icon>查看 + </el-button> +<!-- <el-button size="small" text type="primary" @click="onEdit('修改',scope.row.id)">--> +<!-- <el-icon style="margin-right: 5px;">--> +<!-- <EditPen />--> +<!-- </el-icon>修改--> +<!-- </el-button>--> + <el-button size="small" text type="primary" @click="onRowDel(scope.row.id)"> + <el-icon> + <Delete /> + </el-icon>删除 + </el-button> + </template> + </el-table-column> + </el-table> + <div class="pages"> + <el-pagination + v-if="tableData.length == 0 ? false : true" + v-model:currentPage="pageIndex" + v-model:page-size="pageSize" + :page-sizes="[10, 20, 30]" + :pager-count="5" + layout="total, sizes, prev, pager, next, jumper" + :total="total" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + </el-card> + <SelectEmergencyPlan ref="showRef" @SearchUser="onUser"/> + <OpenSee ref="editRef" @myAdd="onMyAdd" /> + </div> +</template> + +<script lang="ts"> +import { + // toRefs, + reactive, + onMounted, + ref, + defineComponent +} from 'vue'; +import { + ElMessageBox, + ElMessage, +} from 'element-plus'; +import { + Search, + Delete, + // Upload, + Download, + Refresh, + View, + Edit, + EditPen, +} from '@element-plus/icons-vue' +import OpenSee from '/@/views/contingencyManagement/emergencyPlanStartRecord/component/openSee.vue'; +import SelectEmergencyPlan from '/@/views/contingencyManagement/emergencyPlanStartRecord/component/selectEmergencyPlan.vue' +import {emergencyPlanLogApi} from "/@/api/contingencyManagement/emergencyPlanLog"; +import {contingencyApi} from "/@/api/contingencyManagement/contingency"; + +export default defineComponent({ + name: 'systemUser', + components: { + OpenSee, + View, + EditPen, + Edit, + Delete, + SelectEmergencyPlan, + Download, + Refresh, + }, + setup() { + // 列表参数 + const listQuery = reactive({ + pageIndex: 1, + pageSize: 10, + searchParams: { + planId: '', + }, + }); + // 定义表格数据 + const tableData = ref([]); + + // 请求列表数据 + const onSubmit = async () => { + var planName = listQuery.searchParams.planName + delete listQuery.searchParams.planName + let res = await emergencyPlanLogApi().getEmergencyPlanLogList(listQuery); + if (res.data.code == 200) { + tableData.value = res.data.data; + pageIndex.value = res.data.pageIndex; + pageSize.value = res.data.pageSize; + total.value = res.data.total; + listQuery.searchParams.planName = planName + } else { + ElMessage.error(res.data.msg); + } + }; + //重置 + const submitReset = () => { + listQuery.searchParams.planId = ''; + listQuery.searchParams.planName = ''; + onSubmit(); + }; + const warning = ref(true); + const danger = ref(true); + const deleteAll = ref(); + const handleSelectionChange = (val: any) => { + let valId = JSON.parse(JSON.stringify(val)); + let arr = []; + for (let i = 0; i < valId.length; i++) { + arr.push(valId[i].id); + } + deleteAll.value = arr; + if (val.length == 1) { + warning.value = false; + danger.value = false; + } else if (val.length == 0) { + warning.value = true; + danger.value = true; + } else { + warning.value = true; + danger.value = false; + } + }; + // 打开修改应急预案启动记录弹窗 + const editRef = ref(); + const onEdit = (val: string, row: object) => { + if (val == '详情') { + editRef.value.openDialog('查看应急预案启动记录',row,true); + } + else { + editRef.value.openDialog('修改应急预案启动记录',row,false); + } + }; + // 修改后刷新 + const onMyAdd = (e: boolean) => { + if (e) { + onSubmit(); + } else { + onSubmit(); + } + }; + // 应急预案 + const showRef=ref() + const daiInpt=()=>{ + showRef.value.openDailog() + } + const onUser = (e:any) => { + console.log(e) + listQuery.searchParams.planId=e.id + listQuery.searchParams.planName=e.name + }; + // 删除用户 + const onRowDel = (data: any) => { + ElMessageBox.confirm('确定删除所选项吗?', '提示',{ + confirmButtonText: '确认', + cancelButtonText: '取消', + type: 'warning', + }).then(() => { + emergencyPlanLogApi() + .deleteEmergencyPlanLog([data]) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'success', + }); + onSubmit(); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + onSubmit(); + } + }); + }).catch(() => {}); + }; + // 多选删除 + const onDeleteAll = () => { + ElMessageBox.confirm('确定删除所选项吗?', '提示', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + emergencyPlanLogApi() + .deleteEmergencyPlanLog(deleteAll.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'success', + }); + onSubmit(); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + onSubmit(); + } + }); + }) + .catch(() => {}); + }; + // 分页 + const pageIndex = ref(); + const pageSize = ref(); + const total = ref(); + // 分页改变 + const handleSizeChange = (val: number) => { + listQuery.pageSize = val; + onSubmit(); + }; + // 分页未改变 + const handleCurrentChange = (val: number) => { + listQuery.pageIndex = val; + onSubmit(); + }; + // 上传 + const upShow=ref() + const upButton=()=>{ + upShow.value.openDialog() + } + onMounted(() => { + onSubmit(); + }); + return { + upButton, + upShow, + tableData, + editRef, + onMyAdd, + onRowDel, + pageIndex, + pageSize, + handleSizeChange, + handleCurrentChange, + onSubmit, + Search, + daiInpt, + showRef, + onMounted, + submitReset, + listQuery, + Edit, + View, + onEdit, + onDeleteAll, + deleteAll, + warning, + danger, + total, + onUser, + handleSelectionChange, + }; + }, +}); +</script> +<style scoped lang="scss"> +.table_Box{ + padding: 20px; + background-color: #fff; +} +.tableForm{ + margin-top: 10px; +} +/*按钮行*/ +.button_Line{ + display: flex; + flex-direction: row; + justify-content: space-between; +} +//弹窗底部边框线 +::v-deep .el-dialog__footer{ + border-top: 1px solid #e8e8e8; + border-radius: 0 0 4px 4px; +} +//弹窗顶部边框线 +::v-deep .el-dialog__header { + border-bottom: 1px solid #e8e8e8; + margin-right: 0; + border-radius: 4px 4px 0 0; +} +//表头 +::v-deep .el-table th.el-table__cell { + background-color: #f6f7fa; + font-weight: 400; + color: #909399; +} +.el-table .sort-caret.ascending{ + border-bottom-color: #c0c4cc; +} +//分页 +.pages{ + display: flex; + justify-content: flex-end; + margin-top: 15px; +} +::v-deep .el-pagination .el-pager li { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +::v-deep .el-pagination .el-pager li.is-active { + background-color: #409eff; + color: #fff; +} +::v-deep .el-pagination .btn-prev { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +::v-deep .el-pagination button:disabled{ + color: #c0c4cc; +} +::v-deep .el-pagination .btn-next{ + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +</style> \ No newline at end of file diff --git a/src/views/contingencyManagement/emergencyResources/emergencyMaterialsInspection/component/openAdd.vue b/src/views/contingencyManagement/emergencyResources/emergencyMaterialsInspection/component/openAdd.vue new file mode 100644 index 0000000..a241308 --- /dev/null +++ b/src/views/contingencyManagement/emergencyResources/emergencyMaterialsInspection/component/openAdd.vue @@ -0,0 +1,284 @@ +<template> + <div class="system-edit-user-container"> + <el-dialog :title="titles" @close="resetForm(ruleFormRef)" v-model="isShowDialog" width="50%" draggable :fullscreen="full"> + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-form ref="ruleFormRef" :disabled="titles=='查看应急物资检查'?true:false" :rules="rules" :model="ruleForm" size="default" label-width="120px"> + <el-row :gutter="35"> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="应急物资" prop="suppliesName"> + <el-input v-model="ruleForm.suppliesName" placeholder="请选择" class="input-with-select"> + <template #append> + <el-button :icon="Search" @click="daiInpt" /> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="检查结果" prop="inspectResult"> + <el-select v-model="ruleForm.inspectResult" class="w100" placeholder="请选择"> + <el-option label="正常" value="1"></el-option> + <el-option label="异常" value="2"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="创建人" prop="userName"> + <el-input v-model="ruleForm.userName" placeholder="请选择" class="input-with-select"> + <template #append> + <el-button :icon="Search" @click="openUser(0)" /> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="创建时间" prop="inspectTime"> + <el-date-picker + class="w100" + v-model="ruleForm.inspectTime" + type="datetime" + value-format="YYYY-MM-DD HH:mm:ss" + placeholder="选择日期时间" + /> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="resetForm(ruleFormRef)" size="default">关闭</el-button> + <el-button size="default" type="primary" v-if="titles=='查看应急物资检查'?false:true" @click="submitForm(titles, ruleFormRef)">确定</el-button> + </span> + </template> + </el-dialog> + <EmergencySupplies ref="showRef" @SearchUser="onUser" /> + <DailogSearchUser ref="userRef" @SearchUser="onUsers" /> + </div> +</template> + +<script lang="ts"> +import { ref, defineComponent, reactive } from 'vue'; + +import type { FormInstance, FormRules } from 'element-plus'; +import { ElMessage } from 'element-plus'; +import DailogSearchUser from '/@/components/DailogSearchUser/index.vue'; +import { Search, FullScreen } from '@element-plus/icons-vue'; +import EmergencySupplies from '/@/components/emergencySupplies/index.vue'; +import UserSelections from '/@/components/userSelections/index.vue'; +import { emergencyMaterialsInspectionApi } from '/@/api/contingencyManagement/emergencyMaterialsInspection'; +import { maintenanceEmergencyMaterialsApi } from '/@/api/contingencyManagement/maintenanceEmergencyMaterials'; + +export default defineComponent({ + name: 'openAdd', + components: { + DailogSearchUser, + EmergencySupplies, + }, + setup(props, { emit }) { + const isShowDialog = ref(false); + + const ruleFormRef = ref<FormInstance>(); + //定义表单 + const ruleForm = ref({ + suppliesId: '', // 物资ID + inspectResult: '', //检查结果 + inspectTime: '', // 创建时间 + userList: [], + }); + const titles = ref(); + const disableds = ref(); + // 打开弹窗 + const openDialog = (title: string, id: number) => { + isShowDialog.value = true; + titles.value = title; + if (title == '查看应急物资检查' || title == '修改应急物资检查') { + emergencyMaterialsInspectionApi() + .seeEmergencyMaterialsInspection(id) + .then((res) => { + if (res.data.code == 200) { + ruleForm.value = res.data.data; + let arr = []; + for (let i = 0; i < ruleForm.value.userList.length; i++) { + arr.push(ruleForm.value.userList[i].userName); + } + ruleForm.value.userName = arr.toString(); + } + }); + } + }; + //日期选择器 + const value1 = ref(''); + const rules = reactive<FormRules>({ + nameTitle: [], + inspectResult: [ + { + required: true, + message: '保养结果不能为空', + trigger: 'change', + }, + ], + userName: [ + { + required: true, + message: '创建人不能为空', + trigger: 'change', + }, + ], + inspectTime: [ + { + required: true, + message: '创建时间不能为空', + trigger: 'blur', + }, + ], + }); + // 表单提交验证必填项 + const submitForm = async (title: string, formEl: FormInstance | undefined) => { + if (title == '新建应急物资检查') { + if (!formEl) return; + await formEl.validate((valid, fields) => { + if (valid) { + isShowDialog.value = false; + delete ruleForm.value.suppliesName + delete ruleForm.value.userName + emergencyMaterialsInspectionApi() + .addEmergencyMaterialsInspection(ruleForm.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'success', + }); + emit('myAdd', true); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + emit('myAdd', true); + } + formEl.resetFields(); + }); + } else { + console.log('error submit!', fields); + } + }); + } else if (title == '修改应急物资检查') { + if (!formEl) return; + await formEl.validate((valid, fields) => { + if (valid) { + isShowDialog.value = false; + delete ruleForm.value.suppliesName + delete ruleForm.value.userName + emergencyMaterialsInspectionApi() + .editEmergencyMaterialsInspection(ruleForm.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: '修改成功', + type: 'success', + }); + emit('myAdd', true); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + emit('myAdd', true); + } + formEl.resetFields(); + }); + } else { + console.log('error submit!', fields); + } + }); + formEl.resetFields(); + } + }; + const resetForm = (formEl: FormInstance | undefined) => { + isShowDialog.value = false; + if (!formEl) return; + formEl.resetFields(); + }; + // 应急物资弹窗 + const showRef = ref(); + const daiInpt = () => { + showRef.value.openDailog(); + }; + const onUser = (e: any) => { + ruleForm.value.suppliesId = e.id; + ruleForm.value.suppliesName = e.name; + }; + // 编写人弹窗 + const userRef = ref(); + const openUser = (data: any) => { + userRef.value.openDailog(data); + }; + const onUsers = (val: any) => { + let arr = []; + for (let i = 0; i < val.length; i++) { + arr.push(val[i].realName); + ruleForm.value.userList.push({ + userUid: val[i].uid, + userName: val[i].realName, + }); + } + ruleForm.value.userName = arr.toString(); + }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + return { + openDialog, + isShowDialog, + Search, + ruleForm, + value1, + onUsers, + daiInpt, + showRef, + ruleFormRef, + submitForm, + openUser, + rules, + userRef, + resetForm, + toggleFullscreen, + FullScreen, + full, + titles, + disableds, + emit, + onUser, + }; + }, +}); +</script> +<style scoped lang="scss"> +.textarea { + height: 168px !important; +} +.textarea ::v-deep .el-textarea__inner { + height: 168px !important; +} +::v-deep .el-table__cell { + font-weight: 400; +} +.el-divider--horizontal { + height: 0; + margin: 0; + border-top: transparent; +} +.el-select { + width: 100%; +} +</style> \ No newline at end of file diff --git a/src/views/contingencyManagement/emergencyResources/emergencyMaterialsInspection/index.vue b/src/views/contingencyManagement/emergencyResources/emergencyMaterialsInspection/index.vue new file mode 100644 index 0000000..7ad1c4f --- /dev/null +++ b/src/views/contingencyManagement/emergencyResources/emergencyMaterialsInspection/index.vue @@ -0,0 +1,391 @@ +<template> + <div class="system-user-container"> + <el-card shadow="hover"> + <div class="system-user-search mb15"> + <el-form size="default" label-width="80px" :inline="true"> + <el-form-item prop="telephone"> + <el-input v-model="suppliesName" placeholder="请选择应急物资" class="input-with-select"> + <template #append> + <el-button :icon="Search" @click="daiInpt" /> + </template> + </el-input> + </el-form-item> + <el-button size="default" type="primary" class="ml10" @click="onSubmit"> 查询 </el-button> + <el-button size="default" class="ml10" @click="submitReset"> 重置 </el-button> + </el-form> + </div> + <div class="button_Line"> + <div class="button_Left"> + <el-button size="default" type="primary" @click="onOpenAdd"> + <el-icon> <Plus /> </el-icon>新建 + </el-button> + <el-button size="default" type="warning" plain :disabled="warning" @click="onEdit('修改', deletAll[0])"> + <el-icon> <Edit /> </el-icon>修改 + </el-button> + <el-button size="default" type="danger" plain @click="onDeleteAll" :disabled="danger"> + <el-icon> <Delete /> </el-icon>删除 + </el-button> + </div> + <div class="button_Right"> + <el-button> + <el-icon> + <Download /> + </el-icon> + </el-button> + <el-button> + <el-icon> + <Refresh /> + </el-icon> + </el-button> + </div> + </div> + <el-table :data="tableData" style="width: 100%" ref="multipleTableRef" @selection-change="handleSelectionChange"> + <el-table-column align="center" type="selection" width="55" /> + <el-table-column align="center" prop="suppliesName" label="物资名称" min-width="120" show-overflow-tooltip sortable></el-table-column> + <el-table-column align="center" label="维修结果" min-width="120" show-overflow-tooltip sortable> + <template #default="scope"> + <span v-if="scope.row.inspectResult == 1">正常</span> + <span v-if="scope.row.inspectResult == 2">异常</span> + </template> + </el-table-column> + <el-table-column align="center" prop="inspectTime" label="维修日期" min-width="120" show-overflow-tooltip sortable></el-table-column> + <el-table-column label="操作" width="200" align="center" fixed="right"> + <template #default="scope"> + <el-button size="small" text type="primary" @click="onEdit('查看',scope.row.id)"> + <el-icon style="margin-right: 5px"> <View /> </el-icon>查看 + </el-button> + <el-button size="small" text type="primary" @click="onEdit('修改', scope.row.id)"> + <el-icon style="margin-right: 5px"> <EditPen /> </el-icon>修改 + </el-button> + <el-button size="small" text type="primary" @click="onRowDel(scope.row.id)"> + <el-icon> <Delete /> </el-icon>删除 + </el-button> + </template> + </el-table-column> + </el-table> + <div class="pages"> + <el-pagination + v-if="tableData.length == 0 ? false : true" + v-model:currentPage="pageIndex" + v-model:page-size="pageSize" + :page-sizes="[10, 20, 30]" + :pager-count="5" + layout="total, sizes, prev, pager, next, jumper" + :total="total" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + </el-card> + <EmergencySupplies ref="showRef" @SearchUser="onUser" /> + <upData ref="upShow"></upData> + <OpenAdd ref="addRef" @myAdd="onMyAdd" /> + </div> +</template> + +<script lang="ts"> +import { + // toRefs, + reactive, + onMounted, + ref, + defineComponent, +} from 'vue'; +import { + ElMessageBox, + ElMessage, + // ElTable, +} from 'element-plus'; +import { Plus, Search, Delete, Edit, Download, Refresh, View, EditPen } from '@element-plus/icons-vue'; +import UpData from '/@/views/contingencyManagement/panManagement/component/upData.vue'; +import EmergencySupplies from '/@/components/emergencySupplies/index.vue'; +import OpenAdd from '/@/views/contingencyManagement/emergencyResources/emergencyMaterialsInspection/component/openAdd.vue'; +import { emergencyMaterialsInspectionApi } from '/@/api/contingencyManagement/emergencyMaterialsInspection'; + +export default defineComponent({ + name: 'index', + components: { + View, + OpenAdd, + EditPen, + Plus, + Edit, + Delete, + EmergencySupplies, + Download, + Refresh, + UpData, + }, + setup() { + //定义表单 + const listQuery = reactive({ + pageIndex: 1, + pageSize: 10, + searchParams: { + suppliesId: '', + }, + }); + // 定义表格数据 + const tableData = ref([]); + // 搜索按钮 + const onSubmit = async () => { + let res = await emergencyMaterialsInspectionApi().getEmergencyMaterialsInspectionList(listQuery); + if (res.data.code == 200) { + tableData.value = res.data.data; + pageIndex.value = res.data.pageIndex; + pageSize.value = res.data.pageSize; + total.value = res.data.total; + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + } + }; + const suppliesName=ref() + // 重置 + const submitReset = () => { + listQuery.searchParams.suppliesId = ''; + suppliesName.value="" + onSubmit(); + }; + const warning = ref(true); + const danger = ref(true); + const deletAll = ref(); + const handleSelectionChange = (val: any) => { + let valId = JSON.parse(JSON.stringify(val)); + let arr = []; + for (let i = 0; i < valId.length; i++) { + arr.push(valId[i].id); + } + deletAll.value = arr; + if (val.length == 1) { + warning.value = false; + danger.value = false; + } else if (val.length == 0) { + warning.value = true; + danger.value = true; + } else { + warning.value = true; + danger.value = false; + } + }; + // 打开新建用户弹窗 + const addRef = ref(); + const onOpenAdd = () => { + addRef.value.openDialog('新建应急物资检查'); + }; + // 新增后刷新 + const onMyAdd = (e: boolean) => { + if (e) { + onSubmit(); + } else { + onSubmit(); + } + }; + // 打开修改用户弹窗 + const onEdit = (val: string, row: object) => { + if (val == '查看') { + addRef.value.openDialog('查看应急物资检查', row); + } else { + addRef.value.openDialog('修改应急物资检查', row); + } + }; + // 删除 + const onRowDel = (id: number) => { + let arr = []; + arr.push(id); + ElMessageBox.confirm('确定删除所选项吗?', '提示', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + emergencyMaterialsInspectionApi() + .deleteEmergencyMaterialsInspection(arr) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'success', + }); + onSubmit(); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + onSubmit(); + } + }); + }) + .catch(() => {}); + }; + // 多选删除 + const onDeleteAll = () => { + ElMessageBox.confirm('确定删除所选项吗?', '提示', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + emergencyMaterialsInspectionApi() + .deleteEmergencyMaterialsInspection(deletAll.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'success', + }); + onSubmit(); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + onSubmit(); + } + }); + }) + .catch(() => {}); + }; + // 上传 + const upShow = ref(); + const upButton = () => { + upShow.value.openDialog(); + }; + + // 应急物资弹窗 + const showRef = ref(); + const daiInpt = () => { + showRef.value.openDailog(); + }; + const onUser = (e: any) => { + listQuery.searchParams.suppliesId = e.id; + suppliesName.value=e.name + }; + // 分页 + const pageIndex = ref(); + const pageSize = ref(); + const total = ref(); + // 分页改变 + const handleSizeChange = (val: number) => { + listQuery.pageSize = val; + onSubmit(); + }; + // 分页未改变 + const handleCurrentChange = (val: number) => { + listQuery.pageIndex = val; + onSubmit(); + }; + // 页面加载时 + onMounted(() => { + onSubmit(); + }); + return { + suppliesName, + upButton, + upShow, + Edit, + onRowDel, + pageIndex, + pageSize, + handleSizeChange, + handleCurrentChange, + Search, + daiInpt, + showRef, + onOpenAdd, //新增 + addRef, + onSubmit, + View, + submitReset, + tableData, + onMyAdd, + onEdit, + onDeleteAll, + handleSelectionChange, + listQuery, + warning, + danger, + total, + onUser, + deletAll + }; + }, +}); +</script> +<style scoped lang="scss"> +.table_Box { + padding: 20px; + background-color: #fff; +} +.tableForm { + margin-top: 10px; +} +/*按钮行*/ +.button_Line { + display: flex; + flex-direction: row; + justify-content: space-between; +} +//弹窗底部边框线 +::v-deep .el-dialog__footer { + border-top: 1px solid #e8e8e8; + border-radius: 0 0 4px 4px; +} +//弹窗顶部边框线 +::v-deep .el-dialog__header { + border-bottom: 1px solid #e8e8e8; + margin-right: 0; + border-radius: 4px 4px 0 0; +} +//表头 +::v-deep .el-table th.el-table__cell { + background-color: #f6f7fa; + font-weight: 400; + color: #909399; +} +.el-table .sort-caret.ascending { + border-bottom-color: #c0c4cc; +} +//分页 +.pages { + display: flex; + justify-content: flex-end; + margin-top: 15px; +} +::v-deep .el-pagination .el-pager li { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +::v-deep .el-pagination .el-pager li.is-active { + background-color: #409eff; + color: #fff; +} +::v-deep .el-pagination .btn-prev { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +::v-deep .el-pagination button:disabled { + color: #c0c4cc; +} +::v-deep .el-pagination .btn-next { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +</style> \ No newline at end of file diff --git a/src/views/contingencyManagement/emergencyResources/emergencySupplies/component/inspect.vue b/src/views/contingencyManagement/emergencyResources/emergencySupplies/component/inspect.vue new file mode 100644 index 0000000..d67642c --- /dev/null +++ b/src/views/contingencyManagement/emergencyResources/emergencySupplies/component/inspect.vue @@ -0,0 +1,225 @@ +<template> + <div class="system-edit-user-container"> + <el-dialog title="修改应急物资检查" v-model="isShowDialog" @close="resetForm(ruleFormRef)" width="50%" draggable :fullscreen="full"> + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-form ref="ruleFormRef" :model="ruleForm" :rules="rules" size="default" label-width="120px"> + <el-row :gutter="35"> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="应急物资"> + <el-input v-model="nameTitle" disabled placeholder="请选择" class="input-with-select"> + <!-- <template #append> + <el-button :icon="Search" @click="daiInpt" /> + </template> --> + </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="检查结果" prop="inspectResult"> + <el-select v-model="ruleForm.inspectResult" class="w100" placeholder="请选择"> + <el-option label="正常" value="1"></el-option> + <el-option label="异常" value="2"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="创建人" prop="userName"> + <el-input v-model="ruleForm.userName" placeholder="请选择" class="input-with-select"> + <template #append> + <el-button :icon="Search" @click="openUser(0)" /> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="创建时间" prop="inspectTime"> + <el-date-picker + class="w100" + v-model="ruleForm.inspectTime" + type="datetime" + placeholder="选择日期时间" + value-format="YYYY-MM-DD HH:mm:ss" + /> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="resetForm(ruleFormRef)" size="default">关闭</el-button> + <el-button size="default" type="primary" @click="submitForm(ruleFormRef)">确定</el-button> + </span> + </template> + </el-dialog> + <!-- <EmergencySupplies ref="showRef" @SearchUser="onUser"/> --> + <DailogSearchUser ref="userRef" @SearchUser="onUsers" /> + </div> +</template> + +<script lang="ts"> +import { ref, defineComponent,reactive } from 'vue'; +import DailogSearchUser from '/@/components/DailogSearchUser/index.vue'; +import type { FormInstance,FormRules } from 'element-plus'; +import { ElMessage } from 'element-plus'; +import { Search, FullScreen } from '@element-plus/icons-vue'; +import EmergencySupplies from '/@/components/emergencySupplies/index.vue'; +import UserSelections from '/@/components/userSelections/index.vue'; +import { emergencyMaterialsInspectionApi } from '/@/api/contingencyManagement/emergencyMaterialsInspection'; + +export default defineComponent({ + name: 'inspect', + components: { + UserSelections, + EmergencySupplies, + DailogSearchUser, + }, + setup(props, { emit }) { + const isShowDialog = ref(false); + + const ruleFormRef = ref<FormInstance>(); + //定义表单 + const ruleForm = ref({ + suppliesId: '', // 物资ID + inspectResult: '', //保养结果 + inspectTime: '', // 创建时间 + userList: [], + }); + const disabled = ref(); + // 打开弹窗 + const nameTitle = ref(); + const openDialog = (data: string) => { + isShowDialog.value = true; + ruleForm.value.suppliesId = data.id; + nameTitle.value = data.name; + }; + const rules = reactive<FormRules>({ + nameTitle: [], + inspectResult: [ + { + required: true, + message: '保养结果不能为空', + trigger: 'change', + }, + ], + userName: [ + { + required: true, + message: '创建人不能为空', + trigger: 'change', + }, + ], + inspectTime: [ + { + required: true, + message: '创建时间不能为空', + trigger: 'blur', + }, + ], + }); + // 表单提交验证必填项 + const submitForm = async (formEl: FormInstance | undefined) => { + if (!formEl) return; + await formEl.validate((valid, fields) => { + if (valid) { + isShowDialog.value = false; + delete ruleForm.value.userName + emergencyMaterialsInspectionApi() + .addEmergencyMaterialsInspection(ruleForm.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'success', + }); + emit('myAdd', true); + formEl.resetFields(); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + emit('myAdd', true); + } + }); + } else { + console.log('error submit!', fields); + } + }); + }; + const resetForm = (formEl: FormInstance | undefined) => { + isShowDialog.value = false; + if (!formEl) return; + formEl.resetFields(); + }; + + //日期选择器 + const value1 = ref(''); + + // 编写人弹窗 + const userRef = ref(); + const openUser = (type: any) => { + userRef.value.openDailog(type); + }; + const onUsers = (val: any) => { + let arr = []; + for (let i = 0; i < val.length; i++) { + arr.push(val[i].realName); + ruleForm.value.userList.push({ + userUid: val[i].uid, + userName: val[i].realName, + }); + } + ruleForm.value.userName = arr.toString(); + }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + return { + nameTitle, + openDialog, + isShowDialog, + resetForm, + rules, + Search, + ruleForm, + value1, + onUsers, + ruleFormRef, + submitForm, + openUser, + userRef, + toggleFullscreen, + FullScreen, + full, + disabled, + emit, + }; + }, +}); +</script> +<style scoped lang="scss"> +.textarea { + height: 168px !important; +} +.textarea ::v-deep .el-textarea__inner { + height: 168px !important; +} +::v-deep .el-table__cell { + font-weight: 400; +} +.el-divider--horizontal { + height: 0; + margin: 0; + border-top: transparent; +} +.el-select { + width: 100%; +} +</style> \ No newline at end of file diff --git a/src/views/contingencyManagement/emergencyResources/emergencySupplies/component/maintain.vue b/src/views/contingencyManagement/emergencyResources/emergencySupplies/component/maintain.vue new file mode 100644 index 0000000..fb8b0a1 --- /dev/null +++ b/src/views/contingencyManagement/emergencyResources/emergencySupplies/component/maintain.vue @@ -0,0 +1,236 @@ +<template> + <div class="system-edit-user-container"> + <el-dialog title="修改应急物资保养" @close="resetForm(ruleFormRef)" v-model="isShowDialog" width="50%" draggable :fullscreen="full"> + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-form ref="ruleFormRef" :model="ruleForm" :rules="rules" size="default" label-width="120px"> + <el-row :gutter="35"> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="应急物资" prop="nameTitle"> + <el-input v-model="nameTitle" disabled placeholder="请选择" class="input-with-select"> + <!-- <template #append> + <el-button :icon="Search" @click="daiInpt"/> + </template> --> + </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="保养结果" prop="maintainResult"> + <el-select v-model="ruleForm.maintainResult" class="w100" placeholder="请选择"> + <el-option label="正常" value="1"></el-option> + <el-option label="异常" value="2"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="创建人" prop="userName"> + <el-input v-model="ruleForm.userName" placeholder="请选择" class="input-with-select"> + <template #append> + <el-button :icon="Search" @click="openUser(0)" /> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="创建时间" prop="maintainTime"> + <el-date-picker + class="w100" + v-model="ruleForm.maintainTime" + type="datetime" + placeholder="选择日期时间" + value-format="YYYY-MM-DD HH:mm:ss" + /> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="resetForm(ruleFormRef)" size="default">关闭</el-button> + <el-button size="default" type="primary" @click="submitForm(ruleFormRef)">确定</el-button> + </span> + </template> + </el-dialog> + <EmergencySupplies ref="showRef" @SearchUser="onUser" /> + <DailogSearchUser ref="userRef" @SearchUser="onUsers" /> + </div> +</template> + +<script lang="ts"> +import { ref, defineComponent, reactive } from 'vue'; + +import type { FormInstance, FormRules } from 'element-plus'; +import { ElMessage } from 'element-plus'; +import { Search, FullScreen } from '@element-plus/icons-vue'; +import EmergencySupplies from '/@/components/emergencySupplies/index.vue'; +import DailogSearchUser from '../../../../../components/DailogSearchUser/index.vue'; +import { maintenanceEmergencyMaterialsApi } from '/@/api/contingencyManagement/maintenanceEmergencyMaterials'; + +export default defineComponent({ + name: 'maintain', + components: { + DailogSearchUser, + EmergencySupplies, + }, + setup(props, { emit }) { + const isShowDialog = ref(false); + + const ruleFormRef = ref<FormInstance>(); + //定义表单 + const ruleForm = ref({ + suppliesId: '', // 物资ID + maintainResult: '', //保养结果 + maintainTime: '', // 创建时间 + userList: [], + }); + const disabled = ref(); + // 打开弹窗 + const nameTitle = ref(); + const openDialog = (data: string) => { + isShowDialog.value = true; + ruleForm.value.suppliesId = data.id; + nameTitle.value = data.name; + }; + const rules = reactive<FormRules>({ + nameTitle: [], + maintainResult: [ + { + required: true, + message: '保养结果不能为空', + trigger: 'change', + }, + ], + userName: [ + { + required: true, + message: '创建人不能为空', + trigger: 'change', + }, + ], + maintainTime: [ + { + required: true, + message: '创建时间不能为空', + trigger: 'blur', + }, + ], + }); + // 表单提交验证必填项 + const submitForm = async (formEl: FormInstance | undefined) => { + if (!formEl) return; + await formEl.validate((valid, fields) => { + if (valid) { + isShowDialog.value = false; + delete ruleForm.value.userName + maintenanceEmergencyMaterialsApi() + .addMaintenanceEmergencyMaterials(ruleForm.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'success', + }); + emit('myAdd', true); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + emit('myAdd', true); + } + formEl.resetFields(); + }); + } else { + console.log('error submit!', fields); + } + }); + }; + const resetForm = (formEl: FormInstance | undefined) => { + isShowDialog.value = false; + if (!formEl) return; + formEl.resetFields(); + }; + + //日期选择器 + const value1 = ref(''); + + // 应急物资弹窗 + const showRef = ref(); + const daiInpt = () => { + showRef.value.openDailog(); + }; + const onUser = (e: any) => { + ruleForm.value.suppliesId = e.id; + }; + + // 编写人弹窗 + const userRef = ref(); + const openUser = (type: any) => { + userRef.value.openDailog(type); + }; + const onUsers = (val: any) => { + let arr = []; + for (let i = 0; i < val.length; i++) { + arr.push(val[i].realName); + ruleForm.value.userList.push({ + userUid: val[i].uid, + userName: val[i].realName, + }); + } + ruleForm.value.userName = arr.toString(); + }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + return { + openDialog, + rules, + isShowDialog, + resetForm, + Search, + ruleForm, + value1, + daiInpt, + onUsers, + showRef, + ruleFormRef, + onUser, + submitForm, + openUser, + userRef, + toggleFullscreen, + FullScreen, + full, + disabled, + emit, + nameTitle, + }; + }, +}); +</script> +<style scoped lang="scss"> +.textarea { + height: 168px !important; +} +.textarea ::v-deep .el-textarea__inner { + height: 168px !important; +} +::v-deep .el-table__cell { + font-weight: 400; +} +.el-divider--horizontal { + height: 0; + margin: 0; + border-top: transparent; +} +.el-select { + width: 100%; +} +</style> \ No newline at end of file diff --git a/src/views/contingencyManagement/emergencyResources/emergencySupplies/component/openAdd.vue b/src/views/contingencyManagement/emergencyResources/emergencySupplies/component/openAdd.vue new file mode 100644 index 0000000..17defc0 --- /dev/null +++ b/src/views/contingencyManagement/emergencyResources/emergencySupplies/component/openAdd.vue @@ -0,0 +1,515 @@ +<template> + <div class="system-edit-user-container"> + <el-dialog :title="titles" v-model="isShowDialog" @close="resetForm(ruleFormRef)" width="50%" draggable :fullscreen="full"> + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-form ref="ruleFormRef" :rules="rules" :model="ruleForm" size="default" label-width="120px" :disabled="disabled"> + <el-row :gutter="35"> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="物资名称" prop="name"> + <el-input v-model="ruleForm.name" placeholder="请填写物资名称"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="物资编号" prop="number"> + <el-input v-model="ruleForm.number" placeholder="请填写物资编号"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="物资用途" prop="use"> + <el-input v-model="ruleForm.use" placeholder="请填写物资用途"></el-input> + </el-form-item> + </el-col> + <!-- <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">--> + <!-- <el-form-item label="所属区域">--> + <!-- <el-input v-model="ruleForm.areaId" placeholder="请选择" class="input-with-select">--> + <!-- <template #append>--> + <!-- <el-button :icon="Search" @click="regionsDialog" />--> + <!-- </template>--> + <!-- </el-input>--> + <!-- </el-form-item>--> + <!-- </el-col>--> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="物资型号" prop="model"> + <el-input v-model="ruleForm.model" placeholder="请填写物资型号"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="负责部门" prop="departmentId"> + <el-tree-select + v-model="ruleForm.departmentId" + check-strictly + :data="data" + :props="propse" + class="w100" + clearable + :render-after-expand="false" + placeholder="请选择" + /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="物资分类" prop="classification"> + <el-select v-model="ruleForm.classification" class="w100" placeholder="请选择"> + <el-option label="事故气体吸收装置" value="1"></el-option> + <el-option label="通讯设施" value="2"></el-option> + <el-option label="交通运输工具" value="3"></el-option> + <el-option label="照明装置" value="4"></el-option> + <el-option label="防护器材" value="5"></el-option> + <el-option label="其它" value="6"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="存放位置" prop="place"> + <el-input v-model="ruleForm.place" placeholder="请填写存放位置"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="存储数量" prop="count"> + <el-input v-model.number="ruleForm.count" maxlength="6" placeholder="请填写存储数量"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="生产日期" prop="productionDate"> + <el-date-picker + v-model="ruleForm.productionDate" + type="datetime" + class="w100" + placeholder="选择日期时间" + value-format="YYYY-MM-DD HH:mm:ss" + /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="使用期限(天)" prop="usePeriod"> + <el-input v-model.number="ruleForm.usePeriod" maxlength="6" placeholder="请填写使用期限"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="物资状态" prop="status"> + <el-select v-model="ruleForm.status" class="w100" placeholder="请选择"> + <el-option label="完好" :value="1"></el-option> + <el-option label="维修" :value="2"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="检查周期月" prop="inspectPeriod"> + <el-input v-model.number="ruleForm.inspectPeriod" type="" maxlength="4" placeholder="请填写使用期限"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="投用日期" prop="useDate"> + <el-date-picker v-model="ruleForm.useDate" type="datetime" class="w100" placeholder="选择日期时间" value-format="YYYY-MM-DD HH:mm:ss" /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="使用说明" prop="useExplain"> + <el-input v-model="ruleForm.useExplain" type="textarea" placeholder="请填写使用说明"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="检查日期" prop="inspectDate"> + <el-date-picker + v-model="ruleForm.inspectDate" + type="datetime" + class="w100" + placeholder="选择日期时间" + value-format="YYYY-MM-DD HH:mm:ss" + /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="下次检查日期" prop="nextInspectDate"> + <el-date-picker + v-model="ruleForm.nextInspectDate" + type="datetime" + value-format="YYYY-MM-DD HH:mm:ss" + class="w100" + placeholder="选择日期时间" + /> + </el-form-item> + </el-col> + <!-- <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">--> + <!-- <el-form-item label="经度(度)">--> + <!-- <el-input v-model="ruleForm.longitude" placeholder="请填写经度(度)"></el-input>--> + <!-- </el-form-item>--> + <!-- </el-col>--> + <!-- <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">--> + <!-- <el-form-item label="纬度(度)">--> + <!-- <el-input v-model="ruleForm.latitude" placeholder="请填写纬度(度)"></el-input>--> + <!-- </el-form-item>--> + <!-- </el-col>--> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="负责人" prop="principalUserName"> + <el-input v-model="ruleForm.principalUserName" placeholder="请选择" class="input-with-select"> + <template #append> + <el-button :icon="Search" @click="daiInpt" /> + </template> + </el-input> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="resetForm(ruleFormRef)" size="default">关闭</el-button> + <el-button size="default" type="primary" v-if="disabled == true ? false : true" @click="submitForm(titles, ruleFormRef)">确定</el-button> + </span> + </template> + </el-dialog> + <DailogSearchUser ref="Shows" @SearchUser="onUser"></DailogSearchUser> + <userSelections ref="userRef" /> + <RegionsCheckbox ref="openRef" /> + </div> +</template> + +<script lang="ts"> +import { reactive, ref, defineComponent, onMounted } from 'vue'; + +import type { FormInstance, FormRules } from 'element-plus'; +import { ElMessage } from 'element-plus'; +import DailogSearchUser from '/@/components/DailogSearchUser/index.vue'; +import { Search, FullScreen } from '@element-plus/icons-vue'; +import UserSelections from '/@/components/userSelections/index.vue'; +import PersonInCharge from '/@/views/contingencyManagement/emergencyResources/emergencySupplies/component/personInCharge.vue'; +import RegionsCheckbox from '/@/views/contingencyManagement/emergencyResources/emergencySupplies/component/regionsCheckbox.vue'; +import { emergencySuppliesApi } from '/@/api/contingencyManagement/emergencyResources'; +import { goalManagementApi } from '/@/api/goalManagement'; + +export default defineComponent({ + name: 'openAdd', + components: { + PersonInCharge, + UserSelections, + RegionsCheckbox, + DailogSearchUser, + }, + setup(props, { emit }) { + const isShowDialog = ref(false); + + const ruleFormRef = ref<FormInstance>(); + //定义表单 + const ruleForm = ref({ + productionDate: '', + useDate: '', + inspectDate: '', + nextInspectDate: '', + inspectPeriod: '', + count: '', + usePeriod: '', + departmentId: '', + principalUserUid: '', + principalUserName: '', + status: '', + classification: '', + name: '', + number: '', + model: '', + longitude: '', + latitude: '', + use: '', + areaId: null, + place: '', + useExplain: '', + }); + const titles = ref(); + const disabled = ref(); + // 打开弹窗 + const openDialog = (title: string, id: number, type: boolean) => { + isShowDialog.value = true; + titles.value = title; + disabled.value = type; + if (title == '查看应急物资代码' || title == '修改应急物资代码') { + emergencySuppliesApi() + .seeEmergencySupplies(id) + .then((res) => { + if (res.data.code == 200) { + ruleForm.value = res.data.data; + } + }); + } + }; + //日期选择器 + const value1 = ref(''); + //部门树 + const department = () => { + goalManagementApi() + .getTreedepartment() + .then((res) => { + if (res.data.code == 200) { + data.value = res.data.data; + } else { + ElMessage.error(res.data.msg); + } + }); + }; + //定义树形下拉框 + const responsibleDepartment = ref(); + const data = ref(); + const propse = { + label: 'depName', + children: 'children', + value: 'depId', + }; + onMounted(() => { + department(); + }); + // 必填项提示 + const rules = reactive<FormRules>({ + name: [ + { + required: true, + message: '物资名称不能为空', + trigger: 'change', + }, + ], + number: [ + { + required: true, + message: '物资编号不能为空', + trigger: 'change', + }, + ], + use: [ + { + required: true, + message: '物资用途不能为空', + trigger: 'change', + }, + ], + model: [ + { + required: true, + message: '物资型号不能为空', + trigger: 'change', + }, + ], + departmentId: [ + { + required: true, + message: '负责部门不能为空', + trigger: 'change', + }, + ], + classification: [ + { + required: true, + message: '物资分类不能为空', + trigger: 'change', + }, + ], + place: [ + { + required: true, + message: '存放位置不能为空', + trigger: 'change', + }, + ], + count: [ + { + required: true, + message: '存储数量不能为空', + trigger: 'change', + }, + { type: 'number', message: '请输入数字类型', trigger: 'change' }, + ], + productionDate: [ + { + required: true, + message: '生产日期不能为空', + trigger: 'change', + }, + ], + usePeriod: [ + { + required: true, + message: '使用期限不能为空', + trigger: 'change', + }, + { type: 'number', message: '请输入数字类型', trigger: 'change' }, + ], + status: [ + { + required: true, + message: '物资状态不能为空', + trigger: 'change', + }, + ], + inspectPeriod: [ + { + required: true, + message: '检查周期月不能为空', + trigger: 'change', + }, + { type: 'number', message: '请输入数字类型', trigger: 'change' }, + ], + useDate: [ + { + required: true, + message: '投用日期不能为空', + trigger: 'change', + }, + ], + inspectDate: [ + { + required: true, + message: '检查日期不能为空', + trigger: 'change', + }, + ], + nextInspectDate: [ + { + required: true, + message: '下次检查日期不能为空', + trigger: 'change', + }, + ], + principalUserName:[], + useExplain:[] + }); + // 表单提交验证必填项 + const submitForm = async (title: string, formEl: FormInstance | undefined) => { + if (title == '新建应急物资代码') { + if (!formEl) return; + await formEl.validate((valid, fields) => { + if (valid) { + isShowDialog.value = false; + emergencySuppliesApi() + .addEmergencySupplies(ruleForm.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'success', + }); + emit('myAdd', true); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + emit('myAdd', true); + } + formEl.resetFields(); + }); + } else { + console.log('error submit!', fields); + } + }); + } else if (title == '修改应急物资代码') { + if (!formEl) return; + await formEl.validate((valid, fields) => { + if (valid) { + isShowDialog.value = false; + emergencySuppliesApi() + .editEmergencySupplies(ruleForm.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: '修改成功', + type: 'success', + }); + emit('myAdd', true); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + emit('myAdd', true); + } + formEl.resetFields(); + }); + } else { + console.log('error submit!', fields); + } + }); + } + }; + const resetForm = (formEl: FormInstance | undefined) => { + isShowDialog.value = false; + if (!formEl) return; + formEl.resetFields(); + }; + // 人名 + const Shows = ref(); + const daiInpt = () => { + Shows.value.openDailog(); + }; + // 选择区域弹窗 + const openRef = ref(); + const regionsDialog = () => { + openRef.value.openDailog(); + }; + // 打开用户选择弹窗 + const userRef = ref(); + const openUser = () => { + userRef.value.openDialog(); + }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + const onUser = (e: any) => { + ruleForm.value.principalUserUid = e.uid; + ruleForm.value.principalUserName = e.realName; + }; + return { + openDialog, + isShowDialog, + responsibleDepartment, + data, + propse, + department, + Search, + ruleForm, + value1, + daiInpt, + Shows, + ruleFormRef, + submitForm, + rules, + openUser, + userRef, + regionsDialog, + openRef, + toggleFullscreen, + FullScreen, + full, + resetForm, + titles, + disabled, + emit, + onUser + }; + }, +}); +</script> +<style scoped lang="scss"> +.textarea { + height: 168px !important; +} +.textarea ::v-deep .el-textarea__inner { + height: 168px !important; +} +::v-deep .el-table__cell { + font-weight: 400; +} +.el-divider--horizontal { + height: 0; + margin: 0; + border-top: transparent; +} +.el-select { + width: 100%; +} +</style> \ No newline at end of file diff --git a/src/views/contingencyManagement/emergencyResources/emergencySupplies/component/openEdit.vue b/src/views/contingencyManagement/emergencyResources/emergencySupplies/component/openEdit.vue new file mode 100644 index 0000000..f5b2e61 --- /dev/null +++ b/src/views/contingencyManagement/emergencyResources/emergencySupplies/component/openEdit.vue @@ -0,0 +1,549 @@ +<template> + <div class="system-edit-user-container"> + <el-dialog :title="titles" v-model="isShowDialog" @close="resetForm(ruleFormRef)" width="50%" draggable :fullscreen="full"> + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-form ref="ruleFormRef" :rules="rules" :model="ruleForm" size="default" label-width="120px" :disabled="disabled"> + <el-row :gutter="35"> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="物资名称" prop="name"> + <el-input v-model="ruleForm.name" placeholder="请填写物资名称"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="物资编号" prop="number"> + <el-input v-model="ruleForm.number" placeholder="请填写物资编号"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="物资用途" prop="use"> + <el-input v-model="ruleForm.use" placeholder="请填写物资用途"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="投用日期" prop="useDate"> + <el-date-picker v-model="ruleForm.useDate" type="datetime" class="w100" placeholder="选择日期时间" value-format="YYYY-MM-DD HH:mm:ss" /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="物资型号" prop="model"> + <el-input v-model="ruleForm.model" placeholder="请填写物资型号"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="负责部门" prop="departmentId"> + <el-tree-select v-model="ruleForm.departmentId" :data="data" class="w100" :props="propse" placeholder="请选择" /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="物资分类" prop="classification"> + <el-select v-model="ruleForm.classification" class="w100" placeholder="请选择"> + <el-option label="事故气体吸收装置" value="1"></el-option> + <el-option label="通讯设施" value="2"></el-option> + <el-option label="交通运输工具" value="3"></el-option> + <el-option label="照明装置" value="4"></el-option> + <el-option label="防护器材" value="5"></el-option> + <el-option label="其它" value="6"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="存放位置" prop="place"> + <el-input v-model="ruleForm.place" placeholder="请填写存放位置"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="存储数量" prop="count"> + <el-input v-model.number="ruleForm.count" maxlength="6" placeholder="请填写存储数量"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="生产日期" prop="productionDate"> + <el-date-picker + v-model="ruleForm.productionDate" + type="datetime" + class="w100" + placeholder="选择日期时间" + value-format="YYYY-MM-DD HH:mm:ss" + /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="使用期限(天)" prop="usePeriod"> + <el-input v-model.number="ruleForm.usePeriod" maxlength="6" placeholder="请填写使用期限"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="物资状态" prop="status"> + <el-select v-model="ruleForm.status" class="w100" placeholder="请选择"> + <el-option label="完好" value="1"></el-option> + <el-option label="维修" value="2"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="检查周期月" prop="inspectPeriod"> + <el-input v-model.number="ruleForm.inspectPeriod" type="" maxlength="4" placeholder="请填写使用期限"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="使用说明"> + <el-input v-model="ruleForm.useExplain" type="textarea" placeholder="请填写使用说明"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="检查日期" prop="inspectDate"> + <el-date-picker + v-model="ruleForm.inspectDate" + type="datetime" + class="w100" + placeholder="选择日期时间" + value-format="YYYY-MM-DD HH:mm:ss" + /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="下次检查日期" prop="nextInspectDate"> + <el-date-picker + v-model="ruleForm.nextInspectDate" + type="datetime" + value-format="YYYY-MM-DD HH:mm:ss" + class="w100" + placeholder="选择日期时间" + /> + </el-form-item> + </el-col> + <!-- <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">--> + <!-- <el-form-item label="经度(度)">--> + <!-- <el-input v-model="ruleForm.longitude" placeholder="请填写经度(度)"></el-input>--> + <!-- </el-form-item>--> + <!-- </el-col>--> + <!-- <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">--> + <!-- <el-form-item label="纬度(度)">--> + <!-- <el-input v-model="ruleForm.latitude" placeholder="请填写纬度(度)"></el-input>--> + <!-- </el-form-item>--> + <!-- </el-col>--> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="负责人" prop="principalUserName"> + <el-input v-model="ruleForm.principalUserName" placeholder="请选择" class="input-with-select"> + <template #append> + <el-button :icon="Search" @click="daiInpt" /> + </template> + </el-input> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="24"> + <el-form-item label="保养记录"> + <el-table :data="ruleForm.maintainList" highlight-current-row> + <el-table-column align="center" label="保养结果" prop="maintainResult"> + <template #default="scope"> + <el-select size="mini" disabled v-model="scope.row.maintainResult"> + <el-option label="正常" value="1"></el-option> + <el-option label="异常" value="2"></el-option> + </el-select> + </template> + </el-table-column> + <el-table-column align="center" label="创建人" prop="userName"></el-table-column> + <el-table-column align="center" label="创建时间" prop="maintainTime"></el-table-column> + </el-table> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="24"> + <el-form-item label="检查记录"> + <el-table :data="ruleForm.inspectList" highlight-current-row> + <el-table-column align="center" label="检查结果" prop="maintainResult"> + <template #default="scope"> + <el-select size="mini" disabled v-model="scope.row.inspectResult"> + <el-option label="正常" value="1"></el-option> + <el-option label="异常" value="2"></el-option> + </el-select> + </template> + </el-table-column> + <el-table-column align="center" label="创建人" prop="userName"></el-table-column> + <el-table-column align="center" label="创建时间" prop="inspectTime"></el-table-column> + </el-table> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="resetForm(ruleFormRef)" size="default">关闭</el-button> + <el-button size="default" type="primary" v-if="disabled == true ? false : true" @click="submitForm(titles, ruleFormRef)">确定</el-button> + </span> + </template> + </el-dialog> + <DailogSearchUser ref="Shows" @SearchUser="onUser"></DailogSearchUser> + <userSelections ref="userRef" /> + <RegionsCheckbox ref="openRef" /> + </div> +</template> + +<script lang="ts"> +import { reactive, ref, defineComponent } from 'vue'; +import DailogSearchUser from '/@/components/DailogSearchUser/index.vue'; +import type { FormInstance, FormRules } from 'element-plus'; +import { ElMessage } from 'element-plus'; + +import { Search, FullScreen } from '@element-plus/icons-vue'; +import UserSelections from '../../../../../components/userSelections/index.vue'; +import PersonInCharge from '../component/personInCharge.vue'; +import RegionsCheckbox from '../component/regionsCheckbox.vue'; +import { emergencySuppliesApi } from '../../../../../api/contingencyManagement/emergencyResources'; +import { goalManagementApi } from '/@/api/goalManagement'; +import { AnyAaaaRecord } from 'dns'; +export default defineComponent({ + name: 'openAdd', + components: { + DailogSearchUser, + UserSelections, + RegionsCheckbox, + }, + setup(props, { emit }) { + const isShowDialog = ref(false); + + const ruleFormRef = ref<FormInstance>(); + //定义表单 + const ruleForm = ref({ + productionDate: '', + useDate: '', + inspectDate: '', + nextInspectDate: '', + inspectPeriod: '', + count: '', + usePeriod: '', + departmentId: '', + principalUserUid: '', + principalUserName:"", + status: '', + classification: '', + name: '', + number: '', + model: '', + longitude: '', + latitude: '', + use: '', + areaId: null, + place: '', + useExplain: '', + }); + const titles = ref(); + const disabled = ref(); + // 打开弹窗 + const openDialog = (title: string, id: number, type: boolean) => { + department() + isShowDialog.value = true; + titles.value = title; + disabled.value = type; + if (title == '查看应急物资代码' || title == '修改应急物资代码') { + emergencySuppliesApi() + .seeEmergencySupplies(id) + .then((res) => { + if (res.data.code == 200) { + ruleForm.value = res.data.data; + userNames(res.data.data.maintainList) + userNames(res.data.data.inspectList) + } + }); + } + }; + const userNames=(data:AnyAaaaRecord)=>{ + for(let i=0;i<data.length;i++){ + let arr=[] + for(let s=0;s<data[i].userList.length;s++){ + arr.push(data[i].userList[s].userName) + } + + data[i].userName=arr.toString() + } + } + //日期选择器 + const value1 = ref(''); + // 可选择树 + const treeSelect = ref(); + //部门树 + const department = () => { + goalManagementApi() + .getTreedepartment() + .then((res) => { + if (res.data.code == 200) { + data.value = res.data.data; + } else { + ElMessage.error(res.data.msg); + } + }); + }; + //定义树形下拉框 + const responsibleDepartment = ref(); + const data = ref(); + const propse = { + label: 'depName', + children: 'children', + value: 'depId', + }; + // 必填项提示 + const rules = reactive<FormRules>({ + name: [ + { + required: true, + message: '物资名称不能为空', + trigger: 'change', + }, + ], + number: [ + { + required: true, + message: '物资编号不能为空', + trigger: 'change', + }, + ], + use: [ + { + required: true, + message: '物资用途不能为空', + trigger: 'change', + }, + ], + model: [ + { + required: true, + message: '物资型号不能为空', + trigger: 'change', + }, + ], + departmentId: [ + { + required: true, + message: '负责部门不能为空', + trigger: 'change', + }, + ], + classification: [ + { + required: true, + message: '物资分类不能为空', + trigger: 'change', + }, + ], + place: [ + { + required: true, + message: '存放位置不能为空', + trigger: 'change', + }, + ], + count: [ + { + required: true, + message: '存储数量不能为空', + trigger: 'change', + }, + { type: 'number', message: '请输入数字类型', trigger: 'change' }, + ], + productionDate: [ + { + required: true, + message: '生产日期不能为空', + trigger: 'blur', + }, + ], + usePeriod: [ + { + required: true, + message: '使用期限不能为空', + trigger: 'blur', + }, + { type: 'number', message: '请输入数字类型', trigger: 'change' }, + ], + status: [ + { + required: true, + message: '物资状态不能为空', + trigger: 'change', + }, + ], + inspectPeriod: [ + { + required: true, + message: '检查周期月不能为空', + trigger: 'change', + }, + { type: 'number', message: '请输入数字类型', trigger: 'change' }, + ], + useDate: [ + { + required: true, + message: '投用日期不能为空', + trigger: 'blur', + }, + ], + inspectDate: [ + { + required: true, + message: '检查日期不能为空', + trigger: 'blur', + }, + ], + nextInspectDate: [ + { + required: true, + message: '下次检查日期不能为空', + trigger: 'blur', + }, + ], + principalUserName:[], + }); + // 表单提交验证必填项 + const submitForm = async (title: string, formEl: FormInstance | undefined) => { + if (title == '新建应急物资代码') { + if (!formEl) return; + await formEl.validate((valid, fields) => { + if (valid) { + isShowDialog.value = false; + emergencySuppliesApi() + .addEmergencySupplies(ruleForm.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'success', + }); + emit('myAdd', true); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + emit('myAdd', true); + } + formEl.resetFields(); + }); + } else { + console.log('error submit!', fields); + } + }); + } else if (title == '修改应急物资代码') { + if (!formEl) return; + await formEl.validate((valid, fields) => { + if (valid) { + isShowDialog.value = false; + emergencySuppliesApi() + .editEmergencySupplies(ruleForm.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: '修改成功', + type: 'success', + }); + emit('myAdd', true); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + emit('myAdd', true); + } + formEl.resetFields(); + }); + } else { + console.log('error submit!', fields); + } + }); + formEl.resetFields(); + } + }; + const resetForm = (formEl: FormInstance | undefined) => { + isShowDialog.value = false; + if (!formEl) return; + formEl.resetFields(); + }; + // 人名 + const Shows = ref(); + const daiInpt = () => { + Shows.value.openDailog(); + }; + // 选择区域弹窗 + const openRef = ref(); + const regionsDialog = () => { + openRef.value.openDailog(); + }; + // 打开用户选择弹窗 + const userRef = ref(); + const openUser = () => { + userRef.value.openDialog(); + }; + const dataList = ref(); + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + const onUser = (e: any) => { + ruleForm.value.principalUserUid = e.uid; + ruleForm.value.principalUserName = e.realName; + }; + return { + onUser, + userNames, + openDialog, + isShowDialog, + responsibleDepartment, + data, + Search, + ruleForm, + value1, + treeSelect, + daiInpt, + Shows, + ruleFormRef, + submitForm, + rules, + openUser, + userRef, + regionsDialog, + openRef, + toggleFullscreen, + FullScreen, + full, + resetForm, + titles, + disabled, + emit, + dataList, + propse, + department + }; + }, +}); +</script> +<style scoped lang="scss"> +.textarea { + height: 168px !important; +} +.textarea ::v-deep .el-textarea__inner { + height: 168px !important; +} +::v-deep .el-table__cell { + font-weight: 400; +} +.el-divider--horizontal { + height: 0; + margin: 0; + border-top: transparent; +} +.el-select { + width: 100%; +} +</style> \ No newline at end of file diff --git a/src/views/contingencyManagement/emergencyResources/emergencySupplies/component/personInCharge.vue b/src/views/contingencyManagement/emergencyResources/emergencySupplies/component/personInCharge.vue new file mode 100644 index 0000000..2e719ea --- /dev/null +++ b/src/views/contingencyManagement/emergencyResources/emergencySupplies/component/personInCharge.vue @@ -0,0 +1,213 @@ +<template> + <el-dialog + v-model="dialogVisible" + title="选择岗位id" + width="900px" + draggable + :fullscreen="full" + > + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-row> + <el-col :span="18"> + <el-row> + <el-col :span="24"> + <el-form ref="ruleFormRef" :model="ruleForm" :inline="true" status-icon> + <el-form-item> + <el-input size="default" v-model="ruleForm.pass" placeholder="编号" style="max-width: 215px;"/> + </el-form-item> + <el-form-item> + <el-input size="default" v-model="ruleForm.checkPass" placeholder="姓名" style="max-width: 215px;padding: 0 12px;"/> + </el-form-item> + <el-form-item> + <el-button size="default" type="primary" @click="submitForm(ruleFormRef)">查询</el-button> + <el-button size="default" @click="resetForm(ruleFormRef)">重置</el-button> + </el-form-item> + </el-form> + </el-col> + <el-col :span="24"> + <el-button size="default" :icon="Delete" style="margin-top: 15px;">清除选择</el-button> + </el-col> + </el-row> + <el-table + :data="tableData" + ref="multipleTableRef" + style="width: 100%;margin-top:20px" + > + <el-table-column align="center" width="55"> + <template #default="scope"> + <el-radio-group v-model="radio1" @change="radio"> + <el-radio :label="scope.row.name" size="large">{{null}}</el-radio> + </el-radio-group> + </template> + </el-table-column> + <el-table-column align="center" prop="date" label="编号" /> + <el-table-column align="center" prop="name" label="姓名"/> + </el-table> + <div class="pages"> + <el-pagination + v-model:currentPage="currentPage4" + v-model:page-size="pageSize4" + :page-sizes="[100, 200, 300, 400]" + :small="small" + :disabled="disabled" + :background="background" + layout="total, sizes, prev, pager, next, jumper" + :total="400" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + </el-col> + <el-col :span="6" style="padding-left: 15px"> + <el-tag + v-for="tag in dynamicTags" + :key="tag" + class="mx-1" + style="margin: 5px" + closable + :disable-transitions="false" + @close="handleClose(tag)" + > + {{ tag }} + </el-tag> + </el-col> + </el-row> + <template #footer> + <span class="dialog-footer"> + <el-button @click="dialogVisible = false" size="default">关闭</el-button> + <el-button type="primary" @click="dialogVisible = false" size="default">确定</el-button> + </span> + </template> + </el-dialog> +</template> +<script lang="ts"> +import { + defineComponent, + reactive, + ref, +} from 'vue'; +import { + Delete, + FullScreen +} from '@element-plus/icons-vue'; +interface User { + date: string + name: string + address: string +} +export default defineComponent({ + setup() { + const dialogVisible = ref<boolean>(false); + const openDailog = () => { + dialogVisible.value = true; + }; + // 搜索条件 + const ruleForm = reactive({ + pass: '', + checkPass: '', + }); + // 表格 + const tableData = [ + { + date: '6421cbc6cbb5493eabf9b27e83372d78', + name: '金伟', + }, + { + date: '6421cbc6cbb5493eabf9b27e83372d78', + name: '施凯健', + }, + { + date: '6421cbc6cbb5493eabf9b27e83372d78', + name: '程雪', + }, + { + date: '6421cbc6cbb5493eabf9b27e83372d78', + name: '杨恒', + }, + ]; + const pageSize4 = ref(100); + const handleSizeChange = (val: number) => { + console.log(`${val} items per page`); + }; + const handleCurrentChange = (val: number) => { + console.log(`current page: ${val}`); + }; + // 右方点击添加后显示标签 + const dynamicTags = ref(['杨恒']); + const handleClose = (tag: string) => { + dynamicTags.value.splice(dynamicTags.value.indexOf(tag), 1); + radio1.value="" + }; + const radio1=ref('金伟') + const radio=(event:any)=>{ + dynamicTags.value[0]=event + } + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + return { + dialogVisible, + openDailog, + ruleForm, + tableData, + pageSize4, + handleSizeChange, + handleCurrentChange, + dynamicTags, + handleClose, + Delete, + radio1, + radio, + toggleFullscreen, + FullScreen, + full, + }; + }, +}); +</script> +<style scoped> +.el-form--inline .el-form-item{ + margin-bottom: 0; + margin-right: 0; +} +/*分页*/ +.pages{ + /*display: flex;*/ + /*justify-content: flex-end;*/ + margin-top: 15px; +} +::v-deep .el-pagination .el-pager li { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +::v-deep .el-pagination .el-pager li.is-active { + background-color: #409eff; + color: #fff; +} +::v-deep .el-pagination .btn-prev { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +::v-deep .el-pagination button:disabled{ + color: #c0c4cc; +} +::v-deep .el-pagination .btn-next{ + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +</style> diff --git a/src/views/contingencyManagement/emergencyResources/emergencySupplies/component/regionsCheckbox.vue b/src/views/contingencyManagement/emergencyResources/emergencySupplies/component/regionsCheckbox.vue new file mode 100644 index 0000000..d8d1973 --- /dev/null +++ b/src/views/contingencyManagement/emergencyResources/emergencySupplies/component/regionsCheckbox.vue @@ -0,0 +1,164 @@ +<template> + <el-dialog + v-model="dialogVisible" + title="选择区域" + width="900px" + draggable + :fullscreen="full" + > + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-row> + <el-col :span="18"> + <el-form :inline="true" ref="ruleFormRef" :model="ruleForm" status-icon> + <el-form-item> + <el-input size="default" v-model="ruleForm.checkPass" placeholder="风险区域名称" style="max-width: 215px;" /> + </el-form-item> + <el-form-item> + <el-button size="default" type="primary" @click="submitForm(ruleFormRef)" style="margin-left: 12px;">查询</el-button> + <el-button size="default" @click="resetForm(ruleFormRef)">重置</el-button> + </el-form-item> + <el-button size="default" :icon="Delete" style="margin-left: 12px;">清除选择</el-button> + </el-form> + <el-table :data="tableData" style="width: 100%;margin-top:20px;"> + <el-table-column align="center" width="55"> + <template #default="scope"> + <el-radio-group v-model="radio1" @change="radio"> + <el-radio :label="scope.row.name" size="large">{{null}}</el-radio> + </el-radio-group> + </template> + </el-table-column> + <el-table-column align="center" prop="name" label="风险区域名称"/> + </el-table> + <div class="pages"> + <el-pagination + v-model:currentPage="pageIndex" + v-model:page-size="pageSize" + :page-sizes="[10, 20, 30]" + :pager-count="5" + :small="small" + :disabled="disabled" + :background="background" + layout="total, sizes, prev, pager, next, jumper" + :total="40" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + </el-col> + <el-col :span="6" style="padding-left: 15px;"> + <el-tag + v-for="tag in dynamicTags" + :key="tag" + class="mx-1" + style="margin: 5px" + closable + :disable-transitions="false" + @close="handleClose(tag)" + > + {{ tag }} + </el-tag> + </el-col> + </el-row> + <template #footer> + <span class="dialog-footer"> + <el-button @click="dialogVisible = false" size="default">关闭</el-button> + <el-button type="primary" @click="dialogVisible = false" size="default">确定</el-button> + </span> + </template> + </el-dialog> +</template> +<script lang="ts"> +import { + defineComponent, + reactive, + ref +} from 'vue'; +import { + Delete, + FullScreen +} from '@element-plus/icons-vue'; +export default defineComponent({ + setup() { + const dialogVisible = ref<boolean>(false); + const openDailog = () => { + dialogVisible.value = true; + }; + // 搜索条件 + const ruleForm = reactive({ + checkPass: '', + }); + // 表格 + const tableData = [ + { + name: '1#LNG储罐单元', + }, + { + name: 'LNG装车区', + }, + { + name: '丙烷储罐区', + }, + { + name: '4#LNG储罐单元', + }, + ]; + // 右方点击添加后显示标签 + const dynamicTags = ref(['LNG装车区']); + const handleClose = (tag: string) => { + dynamicTags.value.splice(dynamicTags.value.indexOf(tag), 1); + radio1.value="" + }; + const radio1=ref('1#LNG储罐单元') + const radio=(event:any)=>{ + dynamicTags.value[0]=event + } + + // 分页 + const pageIndex = ref(4); + const pageSize = ref(10); + // 分页改变 + const handleSizeChange = (val: number) => { + console.log(`${val} items per page`); + }; + // 分页未改变 + const handleCurrentChange = (val: number) => { + console.log(`current page: ${val}`); + }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + return { + dialogVisible, + openDailog, + ruleForm, + tableData, + handleSizeChange, + handleCurrentChange, + pageIndex, + pageSize, + radio1, + radio, + dynamicTags, + handleClose, + Delete, + toggleFullscreen, + FullScreen, + full, + }; + }, +}); +</script> +<style scoped> +.el-row { + padding: 0 0 20px 0; +} +.el-form--inline .el-form-item{ + margin: 0; +} +</style> diff --git a/src/views/contingencyManagement/emergencyResources/emergencySupplies/index.vue b/src/views/contingencyManagement/emergencyResources/emergencySupplies/index.vue new file mode 100644 index 0000000..afe1cd7 --- /dev/null +++ b/src/views/contingencyManagement/emergencyResources/emergencySupplies/index.vue @@ -0,0 +1,397 @@ +<template> + <div class="system-user-container"> + <el-card shadow="hover"> + <div class="system-user-search mb15"> + <el-input size="default" v-model="listQuery.searchParams.name" placeholder="物资名称" style="max-width: 215px" /> + <el-button size="default" type="primary" class="ml10" @click="listApi"> 查询 </el-button> + <el-button size="default" class="ml10" @click="submitReset"> 重置 </el-button> + </div> + <div class="button_Line"> + <div class="button_Left"> + <el-button size="default" type="primary" @click="onOpenAdd"> + <el-icon> <Plus /> </el-icon>新建 + </el-button> + <el-button size="default" type="warning" plain :disabled="warning" @click="onEdit('修改', deletAll[0])"> + <el-icon> <Edit /> </el-icon>修改 + </el-button> + <el-button size="default" type="danger" plain @click="onDeleteAll" :disabled="danger"> + <el-icon> <Delete /> </el-icon>删除 + </el-button> + </div> + <div class="button_Right"> + <!-- <el-button @click="upButton">--> + <!-- <el-icon>--> + <!-- <Upload />--> + <!-- </el-icon>--> + <!-- </el-button>--> + <!-- <el-button>--> + <!-- <el-icon>--> + <!-- <Refresh />--> + <!-- </el-icon>--> + <!-- </el-button>--> + </div> + </div> + <el-table :data="tableData" style="width: 100%" ref="multipleTableRef" @selection-change="handleSelectionChange"> + <el-table-column align="center" type="selection" width="55" /> + <el-table-column align="center" prop="name" label="物资名称" min-width="120" show-overflow-tooltip sortable></el-table-column> + <el-table-column align="center" prop="number" label="物资编号" min-width="120" show-overflow-tooltip sortable></el-table-column> + <el-table-column align="center" prop="deptName" label="负责部门" min-width="120" show-overflow-tooltip sortable></el-table-column> + <el-table-column align="center" label="物资分类" min-width="120" show-overflow-tooltip sortable> + <template #default="scope"> + <span v-if="scope.row.classification == 1">事故气体吸收装置</span><span v-if="scope.row.classification == 2">通讯设施</span + ><span v-if="scope.row.classification == 3">交通运输工具</span><span v-if="scope.row.classification == 4">照明装置</span + ><span v-if="scope.row.classification == 5">防护器材</span><span v-if="scope.row.classification == 6">其它</span> + </template> + </el-table-column> + <el-table-column align="center" prop="place" label="存放位置" min-width="120" show-overflow-tooltip sortable></el-table-column> + <el-table-column align="center" prop="count" label="存储数量" min-width="120" show-overflow-tooltip sortable></el-table-column> + <el-table-column label="操作" width="200" align="center" fixed="right"> + <template #default="scope"> + <el-button size="small" text type="primary" @click="onMaintain(scope.row)"> + <el-icon style="margin-right: 5px"> <EditPen /> </el-icon>保养 + </el-button> + <el-button size="small" text type="primary" @click="onInspect(scope.row)"> + <el-icon style="margin-right: 5px"> <EditPen /> </el-icon>检查 + </el-button> + <el-button size="small" text type="primary" @click="onEdit('详情', scope.row.id)"> + <el-icon style="margin-right: 5px"> <View /> </el-icon>查看 + </el-button> + <el-button size="small" text type="primary" @click="onEdit('修改', scope.row.id)"> + <el-icon style="margin-right: 5px"> + <EditPen /> + </el-icon> + 修改 + </el-button> + <el-button size="small" text type="primary" @click="onRowDel(scope.row.id)"> + <el-icon> <Delete /> </el-icon>删除 + </el-button> + </template> + </el-table-column> + </el-table> + <div class="pages"> + <el-pagination + v-if="tableData.length == 0 ? false : true" + v-model:currentPage="pageIndex" + v-model:page-size="pageSize" + :page-sizes="[10, 20, 30]" + :pager-count="5" + layout="total, sizes, prev, pager, next, jumper" + :total="total" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + </el-card> + <Maintain ref="seeRef" @myadd="onMaintainAdd" /> + <Inspect ref="spectRef" @myadd="onInspectAdd" /> + <OpenAdd ref="addRef" @myAdd="onMyAdd" /> + <OpenEdit ref="editRef" @myAdd="onMyAdds" /> + <!-- <upData ref="upShow"></upData>--> + </div> +</template> + +<script lang="ts"> +import { ref, defineComponent, reactive, onMounted } from 'vue'; +import { + ElMessageBox, + ElMessage, + // ElTable +} from 'element-plus'; +import { Plus, Edit, Delete, Upload, Refresh, View, EditPen } from '@element-plus/icons-vue'; +import OpenAdd from '/@/views/contingencyManagement/emergencyResources/emergencySupplies/component/openAdd.vue'; +import Maintain from '/@/views/contingencyManagement/emergencyResources/emergencySupplies/component/maintain.vue'; +import Inspect from '/@/views/contingencyManagement/emergencyResources/emergencySupplies/component/inspect.vue'; +import OpenEdit from '/@/views/contingencyManagement/emergencyResources/emergencySupplies/component/openEdit.vue'; +import UpData from '/@/views/contingencyManagement/panManagement/component/upData.vue'; +import { emergencySuppliesApi } from '/@/api/contingencyManagement/emergencyResources'; + +export default defineComponent({ + name: 'systemUser', + components: { + OpenAdd, + Maintain, + View, + OpenEdit, + EditPen, + Plus, + Edit, + Delete, + Upload, + // Download, + Inspect, + Refresh, + UpData, + }, + setup() { + // 列表参数 + const listQuery = reactive({ + pageIndex: 1, + pageSize: 10, + searchParams: { + name: '', + }, + }); + // 定义表格数据 + const tableData = ref([]); + // 请求列表数据 + const listApi = async () => { + let res = await emergencySuppliesApi().getEmergencySuppliesList(listQuery); + // console.log(res); + if (res.data.code == 200) { + tableData.value = res.data.data; + pageIndex.value = res.data.pageIndex; + pageSize.value = res.data.pageSize; + total.value = res.data.total; + } else { + ElMessage.error(res.data.msg); + } + }; + //重置 + const submitReset = () => { + listQuery.searchParams.name = ''; + listApi(); + }; + const warning = ref(true); + const danger = ref(true); + const deletAll = ref(); + const handleSelectionChange = (val: any) => { + let valId = JSON.parse(JSON.stringify(val)); + let arr = []; + for (let i = 0; i < valId.length; i++) { + arr.push(valId[i].id); + } + deletAll.value = arr; + // console.log(deletAll.value); + if (val.length == 1) { + warning.value = false; + danger.value = false; + } else if (val.length == 0) { + warning.value = true; + danger.value = true; + } else { + warning.value = true; + danger.value = false; + } + }; + // 页面加载时 + onMounted(() => { + listApi(); + }); + // 上传 + // const upShow = ref(); + // const upButton = () => { + // upShow.value.openDialog(); + // }; + + //新增应急物资检查弹窗 + const seeRef = ref(); + const onMaintain = (data: any) => { + seeRef.value.openDialog(data); + }; + // 应急物资保养新增后刷新 + const onMaintainAdd = () => { + listApi(); + }; + //修改应急物资检查弹窗 + const spectRef = ref(); + const onInspect = (data: any) => { + spectRef.value.openDialog(data); + }; + // 应急物资检查新增后刷新 + const onInspectAdd = (e: boolean) => { + if (e) { + listApi(); + } else { + listApi(); + } + }; + // 新建应急物资代码弹窗 + const addRef = ref(); + const onOpenAdd = () => { + addRef.value.openDialog('新建应急物资代码', false); + }; + // 新增后刷新 + const onMyAdd = (e: boolean) => { + if (e) { + listApi(); + } else { + listApi(); + } + }; + // 打开修改用户弹窗 + const editRef = ref(); + const onEdit = (val: string, row: object) => { + if (val == '详情') { + editRef.value.openDialog('查看应急物资代码', row, true); + } else { + editRef.value.openDialog('修改应急物资代码', row, false); + } + }; + // 新增后刷新 + const onMyAdds = (e: boolean) => { + if (e) { + listApi(); + } else { + listApi(); + } + }; + // 删除用户 + const onRowDel = (id: number) => { + let arr = []; + arr.push(id); + ElMessageBox.confirm('确定删除所选项吗?', '提示', { + confirmButtonText: '确认', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + emergencySuppliesApi() + .deleteEmergencySupplies(arr) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'success', + }); + listApi(); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + listApi(); + } + }); + }) + .catch(() => {}); + }; + // 多选删除 + const onDeleteAll = () => { + ElMessageBox.confirm('确定删除所选项吗?', '提示', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + emergencySuppliesApi() + .deleteEmergencySupplies(deletAll.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'success', + }); + listApi(); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + listApi(); + } + }); + }) + .catch(() => {}); + }; + // 分页 + const pageIndex = ref(); + const pageSize = ref(); + const total = ref(); + // 分页条数 + const handleSizeChange = (val: number) => { + // console.log(`${val} items per page`); + listQuery.pageSize = val; + }; + // 分页数 + const handleCurrentChange = (val: number) => { + // console.log(`current page: ${val}`); + listQuery.pageIndex = val; + }; + return { + // upButton, + // upShow, + tableData, + onMaintain, //保养 + seeRef, + onOpenAdd, //新增 + addRef, + onRowDel, + pageIndex, + pageSize, + total, + handleSizeChange, + handleCurrentChange, + listQuery, + listApi, + onMounted, + submitReset, + onMyAdd, + onEdit, + editRef, + onDeleteAll, + handleSelectionChange, + warning, + danger, + spectRef, + onInspect, + onMaintainAdd, + onInspectAdd, + onMyAdds, + deletAll + }; + }, +}); +</script> +<style scoped lang="scss"> +.table_Box { + padding: 20px; + background-color: #fff; +} +.tableForm { + margin-top: 10px; +} +/*按钮行*/ +.button_Line { + display: flex; + flex-direction: row; + justify-content: space-between; +} +//分页 +.pages { + display: flex; + justify-content: flex-end; + margin-top: 15px; +} +::v-deep .el-pagination .el-pager li { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +::v-deep .el-pagination .el-pager li.is-active { + background-color: #409eff; + color: #fff; +} +::v-deep .el-pagination .btn-prev { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +::v-deep .el-pagination button:disabled { + color: #c0c4cc; +} +::v-deep .el-pagination .btn-next { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +</style> \ No newline at end of file diff --git a/src/views/contingencyManagement/emergencyResources/maintenanceOfEmergencyMaterials/component/openAdd.vue b/src/views/contingencyManagement/emergencyResources/maintenanceOfEmergencyMaterials/component/openAdd.vue new file mode 100644 index 0000000..d746a59 --- /dev/null +++ b/src/views/contingencyManagement/emergencyResources/maintenanceOfEmergencyMaterials/component/openAdd.vue @@ -0,0 +1,277 @@ +<template> + <div class="system-edit-user-container"> + <el-dialog :title="titles" v-model="isShowDialog" width="50%" @close="resetForm(ruleFormRef)" draggable :fullscreen="full"> + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-form ref="ruleFormRef" :rules="rules" :model="ruleForm" size="default" label-width="120px" :disabled="disabled"> + <el-row :gutter="35"> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="应急物资" prop="suppliesName"> + <el-input v-model="ruleForm.suppliesName" placeholder="请选择" class="input-with-select"> + <template #append> + <el-button :icon="Search" @click="daiInpt" /> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="保养结果" prop="maintainResult"> + <el-select v-model="ruleForm.maintainResult" class="w100" placeholder="请选择"> + <el-option label="正常" value="1"></el-option> + <el-option label="异常" value="2"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="创建人" prop="userName"> + <el-input v-model="ruleForm.userName" placeholder="请选择" class="input-with-select"> + <template #append> + <el-button :icon="Search" @click="openUser(0)" /> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="创建时间" prop="maintainTime"> + <el-date-picker + class="w100" + v-model="ruleForm.maintainTime" + type="datetime" + value-format="YYYY-MM-DD HH:mm:ss" + placeholder="选择日期时间" + /> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="resetForm(ruleFormRef)" size="default">关闭</el-button> + <el-button size="default" type="primary" v-if="disabled == true ? false : true" @click="submitForm(ruleFormRef)">确定</el-button> + </span> + </template> + </el-dialog> + <EmergencySupplies ref="showRef" @SearchUser="onUser" /> + <DailogSearchUser ref="userRef" @SearchUser="onUsers" /> + </div> +</template> + +<script lang="ts"> +import { ref, defineComponent, reactive } from 'vue'; + +import type { FormInstance, FormRules } from 'element-plus'; +import { ElMessage } from 'element-plus'; +import { Search, FullScreen } from '@element-plus/icons-vue'; +import EmergencySupplies from '../../../../../components/emergencySupplies/index.vue'; +import DailogSearchUser from '/@/components/DailogSearchUser/index.vue'; +import { maintenanceEmergencyMaterialsApi } from '../../../../../api/contingencyManagement/maintenanceEmergencyMaterials'; + +export default defineComponent({ + name: 'openAdd', + components: { + DailogSearchUser, + EmergencySupplies, + }, + setup(props, { emit }) { + const isShowDialog = ref(false); + + const ruleFormRef = ref<FormInstance>(); + //定义表单 + const ruleForm = ref({ + suppliesId: '', // 物资ID + maintainResult: '', //保养结果 + maintainTime: '', // 创建时间 + userList: [], + }); + const titles = ref(); + const disabled = ref(); + // 打开弹窗 + const openDialog = (title: string, id: number) => { + isShowDialog.value = true; + titles.value = `${title}应急物资保养`; + disabled.value = title == '查看' ? true : false; + if (title == '查看' || title == '修改') { + maintenanceEmergencyMaterialsApi() + .seeMaintenanceEmergencyMaterials(id) + .then((res) => { + if (res.data.code == 200) { + ruleForm.value = res.data.data; + let arr = []; + for (let i = 0; i < ruleForm.value.userList.length; i++) { + arr.push(ruleForm.value.userList[i].userName); + } + ruleForm.value.userName = arr.toString(); + } + }); + } + }; + //日期选择器 + const maintainTime = ref(''); + // 表单提交验证必填项 + const submitForm = async (formEl: FormInstance | undefined) => { + if (!formEl) return; + await formEl.validate((valid, fields) => { + if (valid) { + if (titles.value == '新建应急物资保养') { + delete ruleForm.value.suppliesName + delete ruleForm.value.userName + delete ruleForm.value.id + maintenanceEmergencyMaterialsApi() + .addMaintenanceEmergencyMaterials(ruleForm.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'success', + }); + emit('myAdd', true); + isShowDialog.value = false; + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + emit('myAdd', true); + } + }); + } else if (titles.value == '修改应急物资保养') { + delete ruleForm.value.suppliesName + delete ruleForm.value.userName + maintenanceEmergencyMaterialsApi() + .editMaintenanceEmergencyMaterials(ruleForm.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: '修改成功', + type: 'success', + }); + emit('myAdd', true); + isShowDialog.value = false; + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + emit('myAdd', true); + } + formEl.resetFields(); + }); + } + } else { + console.log('error submit!', fields); + } + }); + + }; + const resetForm = (formEl: FormInstance | undefined) => { + isShowDialog.value = false; + if (!formEl) return; + formEl.resetFields(); + ruleForm.value.userList=[] + }; + const rules = reactive<FormRules>({ + nameTitle: [], + maintainResult: [ + { + required: true, + message: '保养结果不能为空', + trigger: 'change', + }, + ], + userName: [ + { + required: true, + message: '创建人不能为空', + trigger: 'change', + }, + ], + maintainTime: [ + { + required: true, + message: '创建时间不能为空', + trigger: 'blur', + }, + ], + }); + // 应急物资弹窗 + const showRef = ref(); + const daiInpt = () => { + showRef.value.openDailog(); + }; + const onUser = (e: any) => { + ruleForm.value.suppliesId = e.id; + ruleForm.value.suppliesName = e.name; + }; + // 编写人弹窗 + const userRef = ref(); + const openUser = (data: any) => { + userRef.value.openDailog(data); + }; + const onUsers = (val: any) => { + let arr = []; + for (let i = 0; i < val.length; i++) { + arr.push(val[i].realName); + ruleForm.value.userList.push({ + userUid: val[i].uid, + userName: val[i].realName, + }); + } + ruleForm.value.userName = arr.toString(); + }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + return { + openDialog, + isShowDialog, + Search, + ruleForm, + maintainTime, + daiInpt, + onUser, + onUsers, + rules, + showRef, + ruleFormRef, + submitForm, + openUser, + userRef, + toggleFullscreen, + FullScreen, + full, + resetForm, + titles, + disabled, + emit, + }; + }, +}); +</script> +<style scoped lang="scss"> +.textarea { + height: 168px !important; +} +.textarea ::v-deep .el-textarea__inner { + height: 168px !important; +} +::v-deep .el-table__cell { + font-weight: 400; +} +.el-divider--horizontal { + height: 0; + margin: 0; + border-top: transparent; +} +.el-select { + width: 100%; +} +</style> \ No newline at end of file diff --git a/src/views/contingencyManagement/emergencyResources/maintenanceOfEmergencyMaterials/index.vue b/src/views/contingencyManagement/emergencyResources/maintenanceOfEmergencyMaterials/index.vue new file mode 100644 index 0000000..69ec3e8 --- /dev/null +++ b/src/views/contingencyManagement/emergencyResources/maintenanceOfEmergencyMaterials/index.vue @@ -0,0 +1,395 @@ +<template> + <div class="system-user-container"> + <el-card shadow="hover"> + <div class="system-user-search mb15"> + <el-form size="default" label-width="80px" :inline="true"> + <el-form-item prop="telephone"> + <el-input v-model="suppliesName" placeholder="请选择应急物资" class="input-with-select"> + <template #append> + <el-button :icon="Search" @click="daiInpt" /> + </template> + </el-input> + </el-form-item> + <el-button size="default" type="primary" class="ml10" @click="onSubmit"> 查询 </el-button> + <el-button size="default" class="ml10" @click="submitReset"> 重置 </el-button> + </el-form> + </div> + <div class="button_Line"> + <div class="button_Left"> + <el-button size="default" type="primary" @click="onOpenAdd('新建')"> + <el-icon> <Plus /> </el-icon>新建 + </el-button> + <el-button size="default" type="warning" plain :disabled="warning" @click="onEdit('修改', deletAll[0])"> + <el-icon> <Edit /> </el-icon>修改 + </el-button> + <el-button size="default" type="danger" plain @click="onDeleteAll" :disabled="danger"> + <el-icon> <Delete /> </el-icon>删除 + </el-button> + </div> + <div class="button_Right"> + <el-button> + <el-icon> + <Download /> + </el-icon> + </el-button> + <el-button> + <el-icon> + <Refresh /> + </el-icon> + </el-button> + </div> + </div> + <el-table :data="tableData" style="width: 100%" ref="multipleTableRef" @selection-change="handleSelectionChange"> + <el-table-column align="center" type="selection" width="55" /> + <el-table-column align="center" prop="suppliesName" label="应急物资" min-width="120" show-overflow-tooltip sortable></el-table-column> + <el-table-column align="center" label="保养结果" min-width="120" show-overflow-tooltip sortable> + <template #default="scope"> + <span v-if="scope.row.maintainResult == 1">正常</span> + <span v-if="scope.row.maintainResult == 2">异常</span> + </template> + </el-table-column> + <el-table-column align="center" prop="maintainTime" label="保养日期" min-width="120" show-overflow-tooltip sortable></el-table-column> + <el-table-column label="操作" width="200" align="center" fixed="right"> + <template #default="scope"> + <el-button size="small" text type="primary" @click="onEdit('查看', scope.row.id)"> + <el-icon style="margin-right: 5px"> <View /> </el-icon>查看 + </el-button> + <el-button size="small" text type="primary" @click="onEdit('修改', scope.row.id)"> + <el-icon style="margin-right: 5px"> <EditPen /> </el-icon>修改 + </el-button> + <el-button size="small" text type="primary" @click="onRowDel(scope.row.id)"> + <el-icon> <Delete /> </el-icon>删除 + </el-button> + </template> + </el-table-column> + </el-table> + <div class="pages"> + <el-pagination + v-if="tableData.length == 0 ? false : true" + v-model:currentPage="pageIndex" + v-model:page-size="pageSize" + :page-sizes="[10, 20, 30]" + :pager-count="5" + layout="total, sizes, prev, pager, next, jumper" + :total="total" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + </el-card> + <EmergencySupplies ref="showRef" @SearchUser="onUser" /> + <OpenSee ref="editRef" /> + <upData ref="upShow"></upData> + <OpenAdd ref="addRef" @myAdd="onMyAdd" /> + </div> +</template> + +<script lang="ts"> +import { reactive, onMounted, ref, defineComponent } from 'vue'; +import { + ElMessageBox, + ElMessage, + // ElTable, + // FormInstance, +} from 'element-plus'; +import { Plus, Search, Delete, Edit, Download, Refresh, View, EditPen } from '@element-plus/icons-vue'; +// import OpenSee from '/@/views/contingencyManagement/emergencyPlanStartRecord/component/openSee.vue'; +// import UpData from '/@/views/contingencyManagement/panManagement/component/upData.vue'; +// import EmergencySupplies from '/@/components/emergencySupplies/spi.vue'; +// import OpenAdd from '/@/views/contingencyManagement/emergencyResources/maintenanceOfEmergencyMaterials/component/openAdd.vue'; +// import { contingencyApi } from '/@/api/contingency'; +// import { emergencySuppliesMaintainApi } from '/@/api/emergencySuppliesMaintain'; + +import OpenSee from '../../emergencyPlanStartRecord/component/openSee.vue'; +import UpData from '../../panManagement/component/upData.vue'; +import EmergencySupplies from '../../../../components/emergencySupplies/index.vue'; +import OpenAdd from '../maintenanceOfEmergencyMaterials/component/openAdd.vue'; +import { maintenanceEmergencyMaterialsApi } from '/@/api/contingencyManagement/maintenanceEmergencyMaterials'; + +export default defineComponent({ + name: 'systemUser', + components: { + OpenSee, + View, + OpenAdd, + EditPen, + Plus, + Edit, + Delete, + EmergencySupplies, + Download, + Refresh, + UpData, + }, + setup() { + //定义表单 + const listQuery = reactive({ + pageIndex: 1, + pageSize: 10, + searchParams: { + suppliesId: '', + }, + }); + // 定义表格数据 + const tableData = ref([]); + // 请求列表数据 + const onSubmit = async () => { + let res = await maintenanceEmergencyMaterialsApi().getMaintenanceEmergencyMaterialsList(listQuery); + if (res.data.code == 200) { + tableData.value = res.data.data; + pageIndex.value = res.data.pageIndex; + pageSize.value = res.data.pageSize; + total.value = res.data.total; + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + } + }; + const suppliesName = ref(''); + // 重置 + const submitReset = () => { + listQuery.searchParams.suppliesId = ''; + suppliesName.value = ''; + onSubmit(); + }; + const warning = ref(true); + const danger = ref(true); + const deletAll = ref(); + const handleSelectionChange = (val: any) => { + let valId = JSON.parse(JSON.stringify(val)); + let arr = []; + for (let i = 0; i < valId.length; i++) { + arr.push(valId[i].id); + } + deletAll.value = arr; + if (val.length == 1) { + warning.value = false; + danger.value = false; + } else if (val.length == 0) { + warning.value = true; + danger.value = true; + } else { + warning.value = true; + danger.value = false; + } + }; + + // 打开新建用户弹窗 + const addRef = ref(); + const onOpenAdd = (data: any) => { + addRef.value.openDialog(data); + }; + // 新增后刷新 + const onMyAdd = (e: boolean) => { + if (e) { + onSubmit(); + } else { + onSubmit(); + } + }; + // 打开修改用户弹窗 + const onEdit = (val: string, row: object) => { + if (val == '详情') { + addRef.value.openDialog(val, row); + } else { + addRef.value.openDialog(val, row); + } + }; + // 删除 + const onRowDel = (data: any) => { + let arr = []; + arr.push(data); + ElMessageBox.confirm('确定删除所选项吗?', '提示', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + maintenanceEmergencyMaterialsApi() + .deleteMaintenanceEmergencyMaterials(arr) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'success', + }); + onSubmit(); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + onSubmit(); + } + }); + }) + .catch(() => {}); + }; + // 多选删除 + const onDeleteAll = () => { + ElMessageBox.confirm('确定删除所选项吗?', '提示', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + maintenanceEmergencyMaterialsApi() + .deleteMaintenanceEmergencyMaterials(deletAll.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'success', + }); + onSubmit(); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + onSubmit(); + } + }); + }) + .catch(() => {}); + }; + // 上传 + const upShow = ref(); + const upButton = () => { + upShow.value.openDialog(); + }; + // 应急物资弹窗 + const showRef = ref(); + const daiInpt = () => { + showRef.value.openDailog(); + }; + const onUser = (e: any) => { + listQuery.searchParams.suppliesId = e.id; + suppliesName.value = e.name; + }; + // 分页 + const pageIndex = ref(); + const pageSize = ref(); + const total = ref(); + // 分页改变 + const handleSizeChange = (val: number) => { + listQuery.pageSize = val; + onSubmit(); + }; + // 分页未改变 + const handleCurrentChange = (val: number) => { + listQuery.pageIndex = val; + onSubmit(); + }; + // 页面加载时 + onMounted(() => { + onSubmit(); + }); + return { + suppliesName, + upButton, + upShow, + Edit, + onRowDel, + handleSizeChange, + handleCurrentChange, + Search, + daiInpt, + showRef, + onOpenAdd, //新增 + addRef, + onSubmit, + submitReset, + onMyAdd, + listQuery, + warning, + danger, + tableData, + pageIndex, + pageSize, + total, + handleSelectionChange, + onDeleteAll, + onEdit, + onUser, + deletAll + }; + }, +}); +</script> +<style scoped lang="scss"> +.table_Box { + padding: 20px; + background-color: #fff; +} +.tableForm { + margin-top: 10px; +} +/*按钮行*/ +.button_Line { + display: flex; + flex-direction: row; + justify-content: space-between; +} +//弹窗底部边框线 +::v-deep .el-dialog__footer { + border-top: 1px solid #e8e8e8; + border-radius: 0 0 4px 4px; +} +//弹窗顶部边框线 +::v-deep .el-dialog__header { + border-bottom: 1px solid #e8e8e8; + margin-right: 0; + border-radius: 4px 4px 0 0; +} +//表头 +::v-deep .el-table th.el-table__cell { + background-color: #f6f7fa; + font-weight: 400; + color: #909399; +} +.el-table .sort-caret.ascending { + border-bottom-color: #c0c4cc; +} +//分页 +.pages { + display: flex; + justify-content: flex-end; + margin-top: 15px; +} +::v-deep .el-pagination .el-pager li { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +::v-deep .el-pagination .el-pager li.is-active { + background-color: #409eff; + color: #fff; +} +::v-deep .el-pagination .btn-prev { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +::v-deep .el-pagination button:disabled { + color: #c0c4cc; +} +::v-deep .el-pagination .btn-next { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +</style> \ No newline at end of file diff --git a/src/views/contingencyManagement/panManagement/component/abolishLibrary.vue b/src/views/contingencyManagement/panManagement/component/abolishLibrary.vue new file mode 100644 index 0000000..c36b1e3 --- /dev/null +++ b/src/views/contingencyManagement/panManagement/component/abolishLibrary.vue @@ -0,0 +1,226 @@ +<template> + <div class="system-edit-user-container"> + <el-dialog title="废止库" v-model="isShowDialog" width="60%" draggable :fullscreen="full"> + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-row :gutter="35"> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-table + :data="tableData" + style="width: 100%; margin-top: 15px" + ref="multipleTableRef" + :model="formInline" + :header-cell-style="{ background: '#f6f7fa', color: '#909399' }" + > + <el-table-column prop="name" label="预案名称" show-overflow-tooltip sortable></el-table-column> + <el-table-column prop="type" label="预案类型" show-overflow-tooltip sortable> + <template #default="scope"> + <div v-if="scope.row.type==1">综合应急预案</div> + <div v-if="scope.row.type==2">现场处置方案</div> + <div v-if="scope.row.type==3">专项应急预案</div> + <div v-if="scope.row.type==4">其他预案</div> + </template> + </el-table-column> + <el-table-column prop="authorName" label="编写人" show-overflow-tooltip sortable></el-table-column> + <el-table-column prop="releaseDate" label="发布实施日期" show-overflow-tooltip sortable></el-table-column> + <el-table-column label="操作" width="200" align="center"> + <template #default="scope"> + <el-button size="small" text type="primary" @click="onReduction(scope.row.id)">还原 </el-button> + </template> + </el-table-column> + </el-table> + </el-col> + </el-row> + <div class="pages"> + <el-pagination + v-if="tableData.length == 0 ? false : true" + v-model:currentPage="pageIndex" + v-model:page-size="pageSize" + :page-sizes="[10, 20, 30]" + :pager-count="5" + class="mt15" + background + layout="total, sizes, prev, pager, next, jumper" + :total="total" + @size-change="onHandleSizeChange" + @current-change="onHandleCurrentChange" + /> + </div> + <template #footer> + <span class="dialog-footer"> + <el-button @click="onCancel">取消</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script lang="ts"> +import { ref, reactive, defineComponent, onMounted } from 'vue'; + +import type { FormInstance } from 'element-plus'; +import { + // ElMessageBox, + ElMessage, +} from 'element-plus'; +import { Search, FullScreen } from '@element-plus/icons-vue'; +import { emergencyPlanApi } from '../../../../api/contingencyManagement/emergencyPlan'; +export default defineComponent({ + name: 'abolishLibrary', + components: {}, + setup(prop, { emit }) { + // 列表参数 + const listQuery = reactive({ + pageIndex: 1, + pageSize: 10, + searchParams: { + abolishStatus: true, + }, + }); + // 定义表格数据 + const tableData = ref([]); + + // 列表数据请求 + const openDialog = async () => { + isShowDialog.value = true; + let res = await emergencyPlanApi().getEmergencyPlanList(listQuery); + if (res.data.code === '200') { + tableData.value = res.data.data; + pageIndex.value = res.data.pageIndex; + pageSize.value = res.data.pageSize; + total.value = res.data.total; + } else { + ElMessage({ + showClose: true, + type: 'error', + message: res.data.msg, + }); + } + }; + const isShowDialog = ref(false); + + const ruleFormRef = ref<FormInstance>(); + // 打开弹窗 + // const openDialog = () => { + // isShowDialog.value = true; + // }; + // 关闭弹窗 + const closeDialog = () => { + isShowDialog.value = false; + }; + // 取消 + const onCancel = () => { + closeDialog(); + }; + const onReduction = async (id: number) => { + isShowDialog.value = false; + emergencyPlanApi() + .reductionEmergencyTeam(id) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'success', + }); + emit('myAdd', true); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + emit('myAdd', true); + openDialog(); + } + }) + .catch(() => {}); + }; + // 分页 + const pageIndex = ref(); + const pageSize = ref(); + const total = ref(); + // 分页改变 + const handleSizeChange = (val: number) => { + listQuery.pageSize = val; + }; + // 分页未改变 + const handleCurrentChange = (val: number) => { + listQuery.pageIndex = val; + }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + return { + openDialog, + closeDialog, + isShowDialog, + onCancel, + tableData, + Search, + ruleFormRef, + pageIndex, + pageSize, + handleSizeChange, + handleCurrentChange, + toggleFullscreen, + FullScreen, + full, + listQuery, + // onSubmit, + total, + emit, + onReduction, + }; + }, +}); +</script> +<style scoped lang="scss"> +.textarea { + height: 168px !important; +} +.textarea ::v-deep .el-textarea__inner { + height: 168px !important; +} +::v-deep .el-table__cell { + font-weight: 400; +} +//分页 +.pages { + display: flex; + justify-content: flex-end; +} +::v-deep .el-pagination .el-pager li { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +::v-deep .el-pagination .el-pager li.is-active { + background-color: #409eff; + color: #fff; +} +::v-deep .el-pagination .btn-prev { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +::v-deep .el-pagination button:disabled { + color: #c0c4cc; +} +::v-deep .el-pagination .btn-next { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +</style> \ No newline at end of file diff --git a/src/views/contingencyManagement/panManagement/component/approval.vue b/src/views/contingencyManagement/panManagement/component/approval.vue new file mode 100644 index 0000000..aed57e8 --- /dev/null +++ b/src/views/contingencyManagement/panManagement/component/approval.vue @@ -0,0 +1,239 @@ +<template> + <div class="system-edit-user-container"> + <el-dialog :title="titles" v-model="isShowDialog" width="40%" draggable :fullscreen="full" :close-on-click-modal="false"> + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-form ref="ruleFormRef" :model="ruleForm" size="default" label-width="120px" :disabled="disabled"> + <el-row :gutter="35"> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="审批名称" prop="workName"> + <el-input v-model="ruleForm.workName" placeholder="请填写队伍名称" disabled></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="审批标题" prop="title"> + <el-input v-model="ruleForm.title" placeholder="请填写审批名称" disabled></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="审批人" prop="approvePersonId"> + <el-input v-model="ruleForm.approvePersonName" placeholder="请选择" class="input-with-select" disabled> + <template #append> + <el-button :icon="Search" @click="openUser" :disabled="disabled"/> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="审批结果" prop="authorUid"> + <el-radio-group v-model="ruleForm.approveResult"> + <el-radio :label="false">不通过</el-radio> + <el-radio :label="true">通过</el-radio> + </el-radio-group> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="审批意见" prop="approveMemo"> + <el-input v-model="ruleForm.approveMemo" type="textarea" placeholder="请填写审批意见"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="是否完成" prop="complete" @change="typeChang"> + <el-radio-group v-model="ruleForm.complete"> + <el-radio :label="false">是</el-radio> + <el-radio :label="true">否</el-radio> + </el-radio-group> + </el-form-item> + </el-col> + <el-col v-if="ruleForm.complete" :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="审批名称" prop="twoWorkName"> + <el-input v-model="ruleForm.twoWorkName" placeholder="请填写队伍名称"></el-input> + </el-form-item> + </el-col> + <el-col v-if="ruleForm.complete" :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="审批标题" prop="twoTitle"> + <el-input v-model="ruleForm.twoTitle" placeholder="请填写审批名称"></el-input> + </el-form-item> + </el-col> + <el-col v-if="ruleForm.complete" :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="审批人" prop="twoApprovePersonName"> + <el-input v-model="ruleForm.twoApprovePersonName" placeholder="请选择" class="input-with-select"> + <template #append> + <el-button :icon="Search" @click="openUser" /> + </template> + </el-input> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="resetForm(ruleFormRef)" size="default">关闭</el-button> + <el-button size="default" type="primary" v-if="disabled == true ? false : true" @click="submitForm(titles, ruleFormRef)">确定</el-button> + </span> + </template> + </el-dialog> + <DailogSearchUserManger ref="userRef" @SearchUser="onUser" /> + </div> +</template> + +<script lang="ts"> +import { ref, defineComponent } from 'vue'; + +import type { FormInstance } from 'element-plus'; +import { ElMessage } from 'element-plus'; +import { Search, FullScreen } from '@element-plus/icons-vue'; +import DailogSearchUserManger from '/@/components/DailogSearchUserManger/index.vue'; +import { emergencyPlanApi } from '/@/api/contingencyManagement/emergencyPlan'; + +export default defineComponent({ + name: 'openAdd', + components: { + DailogSearchUserManger, + }, + setup(prop, { emit }) { + const isShowDialog = ref(false); + const ruleFormRef = ref<FormInstance>(); + const ruleForm = ref({ + approveId: '', + workName: '', // 审批名称 + title: '', //审批标题 + approvePersonId: '', // + approvePersonName: '', // 审批人 + approveStatus: 2, //审批状态 + relateType: 1, //业务类型 + approveResult: false, //审批结果 + approveMemo: '', //审批意见 + relateId: '', + twoWorkName: '', + twoTitle: '', + twoApprovePersonId: '', + twoApprovePersonName: '', + }); + const titles = ref(); + const disabled = ref(); + const uid = ref(); + // 打开弹窗 + const openDialog = (title: string, approveId: number, type: boolean, id: number) => { + isShowDialog.value = true; + titles.value = title; + disabled.value = type; + + uid.value = approveId; + if (title == '查看审批' || title == '审批') { + emergencyPlanApi() + .approvalProcessEmergencyPlan(approveId) + .then((res) => { + if (res.data.code == 200) { + ruleForm.value = res.data.data; + ruleForm.value.relateId = id; + } + }); + } + }; + const submitForm = async () => { + console.log(ruleForm.value); + + ruleForm.value.workName = ruleForm.value.twoWorkName; + ruleForm.value.title = ruleForm.value.twoTitle; + ruleForm.value.approvePersonId = ruleForm.value.twoApprovePersonId; + ruleForm.value.approvePersonName = ruleForm.value.twoApprovePersonName; + ruleForm.value.relateType = 1; + isShowDialog.value = false; + if(ruleForm.value.complete == false) { + ruleForm.value.approveStatus=3 + } + delete ruleForm.value.gmtCreate + delete ruleForm.value.complete + delete ruleForm.value.submitPersonName + + delete ruleForm.value.twoApprovePersonId + delete ruleForm.value.twoApprovePersonName + delete ruleForm.value.twoTitle + delete ruleForm.value.twoWorkName + emergencyPlanApi() + .editApprovalEmergencyPlan(ruleForm.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: '修改成功', + type: 'success', + }); + emit('myAdd', true); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + emit('myAdd', true); + } + }); + }; + const resetForm = () => { + isShowDialog.value = false; + }; + // 打开用户选择弹窗 + const userRef = ref(); + const openUser = () => { + userRef.value.openDailog(); + }; + //回显 + const onUser = (e: any) => { + ruleForm.value.twoApprovePersonId = e[0].uid; + ruleForm.value.twoApprovePersonName = e[0].realName; + }; + const typeChang = () => { + console.log('tag', ruleForm); + }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + return { + openDialog, + Search, + submitForm, + openUser, + userRef, + toggleFullscreen, + FullScreen, + full, + titles, + disabled, + emit, + isShowDialog, + ruleFormRef, + ruleForm, + resetForm, + onUser, + typeChang, + uid, + }; + }, +}); +</script> +<style scoped lang="scss"> +.textarea { + height: 168px !important; +} +.textarea ::v-deep .el-textarea__inner { + height: 168px !important; +} +::v-deep .el-table__cell { + font-weight: 400; +} +.el-divider--horizontal { + height: 0; + margin: 0; + border-top: transparent; +} +.el-select { + width: 100%; +} +</style> \ No newline at end of file diff --git a/src/views/contingencyManagement/panManagement/component/approvalProcess.vue b/src/views/contingencyManagement/panManagement/component/approvalProcess.vue new file mode 100644 index 0000000..209c51a --- /dev/null +++ b/src/views/contingencyManagement/panManagement/component/approvalProcess.vue @@ -0,0 +1,196 @@ +<template> + <div class="system-edit-user-container"> + <el-dialog title="查看审批流程" v-model="isShowDialog" width="60%" draggable :fullscreen="full"> + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-row :gutter="35"> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-table + :data="tableData" + style="width: 100%; margin-top: 15px" + ref="multipleTableRef" + :model="formInline" + :header-cell-style="{ background: '#f6f7fa', color: '#909399' }" + > + <el-table-column prop="workName" label="审批人" show-overflow-tooltip sortable></el-table-column> + <el-table-column prop="title" label="审批标题" show-overflow-tooltip sortable></el-table-column> + <el-table-column prop="approvePersonName" label="编写人" show-overflow-tooltip sortable></el-table-column> + <el-table-column prop="approveMemo" label="审批意见" show-overflow-tooltip sortable></el-table-column> + </el-table> + </el-col> + </el-row> + <div class="pages"> + <el-pagination + v-if="tableData.length == 0 ? false : true" + v-model:currentPage="pageIndex" + v-model:page-size="pageSize" + :page-sizes="[10, 20, 30]" + :pager-count="5" + class="mt15" + background + layout="total, sizes, prev, pager, next, jumper" + :total="total" + @size-change="onHandleSizeChange" + @current-change="onHandleCurrentChange" + /> + </div> + <template #footer> + <span class="dialog-footer"> + <el-button @click="onCancel">取消</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script lang="ts"> +import { ref, reactive, defineComponent, onMounted } from 'vue'; + +import type { FormInstance } from 'element-plus'; +import { + // ElMessageBox, + ElMessage, +} from 'element-plus'; +import { Search, FullScreen } from '@element-plus/icons-vue'; +import { emergencyPlanApi } from '../../../../api/contingencyManagement/emergencyPlan'; +export default defineComponent({ + name: 'abolishLibrary', + components: {}, + setup(prop, { emit }) { + // 列表参数 + const listQuery = reactive({ + pageIndex: 1, + pageSize: 10, + searchParams: { + relateType: 1, + relateId: '', + startTime: '', + endTime: '', + }, + }); + // 定义表格数据 + const tableData = ref([]); + + // 列表数据请求 + const uid = ref(); + const openDialog = async (id: number) => { + isShowDialog.value = true; + listQuery.searchParams.relateId=id + uid.value = id; + let res = await emergencyPlanApi().processEmergencyPlan(listQuery); + if (res.data.code === '200') { + tableData.value = res.data.data; + pageIndex.value = res.data.pageIndex; + pageSize.value = res.data.pageSize; + total.value = res.data.total; + } else { + ElMessage({ + showClose: true, + type: 'error', + message: res.data.msg, + }); + } + }; + + const isShowDialog = ref(false); + + const ruleFormRef = ref<FormInstance>(); + // 打开弹窗 + // const openDialog = () => { + // isShowDialog.value = true; + // }; + // 关闭弹窗 + const closeDialog = () => { + isShowDialog.value = false; + }; + // 取消 + const onCancel = () => { + closeDialog(); + }; + // 分页 + const pageIndex = ref(); + const pageSize = ref(); + const total = ref(); + // 分页改变 + const handleSizeChange = (val: number) => { + listQuery.pageSize = val; + }; + // 分页未改变 + const handleCurrentChange = (val: number) => { + listQuery.pageIndex = val; + }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + return { + openDialog, + closeDialog, + isShowDialog, + onCancel, + tableData, + Search, + ruleFormRef, + pageIndex, + pageSize, + handleSizeChange, + handleCurrentChange, + toggleFullscreen, + FullScreen, + full, + listQuery, + total, + emit, + uid, + }; + }, +}); +</script> +<style scoped lang="scss"> +.textarea { + height: 168px !important; +} +.textarea ::v-deep .el-textarea__inner { + height: 168px !important; +} +::v-deep .el-table__cell { + font-weight: 400; +} +//分页 +.pages { + display: flex; + justify-content: flex-end; +} +::v-deep .el-pagination .el-pager li { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +::v-deep .el-pagination .el-pager li.is-active { + background-color: #409eff; + color: #fff; +} +::v-deep .el-pagination .btn-prev { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +::v-deep .el-pagination button:disabled { + color: #c0c4cc; +} +::v-deep .el-pagination .btn-next { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +</style> \ No newline at end of file diff --git a/src/views/contingencyManagement/panManagement/component/initiateApproval.vue b/src/views/contingencyManagement/panManagement/component/initiateApproval.vue new file mode 100644 index 0000000..eb2afa2 --- /dev/null +++ b/src/views/contingencyManagement/panManagement/component/initiateApproval.vue @@ -0,0 +1,159 @@ +<template> + <div class="system-edit-user-container"> + <el-dialog title="发起审批" v-model="isShowDialog" width="40%" draggable :fullscreen="full" :close-on-click-modal="false"> + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-form ref="ruleFormRef" :model="ruleForm" size="default" label-width="120px"> + <el-row :gutter="35"> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="审批名称" prop="workName"> + <el-input v-model="ruleForm.workName" placeholder="请填写审批名称"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="审批标题" prop="title"> + <el-input v-model="ruleForm.title" placeholder="请填写审批名称"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="审批人" prop="approvePersonId"> + <el-input v-model="ruleForm.approvePersonName" placeholder="请选择" class="input-with-select"> + <template #append> + <el-button :icon="Search" @click="openUser" /> + </template> + </el-input> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="resetForm" size="default">关闭</el-button> + <el-button size="default" type="primary" @click="submitForm">确定</el-button> + </span> + </template> + </el-dialog> + <DailogSearchUserManger ref="userRef" @SearchUser="onUser" /> + </div> +</template> + +<script lang="ts"> +import { ref, defineComponent } from 'vue'; + +import type { FormInstance } from 'element-plus'; +import { ElMessage } from 'element-plus'; +import { Search, FullScreen } from '@element-plus/icons-vue'; +import DailogSearchUserManger from '/@/components/DailogSearchUserManger/index.vue'; +import { emergencyPlanApi } from '/@/api/contingencyManagement/emergencyPlan'; + +export default defineComponent({ + name: 'openAdd', + components: { + DailogSearchUserManger, + }, + setup(prop, { emit }) { + const isShowDialog = ref(false); + const ruleFormRef = ref<FormInstance>(); + const ruleForm = ref({ + workName: '', // 审批名称 + title: '', //审批标题 + approvePersonId: '', + approvePersonName: '', + approveStatus: 2, + relateType: 1, + relateId: '', + }); + const titles = ref(); + + // 打开弹窗 + const openDialog = (title: string, id: number) => { + isShowDialog.value = true; + titles.value = title; + ruleForm.value.relateId = id; + uid.value = id; + }; + const uid = ref(); + const submitForm = async () => { + isShowDialog.value = false; + + emergencyPlanApi() + .approvalEmergencyPlan(ruleForm.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'success', + }); + emit('myAdd', true); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + emit('myAdd', true); + } + }); + }; + const resetForm = () => { + isShowDialog.value = false; + }; + // 打开用户选择弹窗 + const userRef = ref(); + const openUser = () => { + userRef.value.openDailog(); + }; + //回显 + const onUser = (e: any) => { + ruleForm.value.approvePersonId = e[0].uid; + ruleForm.value.approvePersonName = e[0].realName; + }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + return { + openDialog, + Search, + submitForm, + openUser, + userRef, + toggleFullscreen, + FullScreen, + full, + titles, + emit, + isShowDialog, + ruleFormRef, + ruleForm, + resetForm, + onUser, + uid, + }; + }, +}); +</script> +<style scoped lang="scss"> +.textarea { + height: 168px !important; +} +.textarea ::v-deep .el-textarea__inner { + height: 168px !important; +} +::v-deep .el-table__cell { + font-weight: 400; +} +.el-divider--horizontal { + height: 0; + margin: 0; + border-top: transparent; +} +.el-select { + width: 100%; +} +</style> \ No newline at end of file diff --git a/src/views/contingencyManagement/panManagement/component/openAdd.vue b/src/views/contingencyManagement/panManagement/component/openAdd.vue new file mode 100644 index 0000000..4114bb7 --- /dev/null +++ b/src/views/contingencyManagement/panManagement/component/openAdd.vue @@ -0,0 +1,471 @@ +<template> + <div class="system-edit-user-container"> + <el-dialog + :title="titles" + v-model="isShowDialog" + width="50%" + draggable + :fullscreen="full" + :close-on-click-modal="false" + @close="resetForm(ruleFormRef)" + > + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-form ref="ruleFormRef" :model="ruleForm" size="default" label-width="120px" :disabled="disabled"> + <el-row :gutter="35"> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="预案名称" prop="name"> + <el-input v-model="ruleForm.name" placeholder="请填写队伍名称"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="适用部门" prop="responsibleDepartment"> + <el-tree-select + v-model="responsibleDepartment" + :data="newTreeList" + class="w100" + clearable + :props="propse" + multiple + :render-after-expand="false" + check-strictly + check-on-click-node + placeholder="请选择" + @change="changeDepartment" + /> + <el-divider /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="预案类型" prop="type"> + <el-select v-model="ruleForm.type" class="w100" placeholder="请选择"> + <el-option label="综合应急预案" value="1"></el-option> + <el-option label="现场处置方案" value="2"></el-option> + <el-option label="专项应急预案" value="3"></el-option> + <el-option label="其他预案" value="4"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="危险源关联" prop="associatedDanger"> + <el-select v-model="ruleForm.associatedDanger" class="w100" placeholder="请选择"> + <el-option label="是" :value="false"></el-option> + <el-option label="否" :value="true"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="预案级别" prop="level"> + <el-select v-model="ruleForm.level" class="w100" placeholder="请选择"> + <el-option label="公司级" value="1"></el-option> + <el-option label="分厂级" value="2"></el-option> + <el-option label="车间级" value="3"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="编写人" prop="authorId"> + <el-input v-model="ruleForm.authorName" placeholder="请选择" class="input-with-select"> + <template #append> + <el-button :icon="Search" @click="openUser" /> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="编写部门" prop="authorDeptId"> + <el-tree-select + v-model="ruleForm.authorDeptId" + :data="newTreeList" + class="w100" + :props="propse" + clearable + :render-after-expand="false" + placeholder="请选择" + /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="发布实施日期" prop="releaseDate"> + <el-date-picker + v-model="ruleForm.releaseDate" + type="datetime" + class="w100" + placeholder="选择日期时间" + value-format="YYYY-MM-DD HH:mm:ss" + /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="应急队伍" prop="emergencyTeam"> + <el-input v-model="ruleForm.teamName" placeholder="请选择" class="input-with-select"> + <template #append> + <el-button :icon="Search" @click="daiInpt(0)" /> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="相关附件"> + <uploaderFile :fileList="fileList" :systemName="'EMERGENCY'" :disabled="disabled" + @successUploader="successUploader"></uploaderFile> + </el-form-item> + </el-col> + <!-- <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">--> + <!-- <el-form-item label="区域名称" prop="areaName">--> + <!-- <el-input--> + <!-- v-model="ruleForm.areaName"--> + <!-- placeholder="请选择"--> + <!-- class="input-with-select"--> + <!-- >--> + <!-- <template #append>--> + <!-- <el-button :icon="Search" @click="regionsDialog"/>--> + <!-- </template>--> + <!-- </el-input>--> + <!-- </el-form-item>--> + <!-- </el-col>--> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="resetForm(ruleFormRef)" size="default">关闭</el-button> + <el-button size="default" type="primary" v-if="disabled == true ? false : true" @click="submitForm(titles, ruleFormRef)">确定</el-button> + </span> + </template> + </el-dialog> + <CheckTemplate ref="Shows" @SearchUser="SearchUser" /> + <DailogSearchUserManger ref="userRef" @SearchUser="onUser" /> + <RegionsDialog ref="openRef" /> + </div> +</template> + +<script lang="ts"> +import { ref, defineComponent, onMounted } from 'vue'; + +import type { UploadUserFile, FormInstance } from 'element-plus'; +import { ElMessage } from 'element-plus'; +import { Search, FullScreen } from '@element-plus/icons-vue'; +import DailogSearchUserManger from '/@/components/DailogSearchUserManger/index.vue'; +import CheckTemplate from '/@/components/checkTemplate/index.vue'; +import RegionsDialog from '/@/components/regionsDialog/index.vue'; +import { emergencyPlanApi } from '/@/api/contingencyManagement/emergencyPlan'; +import { goalManagementApi } from '/@/api/goalManagement'; +import uploaderFile from '/@/components/uploaderFile/index.vue'; +export default defineComponent({ + name: 'openAdd', + components: { + CheckTemplate, + DailogSearchUserManger, + RegionsDialog, + uploaderFile + }, + setup(prop, { emit }) { + const isShowDialog = ref(false); + const ruleFormRef = ref<FormInstance>(); + const ruleForm = ref({ + name: '', // 预案名称 + type: '', //预案类型 + associatedDanger: '', // 危险源关联 + level: '', // 预案级别 + authorUid: '', // 编写人 + authorName: '', + authorDeptId: '', // 编写部门 + releaseDate: '', // 发布实施日期 + fileList: [], + areaList: [], //区域列表 + teamList: [], + // teamId: '', //应急队伍 + deptList: [], + }); + const titles = ref(); + const disabled = ref(); + + // 打开弹窗 + const openDialog = (title: string, id: number, type: boolean) => { + isShowDialog.value = true; + titles.value = title; + disabled.value = type; + if (title == '查看应急预案管理' || title == '修改应急预案管理') { + emergencyPlanApi() + .seeEmergencyTeam(id) + .then((res) => { + if (res.data.code == 200) { + ruleForm.value = res.data.data; + ruleForm.value.teamName = '' + responsibleDepartment.value = [] + if(res.data.data.teamList){ + for(var a = 0;a<res.data.data.teamList.length;a++){ + ruleForm.value.teamName+=res.data.data.teamList[a].teamName+';' + } + } + if(res.data.data.deptList){ + for(var a = 0;a<res.data.data.deptList.length;a++){ + + responsibleDepartment.value.push(res.data.data.deptList[a].departmentId) + } + } + fileList.value = (res.data.data.fileList?res.data.data.fileList:[]) + initFileListData() + } + }); + } + }; + const initFileListData = async () => { + for(var a = 0;a<fileList.value.length;a++){ + fileList.value[a].name = fileList.value[a].fileName + } + } + // 上传成功组装数据 + const successUploader = (list) =>{ + fileList.value = list + const formFileList = [] + for(var a = 0;a<fileList.value.length;a++){ + formFileList.push( + { + fileName:fileList.value[a].fileName, + fileUrl:'' + } + ) + } + ruleForm.value.fileList = formFileList + } + //日期选择器 + const releaseDate = ref(''); + // 上传附件 + const fileList = ref([]); + //el-tree-select回显 + const propse = { + label: 'depName', + children: 'children', + }; + const newTreeList = []; + //得到部门树 + const department = async () => { + await goalManagementApi() + .getTreedepartment() + .then((res) => { + if (res.data.code == 200) { + data.value = res.data.data; + getTreeList(res.data.data, newTreeList); + } else { + ElMessage.error(res.data.msg); + } + }); + }; + // 递归树状数据且修改字段名 + const getTreeList = (treeList, newTreeList) => { + treeList.map((c) => { + let tempData = { + depName: c.depName, + value: c.depId, + children: [], + }; + if (c.children && c.children.length > 0) { + tempData.children = []; + getTreeList(c.children, tempData.children); + } + newTreeList.push(tempData); + }); + }; + onMounted(() => { + department(); + }); + const changeDepartment = (e) => { + var temList = []; + for (var a = 0; a < e.length; a++) { + temList.push({ + departmentId: e[a], + }); + } + ruleForm.value.deptList = temList; + console.log(ruleForm); + }; + //定义树形下拉框 + const responsibleDepartment = ref([]); + const data = ref(); + + const submitForm = async (title: string, formEl: FormInstance | undefined) => { + if(!ruleForm.value.fileList){ + ruleForm.value.fileList = [] + } + if (title == '新建应急预案管理') { + if (!formEl) return; + await formEl.validate((valid, fields) => { + if (valid) { + isShowDialog.value = false; + delete ruleForm.value.teamName + emergencyPlanApi() + .addEmergencyPlan(ruleForm.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'success', + }); + emit('myAdd', true); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + emit('myAdd', true); + } + formEl.resetFields(); + }); + } else { + console.log('error submit!', fields); + } + }); + } else if (title == '修改应急预案管理') { + if (!formEl) return; + await formEl.validate((valid, fields) => { + if (valid) { + isShowDialog.value = false; + delete ruleForm.value.teamName + emergencyPlanApi() + .editEmergencyTeam(ruleForm.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: '修改成功', + type: 'success', + }); + emit('myAdd', true); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + emit('myAdd', true); + } + formEl.resetFields(); + }); + } else { + console.log('error submit!', fields); + } + }); + formEl.resetFields(); + ruleForm.value = { + name: '', // 预案名称 + type: '', //预案类型 + associatedDanger: '', // 危险源关联 + level: '', // 预案级别 + authorUid: '', // 编写人 + authorName: '', + authorDeptId: '', // 编写部门 + releaseDate: '', // 发布实施日期 + fileList: [], + // teamId: '', //应急队伍ID + areaList: [], //区域列表 + teamList: [], + deptList: [], + }; + } + }; + const resetForm = (formEl: FormInstance | undefined) => { + isShowDialog.value = false; + if (!formEl) return; + formEl.resetFields(); + ruleForm.value = {}; + fileList.value = [] + }; + // 应急队伍弹窗 + const Shows = ref(); + const daiInpt = (data: any) => { + Shows.value.openDailog(data); + }; + const SearchUser = (val: any) => { + let arr = []; + ruleForm.value.teamList = []; + for (let i = 0; i < val.length; i++) { + arr.push(val[i].teamName); + ruleForm.value.teamList.push({ + teamId: val[i].id, + }); + } + ruleForm.value.teamName = arr.toString(); + }; + // 选择区域弹窗 + const openRef = ref(); + const regionsDialog = () => { + openRef.value.openDailog(); + }; + // 打开用户选择弹窗 + const userRef = ref(); + const openUser = () => { + userRef.value.openDailog(); + }; + //回显 + const onUser = (e: any) => { + ruleForm.value.authorUid = e[0].uid; + ruleForm.value.authorName = e[0].realName; + }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + return { + openDialog, + fileList, + responsibleDepartment, + data, + Search, + releaseDate, + // treeSelect, + // trees, + propse, + department, + daiInpt, + Shows, + SearchUser, + submitForm, + openUser, + userRef, + regionsDialog, + openRef, + toggleFullscreen, + FullScreen, + full, + titles, + disabled, + emit, + isShowDialog, + ruleFormRef, + ruleForm, + resetForm, + onUser, + newTreeList, + changeDepartment, + successUploader, + initFileListData + }; + }, +}); +</script> +<style scoped lang="scss"> +.textarea { + height: 168px !important; +} +.textarea ::v-deep .el-textarea__inner { + height: 168px !important; +} +::v-deep .el-table__cell { + font-weight: 400; +} +.el-divider--horizontal { + height: 0; + margin: 0; + border-top: transparent; +} +.el-select { + width: 100%; +} +</style> \ No newline at end of file diff --git a/src/views/contingencyManagement/panManagement/component/startUp.vue b/src/views/contingencyManagement/panManagement/component/startUp.vue new file mode 100644 index 0000000..49f5500 --- /dev/null +++ b/src/views/contingencyManagement/panManagement/component/startUp.vue @@ -0,0 +1,160 @@ +<template> + <div class="system-edit-user-container"> + <el-dialog + :title="titles" + v-model="isShowDialog" + width="30%" + draggable + :fullscreen="full" + > + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-form :model="ruleForm" ref="ruleFormRef" label-width="80px"> + <el-form-item label="备注" > + <el-input v-model="ruleForm.remark" type="textarea" autocomplete="off" /> + </el-form-item> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="resetForm(ruleFormRef)" size="default">取消</el-button> + <el-button size="default" type="primary" @click="submitForm(titles,ruleFormRef)">确定</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script lang="ts"> +import { + ref, + defineComponent +} from 'vue'; + +import type { + FormInstance, +} from 'element-plus' +import { ElMessage } from 'element-plus'; +import { + Search, + FullScreen +} from '@element-plus/icons-vue' +import {emergencyPlanLogApi} from "/@/api/contingencyManagement/emergencyPlanLog"; + +export default defineComponent({ + name: 'openAdd', + components: { + }, + setup(prop, {emit}) { + const isShowDialog = ref(false); + const ruleFormRef = ref<FormInstance>(); + + const ruleForm = ref({ + // id: id, + remark: '', + }) + const titles = ref(); + const disabled = ref(); + // 打开弹窗 + // const openDialog = (title: string ,id: number,) => { + // isShowDialog.value = true; + // titles.value = title; + // if (title == '启动') { + // emergencyPlanLogApi() + // .seeEmergencyPlanLog(id) + // .then((res) => { + // if (res.data.code == 200) { + // ruleForm.value = res.data.data; + // } + // }); + // } + // }; + const openDialog = (title: string) => { + isShowDialog.value = true; + titles.value = title; + }; + const submitForm = async (title: string, formEl: FormInstance | undefined) => { + if (title == '启动') { + if (!formEl) return; + await formEl.validate((valid, fields) => { + if (valid) { + isShowDialog.value = false; + emergencyPlanLogApi() + .addEmergencyPlanLog(ruleForm.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'success', + }); + emit('myAdd', true); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + emit('myAdd', true); + } + formEl.resetFields(); + }); + ruleForm.value = { + // id: id, + remark: '', + } + } else { + console.log('error submit!', fields); + } + }); + } + }; + const resetForm = (formEl: FormInstance | undefined) => { + isShowDialog.value = false; + if (!formEl) return; + formEl.resetFields(); + }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + return { + openDialog, + Search, + toggleFullscreen, + FullScreen, + full, + titles, + emit, + isShowDialog, + ruleFormRef, + ruleForm, + submitForm, + disabled, + resetForm, + }; + }, +}); +</script> +<style scoped lang="scss"> +.textarea{ + height: 168px!important; +} +.textarea ::v-deep .el-textarea__inner{ + height: 168px!important; +} +::v-deep .el-table__cell { + font-weight: 400; +} +.el-divider--horizontal{ + height: 0; + margin: 0; + border-top: transparent; +} +.el-select{ + width: 100%; +} +</style> \ No newline at end of file diff --git a/src/views/contingencyManagement/panManagement/component/upData.vue b/src/views/contingencyManagement/panManagement/component/upData.vue new file mode 100644 index 0000000..cc3e2d0 --- /dev/null +++ b/src/views/contingencyManagement/panManagement/component/upData.vue @@ -0,0 +1,125 @@ +<template> + <el-dialog + v-model="dialogVisible" + title="导入Excel" + width="50%" + draggable + :fullscreen="full" + > + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-upload + v-model:file-list="fileList" + class="upload-demo" + action="https://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15" + multiple + :on-preview="handlePreview" + :on-remove="handleRemove" + :before-remove="beforeRemove" + :limit="3" + :on-exceed="handleExceed" + > + <el-button size="default">下载模板</el-button> + <el-button size="default" type="primary">点击上传</el-button> + <template #tip> + <div class="el-upload__tip"> + 只允许导入“xls”或“xlsx”格式文件! + </div> + </template> + </el-upload> + </el-dialog> +</template> +<script lang="ts"> +import { ref, + defineComponent, +} from "vue"; +import { + ElMessage, + ElMessageBox +} from "element-plus"; +import type { + UploadProps, + UploadUserFile, +} from "element-plus"; +import { + FullScreen +} from '@element-plus/icons-vue' +export default defineComponent({ + setup() { + let dialogVisible =ref<boolean>(false) + const fileList = ref<UploadUserFile[]>([ + // { + // name: "element-plus-logo.svg", + // url: "https://element-plus.org/images/element-plus-logo.svg", + // }, + // { + // name: "element-plus-logo2.svg", + // url: "https://element-plus.org/images/element-plus-logo.svg", + // }, + ]); + + const handleRemove: UploadProps["onRemove"] = (file, uploadFiles) => { + console.log(file, uploadFiles); + }; + + const handlePreview: UploadProps["onPreview"] = (uploadFile) => { + console.log(uploadFile); + }; + + const handleExceed: UploadProps["onExceed"] = (files, uploadFiles) => { + ElMessage.warning( + `The limit is 3, you selected ${ + files.length + } files this time, add up to ${ + files.length + uploadFiles.length + } totally` + ); + }; + + const beforeRemove: UploadProps["beforeRemove"] = ( + uploadFile, + uploadFiles + ) => { + return ElMessageBox.confirm( + `Cancel the transfert of ${uploadFile.name} ?` + ).then( + () => true, + () => false + ); + }; + // 打开弹窗 + const openDialog = (type:string,value:any,projectList: any,projectId:string) => { + dialogVisible.value=true + } + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + return { + dialogVisible, + fileList, + handleRemove, + handlePreview, + handleExceed, + beforeRemove, + openDialog, + toggleFullscreen, + FullScreen, + full, + }; + }, +}); +</script> +<style scoped lang="scss"> +.el-upload__tip{ + margin-left: 100px; + margin-top: 20px; +} +::v-deep .el-dialog__header{ + border-bottom: 1px solid #e8e8e8; +} +</style> \ No newline at end of file diff --git a/src/views/contingencyManagement/panManagement/index.vue b/src/views/contingencyManagement/panManagement/index.vue new file mode 100644 index 0000000..eed76c4 --- /dev/null +++ b/src/views/contingencyManagement/panManagement/index.vue @@ -0,0 +1,614 @@ +<template> + <div class="system-user-container"> + <el-card shadow="hover"> + <div class="system-user-search mb15"> + <el-form :inline="true" class="demo-form-inline"> + <el-form-item> + <el-input size="default" v-model="listQuery.searchParams.name" placeholder="预案名称" style="max-width: 215px"> </el-input> + </el-form-item> + <el-form-item> + <el-select size="default" v-model="listQuery.searchParams.type" placeholder="请选择预案类型" class="ml10" style="max-width: 215px"> + <el-option label="综合应急预案" value="1"></el-option> + <el-option label="现场处置方案" value="2"></el-option> + <el-option label="专项应急预案" value="3"></el-option> + <el-option label="其他预案" value="4"></el-option> + </el-select> + </el-form-item> + <el-form-item> + <el-button size="default" type="primary" class="ml10" @click="onSubmit"> 查询 </el-button> + <el-button size="default" class="ml10" @click="submitReset"> 重置 </el-button> + </el-form-item> + </el-form> + </div> + <div class="button_Line"> + <div class="button_Left"> + <el-button size="default" type="primary" @click="onOpenAdd"> + <el-icon> <Plus /> </el-icon>新建 + </el-button> + <el-button size="default" type="warning" plain :disabled="warning" @click="onEdit('修改', deleteAll[0])"> + <el-icon> <Edit /> </el-icon>修改 + </el-button> + <el-button size="default" type="danger" plain :disabled="danger" @click="onDeleteAll"> + <el-icon> <Delete /> </el-icon>删除 + </el-button> + <el-button size="default" type="primary" @click="onabolishLibrary"> 废止库 </el-button> + </div> + <div class="button_Right"> + <!-- <el-button size="default" @click="upButton">--> + <!-- <el-icon>--> + <!-- <Upload />--> + <!-- </el-icon>--> + <!-- </el-button>--> + <!-- <el-button size="default">--> + <!-- <el-icon>--> + <!-- <Download />--> + <!-- </el-icon>--> + <!-- </el-button>--> + <!-- <el-button size="default">--> + <!-- <el-icon>--> + <!-- <Refresh />--> + <!-- </el-icon>--> + <!-- </el-button>--> + </div> + </div> + <el-table :data="tableData" style="width: 100%" ref="multipleTableRef" @selection-change="handleSelectionChange"> + <el-table-column type="selection" width="55" /> + <el-table-column prop="name" label="预案名称" show-overflow-tooltip sortable></el-table-column> + <el-table-column prop="type" label="预案类型" show-overflow-tooltip sortable> + <template #default="scope"> + <span v-if="scope.row.type == 1">综合应急预案</span> + <span v-if="scope.row.type == 2">现场处置方案</span> + <span v-if="scope.row.type == 3">专项应急预案</span> + <span v-if="scope.row.type == 4">其他预案</span> + </template> + </el-table-column> + <el-table-column prop="level" label="预案级别" show-overflow-tooltip sortable> + <template #default="scope"> + <span v-if="scope.row.level == 1">综合应急预案</span> + <span v-if="scope.row.level == 2">现场处置方案</span> + <span v-if="scope.row.level == 3">专项应急预案</span> + </template> + </el-table-column> + <el-table-column prop="releaseDate" label="发布实施日期" show-overflow-tooltip sortable></el-table-column> + <el-table-column label="操作" width="260" align="center" fixed="right"> + <template #default="scope"> + <el-button size="small" text type="primary" @click="isDialogFormVisible(scope.row.id)"> + <el-icon style="margin-right: 5px"> <VideoPlay /> </el-icon>启动 + </el-button> + <el-button size="small" text type="primary" @click="abolish(scope.row.id)"> + <el-icon style="margin-right: 5px"> <VideoPause /> </el-icon>废止 + </el-button> + <el-button size="small" text type="primary" @click="onEdit('修改', scope.row.id)"> + <el-icon style="margin-right: 5px"> <EditPen /> </el-icon>修改 + </el-button> + <el-button + size="small" + text + type="primary" + v-if="scope.row.approveStatus === 0 || scope.row.approveStatus === null" + @click="initiateApproval(scope.row.id)" + > + 发起审批 + </el-button> + <el-button + size="small" + text + type="primary" + v-if="scope.row.approveStatus === 2 && scope.row.checkApprove === true" + @click="onApproval('修改', scope.row.approveId, scope.row.id)" + > + 审批 + </el-button> + <el-button + size="small" + text + type="primary" + v-if="scope.row.approveStatus === 2 && scope.row.checkApprove === false" + @click="onApproval('详情', scope.row.approveId, scope.row.id)" + > + 查看审批 + </el-button> + <el-button size="small" text type="primary" v-if="scope.row.approveStatus === 3" @click="onApprovalProcess(scope.row.id)"> + 查看审批流程 + </el-button> + <!-- <el-button size="small" text type="primary" @click="jumpFrom(0)">--> + <!-- <el-icon style="margin-right: 5px;">--> + <!-- <EditPen />--> + <!-- </el-icon>修改--> + <!-- </el-button>--> + <!-- <el-button size="small" text type="primary" @click="abolish(0)">--> + <!-- 发起审批--> + <!-- </el-button>--> + <el-button size="small" text type="primary" @click="onRowDel(scope.row.id)"> + <el-icon> <Delete /> </el-icon>删除 + </el-button> + </template> + </el-table-column> + </el-table> + <div class="pages"> + <el-pagination + v-if="tableData.length == 0 ? false : true" + v-model:currentPage="pageIndex" + v-model:page-size="pageSize" + :page-sizes="[10, 20, 30]" + :pager-count="5" + class="mt15" + background + layout="total, sizes, prev, pager, next, jumper" + :total="total" + @size-change="onHandleSizeChange" + @current-change="onHandleCurrentChange" + /> + </div> + </el-card> + <OpenAdd ref="addRef" @myAdd="onMyAdd" /> + <AbolishLibrary ref="abolishRef" @myAdd="onMyAdd" /> + <InitiateApproval ref="initiateApprovalRef" @myAdd="onMyAdd" /> + <Approval ref="approvalRef" @myAdd="onMyAdd" /> + <ApprovalProcess ref="processRef" @myAdd="onMyAdd" /> + <!-- <StartUp ref="startRef" @myAdd="startUp"/>--> + <el-dialog v-model="dialogFormVisible" width="30%" title="启动" :fullscreen="full"> + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-form :model="form" ref="ruleFormRef" label-width="80px"> + <el-form-item label="备注"> + <el-input v-model="form.remark" type="textarea" autocomplete="off" /> + </el-form-item> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="dialogFormVisible = false">取消</el-button> + <el-button type="primary" @click="onDetermine">确定</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script lang="ts"> +import { reactive, onMounted, ref, defineComponent } from 'vue'; +import { ElMessageBox, ElMessage } from 'element-plus'; +// import {useRouter} from "vue-router" +import type {} from // FormInstance, +'element-plus'; +import { Plus, Edit, Delete, Upload, Download, Refresh, VideoPause, VideoPlay, EditPen, FullScreen } from '@element-plus/icons-vue'; +import OpenAdd from '/@/views/contingencyManagement/panManagement/component/openAdd.vue'; +// import StartUp from '/@/views/contingencyManagement/panManagement/component/startUp.vue'; +import AbolishLibrary from '/@/views/contingencyManagement/panManagement/component/abolishLibrary.vue'; +import ApprovalProcess from '/@/views/contingencyManagement/panManagement/component/approvalProcess.vue'; +import InitiateApproval from '/@/views/contingencyManagement/panManagement/component/initiateApproval.vue'; +import Approval from '/@/views/contingencyManagement/panManagement/component/approval.vue'; +// import UpData from '/@/views/contingencyManagement/panManagement/component/upData.vue'; +import { emergencyPlanApi } from '/@/api/contingencyManagement/emergencyPlan'; +import { emergencyPlanLogApi } from '/@/api/contingencyManagement/emergencyPlanLog'; + +export default defineComponent({ + name: 'systemUser', + components: { + OpenAdd, + // StartUp, + InitiateApproval, + AbolishLibrary, + Approval, + EditPen, + Plus, + Edit, + Delete, + Upload, + Download, + Refresh, + VideoPause, + VideoPlay, + ApprovalProcess, + // UpData, + emergencyPlanApi, + }, + setup(prop, { emit }) { + // 列表参数 + const listQuery = reactive({ + pageIndex: 1, + pageSize: 10, + searchParams: { + name: '', + type: '', + abolishStatus: false, + }, + }); + // 定义表格数据 + const tableData = ref([]); + // 列表数据请求 + const onSubmit = async () => { + let res = await emergencyPlanApi().getEmergencyPlanList(listQuery); + if (res.data.code === '200') { + tableData.value = res.data.data; + pageIndex.value = res.data.pageIndex; + pageSize.value = res.data.pageSize; + total.value = res.data.total; + } else { + ElMessage({ + showClose: true, + type: 'error', + message: res.data.msg, + }); + } + }; + // 重置 + const submitReset = () => { + listQuery.searchParams.name = ''; + listQuery.searchParams.type = ''; + onSubmit(); + }; + const warning = ref(true); + const danger = ref(true); + + // 上传 + // const upShow=ref() + // const upButton=()=>{ + // upShow.value.openDialog() + // } + // 启动弹窗 + const isDialogFormVisible = (data: any) => { + dialogFormVisible.value = true; + form.value.planId = data; + }; + const dialogFormVisible = ref(false); + const form = ref({ + remark: '', + }); + const onDetermine = () => { + dialogFormVisible.value = false; + emergencyPlanLogApi() + .addEmergencyPlanLog(form.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'success', + }); + emit('myAdd', true); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + emit('myAdd', true); + } + }); + form.value = { + remark: '', + }; + }; + // 打开新增用户弹窗 + const addRef = ref(); + const onOpenAdd = () => { + addRef.value.openDialog('新建应急预案管理', false); + }; + // 新增后刷新 + const onMyAdd = (e: boolean) => { + if (e) { + onSubmit(); + } else { + onSubmit(); + } + }; + // 打开修改应急预案管理弹窗 + const onEdit = (val: string, row: object) => { + if (val == '详情') { + addRef.value.openDialog('查看应急预案管理', row, true); + } else { + addRef.value.openDialog('修改应急预案管理', row, false); + } + }; + + //打开废止库弹窗 + const abolishRef = ref(); + const onabolishLibrary = () => { + abolishRef.value.openDialog(); + }; + // 废止 + const abolish = (data: any) => { + ElMessageBox.confirm('确定要废止所选项吗?', '提示', { + confirmButtonText: '确认', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + emergencyPlanApi() + .EmergencyTeam(data) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'success', + }); + onSubmit(); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + onSubmit(); + } + }); + }) + .catch(() => {}); + }; + + // 删除用户 + const onRowDel = (id: number) => { + let arr = []; + arr.push(id); + ElMessageBox.confirm('确定删除所选项吗?', '提示', { + confirmButtonText: '确认', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + emergencyPlanApi() + .deleteEmergencyTeam(arr) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'success', + }); + onSubmit(); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + onSubmit(); + } + }); + }) + .catch(() => {}); + }; + + const deleteAll = ref(); + const handleSelectionChange = (val: any) => { + let valId = JSON.parse(JSON.stringify(val)); + let arr = []; + for (let i = 0; i < valId.length; i++) { + arr.push(valId[i].id); + } + deleteAll.value = arr; + if (val.length == 1) { + warning.value = false; + danger.value = false; + } else if (val.length == 0) { + warning.value = true; + danger.value = true; + } else { + warning.value = true; + danger.value = false; + } + }; + // 多选删除 + const onDeleteAll = () => { + ElMessageBox.confirm('确定删除所选项吗?', '提示', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + emergencyPlanApi() + .deleteEmergencyTeam(deleteAll.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + message: res.data.msg, + type: 'success', + }); + onSubmit(); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + onSubmit(); + } + }); + }) + .catch(() => {}); + }; + // 分页 + const pageIndex = ref(); + const pageSize = ref(); + const total = ref(); + // 分页改变 + const onHandleSizeChange = (val: number) => { + listQuery.pageSize = val; + onSubmit(); + }; + // 分页未改变 + const onHandleCurrentChange = (val: number) => { + listQuery.pageIndex = val; + onSubmit(); + }; + + // const router=useRouter() + // 修改跳转 + // const jumpFrom=(data:string)=>{ + // router.push({ + // path:"/processForm", + // query:{ + // type:data + // } + // }) + // } + // 发起审批跳转 + // const abolish=(data:string)=>{ + // router.push({ + // path:"/abolishDialog", + // query:{ + // type:data + // } + // }) + // } + // 发起审批弹窗 + const initiateApprovalRef = ref(); + const initiateApproval = (row: object) => { + initiateApprovalRef.value.openDialog('发起审批', row, true); + }; + // 审批 + const approvalRef = ref(); + const onApproval = (val: string, row: object, id) => { + if (val == '详情') { + approvalRef.value.openDialog('查看审批', row, true); + } else { + approvalRef.value.openDialog('审批', row, false, id); + } + }; + // 审批流程 + const processRef = ref(); + const onApprovalProcess = (row: object, id) => { + processRef.value.openDialog(row, id); + }; + + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + // 页面加载时 + onMounted(() => { + onSubmit(); + }); + return { + tableData, + onSubmit, + onOpenAdd, //新增 + addRef, + onabolishLibrary, + abolishRef, + abolish, + onRowDel, + onHandleSizeChange, + onHandleCurrentChange, + toggleFullscreen, + FullScreen, + full, + listQuery, + pageIndex, + pageSize, + total, + submitReset, + onMounted, + deleteAll, + warning, + danger, + handleSelectionChange, + onMyAdd, + onDeleteAll, + dialogFormVisible, + isDialogFormVisible, + form, + emit, + onDetermine, + onEdit, + initiateApproval, + initiateApprovalRef, + onApproval, + approvalRef, + onApprovalProcess, + processRef, + }; + }, +}); +</script> +<style scoped lang="scss"> +.table_Box { + padding: 20px; + background-color: #fff; +} +.tableForm { + margin-top: 10px; +} +/*按钮行*/ +.button_Line { + display: flex; + flex-direction: row; + justify-content: space-between; + margin-bottom: 10px; +} +.el-form .el-form-item { + margin-bottom: 0 !important; +} +.el-button--text { + margin-right: 15px; +} +.el-select { + width: 300px; +} +.el-input { + width: 300px; +} +.dialog-footer button:first-child { + margin-right: 10px; +} +//弹窗底部边框线 +::v-deep .el-dialog__footer { + border-top: 1px solid #e8e8e8; + border-radius: 0 0 4px 4px; +} +//弹窗顶部边框线 +::v-deep .el-dialog__header { + border-bottom: 1px solid #e8e8e8; + margin-right: 0; + border-radius: 4px 4px 0 0; +} +//表头 +::v-deep .el-table th.el-table__cell { + background-color: #f6f7fa; + font-weight: 400; + color: #909399; +} +.el-table .sort-caret.ascending { + border-bottom-color: #c0c4cc; +} +//分页 +.pages { + display: flex; + justify-content: flex-end; + margin-top: 15px; +} +::v-deep .el-pagination .el-pager li { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +::v-deep .el-pagination .el-pager li.is-active { + background-color: #409eff; + color: #fff; +} +::v-deep .el-pagination .btn-prev { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +::v-deep .el-pagination button:disabled { + color: #c0c4cc; +} +::v-deep .el-pagination .btn-next { + margin: 0 5px; + background-color: #f4f4f5; + color: #606266; + min-width: 30px; + border-radius: 2px; +} +</style> \ No newline at end of file diff --git a/src/views/contingencyManagement/processForm/component/formInformationTop.vue b/src/views/contingencyManagement/processForm/component/formInformationTop.vue new file mode 100644 index 0000000..ef75063 --- /dev/null +++ b/src/views/contingencyManagement/processForm/component/formInformationTop.vue @@ -0,0 +1,144 @@ +<template> + <el-form ref="form" :model="form" label-width="120px"> + <el-row> + <el-col :span="11"> + <el-form-item label="安全目标指标"> + <el-input v-model="form.name"></el-input> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="目标指标编号"> + <el-input v-model="form.name"></el-input> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="11"> + <el-form-item label="年度"> + <el-input v-model="form.name"></el-input> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="指标值"> + <el-input v-model="form.name"></el-input> + </el-form-item> + </el-col> + </el-row> + </el-form> + <el-tabs v-model="activeName" style="padding: 0 20px"> + <el-tab-pane label="考核指标" name="1"> + <el-table :data="tableData" style="width: 100%"> + <el-table-column align="center" type="index" label="序号" width="70" /> + <el-table-column align="center" prop="date" label="责任部门" /> + <el-table-column align="center" prop="name" label="考核指标" /> + <el-table-column align="center" prop="address" label="制定部门" /> + <el-table-column align="center" prop="address" label="制定日期" /> + <el-table-column align="center" label="检查值"> + <template #default> + <el-input v-model="form.name" placeholder=""></el-input> + </template> + </el-table-column> + <el-table-column align="center" prop="address" label="检查人" /> + <el-table-column align="center" prop="address" label="检查时间" /> + </el-table> + <div class="tiao"> + <div class="typeS">审批</div> + </div> + <el-row style="padding:20px 0"> + <el-col :span="6" style="text-align:right">一级审批:</el-col> + <el-col :span="18">同意</el-col> + </el-row> + <el-row style="padding:0 0 20px 0"> + <el-col :span="6"></el-col> + <el-col :span="18"><span class="logoColor">同意</span><span style="margin-right: 8px;">杜建喜</span><span>2021-05-24 04:47:42</span></el-col> + </el-row> + </el-tab-pane> + </el-tabs> +</template> +<script lang="ts"> +import { defineComponent,ref,reactive } from 'vue' + +export default defineComponent({ + setup() { + const form = reactive({ + name: '', + region: '', + date1: '', + date2: '', + delivery: false, + type: [], + resource: '', + desc: '', + }); + const tableData = [ + { + date: '2016-05-03', + name: 'Tom', + address: 'No. 189, Grove St, Los Angeles', + }, + ]; + const activeName = ref('1'); + return{ + form, + tableData, + activeName + } + }, +}) +</script> +<style scoped> +.title { + text-align: center; + font-size: 16px; + margin-bottom: 20px; +} +.box{ + border: 1px solid #dcdfe6; + box-shadow: 0 2px 4px 0 rgb(0 0 0 / 12%), 0 0 6px 0 rgb(0 0 0 / 4%); +} +.navType { + background-color: #fff; +} +.tiao{ + width: 100%; + height: 1px; + background-color: #dcdfe6; + margin: 30px 0 ; + position: relative; +} +.typeS{ + width: 80px; + background-color: #fff; + position: absolute; + left: 30px; + top: -9px; + font-size: 14px; + text-align: center; +} +.logoColor{ + background-color: #67c23a; + color: #fff; + padding: 5px 8px; + border-radius: 5px; + margin-right: 5px; +} +.btns{ + width: 100%; + padding:20px 0; + background-color: #fff; + position: fixed; + bottom: 0px; + left: 0px; + text-align: center; + box-shadow: 0 -3px 5px 0 rgb(0 0 0 / 12%); + +} +.title2{ + padding: 20px 0 20px 10px; + width: 100%; + border: 1px solid #dcdfe6; +} +.el-row{ + padding:0 0 20px 0 ; +} +</style> diff --git a/src/views/contingencyManagement/processForm/component/formInformationTops.vue b/src/views/contingencyManagement/processForm/component/formInformationTops.vue new file mode 100644 index 0000000..53eed6a --- /dev/null +++ b/src/views/contingencyManagement/processForm/component/formInformationTops.vue @@ -0,0 +1,312 @@ +<template> + <el-form ref="form" :model="form" label-width="120px"> + <el-row> + <el-col :span="12"> + <el-form-item label="预案名称"> + <el-input v-model="form.name" placeholder="请填写预案名称"></el-input> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="适用部门"> + <el-tree-select + class="select" + placeholder="请选择" + v-model="value" + :data="data" + :render-after-expand="false" + show-checkbox + multiple + clearable + /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="预案类型"> + <el-select class="select" v-model="form.region" placeholder="请选择"> + <el-option label="综合应急预案" value="shanghai" /> + <el-option label="现场处置方案" value="beijing" /> + <el-option label="专项应急预案" value="shanghai" /> + <el-option label="其它预案" value="beijing" /> + </el-select> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="危险源关联"> + <el-select class="select" v-model="form.region" placeholder="请选择"> + <el-option label="是" value="shanghai" /> + <el-option label="否" value="beijing" /> + </el-select> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="预案级别"> + <el-select class="select" v-model="form.region" placeholder="请选择"> + <el-option label="公司及" value="shanghai" /> + <el-option label="分厂级" value="beijing" /> + <el-option label="车间级" value="beijing" /> + </el-select> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="编写人"> + <el-input + v-model="form.teamLeader" + placeholder="请选择" + class="input-with-select" + > + <template #append> + <el-button :icon="Search" @click="openUser"/> + </template> + </el-input> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="编写部门" placeholder="请选择"> + <el-tree-select + class="select" + v-model="value2" + :data="dataSelect" + :render-after-expand="false" + multiple + check-strictly + check-on-click-node + clearable + /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="发布实施日期"> + <el-date-picker v-model="datetime" type="datetime" placeholder="选择日期时间" style="width: 100%" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="应急队伍" prop="telephone" @click="daiInpt" > + <el-input + v-model="form.teamLeader" + placeholder="请选择" + class="input-with-select" + > + <template #append> + <el-button :icon="Search"/> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="预案附件"> + <el-upload + v-model:file-list="fileList" + class="upload-demo" + action="https://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15" + :on-change="handleChange" + > + <el-button type="primary" + >点击上传</el-button> + <template #tip> + <div class="el-upload__tip"> + 添加相关附件 + </div> + </template> + </el-upload> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="区域名称" prop="telephone"> + <el-input + v-model="form.teamLeader" + placeholder="请选择" + class="input-with-select" + > + <template #append> + <el-button :icon="Search" @click="regionsDialog"/> + </template> + </el-input> + </el-form-item> + </el-col> + </el-row> + </el-form> + <checkTemplate ref="ShowRef"/> + <userSelections ref="userRef"/> + <RegionsDialog ref="openRef"/> +</template> +<script lang="ts"> +import { + defineComponent, + ref, + reactive +} from 'vue'; +import { + Search +} from '@element-plus/icons-vue' +import UserSelections from "/@/components/userSelections/index.vue" +import CheckTemplate from "/@/components/checkTemplate/index.vue" +import RegionsDialog from "/@/components/regionsDialog/index.vue"; +export default defineComponent({ + components: { + CheckTemplate, + UserSelections, + RegionsDialog, + }, + setup() { + const form = reactive({ + name: '', + value: '', + value2: '', + teamLeader: '', + + // data: '', + // dataSelect: '', + date1: '', + date2: '', + delivery: false, + type: [], + resource: '', + desc: '', + }); + + // 可选择树形选择框 + const value = ref() + + const data = [ + { + value: '1', + label: '广汇能源综合物流发展有限责任公司', + children: [ + { + value: '1-1', + label: '生产运行部', + children: [ + { + value: '1-1-1', + label: '工艺二班', + }, + ], + }, + ], + } + ] + // 树形选择框 + const value2 = ref() + + const dataSelect = [ + { + value: '1', + label: '广汇能源综合物流发展有限责任公司', + children: [ + { + value: '1-1', + label: '生产运行部', + children: [ + { + value: '1-1-1', + label: '工艺二班', + }, + ], + }, + ], + } + ] + // 应急队伍弹窗 + const ShowRef=ref() + const daiInpt=()=>{ + ShowRef.value.openDailog() + } + // 选择区域弹窗 + const openRef=ref() + const regionsDialog=()=>{ + openRef.value.openDailog() + } + // 打开编写人选择用户弹窗 + const userRef = ref(); + const openUser = () => { + userRef.value.openDialog(); + }; + // 日期选择 + const datetime = ref('') + return { + form, + value, + data, + value2, + dataSelect, + openUser, + userRef, + Search, + ShowRef, + daiInpt, + openRef, + datetime, + regionsDialog, + }; + }, +}); +</script> +<style scoped> +.title { + text-align: center; + font-size: 16px; + margin-bottom: 20px; +} +.box { + border: 1px solid #dcdfe6; + box-shadow: 0 2px 4px 0 rgb(0 0 0 / 12%), 0 0 6px 0 rgb(0 0 0 / 4%); +} +.navType { + background-color: #fff; +} +.tiao { + width: 100%; + height: 1px; + background-color: #dcdfe6; + margin: 30px 0; + position: relative; +} +.typeS { + width: 80px; + background-color: #fff; + position: absolute; + left: 30px; + top: -9px; + font-size: 14px; + text-align: center; +} +.logoColor { + background-color: #67c23a; + color: #fff; + padding: 5px 8px; + border-radius: 5px; + margin-right: 5px; +} +.btns { + width: 100%; + padding: 20px 0; + background-color: #fff; + position: fixed; + bottom: 0px; + left: 0px; + text-align: center; + box-shadow: 0 -3px 5px 0 rgb(0 0 0 / 12%); +} +.title2 { + padding: 20px 0 20px 10px; + width: 100%; + border: 1px solid #dcdfe6; +} +.el-row{ + padding:0 0 20px 0; +} +.select{ + width: 100%; +} +.select ::v-deep .el-select{ + width: 100%; +} +</style> diff --git a/src/views/contingencyManagement/processForm/component/lowerPlate.vue b/src/views/contingencyManagement/processForm/component/lowerPlate.vue new file mode 100644 index 0000000..cbb82fb --- /dev/null +++ b/src/views/contingencyManagement/processForm/component/lowerPlate.vue @@ -0,0 +1,120 @@ +<template> + <div class="box"> + <el-form ref="formS" :model="form" :rules="rules" label-width="120px"> + <el-row> + <el-col :span="15"> + <el-form-item label="流程标题"> + <el-input v-model="form.names" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="15"> + <el-form-item label="下级审批日期"> + <el-date-picker v-model="form.date1" type="date" placeholder="下级审批日期" style="width: 100%" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="15"> + <el-form-item label=""> + <el-checkbox v-model="form.delivery" label="是否抄送" @change="typeChang"/> + </el-form-item> + </el-col> + </el-row> + <el-row v-if="form.delivery"> + <el-col :span="15"> + <el-form-item label="抄送给" prop="resource"> + <el-input v-model="form.resource" placeholder=""> + <template #append> <el-button :icon="Search" @click="openDai" /> </template + ></el-input> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="15"> + <el-form-item label=""> + <el-checkbox v-model="form.type" label="指定下一步处理者(不设置就使用默认处理人)"/> + </el-form-item> + </el-col> + </el-row> + <el-row v-if="form.type"> + <el-col :span="15"> + <el-form-item label="指定" prop="desc"> + <el-input v-model="form.desc" placeholder=""> + <template #append> <el-button :icon="Search" @click="openDai" /> </template + ></el-input> + </el-form-item> + </el-col> + </el-row> + </el-form> + </div> + <DailogSearchUser ref="ShowUser"></DailogSearchUser> +</template> +<script lang="ts"> +import { defineComponent, ref, reactive } from 'vue'; +import DailogSearchUser from '/@/components/DailogSearchUser/index.vue' +import { Search } from '@element-plus/icons-vue'; +import type { FormInstance, FormRules } from 'element-plus' +export default defineComponent({ + components:{DailogSearchUser}, + setup() { + const formS=ref<FormInstance>() + let form = reactive({ + names: '', + region: '', + date1: '', + date2: '', + delivery: "", + type: "", + resource: '', + desc: '', + }); + const typeChang=()=>{ + console.log('tag',form) + } + const rules = reactive<FormRules>({ + resource: [ + { + type: 'array', + required: true, + message: '用户不能为空', + trigger: 'change', + }, + ], + desc: [ + { + required: true, + message: '用户不能为空', + trigger: 'change', + }, + ]}) + const ShowUser=ref() + const openDai =()=>{ + ShowUser.value.openDailog() + } + return { + form, + rules, + formS, + typeChang, + ShowUser, + openDai, + Search, + }; + }, +}); +</script> + +<style scoped> +.box { + margin: 30px 0 100px 0; + background-color: #fff; + border: 1px solid #dcdfe6; + box-shadow: 0 2px 4px 0 rgb(0 0 0 / 12%), 0 0 6px 0 rgb(0 0 0 / 4%); + padding: 20px; +} +.el-row { + padding: 0 0 20px 0; +} +</style> \ No newline at end of file diff --git a/src/views/contingencyManagement/processForm/processForm.vue b/src/views/contingencyManagement/processForm/processForm.vue new file mode 100644 index 0000000..98218a0 --- /dev/null +++ b/src/views/contingencyManagement/processForm/processForm.vue @@ -0,0 +1,137 @@ +<template> + <div class="system-user-container"> + <h4 class="title">胡海涛2022-07-01 16:08:42发起了目标检查上报(检查)--检查</h4> + <div class="box"> + <el-menu + :default-active="activeIndex" + class="el-menu-demo" + background-color="#ebeef5" + text-color="#fff" + active-text-color="#fff" + mode="horizontal" + @select="handleSelect" + > + <el-menu-item index="1">表单信息</el-menu-item> + <el-menu-item index="2">流程图</el-menu-item> + </el-menu> + <div v-if="activeIndex == 1" class="navType"> + <formInformationTop v-if="false"></formInformationTop> + <formInformationTops></formInformationTops> + </div> + <div v-if="activeIndex == 2" class="navType" style="padding:20px 20px 0 20px"> + <div class="title2">流程图</div> + <div style="width:100%;height:400px"></div> + </div> + </div> + <lowerPlate></lowerPlate> + <div class="btns"> + <el-button type="primary">启动</el-button> + </div> + </div> +</template> +<script lang="ts"> +import { defineComponent, reactive, ref,onMounted } from 'vue'; +import { useRouter } from 'vue-router'; +import formInformationTop from './component/formInformationTop.vue' +import formInformationTops from './component/formInformationTops.vue' +import lowerPlate from './component/lowerPlate.vue' +export default defineComponent({ + components:{lowerPlate,formInformationTop,formInformationTops}, + setup() { + const activeIndex = ref('1'); + const handleSelect = (key: string, keyPath: string[]) => { + // console.log(key, keyPath); + activeIndex.value = key; + }; + const form = reactive({ + name: '', + region: '', + date1: '', + date2: '', + delivery: false, + type: [], + resource: '', + desc: '', + }); + + const router=useRouter() + const Type=onMounted(()=>{ + // console.log("xxxxxxx",router) + }) + + return { + activeIndex, + handleSelect, + form, + router, + Type + }; + }, +}); +</script> +<style scoped> +.title { + text-align: center; + font-size: 16px; + margin-bottom: 20px; +} +.box{ + border: 1px solid #dcdfe6; + box-shadow: 0 2px 4px 0 rgb(0 0 0 / 12%), 0 0 6px 0 rgb(0 0 0 / 4%); +} +.navType { + background-color: #fff; + padding: 15px; +} +.tiao{ + width: 100%; + height: 1px; + background-color: #dcdfe6; + margin: 30px 0 ; + position: relative; +} +.typeS{ + width: 80px; + background-color: #fff; + position: absolute; + left: 30px; + top: -9px; + font-size: 14px; + text-align: center; +} +.logoColor{ + background-color: #67c23a; + color: #fff; + padding: 5px 8px; + border-radius: 5px; + margin-right: 5px; +} +.btns{ + width: 100%; + padding:20px 0; + background-color: #fff; + position: fixed; + bottom: 0px; + left: 0px; + text-align: center; + box-shadow: 0 -3px 5px 0 rgb(0 0 0 / 12%); + +} +.title2{ + padding: 20px 0 20px 10px; + width: 100%; + border: 1px solid #dcdfe6; +} + +/*弹窗底部边框线*/ +::v-deep .el-dialog__footer{ + border-top: 1px solid #e8e8e8; + border-radius: 0 0 4px 4px; +} +/*弹窗顶部边框线*/ +::v-deep .el-dialog__header { + border-bottom: 1px solid #e8e8e8; + margin-right: 0; + border-radius: 4px 4px 0 0; +} +</style> diff --git a/src/views/contingencyManagement/releaseOfDrillStart/component/formInformationTop.vue b/src/views/contingencyManagement/releaseOfDrillStart/component/formInformationTop.vue new file mode 100644 index 0000000..ef75063 --- /dev/null +++ b/src/views/contingencyManagement/releaseOfDrillStart/component/formInformationTop.vue @@ -0,0 +1,144 @@ +<template> + <el-form ref="form" :model="form" label-width="120px"> + <el-row> + <el-col :span="11"> + <el-form-item label="安全目标指标"> + <el-input v-model="form.name"></el-input> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="目标指标编号"> + <el-input v-model="form.name"></el-input> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="11"> + <el-form-item label="年度"> + <el-input v-model="form.name"></el-input> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="指标值"> + <el-input v-model="form.name"></el-input> + </el-form-item> + </el-col> + </el-row> + </el-form> + <el-tabs v-model="activeName" style="padding: 0 20px"> + <el-tab-pane label="考核指标" name="1"> + <el-table :data="tableData" style="width: 100%"> + <el-table-column align="center" type="index" label="序号" width="70" /> + <el-table-column align="center" prop="date" label="责任部门" /> + <el-table-column align="center" prop="name" label="考核指标" /> + <el-table-column align="center" prop="address" label="制定部门" /> + <el-table-column align="center" prop="address" label="制定日期" /> + <el-table-column align="center" label="检查值"> + <template #default> + <el-input v-model="form.name" placeholder=""></el-input> + </template> + </el-table-column> + <el-table-column align="center" prop="address" label="检查人" /> + <el-table-column align="center" prop="address" label="检查时间" /> + </el-table> + <div class="tiao"> + <div class="typeS">审批</div> + </div> + <el-row style="padding:20px 0"> + <el-col :span="6" style="text-align:right">一级审批:</el-col> + <el-col :span="18">同意</el-col> + </el-row> + <el-row style="padding:0 0 20px 0"> + <el-col :span="6"></el-col> + <el-col :span="18"><span class="logoColor">同意</span><span style="margin-right: 8px;">杜建喜</span><span>2021-05-24 04:47:42</span></el-col> + </el-row> + </el-tab-pane> + </el-tabs> +</template> +<script lang="ts"> +import { defineComponent,ref,reactive } from 'vue' + +export default defineComponent({ + setup() { + const form = reactive({ + name: '', + region: '', + date1: '', + date2: '', + delivery: false, + type: [], + resource: '', + desc: '', + }); + const tableData = [ + { + date: '2016-05-03', + name: 'Tom', + address: 'No. 189, Grove St, Los Angeles', + }, + ]; + const activeName = ref('1'); + return{ + form, + tableData, + activeName + } + }, +}) +</script> +<style scoped> +.title { + text-align: center; + font-size: 16px; + margin-bottom: 20px; +} +.box{ + border: 1px solid #dcdfe6; + box-shadow: 0 2px 4px 0 rgb(0 0 0 / 12%), 0 0 6px 0 rgb(0 0 0 / 4%); +} +.navType { + background-color: #fff; +} +.tiao{ + width: 100%; + height: 1px; + background-color: #dcdfe6; + margin: 30px 0 ; + position: relative; +} +.typeS{ + width: 80px; + background-color: #fff; + position: absolute; + left: 30px; + top: -9px; + font-size: 14px; + text-align: center; +} +.logoColor{ + background-color: #67c23a; + color: #fff; + padding: 5px 8px; + border-radius: 5px; + margin-right: 5px; +} +.btns{ + width: 100%; + padding:20px 0; + background-color: #fff; + position: fixed; + bottom: 0px; + left: 0px; + text-align: center; + box-shadow: 0 -3px 5px 0 rgb(0 0 0 / 12%); + +} +.title2{ + padding: 20px 0 20px 10px; + width: 100%; + border: 1px solid #dcdfe6; +} +.el-row{ + padding:0 0 20px 0 ; +} +</style> diff --git a/src/views/contingencyManagement/releaseOfDrillStart/component/formInformationTops.vue b/src/views/contingencyManagement/releaseOfDrillStart/component/formInformationTops.vue new file mode 100644 index 0000000..8a1f2a5 --- /dev/null +++ b/src/views/contingencyManagement/releaseOfDrillStart/component/formInformationTops.vue @@ -0,0 +1,440 @@ +<template> + <el-form ref="form" :model="form" label-width="120px"> + <el-row> + <el-col :span="12"> + <el-form-item label="演练名称"> + <el-input v-model="form.name" placeholder="请填写预案名称" disabled></el-input> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="演练地点"> + <el-input v-model="form.teamName" placeholder="请填写演练地点" disabled></el-input> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="主办部门"> + <el-tree-select + v-model="form.responsibleDepartment" + :data="data" class="w100" + placeholder="请选择" + disabled + /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="演练方式" prop="teamLevel"> + <el-select v-model="form.teamLevel" class="w100" placeholder="请选择" disabled> + <el-option label="综合" value="admin"></el-option> + <el-option label="桌面" value="common3"></el-option> + <el-option label="专项" value="common2"></el-option> + </el-select> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="应急预案" prop="telephone" > + <el-input + v-model="form.teamLeader" + placeholder="请选择" + class="input-with-select" + disabled + > + <template #append> + <el-button :icon="Search" @click="daiInpt" disabled/> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="演练级别" prop="teamPhone"> + <el-select v-model="form.teamLevel" class="w100" placeholder="请选择" disabled> + <el-option label="公司级" value="admin"></el-option> + <el-option label="分厂级" value="common"></el-option> + <el-option label="车间级" value="common1"></el-option> + </el-select> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="计划定制日期" prop="teamPhone"> + <el-date-picker v-model="datetime" type="datetime" placeholder="选择日期时间" disabled style="width: 100%" /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="计划演练日期" prop="teamPhone"> + <el-date-picker v-model="drillDate" type="datetime" placeholder="选择日期时间" disabled style="width: 100%" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="修改时间" prop="teamPhone"> + <el-date-picker v-model="editDate" class="w100" type="datetime" placeholder="选择日期时间" disabled style="width: 100%" /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="计划定制人" prop="teamPhone"> + <el-input v-model="form.planCustomizer" disabled placeholder="请填写演练地点"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="制定部门" prop="telephone"> + <el-tree-select + v-model="form.responsibleDepartment" + :data="data" class="w100" + placeholder="请选择" + disabled + /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="演练人员" prop="telephone" > + <el-input + v-model="form.teamLeader" + placeholder="请选择" + class="input-with-select" + disabled + > + <template #append> + <el-button :icon="Search" @click="openUser" disabled/> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="演练目的" prop="telephone"> + <el-input + v-model="form.teamLeader" + placeholder="请填写演练目的" + class="input-with-select textarea" + type="textarea" + disabled + > + </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="演练负责人" prop="telephone" > + <el-input + v-model="form.teamLeader" + placeholder="请选择" + class="input-with-select" + disabled + > + <template #append> + <el-button :icon="Search" @click="openUser" disabled/> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="保险措施" prop="teamName"> + <el-input v-model="form.teamName" placeholder="请填写演练名称" disabled></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="演练经费" prop="teamName"> + <el-input v-model="form.teamName" placeholder="请填写演练名称" disabled></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="备注信息" prop="telephone"> + <el-input + v-model="form.teamLeader" + placeholder="请填写备注信息" + class="input-with-select textarea" + type="textarea" + disabled + > + </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20" style="margin-bottom: 0!important;"> + <el-form-item label="预案附件"> + <el-upload + v-model:file-list="fileList" + class="upload-demo" + action="https://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15" + :on-change="handleChange" + disabled + > + <el-button type="primary" disabled + >点击上传</el-button> + <template #tip> + <div class="el-upload__tip"> + 添加相关附件 + </div> + </template> + </el-upload> + </el-form-item> + </el-col> + </el-row> + </el-form> + <checkTemplate ref="ShowRef"/> + <userSelections ref="userRef"/> + <RegionsDialog ref="openRef"/> +</template> +<script lang="ts"> +import { + defineComponent, + ref, + reactive +} from 'vue'; +import { + Search +} from '@element-plus/icons-vue' +import type { + UploadUserFile, + // FormRules, +} from 'element-plus' +import UserSelections from "/@/components/userSelections/index.vue" +import CheckTemplate from "/@/components/checkTemplate/index.vue" +import RegionsDialog from "/@/components/regionsDialog/index.vue"; +export default defineComponent({ + components: { + CheckTemplate, + UserSelections, + RegionsDialog, + }, + setup() { + const form = reactive({ + name: '', + teamName: '', + responsibleDepartment: '', + teamLevel: '', + teamLeader: '', + date1: '', + date2: '', + delivery: false, + type: [], + resource: '', + desc: '', + }); + // 上传附件 + const fileList = ref<UploadUserFile[]>([]) + // 可选择树 + const treeSelect = ref() + const tree = [ + { + value: '1', + label: 'Level one 1', + children: [ + { + value: '1-1', + label: 'Level two 1-1', + children: [ + { + value: '1-1-1', + label: 'Level three 1-1-1', + }, + ], + }, + ], + }, + { + value: '2', + label: 'Level one 2', + children: [ + { + value: '2-1', + label: 'Level two 2-1', + children: [ + { + value: '2-1-1', + label: 'Level three 2-1-1', + }, + ], + }, + { + value: '2-2', + label: 'Level two 2-2', + children: [ + { + value: '2-2-1', + label: 'Level three 2-2-1', + }, + ], + }, + ], + }, + { + value: '3', + label: 'Level one 3', + children: [ + { + value: '3-1', + label: 'Level two 3-1', + children: [ + { + value: '3-1-1', + label: 'Level three 3-1-1', + }, + ], + }, + { + value: '3-2', + label: 'Level two 3-2', + children: [ + { + value: '3-2-1', + label: 'Level three 3-2-1', + }, + ], + }, + ], + }, + ] + //定义树形下拉框 + const responsibleDepartment = ref() + const data = [ + { + value: '1', + label: '广汇能源综合物流发展有限责任公司', + children: [ + { + value: '1-1', + label: '经营班子', + children: [], + }, + ], + }, + { + value: '2', + label: '生产运行部', + children: [ + { + value: '2-1', + label: '灌装一班', + children: [] + }, + { + value: '2-2', + label: '工艺四班', + children: [], + }, + ], + }, + { + value: '3', + label: '设备部', + children: [ + { + value: '3-1', + label: '仪表班', + children: [], + }, + { + value: '3-2', + label: '机修班', + children: [], + }, + ], + }, + ] + // 计划定制日期 + const datetime = ref('') + // 计划演练日期 + const drillDate = ref('') + // 修改时间 + const editDate = ref('') + // 应急队伍弹窗 + const ShowRef=ref() + const daiInpt=()=>{ + ShowRef.value.openDailog() + } + // 选择区域弹窗 + const openRef=ref() + const regionsDialog=()=>{ + openRef.value.openDailog() + } + // 打开编写人选择用户弹窗 + const userRef = ref(); + const openUser = () => { + userRef.value.openDialog(); + }; + return { + form, + data, + treeSelect, + tree, + drillDate, + editDate, + openUser, + userRef, + Search, + ShowRef, + daiInpt, + responsibleDepartment, + openRef, + datetime, + regionsDialog, + fileList, + }; + }, +}); +</script> +<style scoped> +.title { + text-align: center; + font-size: 16px; + margin-bottom: 20px; +} +.box { + border: 1px solid #dcdfe6; + box-shadow: 0 2px 4px 0 rgb(0 0 0 / 12%), 0 0 6px 0 rgb(0 0 0 / 4%); +} +.navType { + background-color: #fff; +} +.tiao { + width: 100%; + height: 1px; + background-color: #dcdfe6; + margin: 30px 0; + position: relative; +} +.typeS { + width: 80px; + background-color: #fff; + position: absolute; + left: 30px; + top: -9px; + font-size: 14px; + text-align: center; +} +.logoColor { + background-color: #67c23a; + color: #fff; + padding: 5px 8px; + border-radius: 5px; + margin-right: 5px; +} +.btns { + width: 100%; + padding: 20px 0; + background-color: #fff; + position: fixed; + bottom: 0px; + left: 0px; + text-align: center; + box-shadow: 0 -3px 5px 0 rgb(0 0 0 / 12%); +} +.title2 { + padding: 20px 0 20px 10px; + width: 100%; + border: 1px solid #dcdfe6; +} +.el-row{ + padding:0 0 20px 0; +} +.select{ + width: 100%; +} +.select ::v-deep .el-select{ + width: 100%; +} +</style> diff --git a/src/views/contingencyManagement/releaseOfDrillStart/component/lowerPlate.vue b/src/views/contingencyManagement/releaseOfDrillStart/component/lowerPlate.vue new file mode 100644 index 0000000..cbb82fb --- /dev/null +++ b/src/views/contingencyManagement/releaseOfDrillStart/component/lowerPlate.vue @@ -0,0 +1,120 @@ +<template> + <div class="box"> + <el-form ref="formS" :model="form" :rules="rules" label-width="120px"> + <el-row> + <el-col :span="15"> + <el-form-item label="流程标题"> + <el-input v-model="form.names" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="15"> + <el-form-item label="下级审批日期"> + <el-date-picker v-model="form.date1" type="date" placeholder="下级审批日期" style="width: 100%" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="15"> + <el-form-item label=""> + <el-checkbox v-model="form.delivery" label="是否抄送" @change="typeChang"/> + </el-form-item> + </el-col> + </el-row> + <el-row v-if="form.delivery"> + <el-col :span="15"> + <el-form-item label="抄送给" prop="resource"> + <el-input v-model="form.resource" placeholder=""> + <template #append> <el-button :icon="Search" @click="openDai" /> </template + ></el-input> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="15"> + <el-form-item label=""> + <el-checkbox v-model="form.type" label="指定下一步处理者(不设置就使用默认处理人)"/> + </el-form-item> + </el-col> + </el-row> + <el-row v-if="form.type"> + <el-col :span="15"> + <el-form-item label="指定" prop="desc"> + <el-input v-model="form.desc" placeholder=""> + <template #append> <el-button :icon="Search" @click="openDai" /> </template + ></el-input> + </el-form-item> + </el-col> + </el-row> + </el-form> + </div> + <DailogSearchUser ref="ShowUser"></DailogSearchUser> +</template> +<script lang="ts"> +import { defineComponent, ref, reactive } from 'vue'; +import DailogSearchUser from '/@/components/DailogSearchUser/index.vue' +import { Search } from '@element-plus/icons-vue'; +import type { FormInstance, FormRules } from 'element-plus' +export default defineComponent({ + components:{DailogSearchUser}, + setup() { + const formS=ref<FormInstance>() + let form = reactive({ + names: '', + region: '', + date1: '', + date2: '', + delivery: "", + type: "", + resource: '', + desc: '', + }); + const typeChang=()=>{ + console.log('tag',form) + } + const rules = reactive<FormRules>({ + resource: [ + { + type: 'array', + required: true, + message: '用户不能为空', + trigger: 'change', + }, + ], + desc: [ + { + required: true, + message: '用户不能为空', + trigger: 'change', + }, + ]}) + const ShowUser=ref() + const openDai =()=>{ + ShowUser.value.openDailog() + } + return { + form, + rules, + formS, + typeChang, + ShowUser, + openDai, + Search, + }; + }, +}); +</script> + +<style scoped> +.box { + margin: 30px 0 100px 0; + background-color: #fff; + border: 1px solid #dcdfe6; + box-shadow: 0 2px 4px 0 rgb(0 0 0 / 12%), 0 0 6px 0 rgb(0 0 0 / 4%); + padding: 20px; +} +.el-row { + padding: 0 0 20px 0; +} +</style> \ No newline at end of file diff --git a/src/views/contingencyManagement/releaseOfDrillStart/releaseOfDrillStart.vue b/src/views/contingencyManagement/releaseOfDrillStart/releaseOfDrillStart.vue new file mode 100644 index 0000000..98218a0 --- /dev/null +++ b/src/views/contingencyManagement/releaseOfDrillStart/releaseOfDrillStart.vue @@ -0,0 +1,137 @@ +<template> + <div class="system-user-container"> + <h4 class="title">胡海涛2022-07-01 16:08:42发起了目标检查上报(检查)--检查</h4> + <div class="box"> + <el-menu + :default-active="activeIndex" + class="el-menu-demo" + background-color="#ebeef5" + text-color="#fff" + active-text-color="#fff" + mode="horizontal" + @select="handleSelect" + > + <el-menu-item index="1">表单信息</el-menu-item> + <el-menu-item index="2">流程图</el-menu-item> + </el-menu> + <div v-if="activeIndex == 1" class="navType"> + <formInformationTop v-if="false"></formInformationTop> + <formInformationTops></formInformationTops> + </div> + <div v-if="activeIndex == 2" class="navType" style="padding:20px 20px 0 20px"> + <div class="title2">流程图</div> + <div style="width:100%;height:400px"></div> + </div> + </div> + <lowerPlate></lowerPlate> + <div class="btns"> + <el-button type="primary">启动</el-button> + </div> + </div> +</template> +<script lang="ts"> +import { defineComponent, reactive, ref,onMounted } from 'vue'; +import { useRouter } from 'vue-router'; +import formInformationTop from './component/formInformationTop.vue' +import formInformationTops from './component/formInformationTops.vue' +import lowerPlate from './component/lowerPlate.vue' +export default defineComponent({ + components:{lowerPlate,formInformationTop,formInformationTops}, + setup() { + const activeIndex = ref('1'); + const handleSelect = (key: string, keyPath: string[]) => { + // console.log(key, keyPath); + activeIndex.value = key; + }; + const form = reactive({ + name: '', + region: '', + date1: '', + date2: '', + delivery: false, + type: [], + resource: '', + desc: '', + }); + + const router=useRouter() + const Type=onMounted(()=>{ + // console.log("xxxxxxx",router) + }) + + return { + activeIndex, + handleSelect, + form, + router, + Type + }; + }, +}); +</script> +<style scoped> +.title { + text-align: center; + font-size: 16px; + margin-bottom: 20px; +} +.box{ + border: 1px solid #dcdfe6; + box-shadow: 0 2px 4px 0 rgb(0 0 0 / 12%), 0 0 6px 0 rgb(0 0 0 / 4%); +} +.navType { + background-color: #fff; + padding: 15px; +} +.tiao{ + width: 100%; + height: 1px; + background-color: #dcdfe6; + margin: 30px 0 ; + position: relative; +} +.typeS{ + width: 80px; + background-color: #fff; + position: absolute; + left: 30px; + top: -9px; + font-size: 14px; + text-align: center; +} +.logoColor{ + background-color: #67c23a; + color: #fff; + padding: 5px 8px; + border-radius: 5px; + margin-right: 5px; +} +.btns{ + width: 100%; + padding:20px 0; + background-color: #fff; + position: fixed; + bottom: 0px; + left: 0px; + text-align: center; + box-shadow: 0 -3px 5px 0 rgb(0 0 0 / 12%); + +} +.title2{ + padding: 20px 0 20px 10px; + width: 100%; + border: 1px solid #dcdfe6; +} + +/*弹窗底部边框线*/ +::v-deep .el-dialog__footer{ + border-top: 1px solid #e8e8e8; + border-radius: 0 0 4px 4px; +} +/*弹窗顶部边框线*/ +::v-deep .el-dialog__header { + border-bottom: 1px solid #e8e8e8; + margin-right: 0; + border-radius: 4px 4px 0 0; +} +</style> diff --git a/src/views/doublePrevent/dpIndex/index.vue b/src/views/doublePrevent/dpIndex/index.vue new file mode 100644 index 0000000..2f864e4 --- /dev/null +++ b/src/views/doublePrevent/dpIndex/index.vue @@ -0,0 +1,596 @@ +<template> + <div class="home-container"> + <el-scrollbar height="100%"> + <div class="main-cont"> + <div class="table-item"> + <div class="item-head"> + <span>告警风险事件概括</span> + <div @click="toRiskEve">查看更多>></div> + </div> + <el-table :data="eventData" style="width: 100%;height: 90%" :header-cell-style="{ background: '#fafafa' }"> + <el-table-column prop="riskEventName" label="风险事件名称" show-overflow-tooltip></el-table-column> + <el-table-column prop="riskUnitName" label="风险分析单元名称" show-overflow-tooltip></el-table-column> + <el-table-column prop="createByUserName" label="创建人" show-overflow-tooltip></el-table-column> + <el-table-column prop="gmtCreate" label="创建时间" show-overflow-tooltip></el-table-column> + </el-table> + </div> + <div class="table-item table-item2"> + <div class="item-head"> + <span>隐患状态详情</span> + <div @click="toRiskStatus">查看更多>></div> + </div> + <el-table :data="riskStatusData" style="width: 100%;height: 90%" :header-cell-style="{ background: '#fafafa' }"> + <el-table-column type="index" label="序号" width="60" /> +<!-- <el-table-column prop="reportTime" label="上报时间" show-overflow-tooltip width="170px"></el-table-column>--> + <el-table-column prop="dangerCode" label="隐患名称" show-overflow-tooltip></el-table-column> + <el-table-column prop="dangerLevel" label="隐患等级" show-overflow-tooltip> + <template #default="scope"> + <div :style="{color: scope.row.dangerLevel==1?'#409eff':'#ff0000'}"> + {{scope.row.dangerLevel==1?'一般隐患':'重大隐患'}} + </div> + </template> + </el-table-column> + <el-table-column prop="reportTime" label="上报时间" show-overflow-tooltip align="center"></el-table-column> + <el-table-column prop="dangerStatus" label="隐患状态" show-overflow-tooltip> + <template #default="scope"> + <div :style="{color: scope.row.dangerStatus==0 || scope.row.dangerStatus==1 ?'#67C23A':(scope.row.dangerStatus==2 || scope.row.dangerStatus==3?'#F56C6C':'#409EFF')}"> + {{scope.row.dangerStatus==0?'整改中':(scope.row.dangerStatus==1?'待验收':(scope.row.dangerStatus==2?'延期整改':(scope.row.dangerStatus==3?'超期未整改':'已验收')))}} + </div> + </template> + </el-table-column> + </el-table> + </div> + <div class="table-item"> + <div class="item-head"> + <span>隐患整改情况</span> + </div> + <div class="riskFix" :id="riskFixId"></div> + </div> + <div class="table-item"> + <div class="item-head"> + <span>风险装置列表</span> + <div @click="toRevice">查看更多>></div> + </div> + <el-table class="deviceTable" :data="deviceData" style="width: 100%" :header-cell-style="{ background: '#fafafa' }"> + <el-table-column prop="produceDeviceName" label="装置名称" show-overflow-tooltip></el-table-column> + <el-table-column prop="riskLevel" label="风险等级" show-overflow-tooltip> + <template #default="scope"> + <div :style="{color: scope.row.riskLevel==1?'#409EFF':(scope.row.riskLevel==2?'#67C23A':(scope.row.riskLevel==3?'#E6A23C':'#F56C6C'))}"> + {{scope.row.riskLevel==1?'低风险':(scope.row.riskLevel==2?'一般风险':(scope.row.riskLevel==3?'较大风险':'重大风险'))}} + </div> + </template> + </el-table-column> + </el-table> + <div class="deviceLevel"> + <div class="levelItem red"> + <span>0</span> + <div>重大风险</div> + </div> + <div class="levelItem orange"> + <span>2</span> + <div>较大风险</div> + </div> + <div class="levelItem green"> + <span>8</span> + <div>一般风险</div> + </div> + <div class="levelItem blue"> + <span>10</span> + <div>低风险</div> + </div> + </div> + </div> + <div class="table-item"> + <div class="item-head"> + <span>隐患等级分布</span> + </div> + <div class="riskLevel" :id="riskLevelId"></div> + </div> + </div> + </el-scrollbar> + </div> +</template> + +<script lang="ts"> + import { toRefs, reactive, ref, onMounted } from 'vue'; + import { storeToRefs } from 'pinia'; + import { initBackEndControlRoutes } from '/@/router/backEnd'; + import { useUserInfo } from '/@/stores/userInfo'; + import { Session } from '/@/utils/storage'; + import { Edit, View, Plus, Delete, Refresh, Search, Download } from '@element-plus/icons-vue'; + import { ElTable } from 'element-plus'; + import { FormInstance, FormRules, ElMessage } from 'element-plus'; + import { safetyRiskEventApi } from '/@/api/doublePreventSystem/safetyRiskEvent/index.ts'; + import { useRouter } from 'vue-router'; + import {hiddenReportApi} from "/@/api/doublePreventSystem/report"; + import { productionDeviceApi } from '/@/api/doublePreventSystem/productionDevice/index.ts'; + import * as echarts from 'echarts/core'; + import {TooltipComponent, TooltipComponentOption, LegendComponent, LegendComponentOption} from 'echarts/components'; + import {PieChart, PieSeriesOption} from 'echarts/charts'; + import {LabelLayout} from 'echarts/features'; + import {CanvasRenderer} from 'echarts/renderers'; + echarts.use([TooltipComponent, LegendComponent, PieChart, CanvasRenderer, LabelLayout]); + // 定义接口来定义对象的类型 + interface stateType { + eventData: Array<any>; + riskStatusData: Array<any>; + deviceData: Array<any>; + pageIndex: number; + pageSize: number; + totalSize: number; + departmentList: []; + classGroupList: Array<classGroup>; + inspectPointAllList: []; + } + interface type { + id: number; + name: string; + } + interface classGroup { + id: number; + groupName: string; + } + export default { + name: 'workingHours', + components: {}, + setup() { + const router = useRouter(); + const state = reactive<stateType>({ + pageIndex: 1, + pageSize: 5, + totalSize: 0, + eventData: [], + riskStatusData: [], + deviceData: [], + departmentList: [], + classGroupList: [], + inspectPointAllList: [] + }); + const riskFixId = ref("eChartFix" + Date.now() + Math.random()) + const riskLevelId = ref("eChartLe" + Date.now() + Math.random()) + + // 页面载入时执行方法 + onMounted(() => { + getEventRecord(); + getRiskStatusRecord(); + getDeviceRecord(); + initRiskFix(); + initRiskLevel() + }); + + // 告警列表 + const getEventRecord = async () => { + const data = { pageSize: state.pageSize, pageIndex: state.pageIndex}; + let res = await safetyRiskEventApi().getSafetyRiskEventList(data) + if (res.data.code === '200'){ + state.eventData = res.data.data + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 隐患状态列表 + const getRiskStatusRecord = async () => { + const data = { pageSize: state.pageSize, pageIndex: state.pageIndex}; + let res = await hiddenReportApi().getHiddenReportList(data) + if (res.data.code === '200'){ + state.riskStatusData = res.data.data + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 隐患状态列表 + const getDeviceRecord = async () => { + const data = { pageSize: state.pageSize, pageIndex: state.pageIndex}; + let res = await productionDeviceApi().getProductionDeviceList(data) + if (res.data.code === '200'){ + state.deviceData = res.data.data + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 隐患整改情况 + const initRiskFix =()=>{ + const dom = document.getElementById(riskFixId.value); + let myChart = echarts.init(dom, null, { + renderer: 'canvas', + useDirtyRect: false + }); + let app = {}; + + let option; + + option = { + tooltip: { + trigger: 'item' + }, + legend: { + bottom: '5%', + left: 'center' + }, + series: [ + { + type: 'pie', + radius: ['35%', '60%'], + avoidLabelOverlap: false, + itemStyle: { + borderRadius: 6, + borderColor: '#fff', + borderWidth: 2 + }, + label: { + alignTo: 'labelLine', + formatter: '{name|{b}}\n{value|{c}}', + minMargin: 5, + edgeDistance: 5, + lineHeight: 15, + rich: { + name: { + fontSize: 14, + color: '#666' + } + } + }, + labelLine: { + length: 15, + maxSurfaceAngle: 80 + }, + emphasis: { + label: { + show: true, + fontSize: '40', + fontWeight: 'bold' + } + }, + data: [ + { value: 1048, name: '整改中' }, + { value: 735, name: '待验收' }, + { value: 580, name: '延期整改' }, + { value: 484, name: '超期未整改' }, + { value: 300, name: '已验收' } + ], + center: ['50%','40%'] + } + ] + }; + + if (option && typeof option === 'object') { + myChart.setOption(option); + } + + window.addEventListener('resize', myChart.resize); + } + + // 隐患整改情况 + const initRiskLevel =()=>{ + const dom = document.getElementById(riskLevelId.value); + let myChart = echarts.init(dom, null, { + renderer: 'canvas', + useDirtyRect: false + }); + let app = {}; + + let option; + + option = { + tooltip: { + trigger: 'item', + formatter: '已完成整改:75%' + '\n\r' + '整改中:19%' + '\n\r' + '暂未整改:6%' + }, + legend: { + bottom: '5%', + left: 'center' + }, + series: [ + { + type: 'pie', + radius: ['35%', '60%'], + avoidLabelOverlap: false, + itemStyle: { + borderRadius: 6, + borderColor: '#fff', + borderWidth: 2 + }, + label: { + alignTo: 'labelLine', + formatter: '{name|{b}}\n{value|{c}}', + minMargin: 5, + edgeDistance: 5, + lineHeight: 15, + rich: { + name: { + fontSize: 14, + color: '#666' + } + } + }, + labelLine: { + length: 15, + maxSurfaceAngle: 80 + }, + emphasis: { + label: { + show: true, + fontSize: '40', + fontWeight: 'bold' + } + }, + data: [ + { value: 1048, name: '一般隐患' }, + { value: 235, name: '重大隐患' } + ], + center: ['50%','40%'] + } + ] + }; + + if (option && typeof option === 'object') { + myChart.setOption(option); + } + + window.addEventListener('resize', myChart.resize); + setTimeout(()=>{ + myChart.resize + },500) + } + + const toRiskEve = ()=>{ + router.push({ + path: 'event', + }); + } + + const toRiskStatus = ()=>{ + router.push({ + path: 'hiddenReport', + }); + } + + const toRevice = ()=>{ + router.push({ + path: 'device', + }); + } + + return { + View, + Edit, + Delete, + Refresh, + Plus, + router, + riskFixId, + riskLevelId, + toRiskEve, + toRiskStatus, + toRevice, + ...toRefs(state) + }; + } + }; +</script> + +<style scoped lang="scss"> + $homeNavLengh: 8; + + @media screen and (min-width: 1366px) { + .main-cont { + width: 100%; + height: 100%; + display: grid; + margin-bottom: 40px; + box-sizing: border-box; + grid-gap: 20px; + grid-template-columns: repeat(3, 1fr); + grid-template-rows: repeat(2, 1fr); + grid-auto-flow: row; + justify-content: center; + } + .item-head{ + height: 25px; + line-height: 25px; + span{ + font-size: 20px; + } + div{ + font-size: 16px; + } + } + + .levelItem{ + font-size: 16px; + + span{ + margin-bottom: 10px; + font-size: 24px; + font-weight: bolder; + } + } + } + + @media screen and (min-width: 1024px) and (max-width: 1366px){ + .main-cont { + width: 100%; + height: 100%; + display: grid; + margin-bottom: 40px; + box-sizing: border-box; + grid-gap: 15px; + grid-template-columns: repeat(3, 1fr); + grid-template-rows: repeat(2, 1fr); + grid-auto-flow: row; + justify-content: center; + } + .item-head{ + height: 20px; + line-height: 20px; + span{ + font-size: 16px; + } + div{ + font-size: 14px; + } + } + .levelItem{ + font-size: 14px; + + span{ + margin-bottom: 10px; + font-size: 20px; + font-weight: bolder; + } + } + } + + @media screen and (max-width: 1024px) { + .main-cont { + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + margin-bottom: 40px; + box-sizing: border-box; + justify-content: center; + } + .item-head{ + height: 20px; + line-height: 20px; + span{ + font-size: 16px; + } + div{ + font-size: 14px; + } + } + .levelItem{ + font-size: 12px; + + span{ + margin-bottom: 10px; + font-size: 16px; + font-weight: bolder; + } + } + } + .home-container { + height: 100%; + box-sizing: border-box; + overflow: hidden; + + .main-cont { + + .table-item{ + border-radius: 8px; + background: #fff; + padding: 15px; + display: flex; + flex-direction: column; + justify-content: space-between; + box-sizing: border-box; + + .item-head{ + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 20px; + border-left: 4px solid #409eff; + padding-left: 10px; + span{ + color: #333; + font-weight: bolder; + } + div{ + cursor: pointer; + + &:hover{ + color: #409eff; + } + } + } + .riskFix{ + height: 300px; + } + .riskLevel{ + height: 300px + } + .deviceTable{ + height: 200px; + } + .deviceLevel{ + width: 100%; + height: 100px; + display: grid; + grid-gap: 10px; + grid-template-columns: repeat(4, 1fr); + align-items: center; + justify-content: space-between; + + .levelItem{ + display: flex; + height: 100%; + flex-direction: column; + justify-content: flex-start; + align-items: center; + padding: 15px; + box-sizing: border-box; + border-radius: 8px; + color: #fff; + + span{ + margin-bottom: 10px; + font-weight: bolder; + } + } + .red{ + background: #F56C6C; + } + .orange{ + background: #E6A23C; + } + .green{ + background: #67C23A; + } + .blue{ + background: #409EFF; + } + } + } + .table-item2{ + grid-column-start: 2; + grid-column-end: 4; + } + } + .el-row { + display: flex; + align-items: center; + margin-bottom: 20px; + &:last-child { + margin-bottom: 0; + } + .grid-content { + align-items: center; + min-height: 36px; + } + } + } + .el-input { + width: 100% !important; + } + .el-date-editor::v-deep { + width: 100%; + } + .el-select { + width: 100%; + } +</style> \ No newline at end of file diff --git a/src/views/doublePrevent/riskCheckManage/checkTaskManage/checkTask/components/recordDialog.vue b/src/views/doublePrevent/riskCheckManage/checkTaskManage/checkTask/components/recordDialog.vue new file mode 100644 index 0000000..e22be03 --- /dev/null +++ b/src/views/doublePrevent/riskCheckManage/checkTaskManage/checkTask/components/recordDialog.vue @@ -0,0 +1,186 @@ +<template> + <div class="system-add-menu-container"> + <el-dialog :title="title" v-model="isShowRecordDialog" append-to-body :close-on-click-modal="false" width="600px"> + <div class="record-form"> + <el-form :model="recordForm" ref="recordFormRef" size="default" label-width="100px"> + <el-row :gutter="35"> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="检查内容" prop="checkContent"> + <el-input class="input-length" :disabled="true" type="textarea" :rows="3" v-model.trim="recordForm.checkContent" placeholder="检查内容"> </el-input> + </el-form-item> + </el-col> + </el-row> + </el-form> + </div> + </el-dialog> + <el-dialog :title="title" v-model="isShowSubmitDialog" width="600px" :close-on-click-modal="false"> + <el-form :model="submitForm" ref="rectifyFormRef" size="default" label-width="120px"> + <el-row :gutter="35"> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="处理结果" prop="checkResult"> + <el-select class="input-add" v-model="checkResults.checkResult" placeholder="请输入处理结果"> + <el-option v-for="item in resultList" :label="item.name" :key="item.id" :value="item.id"></el-option> + </el-select> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="isShowSubmitDialog = !isShowSubmitDialog" size="default">取 消</el-button> + <el-button type="primary" @click="submitRecord" v-throttle size="default">确 定</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script lang="ts"> +import { getUserByDepartment } from '/@/assets/methods'; + +interface stateType { + isShowRecordDialog: Boolean; + isShowSubmitDialog: Boolean; + recordForm: { + taskCode: string | null; + checkContent: string | null; + checkResult: string | null; + checkTaskId: number | null; + classify1: number | null; + classify2: number | null; + classify3: string | null; + controlMeasureCode: string | null; + controlMeasureId: number | null; + controlType: number | null; + measureDesc: string | null; + }; + title: string; + submitForm: { + execUserId: number | null; + id: number | null; + checkResults: Array<checkResults>; + }; + checkResults: { + id: number | null; + controlMeasureId: number | null; + checkResult: number | null; + }; + resultList: Array<result>; +} +interface result { + id: number; + name: string; +} +interface checkResults { + id: number | null; + controlMeasureId: number | null; + checkResult: number | null; +} +import { reactive, toRefs, ref } from 'vue'; +import { recordApi } from '/@/api/doublePreventSystem/record'; +import { ElMessage } from 'element-plus'; +export default { + name: 'recordDialog', + setup(props: any, context: any) { + const recordFormRef = ref(); + const state = reactive<stateType>({ + title: '查看', + isShowSubmitDialog: false, + isShowRecordDialog: false, + recordForm: { + taskCode: null, + checkContent: null, + checkResult: null, + checkTaskId: null, + classify1: null, + classify2: null, + classify3: null, + controlMeasureCode: null, + controlMeasureId: null, + controlType: null, + measureDesc: null + }, + submitForm: { + id: null, + execUserId: null, + checkResults: [] + }, + checkResults: { + id: null, + controlMeasureId: null, + checkResult: null + }, + resultList: [ + { id: 1, name: '正常' }, + { id: 2, name: '不正常' } + ] + }); + + //打开模态框 + const openRecordDialog = async (type: string, value: object) => { + if (type === '查看') { + state.title = '查看'; + state.isShowRecordDialog = true; + let recordFormValue = JSON.parse(JSON.stringify(value)); + state.recordForm.taskCode = recordFormValue.taskCode; + state.recordForm.checkContent = recordFormValue.checkContent; + } else { + state.title = '提交'; + state.isShowSubmitDialog = true; + state.submitForm.id = JSON.parse(JSON.stringify(value)).checkTaskId; + state.checkResults.id = JSON.parse(JSON.stringify(value)).id; + state.checkResults.controlMeasureId = JSON.parse(JSON.stringify(value)).controlMeasureId; + } + }; + + //新增修改提交 + const submitRecord = async () => { + if (state.checkResults.checkResult !== null) { + if (state.title === '提交') { + state.submitForm.checkResults.push(state.checkResults); + let res = await recordApi().submitRecord(state.submitForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '排查记录新增成功', + duration: 2000 + }); + state.isShowRecordDialog = false; + context.emit('refreshRecord'); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } + } else { + ElMessage({ + type: 'warning', + message: '请完善基本信息' + }); + } + }; + + return { + ...toRefs(state), + recordFormRef, + submitRecord, + openRecordDialog + }; + } +}; +</script> + +<style scoped> +::v-deep.el-divider--horizontal { + margin-top: 0px !important; +} + +::v-deep.el-dialog__body { + padding-top: 10px !important; +} +.filter-container { + padding: 10px 0px; +} +</style> diff --git a/src/views/doublePrevent/riskCheckManage/checkTaskManage/checkTask/index.vue b/src/views/doublePrevent/riskCheckManage/checkTaskManage/checkTask/index.vue new file mode 100644 index 0000000..f15e2ad --- /dev/null +++ b/src/views/doublePrevent/riskCheckManage/checkTaskManage/checkTask/index.vue @@ -0,0 +1,316 @@ +<template> + <div class="system-role-container"> + <el-card shadow="hover"> + <div class="system-user-search mb15"> + <div class="basic-line"> + <span>排查结果:</span> + <el-select class="input-box" v-model="recordData.params.result" placeholder="排查结果" filterable clearable> + <el-option v-for="item in resultList" :key="item.id" :label="item.name" :value="item.id"></el-option> + </el-select> + </div> + <div class="basic-line"> + <span>排查任务状态:</span> + <el-select class="input-box" v-model="recordData.params.taskStatus" placeholder="排查任务状态" filterable clearable> + <el-option v-for="item in taskStatusList" :key="item.id" :label="item.name" :value="item.id"></el-option> + </el-select> + </div> + <div class="basic-line"> + <span>任务类型:</span> + <el-select class="input-box" v-model="recordData.params.taskType" placeholder="任务类型" filterable clearable> + <el-option v-for="item in taskTypeList" :key="item.id" :label="item.name" :value="item.id"></el-option> + </el-select> + </div> + + <el-button size="default" type="primary" class="ml10" v-throttle @click="handleSearch"> + <el-icon> + <ele-Search /> + </el-icon> + 查询 + </el-button> + </div> + <el-table :data="recordData.data" style="width: 100%"> + <el-table-column type="expand"> + <template #default="scope"> + <el-table :data="scope.row.checkContent" style="width: 100%"> + <el-table-column label="序号" type="index" width="150" align="center"> </el-table-column> + <el-table-column label="检查内容" prop="checkContent" align="center"> </el-table-column> + <el-table-column label="检查结果" prop="checkResult" align="center"> + <template #default="scope"> + <el-tag :type="scope.row.checkResult === 1 ? 'success' : scope.row.checkResult === 2 ? 'danger' : 'info'"> + {{ parseNumber(scope.row.checkResult, '检查结果') }} + </el-tag> + </template> + </el-table-column> + <el-table-column label="操作" align="center" width="280" class-name="small-padding fixed-width"> + <template #default="scope"> + <el-button size="small" text type="primary" :icon="View" @click="onOpenDialogRef('查看', scope.row)">查看</el-button> + <el-button size="small" text type="primary" :icon="Check" @click="onOpenDialogRef('整改', scope.row)">提交</el-button> + </template> + </el-table-column> + </el-table> + </template> + </el-table-column> + <el-table-column type="index" label="序号" width="60" /> + <el-table-column prop="taskCode" label="排查名称" show-overflow-tooltip></el-table-column> + <el-table-column prop="execDepId" label="执行部门" show-overflow-tooltip> + <template #default="scope"> + {{ parseNumber(scope.row.execDepId, '执行部门') }} + </template> + </el-table-column> + <el-table-column prop="taskStatus" label="状态" show-overflow-tooltip> + <template #default="scope"> + {{ parseNumber(scope.row.taskStatus, '状态') }} + </template> + </el-table-column> + <el-table-column prop="taskBelong" label="是否认领" show-overflow-tooltip> + <template #default="scope"> + {{ parseNumber(scope.row.taskBelong, '认领状态') }} + </template> + </el-table-column> + <el-table-column prop="createUserName" label="创建人" show-overflow-tooltip></el-table-column> + <el-table-column prop="gmtCreate" label="创建时间" show-overflow-tooltip></el-table-column> + <el-table-column prop="lastEditUserName" label="最后修改人" show-overflow-tooltip></el-table-column> + <el-table-column prop="gmtModitify" label="最后修改时间" show-overflow-tooltip></el-table-column> + <el-table-column label="操作" align="center" width="280" class-name="small-padding fixed-width"> + <template #default="scope"> + <el-button size="small" text type="primary" v-show="(scope.row.taskStatus === 1 || scope.row.taskStatus === 4) && scope.row.taskBelong === 1" :icon="Check" @click="onHandleTask(scope.row)">任务认领</el-button> + </template> + </el-table-column> + </el-table> + <br /> + <el-pagination @size-change="onHandleSizeChange" @current-change="onHandleCurrentChange" :pager-count="5" :page-sizes="[10, 20, 30]" v-model:current-page="recordData.params.pageIndex" background v-model:page-size="recordData.params.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="recordData.total" class="page-position"> </el-pagination> + <br /> + <br /> + </el-card> + <recordDialog ref="recordDialogRef" @refreshrecord="initRecordTableData" /> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, onMounted, ref, defineComponent } from 'vue'; +import { ElMessageBox, ElMessage } from 'element-plus'; +import recordDialog from './components/recordDialog.vue'; +import { recordApi } from '/@/api/doublePreventSystem/record/index.ts'; +import { departmentApi } from '/@/api/systemManage/department'; +import { checkUnitApi } from '/@/api/doublePreventSystem/checkUnit'; +import { View, Check } from '@element-plus/icons-vue'; + +// 定义接口来定义对象的类型 +interface TableData { + roleName: string; + roleSign: string; + describe: string; + sort: number; + status: boolean; + createTime: string; +} +interface TableDataState { + recordData: { + data: Array<TableData>; + total: number; + loading: boolean; + params: { + pageIndex: number; + pageSize: number; + result: number | null; + taskStatus: number | null; + taskType: number | null; + }; + }; + taskUnitList: []; + departmentList: Array<DepartmentState>; + departmentRecursionList: Array<DepartmentState>; + resultList: Array<levelListState>; + checkResultList: Array<levelListState>; + taskStatusList: Array<levelListState>; + taskTypeList: Array<levelListState>; +} +interface levelListState { + id: number; + name: string; +} +interface DepartmentState { + depId: number; + depName: string; +} + +export default defineComponent({ + name: 'record', + components: { recordDialog, View, Check }, + setup() { + const recordDialogRef = ref(); + const state = reactive<TableDataState>({ + recordData: { + data: [], + total: 0, + loading: false, + params: { + pageIndex: 1, + pageSize: 10, + result: null, + taskStatus: null, + taskType: null + } + }, + taskUnitList: [], + departmentList: [], + departmentRecursionList: [], + resultList: [ + { id: 1, name: '正常' }, + { id: 2, name: '存在隐患' }, + { id: 3, name: '未排查' }, + { id: 4, name: '其他' } + ], + checkResultList: [ + { id: 1, name: '正常' }, + { id: 2, name: '异常' }, + { id: 3, name: '未处理' } + ], + taskStatusList: [ + { id: 1, name: '待排查' }, + { id: 2, name: '已完成' }, + { id: 3, name: '超时未排查' }, + { id: 4, name: '排查中' } + ], + taskTypeList: [ + { id: 1, name: '周期任务' }, + { id: 2, name: '日常任务' } + ] + }); + // 初始化表格数据 + const initRecordTableData = async () => { + let res = await recordApi().getRecordList(state.recordData.params); + if (res.data.code === '200') { + state.recordData.data = res.data.data; + state.recordData.total = res.data.count; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + //获取部门列表 + const getDepartmentData = async () => { + let res = await departmentApi().getDepartmentList(); + if (res.data.code === '200') { + state.departmentList = res.data.data; + recursion(state.departmentList); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + const getCheckUnitData = async () => { + let res = await checkUnitApi().getAllCheckUnitList(); + if (res.data.code === '200') { + state.taskUnitList = res.data.data; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 打开生产装置弹窗 + const onOpenDialogRef = (type: string, value: any) => { + recordDialogRef.value.openRecordDialog(type, value); + }; + // 删除角色 + const onHandleTask = (row: any) => { + ElMessageBox.confirm(`此操作将认领该任务:“${row.taskCode}”,是否继续?`, '提示', { + confirmButtonText: '确认', + cancelButtonText: '取消', + type: 'warning' + }) + .then(async () => { + let res = await recordApi().getTask({ id: row.id }); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + duration: 2000, + message: '认领成功' + }); + await initRecordTableData(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }) + .catch(() => {}); + }; + + const handleSearch = () => { + initRecordTableData(); + }; + // 分页改变 + const onHandleSizeChange = (val: number) => { + state.recordData.params.pageSize = val; + initRecordTableData(); + }; + // 分页改变 + const onHandleCurrentChange = (val: number) => { + state.recordData.params.pageIndex = val; + initRecordTableData(); + }; + + const recursion = (value: any) => { + for (let i of value) { + if (i.children.length !== 0) { + state.departmentRecursionList.push(i); + recursion(i.children); + } else { + state.departmentRecursionList.push(i); + } + } + }; + + const parseNumber = (value: string | number, type: string) => { + if (type === '状态') { + return state.taskStatusList.find((item) => item.id === value)?.name; + } else if (type === '执行部门') { + return state.departmentRecursionList.find((item) => item.depId === value)?.depName; + } else if (type === '检查结果') { + return state.checkResultList.find((item) => item.id === value)?.name; + } else { + if (value === 1) { + return '未认领'; + } else { + return '已认领'; + } + } + }; + + // 页面加载时 + onMounted(() => { + initRecordTableData(); + getCheckUnitData(); + getDepartmentData(); + }); + + return { + View, + Check, + parseNumber, + handleSearch, + onOpenDialogRef, + onHandleSizeChange, + onHandleTask, + onHandleCurrentChange, + recordDialog, + recordDialogRef, + initRecordTableData, + ...toRefs(state) + }; + } +}); +</script> + +<style scoped></style> diff --git a/src/views/doublePrevent/riskCheckManage/checkTaskManage/checkWork/components/workDialog.vue b/src/views/doublePrevent/riskCheckManage/checkTaskManage/checkWork/components/workDialog.vue new file mode 100644 index 0000000..63f6139 --- /dev/null +++ b/src/views/doublePrevent/riskCheckManage/checkTaskManage/checkWork/components/workDialog.vue @@ -0,0 +1,313 @@ +<template> + <div class="system-add-menu-container"> + <el-dialog :title="title" v-model="isShowWorkDialog" append-to-body :close-on-click-modal="false" width="50%"> + <div class="work-form"> + <el-form :model="workForm" :rules="workFormRules" ref="workFormRef" size="default" label-width="150px"> + <el-row :gutter="35"> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" class="mb20"> + <el-form-item label="排查类型" prop="checkWorkType"> + <el-select class="input-add" :disabled="!disabled" v-model="workForm.checkWorkType" placeholder="请输入排查类型" clearable> <el-option v-for="item in checkWorkTypeList" :key="item.id" :label="item.name" :value="item.id"></el-option></el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" class="mb20"> + <el-form-item label="排查名称" prop="checkWorkName"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="workForm.checkWorkName" placeholder="请输入排查名称" clearable></el-input> + </el-form-item> + </el-col> + + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" class="mb20"> + <el-form-item label="排查周期" prop="checkCycle"> + <el-input class="input-add" :disabled="!disabled" type="number" v-model.trim="workForm.checkCycle" placeholder="请输入排查周期" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" class="mb20"> + <el-form-item label="时间单位" prop="checkCycleUnit"> + <el-select class="input-add" :disabled="!disabled" v-model="workForm.checkCycleUnit" placeholder="请输入时间单位" clearable> + <el-option v-for="item in timeType" :key="item.id" :label="item.name" :value="item.id"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" class="mb20"> + <el-form-item label="有效时间" prop="validTime"> + <el-input class="input-add" :disabled="!disabled" type="number" v-model.trim="workForm.validTime" placeholder="请输入有效时间" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" class="mb20"> + <el-form-item label="时间单位" prop="validTimeUnit"> + <el-select class="input-add" :disabled="!disabled" v-model="workForm.validTimeUnit" placeholder="请输入时间单位" clearable> + <el-option v-for="item in timeType" :key="item.id" :label="item.name" :value="item.id"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" class="mb20"> + <el-form-item label="提醒时间" prop="noticeTime"> + <el-input class="input-add" :disabled="!disabled" type="number" v-model.trim="workForm.noticeTime" placeholder="请输入提醒时间" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" class="mb20"> + <el-form-item label="时间单位" prop="noticeTimeUnit"> + <el-select class="input-add" :disabled="!disabled" v-model="workForm.noticeTimeUnit" placeholder="请输入时间单位" clearable> + <el-option v-for="item in timeType" :key="item.id" :label="item.name" :value="item.id"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" class="mb20"> + <el-form-item label="执行部门" prop="execDepId"> + <el-cascader :disabled="!disabled" :options="departmentList" :props="{ emitPath: false, checkStrictly: true, value: 'depId', label: 'depName' }" placeholder="请选择部门" clearable filterable class="input-add" v-model="workForm.execDepId"> </el-cascader> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" class="mb20"> + <el-form-item label="任务单元" prop="taskUnitId"> + <el-select class="input-add" :disabled="!disabled" v-model="workForm.taskUnitId" placeholder="请输入任务单元" clearable filterable> + <el-option v-for="item in taskUnitList" :key="item.id" :label="item.taskUnitName" :value="item.id"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" class="mb20"> + <el-form-item label="首次任务开始时间" prop="firstStartTime"> + <el-date-picker :disabled="!disabled" class="input-add" type="datetime" value-format="YYYY-MM-DD HH:mm:ss" v-model="workForm.firstStartTime" placeholder="请选择首次任务开始时间" clearable></el-date-picker> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" class="mb20" v-show="personTime"> + <el-form-item label="创建人" prop="location"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="workForm.createByUserName" placeholder="请输入区域位置"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" class="mb20" v-show="personTime"> + <el-form-item label="创建时间" prop="location"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="workForm.gmtCreate" placeholder="请输入区域位置"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" class="mb20" v-show="personTime"> + <el-form-item label="最后修改人" prop="location"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="workForm.lastEditUserName" placeholder="请输入区域位置"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" class="mb20" v-show="personTime"> + <el-form-item label="最后修改时间" prop="location"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="workForm.gmtModitify" placeholder="请输入区域位置"></el-input> + </el-form-item> + </el-col> + </el-row> + </el-form> + </div> + + <template #footer> + <span class="dialog-footer" v-show="disabled"> + <el-button @click="isShowWorkDialog = !isShowWorkDialog" size="default">取 消</el-button> + <el-button type="primary" @click="submitWork" v-throttle size="default">确 定</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script lang="ts"> +import { getUserByDepartment } from '/@/assets/methods'; + +interface stateType { + disabled: Boolean; + isShowWorkDialog: Boolean; + personTime: Boolean; + workForm: { + checkWorkType: number | null; + checkWorkName: string | null; + taskUnitId: number | null; + execDepId: number | null; + checkCycle: number | null; + checkCycleUnit: number | null; + validTime: number | null; + validTimeUnit: number | null; + noticeTime: number | null; + noticeTimeUnit: number | null; + firstStartTime: string | null; + }; + title: string; + activeName: string; + checkWorkTypeList: []; + departmentList: []; + taskUnitList: []; + userList: []; + timeType: Array<timeState>; + workFormRules: {}; +} +interface timeState { + id: number; + name: string; +} +import { reactive, toRefs, ref } from 'vue'; +import { workApi } from '/@/api/doublePreventSystem/work'; +import { ElMessage } from 'element-plus'; +export default { + name: 'workDialog', + setup(props: any, context: any) { + const workFormRef = ref(); + const state = reactive<stateType>({ + title: '', + disabled: false, + personTime: false, + activeName: 'inspectionPoint', + checkWorkTypeList: [], + departmentList: [], + taskUnitList: [], + userList: [], + timeType: [ + { id: 1, name: '分' }, + { id: 2, name: '小时' }, + { id: 3, name: '日' }, + { id: 4, name: '月' }, + { id: 5, name: '年' } + ], + isShowWorkDialog: false, + workForm: { + checkWorkType: null, + checkWorkName: null, + taskUnitId: null, + execDepId: null, + checkCycle: null, + checkCycleUnit: null, + validTime: null, + validTimeUnit: null, + noticeTime: null, + noticeTimeUnit: null, + firstStartTime: null + }, + workFormRules: { + checkWorkType: [{ required: true, message: '请填写排查作业类型', trigger: 'change' }], + checkWorkName: [{ required: true, message: '请选择排查作业名称', trigger: 'blur' }], + taskUnitId: [{ required: true, message: '请选择任务单元', trigger: 'change' }], + execUserId: [{ required: true, message: '请选择执行人', trigger: 'change' }], + checkCycle: [{ required: true, message: '请填写排查周期', trigger: 'blur' }], + checkCycleUnit: [{ required: true, message: '请选择时间单位', trigger: 'change' }], + validTime: [{ required: true, message: '请填写有效时间', trigger: 'blur' }], + validTimeUnit: [{ required: true, message: '请选择时间单位', trigger: 'change' }], + noticeTime: [{ required: true, message: '请填写提醒时间', trigger: 'blur' }], + noticeTimeUnit: [{ required: true, message: '请选择时间单位', trigger: 'change' }], + firstStartTime: [{ required: true, message: '请填写首次排查任务开始时间', trigger: 'blur' }], + depId: [{ required: true, message: '请选择部门', trigger: 'change' }] + } + }); + + //打开模态框 + const openWorkDialog = async (type: string, value: object, department: [], checkWorkTypeList: [], taskUnitList: []) => { + state.isShowWorkDialog = true; + state.departmentList = department; + state.taskUnitList = JSON.parse(JSON.stringify(taskUnitList)); + state.checkWorkTypeList = JSON.parse(JSON.stringify(checkWorkTypeList)); + setTimeout(() => { + workFormRef.value.clearValidate(); + }); + if (type === '新增') { + state.disabled = true; + state.personTime = false; + state.title = '新增排查任务'; + state.workForm = { + checkWorkType: null, + checkWorkName: null, + taskUnitId: null, + execDepId: null, + checkCycle: null, + checkCycleUnit: null, + validTime: null, + validTimeUnit: null, + noticeTime: null, + noticeTimeUnit: null, + firstStartTime: null + }; + } else if (type === '查看') { + state.disabled = false; + state.personTime = true; + state.title = '查看排查任务'; + state.workForm = JSON.parse(JSON.stringify(value)); + } else { + state.disabled = true; + state.personTime = false; + state.title = '修改排查任务'; + state.workForm = JSON.parse(JSON.stringify(value)); + } + }; + + //新增修改提交 + const submitWork = async () => { + workFormRef.value.validate(async (valid: Boolean) => { + if (valid) { + if (state.title === '新增排查任务') { + let res = await workApi().addWork(state.workForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '排查任务新增成功', + duration: 2000 + }); + state.isShowWorkDialog = false; + context.emit('refreshWork'); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } else { + let res = await workApi().modWork(state.workForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '排查任务修改成功', + duration: 2000 + }); + state.isShowWorkDialog = false; + context.emit('refreshWork'); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } + } else { + ElMessage({ + type: 'warning', + message: '请完善基本信息' + }); + } + }); + }; + + // const achieveUserList = async () => { + // state.workForm.execUserId = null; + // const user: unknown = await getUserByDepartment(state.workForm.depId); + // state.userList = user as []; + // }; + + return { + ...toRefs(state), + workFormRef, + submitWork, + openWorkDialog + }; + } +}; +</script> + +<style scoped> +::v-deep.el-divider--horizontal { + margin-top: 0px !important; +} + +::v-deep.el-dialog__body { + padding-top: 10px !important; +} +.filter-container { + padding: 10px 0px; +} +:deep(.el-textarea.is-disabled .el-textarea__inner) { + background-color: var(--el-card-bg-color); + color: var(--el-input-text-color, var(--el-text-color-regular)); +} +:deep(.el-input.is-disabled .el-input__inner) { + color: var(--el-input-text-color, var(--el-text-color-regular)); +} +:deep(.el-input.is-disabled .el-input__wrapper) { + background-color: var(--el-card-bg-color); +} +</style> diff --git a/src/views/doublePrevent/riskCheckManage/checkTaskManage/checkWork/index.vue b/src/views/doublePrevent/riskCheckManage/checkTaskManage/checkWork/index.vue new file mode 100644 index 0000000..7e0ac2a --- /dev/null +++ b/src/views/doublePrevent/riskCheckManage/checkTaskManage/checkWork/index.vue @@ -0,0 +1,361 @@ +<template> + <div class="system-role-container"> + <el-card shadow="hover"> + <div class="system-user-search mb15"> + <div class="basic-line"> + <span>排查作业类型:</span> + <el-select class="input-box" v-model="workData.params.checkWorkType" placeholder="排查作业类型" filterable clearable> + <el-option v-for="item in checkWorkTypeList" :key="item.id" :label="item.name" :value="item.id"></el-option> + </el-select> + </div> + <div class="basic-line"> + <span>排查作业状态:</span> + <el-select class="input-box" v-model="workData.params.checkWorkStatus" placeholder="排查作业状态" filterable clearable> + <el-option v-for="item in checkWorkStatusList" :key="item.id" :label="item.name" :value="item.id"></el-option> + </el-select> + </div> + <div class="basic-line"> + <span>排查作业名称:</span> + <el-input class="input-box" v-model="workData.params.checkWorkName" placeholder="排查作业名称" clearable> </el-input> + </div> + + <el-button size="default" type="primary" class="ml10" v-throttle @click="handleSearch"> + <el-icon> + <ele-Search /> + </el-icon> + 查询 + </el-button> + <el-button size="default" type="success" class="ml10" @click="onOpenDialogRef('新增', '')"> + <el-icon> + <ele-FolderAdd /> + </el-icon> + 新增排查任务 + </el-button> + </div> + <el-table :data="workData.data" style="width: 100%"> + <el-table-column type="index" label="序号" width="60" /> + <el-table-column prop="checkWorkName" label="排查名称" show-overflow-tooltip></el-table-column> + <el-table-column prop="checkWorkType" label="排查类型" show-overflow-tooltip> + <template #default="scope"> + {{ parseNumber(scope.row.checkWorkType, '排查类型') }} + </template> + </el-table-column> + <el-table-column prop="taskUnitName" label="任务单元" show-overflow-tooltip></el-table-column> + <el-table-column prop="execDepId" label="执行部门" show-overflow-tooltip> + <template #default="scope"> + {{ parseNumber(scope.row.execDepId, '执行部门') }} + </template> + </el-table-column> + <el-table-column prop="checkCycle" label="排查周期" show-overflow-tooltip> + <template #default="scope"> + <span> + {{ scope.row.checkCycle }} + </span> + <span> + {{ parseNumber(scope.row.checkWorkType, '排查周期') }} + </span> + </template> + </el-table-column> + <el-table-column prop="validTime" label="有效时间" show-overflow-tooltip> + <template #default="scope"> + <span> + {{ scope.row.validTime }} + </span> + <span> + {{ parseNumber(scope.row.validTimeUnit, '排查周期') }} + </span> + </template> + </el-table-column> + <el-table-column prop="validTime" label="提醒时间" show-overflow-tooltip> + <template #default="scope"> + <span> + {{ scope.row.noticeTime }} + </span> + <span> + {{ parseNumber(scope.row.noticeTimeUnit, '排查周期') }} + </span> + </template> + </el-table-column> + <el-table-column prop="createByUserName" label="创建人" show-overflow-tooltip></el-table-column> + <el-table-column prop="gmtCreate" label="创建时间" show-overflow-tooltip></el-table-column> + <el-table-column prop="lastEditUserName" label="最后修改人" show-overflow-tooltip></el-table-column> + <el-table-column prop="gmtModitify" label="最后修改时间" show-overflow-tooltip></el-table-column> + <el-table-column label="操作" width="200" align="center"> + <template #default="scope"> + <el-button size="small" text type="primary" :icon="View" @click="onOpenDialogRef('查看', scope.row)">查看</el-button> + <el-button size="small" text type="primary" :icon="Edit" @click="onOpenDialogRef('修改', scope.row)">修改</el-button> + <el-button size="small" text type="danger" :icon="Delete" @click="onDelWork(scope.row)">删除</el-button> + </template> + </el-table-column> + </el-table> + <br /> + <el-pagination @size-change="onHandleSizeChange" @current-change="onHandleCurrentChange" :pager-count="5" :page-sizes="[10, 20, 30]" v-model:current-page="workData.params.pageIndex" background v-model:page-size="workData.params.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="workData.total" class="page-position"> </el-pagination> + <br /> + <br /> + </el-card> + <workDialog ref="workDialogRef" @refreshWork="initWorkTableData" /> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, onMounted, ref, defineComponent } from 'vue'; +import { ElMessageBox, ElMessage } from 'element-plus'; +import workDialog from './components/workDialog.vue'; +import { workApi } from '/@/api/doublePreventSystem/work/index.ts'; +import { departmentApi } from '/@/api/systemManage/department'; +import { Edit, Delete, View } from '@element-plus/icons-vue'; +import { checkUnitApi } from '/@/api/doublePreventSystem/checkUnit'; + +// 定义接口来定义对象的类型 +interface TableData { + roleName: string; + roleSign: string; + describe: string; + sort: number; + status: boolean; + createTime: string; +} +interface TableDataState { + workData: { + data: Array<TableData>; + total: number; + loading: boolean; + params: { + pageIndex: number; + pageSize: number; + checkWorkType: number | null | ''; + checkWorkStatus: number | null | ''; + checkWorkName: string | null; + }; + }; + timeType: Array<levelListState>; + taskUnitList: Array<taskUnit>; + departmentList: Array<DepartmentState>; + departmentRecursionList: Array<DepartmentState>; + checkWorkTypeList: Array<levelListState>; + checkWorkStatusList: Array<levelListState>; +} +interface levelListState { + id: number; + name: string; +} +interface DepartmentState { + depId: number; + depName: string; + children: Array<DepartmentState>; +} +interface taskUnit { + id: number; + taskUnitName: string; +} + +export default defineComponent({ + name: 'work', + components: { workDialog, Edit, Delete, View }, + setup() { + const workDialogRef = ref(); + const state = reactive<TableDataState>({ + workData: { + data: [], + total: 0, + loading: false, + params: { + pageIndex: 1, + pageSize: 10, + checkWorkType: null, + checkWorkStatus: null, + checkWorkName: null + } + }, + taskUnitList: [], + departmentList: [], + departmentRecursionList: [], + checkWorkTypeList: [ + { id: 1, name: '日常作业' }, + { id: 2, name: '周期作业' } + ], + checkWorkStatusList: [ + { id: 1, name: '开启' }, + { id: 2, name: '关闭' } + ], + timeType: [ + { id: 1, name: '分' }, + { id: 2, name: '小时' }, + { id: 3, name: '日' }, + { id: 4, name: '月' }, + { id: 5, name: '年' } + ] + }); + // 初始化表格数据 + const initWorkTableData = async () => { + // state.workData.params.checkWorkType = state.workData.params.checkWorkType === '' ? null : state.workData.params.checkWorkType; + // state.workData.params.checkWorkStatus = state.workData.params.checkWorkStatus === '' ? null : state.workData.params.checkWorkStatus; + let res = await workApi().getWorkList(state.workData.params); + if (res.data.code === '200') { + state.workData.data = res.data.data; + state.workData.total = res.data.count; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + //获取部门列表 + const getDepartmentData = async () => { + let res = await departmentApi().getDepartmentList(); + if (res.data.code === '200') { + state.departmentList = res.data.data; + recursion(state.departmentList); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + const getCheckUnitData = async () => { + let res = await checkUnitApi().getAllCheckUnitList(); + if (res.data.code === '200') { + state.taskUnitList = res.data.data; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 打开生产装置弹窗 + const onOpenDialogRef = (type: string, value: any) => { + workDialogRef.value.openWorkDialog(type, value, state.departmentList, state.checkWorkTypeList, state.taskUnitList); + }; + // 删除角色 + const onDelWork = (row: any) => { + ElMessageBox.confirm(`此操作将永久删除该条生产装置:“${row.produceDeviceName}”,是否继续?`, '提示', { + confirmButtonText: '确认', + cancelButtonText: '取消', + type: 'warning' + }) + .then(async () => { + let res = await workApi().deleteWork({ id: row.id }); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + duration: 2000, + message: '删除成功' + }); + await initWorkTableData(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }) + .catch(() => {}); + }; + + const recursion = (value: any) => { + for (let i of value) { + if (i.children.length !== 0) { + state.departmentRecursionList.push(i); + recursion(i.children); + } else { + state.departmentRecursionList.push(i); + } + } + }; + + const parseNumber = (value: number, type: string) => { + if (type === '排查类型') { + return state.checkWorkTypeList.find((item) => item.id === value)?.name; + } else if (type === '排查周期') { + return state.timeType.find((item) => item.id == value)?.name; + } else if (type === '执行部门') { + return state.departmentRecursionList.find((item) => item.depId === value)?.depName; + // return state.departmentList.find((item: any) => { + // if (item.children.length !== 0) { + // if (item.depId === value) { + // return item; + // } else { + // return recursion(item.children, value); + // } + // } else { + // if (item.depId === value) { + // return item; + // } + // } + // })?.depName; + } + }; + + // const recursion = (children: any, value: number | string) => { + // return children.find((item: any) => { + // if (item.children.length !== 0) { + // if (item.depId === value) { + // return item; + // } else { + // return recursion(item.children, value); + // } + // } else { + // if (item.depId === value) { + // return item; + // } + // } + // }); + // }; + + const handleSearch = () => { + initWorkTableData(); + }; + // 分页改变 + const onHandleSizeChange = (val: number) => { + state.workData.params.pageSize = val; + initWorkTableData(); + }; + // 分页改变 + const onHandleCurrentChange = (val: number) => { + state.workData.params.pageIndex = val; + initWorkTableData(); + }; + // 页面加载时 + onMounted(() => { + initWorkTableData(); + getCheckUnitData(); + getDepartmentData(); + }); + + return { + Edit, + Delete, + View, + handleSearch, + onOpenDialogRef, + onHandleSizeChange, + onDelWork, + parseNumber, + onHandleCurrentChange, + workDialog, + workDialogRef, + initWorkTableData, + ...toRefs(state) + }; + } +}); +</script> + +<style scoped> +:deep(.el-textarea.is-disabled .el-textarea__inner) { + background-color: var(--el-card-bg-color); + color: var(--el-input-text-color, var(--el-text-color-regular)); +} +:deep(.el-input.is-disabled .el-input__inner) { + color: var(--el-input-text-color, var(--el-text-color-regular)); +} +:deep(.el-input.is-disabled .el-input__wrapper) { + background-color: var(--el-card-bg-color); +} +</style> diff --git a/src/views/doublePrevent/riskCheckManage/hiddenManagement/hiddenCheck/components/checkDialog.vue b/src/views/doublePrevent/riskCheckManage/hiddenManagement/hiddenCheck/components/checkDialog.vue new file mode 100644 index 0000000..e225a9d --- /dev/null +++ b/src/views/doublePrevent/riskCheckManage/hiddenManagement/hiddenCheck/components/checkDialog.vue @@ -0,0 +1,201 @@ +<template> + <div class="system-add-menu-container"> + <el-dialog :title="title" v-model="isShowCheckDialog" width="600px" :close-on-click-modal="false"> + <el-form :model="checkForm" :rules="checkFormRules" ref="checkFormRef" size="default" label-width="120px"> + <el-row :gutter="35"> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="验收意见" prop="checkInfo"> + <el-input class="input-add" type="textarea" :rows="2" v-model.trim="checkForm.checkAcceptDesc" placeholder="请输入验收意见" clearable></el-input> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="isShowCheckDialog = !isShowCheckDialog" size="default">取 消</el-button> + <el-button type="primary" @click="submitCheck" v-throttle size="default">确 定</el-button> + </span> + </template> + </el-dialog> + <el-dialog :title="title" v-model="isShowCheckInfoDialog" width="600px" :close-on-click-modal="false"> + <el-form :model="checkInfoForm" ref="checkFormRef" size="default" label-width="120px"> + <el-row :gutter="35"> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="验收意见" prop="rectifyDesc"> + <el-input class="input-add" :disabled="true" type="textarea" :rows="2" v-model.trim="checkInfoForm.rectifyDesc" readonly></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="整改类型" prop="rectifyType"> + <el-select class="input-add" :disabled="true" v-model="checkInfoForm.rectifyType" readonly> + <el-option v-for="item in rectifyTypeList" :key="item.id" :label="item.name" :value="item.id"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="整改部门" prop="rectifyDepId"> + <el-cascader :disabled="true" :options="departmentList" :props="{ emitPath: false, checkStrictly: true, value: 'depId', label: 'depName' }" placeholder="请选择部门" clearable filterable class="input-add" v-model="checkInfoForm.rectifyDepId" readonly> </el-cascader> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="整改责任人" prop="liablePersonId"> + <el-select class="input-add" :disabled="true" v-model="checkInfoForm.liablePersonId" clearable filterable readonly> + <el-option v-for="item in userList" :key="item.uid" :label="item.username" :value="item.uid"></el-option> + </el-select> + </el-form-item> + </el-col> + + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="整改资金" prop="dangerResult"> + <el-input class="input-add" :disabled="true" type="number" v-model="checkInfoForm.cost" readonly> </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="验收人" prop="checkAcceptPerson"> + <el-input class="input-add" :disabled="true" v-model="checkInfoForm.checkAcceptPerson" readonly /> + </el-form-item> + </el-col> + </el-row> + </el-form> + </el-dialog> + </div> +</template> + +<script lang="ts"> +import { getUserByDepartment } from '/@/assets/methods'; + +interface stateType { + isShowCheckDialog: Boolean; + isShowCheckInfoDialog: Boolean; + checkForm: { + id: number | null; + dangerManagerId: number | null; + checkAcceptDesc: string | null; + }; + departmentList: []; + userList: []; + rectifyTypeList: Array<rectifyType>; + checkInfoForm: { + rectifyDepId: number | null; + liablePersonId: number | null; + }; + title: string; + checkTypeList: Array<checkTypeState>; + checkFormRules: {}; +} +interface checkTypeState { + regionType: string; + id: number; +} + +interface rectifyType { + id: number; + name: string; +} + +import { reactive, toRefs, ref } from 'vue'; +import { ElMessage } from 'element-plus'; +import { hiddenCheckApi } from '/@/api/doublePreventSystem/check'; +export default { + name: 'hiddenCheckDialog', + setup(props: any, context: any) { + const checkFormRef = ref(); + const state = reactive<stateType>({ + title: '', + checkTypeList: [], + rectifyTypeList: [ + { id: 1, name: '即查即改' }, + { id: 2, name: '限期整改' } + ], + departmentList: [], + userList: [], + isShowCheckDialog: false, + isShowCheckInfoDialog: false, + checkForm: { + id: null, + dangerManagerId: null, + checkAcceptDesc: null + }, + checkInfoForm: { + rectifyDepId: null, + liablePersonId: null + }, + checkFormRules: { + checkAcceptDesc: [{ required: true, message: '请填写整改说明', trigger: 'blur' }] + } + }); + + //打开模态框 + const openCheckDialog = async (type: string, value: object, departmentList: []) => { + state.departmentList = departmentList; + if (type === '验收') { + state.title = '验收'; + state.isShowCheckDialog = true; + const checkForm = JSON.parse(JSON.stringify(value)); + state.checkForm.id = checkForm.id; + state.checkForm.dangerManagerId = checkForm.dangerManagerId; + } else { + state.title = '查看'; + state.isShowCheckInfoDialog = true; + state.checkInfoForm.rectifyDepId = JSON.parse(JSON.stringify(value)).rectifyDepId; + await achieveUserList(); + state.checkInfoForm = JSON.parse(JSON.stringify(value)); + } + }; + + //提交整改 + const submitCheck = async () => { + checkFormRef.value.validate(async (valid: Boolean) => { + if (valid) { + let res = await hiddenCheckApi().submitHiddenCheck(state.checkForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '整改提交成功', + duration: 2000 + }); + state.isShowCheckDialog = false; + context.emit('refreshCheck'); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } else { + ElMessage({ + type: 'warning', + message: '请完善基本信息' + }); + } + }); + }; + + const achieveUserList = async () => { + state.checkInfoForm.liablePersonId = null; + const user: unknown = await getUserByDepartment(state.checkInfoForm.rectifyDepId); + state.userList = user as []; + }; + + return { + ...toRefs(state), + checkFormRef, + submitCheck, + openCheckDialog + }; + } +}; +</script> + +<style scoped> +:deep(.el-textarea.is-disabled .el-textarea__inner) { + background-color: var(--el-card-bg-color); + color: var(--el-input-text-color, var(--el-text-color-regular)); +} +:deep(.el-input.is-disabled .el-input__inner) { + color: var(--el-input-text-color, var(--el-text-color-regular)); +} +:deep(.el-input.is-disabled .el-input__wrapper) { + background-color: var(--el-card-bg-color); +} +</style> diff --git a/src/views/doublePrevent/riskCheckManage/hiddenManagement/hiddenCheck/index.vue b/src/views/doublePrevent/riskCheckManage/hiddenManagement/hiddenCheck/index.vue new file mode 100644 index 0000000..3e4bea4 --- /dev/null +++ b/src/views/doublePrevent/riskCheckManage/hiddenManagement/hiddenCheck/index.vue @@ -0,0 +1,222 @@ +<template> + <div class="system-role-container"> + <el-card shadow="hover"> + <div class="system-user-search mb15"> + <div class="basic-line"> + <span>整改类型:</span> + <el-select class="input-box" v-model="checkData.params.rectifyType" placeholder="整改类型" filterable> + <el-option v-for="item in rectifyTypeList" :key="item.id" :label="item.name" :value="item.id"></el-option> + </el-select> + </div> + <div class="basic-line"> + <span>整改部门:</span> + <el-cascader :options="departmentList" :props="{ emitPath: false, checkStrictly: true, value: 'depId', label: 'depName' }" placeholder="请选择部门" clearable filterable class="input-box" v-model="checkData.params.rectifyDepId"> </el-cascader> + </div> + <div class="basic-line"> + <span>整改状态:</span> + <el-select class="input-box" v-model="checkData.params.dangerStatus" placeholder="整改状态" clearable filterable> + <el-option v-for="item in dangerStatusList" :key="item.id" :label="item.name" :value="item.id"></el-option> + </el-select> + </div> + <el-button size="default" type="primary" class="ml10" v-throttle @click="handleSearch"> + <el-icon> + <ele-Search /> + </el-icon> + 查询 + </el-button> + </div> + <el-table :data="checkData.data" style="width: 100%" fit highlight-current-row> + <el-table-column type="index" label="序号" width="60" /> + <el-table-column prop="reportTime" label="上报时间" show-overflow-tooltip width="170px"></el-table-column> + <el-table-column prop="dangerCode" label="隐患名称" show-overflow-tooltip></el-table-column> + <el-table-column prop="rectifyDesc" label="整改内容说明" show-overflow-tooltip min-width="150px"></el-table-column> + <el-table-column prop="applyTime" label="整改时间" show-overflow-tooltip min-width="150px"></el-table-column> + <el-table-column prop="rectifyType" label=" 整改类型" show-overflow-tooltip min-width="150px"> + <template #default="scope"> + {{ parseNumber(scope.row.rectifyType, '整改类型') }} + </template> + </el-table-column> + <el-table-column prop="liablePerson" label="整改责任人" show-overflow-tooltip min-width="150px"></el-table-column> + <el-table-column prop="cost" label="整改资金" show-overflow-tooltip min-width="150px"></el-table-column> + <el-table-column prop="dangerStatus" label="验收状态" show-overflow-tooltip min-width="150px" align="center"> + <template #default="scope"> + <el-tag :type="scope.row.dangerStatus === 0 ? 'info' : scope.row.dangerStatus === 1 ? 'primary' : scope.row.dangerStatus === 2 ? 'warning' : scope.row.dangerStatus === 4 ? 'danger' : 'success'"> + {{ parseNumber(scope.row.dangerStatus, '隐患整改状态') }} + </el-tag> + </template> + </el-table-column> + <el-table-column prop="checkAcceptPerson" label="验收人" show-overflow-tooltip min-width="150px"></el-table-column> + <el-table-column label="操作" width="250" fixed="right" align="center"> + <template #default="scope"> + <el-button size="small" text type="primary" :icon="View" @click="onOpenDialogRef('查看', scope.row)">查看</el-button> + <el-button size="small" text type="primary" :icon="Check" v-show="scope.row.dangerStatus === 1" @click="onOpenDialogRef('验收', scope.row)">验收</el-button> + </template> + </el-table-column> + </el-table> + <br /> + <el-pagination @size-change="onHandleSizeChange" @current-change="onHandleCurrentChange" :pager-count="5" :page-sizes="[10, 20, 30]" v-model:current-page="checkData.params.pageIndex" background v-model:page-size="checkData.params.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="checkData.total" class="page-position"> </el-pagination> + <br /> + <br /> + </el-card> + <checkDialog ref="checkDialogRef" @refreshCheck="initCheckTableData" /> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, onMounted, ref, defineComponent } from 'vue'; +import { ElMessageBox, ElMessage } from 'element-plus'; +import checkDialog from './components/checkDialog.vue'; +import { Check, Delete, View } from '@element-plus/icons-vue'; +import { departmentApi } from '/@/api/systemManage/department'; +import { hiddenCheckApi } from '/@/api/doublePreventSystem/check'; + +// 定义接口来定义对象的类型 +interface TableData { + quota: string; + quotaUnit: string; + quotaType: string; + createUserName: string; + gmtCreate: string; + lastEditUserName: string; + gmtModitify: string; +} +interface TableDataState { + checkData: { + data: Array<TableData>; + total: number; + loading: boolean; + params: { + pageIndex: number; + pageSize: number; + rectifyType: number | null; + rectifyDepId: number | null; + dangerStatus: number | null; + }; + }; + rectifyTypeList: Array<enumType>; + dangerStatusList: Array<enumType>; + departmentList: []; +} +interface enumType { + id: number; + name: string; +} + +export default defineComponent({ + name: 'check', + components: { checkDialog, Check, Delete, View }, + setup() { + const checkDialogRef = ref(); + const state = reactive<TableDataState>({ + checkData: { + data: [], + total: 0, + loading: false, + params: { + pageIndex: 1, + pageSize: 10, + rectifyType: null, + rectifyDepId: null, + dangerStatus: 1 + } + }, + departmentList: [], + rectifyTypeList: [ + { id: 1, name: '即查即改' }, + { id: 2, name: '限期整改' } + ], + dangerStatusList: [ + { id: 1, name: '待验收' }, + { id: 9, name: '已验收' } + ] + }); + + // 初始化表格数据 + const initCheckTableData = async () => { + let res = await hiddenCheckApi().getHiddenCheckList(state.checkData.params); + if (res.data.code === '200') { + state.checkData.data = res.data.data; + state.checkData.total = res.data.count; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + //获取部门列表 + const getDepartmentData = async () => { + let res = await departmentApi().getDepartmentList(); + if (res.data.code === '200') { + state.departmentList = res.data.data; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 打开弹窗 + const onOpenDialogRef = (type: string, value: any) => { + checkDialogRef.value.openCheckDialog(type, value, state.departmentList); + }; + + const parseNumber = (value: string | number, type: string) => { + if (type === '整改类型') { + return state.rectifyTypeList.find((item) => item.id === value)?.name; + } else if (type === '隐患整改状态') { + return state.dangerStatusList.find((item) => item.id === value)?.name; + } + }; + + const handleSearch = () => { + initCheckTableData(); + }; + // 分页改变 + const onHandleSizeChange = (val: number) => { + state.checkData.params.pageSize = val; + initCheckTableData(); + }; + // 分页改变 + const onHandleCurrentChange = (val: number) => { + state.checkData.params.pageIndex = val; + initCheckTableData(); + }; + // 页面加载时 + onMounted(() => { + initCheckTableData(); + getDepartmentData(); + }); + + return { + Check, + Delete, + View, + parseNumber, + handleSearch, + onOpenDialogRef, + onHandleSizeChange, + onHandleCurrentChange, + checkDialog, + checkDialogRef, + initCheckTableData, + ...toRefs(state) + }; + } +}); +</script> + +<style scoped> +:deep(.el-textarea.is-disabled .el-textarea__inner) { + background-color: var(--el-card-bg-color); + color: var(--el-input-text-color, var(--el-text-color-regular)); +} +:deep(.el-input.is-disabled .el-input__inner) { + color: var(--el-input-text-color, var(--el-text-color-regular)); +} +:deep(.el-input.is-disabled .el-input__wrapper) { + background-color: var(--el-card-bg-color); +} +</style> diff --git a/src/views/doublePrevent/riskCheckManage/hiddenManagement/hiddenRectify/components/rectifyDialog.vue b/src/views/doublePrevent/riskCheckManage/hiddenManagement/hiddenRectify/components/rectifyDialog.vue new file mode 100644 index 0000000..50802ef --- /dev/null +++ b/src/views/doublePrevent/riskCheckManage/hiddenManagement/hiddenRectify/components/rectifyDialog.vue @@ -0,0 +1,303 @@ +<template> + <div class="system-add-menu-container"> + <el-dialog :title="title" v-model="isShowRectifyDialog" width="600px" :close-on-click-modal="false"> + <el-form :model="rectifyForm" :rules="rectifyFormRules" ref="rectifyFormRef" size="default" label-width="120px"> + <el-row :gutter="35"> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="整改说明" prop="rectifyInfo"> + <el-input class="input-add" type="textarea" :rows="2" v-model.trim="rectifyForm.rectifyInfo" placeholder="请输入整改说明" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="整改时间" prop="applyTime"> + <el-date-picker type="datetime" :disabled-date="disabledDate" value-format="YYYY-MM-DD HH:mm:ss" class="input-add" v-model="rectifyForm.applyTime" placeholder="请选择整改时间" clearable> </el-date-picker> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="isShowRectifyDialog = !isShowRectifyDialog" size="default">取 消</el-button> + <el-button type="primary" @click="submitRectify" v-throttle size="default">确 定</el-button> + </span> + </template> + </el-dialog> + <el-dialog :title="title" v-model="isShowDelayDialog" width="600px" :close-on-click-modal="false"> + <el-form :model="delayForm" :rules="delayFormRules" ref="rectifyFormRef" size="default" label-width="120px"> + <el-row :gutter="35"> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="延期说明" prop="timeOutDesc"> + <el-input class="input-add" type="textarea" :rows="2" v-model.trim="delayForm.timeOutDesc" placeholder="请输入延期说明" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="整改期限" prop="rectifyTime"> + <el-date-picker type="datetime" value-format="YYYY-MM-DD HH:mm:ss" class="input-add" v-model="delayForm.rectifyTime" placeholder="请选择整改期限" clearable> </el-date-picker> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer" v-show="disabled"> + <el-button @click="isShowDelayDialog = !isShowDelayDialog" size="default">取 消</el-button> + <el-button type="primary" @click="submitDelay" v-throttle size="default">确 定</el-button> + </span> + </template> + </el-dialog> + <el-dialog :title="title" v-model="isShowCheckInfoDialog" width="600px" :close-on-click-modal="false"> + <el-form :model="checkInfoForm" ref="checkFormRef" size="default" label-width="120px"> + <el-row :gutter="35"> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="整改内容说明" prop="rectifyDesc"> + <el-input class="input-add" :disabled="!disabled" type="textarea" :rows="2" v-model.trim="checkInfoForm.rectifyDesc" readonly></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="整改类型" prop="rectifyType"> + <el-select class="input-add" :disabled="!disabled" v-model="checkInfoForm.rectifyType" readonly> + <el-option v-for="item in rectifyTypeList" :key="item.id" :label="item.name" :value="item.id"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="整改部门" prop="rectifyDepId"> + <el-cascader @change="achieveUserList" :disabled="!disabled" :options="departmentList" :props="{ emitPath: false, checkStrictly: true, value: 'depId', label: 'depName' }" placeholder="请选择部门" clearable filterable class="input-add" v-model="checkInfoForm.rectifyDepId" readonly> </el-cascader> + </el-form-item> + </el-col> + + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="整改责任人" prop="liablePersonId"> + <el-select class="input-add" :disabled="!disabled" v-model="checkInfoForm.liablePersonId" clearable filterable readonly> + <el-option v-for="item in userList" :key="item.uid" :label="item.username" :value="item.uid"></el-option> + </el-select> + </el-form-item> + </el-col> + + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="整改资金" prop="dangerResult"> + <el-input class="input-add" :disabled="!disabled" type="number" v-model="checkInfoForm.cost" readonly> </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20" v-show="personTime"> + <el-form-item label="创建人" prop="location"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="checkInfoForm.createByUserName" placeholder="请输入区域位置"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20" v-show="personTime"> + <el-form-item label="创建时间" prop="location"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="checkInfoForm.gmtCreate" placeholder="请输入区域位置"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20" v-show="personTime"> + <el-form-item label="最后修改人" prop="location"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="checkInfoForm.lastEditUserName" placeholder="请输入区域位置"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20" v-show="personTime"> + <el-form-item label="最后修改时间" prop="location"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="checkInfoForm.gmtModitify" placeholder="请输入区域位置"></el-input> + </el-form-item> + </el-col> + </el-row> + </el-form> + </el-dialog> + </div> +</template> + +<script lang="ts"> +import { getUserByDepartment } from '/@/assets/methods'; + +interface stateType { + disabled: Boolean; + personTime: Boolean; + isShowRectifyDialog: Boolean; + isShowDelayDialog: Boolean; + isShowCheckInfoDialog: Boolean; + rectifyForm: { + id: number | null; + dangerManagerId: number | null; + rectifyInfo: string | null; + applyTime: string | null; + }; + delayForm: { + id: number | null; + dangerManagerId: number | null; + rectifyTime: string | null; + timeOutDesc: string | null; + }; + disabledDate: any; + rangeTime: any; + title: string; + departmentList: []; + userList: []; + rectifyTypeList: Array<rectifyTypeState>; + rectifyFormRules: {}; + delayFormRules: {}; + checkInfoForm: { + rectifyDepId: number | null; + liablePersonId: number | null; + }; +} +interface rectifyTypeState { + regionType: string; + id: number; +} + +import { reactive, toRefs, ref } from 'vue'; +import { ElMessage } from 'element-plus'; +import { hiddenRectifyApi } from '/@/api/doublePreventSystem/rectify'; +export default { + name: 'rectifyDialog', + setup(props: any, context: any) { + const rectifyFormRef = ref(); + const state = reactive<stateType>({ + title: '', + disabled: false, + personTime: false, + rectifyTypeList: [], + departmentList: [], + userList: [], + isShowCheckInfoDialog: false, + checkInfoForm: { + rectifyDepId: null, + liablePersonId: null + }, + isShowDelayDialog: false, + isShowRectifyDialog: false, + rectifyForm: { + id: null, + dangerManagerId: null, + rectifyInfo: null, + applyTime: null + }, + disabledDate: (time: any) => { + const r = new Date().getTime(); + return time.getTime() > new Date().getTime(); + }, + rangeTime: () => { + return '15:15:14'; + }, + delayForm: { + id: null, + dangerManagerId: null, + rectifyTime: null, + timeOutDesc: null + }, + rectifyFormRules: { + rectifyInfo: [{ required: true, message: '请填写整改说明', trigger: 'blur' }], + applyTime: [{ required: true, message: '请选择整改时间', trigger: 'change' }] + }, + delayFormRules: { + timeOutDesc: [{ required: true, message: '请填写延期说明', trigger: 'blur' }], + rectifyTime: [{ required: true, message: '请选择整改期限', trigger: 'change' }] + } + }); + + //打开模态框 + const openRectifyDialog = async (type: string, value: object, departmentList: []) => { + state.departmentList = departmentList; + if (type === '延期') { + state.title = '延期'; + state.disabled = true; + state.personTime = false; + state.isShowDelayDialog = true; + const delayForm = JSON.parse(JSON.stringify(value)); + state.delayForm.id = delayForm.id; + state.delayForm.dangerManagerId = delayForm.dangerManagerId; + state.delayForm.timeOutDesc = null; + state.delayForm.rectifyTime = null; + } else if (type === '查看') { + state.title = '查看'; + state.personTime = true; + state.isShowCheckInfoDialog = true; + state.checkInfoForm.rectifyDepId = JSON.parse(JSON.stringify(value)).rectifyDepId; + await achieveUserList(); + state.checkInfoForm = JSON.parse(JSON.stringify(value)); + } else { + state.disabled = true; + state.personTime = false; + state.title = '整改'; + state.isShowRectifyDialog = true; + const rectifyForm = JSON.parse(JSON.stringify(value)); + state.rectifyForm.id = rectifyForm.id; + state.rectifyForm.dangerManagerId = rectifyForm.dangerManagerId; + state.rectifyForm.rectifyInfo = null; + state.rectifyForm.applyTime = null; + } + }; + + //提交整改 + const submitRectify = async () => { + rectifyFormRef.value.validate(async (valid: Boolean) => { + if (valid) { + let res = await hiddenRectifyApi().submitHiddenRectify(state.rectifyForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '整改提交成功', + duration: 2000 + }); + state.isShowRectifyDialog = false; + context.emit('refreshRectify'); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } else { + ElMessage({ + type: 'warning', + message: '请完善基本信息' + }); + } + }); + }; + + //提交延期 + const submitDelay = async () => { + rectifyFormRef.value.validate(async (valid: Boolean) => { + if (valid) { + let res = await hiddenRectifyApi().delayHiddenRectifyTime(state.delayForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '隐患延期成功', + duration: 2000 + }); + state.isShowDelayDialog = false; + context.emit('refreshRectify'); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } else { + ElMessage({ + type: 'warning', + message: '请完善基本信息' + }); + } + }); + }; + + const achieveUserList = async () => { + state.checkInfoForm.liablePersonId = null; + const user: unknown = await getUserByDepartment(state.checkInfoForm.rectifyDepId); + state.userList = user as []; + }; + + return { + ...toRefs(state), + rectifyFormRef, + submitDelay, + achieveUserList, + submitRectify, + openRectifyDialog + }; + } +}; +</script> + +<style scoped></style> diff --git a/src/views/doublePrevent/riskCheckManage/hiddenManagement/hiddenRectify/index.vue b/src/views/doublePrevent/riskCheckManage/hiddenManagement/hiddenRectify/index.vue new file mode 100644 index 0000000..4ebf282 --- /dev/null +++ b/src/views/doublePrevent/riskCheckManage/hiddenManagement/hiddenRectify/index.vue @@ -0,0 +1,437 @@ +<template> + <div class="system-role-container"> + <el-card shadow="hover"> + <div class="system-user-search mb15"> + <div class="basic-line"> + <div style="display: inline-block">整改编号:</div> + + <div style="display: inline-block"> + <el-autocomplete :fetch-suggestions="querySearch" v-model="rectifyData.params.serialCode" v-on:input="checkDate($event)" placeholder="整改编号(前八位日期)"> </el-autocomplete> + <i class="el-icon-date"></i> + </div> + <!-- <div style="display: inline-block">--> + <!-- <el-button>--> + <!-- <el-date-picker value-format="YYYY-MM-DD" :disabled-date="disabledDate" v-model="dateTime" @change="getSerialCodeList" placeholder="选择日期"> </el-date-picker>--> + <!-- </el-button>--> + <!-- </div>--> + </div> + <div class="basic-line"> + <span>整改类型:</span> + <el-select class="input-box" v-model="rectifyData.params.rectifyType" placeholder="整改类型" filterable> + <el-option v-for="item in rectifyTypeList" :key="item.id" :label="item.name" :value="item.id"></el-option> + </el-select> + </div> + <div class="basic-line"> + <span>整改部门:</span> + <el-cascader :options="departmentList" :props="{ emitPath: false, checkStrictly: true, value: 'depId', label: 'depName' }" placeholder="请选择部门" clearable filterable class="input-box" v-model="rectifyData.params.rectifyDepId"> </el-cascader> + </div> + <div class="basic-line"> + <span>隐患状态:</span> + <el-select class="input-box" v-model="rectifyData.params.dangerStatus" placeholder="隐患状态" filterable clearable> + <el-option v-for="item in dangerStatusList" :key="item.id" :label="item.name" :value="item.id"></el-option> + </el-select> + </div> + <div class="basic-line"> + <span>创建时间范围:</span> + <el-date-picker v-model="dateTimeRange" @change="giveTime" value-format="YYYY-MM-DD HH:mm:ss" type="datetimerange" range-separator="To" start-placeholder="开始时间" end-placeholder="结束时间" /> + </div> + <i class="el-icon-date"></i> + <el-button size="default" type="primary" class="ml10" v-throttle @click="handleSearch"> + <el-icon> + <ele-Search /> + </el-icon> + 查询 + </el-button> + </div> + <el-table :data="rectifyData.data" style="width: 100%" fit highlight-current-row> + <el-table-column type="index" label="序号" width="60" /> + <el-table-column prop="reportTime" label="上报时间" show-overflow-tooltip width="170px"></el-table-column> + <el-table-column prop="dangerCode" label="隐患名称" show-overflow-tooltip></el-table-column> + <el-table-column prop="rectifyDesc" label="整改内容说明" show-overflow-tooltip></el-table-column> + <el-table-column prop="rectifyTime" label="整改期限" min-width="130px" show-overflow-tooltip> + <template #default="scope"> + <span>{{ scope.row.rectifyTime }}</span> + <span v-if="scope.row.dangerStatus === 4" class="overdue-img">逾期</span> + </template> + </el-table-column> + <el-table-column prop="rectifyType" label=" 整改类型" show-overflow-tooltip> + <template #default="scope"> + {{ parseNumber(scope.row.rectifyType, '整改类型') }} + </template> + </el-table-column> + <el-table-column prop="liablePerson" label="整改责任人" show-overflow-tooltip></el-table-column> + <el-table-column prop="cost" label="整改资金" show-overflow-tooltip></el-table-column> + <el-table-column prop="dangerStatus" label="隐患整改状态" show-overflow-tooltip align="center"> + <template #default="scope"> + <el-tag :type="scope.row.dangerStatus === 0 ? 'info' : scope.row.dangerStatus === 1 ? 'primary' : scope.row.dangerStatus === 2 ? 'warning' : scope.row.dangerStatus === 4 ? 'danger' : 'success'"> + {{ parseNumber(scope.row.dangerStatus, '隐患整改状态') }} + </el-tag> + </template> + </el-table-column> + <el-table-column prop="createByUserName" label="创建人" show-overflow-tooltip></el-table-column> + <el-table-column prop="gmtCreate" label="创建时间" show-overflow-tooltip></el-table-column> + <el-table-column prop="lastEditUserName" label="最后修改人" show-overflow-tooltip></el-table-column> + <el-table-column prop="gmtModitify" label="最后修改时间" show-overflow-tooltip></el-table-column> + <el-table-column label="操作" width="250" fixed="right" align="center"> + <template #default="scope"> + <el-button size="small" text type="primary" :icon="View" @click="onOpenDialogRef('查看', scope.row)">查看</el-button> + <el-button size="small" text type="primary" :icon="Check" v-show="scope.row.dangerStatus === 0 || scope.row.dangerStatus === 2" @click="onOpenDialogRef('整改', scope.row)">整改</el-button> + <el-button size="small" text type="primary" :icon="Edit" v-show="scope.row.dangerStatus === 0 || scope.row.dangerStatus === 2" @click="onOpenDialogRef('延期', scope.row)">延期</el-button> + <el-button size="small" text type="danger" :icon="Delete" @click="onDelHiddenRectify(scope.row)">删除</el-button> + </template> + </el-table-column> + </el-table> + <br /> + <el-pagination @size-change="onHandleSizeChange" @current-change="onHandleCurrentChange" :pager-count="5" :page-sizes="[10, 20, 30]" v-model:current-page="rectifyData.params.pageIndex" background v-model:page-size="rectifyData.params.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="rectifyData.total" class="page-position"> </el-pagination> + <br /> + <br /> + </el-card> + <rectifyDialog ref="rectifyDialogRef" @refreshRectify="initRectifyTableData" /> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, onMounted, ref, defineComponent, computed } from 'vue'; +import { ElMessageBox, ElMessage } from 'element-plus'; +import rectifyDialog from './components/rectifyDialog.vue'; +import { Edit, Delete, Check, View } from '@element-plus/icons-vue'; +import { hiddenRectifyApi } from '/@/api/doublePreventSystem/rectify'; +import { departmentApi } from '/@/api/systemManage/department'; +import { productionDeviceApi } from '/@/api/doublePreventSystem/productionDevice'; + +// 定义接口来定义对象的类型 +interface TableData { + quota: string; + quotaUnit: string; + quotaType: string; + createUserName: string; + gmtCreate: string; + lastEditUserName: string; + gmtModitify: string; +} +interface TableDataState { + rectifyData: { + data: Array<TableData>; + + total: number; + disabled: boolean; + loading: boolean; + params: { + pageIndex: number; + pageSize: number; + rectifyType: number | null; + rectifyDepId: number | null; + dangerStatus: number | null; + serialCode: string; + startTime: string; + endTime: string; + }; + }; + rectifyTypeList: Array<enumType>; + dangerStatusList: Array<enumType>; + departmentList: []; + disabledDate: any; + serialCodeList: Array<type>; + dateTime: string; + dateTimeRange: Array<string>; +} +interface enumType { + id: number; + name: string; +} +interface type { + id: number; + value: number; +} + +export default defineComponent({ + name: 'rectify', + components: { rectifyDialog, Edit, Delete, View }, + setup() { + const rectifyDialogRef = ref(); + const state = reactive<TableDataState>({ + rectifyData: { + data: [], + total: 0, + disabled: true, + loading: false, + params: { + pageIndex: 1, + pageSize: 10, + rectifyType: null, + rectifyDepId: null, + dangerStatus: null, + serialCode: '', + startTime: '', + endTime: '' + } + }, + dateTime: '', + dateTimeRange: [], + disabledDate: (time: any) => { + return time.getTime() > new Date().getTime(); + }, + departmentList: [], + serialCodeList: [], + rectifyTypeList: [ + { id: 1, name: '即查即改' }, + { id: 2, name: '限期整改' } + ], + dangerStatusList: [ + { id: 0, name: '整改中' }, + { id: 1, name: '待验收' }, + { id: 2, name: '延期整改' }, + { id: 4, name: '超期未整改' }, + { id: 9, name: '已验收' } + ] + }); + + const giveTime = () => { + if (state.dateTimeRange && state.dateTimeRange !== null) { + state.rectifyData.params.startTime = state.dateTimeRange[0]; + state.rectifyData.params.endTime = state.dateTimeRange[1]; + } else { + state.rectifyData.params.startTime = ''; + state.rectifyData.params.endTime = ''; + } + }; + + const querySearch = () => { + return state.serialCodeList.filter((item) => item.value.toString().indexOf(state.rectifyData.params.serialCode) !== -1); + }; + const handleChange = (value: string): Boolean => { + let year = value.substr(0, 4); + let month = value.substr(4, 2); + let day = value.substr(6, 2); + if (Number(year) < 1000 || Number(year) > new Date().getFullYear()) { + return false; + } + if (Number(month) > 12 || month === '00') { + return false; + } + let leapYearTab = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; + let notLeapYearTab = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; + if (isLeapYear(year)) { + const maxDay = leapYearTab[Number(month) - 1]; + if (Number(day) > maxDay) { + return false; + } + } else { + const maxDay = notLeapYearTab[Number(month) - 1]; + if (Number(day) > maxDay) { + return false; + } + } + return true; + }; + + const isLeapYear = (value: string) => { + return Number(value) % 4 === 0; + }; + + const checkDate = async (value: string) => { + if (value.length >= 8) { + if (handleChange(value.substr(0, 8))) { + let res = await hiddenRectifyApi().getCodeByTime(value.substr(0, 4) + '-' + value.substr(4, 2) + '-' + value.substr(6, 2)); + if (res.data.code === '200' && res.data.data > 0) { + state.serialCodeList = []; + let date = parseInt(value.substr(0, 8) + '0000'); + for (let i = 0; i < res.data.data; i++) { + state.serialCodeList.push({ value: date + 1 + i, id: i }); + } + } else if (res.data.code === '200' && res.data.data === 0) { + ElMessage({ + type: 'warning', + message: '当天无隐患上报' + }); + } + } else { + state.rectifyData.params.serialCode = ''; + ElMessage({ + type: 'warning', + message: '前八位请输入正确得日期格式' + }); + } + } else { + } + // if (state.dateTime === '' || state.dateTime === null) { + // state.serialCodeList = []; + // state.rectifyData.params.serialCode = ''; + // } else { + // state.serialCodeList = []; + // state.rectifyData.params.serialCode = ''; + // let res = await hiddenRectifyApi().getCodeByTime(state.dateTime); + // if (res.data.code === '200' && res.data.data > 0) { + // state.rectifyData.disabled = false; + // let date = parseInt(state.dateTime.replaceAll('-', '') + '0000'); + // for (let i = 0; i < res.data.data; i++) { + // state.serialCodeList.push({ value: date + 1 + i, id: i }); + // } + // state.rectifyData.params.serialCode = state.dateTime.replaceAll('-', ''); + // } else if (res.data.code === '200' && res.data.data === 0) { + // state.rectifyData.disabled = true; + // ElMessage({ + // type: 'warning', + // message: '当天无隐患上报' + // }); + // } + // } + }; + + // 初始化表格数据 + const initRectifyTableData = async () => { + if (state.rectifyData.params.serialCode.toString().length === 0) { + let res = await hiddenRectifyApi().getHiddenRectifyList(state.rectifyData.params); + if (res.data.code === '200') { + state.rectifyData.data = res.data.data; + state.rectifyData.total = res.data.count; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } else if (state.rectifyData.params.serialCode.toString().length !== 12) { + ElMessage({ + type: 'warning', + message: '请输入或选择正确的隐患编号' + }); + } else { + state.rectifyData.params.serialCode = state.rectifyData.params.serialCode.toString().substr(0, 8) + '-' + state.rectifyData.params.serialCode.toString().substr(8, 4); + let res = await hiddenRectifyApi().getHiddenRectifyList(state.rectifyData.params); + if (res.data.code === '200') { + state.rectifyData.params.serialCode = state.rectifyData.params.serialCode.replaceAll('-', ''); + state.rectifyData.data = res.data.data; + state.rectifyData.total = res.data.count; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } + }; + + //获取部门列表 + const getDepartmentData = async () => { + let res = await departmentApi().getDepartmentList(); + if (res.data.code === '200') { + state.departmentList = res.data.data; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 打开弹窗 + const onOpenDialogRef = (type: string, value: any) => { + rectifyDialogRef.value.openRectifyDialog(type, value, state.departmentList); + }; + // 删除 + const onDelHiddenRectify = (row: any) => { + ElMessageBox.confirm(`此操作将永久删除该隐患整改,是否继续?`, '提示', { + confirmButtonText: '确认', + cancelButtonText: '取消', + type: 'warning' + }) + .then(async () => { + let res = await hiddenRectifyApi().deleteHiddenRectify({ id: row.id }); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + duration: 2000, + message: '删除成功' + }); + await initRectifyTableData(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }) + .catch(() => {}); + }; + + const parseNumber = (value: string | number, type: string) => { + if (type === '整改类型') { + return state.rectifyTypeList.find((item) => item.id === value)?.name; + } else if (type === '隐患整改状态') { + return state.dangerStatusList.find((item) => item.id === value)?.name; + } + }; + + const handleSearch = () => { + initRectifyTableData(); + }; + // 分页改变 + const onHandleSizeChange = (val: number) => { + state.rectifyData.params.pageSize = val; + initRectifyTableData(); + }; + // 分页改变 + const onHandleCurrentChange = (val: number) => { + state.rectifyData.params.pageIndex = val; + initRectifyTableData(); + }; + // 页面加载时 + onMounted(() => { + initRectifyTableData(); + getDepartmentData(); + }); + + return { + Edit, + View, + Check, + Delete, + giveTime, + querySearch, + parseNumber, + handleSearch, + checkDate, + onOpenDialogRef, + onHandleSizeChange, + onDelHiddenRectify, + onHandleCurrentChange, + rectifyDialog, + rectifyDialogRef, + initRectifyTableData, + ...toRefs(state) + }; + } +}); +</script> + +<style scoped> +.overdue-img { + position: absolute; + background-color: #f56c6c; + border-radius: 4px; + color: #fff; + display: inline-block; + font-size: 12px; + height: 21px; + line-height: 18px; + text-align: center; + white-space: nowrap; + border: 1px solid #fff; + transform: scale(0.8); + padding: 1px 3px 0 3px; +} +:deep(.el-textarea.is-disabled .el-textarea__inner) { + background-color: var(--el-card-bg-color); + color: var(--el-input-text-color, var(--el-text-color-regular)); +} +:deep(.el-input.is-disabled .el-input__inner) { + color: var(--el-input-text-color, var(--el-text-color-regular)); +} +:deep(.el-input.is-disabled .el-input__wrapper) { + background-color: var(--el-card-bg-color); +} +:deep(.el-input-group__prepend) { + padding: 0; +} +</style> diff --git a/src/views/doublePrevent/riskCheckManage/hiddenManagement/hiddenReport/components/reportDialog.vue b/src/views/doublePrevent/riskCheckManage/hiddenManagement/hiddenReport/components/reportDialog.vue new file mode 100644 index 0000000..3cf8972 --- /dev/null +++ b/src/views/doublePrevent/riskCheckManage/hiddenManagement/hiddenReport/components/reportDialog.vue @@ -0,0 +1,391 @@ +<template> + <div class="system-add-menu-container"> + <el-dialog :title="title" v-model="isShowReportDialog" width="50%" :close-on-click-modal="false"> + <el-form :model="reportForm" :rules="reportFormRules" ref="reportFormRef" size="default" label-width="120px"> + <el-tabs class="active" v-model="activeNameOne"> + <el-tab-pane label="隐患信息" name="hiddenInfo"> + <el-row :gutter="25"> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" class="mb20"> + <el-form-item label="隐患名称" prop="dangerCode"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="reportForm.dangerCode" placeholder="请输入隐患名称" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" class="mb20"> + <el-form-item label="隐患描述" prop="dangerDesc"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="reportForm.dangerDesc" placeholder="请输入隐患情况描述" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" class="mb20"> + <el-form-item label="隐患所属部门" prop="depId"> + <el-cascader :disabled="!disabled" :options="departmentList" :props="{ emitPath: false, checkStrictly: true, value: 'depId', label: 'depName' }" placeholder="请选择部门" clearable filterable class="input-add" v-model="reportForm.depId"> </el-cascader> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" class="mb20"> + <el-form-item label="生产装置" prop="produceDeviceId"> + <el-select class="input-add" :disabled="!disabled" v-model="reportForm.produceDeviceId" placeholder="请输入生产装置" clearable filterable @change="changeUnit"> + <el-option v-for="item in allProduceDeviceData" :key="item.id" :label="item.produceDeviceName" :value="item.id"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" class="mb20"> + <el-form-item label="风险分析单元" prop="riskUnitId"> + <el-select class="input-add" :disabled="!disabled" v-model.trim="reportForm.riskUnitId" placeholder="请输入风险分析单元" clearable filterable> + <el-option v-for="item in safetyRiskUnitData" :key="item.id" :label="item.riskUnitName" :value="item.id"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" class="mb20"> + <el-form-item label="隐患来源" prop="dangerSource"> + <el-select class="input-add" :disabled="!disabled" v-model="reportForm.dangerSource" placeholder="请选择隐患来源" clearable filterable> + <el-option v-for="item in dangerSourceList" :key="item.id" :label="item.name" :value="item.id"></el-option> + </el-select> + </el-form-item> + </el-col> + + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" class="mb20"> + <el-form-item label="隐患等级" prop="dangerLevel"> + <el-select class="input-add" :disabled="!disabled" v-model="reportForm.dangerLevel" placeholder="请选择隐患等级" clearable filterable> + <el-option v-for="item in dangerLevelList" :key="item.id" :label="item.name" :value="item.id"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" class="mb20"> + <el-form-item label="隐患类型" prop="dangerType"> + <el-select class="input-add" :disabled="!disabled" v-model="reportForm.dangerType" placeholder="请选择隐患类型" clearable filterable> + <el-option v-for="item in dangerTypeList" :key="item.id" :label="item.name" :value="item.id"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" class="mb20"> + <el-form-item label="隐患可能后果" prop="dangerResult"> + <el-select class="input-add" :disabled="!disabled" v-model="reportForm.dangerResult" placeholder="请选择隐患可能后果" clearable filterable> + <el-option v-for="item in dangerResultList" :key="item.id" :label="item.name" :value="item.id"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12"> + <el-form-item label="隐患产生原因" prop="dangerReason"> + <el-input class="input-add" :disabled="!disabled" type="textarea" :rows="2" style="padding-bottom: 10px" v-model.trim="reportForm.dangerReason" placeholder="请输入隐患产生原因"></el-input> + </el-form-item> + </el-col> + </el-row> + </el-tab-pane> + </el-tabs> + + <el-divider></el-divider> + + <el-tabs class="active" v-model="activeNameTwo"> + <el-tab-pane label="整改信息" name="rectifyInfo"> + <el-row> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" class="mb20"> + <el-form-item label="整改类型" prop="rectifyType"> + <el-select class="input-add" :disabled="!disabled" v-model="reportForm.rectifyType" placeholder="请选择整改类型" clearable filterable> + <el-option v-for="item in rectifyTypeList" :key="item.id" :label="item.name" :value="item.id"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" class="mb20"> + <el-form-item label="整改期限" prop="rectifyTime"> + <el-date-picker type="datetime" :disabled="!disabled" value-format="YYYY-MM-DD HH:mm:ss" class="input-add" v-model="reportForm.rectifyTime" placeholder="请选择整改期限" clearable> </el-date-picker> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" class="mb20"> + <el-form-item label="整改部门" prop="rectifyDepId"> + <el-cascader :disabled="!disabled" @change="achieveUserList" :options="departmentList" :props="{ emitPath: false, checkStrictly: true, value: 'depId', label: 'depName' }" placeholder="请选择部门" clearable filterable class="input-add" v-model="reportForm.rectifyDepId"> </el-cascader> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" class="mb20"> + <el-form-item label="整改责任人" prop="liablePersonId"> + <el-select class="input-add" :disabled="!disabled" v-model="reportForm.liablePersonId" placeholder="请选择整改责任人" clearable filterable> + <el-option v-for="item in userList" :key="item.uid" :label="item.username" :value="item.uid"></el-option> + </el-select> + </el-form-item> + </el-col> + + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" class="mb20"> + <el-form-item label="整改资金" prop="dangerResult"> + <el-input class="input-add" :disabled="!disabled" type="number" @input="onVerifyNumberPercentageFloat($event)" v-model="reportForm.cost" placeholder="请选择整改资金"> </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12"> + <el-form-item label="整改措施" prop="rectifyDesc"> + <el-input class="input-add" :disabled="!disabled" type="textarea" :rows="2" style="padding-bottom: 10px" v-model.trim="reportForm.rectifyDesc" placeholder="请输入整改措施"></el-input> + </el-form-item> + </el-col> + </el-row> + </el-tab-pane> + </el-tabs> + </el-form> + <template #footer> + <span class="dialog-footer" v-show="disabled"> + <el-button @click="isShowReportDialog = !isShowReportDialog" size="default">取 消</el-button> + <el-button type="primary" @click="submitReport" v-throttle size="default">确 定</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script lang="ts"> +interface stateType { + isShowReportDialog: Boolean; + reportForm: { + dangerDesc: string | null; + dangerCode: string | null; + depId: number | null; + produceDeviceId: number | null; + riskUnitId: number | null; + dangerSource: number | null; + dangerLevel: number | null; + dangerType: number | null; + dangerReason: string | null; + dangerResult: number | null; + rectifyType: number | null; + rectifyDepId: number | null; + liablePersonId: number | null; + rectifyTime: string | null; + cost: number | null; + rectifyDesc: string | null; + }; + title: string; + disabled: boolean; + activeNameOne: string; + activeNameTwo: string; + reportFormRules: {}; + departmentList: []; + userList: []; + allProduceDeviceData: []; + allSafetyRiskUnitData: Array<safetyRiskUnit>; + safetyRiskUnitData: Array<safetyRiskUnit>; + dangerLevelList: Array<enumType>; + dangerSourceList: Array<enumType>; + dangerResultList: Array<enumType>; + dangerTypeList: Array<enumType>; + rectifyTypeList: Array<enumType>; +} +interface enumType { + id: number; + name: string; +} +interface safetyRiskUnit { + produceDeviceId: number; +} +interface T {} +import { reactive, toRefs, ref } from 'vue'; +import { ElMessage } from 'element-plus'; +import { hiddenReportApi } from '/@/api/doublePreventSystem/report'; +import { getUserByDepartment } from '/@/assets/methods'; +import { verifyNumberIntegerAndFloat, verifyNumberPercentageFloat } from '../../../../../../utils/toolsValidate'; +export default { + name: 'reportDialog', + setup(props: any, context: any) { + const reportFormRef = ref(); + const state = reactive<stateType>({ + title: '', + disabled: false, + activeNameOne: 'hiddenInfo', + activeNameTwo: 'rectifyInfo', + isShowReportDialog: false, + departmentList: [], + userList: [], + allProduceDeviceData: [], + allSafetyRiskUnitData: [], + safetyRiskUnitData: [], + dangerLevelList: [ + { id: 1, name: '一般隐患' }, + { id: 2, name: '重大隐患' } + ], + dangerSourceList: [ + { id: 1, name: '日常排查' }, + { id: 2, name: '综合性排查' }, + { id: 3, name: '专业性排查' }, + { id: 4, name: '季节性排查' }, + { id: 5, name: '重点时段及节假日前排查' }, + { id: 6, name: '事故类比排查' }, + { id: 7, name: '复产复工前排查' }, + { id: 8, name: '外聘专家诊断式排查' }, + { id: 9, name: '管控措施失效' }, + { id: 10, name: '其他' } + ], + dangerResultList: [ + { id: 1, name: '无' }, + { id: 2, name: '轻伤' }, + { id: 3, name: '重伤' }, + { id: 4, name: '死亡' } + ], + dangerTypeList: [ + { id: 1, name: '安全' }, + { id: 2, name: '工艺' }, + { id: 3, name: '电气' }, + { id: 4, name: '仪表' }, + { id: 5, name: '消防' }, + { id: 6, name: '总图' }, + { id: 7, name: '设备' }, + { id: 8, name: '其他' } + ], + rectifyTypeList: [ + { id: 1, name: '即查即改' }, + { id: 2, name: '限期整改' } + ], + reportForm: { + dangerDesc: null, + dangerCode: null, + depId: null, + produceDeviceId: null, + riskUnitId: null, + dangerSource: null, + dangerLevel: null, + dangerType: null, + dangerReason: null, + dangerResult: null, + rectifyType: null, + rectifyDepId: null, + liablePersonId: null, + rectifyTime: null, + cost: null, + rectifyDesc: null + }, + reportFormRules: { + dangerDesc: [{ required: true, message: '请填写隐患情况描述', trigger: 'blur' }], + dangerCode: [{ required: true, message: '请填写隐患名称', trigger: 'blur' }], + depId: [{ required: true, message: '请选择隐患所属部门', trigger: 'change' }], + produceDeviceId: [{ required: true, message: '请选择生产装置', trigger: 'change' }], + riskUnitId: [{ required: true, message: '请选择风险分析单元', trigger: 'change' }], + dangerSource: [{ required: true, message: '请选择隐患来源', trigger: 'change' }], + dangerLevel: [{ required: true, message: '请选择隐患等级', trigger: 'change' }], + dangerType: [{ required: true, message: '请选择隐患类型', trigger: 'change' }], + dangerReason: [{ required: true, message: '请填写隐患产生原因分析', trigger: 'blur' }], + dangerResult: [{ required: true, message: '请选择隐患可能后果', trigger: 'change' }], + rectifyType: [{ required: true, message: '请选择整改类型', trigger: 'change' }], + rectifyDepId: [{ required: true, message: '请选择整改单位', trigger: 'change' }], + liablePersonId: [{ required: true, message: '请选择整改责任人', trigger: 'change' }], + rectifyTime: [{ required: true, message: '请选择整改期限', trigger: 'change' }], + cost: [{ required: true, message: '请选择整改资金', trigger: 'blur' }], + rectifyDesc: [{ required: true, message: '请填写整改内容', trigger: 'blur' }] + } + }); + + //打开模态框 + const openReportDialog = (type: string, value: { id: number }, departmentList: [], allProduceDeviceData: [], allSafetyRiskUnitData: []) => { + state.isShowReportDialog = true; + state.departmentList = departmentList; + state.allProduceDeviceData = JSON.parse(JSON.stringify(allProduceDeviceData)); + state.allSafetyRiskUnitData = allSafetyRiskUnitData; + setTimeout(() => { + reportFormRef.value.clearValidate(); + }); + if (type === '新增') { + state.disabled = true; + state.title = '新增隐患'; + state.reportForm = { + dangerDesc: null, + dangerCode: null, + depId: null, + produceDeviceId: null, + riskUnitId: null, + dangerSource: null, + dangerLevel: null, + dangerType: null, + dangerReason: null, + dangerResult: null, + rectifyType: null, + rectifyDepId: null, + liablePersonId: null, + rectifyTime: null, + cost: null, + rectifyDesc: null + }; + } else if (type === '查看') { + state.title = '修改隐患'; + state.disabled = false; + state.reportForm.rectifyDepId = JSON.parse(JSON.stringify(value)).rectifyDepId; + achieveUserList(); + state.reportForm = JSON.parse(JSON.stringify(value)); + } else { + state.title = '修改隐患'; + state.disabled = true; + state.reportForm.rectifyDepId = JSON.parse(JSON.stringify(value)).rectifyDepId; + achieveUserList(); + state.reportForm = JSON.parse(JSON.stringify(value)); + } + }; + + //新增修改提交 + const submitReport = async () => { + reportFormRef.value.validate(async (valid: Boolean) => { + if (valid) { + if (state.title === '新增隐患') { + let res = await hiddenReportApi().addHiddenReport(state.reportForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '隐患新增成功', + duration: 2000 + }); + state.isShowReportDialog = false; + context.emit('refreshReport'); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } else { + let res = await hiddenReportApi().modHiddenReport(state.reportForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '隐患修改成功', + duration: 2000 + }); + state.isShowReportDialog = false; + context.emit('refreshReport'); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } + } else { + ElMessage({ + type: 'warning', + message: '请完善基本信息' + }); + } + }); + }; + + const achieveUserList = async () => { + state.reportForm.liablePersonId = null; + const user: unknown = await getUserByDepartment(state.reportForm.rectifyDepId); + state.userList = user as []; + }; + + const changeUnit = () => { + state.reportForm.riskUnitId = null; + state.safetyRiskUnitData = state.allSafetyRiskUnitData.filter((item) => item.produceDeviceId === state.reportForm.produceDeviceId); + }; + + const onVerifyNumberPercentageFloat = (val: string) => { + state.reportForm.cost = JSON.parse(verifyNumberIntegerAndFloat(val)); + }; + + return { + ...toRefs(state), + changeUnit, + reportFormRef, + submitReport, + achieveUserList, + openReportDialog, + onVerifyNumberPercentageFloat + }; + } +}; +</script> + +<style scoped> +:deep(.el-dialog__header) { + padding-bottom: 0px !important; +} +</style> diff --git a/src/views/doublePrevent/riskCheckManage/hiddenManagement/hiddenReport/index.vue b/src/views/doublePrevent/riskCheckManage/hiddenManagement/hiddenReport/index.vue new file mode 100644 index 0000000..d958349 --- /dev/null +++ b/src/views/doublePrevent/riskCheckManage/hiddenManagement/hiddenReport/index.vue @@ -0,0 +1,352 @@ +<template> + <div class="system-role-container"> + <el-card shadow="hover"> + <div class="system-user-search mb15"> + <div class="basic-line"> + <span>隐患等级:</span> + <el-select class="input-box" v-model="reportData.params.dangerLevel" placeholder="隐患等级" filterable clearable> + <el-option v-for="item in dangerLevelList" :key="item.id" :label="item.name" :value="item.id"></el-option> + </el-select> + </div> + <div class="basic-line"> + <span>隐患来源:</span> + <el-select class="input-box" v-model="reportData.params.dangerSource" placeholder="隐患来源" filterable clearable> + <el-option v-for="item in dangerSourceList" :key="item.id" :label="item.name" :value="item.id"></el-option> + </el-select> + </div> + <div class="basic-line"> + <span>隐患状态:</span> + <el-select class="input-box" v-model="reportData.params.dangerStatus" placeholder="隐患状态" filterable clearable> + <el-option v-for="item in dangerStatusList" :key="item.id" :label="item.name" :value="item.id"></el-option> + </el-select> + </div> + <div class="basic-line"> + <span>隐患类型:</span> + <el-select class="input-box" v-model="reportData.params.dangerType" placeholder="隐患类型" filterable clearable> + <el-option v-for="item in dangerTypeList" :key="item.id" :label="item.name" :value="item.id"></el-option> + </el-select> + </div> + + <el-button size="default" type="primary" class="ml10" v-throttle @click="handleSearch"> + <el-icon> + <ele-Search /> + </el-icon> + 查询 + </el-button> + <el-button size="default" type="success" class="ml10" @click="onOpenDialogRef('新增', '')"> + <el-icon> + <ele-FolderAdd /> + </el-icon> + 新增隐患 + </el-button> + </div> + <el-table :data="reportData.data" style="width: 100%"> + <el-table-column type="index" label="序号" width="60" /> + <el-table-column prop="reportTime" label="上报时间" show-overflow-tooltip width="170px"></el-table-column> + <el-table-column prop="dangerCode" label="隐患名称" show-overflow-tooltip></el-table-column> + <el-table-column prop="dangerDesc" label="隐患情况描述" show-overflow-tooltip></el-table-column> + <el-table-column prop="produceDeviceName" label="生产装置名称" show-overflow-tooltip></el-table-column> + <el-table-column prop="riskUnitName" label="风险分析单元名称" show-overflow-tooltip></el-table-column> + <el-table-column prop="dangerSource" label="隐患来源" show-overflow-tooltip> + <template #default="scope"> + {{ parseNumber(scope.row.dangerSource, '隐患来源') }} + </template> + </el-table-column> + <el-table-column prop="dangerLevel" label="隐患等级" show-overflow-tooltip align="center"> + <template #default="scope"> + <el-tag :type="scope.row.dangerLevel === 1 ? 'warning' : 'danger'"> + {{ parseNumber(scope.row.dangerLevel, '隐患等级') }} + </el-tag> + </template> + </el-table-column> + <el-table-column prop="dangerType" label="隐患类型" show-overflow-tooltip> + <template #default="scope"> + {{ parseNumber(scope.row.dangerType, '隐患类型') }} + </template> + </el-table-column> + <el-table-column prop="dangerReason" label="隐患产生原因分析" show-overflow-tooltip></el-table-column> + <el-table-column prop="dangerResult" label="隐患可能导致后果" show-overflow-tooltip align="center"> + <template #default="scope"> + <el-tag :type="scope.row.dangerResult === 1 ? 'success' : scope.row.dangerResult === 2 ? 'info' : scope.row.dangerResult === 3 ? 'warning' : 'danger'"> {{ parseNumber(scope.row.dangerResult, '隐患可能导致后果') }}</el-tag> + </template> + </el-table-column> + <el-table-column prop="createByUserName" label="创建人" show-overflow-tooltip></el-table-column> + <el-table-column prop="gmtCreate" label="创建时间" show-overflow-tooltip></el-table-column> + <el-table-column prop="lastEditUserName" label="最后修改人" show-overflow-tooltip></el-table-column> + <el-table-column prop="gmtModitify" label="最后修改时间" show-overflow-tooltip></el-table-column> + <el-table-column label="操作" width="250" fixed="right" align="center"> + <template #default="scope"> + <el-button size="small" text type="primary" :icon="View" @click="onOpenDialogRef('查看', scope.row)">查看</el-button> + <el-button size="small" text type="primary" :icon="Edit" @click="onOpenDialogRef('修改', scope.row)">修改</el-button> + <el-button size="small" text type="danger" :icon="Delete" @click="onDelProductionDevice(scope.row)">删除</el-button> + </template> + </el-table-column> + </el-table> + <br /> + <el-pagination @size-change="onHandleSizeChange" @current-change="onHandleCurrentChange" :pager-count="5" :page-sizes="[10, 15, 20, 30]" v-model:current-page="reportData.params.pageIndex" background v-model:page-size="reportData.params.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="reportData.total" class="page-position"> </el-pagination> + <br /> + <br /> + </el-card> + <reportDialog ref="reportDialogRef" @refreshReport="initReportTableData" /> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, onMounted, ref, defineComponent } from 'vue'; +import { ElMessageBox, ElMessage } from 'element-plus'; +import reportDialog from './components/reportDialog.vue'; +import { Edit, Delete, View } from '@element-plus/icons-vue'; +import { hiddenReportApi } from '/@/api/doublePreventSystem/report'; +import { departmentApi } from '/@/api/systemManage/department'; +import { productionDeviceApi } from '/@/api/doublePreventSystem/productionDevice'; +import { safetyRiskAnalyseUnitApi } from '/@/api/doublePreventSystem/safetyRiskAnalyseUnit'; + +// 定义接口来定义对象的类型 +interface TableData { + quota: string; + quotaUnit: string; + quotaType: string; + createUserName: string; + gmtCreate: string; + lastEditUserName: string; + gmtModitify: string; +} +interface TableDataState { + reportData: { + data: Array<TableData>; + total: number; + loading: boolean; + params: { + pageIndex: number; + pageSize: number; + dangerLevel: number | null; + dangerSource: number | null; + dangerStatus: string | null; + dangerType: number | null; + }; + }; + dangerLevelList: Array<enumType>; + dangerSourceList: Array<enumType>; + dangerStatusList: Array<enumType>; + dangerTypeList: Array<enumType>; + dangerResultList: Array<enumType>; + departmentList: []; + allProduceDeviceData: []; + allSafetyRiskUnitData: []; +} +interface enumType { + id: number; + name: string; +} + +export default defineComponent({ + name: 'report', + components: { reportDialog, Edit, Delete, View }, + setup() { + const reportDialogRef = ref(); + const state = reactive<TableDataState>({ + reportData: { + data: [], + total: 0, + loading: false, + params: { + pageIndex: 1, + pageSize: 10, + dangerLevel: null, + dangerSource: null, + dangerStatus: null, + dangerType: null + } + }, + departmentList: [], + dangerLevelList: [ + { id: 1, name: '一般隐患' }, + { id: 2, name: '重大隐患' } + ], + dangerSourceList: [ + { id: 1, name: '日常排查' }, + { id: 2, name: '综合性排查' }, + { id: 3, name: '专业性排查' }, + { id: 4, name: '季节性排查' }, + { id: 5, name: '重点时段及节假日前排查' }, + { id: 6, name: '事故类比排查' }, + { id: 7, name: '复产复工前排查' }, + { id: 8, name: '外聘专家诊断式排查' }, + { id: 9, name: '管控措施失效' }, + { id: 10, name: '其他' } + ], + dangerStatusList: [ + { id: 0, name: '整改中' }, + { id: 1, name: '待验收' }, + { id: 2, name: '延期整改' }, + { id: 4, name: '超期未整改' }, + { id: 9, name: '已验收' } + ], + dangerTypeList: [ + { id: 1, name: '安全' }, + { id: 2, name: '工艺' }, + { id: 3, name: '电气' }, + { id: 4, name: '仪表' }, + { id: 5, name: '消防' }, + { id: 6, name: '总图' }, + { id: 7, name: '设备' }, + { id: 8, name: '其他' } + ], + dangerResultList: [ + { id: 1, name: '无' }, + { id: 2, name: '轻伤' }, + { id: 3, name: '重伤' }, + { id: 4, name: '死亡' } + ], + allProduceDeviceData: [], + allSafetyRiskUnitData: [] + }); + + // 初始化表格数据 + const initReportTableData = async () => { + let res = await hiddenReportApi().getHiddenReportList(state.reportData.params); + if (res.data.code === '200') { + state.reportData.data = res.data.data; + state.reportData.total = res.data.count; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + //获取生产装置列表 + const getAllProduceDeviceData = async () => { + let res = await productionDeviceApi().getAllProductionDeviceList(); + if (res.data.code === '200') { + state.allProduceDeviceData = res.data.data; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 获取安全风险分析单元数据 + const getAllSafetyRiskEventData = async () => { + let res = await safetyRiskAnalyseUnitApi().getAllSafetyRiskAnalyseUnitList(); + if (res.data.code === '200') { + state.allSafetyRiskUnitData = JSON.parse(JSON.stringify(res.data.data)); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + //获取部门列表 + const getDepartmentData = async () => { + let res = await departmentApi().getDepartmentList(); + if (res.data.code === '200') { + state.departmentList = res.data.data; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 打开弹窗 + const onOpenDialogRef = (type: string, value: any) => { + reportDialogRef.value.openReportDialog(type, value, state.departmentList, state.allProduceDeviceData, state.allSafetyRiskUnitData); + }; + // 删除 + const onDelProductionDevice = (row: any) => { + ElMessageBox.confirm(`此操作将永久该条隐患,是否继续?`, '提示', { + confirmButtonText: '确认', + cancelButtonText: '取消', + type: 'warning' + }) + .then(async () => { + let res = await hiddenReportApi().deleteHiddenReport({ id: row.id }); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + duration: 2000, + message: '删除成功' + }); + await initReportTableData(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }) + .catch(() => {}); + }; + + const handleSearch = () => { + initReportTableData(); + }; + // 分页改变 + const onHandleSizeChange = (val: number) => { + state.reportData.params.pageSize = val; + initReportTableData(); + }; + // 分页改变 + const onHandleCurrentChange = (val: number) => { + state.reportData.params.pageIndex = val; + initReportTableData(); + }; + + const parseNumber = (value: string | number, type: string) => { + if (type === '隐患来源') { + return state.dangerSourceList.find((item) => item.id === value)?.name; + } else if (type === '隐患等级') { + return state.dangerLevelList.find((item) => item.id === value)?.name; + } else if (type === '隐患类型') { + return state.dangerTypeList.find((item) => item.id === value)?.name; + } else { + return state.dangerResultList.find((item) => item.id === value)?.name; + } + }; + + // 页面加载时 + onMounted(() => { + initReportTableData(); + getDepartmentData(); + getAllProduceDeviceData(); + getAllSafetyRiskEventData(); + }); + + return { + Edit, + View, + Delete, + parseNumber, + handleSearch, + onOpenDialogRef, + onHandleSizeChange, + onDelProductionDevice, + onHandleCurrentChange, + reportDialog, + reportDialogRef, + initReportTableData, + ...toRefs(state) + }; + } +}); +</script> + +<style scoped> +:deep(.el-textarea.is-disabled .el-textarea__inner) { + background-color: var(--el-card-bg-color); + color: var(--el-input-text-color, var(--el-text-color-regular)); +} +:deep(.el-input.is-disabled .el-input__inner) { + color: var(--el-input-text-color, var(--el-text-color-regular)); +} +:deep(.el-input.is-disabled .el-input__wrapper) { + background-color: var(--el-card-bg-color); +} +</style> diff --git a/src/views/doublePrevent/riskCheckManage/riskCheckUnit/components/checkUnitDialog.vue b/src/views/doublePrevent/riskCheckManage/riskCheckUnit/components/checkUnitDialog.vue new file mode 100644 index 0000000..81ab0c6 --- /dev/null +++ b/src/views/doublePrevent/riskCheckManage/riskCheckUnit/components/checkUnitDialog.vue @@ -0,0 +1,260 @@ +<template> + <div class="system-add-menu-container"> + <el-dialog :title="title" v-model="isShowCheckUnitDialog" append-to-body :close-on-click-modal="false" width="50%"> + <el-divider></el-divider> + <div class="checkUnit-form"> + <el-form :model="checkUnitForm" :rules="checkUnitFormRules" ref="checkUnitFormRef" size="default" label-width="120px"> + <el-row :gutter="35"> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" class="mb20"> + <el-form-item label="任务单元名称" prop="taskUnitName"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="checkUnitForm.taskUnitName" placeholder="请输入任务单元名称" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" class="mb20"> + <el-form-item label="任务单元说明" prop="note"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="checkUnitForm.note" placeholder="请输入任务单元说明" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" class="mb20" v-show="personTime"> + <el-form-item label="创建人" prop="location"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="checkUnitForm.createByUserName" placeholder="请输入区域位置"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" class="mb20" v-show="personTime"> + <el-form-item label="创建时间" prop="location"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="checkUnitForm.gmtCreate" placeholder="请输入区域位置"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" class="mb20" v-show="personTime"> + <el-form-item label="最后修改人" prop="location"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="checkUnitForm.lastEditUserName" placeholder="请输入区域位置"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" class="mb20" v-show="personTime"> + <el-form-item label="最后修改时间" prop="location"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="checkUnitForm.gmtModitify" placeholder="请输入区域位置"></el-input> + </el-form-item> + </el-col> + </el-row> + </el-form> + </div> + + <div class="checkUnit-point"> + <el-tabs class="active" v-model="activeName"> + <el-tab-pane label="检查项信息" name="checkUnit"> + <div class="filter-container"> + <el-button size="default" :disabled="!disabled" type="success" @click="onOpenDialogRef('新增', '')"> + <el-icon> + <ele-FolderAdd /> + </el-icon> + 选择风险管控措施 + </el-button> + </div> + + <el-table :data="measureData" border fit highlight-current-row style="width: 100%"> + <el-table-column type="index" label="序号" width="60" /> + <el-table-column prop="checkContent" label="管控内容" show-overflow-tooltip align="center"></el-table-column> + <el-table-column label="操作" width="150" align="center"> + <template #default="scope"> + <el-button size="small" text :disabled="!disabled" type="danger" @click="onDelCheckUnit(scope.$index, scope.row)">删除</el-button> + </template> + </el-table-column> + </el-table> + </el-tab-pane> + </el-tabs> + </div> + + <template #footer> + <span class="dialog-footer" v-show="disabled"> + <el-button @click="isShowCheckUnitDialog = !isShowCheckUnitDialog" size="default">取 消</el-button> + <el-button type="primary" @click="submitCheckUnit" v-throttle size="default">确 定</el-button> + </span> + </template> + </el-dialog> + <el-dialog title="选择风险管控措施" v-model="isShowSelectMeasureControlDialog" append-to-body :close-on-click-modal="false" width="70%"> + <select-measure-control-dialog ref="SelectMeasureControlDialogRef" @receiveRiskControlId="receiveRiskControlId"></select-measure-control-dialog> + </el-dialog> + </div> +</template> + +<script lang="ts"> +import SelectMeasureControlDialog from './selectMeasureControlDialog.vue'; +import { reactive, toRefs, ref } from 'vue'; +import { checkUnitApi } from '/@/api/doublePreventSystem/checkUnit'; +import { ElMessage } from 'element-plus'; +interface stateType { + isShowCheckUnitDialog: Boolean; + disabled: Boolean; + personTime: Boolean; + isShowSelectMeasureControlDialog: Boolean; + checkUnitForm: { + taskUnitName: string | null; + note: string | null; + measureList: []; + }; + title: string; + activeName: string; + measureData: []; + checkUnitData: []; + checkUnitFormRules: {}; +} + +export default { + name: 'checkUnitDialog', + components: { SelectMeasureControlDialog }, + setup(props: any, context: any) { + const checkUnitFormRef = ref(); + const riskControlMeasureDialogRef = ref(); + const state = reactive<stateType>({ + title: '', + disabled: false, + personTime: false, + activeName: 'checkUnit', + measureData: [], + checkUnitData: [], + isShowCheckUnitDialog: false, + isShowSelectMeasureControlDialog: false, + checkUnitForm: { + taskUnitName: null, + note: null, + measureList: [] + }, + checkUnitFormRules: { + taskUnitName: [{ required: true, message: '请填写任务单元名称', trigger: 'blur' }], + note: [{ required: true, message: '请填写任务单元说明', trigger: 'change' }] + } + }); + + //打开模态框 + const openCheckUnitDialog = (type: string, value: object) => { + state.isShowCheckUnitDialog = true; + setTimeout(() => { + checkUnitFormRef.value.clearValidate(); + }); + if (type === '新增') { + state.disabled = true; + state.personTime = false; + state.title = '新增隐患排查单元'; + state.measureData = []; + state.checkUnitForm = { + taskUnitName: null, + note: null, + measureList: [] + }; + } else if (type === '查看') { + state.disabled = false; + state.personTime = true; + state.title = '查看隐患排查单元'; + state.checkUnitForm = JSON.parse(JSON.stringify(value)); + state.measureData = state.checkUnitForm.measureList; + } else { + state.disabled = true; + state.personTime = false; + state.title = '修改隐患排查单元'; + state.checkUnitForm = JSON.parse(JSON.stringify(value)); + state.measureData = state.checkUnitForm.measureList; + } + }; + + const onOpenDialogRef = () => { + state.isShowSelectMeasureControlDialog = true; + }; + + const onDelCheckUnit = (value: number, scope: object) => { + state.measureData.splice(value, 1); + }; + + const receiveRiskControlId = (value: []) => { + state.isShowSelectMeasureControlDialog = false; + state.measureData = value; + state.checkUnitForm.measureList = JSON.parse( + JSON.stringify( + value.map((item: { id: number }) => { + return item.id; + }) + ) + ); + }; + + //新增修改提交 + const submitCheckUnit = async () => { + checkUnitFormRef.value.validate(async (valid: Boolean) => { + if (valid) { + if (state.title === '新增隐患排查单元') { + let res = await checkUnitApi().addCheckUnit(state.checkUnitForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '隐患排查单元新增成功', + duration: 2000 + }); + state.isShowCheckUnitDialog = false; + context.emit('refreshCheckUnit'); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } else { + let res = await checkUnitApi().modCheckUnit(state.checkUnitForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '隐患排查单元修改成功', + duration: 2000 + }); + state.isShowCheckUnitDialog = false; + context.emit('refreshCheckUnit'); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } + } else { + ElMessage({ + type: 'warning', + message: '请完善基本信息' + }); + } + }); + }; + + return { + ...toRefs(state), + checkUnitFormRef, + submitCheckUnit, + onDelCheckUnit, + onOpenDialogRef, + openCheckUnitDialog, + receiveRiskControlId, + riskControlMeasureDialogRef + }; + } +}; +</script> + +<style scoped> +::v-deep.el-divider--horizontal { + margin-top: 0px !important; +} + +::v-deep.el-dialog__body { + padding-top: 10px !important; +} +.filter-container { + padding: 10px 0px; +} +:deep(.el-textarea.is-disabled .el-textarea__inner) { + background-color: var(--el-card-bg-color); + color: var(--el-input-text-color, var(--el-text-color-regular)); +} +:deep(.el-input.is-disabled .el-input__inner) { + color: var(--el-input-text-color, var(--el-text-color-regular)); +} +:deep(.el-input.is-disabled .el-input__wrapper) { + background-color: var(--el-card-bg-color); +} +</style> diff --git a/src/views/doublePrevent/riskCheckManage/riskCheckUnit/components/selectMeasureControlDialog.vue b/src/views/doublePrevent/riskCheckManage/riskCheckUnit/components/selectMeasureControlDialog.vue new file mode 100644 index 0000000..df01f4a --- /dev/null +++ b/src/views/doublePrevent/riskCheckManage/riskCheckUnit/components/selectMeasureControlDialog.vue @@ -0,0 +1,219 @@ +<template> + <div class="system-role-container"> + <el-card shadow="hover"> + <div class="system-user-search mb15"> + <div class="basic-line"> + <span>管控方式:</span> + <el-select class="input-box" v-model="riskControlMeasureData.params.controlType" placeholder="管控方式" clearable> + <el-option v-for="item in controlTypeList" :key="item.id" :label="item.name" :value="item.id"></el-option> + </el-select> + </div> + <div class="basic-line"> + <span>安全风险事件:</span> + <el-select class="input-box" v-model="riskControlMeasureData.params.riskEventId" placeholder="安全风险事件" clearable> + <el-option v-for="item in allSafetyRiskEventData" :key="item.id" :label="item.riskEventName" :value="item.id"></el-option> + </el-select> + </div> + <el-button size="default" type="primary" class="ml10" v-throttle @click="handleSearch"> + <el-icon> + <ele-Search /> + </el-icon> + 查询 + </el-button> + </div> + <el-table + @selection-change="handleSelectionChange" + ref="table" + :row-key="getRowKey" + :data="riskControlMeasureData.data" + style="width: 100%" + > + <el-table-column type="selection" :reserve-selection="true" width="55"></el-table-column> + <el-table-column prop="riskEventName" label="安全风险事件名称" show-overflow-tooltip></el-table-column> + <el-table-column prop="controlMeasureCode" label="风控措施编码" show-overflow-tooltip></el-table-column> + <el-table-column prop="controlType" label="管控方式" show-overflow-tooltip> + <template #default="scope"> + {{ parseNumber(scope.row.controlType, '管控方式') }} + </template> + </el-table-column> + <el-table-column prop="checkContent" label="管控内容" show-overflow-tooltip></el-table-column> + <el-table-column prop="classify1" label="管控措施分类1" show-overflow-tooltip> + <template #default="scope"> + {{ parseNumber(scope.row.classify1, '管控措施分类1') }} + </template> + </el-table-column> + <el-table-column prop="classify2" label="管控措施分类2" show-overflow-tooltip> + <template #default="scope"> + {{ parseNumber(scope.row.classify2, '管控措施分类2') }} + </template> + </el-table-column> + <el-table-column prop="classify3" label="管控措施分类3" show-overflow-tooltip></el-table-column> + <el-table-column prop="measureDesc" label="措施说明" show-overflow-tooltip></el-table-column>> + <el-table-column label="操作" width="150"> + <template #default="scope"> + <el-button type="text" @click="giveValue(scope.row)">选择 </el-button> + </template> + </el-table-column> + </el-table> + </el-card> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, onMounted, ref } from 'vue'; +import { ElMessageBox, ElMessage } from 'element-plus'; +import { riskControlMeasureApi } from '/@/api/doublePreventSystem/riskControlMeasure/index.ts'; +import { safetyRiskEventApi } from '/@/api/doublePreventSystem/safetyRiskEvent'; + +// 定义接口来定义对象的类型 +interface TableData { + roleName: string; + roleSign: string; + describe: string; + sort: number; + status: boolean; + createTime: string; +} +interface TableDataState { + isShowSelectMeasureControlDialog: boolean; + riskControlMeasureIdList: Array<riskControlMeasure>; + riskControlMeasureData: { + data: Array<TableData>; + total: number; + loading: boolean; + params: { + pageIndex: number; + pageSize: number; + controlType: number | null; + riskEventId: number | null; + }; + }; + controlTypeList: Array<controlTypeType>; + classifyOneList: Array<classifyOneType>; + classifyTwoList: Array<classifyOneType>; +} +interface controlTypeType { + id: number; + name: string; +} +interface classifyOneType { + id: number; + riskMeasureName: string; +} + +interface riskControlMeasure {} +export default { + name: 'selectMeasureControlDialog', + components: {}, + setup(props: any, context: any) { + const riskControlMeasureDialogRef = ref(); + const state = reactive<TableDataState>({ + isShowSelectMeasureControlDialog: false, + riskControlMeasureIdList: [], + riskControlMeasureData: { + data: [], + total: 0, + loading: false, + params: { + pageIndex: 1, + pageSize: 10, + controlType: null, + riskEventId: null + } + }, + controlTypeList: [ + { id: 1, name: '自动化监控' }, + { id: 2, name: '隐患排查' } + ], + classifyOneList: [], + classifyTwoList: [] + }); + + // 初始化表格数据 + const initRiskControlMeasureData = async () => { + let res = await riskControlMeasureApi().getAllRiskControlMeasureList(); + if (res.data.code === '200') { + state.riskControlMeasureData.data = res.data.data; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + //获取管控措施分类 + const getClassify = async () => { + let res = await riskControlMeasureApi().getClassifyData(); + if (res.data.code === '200') { + state.classifyOneList = res.data.data.filter((item: any) => item.parentId === null); + state.classifyTwoList = res.data.data.filter((item: any) => item.parentId !== null); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + const parseNumber = (value: string | number, type: string) => { + if (type === '管控方式') { + return state.controlTypeList.find((item) => item.id === value)?.name; + } else if (type === '管控措施分类1') { + return state.classifyOneList.find((item) => item.id === value)?.riskMeasureName; + } else { + return state.classifyTwoList.find((item) => item.id === value)?.riskMeasureName; + } + }; + + const handleSearch = () => { + initRiskControlMeasureData(); + }; + + // 分页改变 + const onHandleSizeChange = (val: number) => { + state.riskControlMeasureData.params.pageSize = val; + initRiskControlMeasureData(); + }; + + // 分页改变 + const onHandleCurrentChange = (val: number) => { + state.riskControlMeasureData.params.pageIndex = val; + initRiskControlMeasureData(); + }; + + const handleSelectionChange = (val: []) => { + state.riskControlMeasureIdList = val; + }; + + const getRowKey = (value: { id: number }) => { + return value.id; + }; + + const giveValue = () => { + context.emit('receiveRiskControlId', state.riskControlMeasureIdList); + }; + + // 页面加载时 + onMounted(() => { + initRiskControlMeasureData(); + getClassify(); + }); + + return { + handleSearch, + parseNumber, + getRowKey, + giveValue, + handleSelectionChange, + onHandleSizeChange, + onHandleCurrentChange, + riskControlMeasureDialogRef, + initRiskControlMeasureData, + ...toRefs(state) + }; + } +}; +</script> + +<style scoped></style> diff --git a/src/views/doublePrevent/riskCheckManage/riskCheckUnit/index.vue b/src/views/doublePrevent/riskCheckManage/riskCheckUnit/index.vue new file mode 100644 index 0000000..ad9a72f --- /dev/null +++ b/src/views/doublePrevent/riskCheckManage/riskCheckUnit/index.vue @@ -0,0 +1,194 @@ +<template> + <div class="system-role-container"> + <el-card shadow="hover"> + <div class="system-user-search mb15"> + <!-- <div class="basic-line">--> + <!-- <span>风险等级:</span>--> + <!-- <el-select v-model="checkUnitData.params.riskLevel" clearable filterable class="input-box" placeholder="请选择风险等级">--> + <!-- <el-option v-for="item in levelList" :key="item.id" :label="item.name" :value="item.id"></el-option>--> + <!-- </el-select>--> + <!-- </div>--> + <!-- <div class="basic-line">--> + <!-- <span>部门:</span>--> + <!-- <el-cascader :options="departmentList" :props="{ emitPath: false, checkStrictly: true, value: 'depId', label: 'depName' }" placeholder="请选择部门" clearable filterable class="input-box" v-model="checkUnitData.params.depId"> </el-cascader>--> + <!-- </div>--> + <div class="basic-line"> + <span>任务单元名称:</span> + <el-input class="input-box" v-model="checkUnitData.params.taskUnitName" placeholder="任务单元名称" clearable> </el-input> + </div> + <el-button size="default" type="primary" class="ml10" v-throttle @click="handleSearch"> + <el-icon> + <ele-Search /> + </el-icon> + 查询 + </el-button> + <el-button size="default" type="success" class="ml10" @click="onOpenDialogRef('新增', '')"> + <el-icon> + <ele-FolderAdd /> + </el-icon> + 新增排查单元 + </el-button> + </div> + <el-table :data="checkUnitData.data" style="width: 100%"> + <el-table-column type="index" label="序号" width="60" /> + <el-table-column prop="taskUnitName" label="任务单元名称" show-overflow-tooltip></el-table-column> + <el-table-column prop="note" label="任务单元说明" show-overflow-tooltip></el-table-column> + <el-table-column prop="createByUserName" label="创建人" show-overflow-tooltip></el-table-column> + <el-table-column prop="gmtCreate" label="创建时间" show-overflow-tooltip></el-table-column> + <el-table-column prop="lastEditUserName" label="最后修改人" show-overflow-tooltip></el-table-column> + <el-table-column prop="gmtModitify" label="最后修改时间" show-overflow-tooltip></el-table-column> + <el-table-column label="操作" width="200" align="center"> + <template #default="scope"> + <el-button size="small" text type="primary" :icon="View" @click="onOpenDialogRef('查看', scope.row)">查看</el-button> + <el-button size="small" text type="primary" :icon="Edit" @click="onOpenDialogRef('修改', scope.row)">修改</el-button> + <el-button size="small" text type="danger" :icon="Delete" @click="onDelcheckUnit(scope.row)">删除</el-button> + </template> + </el-table-column> + </el-table> + <br /> + <el-pagination @size-change="onHandleSizeChange" @current-change="onHandleCurrentChange" :pager-count="5" :page-sizes="[10, 20, 30]" v-model:current-page="checkUnitData.params.pageIndex" background v-model:page-size="checkUnitData.params.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="checkUnitData.total" class="page-position"> </el-pagination> + <br /> + <br /> + </el-card> + <checkUnitDialog ref="checkUnitDialogRef" @refreshCheckUnit="initCheckUnitTableData" /> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, onMounted, ref, defineComponent } from 'vue'; +import { ElMessageBox, ElMessage } from 'element-plus'; +import checkUnitDialog from './components/checkUnitDialog.vue'; +import { checkUnitApi } from '/@/api/doublePreventSystem/checkUnit/index.ts'; +import { Edit, Delete, View } from '@element-plus/icons-vue'; + +// 定义接口来定义对象的类型 +interface TableData { + roleName: string; + roleSign: string; + describe: string; + sort: number; + status: boolean; + createTime: string; +} +interface TableDataState { + checkUnitData: { + data: Array<TableData>; + total: number; + loading: boolean; + params: { + pageIndex: number; + pageSize: number; + taskUnitName: number | null; + }; + }; +} + +export default defineComponent({ + name: 'index', + components: { checkUnitDialog, Edit, Delete, View }, + setup() { + const checkUnitDialogRef = ref(); + const state = reactive<TableDataState>({ + checkUnitData: { + data: [], + total: 0, + loading: false, + params: { + pageIndex: 1, + pageSize: 10, + taskUnitId: null + } + } + }); + // 初始化表格数据 + const initCheckUnitTableData = async () => { + let res = await checkUnitApi().getCheckUnitList(state.checkUnitData.params); + if (res.data.code === '200') { + state.checkUnitData.data = res.data.data; + state.checkUnitData.total = res.data.count; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 打开生产装置弹窗 + const onOpenDialogRef = (type: string, value: any) => { + checkUnitDialogRef.value.openCheckUnitDialog(type, value); + }; + // 删除角色 + const onDelCheckUnit = (row: any) => { + ElMessageBox.confirm(`此操作将永久删除该条生产装置:“${row.produceDeviceName}”,是否继续?`, '提示', { + confirmButtonText: '确认', + cancelButtonText: '取消', + type: 'warning' + }) + .then(async () => { + let res = await checkUnitApi().deleteCheckUnit({ id: row.id }); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + duration: 2000, + message: '删除成功' + }); + await initCheckUnitTableData(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }) + .catch(() => {}); + }; + + const handleSearch = () => { + initCheckUnitTableData(); + }; + // 分页改变 + const onHandleSizeChange = (val: number) => { + state.checkUnitData.params.pageSize = val; + initCheckUnitTableData(); + }; + // 分页改变 + const onHandleCurrentChange = (val: number) => { + state.checkUnitData.params.pageIndex = val; + initCheckUnitTableData(); + }; + // 页面加载时 + onMounted(() => { + initCheckUnitTableData(); + }); + + return { + Edit, + Delete, + View, + handleSearch, + onOpenDialogRef, + onHandleSizeChange, + onDelCheckUnit, + onHandleCurrentChange, + checkUnitDialog, + checkUnitDialogRef, + initCheckUnitTableData, + ...toRefs(state) + }; + } +}); +</script> + +<style scoped> +:deep(.el-textarea.is-disabled .el-textarea__inner) { + background-color: var(--el-card-bg-color); + color: var(--el-input-text-color, var(--el-text-color-regular)); +} +:deep(.el-input.is-disabled .el-input__inner) { + color: var(--el-input-text-color, var(--el-text-color-regular)); +} +:deep(.el-input.is-disabled .el-input__wrapper) { + background-color: var(--el-card-bg-color); +} +</style> diff --git a/src/views/doublePrevent/riskLevel/action/components/riskControlMeasureDialog.vue b/src/views/doublePrevent/riskLevel/action/components/riskControlMeasureDialog.vue new file mode 100644 index 0000000..316d156 --- /dev/null +++ b/src/views/doublePrevent/riskLevel/action/components/riskControlMeasureDialog.vue @@ -0,0 +1,265 @@ +<template> + <div class="system-add-menu-container"> + <el-dialog :title="title" v-model="isRiskControlMeasureDialog" width="600px" :close-on-click-modal="false"> + <el-form :model="riskControlMeasureForm" :rules="riskControlMeasureFormRules" ref="riskControlMeasureFormRef" size="default" label-width="160px"> + <el-row :gutter="35"> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="风险事件名称" prop="riskEventId"> + <el-select class="input-add" :disabled="!disabled" v-model="riskControlMeasureForm.riskEventId" placeholder="请选择风险事件" clearable> + <el-option v-for="item in allSafetyRiskEventData" :key="item.id" :label="item.riskEventName" :value="item.id"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="风险措施编码" prop="controlMeasureCode"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="riskControlMeasureForm.controlMeasureCode" placeholder="请输入风险措施编码"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="管控方式" prop="controlType"> + <el-select class="input-add" :disabled="!disabled" v-model="riskControlMeasureForm.controlType" placeholder="请选择管控方式" clearable> + <el-option v-for="item in controlTypeList" :key="item.id" :label="item.name" :value="item.id"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="管控内容" prop="checkContent"> + <el-input class="input-add" :disabled="!disabled" type="textarea" :rows="3" v-model.trim="riskControlMeasureForm.checkContent" placeholder="请输入管控内容" clearable> </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="管控措施分类1" prop="classify1"> + <el-select class="input-add" :disabled="!disabled" v-model="riskControlMeasureForm.classify1" @change="changeClassifyTwoList" placeholder="请选择管控措施分类1" clearable> + <el-option v-for="item in classifyOneList" :key="item.id" :label="item.riskMeasureName" :value="item.id"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="管控措施分类2" prop="classify2"> + <el-select class="input-add" :disabled="!disabled" v-model="riskControlMeasureForm.classify2" placeholder="请选择管控措施分类2" clearable> + <el-option v-for="item in classifyTwoList" :key="item.id" :label="item.riskMeasureName" :value="item.id"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="管控措施分类3" prop="classify3"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="riskControlMeasureForm.classify3" placeholder="请填写管控措施分类3" clearable> </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="措施说明" prop="measureDesc"> + <el-input class="input-add" :disabled="!disabled" type="textarea" :rows="3" v-model.trim="riskControlMeasureForm.measureDesc" placeholder="请输入措施说明" clearable> </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20" v-show="personTime"> + <el-form-item label="创建人" prop="location"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="riskControlMeasureForm.createByUserName" placeholder="请输入区域位置"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20" v-show="personTime"> + <el-form-item label="创建时间" prop="location"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="riskControlMeasureForm.gmtCreate" placeholder="请输入区域位置"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20" v-show="personTime"> + <el-form-item label="最后修改人" prop="location"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="riskControlMeasureForm.lastEditUserName" placeholder="请输入区域位置"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20" v-show="personTime"> + <el-form-item label="最后修改时间" prop="location"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="riskControlMeasureForm.gmtModitify" placeholder="请输入区域位置"></el-input> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer" v-show="disabled"> + <el-button @click="isRiskControlMeasureDialog = !isRiskControlMeasureDialog" size="default">取 消</el-button> + <el-button type="primary" @click="submitRiskControlMeasureDialog" v-throttle size="default">确 定</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script lang="ts"> +interface stateType { + isRiskControlMeasureDialog: Boolean; + disabled: Boolean; + personTime: Boolean; + riskControlMeasureForm: { + riskEventId: number | null; + controlMeasureCode: string | null; + controlType: number | null; + checkContent: string | null; + classify1: number | null; + classify2: number | null; + classify3: string | null; + measureDesc: string | null; + }; + title: string; + controlTypeList: Array<controlTypeListType>; + classifyOneList: []; + classifyTwoList: Array<classifyTwoType>; + classifyTwoListAll: []; + allSafetyRiskEventData: []; + riskControlMeasureFormRules: {}; +} +interface classifyTwoType { + id: number; + riskMeasureName: string; +} +interface controlTypeListType {} + +import { reactive, toRefs, ref } from 'vue'; +import { riskControlMeasureApi } from '/@/api/doublePreventSystem/riskControlMeasure'; +import { ElMessage } from 'element-plus'; +export default { + name: 'riskControlMeasureDialog', + setup(props: any, context: any) { + const riskControlMeasureFormRef = ref(); + const state = reactive<stateType>({ + title: '', + disabled: false, + personTime: false, + controlTypeList: [ + { id: 1, name: '自动化监控' }, + { id: 2, name: '隐患排查' } + ], + classifyOneList: [], + classifyTwoList: [], + classifyTwoListAll: [], + allSafetyRiskEventData: [], + isRiskControlMeasureDialog: false, + riskControlMeasureForm: { + riskEventId: null, + controlMeasureCode: null, + controlType: null, + checkContent: null, + classify1: null, + classify2: null, + classify3: null, + measureDesc: null + }, + riskControlMeasureFormRules: { + riskEventId: [{ required: true, message: '请选择风险事件', trigger: 'change' }], + controlMeasureCode: [{ required: true, message: '请填写风险措施编码', trigger: 'blur' }], + controlType: [{ required: true, message: '请选择管控方式', trigger: 'change' }], + checkContent: [{ required: true, message: '请填写管控内容', trigger: 'blur' }], + classify1: [{ required: true, message: '请选择管控措施分类1', trigger: 'change' }], + classify2: [{ required: true, message: '请选择管控措施分类2', trigger: 'change' }], + classify3: [{ required: true, message: '请填写管控措施分类3', trigger: 'blur' }], + measureDesc: [{ required: true, message: '请填写措施说明', trigger: 'blur' }] + } + }); + + //打开模态框 + const openSafetyRiskEventDialog = (type: string, value: object, allSafetyRiskEventData: [], classifyOneList: [], classifyTwoList: []) => { + state.isRiskControlMeasureDialog = true; + state.allSafetyRiskEventData = JSON.parse(JSON.stringify(allSafetyRiskEventData)); + state.classifyOneList = JSON.parse(JSON.stringify(classifyOneList)); + state.classifyTwoListAll = JSON.parse(JSON.stringify(classifyTwoList)); + state.classifyTwoList = []; + setTimeout(() => { + riskControlMeasureFormRef.value.clearValidate(); + }); + if (type === '新增') { + state.disabled = true; + state.personTime = false; + state.title = '新增风险管控措施'; + state.riskControlMeasureForm = { + riskEventId: null, + controlMeasureCode: null, + controlType: null, + checkContent: null, + classify1: null, + classify2: null, + classify3: null, + measureDesc: null + }; + } else if (type === '查看') { + state.disabled = false; + state.personTime = true; + state.title = '修改风险管控措施'; + state.riskControlMeasureForm.classify1 = JSON.parse(JSON.stringify(value)).classify1; + state.classifyTwoList = state.classifyTwoListAll.filter((item: any) => item.parentId === state.riskControlMeasureForm.classify1); + state.riskControlMeasureForm = JSON.parse(JSON.stringify(value)); + } else { + state.disabled = true; + state.personTime = false; + state.title = '修改风险管控措施'; + state.riskControlMeasureForm.classify1 = JSON.parse(JSON.stringify(value)).classify1; + state.classifyTwoList = state.classifyTwoListAll.filter((item: any) => item.parentId === state.riskControlMeasureForm.classify1); + state.riskControlMeasureForm = JSON.parse(JSON.stringify(value)); + } + }; + + const changeClassifyTwoList = () => { + state.riskControlMeasureForm.classify2 = null; + state.classifyTwoList = []; + state.classifyTwoList = state.classifyTwoListAll.filter((item: any) => item.parentId === state.riskControlMeasureForm.classify1); + }; + + //新增修改提交 + const submitRiskControlMeasureDialog = async () => { + riskControlMeasureFormRef.value.validate(async (valid: Boolean) => { + if (valid) { + if (state.title === '新增风险管控措施') { + let res = await riskControlMeasureApi().addRiskControlMeasure(state.riskControlMeasureForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '风险管控措施新增成功', + duration: 2000 + }); + state.isRiskControlMeasureDialog = false; + context.emit('refreshRiskControlMeasure'); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } else { + let res = await riskControlMeasureApi().modRiskControlMeasure(state.riskControlMeasureForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '风险管控措施修改成功', + duration: 2000 + }); + state.isRiskControlMeasureDialog = false; + context.emit('refreshRiskControlMeasure'); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } + } else { + ElMessage({ + type: 'warning', + message: '请完善基本信息' + }); + } + }); + }; + + return { + ...toRefs(state), + riskControlMeasureFormRef, + changeClassifyTwoList, + submitRiskControlMeasureDialog, + openSafetyRiskEventDialog + }; + } +}; +</script> + +<style scoped> +.input-length { + width: 85%; +} +</style> diff --git a/src/views/doublePrevent/riskLevel/action/index.vue b/src/views/doublePrevent/riskLevel/action/index.vue new file mode 100644 index 0000000..0629615 --- /dev/null +++ b/src/views/doublePrevent/riskLevel/action/index.vue @@ -0,0 +1,323 @@ +<template> + <div class="system-role-container"> + <el-card shadow="hover"> + <div class="system-user-search mb15"> + <div class="basic-line"> + <span>管控方式:</span> + <el-select class="input-box" v-model="riskControlMeasureData.params.controlType" placeholder="管控方式" clearable> + <el-option v-for="item in controlTypeList" :key="item.id" :label="item.name" :value="item.id"></el-option> + </el-select> + </div> + <div class="basic-line"> + <span>安全风险事件:</span> + <el-select class="input-box" v-model="riskControlMeasureData.params.riskEventId" placeholder="安全风险事件" clearable> + <el-option v-for="item in allSafetyRiskEventData" :key="item.id" :label="item.riskEventName" :value="item.id"></el-option> + </el-select> + </div> + <el-button size="default" type="primary" class="ml10" v-throttle @click="handleSearch"> + <el-icon> + <ele-Search /> + </el-icon> + 查询 + </el-button> + <el-button size="default" type="success" class="ml10" @click="onOpenDialogRef('新增', '')"> + <el-icon> + <ele-FolderAdd /> + </el-icon> + 新增措施 + </el-button> + </div> + <el-table :data="riskControlMeasureData.data" style="width: 100%"> + <el-table-column type="index" label="序号" width="60" /> + <el-table-column prop="riskEventName" label="安全风险事件名称" show-overflow-tooltip></el-table-column> + <el-table-column prop="controlMeasureCode" label="风控措施编码" show-overflow-tooltip></el-table-column> + <el-table-column prop="controlType" label="管控方式" show-overflow-tooltip> + <template #default="scope"> + {{ parseNumber(scope.row.controlType, '管控方式') }} + </template> + </el-table-column> + <el-table-column prop="checkContent" label="管控内容" show-overflow-tooltip></el-table-column> + <el-table-column prop="classify1" label="管控措施分类1" show-overflow-tooltip> + <template #default="scope"> + {{ parseNumber(scope.row.classify1, '管控措施分类1') }} + </template> + </el-table-column> + <el-table-column prop="classify2" label="管控措施分类2" show-overflow-tooltip> + <template #default="scope"> + {{ parseNumber(scope.row.classify2, '管控措施分类2') }} + </template> + </el-table-column> + <el-table-column prop="classify3" label="管控措施分类3" show-overflow-tooltip></el-table-column> + <el-table-column prop="measureDesc" label="措施说明" show-overflow-tooltip></el-table-column> + <el-table-column prop="createByUserName" label="创建人" show-overflow-tooltip></el-table-column> + <el-table-column prop="gmtCreate" label="创建时间" show-overflow-tooltip> + <template #default="scope"> + <span>{{ dateFormat('YYYY-mm-dd HH:MM:SS', '2022-07-07T08:00:00') }}</span> + </template> + </el-table-column> + <el-table-column prop="lastEditUserName" label="最后修改人" show-overflow-tooltip></el-table-column> + <el-table-column prop="gmtModitify" label="最后修改时间" show-overflow-tooltip></el-table-column> + <el-table-column label="操作" width="200" align="center"> + <template #default="scope"> + <el-button size="small" text type="primary" :icon="View" @click="onOpenDialogRef('查看', scope.row)">查看</el-button> + <el-button size="small" text type="primary" :icon="Edit" @click="onOpenDialogRef('修改', scope.row)">修改</el-button> + <el-button size="small" text type="danger" :icon="Delete" @click="onDelRiskControlMeasure(scope.row)">删除</el-button> + </template> + </el-table-column> + </el-table> + <br /> + <el-pagination @size-change="onHandleSizeChange" @current-change="onHandleCurrentChange" class="page-position" :pager-count="5" :page-sizes="[10, 20, 30]" v-model:current-page="riskControlMeasureData.params.pageIndex" background v-model:page-size="riskControlMeasureData.params.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="riskControlMeasureData.total"> </el-pagination> + <br /> + <br /> + </el-card> + <riskControlMeasureDialog ref="riskControlMeasureDialogRef" @refreshRiskControlMeasure="initRiskControlMeasureData" /> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, onMounted, ref } from 'vue'; +import { ElMessageBox, ElMessage } from 'element-plus'; +import riskControlMeasureDialog from './components/riskControlMeasureDialog.vue'; +import { riskControlMeasureApi } from '/@/api/doublePreventSystem/riskControlMeasure/index.ts'; +import { safetyRiskEventApi } from '/@/api/doublePreventSystem/safetyRiskEvent'; +import { Edit, Delete, View } from '@element-plus/icons-vue'; + +// 定义接口来定义对象的类型 +interface TableData { + roleName: string; + roleSign: string; + describe: string; + sort: number; + status: boolean; + createTime: string; +} +interface TableDataState { + riskControlMeasureData: { + data: Array<TableData>; + total: number; + loading: boolean; + params: { + pageIndex: number; + pageSize: number; + controlType: number | null; + riskEventId: number | null; + }; + }; + controlTypeList: Array<controlTypeType>; + classifyOneList: Array<classifyOneType>; + classifyTwoList: Array<classifyOneType>; + allSafetyRiskEventData: Array<SafetyRiskEventDataState>; +} +interface controlTypeType { + id: number; + name: string; +} +interface classifyOneType { + id: number; + riskMeasureName: string; +} + +interface SafetyRiskEventDataState {} + +// interface controlTypeListType { +// id: number; +// riskMeasureName: string; +// } +// +// class myType implements controlTypeListType { +// id: number; +// riskMeasureName: string; +// constructor(id: number, riskMeasureName: string) { +// this.id = id; +// this.riskMeasureName = riskMeasureName; +// } +// bark() { +// console.log('1111'); +// } +// } +// +// class type extends myType { +// bark() { +// console.log('222'); +// } +// } +// class typeTwo extends myType { +// bark() { +// super.bark(); +// } +// } +// +// var test = new type(123, '23123'); +// var test2 = new typeTwo(222, '333'); + +export default { + name: 'riskControlMeasure', + components: { riskControlMeasureDialog, Edit, Delete, View }, + setup() { + const riskControlMeasureDialogRef = ref(); + const state = reactive<TableDataState>({ + riskControlMeasureData: { + data: [], + total: 0, + loading: false, + params: { + pageIndex: 1, + pageSize: 10, + controlType: null, + riskEventId: null + } + }, + controlTypeList: [ + { id: 1, name: '自动化监控' }, + { id: 2, name: '隐患排查' } + ], + classifyOneList: [], + classifyTwoList: [], + allSafetyRiskEventData: [] + }); + + // 初始化表格数据 + const initRiskControlMeasureData = async () => { + // console.log(test.bark()); + // console.log(test2.bark()); + let res = await riskControlMeasureApi().getRiskControlMeasureList(state.riskControlMeasureData.params); + if (res.data.code === '200') { + state.riskControlMeasureData.data = res.data.data; + state.riskControlMeasureData.total = res.data.count; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + const dateFormat = (fmt: any, date: any) => { + date = new Date(date); + fmt = date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + date.getDate() + ' ' + date.getHours().toString() + ':' + (date.getMinutes().toString() === '0' ? '00' : date.getMinutes().toString()) + ':' + (date.getSeconds().toString() === '0' ? '00' : date.getMinutes().toString()); + return fmt; + }; + + //获取安全风险事件 + const getAllSafetyRiskEvent = async () => { + let res = await safetyRiskEventApi().getAllSafetyRiskEventList(); + if (res.data.code === '200') { + state.allSafetyRiskEventData = JSON.parse(JSON.stringify(res.data.data)); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + //获取管控措施分类 + const getClassify = async () => { + let res = await riskControlMeasureApi().getClassifyData(); + if (res.data.code === '200') { + state.classifyOneList = res.data.data.filter((item: any) => item.parentId === null); + state.classifyTwoList = res.data.data.filter((item: any) => item.parentId !== null); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 打开生产装置弹窗 + const onOpenDialogRef = (type: string, value: any) => { + riskControlMeasureDialogRef.value.openSafetyRiskEventDialog(type, value, state.allSafetyRiskEventData, state.classifyOneList, state.classifyTwoList); + }; + + // 删除角色 + const onDelRiskControlMeasure = (row: any) => { + ElMessageBox.confirm(`此操作将永久删除该条风险管控措施:“${row.checkContent}”,是否继续?`, '提示', { + confirmButtonText: '确认', + cancelButtonText: '取消', + type: 'warning' + }) + .then(async () => { + let res = await riskControlMeasureApi().deleteRiskControlMeasure({ id: row.id }); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + duration: 2000, + message: '删除成功' + }); + await initRiskControlMeasureData(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }) + .catch(() => {}); + }; + + const parseNumber = (value: string | number, type: string) => { + if (type === '管控方式') { + return state.controlTypeList.find((item) => item.id === value)?.name; + } else if (type === '管控措施分类1') { + return state.classifyOneList.find((item) => item.id === value)?.riskMeasureName; + } else { + return state.classifyTwoList.find((item) => item.id === value)?.riskMeasureName; + } + }; + + const handleSearch = () => { + initRiskControlMeasureData(); + }; + + // 分页改变 + const onHandleSizeChange = (val: number) => { + state.riskControlMeasureData.params.pageSize = val; + initRiskControlMeasureData(); + }; + + // 分页改变 + const onHandleCurrentChange = (val: number) => { + state.riskControlMeasureData.params.pageIndex = val; + initRiskControlMeasureData(); + }; + + // 页面加载时 + onMounted(() => { + initRiskControlMeasureData(); + getAllSafetyRiskEvent(); + getClassify(); + }); + + return { + Edit, + Delete, + View, + dateFormat, + handleSearch, + parseNumber, + onOpenDialogRef, + onHandleSizeChange, + onDelRiskControlMeasure, + onHandleCurrentChange, + riskControlMeasureDialog, + riskControlMeasureDialogRef, + initRiskControlMeasureData, + ...toRefs(state) + }; + } +}; +</script> + +<style scoped> +:deep(.el-textarea.is-disabled .el-textarea__inner) { + background-color: var(--el-card-bg-color); + color: var(--el-input-text-color, var(--el-text-color-regular)); +} +:deep(.el-input.is-disabled .el-input__inner) { + color: var(--el-input-text-color, var(--el-text-color-regular)); +} +:deep(.el-input.is-disabled .el-input__wrapper) { + background-color: var(--el-card-bg-color); +} +</style> diff --git a/src/views/doublePrevent/riskLevel/device/components/productionDeviceDialog.vue b/src/views/doublePrevent/riskLevel/device/components/productionDeviceDialog.vue new file mode 100644 index 0000000..497363d --- /dev/null +++ b/src/views/doublePrevent/riskLevel/device/components/productionDeviceDialog.vue @@ -0,0 +1,197 @@ +<template> + <div class="system-add-menu-container"> + <el-dialog :title="title" v-model="isShowProductionDeviceDialog" width="600px" :close-on-click-modal="false"> + <el-form :model="productionDeviceForm" :rules="productionDeviceFormRules" ref="productionDeviceFormRef" size="default" label-width="120px"> + <el-row :gutter="35"> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="生产装置名称" prop="produceDeviceName"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="productionDeviceForm.produceDeviceName" placeholder="请输入生产装置名称" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="所属部门" prop="depId"> + <el-cascader :options="departmentList" :disabled="!disabled" :props="{ emitPath: false, checkStrictly: true, value: 'depId', label: 'depName' }" placeholder="请选择部门" clearable filterable style="width: 90%" v-model="productionDeviceForm.depId"> </el-cascader> + <!-- <el-select class="input-length" v-model="productionDeviceForm.depName" placeholder="请选择所属部门" clearable filterable></el-select>--> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="风险等级" prop="riskLevel"> + <el-select class="input-add" :disabled="!disabled" v-model="productionDeviceForm.riskLevel" placeholder="请选择风险等级" clearable filterable> + <el-option v-for="item in levelList" :key="item.id" :label="item.name" :value="item.id"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="区域位置" prop="location"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="productionDeviceForm.location" type="textarea" placeholder="请输入区域位置" maxlength="150"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20" v-show="personTime"> + <el-form-item label="创建人" prop="location"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="productionDeviceForm.createByUserName" placeholder="请输入区域位置"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20" v-show="personTime"> + <el-form-item label="创建时间" prop="location"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="productionDeviceForm.gmtCreate" placeholder="请输入区域位置"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20" v-show="personTime"> + <el-form-item label="最后修改人" prop="location"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="productionDeviceForm.lastEditUserName" placeholder="请输入区域位置"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20" v-show="personTime"> + <el-form-item label="最后修改时间" prop="location"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="productionDeviceForm.gmtModitify" placeholder="请输入区域位置"></el-input> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer" v-show="disabled"> + <el-button @click="isShowProductionDeviceDialog = !isShowProductionDeviceDialog" size="default">取 消</el-button> + <el-button type="primary" @click="submitProductionDevice" v-throttle size="default">确 定</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script lang="ts"> +interface stateType { + isShowProductionDeviceDialog: Boolean; + disabled: Boolean; + personTime: Boolean; + productionDeviceForm: { + produceDeviceName: string; + depId: number | null; + riskLevel: number | null; + location: string; + }; + title: string; + departmentList: []; + levelList: Array<levelListState>; + productionDeviceFormRules: {}; +} +interface levelListState {} +import { reactive, toRefs, ref } from 'vue'; +import { productionDeviceApi } from '/@/api/doublePreventSystem/productionDevice'; +import { ElMessage } from 'element-plus'; +export default { + name: 'productionDeviceDialog', + setup(props: any, context: any) { + const productionDeviceFormRef = ref(); + const state = reactive<stateType>({ + title: '', + disabled: false, + personTime: false, + departmentList: [], + isShowProductionDeviceDialog: false, + levelList: [ + { id: 1, name: '低风险' }, + { id: 2, name: '一般风险' }, + { id: 3, name: '较大风险' }, + { id: 4, name: '重大风险' } + ], + productionDeviceForm: { + produceDeviceName: '', + depId: null, + riskLevel: null, + location: '' + }, + productionDeviceFormRules: { + produceDeviceName: [{ required: true, message: '请填写生产装置名称', trigger: 'blur' }], + depId: [{ required: true, message: '请选择部门', trigger: 'change' }], + riskLevel: [{ required: true, message: '请选择风险等级', trigger: 'change' }], + location: [{ required: true, message: '请填写区域位置', trigger: 'blur' }] + } + }); + + //打开模态框 + const openProductionDeviceDialog = (type: string, value: object, department: []) => { + state.isShowProductionDeviceDialog = true; + state.departmentList = department; + setTimeout(() => { + productionDeviceFormRef.value.clearValidate(); + }); + if (type === '新增') { + state.disabled = true; + state.personTime = false; + state.title = '新增生产装置'; + state.productionDeviceForm = { + produceDeviceName: '', + depId: null, + riskLevel: null, + location: '' + }; + } else if (type === '查看') { + state.disabled = false; + state.personTime = true; + state.title = '查看生产装置'; + state.productionDeviceForm = JSON.parse(JSON.stringify(value)); + } else { + state.disabled = true; + state.personTime = false; + state.title = '修改生产装置'; + state.productionDeviceForm = JSON.parse(JSON.stringify(value)); + } + }; + + //新增修改提交 + const submitProductionDevice = async () => { + productionDeviceFormRef.value.validate(async (valid: Boolean) => { + if (valid) { + if (state.title === '新增生产装置') { + let res = await productionDeviceApi().addProductionDevice(state.productionDeviceForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '生产装置新增成功', + duration: 2000 + }); + state.isShowProductionDeviceDialog = false; + context.emit('refreshProductionDevice'); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } else { + let res = await productionDeviceApi().modProductionDevice(state.productionDeviceForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '生产装置修改成功', + duration: 2000 + }); + state.isShowProductionDeviceDialog = false; + context.emit('refreshProductionDevice'); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } + } else { + ElMessage({ + type: 'warning', + message: '请完善基本信息' + }); + } + }); + }; + + return { + ...toRefs(state), + productionDeviceFormRef, + submitProductionDevice, + openProductionDeviceDialog + }; + } +}; +</script> + +<style scoped></style> diff --git a/src/views/doublePrevent/riskLevel/device/index.vue b/src/views/doublePrevent/riskLevel/device/index.vue new file mode 100644 index 0000000..048fbf5 --- /dev/null +++ b/src/views/doublePrevent/riskLevel/device/index.vue @@ -0,0 +1,261 @@ +<template> + <div class="system-role-container"> + <el-card shadow="hover"> + <div class="system-user-search mb15"> + <div class="basic-line"> + <span>生产装置名称: </span> + <el-input v-model="productionDeviceData.params.produceDeviceName" class="input-box"> </el-input> + </div> + <div class="basic-line"> + <span>风险等级: </span> + <el-select v-model="productionDeviceData.params.riskLevel" clearable filterable class="input-box" placeholder="请选择风险等级"> + <el-option v-for="item in levelList" :key="item.id" :label="item.name" :value="item.id"></el-option> + </el-select> + </div> + <div class="basic-line"> + <span>部门: </span> + <el-cascader :options="departmentList" :props="{ emitPath: false, checkStrictly: true, value: 'depId', label: 'depName' }" placeholder="请选择部门" clearable filterable class="input-box" v-model="productionDeviceData.params.depId"> </el-cascader> + </div> + <el-button size="default" type="primary" class="ml10" v-throttle @click="handleSearch"> + <el-icon> + <ele-Search /> + </el-icon> + 查询 + </el-button> + <el-button size="default" type="success" class="ml10" @click="onOpenDialogRef('新增', '')"> + <el-icon> + <ele-FolderAdd /> + </el-icon> + 新增装置 + </el-button> + </div> + <el-table :data="productionDeviceData.data" style="width: 100%"> + <el-table-column type="index" label="序号" width="60" /> + <el-table-column prop="produceDeviceName" label="生产装置名称" show-overflow-tooltip></el-table-column> + <el-table-column prop="depName" label="所属部门" show-overflow-tooltip></el-table-column> + <el-table-column prop="riskLevel" label="风险等级" show-overflow-tooltip> + <template #default="scope"> + <el-tag :type="scope.row.riskLevel === 1 ? 'success' : scope.row.riskLevel === 2 ? 'info' : scope.row.riskLevel === 3 ? 'warning' : 'danger'"> + {{ parseNumber(scope.row.riskLevel, '风险等级') }} + </el-tag> + </template> + </el-table-column> + <el-table-column prop="location" label="区域位置" show-overflow-tooltip></el-table-column> + <el-table-column prop="status" label="状态" show-overflow-tooltip> + <template #default="scope"> + <el-tag :type="scope.row.status === 1 ? 'primary' : 'warning'"> + {{ parseNumber(scope.row.status, '状态') }} + </el-tag> + </template> + </el-table-column> + <el-table-column prop="createByUserName" label="创建人" show-overflow-tooltip></el-table-column> + <el-table-column prop="gmtCreate" label="创建时间" show-overflow-tooltip></el-table-column> + <el-table-column prop="lastEditUserName" label="最后修改人" show-overflow-tooltip></el-table-column> + <el-table-column prop="gmtModitify" label="最后修改时间" show-overflow-tooltip></el-table-column> + <el-table-column label="操作" width="200" align="center"> + <template #default="scope"> + <el-button size="small" text type="primary" :icon="View" @click="onOpenDialogRef('查看', scope.row)">查看</el-button> + <el-button size="small" text type="primary" :icon="Edit" @click="onOpenDialogRef('修改', scope.row)">修改</el-button> + <el-button size="small" text type="danger" :icon="Delete" @click="onDelProductionDevice(scope.row)">删除</el-button> + </template> + </el-table-column> + </el-table> + <br /> + <el-pagination @size-change="onHandleSizeChange" @current-change="onHandleCurrentChange" :pager-count="5" :page-sizes="[10, 20, 30]" v-model:current-page="productionDeviceData.params.pageIndex" background v-model:page-size="productionDeviceData.params.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="productionDeviceData.total" class="page-position"> </el-pagination> + <br /> + <br /> + </el-card> + <productionDeviceDialog ref="productionDeviceDialogRef" @refreshProductionDevice="initProductionDeviceTableData" /> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, onMounted, ref, defineComponent } from 'vue'; +import { ElMessageBox, ElMessage } from 'element-plus'; +import productionDeviceDialog from './components/productionDeviceDialog.vue'; +import { productionDeviceApi } from '/@/api/doublePreventSystem/productionDevice/index.ts'; +import { departmentApi } from '/@/api/systemManage/department'; +import { Edit, Delete, View } from '@element-plus/icons-vue'; + +// 定义接口来定义对象的类型 +interface TableData { + roleName: string; + roleSign: string; + describe: string; + sort: number; + status: boolean; + createTime: string; +} +interface TableDataState { + productionDeviceData: { + data: Array<TableData>; + total: number; + loading: boolean; + params: { + pageIndex: number; + pageSize: number; + riskLevel: number | null | ''; + status: number; + depId: number | null | ''; + location: string | null; + produceDeviceName: string | null; + }; + }; + departmentList: Array<DepartmentState>; + stateList: Array<levelListState>; + levelList: Array<levelListState>; +} +interface levelListState { + id: number; + name: string; +} +interface DepartmentState {} + +export default { + name: 'productionDevice', + components: { productionDeviceDialog, Edit, Delete, View }, + setup() { + const productionDeviceDialogRef = ref(); + const state = reactive<TableDataState>({ + productionDeviceData: { + data: [], + total: 0, + loading: false, + params: { + pageIndex: 1, + pageSize: 10, + riskLevel: null, + status: 1, + depId: null, + location: null, + produceDeviceName: null + } + }, + departmentList: [], + levelList: [ + { id: 1, name: '低风险' }, + { id: 2, name: '一般风险' }, + { id: 3, name: '较大风险' }, + { id: 4, name: '重大风险' } + ], + stateList: [ + { id: 1, name: '使用中' }, + { id: 2, name: '已弃用' } + ] + }); + // 初始化表格数据 + const initProductionDeviceTableData = async () => { + state.productionDeviceData.params.riskLevel = state.productionDeviceData.params.riskLevel === '' ? null : state.productionDeviceData.params.riskLevel; + state.productionDeviceData.params.depId = state.productionDeviceData.params.depId === '' ? null : state.productionDeviceData.params.depId; + let res = await productionDeviceApi().getProductionDeviceList(state.productionDeviceData.params); + if (res.data.code === '200') { + state.productionDeviceData.data = res.data.data; + state.productionDeviceData.total = res.data.count; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + const getDepartmentData = async () => { + let res = await departmentApi().getDepartmentList(); + if (res.data.code === '200') { + state.departmentList = res.data.data; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 打开生产装置弹窗 + const onOpenDialogRef = (type: string, value: any) => { + productionDeviceDialogRef.value.openProductionDeviceDialog(type, value, state.departmentList); + }; + // 删除角色 + const onDelProductionDevice = (row: any) => { + ElMessageBox.confirm(`此操作将永久删除该条生产装置:“${row.produceDeviceName}”,是否继续?`, '提示', { + confirmButtonText: '确认', + cancelButtonText: '取消', + type: 'warning' + }) + .then(async () => { + let res = await productionDeviceApi().deleteProductionDevice({ id: row.id }); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + duration: 2000, + message: '删除成功' + }); + await initProductionDeviceTableData(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }) + .catch(() => {}); + }; + + const handleSearch = () => { + initProductionDeviceTableData(); + }; + // 分页改变 + const onHandleSizeChange = (val: number) => { + state.productionDeviceData.params.pageSize = val; + initProductionDeviceTableData(); + }; + // 分页改变 + const onHandleCurrentChange = (val: number) => { + state.productionDeviceData.params.pageIndex = val; + initProductionDeviceTableData(); + }; + // 页面加载时 + onMounted(() => { + initProductionDeviceTableData(); + getDepartmentData(); + }); + + const parseNumber = (value: string | number, type: string) => { + if (type === '风险等级') { + return state.levelList.find((item) => item.id === value)?.name; + } else if (type === '状态') { + return state.stateList.find((item) => item.id === value)?.name; + } + }; + + return { + Edit, + Delete, + View, + parseNumber, + handleSearch, + onOpenDialogRef, + onHandleSizeChange, + onDelProductionDevice, + onHandleCurrentChange, + productionDeviceDialog, + productionDeviceDialogRef, + initProductionDeviceTableData, + ...toRefs(state) + }; + } +}; +</script> + +<style scoped> +:deep(.el-textarea.is-disabled .el-textarea__inner) { + background-color: var(--el-card-bg-color); + color: var(--el-input-text-color, var(--el-text-color-regular)); +} +:deep(.el-input.is-disabled .el-input__inner) { + color: var(--el-input-text-color, var(--el-text-color-regular)); +} +:deep(.el-input.is-disabled .el-input__wrapper) { + background-color: var(--el-card-bg-color); +} +</style> diff --git a/src/views/doublePrevent/riskLevel/event/components/safetyRiskEventDialog.vue b/src/views/doublePrevent/riskLevel/event/components/safetyRiskEventDialog.vue new file mode 100644 index 0000000..48314ea --- /dev/null +++ b/src/views/doublePrevent/riskLevel/event/components/safetyRiskEventDialog.vue @@ -0,0 +1,184 @@ +<template> + <div class="system-add-menu-container"> + <el-dialog :title="title" v-model="isSafetyRiskEventDialog" width="600px" :close-on-click-modal="false"> + <el-form :model="safetyRiskEventForm" :rules="safetyRiskEventFormRules" ref="safetyRiskAnalyseUnitFormRef" size="default" label-width="180px"> + <el-row :gutter="35"> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="安全风险分析单元名称" prop="riskUnitId"> + <el-select class="input-add" :disabled="!disabled" v-model="safetyRiskEventForm.riskUnitId" placeholder="请输入安全风险分析单元名称"> + <el-option v-for="item in allSafetyRiskEventData" :key="item.id" :label="item.riskUnitName" :value="item.id"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="安全风险事件名称" prop="riskEventName"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="safetyRiskEventForm.riskEventName" placeholder="请输入请输入安全风险事件名称" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="可能造成得后果" prop="eventResult"> + <el-input class="input-add" type="textarea" :rows="2" :disabled="!disabled" v-model.trim="safetyRiskEventForm.eventResult" placeholder="请输入请输入安全风险事件名称" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20" v-show="personTime"> + <el-form-item label="创建人" prop="location"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="safetyRiskEventForm.createByUserName" placeholder="请输入区域位置"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20" v-show="personTime"> + <el-form-item label="创建时间" prop="location"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="safetyRiskEventForm.gmtCreate" placeholder="请输入区域位置"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20" v-show="personTime"> + <el-form-item label="最后修改人" prop="location"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="safetyRiskEventForm.lastEditUserName" placeholder="请输入区域位置"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20" v-show="personTime"> + <el-form-item label="最后修改时间" prop="location"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="safetyRiskEventForm.gmtModitify" placeholder="请输入区域位置"></el-input> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer" v-show="disabled"> + <el-button @click="isSafetyRiskEventDialog = !isSafetyRiskEventDialog" size="default">取 消</el-button> + <el-button type="primary" @click="submitSafetyRiskEventDialog" v-throttle size="default">确 定</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script lang="ts"> +interface stateType { + isSafetyRiskEventDialog: Boolean; + disabled: Boolean; + personTime: Boolean; + safetyRiskEventForm: { + riskEventName: string | null; + eventResult: string | null; + riskUnitId: number | null; + }; + title: string; + departmentList: []; + allSafetyRiskEventData: []; + safetyRiskEventFormRules: {}; +} +import { reactive, toRefs, ref } from 'vue'; +import { safetyRiskEventApi } from '/@/api/doublePreventSystem/safetyRiskEvent'; +import { ElMessage } from 'element-plus'; +export default { + name: 'productionDeviceDialog', + setup(props: any, context: any) { + const safetyRiskAnalyseUnitFormRef = ref(); + const state = reactive<stateType>({ + title: '', + disabled: false, + personTime: false, + departmentList: [], + allSafetyRiskEventData: [], + isSafetyRiskEventDialog: false, + safetyRiskEventForm: { + riskEventName: null, + eventResult: null, + riskUnitId: null + }, + safetyRiskEventFormRules: { + riskEventName: [{ required: true, message: '请填写安全风险分析对象编码', trigger: 'blur' }], + eventResult: [{ required: true, message: '请填写可能造成的后果', trigger: 'blur' }], + riskUnitId: [{ required: true, message: '请选择安全风险分析单元名称', trigger: 'change' }] + } + }); + + //打开模态框 + const openSafetyRiskEventDialog = (type: string, value: object, allSafetyRiskEventData: []) => { + state.isSafetyRiskEventDialog = true; + state.allSafetyRiskEventData = JSON.parse(JSON.stringify(allSafetyRiskEventData)); + setTimeout(() => { + safetyRiskAnalyseUnitFormRef.value.clearValidate(); + }); + if (type === '新增') { + state.disabled = true; + state.personTime = false; + state.title = '新增风险事件'; + state.safetyRiskEventForm = { + riskEventName: null, + riskUnitId: null + }; + } else if (type === '查看') { + state.disabled = false; + state.personTime = true; + state.title = '查看风险事件'; + state.safetyRiskEventForm = JSON.parse(JSON.stringify(value)); + } else { + state.disabled = true; + state.personTime = false; + state.title = '修改风险事件'; + state.safetyRiskEventForm = JSON.parse(JSON.stringify(value)); + } + }; + + //新增修改提交 + const submitSafetyRiskEventDialog = async () => { + safetyRiskAnalyseUnitFormRef.value.validate(async (valid: Boolean) => { + if (valid) { + if (state.title === '新增风险事件') { + let res = await safetyRiskEventApi().addSafetyRiskEvent(state.safetyRiskEventForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '风险事件新增成功', + duration: 2000 + }); + state.isSafetyRiskEventDialog = false; + context.emit('refreshSafetyRiskEvent'); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } else { + let res = await safetyRiskEventApi().modSafetyRiskEvent(state.safetyRiskEventForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '风险事件修改成功', + duration: 2000 + }); + state.isSafetyRiskEventDialog = false; + context.emit('refreshSafetyRiskEvent'); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } + } else { + ElMessage({ + type: 'warning', + message: '请完善基本信息' + }); + } + }); + }; + + return { + ...toRefs(state), + safetyRiskAnalyseUnitFormRef, + submitSafetyRiskEventDialog, + openSafetyRiskEventDialog + }; + } +}; +</script> + +<style scoped> +.input-length { + width: 85%; +} +</style> diff --git a/src/views/doublePrevent/riskLevel/event/index.vue b/src/views/doublePrevent/riskLevel/event/index.vue new file mode 100644 index 0000000..65cf780 --- /dev/null +++ b/src/views/doublePrevent/riskLevel/event/index.vue @@ -0,0 +1,212 @@ +<template> + <div class="system-role-container"> + <el-card shadow="hover"> + <div class="system-user-search mb15"> + <div class="basic-line"> + <span>安全风险单元名称:</span> + <el-select v-model="safetyRiskEventData.params.riskUnitId" class="input-box" placeholder="安全风险单元名称" clearable filterable> + <el-option v-for="item in allSafetyRiskEventData" :key="item.id" :label="item.riskUnitName" :value="item.id"></el-option> + </el-select> + </div> + <div class="basic-line"> + <span>安全风险事件名称:</span> + <el-input v-model="safetyRiskEventData.params.riskEventName" class="input-box" placeholder="安全风险事件名称"> </el-input> + </div> + <el-button size="default" type="primary" class="ml10" v-throttle @click="handleSearch"> + <el-icon><ele-Search /> </el-icon> + 查询 + </el-button> + <el-button size="default" type="success" class="ml10" @click="onOpenDialogRef('新增', '')"> + <el-icon> + <ele-FolderAdd /> + </el-icon> + 新增事件 + </el-button> + </div> + <el-table :data="safetyRiskEventData.data" style="width: 100%"> + <el-table-column type="index" label="序号" width="60" /> + <el-table-column prop="riskUnitName" label="安全风险分析单元名称" width="180" show-overflow-tooltip></el-table-column> + <el-table-column prop="riskEventName" label="安全风险事件名称" width="180" show-overflow-tooltip></el-table-column> + <el-table-column prop="eventResult" label="可能造成的后果" width="180" show-overflow-tooltip></el-table-column> + <el-table-column prop="createByUserName" label="创建人" show-overflow-tooltip></el-table-column> + <el-table-column prop="gmtCreate" label="创建时间" show-overflow-tooltip></el-table-column> + <el-table-column prop="lastEditUserName" label="最后修改人" show-overflow-tooltip></el-table-column> + <el-table-column prop="gmtModitify" label="最后修改时间" show-overflow-tooltip></el-table-column> + <el-table-column label="操作" width="200" align="center"> + <template #default="scope"> + <el-button size="small" text type="primary" :icon="View" @click="onOpenDialogRef('查看', scope.row)">查看</el-button> + <el-button size="small" text type="primary" :icon="Edit" @click="onOpenDialogRef('修改', scope.row)">修改</el-button> + <el-button size="small" text type="danger" :icon="Delete" @click="onDelSafetyRiskEvent(scope.row)">删除</el-button> + </template> + </el-table-column> + </el-table> + <br /> + <el-pagination @size-change="onHandleSizeChange" @current-change="onHandleCurrentChange" class="page-position" :pager-count="5" :page-sizes="[10, 20, 30]" v-model:current-page="safetyRiskEventData.params.pageIndex" background v-model:page-size="safetyRiskEventData.params.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="safetyRiskEventData.total"> </el-pagination> + <br /> + <br /> + </el-card> + <safetyRiskEventDialog ref="safetyRiskEventDialogRef" @refreshSafetyRiskEvent="initSafetyRiskEventData" /> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, onMounted, ref } from 'vue'; +import { ElMessageBox, ElMessage } from 'element-plus'; +import safetyRiskEventDialog from './components/safetyRiskEventDialog.vue'; +import { safetyRiskEventApi } from '/@/api/doublePreventSystem/safetyRiskEvent/index.ts'; +import { departmentApi } from '/@/api/systemManage/department'; +import { safetyRiskAnalyseUnitApi } from '/@/api/doublePreventSystem/safetyRiskAnalyseUnit'; +import { Edit, Delete, View } from '@element-plus/icons-vue'; + +// 定义接口来定义对象的类型 +interface TableData { + roleName: string; + roleSign: string; + describe: string; + sort: number; + status: boolean; + createTime: string; +} +interface TableDataState { + safetyRiskEventData: { + data: Array<TableData>; + total: number; + loading: boolean; + params: { + pageIndex: number; + pageSize: number; + riskEventName: string | null; + }; + }; + allSafetyRiskEventData: Array<safetyRiskEventState>; +} +interface safetyRiskEventState {} + +export default { + name: 'productionDevice', + components: { safetyRiskEventDialog, Edit, Delete, View }, + setup() { + const safetyRiskEventDialogRef = ref(); + const state = reactive<TableDataState>({ + safetyRiskEventData: { + data: [], + total: 0, + loading: false, + params: { + pageIndex: 1, + pageSize: 10, + riskEventName: null + } + }, + allSafetyRiskEventData: [] + }); + // 初始化表格数据 + const initSafetyRiskEventData = async () => { + let res = await safetyRiskEventApi().getSafetyRiskEventList(state.safetyRiskEventData.params); + if (res.data.code === '200') { + state.safetyRiskEventData.data = res.data.data; + state.safetyRiskEventData.total = res.data.count; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 获取安全风险分析单元数据 + const getAllSafetyRiskEventData = async () => { + let res = await safetyRiskAnalyseUnitApi().getAllSafetyRiskAnalyseUnitList(); + if (res.data.code === '200') { + state.allSafetyRiskEventData = JSON.parse(JSON.stringify(res.data.data)); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 打开安全风险事件 + const onOpenDialogRef = (type: string, value: any) => { + safetyRiskEventDialogRef.value.openSafetyRiskEventDialog(type, value, state.allSafetyRiskEventData); + }; + + // 删除角色 + const onDelSafetyRiskEvent = (row: any) => { + ElMessageBox.confirm(`此操作将永久删除该条安全风险事件:“${row.riskEventName}”,是否继续?`, '提示', { + confirmButtonText: '确认', + cancelButtonText: '取消', + type: 'warning' + }) + .then(async () => { + let res = await safetyRiskEventApi().deleteSafetyRiskEvent({ id: row.id }); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + duration: 2000, + message: '删除成功' + }); + await initSafetyRiskEventData(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }) + .catch(() => {}); + }; + + const handleSearch = () => { + initSafetyRiskEventData(); + }; + + // 分页改变 + const onHandleSizeChange = (val: number) => { + state.safetyRiskEventData.params.pageSize = val; + initSafetyRiskEventData(); + }; + + // 分页改变 + const onHandleCurrentChange = (val: number) => { + state.safetyRiskEventData.params.pageIndex = val; + initSafetyRiskEventData(); + }; + + // 页面加载时 + onMounted(() => { + getAllSafetyRiskEventData(); + initSafetyRiskEventData(); + }); + + return { + Edit, + Delete, + View, + handleSearch, + onOpenDialogRef, + onHandleSizeChange, + onDelSafetyRiskEvent, + onHandleCurrentChange, + safetyRiskEventDialog, + safetyRiskEventDialogRef, + initSafetyRiskEventData, + ...toRefs(state) + }; + } +}; +</script> + +<style scoped> +:deep(.el-textarea.is-disabled .el-textarea__inner) { + background-color: var(--el-card-bg-color); + color: var(--el-input-text-color, var(--el-text-color-regular)); +} +:deep(.el-input.is-disabled .el-input__inner) { + color: var(--el-input-text-color, var(--el-text-color-regular)); +} +:deep(.el-input.is-disabled .el-input__wrapper) { + background-color: var(--el-card-bg-color); +} +</style> diff --git a/src/views/doublePrevent/riskLevel/map/components/rectifyDialog.vue b/src/views/doublePrevent/riskLevel/map/components/rectifyDialog.vue new file mode 100644 index 0000000..7f76331 --- /dev/null +++ b/src/views/doublePrevent/riskLevel/map/components/rectifyDialog.vue @@ -0,0 +1,327 @@ +<template> + <div class="system-add-menu-container"> + <el-dialog :title="title" v-model="isShowReportDialog" width="50%"> + <el-form :model="reportForm" :rules="reportFormRules" ref="reportFormRef" size="default" label-width="120px"> + <el-tabs class="active" v-model="activeNameOne"> + <el-tab-pane label="隐患信息" name="hiddenInfo"> + <el-row :gutter="25"> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" class="mb20"> + <el-form-item label="隐患描述" prop="dangerDesc"> + <el-input class="input-add" v-model.trim="reportForm.dangerDesc" placeholder="请输入隐患情况描述" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" class="mb20"> + <el-form-item label="隐患所属部门" prop="depId"> + <el-cascader :options="departmentList" :props="{ emitPath: false, checkStrictly: true, value: 'depId', label: 'depName' }" placeholder="请选择部门" clearable filterable class="input-add" v-model="reportForm.depId"> </el-cascader> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" class="mb20"> + <el-form-item label="生产装置" prop="produceDeviceId"> + <el-select class="input-add" v-model="reportForm.produceDeviceId" placeholder="请输入生产装置" clearable filterable @change="changeUnit"> + <el-option v-for="item in allProduceDeviceData" :key="item.id" :label="item.produceDeviceName" :value="item.id"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" class="mb20"> + <el-form-item label="风险分析单元" prop="riskUnitId"> + <el-select class="input-add" v-model.trim="reportForm.riskUnitId" placeholder="请输入风险分析单元" clearable filterable> + <el-option v-for="item in safetyRiskUnitData" :key="item.id" :label="item.riskUnitName" :value="item.id"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" class="mb20"> + <el-form-item label="隐患来源" prop="dangerSource"> + <el-select class="input-add" v-model="reportForm.dangerSource" placeholder="请选择隐患来源" clearable filterable> + <el-option v-for="item in dangerSourceList" :key="item.id" :label="item.name" :value="item.id"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" class="mb20"> + <el-form-item label="隐患等级" prop="dangerLevel"> + <el-select class="input-add" v-model="reportForm.dangerLevel" placeholder="请选择隐患等级" clearable filterable> + <el-option v-for="item in dangerLevelList" :key="item.id" :label="item.name" :value="item.id"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" class="mb20"> + <el-form-item label="隐患类型" prop="dangerType"> + <el-select class="input-add" v-model="reportForm.dangerType" placeholder="请选择隐患类型" clearable filterable> + <el-option v-for="item in dangerTypeList" :key="item.id" :label="item.name" :value="item.id"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" class="mb20"> + <el-form-item label="隐患可能后果" prop="dangerResult"> + <el-select class="input-add" v-model="reportForm.dangerResult" placeholder="请选择隐患可能后果" clearable filterable> + <el-option v-for="item in dangerResultList" :key="item.id" :label="item.name" :value="item.id"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12"> + <el-form-item label="隐患产生原因" prop="dangerReason"> + <el-input class="input-add" type="textarea" :rows="2" style="padding-bottom: 10px" v-model.trim="reportForm.dangerReason" placeholder="请输入隐患产生原因"></el-input> + </el-form-item> + </el-col> + </el-row> + </el-tab-pane> + </el-tabs> + + <el-divider></el-divider> + + <el-tabs class="active" v-model="activeNameTwo"> + <el-tab-pane label="整改信息" name="rectifyInfo"> + <el-row> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" class="mb20"> + <el-form-item label="整改类型" prop="dangerResult"> + <el-select class="input-add" v-model="reportForm.dangerResult" placeholder="请选择整改类型" clearable filterable> <el-option v-for="item in RFIDList" :key="item.id" :label="item.rfidName" :value="item.id"></el-option> </el-select + ></el-form-item> </el-col + ><el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" class="mb20"> + <el-form-item label="整改责任人" prop="dangerResult"> + <el-select class="input-add" v-model="reportForm.dangerResult" placeholder="请选择整改责任人" clearable filterable> + <el-option v-for="item in RFIDList" :key="item.id" :label="item.rfidName" :value="item.id"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" class="mb20"> + <el-form-item label="整改期限" prop="dangerResult"> + <el-select class="input-add" v-model="reportForm.dangerResult" placeholder="请选择整改期限" clearable filterable> + <el-option v-for="item in RFIDList" :key="item.id" :label="item.rfidName" :value="item.id"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" class="mb20"> + <el-form-item label="整改资金" prop="dangerResult"> + <el-select class="input-add" v-model="reportForm.cost" placeholder="请选择整改资金"> </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12"> + <el-form-item label="整改内容" prop="rectifyDesc"> + <el-input class="input-add" type="textarea" :rows="2" style="padding-bottom: 10px" v-model.trim="reportForm.rectifyDesc" placeholder="请输入整改内容"></el-input> + </el-form-item> + </el-col> + </el-row> + </el-tab-pane> + </el-tabs> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="isShowReportDialog = !isShowReportDialog" size="default">取 消</el-button> + <el-button type="primary" @click="submitReport" v-throttle size="default">确 定</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script lang="ts"> +import { facilityAreaApi } from '/@/api/intellectInspectSystem/facilityAreaManage'; + +interface stateType { + isShowReportDialog: Boolean; + reportForm: { + dangerDesc: string | null; + depId: number | null; + produceDeviceId: number | null; + riskUnitId: number | null; + dangerSource: number | null; + dangerLevel: number | null; + dangerType: number | null; + dangerReason: string | null; + dangerResult: number | null; + rectifyType: number | null; + liablePersonId: number | null; + rectifyTime: string | null; + cost: number | null; + rectifyDesc: string | null; + }; + title: string; + activeNameOne: string; + activeNameTwo: string; + reportFormRules: {}; + departmentList: []; + allProduceDeviceData: []; + allSafetyRiskUnitData: Array<safetyRiskUnit>; + safetyRiskUnitData: Array<safetyRiskUnit>; + dangerLevelList: Array<enumType>; + dangerSourceList: Array<enumType>; + dangerResultList: Array<enumType>; + dangerTypeList: Array<enumType>; +} +interface enumType { + id: number; + name: string; +} +interface safetyRiskUnit { + produceDeviceId: number; +} +import { reactive, toRefs, ref } from 'vue'; +import { ElMessage } from 'element-plus'; +import { hiddenReportApi } from '/@/api/doublePreventSystem/report'; +export default { + name: 'reportDialog', + setup(props: any, context: any) { + const reportFormRef = ref(); + const state = reactive<stateType>({ + title: '', + activeNameOne: 'hiddenInfo', + activeNameTwo: 'rectifyInfo', + isShowReportDialog: false, + departmentList: [], + allProduceDeviceData: [], + allSafetyRiskUnitData: [], + safetyRiskUnitData: [], + dangerLevelList: [ + { id: 1, name: '一般隐患' }, + { id: 2, name: '重大隐患' } + ], + dangerSourceList: [ + { id: 1, name: '日常排查' }, + { id: 2, name: '综合性排查' }, + { id: 3, name: '专业性排查' }, + { id: 4, name: '季节性排查' }, + { id: 5, name: '重点时段及节假日前排查' }, + { id: 6, name: '事故类比排查' }, + { id: 7, name: '复产复工前排查' }, + { id: 8, name: '外聘专家诊断式排查' }, + { id: 9, name: '管控措施失效' }, + { id: 10, name: '其他' } + ], + dangerResultList: [ + { id: 1, name: '无' }, + { id: 2, name: '轻伤' }, + { id: 3, name: '重伤' }, + { id: 4, name: '死亡' } + ], + dangerTypeList: [ + { id: 1, name: '安全' }, + { id: 2, name: '工艺' }, + { id: 3, name: '电气' }, + { id: 4, name: '仪表' }, + { id: 5, name: '消防' }, + { id: 6, name: '总图' }, + { id: 7, name: '设备' }, + { id: 8, name: '其他' } + ], + reportForm: { + dangerDesc: null, + depId: null, + produceDeviceId: null, + riskUnitId: null, + dangerSource: null, + dangerLevel: null, + dangerType: null, + dangerReason: null, + dangerResult: null, + rectifyType: null, + liablePersonId: null, + rectifyTime: null, + cost: null, + rectifyDesc: null + }, + reportFormRules: { + dangerDesc: [{ required: true, message: '请填写隐患情况描述', trigger: 'blur' }], + depId: [{ required: true, message: '请选择隐患所属部门', trigger: 'change' }], + produceDeviceId: [{ required: true, message: '请选择生产装置', trigger: 'change' }] + } + }); + + //打开模态框 + const openReportDialog = (type: string, value: { id: number }, departmentList: [], allProduceDeviceData: [], allSafetyRiskUnitData: []) => { + state.isShowReportDialog = true; + state.departmentList = departmentList; + state.allProduceDeviceData = JSON.parse(JSON.stringify(allProduceDeviceData)); + state.allSafetyRiskUnitData = allSafetyRiskUnitData; + setTimeout(() => { + reportFormRef.value.clearValidate(); + }); + if (type === '新增') { + state.title = '新增隐患'; + state.reportForm = { + dangerDesc: null, + depId: null, + produceDeviceId: null, + riskUnitId: null, + dangerSource: null, + dangerLevel: null, + dangerType: null, + dangerReason: null, + dangerResult: null, + rectifyType: null, + liablePersonId: null, + rectifyTime: null, + cost: null, + rectifyDesc: null + }; + } else { + state.title = '修改隐患'; + state.reportForm = JSON.parse(JSON.stringify(value)); + } + }; + + //新增修改提交 + const submitReport = async () => { + reportFormRef.value.validate(async (valid: Boolean) => { + if (valid) { + if (state.title === '新增隐患') { + let res = await hiddenReportApi().addHiddenReport(state.reportForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '隐患新增成功', + duration: 2000 + }); + state.isShowReportDialog = false; + context.emit('refreshReport'); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } else { + let res = await hiddenReportApi().modHiddenReport(state.reportForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '隐患修改成功', + duration: 2000 + }); + state.isShowReportDialog = false; + context.emit('refreshReport'); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } + } else { + ElMessage({ + type: 'warning', + message: '请完善基本信息' + }); + } + }); + }; + + const changeUnit = () => { + state.reportForm.riskUnitId = null; + state.safetyRiskUnitData = state.allSafetyRiskUnitData.filter((item) => item.produceDeviceId === state.reportForm.produceDeviceId); + }; + + return { + ...toRefs(state), + changeUnit, + reportFormRef, + submitReport, + openReportDialog + }; + } +}; +</script> + +<style scoped> +:deep(.el-dialog__header) { + padding-bottom: 0px !important; +} +</style> diff --git a/src/views/doublePrevent/riskLevel/map/index.vue b/src/views/doublePrevent/riskLevel/map/index.vue new file mode 100644 index 0000000..45cd6da --- /dev/null +++ b/src/views/doublePrevent/riskLevel/map/index.vue @@ -0,0 +1,261 @@ +<template> + <div class="system-role-container"> + <el-card shadow="hover"> + <div class="system-user-search mb15"> + <div class="basic-line"> + <span>整改类型:</span> + <el-select class="input-box" v-model="rectifyData.params.rectifyType" placeholder="整改类型" filterable> + <el-option v-for="item in dangerLevelList" :key="item.id" :label="item.name" :value="item.id"></el-option> + </el-select> + </div> + <div class="basic-line"> + <span>整改单位:</span> + <el-select class="input-box" v-model="rectifyData.params.constructionUnit" placeholder="整改单位" filterable> + <el-option v-for="item in dangerSourceList" :key="item.id" :label="item.name" :value="item.id"></el-option> + </el-select> + </div> + <div class="basic-line"> + <span>隐患管理:</span> + <el-select class="input-box" v-model="rectifyData.params.dangerManagerId" placeholder="隐患管理" filterable> + <el-option v-for="item in dangerStatusList" :key="item.id" :label="item.name" :value="item.id"></el-option> + </el-select> + </div> + + <el-button size="default" type="primary" class="ml10" v-throttle @click="handleSearch"> + <el-icon> + <ele-Search /> + </el-icon> + 查询 + </el-button> + </div> + <el-table :data="rectifyData.data" style="width: 100%" fit highlight-current-row> + <el-table-column type="index" label="序号" width="60" /> + <el-table-column prop="rectifyDesc" label="整改内容说明" show-overflow-tooltip min-width="150px"></el-table-column> + <el-table-column prop="rectifyTime" label="整改期限" show-overflow-tooltip min-width="150px"></el-table-column> + <el-table-column prop="rectifyType" label=" 整改类型" show-overflow-tooltip min-width="150px"></el-table-column> + <el-table-column prop="liablePerson" label="整改责任人" show-overflow-tooltip min-width="150px"></el-table-column> + <el-table-column prop="cost" label="整改资金" show-overflow-tooltip min-width="150px"></el-table-column> + <el-table-column prop="createByUserName" label="创建人" show-overflow-tooltip min-width="150px"></el-table-column> + <el-table-column prop="gmtCreate" label="创建时间" show-overflow-tooltip min-width="200px"></el-table-column> + <el-table-column prop="lastEditUserName" label="最后修改人" show-overflow-tooltip min-width="150px"></el-table-column> + <el-table-column prop="gmtModitify" label="最后修改时间" show-overflow-tooltip min-width="200px"></el-table-column> + <el-table-column label="操作" width="250" fixed="right" align="center"> + <template #default="scope"> + <el-button size="small" text type="primary" :icon="Edit" @click="onOpenDialogRef('修改', scope.row)">修改</el-button> + <el-button size="small" text type="danger" :icon="Delete" @click="onDelProductionDevice(scope.row)">删除</el-button> + </template> + </el-table-column> + </el-table> + <br /> + <el-pagination @size-change="onHandleSizeChange" @current-change="onHandleCurrentChange" :pager-count="5" :page-sizes="[10, 20, 30]" v-model:current-page="rectifyData.params.pageIndex" background v-model:page-size="rectifyData.params.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="rectifyData.total" class="page-position"> </el-pagination> + <br /> + <br /> + </el-card> + <rectifyDialog ref="rectifyDialogRef" @refreshrectify="initRectifyTableData" /> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, onMounted, ref, defineComponent } from 'vue'; +import { ElMessageBox, ElMessage } from 'element-plus'; +import rectifyDialog from './components/rectifyDialog.vue'; +import { Edit, Delete } from '@element-plus/icons-vue'; +import { hiddenRectifyApi } from '/@/api/doublePreventSystem/rectify'; +import { departmentApi } from '/@/api/systemManage/department'; +import { productionDeviceApi } from '/@/api/doublePreventSystem/productionDevice'; + +// 定义接口来定义对象的类型 +interface TableData { + quota: string; + quotaUnit: string; + quotaType: string; + createUserName: string; + gmtCreate: string; + lastEditUserName: string; + gmtModitify: string; +} +interface TableDataState { + rectifyData: { + data: Array<TableData>; + total: number; + loading: boolean; + params: { + pageIndex: number; + pageSize: number; + rectifyType: number | null; + constructionUnit: string | null; + dangerManagerId: number | null; + }; + }; + dangerLevelList: Array<enumType>; + dangerSourceList: Array<enumType>; + dangerStatusList: Array<enumType>; + dangerTypeList: Array<enumType>; + departmentList: []; + allProduceDeviceData: []; +} +interface enumType { + id: number; + name: string; +} + +export default defineComponent({ + name: 'rectify', + components: { rectifyDialog, Edit, Delete }, + setup() { + const rectifyDialogRef = ref(); + const state = reactive<TableDataState>({ + rectifyData: { + data: [], + total: 0, + loading: false, + params: { + pageIndex: 1, + pageSize: 10, + rectifyType: null, + constructionUnit: null, + dangerManagerId: null + } + }, + departmentList: [], + dangerLevelList: [ + { id: 1, name: '一般隐患' }, + { id: 2, name: '重大隐患' } + ], + dangerSourceList: [ + { id: 1, name: '日常排查' }, + { id: 2, name: '综合性排查' }, + { id: 3, name: '专业性排查' }, + { id: 4, name: '季节性排查' }, + { id: 5, name: '重点时段及节假日前排查' }, + { id: 6, name: '事故类比排查' }, + { id: 7, name: '复产复工前排查' }, + { id: 8, name: '外聘专家诊断式排查' }, + { id: 9, name: '管控措施失效' }, + { id: 10, name: '其他' } + ], + dangerStatusList: [ + { id: 1, name: '整改中' }, + { id: 2, name: '待验收' }, + { id: 3, name: '已验收' } + ], + dangerTypeList: [ + { id: 1, name: '安全' }, + { id: 2, name: '工艺' }, + { id: 3, name: '电气' }, + { id: 4, name: '仪表' }, + { id: 5, name: '消防' }, + { id: 6, name: '总图' }, + { id: 7, name: '设备' }, + { id: 8, name: '其他' } + ], + allProduceDeviceData: [] + }); + // 初始化表格数据 + const initRectifyTableData = async () => { + let res = await hiddenRectifyApi().getHiddenRectifyList(state.rectifyData.params); + if (res.data.code === '200') { + state.rectifyData.data = res.data.data; + state.rectifyData.total = res.data.count; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + //获取生产装置列表 + const getAllProduceDeviceData = async () => { + let res = await productionDeviceApi().getAllProductionDeviceList(); + if (res.data.code === '200') { + state.allProduceDeviceData = res.data.data; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + //获取部门列表 + const getDepartmentData = async () => { + let res = await departmentApi().getDepartmentList(); + if (res.data.code === '200') { + state.departmentList = res.data.data; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 打开弹窗 + const onOpenDialogRef = (type: string, value: any) => { + rectifyDialogRef.value.openrectifyDialog(type, value, state.departmentList, state.allProduceDeviceData); + }; + // 删除 + const onDelProductionDevice = (row: any) => { + ElMessageBox.confirm(`此操作将永久删除该巡检点:“${row.code}”,是否继续?`, '提示', { + confirmButtonText: '确认', + cancelButtonText: '取消', + type: 'warning' + }) + .then(async () => { + let res = await hiddenRectifyApi().deleteHiddenRectify({ id: row.id }); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + duration: 2000, + message: '删除成功' + }); + await initRectifyTableData(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }) + .catch(() => {}); + }; + + const handleSearch = () => { + initRectifyTableData(); + }; + // 分页改变 + const onHandleSizeChange = (val: number) => { + state.rectifyData.params.pageSize = val; + initRectifyTableData(); + }; + // 分页改变 + const onHandleCurrentChange = (val: number) => { + state.rectifyData.params.pageIndex = val; + initRectifyTableData(); + }; + // 页面加载时 + onMounted(() => { + initRectifyTableData(); + getDepartmentData(); + getAllProduceDeviceData(); + }); + + return { + Edit, + Delete, + handleSearch, + onOpenDialogRef, + onHandleSizeChange, + onDelProductionDevice, + onHandleCurrentChange, + rectifyDialog, + rectifyDialogRef, + initRectifyTableData, + ...toRefs(state) + }; + } +}); +</script> + +<style scoped></style> diff --git a/src/views/doublePrevent/riskLevel/riskCheckUnit/components/checkUnitDialog.vue b/src/views/doublePrevent/riskLevel/riskCheckUnit/components/checkUnitDialog.vue new file mode 100644 index 0000000..81ab0c6 --- /dev/null +++ b/src/views/doublePrevent/riskLevel/riskCheckUnit/components/checkUnitDialog.vue @@ -0,0 +1,260 @@ +<template> + <div class="system-add-menu-container"> + <el-dialog :title="title" v-model="isShowCheckUnitDialog" append-to-body :close-on-click-modal="false" width="50%"> + <el-divider></el-divider> + <div class="checkUnit-form"> + <el-form :model="checkUnitForm" :rules="checkUnitFormRules" ref="checkUnitFormRef" size="default" label-width="120px"> + <el-row :gutter="35"> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" class="mb20"> + <el-form-item label="任务单元名称" prop="taskUnitName"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="checkUnitForm.taskUnitName" placeholder="请输入任务单元名称" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" class="mb20"> + <el-form-item label="任务单元说明" prop="note"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="checkUnitForm.note" placeholder="请输入任务单元说明" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" class="mb20" v-show="personTime"> + <el-form-item label="创建人" prop="location"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="checkUnitForm.createByUserName" placeholder="请输入区域位置"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" class="mb20" v-show="personTime"> + <el-form-item label="创建时间" prop="location"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="checkUnitForm.gmtCreate" placeholder="请输入区域位置"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" class="mb20" v-show="personTime"> + <el-form-item label="最后修改人" prop="location"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="checkUnitForm.lastEditUserName" placeholder="请输入区域位置"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" class="mb20" v-show="personTime"> + <el-form-item label="最后修改时间" prop="location"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="checkUnitForm.gmtModitify" placeholder="请输入区域位置"></el-input> + </el-form-item> + </el-col> + </el-row> + </el-form> + </div> + + <div class="checkUnit-point"> + <el-tabs class="active" v-model="activeName"> + <el-tab-pane label="检查项信息" name="checkUnit"> + <div class="filter-container"> + <el-button size="default" :disabled="!disabled" type="success" @click="onOpenDialogRef('新增', '')"> + <el-icon> + <ele-FolderAdd /> + </el-icon> + 选择风险管控措施 + </el-button> + </div> + + <el-table :data="measureData" border fit highlight-current-row style="width: 100%"> + <el-table-column type="index" label="序号" width="60" /> + <el-table-column prop="checkContent" label="管控内容" show-overflow-tooltip align="center"></el-table-column> + <el-table-column label="操作" width="150" align="center"> + <template #default="scope"> + <el-button size="small" text :disabled="!disabled" type="danger" @click="onDelCheckUnit(scope.$index, scope.row)">删除</el-button> + </template> + </el-table-column> + </el-table> + </el-tab-pane> + </el-tabs> + </div> + + <template #footer> + <span class="dialog-footer" v-show="disabled"> + <el-button @click="isShowCheckUnitDialog = !isShowCheckUnitDialog" size="default">取 消</el-button> + <el-button type="primary" @click="submitCheckUnit" v-throttle size="default">确 定</el-button> + </span> + </template> + </el-dialog> + <el-dialog title="选择风险管控措施" v-model="isShowSelectMeasureControlDialog" append-to-body :close-on-click-modal="false" width="70%"> + <select-measure-control-dialog ref="SelectMeasureControlDialogRef" @receiveRiskControlId="receiveRiskControlId"></select-measure-control-dialog> + </el-dialog> + </div> +</template> + +<script lang="ts"> +import SelectMeasureControlDialog from './selectMeasureControlDialog.vue'; +import { reactive, toRefs, ref } from 'vue'; +import { checkUnitApi } from '/@/api/doublePreventSystem/checkUnit'; +import { ElMessage } from 'element-plus'; +interface stateType { + isShowCheckUnitDialog: Boolean; + disabled: Boolean; + personTime: Boolean; + isShowSelectMeasureControlDialog: Boolean; + checkUnitForm: { + taskUnitName: string | null; + note: string | null; + measureList: []; + }; + title: string; + activeName: string; + measureData: []; + checkUnitData: []; + checkUnitFormRules: {}; +} + +export default { + name: 'checkUnitDialog', + components: { SelectMeasureControlDialog }, + setup(props: any, context: any) { + const checkUnitFormRef = ref(); + const riskControlMeasureDialogRef = ref(); + const state = reactive<stateType>({ + title: '', + disabled: false, + personTime: false, + activeName: 'checkUnit', + measureData: [], + checkUnitData: [], + isShowCheckUnitDialog: false, + isShowSelectMeasureControlDialog: false, + checkUnitForm: { + taskUnitName: null, + note: null, + measureList: [] + }, + checkUnitFormRules: { + taskUnitName: [{ required: true, message: '请填写任务单元名称', trigger: 'blur' }], + note: [{ required: true, message: '请填写任务单元说明', trigger: 'change' }] + } + }); + + //打开模态框 + const openCheckUnitDialog = (type: string, value: object) => { + state.isShowCheckUnitDialog = true; + setTimeout(() => { + checkUnitFormRef.value.clearValidate(); + }); + if (type === '新增') { + state.disabled = true; + state.personTime = false; + state.title = '新增隐患排查单元'; + state.measureData = []; + state.checkUnitForm = { + taskUnitName: null, + note: null, + measureList: [] + }; + } else if (type === '查看') { + state.disabled = false; + state.personTime = true; + state.title = '查看隐患排查单元'; + state.checkUnitForm = JSON.parse(JSON.stringify(value)); + state.measureData = state.checkUnitForm.measureList; + } else { + state.disabled = true; + state.personTime = false; + state.title = '修改隐患排查单元'; + state.checkUnitForm = JSON.parse(JSON.stringify(value)); + state.measureData = state.checkUnitForm.measureList; + } + }; + + const onOpenDialogRef = () => { + state.isShowSelectMeasureControlDialog = true; + }; + + const onDelCheckUnit = (value: number, scope: object) => { + state.measureData.splice(value, 1); + }; + + const receiveRiskControlId = (value: []) => { + state.isShowSelectMeasureControlDialog = false; + state.measureData = value; + state.checkUnitForm.measureList = JSON.parse( + JSON.stringify( + value.map((item: { id: number }) => { + return item.id; + }) + ) + ); + }; + + //新增修改提交 + const submitCheckUnit = async () => { + checkUnitFormRef.value.validate(async (valid: Boolean) => { + if (valid) { + if (state.title === '新增隐患排查单元') { + let res = await checkUnitApi().addCheckUnit(state.checkUnitForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '隐患排查单元新增成功', + duration: 2000 + }); + state.isShowCheckUnitDialog = false; + context.emit('refreshCheckUnit'); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } else { + let res = await checkUnitApi().modCheckUnit(state.checkUnitForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '隐患排查单元修改成功', + duration: 2000 + }); + state.isShowCheckUnitDialog = false; + context.emit('refreshCheckUnit'); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } + } else { + ElMessage({ + type: 'warning', + message: '请完善基本信息' + }); + } + }); + }; + + return { + ...toRefs(state), + checkUnitFormRef, + submitCheckUnit, + onDelCheckUnit, + onOpenDialogRef, + openCheckUnitDialog, + receiveRiskControlId, + riskControlMeasureDialogRef + }; + } +}; +</script> + +<style scoped> +::v-deep.el-divider--horizontal { + margin-top: 0px !important; +} + +::v-deep.el-dialog__body { + padding-top: 10px !important; +} +.filter-container { + padding: 10px 0px; +} +:deep(.el-textarea.is-disabled .el-textarea__inner) { + background-color: var(--el-card-bg-color); + color: var(--el-input-text-color, var(--el-text-color-regular)); +} +:deep(.el-input.is-disabled .el-input__inner) { + color: var(--el-input-text-color, var(--el-text-color-regular)); +} +:deep(.el-input.is-disabled .el-input__wrapper) { + background-color: var(--el-card-bg-color); +} +</style> diff --git a/src/views/doublePrevent/riskLevel/riskCheckUnit/components/selectMeasureControlDialog.vue b/src/views/doublePrevent/riskLevel/riskCheckUnit/components/selectMeasureControlDialog.vue new file mode 100644 index 0000000..df01f4a --- /dev/null +++ b/src/views/doublePrevent/riskLevel/riskCheckUnit/components/selectMeasureControlDialog.vue @@ -0,0 +1,219 @@ +<template> + <div class="system-role-container"> + <el-card shadow="hover"> + <div class="system-user-search mb15"> + <div class="basic-line"> + <span>管控方式:</span> + <el-select class="input-box" v-model="riskControlMeasureData.params.controlType" placeholder="管控方式" clearable> + <el-option v-for="item in controlTypeList" :key="item.id" :label="item.name" :value="item.id"></el-option> + </el-select> + </div> + <div class="basic-line"> + <span>安全风险事件:</span> + <el-select class="input-box" v-model="riskControlMeasureData.params.riskEventId" placeholder="安全风险事件" clearable> + <el-option v-for="item in allSafetyRiskEventData" :key="item.id" :label="item.riskEventName" :value="item.id"></el-option> + </el-select> + </div> + <el-button size="default" type="primary" class="ml10" v-throttle @click="handleSearch"> + <el-icon> + <ele-Search /> + </el-icon> + 查询 + </el-button> + </div> + <el-table + @selection-change="handleSelectionChange" + ref="table" + :row-key="getRowKey" + :data="riskControlMeasureData.data" + style="width: 100%" + > + <el-table-column type="selection" :reserve-selection="true" width="55"></el-table-column> + <el-table-column prop="riskEventName" label="安全风险事件名称" show-overflow-tooltip></el-table-column> + <el-table-column prop="controlMeasureCode" label="风控措施编码" show-overflow-tooltip></el-table-column> + <el-table-column prop="controlType" label="管控方式" show-overflow-tooltip> + <template #default="scope"> + {{ parseNumber(scope.row.controlType, '管控方式') }} + </template> + </el-table-column> + <el-table-column prop="checkContent" label="管控内容" show-overflow-tooltip></el-table-column> + <el-table-column prop="classify1" label="管控措施分类1" show-overflow-tooltip> + <template #default="scope"> + {{ parseNumber(scope.row.classify1, '管控措施分类1') }} + </template> + </el-table-column> + <el-table-column prop="classify2" label="管控措施分类2" show-overflow-tooltip> + <template #default="scope"> + {{ parseNumber(scope.row.classify2, '管控措施分类2') }} + </template> + </el-table-column> + <el-table-column prop="classify3" label="管控措施分类3" show-overflow-tooltip></el-table-column> + <el-table-column prop="measureDesc" label="措施说明" show-overflow-tooltip></el-table-column>> + <el-table-column label="操作" width="150"> + <template #default="scope"> + <el-button type="text" @click="giveValue(scope.row)">选择 </el-button> + </template> + </el-table-column> + </el-table> + </el-card> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, onMounted, ref } from 'vue'; +import { ElMessageBox, ElMessage } from 'element-plus'; +import { riskControlMeasureApi } from '/@/api/doublePreventSystem/riskControlMeasure/index.ts'; +import { safetyRiskEventApi } from '/@/api/doublePreventSystem/safetyRiskEvent'; + +// 定义接口来定义对象的类型 +interface TableData { + roleName: string; + roleSign: string; + describe: string; + sort: number; + status: boolean; + createTime: string; +} +interface TableDataState { + isShowSelectMeasureControlDialog: boolean; + riskControlMeasureIdList: Array<riskControlMeasure>; + riskControlMeasureData: { + data: Array<TableData>; + total: number; + loading: boolean; + params: { + pageIndex: number; + pageSize: number; + controlType: number | null; + riskEventId: number | null; + }; + }; + controlTypeList: Array<controlTypeType>; + classifyOneList: Array<classifyOneType>; + classifyTwoList: Array<classifyOneType>; +} +interface controlTypeType { + id: number; + name: string; +} +interface classifyOneType { + id: number; + riskMeasureName: string; +} + +interface riskControlMeasure {} +export default { + name: 'selectMeasureControlDialog', + components: {}, + setup(props: any, context: any) { + const riskControlMeasureDialogRef = ref(); + const state = reactive<TableDataState>({ + isShowSelectMeasureControlDialog: false, + riskControlMeasureIdList: [], + riskControlMeasureData: { + data: [], + total: 0, + loading: false, + params: { + pageIndex: 1, + pageSize: 10, + controlType: null, + riskEventId: null + } + }, + controlTypeList: [ + { id: 1, name: '自动化监控' }, + { id: 2, name: '隐患排查' } + ], + classifyOneList: [], + classifyTwoList: [] + }); + + // 初始化表格数据 + const initRiskControlMeasureData = async () => { + let res = await riskControlMeasureApi().getAllRiskControlMeasureList(); + if (res.data.code === '200') { + state.riskControlMeasureData.data = res.data.data; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + //获取管控措施分类 + const getClassify = async () => { + let res = await riskControlMeasureApi().getClassifyData(); + if (res.data.code === '200') { + state.classifyOneList = res.data.data.filter((item: any) => item.parentId === null); + state.classifyTwoList = res.data.data.filter((item: any) => item.parentId !== null); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + const parseNumber = (value: string | number, type: string) => { + if (type === '管控方式') { + return state.controlTypeList.find((item) => item.id === value)?.name; + } else if (type === '管控措施分类1') { + return state.classifyOneList.find((item) => item.id === value)?.riskMeasureName; + } else { + return state.classifyTwoList.find((item) => item.id === value)?.riskMeasureName; + } + }; + + const handleSearch = () => { + initRiskControlMeasureData(); + }; + + // 分页改变 + const onHandleSizeChange = (val: number) => { + state.riskControlMeasureData.params.pageSize = val; + initRiskControlMeasureData(); + }; + + // 分页改变 + const onHandleCurrentChange = (val: number) => { + state.riskControlMeasureData.params.pageIndex = val; + initRiskControlMeasureData(); + }; + + const handleSelectionChange = (val: []) => { + state.riskControlMeasureIdList = val; + }; + + const getRowKey = (value: { id: number }) => { + return value.id; + }; + + const giveValue = () => { + context.emit('receiveRiskControlId', state.riskControlMeasureIdList); + }; + + // 页面加载时 + onMounted(() => { + initRiskControlMeasureData(); + getClassify(); + }); + + return { + handleSearch, + parseNumber, + getRowKey, + giveValue, + handleSelectionChange, + onHandleSizeChange, + onHandleCurrentChange, + riskControlMeasureDialogRef, + initRiskControlMeasureData, + ...toRefs(state) + }; + } +}; +</script> + +<style scoped></style> diff --git a/src/views/doublePrevent/riskLevel/riskCheckUnit/index.vue b/src/views/doublePrevent/riskLevel/riskCheckUnit/index.vue new file mode 100644 index 0000000..ad9a72f --- /dev/null +++ b/src/views/doublePrevent/riskLevel/riskCheckUnit/index.vue @@ -0,0 +1,194 @@ +<template> + <div class="system-role-container"> + <el-card shadow="hover"> + <div class="system-user-search mb15"> + <!-- <div class="basic-line">--> + <!-- <span>风险等级:</span>--> + <!-- <el-select v-model="checkUnitData.params.riskLevel" clearable filterable class="input-box" placeholder="请选择风险等级">--> + <!-- <el-option v-for="item in levelList" :key="item.id" :label="item.name" :value="item.id"></el-option>--> + <!-- </el-select>--> + <!-- </div>--> + <!-- <div class="basic-line">--> + <!-- <span>部门:</span>--> + <!-- <el-cascader :options="departmentList" :props="{ emitPath: false, checkStrictly: true, value: 'depId', label: 'depName' }" placeholder="请选择部门" clearable filterable class="input-box" v-model="checkUnitData.params.depId"> </el-cascader>--> + <!-- </div>--> + <div class="basic-line"> + <span>任务单元名称:</span> + <el-input class="input-box" v-model="checkUnitData.params.taskUnitName" placeholder="任务单元名称" clearable> </el-input> + </div> + <el-button size="default" type="primary" class="ml10" v-throttle @click="handleSearch"> + <el-icon> + <ele-Search /> + </el-icon> + 查询 + </el-button> + <el-button size="default" type="success" class="ml10" @click="onOpenDialogRef('新增', '')"> + <el-icon> + <ele-FolderAdd /> + </el-icon> + 新增排查单元 + </el-button> + </div> + <el-table :data="checkUnitData.data" style="width: 100%"> + <el-table-column type="index" label="序号" width="60" /> + <el-table-column prop="taskUnitName" label="任务单元名称" show-overflow-tooltip></el-table-column> + <el-table-column prop="note" label="任务单元说明" show-overflow-tooltip></el-table-column> + <el-table-column prop="createByUserName" label="创建人" show-overflow-tooltip></el-table-column> + <el-table-column prop="gmtCreate" label="创建时间" show-overflow-tooltip></el-table-column> + <el-table-column prop="lastEditUserName" label="最后修改人" show-overflow-tooltip></el-table-column> + <el-table-column prop="gmtModitify" label="最后修改时间" show-overflow-tooltip></el-table-column> + <el-table-column label="操作" width="200" align="center"> + <template #default="scope"> + <el-button size="small" text type="primary" :icon="View" @click="onOpenDialogRef('查看', scope.row)">查看</el-button> + <el-button size="small" text type="primary" :icon="Edit" @click="onOpenDialogRef('修改', scope.row)">修改</el-button> + <el-button size="small" text type="danger" :icon="Delete" @click="onDelcheckUnit(scope.row)">删除</el-button> + </template> + </el-table-column> + </el-table> + <br /> + <el-pagination @size-change="onHandleSizeChange" @current-change="onHandleCurrentChange" :pager-count="5" :page-sizes="[10, 20, 30]" v-model:current-page="checkUnitData.params.pageIndex" background v-model:page-size="checkUnitData.params.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="checkUnitData.total" class="page-position"> </el-pagination> + <br /> + <br /> + </el-card> + <checkUnitDialog ref="checkUnitDialogRef" @refreshCheckUnit="initCheckUnitTableData" /> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, onMounted, ref, defineComponent } from 'vue'; +import { ElMessageBox, ElMessage } from 'element-plus'; +import checkUnitDialog from './components/checkUnitDialog.vue'; +import { checkUnitApi } from '/@/api/doublePreventSystem/checkUnit/index.ts'; +import { Edit, Delete, View } from '@element-plus/icons-vue'; + +// 定义接口来定义对象的类型 +interface TableData { + roleName: string; + roleSign: string; + describe: string; + sort: number; + status: boolean; + createTime: string; +} +interface TableDataState { + checkUnitData: { + data: Array<TableData>; + total: number; + loading: boolean; + params: { + pageIndex: number; + pageSize: number; + taskUnitName: number | null; + }; + }; +} + +export default defineComponent({ + name: 'index', + components: { checkUnitDialog, Edit, Delete, View }, + setup() { + const checkUnitDialogRef = ref(); + const state = reactive<TableDataState>({ + checkUnitData: { + data: [], + total: 0, + loading: false, + params: { + pageIndex: 1, + pageSize: 10, + taskUnitId: null + } + } + }); + // 初始化表格数据 + const initCheckUnitTableData = async () => { + let res = await checkUnitApi().getCheckUnitList(state.checkUnitData.params); + if (res.data.code === '200') { + state.checkUnitData.data = res.data.data; + state.checkUnitData.total = res.data.count; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 打开生产装置弹窗 + const onOpenDialogRef = (type: string, value: any) => { + checkUnitDialogRef.value.openCheckUnitDialog(type, value); + }; + // 删除角色 + const onDelCheckUnit = (row: any) => { + ElMessageBox.confirm(`此操作将永久删除该条生产装置:“${row.produceDeviceName}”,是否继续?`, '提示', { + confirmButtonText: '确认', + cancelButtonText: '取消', + type: 'warning' + }) + .then(async () => { + let res = await checkUnitApi().deleteCheckUnit({ id: row.id }); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + duration: 2000, + message: '删除成功' + }); + await initCheckUnitTableData(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }) + .catch(() => {}); + }; + + const handleSearch = () => { + initCheckUnitTableData(); + }; + // 分页改变 + const onHandleSizeChange = (val: number) => { + state.checkUnitData.params.pageSize = val; + initCheckUnitTableData(); + }; + // 分页改变 + const onHandleCurrentChange = (val: number) => { + state.checkUnitData.params.pageIndex = val; + initCheckUnitTableData(); + }; + // 页面加载时 + onMounted(() => { + initCheckUnitTableData(); + }); + + return { + Edit, + Delete, + View, + handleSearch, + onOpenDialogRef, + onHandleSizeChange, + onDelCheckUnit, + onHandleCurrentChange, + checkUnitDialog, + checkUnitDialogRef, + initCheckUnitTableData, + ...toRefs(state) + }; + } +}); +</script> + +<style scoped> +:deep(.el-textarea.is-disabled .el-textarea__inner) { + background-color: var(--el-card-bg-color); + color: var(--el-input-text-color, var(--el-text-color-regular)); +} +:deep(.el-input.is-disabled .el-input__inner) { + color: var(--el-input-text-color, var(--el-text-color-regular)); +} +:deep(.el-input.is-disabled .el-input__wrapper) { + background-color: var(--el-card-bg-color); +} +</style> diff --git a/src/views/doublePrevent/riskLevel/unit/components/safetyRiskAnalyseUnitDialog.vue b/src/views/doublePrevent/riskLevel/unit/components/safetyRiskAnalyseUnitDialog.vue new file mode 100644 index 0000000..4723b27 --- /dev/null +++ b/src/views/doublePrevent/riskLevel/unit/components/safetyRiskAnalyseUnitDialog.vue @@ -0,0 +1,227 @@ +<template> + <div class="system-add-menu-container"> + <el-dialog :title="title" v-model="isSafetyRiskAnalyseUnitDialog" width="600px" :close-on-click-modal="false"> + <el-form :model="safetyRiskAnalyseUnitForm" :rules="safetyRiskAnalyseUnitFormRules" ref="safetyRiskAnalyseUnitFormRef" size="default" label-width="180px"> + <el-row :gutter="35"> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="安全风险分析单元名称" prop="riskUnitName"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="safetyRiskAnalyseUnitForm.riskUnitName" placeholder="请输入安全风险分析单元名称"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="安全风险分析对象编码" prop="riskCode"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="safetyRiskAnalyseUnitForm.riskCode" placeholder="请输入安全风险分析对象编码"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="生产装置名称" prop="produceDeviceId"> + <el-select class="input-add" :disabled="!disabled" v-model="safetyRiskAnalyseUnitForm.produceDeviceId" placeholder="请输入生产装置名称" clearable> + <el-option v-for="item in allProduceDeviceData" :key="item.id" :label="item.produceDeviceName" :value="item.id"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="责任部门" prop="liableDepId"> + <el-cascader class="input-add" @change="achieveUserList" :disabled="!disabled" :options="departmentList" :props="{ emitPath: false, checkStrictly: true, value: 'depId', label: 'depName' }" placeholder="请选择部门" clearable filterable style="width: 85%" v-model="safetyRiskAnalyseUnitForm.liableDepId"> </el-cascader> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="责任人" prop="liablePersonId"> + <el-select class="input-add" :disabled="!disabled" v-model="safetyRiskAnalyseUnitForm.liablePersonId" placeholder="请选择责任人" clearable filterable> + <el-option v-for="item in userList" :key="item.uid" :label="item.realName" :value="item.uid"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20" v-show="personTime"> + <el-form-item label="创建人" prop="location"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="safetyRiskAnalyseUnitForm.createByUserName" placeholder="请输入区域位置"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20" v-show="personTime"> + <el-form-item label="创建时间" prop="location"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="safetyRiskAnalyseUnitForm.gmtCreate" placeholder="请输入区域位置"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20" v-show="personTime"> + <el-form-item label="最后修改人" prop="location"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="safetyRiskAnalyseUnitForm.lastEditUserName" placeholder="请输入区域位置"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20" v-show="personTime"> + <el-form-item label="最后修改时间" prop="location"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="safetyRiskAnalyseUnitForm.gmtModitify" placeholder="请输入区域位置"></el-input> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer" v-show="disabled"> + <el-button @click="isSafetyRiskAnalyseUnitDialog = !isSafetyRiskAnalyseUnitDialog" size="default">取 消</el-button> + <el-button type="primary" @click="submitSafetyRiskAnalyseUnitDialog" v-throttle size="default">确 定</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script lang="ts"> +interface stateType { + isSafetyRiskAnalyseUnitDialog: Boolean; + disabled: Boolean; + personTime: Boolean; + safetyRiskAnalyseUnitForm: { + riskCode: string | null; + riskUnitName: string | null; + liablePersonId: number | null; + liableDepId: number | null; + produceDeviceId: number | null; + }; + title: string; + userList: any[]; + departmentList: []; + allProduceDeviceData: []; + safetyRiskAnalyseUnitFormRules: {}; +} +import { reactive, toRefs, ref } from 'vue'; +import { safetyRiskAnalyseUnitApi } from '/@/api/doublePreventSystem/safetyRiskAnalyseUnit'; +import { ElMessage } from 'element-plus'; +import { userApi } from '/@/api/systemManage/user'; +import { getUserByDepartment } from '/@/assets/methods'; +export default { + name: 'productionDeviceDialog', + setup(props: any, context: any) { + const safetyRiskAnalyseUnitFormRef = ref(); + const state = reactive<stateType>({ + title: '', + disabled: false, + personTime: false, + userList: [], + departmentList: [], + allProduceDeviceData: [], + isSafetyRiskAnalyseUnitDialog: false, + safetyRiskAnalyseUnitForm: { + riskCode: null, + riskUnitName: null, + liablePersonId: null, + liableDepId: null, + produceDeviceId: null + }, + safetyRiskAnalyseUnitFormRules: { + riskCode: [{ required: true, message: '请填写安全风险分析对象编码', trigger: 'blur' }], + riskUnitName: [{ required: true, message: '请填写安全风险分析单元名称', trigger: 'blur' }], + liableDepId: [{ required: true, message: '请选择责任部门', trigger: 'change' }], + liablePersonId: [{ required: true, message: '请选择责任人', trigger: 'change' }], + produceDeviceId: [{ required: true, message: '请选择生产装置', trigger: 'change' }] + } + }); + + //打开模态框 + const openSafetyRiskAnalyseUnitDialog = (type: string, value: object, department: [], allProduceDeviceData: []) => { + // console.log(jsonBig.stringify(123124124124214123131)) + state.isSafetyRiskAnalyseUnitDialog = true; + state.allProduceDeviceData = JSON.parse(JSON.stringify(allProduceDeviceData)); + state.departmentList = department; + setTimeout(() => { + safetyRiskAnalyseUnitFormRef.value.clearValidate(); + }); + if (type === '新增') { + state.disabled = true; + state.personTime = false; + state.title = '新增风险分析单元'; + state.safetyRiskAnalyseUnitForm = { + riskCode: null, + riskUnitName: null, + liablePersonId: null, + liableDepId: null, + produceDeviceId: null + }; + } else if (type === '查看') { + state.disabled = false; + state.personTime = true; + state.title = '查看风险分析单元'; + state.safetyRiskAnalyseUnitForm = JSON.parse(JSON.stringify(value)); + } else { + state.disabled = true; + state.personTime = false; + state.title = '修改风险分析单元'; + state.safetyRiskAnalyseUnitForm = JSON.parse(JSON.stringify(value)); + } + }; + + //新增修改提交 + const submitSafetyRiskAnalyseUnitDialog = async () => { + safetyRiskAnalyseUnitFormRef.value.validate(async (valid: Boolean) => { + if (valid) { + if (state.title === '新增风险分析单元') { + let res = await safetyRiskAnalyseUnitApi().addSafetyRiskAnalyseUnit(state.safetyRiskAnalyseUnitForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '风险分析单元新增成功', + duration: 2000 + }); + state.isSafetyRiskAnalyseUnitDialog = false; + context.emit('refreshSafetyRiskAnalyseUnit'); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } else { + let res = await safetyRiskAnalyseUnitApi().modSafetyRiskAnalyseUnit(state.safetyRiskAnalyseUnitForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '风险分析单元修改成功', + duration: 2000 + }); + state.isSafetyRiskAnalyseUnitDialog = false; + context.emit('refreshSafetyRiskAnalyseUnit'); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } + } else { + ElMessage({ + type: 'warning', + message: '请完善基本信息' + }); + } + }); + }; + + const achieveUserList = async () => { + state.safetyRiskAnalyseUnitForm.liablePersonId = null; + const userList: unknown = await getUserByDepartment(state.safetyRiskAnalyseUnitForm.liableDepId); + state.userList = userList as []; + }; + + // //获取用户列表 + // const getUserData = async () => { + // let res = await userApi().getUserLByDepartment(state.safetyRiskAnalyseUnitForm.liableDepId); + // if (res.data.code === '200') { + // state.userList = res.data.data; + // } else { + // ElMessage({ + // type: 'warning', + // message: res.data.msg + // }); + // } + // }; + + return { + ...toRefs(state), + achieveUserList, + safetyRiskAnalyseUnitFormRef, + submitSafetyRiskAnalyseUnitDialog, + openSafetyRiskAnalyseUnitDialog + }; + } +}; +</script> + +<style scoped></style> diff --git a/src/views/doublePrevent/riskLevel/unit/index.vue b/src/views/doublePrevent/riskLevel/unit/index.vue new file mode 100644 index 0000000..ec369c6 --- /dev/null +++ b/src/views/doublePrevent/riskLevel/unit/index.vue @@ -0,0 +1,265 @@ +<template> + <div class="system-role-container"> + <el-card shadow="hover"> + <div class="system-user-search mb15"> + <div class="basic-line"> + <span>责任部门:</span> + <el-cascader @change="achieveUserList" :options="departmentList" :props="{ emitPath: false, checkStrictly: true, value: 'depId', label: 'depName' }" placeholder="责任部门" clearable filterable class="input-box" v-model="safetyRiskAnalyseUnitData.params.liableDepId"> </el-cascader> + </div> + <div class="basic-line"> + <span>责任人:</span> + <el-select v-model="safetyRiskAnalyseUnitData.params.liablePersonId" clearable filterable class="input-box" placeholder="责任人"> + <el-option v-for="item in userList" :key="item.uid" :label="item.realName" :value="item.uid"></el-option> + </el-select> + </div> + <div class="basic-line"> + <span>单元名称:</span> + <el-input v-model="safetyRiskAnalyseUnitData.params.riskUnitName" clearable filterable class="input-box" placeholder="单元名称"> </el-input> + </div> + <el-button size="default" type="primary" class="ml10" v-throttle @click="handleSearch"> + <el-icon> + <ele-Search /> + </el-icon> + 查询 + </el-button> + <el-button size="default" type="success" class="ml10" @click="onOpenDialogRef('新增', '')"> + <el-icon> + <ele-FolderAdd /> + </el-icon> + 新增单元 + </el-button> + </div> + <el-table :data="safetyRiskAnalyseUnitData.data" style="width: 100%"> + <el-table-column type="index" label="序号" width="60" /> + <el-table-column prop="produceDeviceName" label="生产装置名称" show-overflow-tooltip></el-table-column> + <el-table-column prop="riskUnitName" label="安全风险分析单元名称" width="180" show-overflow-tooltip></el-table-column> + <el-table-column prop="riskCode" label="安全风险分析对象编码" width="180" show-overflow-tooltip></el-table-column> + <el-table-column prop="liableDep" label="责任部门" show-overflow-tooltip></el-table-column> + <el-table-column prop="liablePerson" label="责任人" show-overflow-tooltip></el-table-column> + <el-table-column prop="createByUserName" label="创建人" show-overflow-tooltip></el-table-column> + <el-table-column prop="gmtCreate" label="创建时间" show-overflow-tooltip></el-table-column> + <el-table-column prop="lastEditUserName" label="最后修改人" show-overflow-tooltip></el-table-column> + <el-table-column prop="gmtModitify" label="最后修改时间" show-overflow-tooltip></el-table-column> + <el-table-column label="操作" width="200" align="center"> + <template #default="scope"> + <el-button size="small" text type="primary" :icon="View" @click="onOpenDialogRef('查看', scope.row)">查看</el-button> + <el-button size="small" text type="primary" :icon="Edit" @click="onOpenDialogRef('修改', scope.row)">修改</el-button> + <el-button size="small" text type="danger" :icon="Delete" @click="onDelRiskUnit(scope.row)">删除</el-button> + </template> + </el-table-column> + </el-table> + <br /> + <el-pagination @size-change="onHandleSizeChange" @current-change="onHandleCurrentChange" class="page-position" :pager-count="5" :page-sizes="[10, 20, 30]" v-model:current-page="safetyRiskAnalyseUnitData.params.pageIndex" background v-model:page-size="safetyRiskAnalyseUnitData.params.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="safetyRiskAnalyseUnitData.total"> </el-pagination> + <br /> + <br /> + </el-card> + <safetyRiskAnalyseUnitDialog ref="safetyRiskAnalyseUnitDialogRef" @refreshSafetyRiskAnalyseUnit="initSafetyRiskAnalyseUnitData" /> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, onMounted, ref } from 'vue'; +import { ElMessageBox, ElMessage } from 'element-plus'; +import safetyRiskAnalyseUnitDialog from './components/safetyRiskAnalyseUnitDialog.vue'; +import { safetyRiskAnalyseUnitApi } from '/@/api/doublePreventSystem/safetyRiskAnalyseUnit/index.ts'; +import { departmentApi } from '/@/api/systemManage/department'; +import { userApi } from '/@/api/systemManage/user'; +import { productionDeviceApi } from '/@/api/doublePreventSystem/productionDevice'; +import { Edit, Delete, View } from '@element-plus/icons-vue'; + +// 定义接口来定义对象的类型 +interface TableData { + roleName: string; + roleSign: string; + describe: string; + sort: number; + status: boolean; + createTime: string; +} +interface TableDataState { + safetyRiskAnalyseUnitData: { + data: Array<TableData>; + total: number; + loading: boolean; + params: { + pageIndex: number; + pageSize: number; + riskUnitName: string | null; + liableDepId: number | null; + liablePersonId: number | null; + }; + }; + userList: Array<UserState>; + departmentList: Array<DepartmentState>; + allProduceDeviceData: Array<produceDeviceState>; +} +interface produceDeviceState {} +interface DepartmentState {} +interface UserState {} + +export default { + name: 'productionDevice', + components: { safetyRiskAnalyseUnitDialog, Edit, Delete, View }, + setup() { + const safetyRiskAnalyseUnitDialogRef = ref(); + const state = reactive<TableDataState>({ + safetyRiskAnalyseUnitData: { + data: [], + total: 0, + loading: false, + params: { + pageIndex: 1, + pageSize: 10, + riskUnitName: null, + liableDepId: null, + liablePersonId: null + } + }, + userList: [], + departmentList: [], + allProduceDeviceData: [] + }); + // 初始化表格数据 + const initSafetyRiskAnalyseUnitData = async () => { + let res = await safetyRiskAnalyseUnitApi().getSafetyRiskAnalyseUnitList(state.safetyRiskAnalyseUnitData.params); + if (res.data.code === '200') { + state.safetyRiskAnalyseUnitData.data = res.data.data; + state.safetyRiskAnalyseUnitData.total = res.data.count; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + const achieveUserList = () => { + state.safetyRiskAnalyseUnitData.params.liablePersonId = null; + state.userList = []; + getUserData(); + }; + + //获取生产装置列表 + const getAllProduceDeviceData = async () => { + let res = await productionDeviceApi().getAllProductionDeviceList(); + if (res.data.code === '200') { + state.allProduceDeviceData = res.data.data; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + //获取部门列表 + const getDepartmentData = async () => { + let res = await departmentApi().getDepartmentList(); + if (res.data.code === '200') { + state.departmentList = res.data.data; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + //获取用户列表 + const getUserData = async () => { + let res = await userApi().getUserLByDepartment(state.safetyRiskAnalyseUnitData.params.liableDepId); + if (res.data.code === '200') { + state.userList = res.data.data; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 打开生产装置弹窗 + const onOpenDialogRef = (type: string, value: any) => { + safetyRiskAnalyseUnitDialogRef.value.openSafetyRiskAnalyseUnitDialog(type, value, state.departmentList, state.allProduceDeviceData); + }; + + // 删除角色 + const onDelRiskUnit = (row: any) => { + ElMessageBox.confirm(`此操作将永久删除该条安全风险分析单元:“${row.riskUnitName}”,是否继续?`, '提示', { + confirmButtonText: '确认', + cancelButtonText: '取消', + type: 'warning' + }) + .then(async () => { + let res = await safetyRiskAnalyseUnitApi().deleteSafetyRiskAnalyseUnit({ id: row.id }); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + duration: 2000, + message: '删除成功' + }); + await initSafetyRiskAnalyseUnitData(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }) + .catch(() => {}); + }; + + const handleSearch = () => { + initSafetyRiskAnalyseUnitData(); + }; + + // 分页改变 + const onHandleSizeChange = (val: number) => { + state.safetyRiskAnalyseUnitData.params.pageSize = val; + initSafetyRiskAnalyseUnitData(); + }; + + // 分页改变 + const onHandleCurrentChange = (val: number) => { + state.safetyRiskAnalyseUnitData.params.pageIndex = val; + initSafetyRiskAnalyseUnitData(); + }; + + // 页面加载时 + onMounted(() => { + initSafetyRiskAnalyseUnitData(); + getAllProduceDeviceData(); + getDepartmentData(); + }); + + return { + Edit, + Delete, + View, + handleSearch, + achieveUserList, + onOpenDialogRef, + onHandleSizeChange, + onDelRiskUnit, + onHandleCurrentChange, + safetyRiskAnalyseUnitDialog, + safetyRiskAnalyseUnitDialogRef, + initSafetyRiskAnalyseUnitData, + ...toRefs(state) + }; + } +}; +</script> + +<style scoped> +:deep(.el-textarea.is-disabled .el-textarea__inner) { + background-color: var(--el-card-bg-color); + color: var(--el-input-text-color, var(--el-text-color-regular)); +} +:deep(.el-input.is-disabled .el-input__inner) { + color: var(--el-input-text-color, var(--el-text-color-regular)); +} +:deep(.el-input.is-disabled .el-input__wrapper) { + background-color: var(--el-card-bg-color); +} +</style> diff --git a/src/views/error/401.vue b/src/views/error/401.vue new file mode 100644 index 0000000..3ca649d --- /dev/null +++ b/src/views/error/401.vue @@ -0,0 +1,117 @@ +<template> + <div class="error layout-view-bg-white" :style="{ height: `calc(100vh - ${initTagViewHeight}` }"> + <div class="error-flex"> + <div class="left"> + <div class="left-item"> + <div class="left-item-animation left-item-num">401</div> + <div class="left-item-animation left-item-title">{{ $t('message.noAccess.accessTitle') }}</div> + <div class="left-item-animation left-item-msg">{{ $t('message.noAccess.accessMsg') }}</div> + <div class="left-item-animation left-item-btn"> + <el-button type="primary" round @click="onSetAuth">{{ $t('message.noAccess.accessBtn') }}</el-button> + </div> + </div> + </div> + <div class="right"> + <img + src="https://img-blog.csdnimg.cn/3333f265772a4fa89287993500ecbf96.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAbHl0LXRvcA==,size_16,color_FFFFFF,t_70,g_se,x_16" + /> + </div> + </div> + </div> +</template> + +<script lang="ts"> +import { defineComponent, computed } from 'vue'; +import { useRouter } from 'vue-router'; +import { storeToRefs } from 'pinia'; +import { useThemeConfig } from '/@/stores/themeConfig'; +import { useTagsViewRoutes } from '/@/stores/tagsViewRoutes'; +import { Session } from '/@/utils/storage'; + +export default defineComponent({ + name: '401', + setup() { + const storesThemeConfig = useThemeConfig(); + const storesTagsViewRoutes = useTagsViewRoutes(); + const { themeConfig } = storeToRefs(storesThemeConfig); + const { isTagsViewCurrenFull } = storeToRefs(storesTagsViewRoutes); + const router = useRouter(); + const onSetAuth = () => { + Session.clear(); + router.push('/login'); + }; + // 设置主内容的高度 + const initTagViewHeight = computed(() => { + let { isTagsview } = themeConfig.value; + if (isTagsViewCurrenFull.value) { + return `30px`; + } else { + if (isTagsview) return `114px`; + else return `80px`; + } + }); + return { + onSetAuth, + initTagViewHeight, + }; + }, +}); +</script> + +<style scoped lang="scss"> +.error { + height: 100%; + background-color: var(--el-color-white); + display: flex; + .error-flex { + margin: auto; + display: flex; + height: 350px; + width: 900px; + .left { + flex: 1; + height: 100%; + align-items: center; + display: flex; + .left-item { + .left-item-animation { + opacity: 0; + animation-name: error-num; + animation-duration: 0.5s; + animation-fill-mode: forwards; + } + .left-item-num { + color: var(--el-color-info); + font-size: 55px; + } + .left-item-title { + font-size: 20px; + color: var(--el-text-color-primary); + margin: 15px 0 5px 0; + animation-delay: 0.1s; + } + .left-item-msg { + color: var(--el-text-color-secondary); + font-size: 12px; + margin-bottom: 30px; + animation-delay: 0.2s; + } + .left-item-btn { + animation-delay: 0.2s; + } + } + } + .right { + flex: 1; + opacity: 0; + animation-name: error-img; + animation-duration: 2s; + animation-fill-mode: forwards; + img { + width: 100%; + height: 100%; + } + } + } +} +</style> diff --git a/src/views/error/404.vue b/src/views/error/404.vue new file mode 100644 index 0000000..3a7ce22 --- /dev/null +++ b/src/views/error/404.vue @@ -0,0 +1,115 @@ +<template> + <div class="error layout-view-bg-white" :style="{ height: `calc(100vh - ${initTagViewHeight}` }"> + <div class="error-flex"> + <div class="left"> + <div class="left-item"> + <div class="left-item-animation left-item-num">404</div> + <div class="left-item-animation left-item-title">{{ $t('message.notFound.foundTitle') }}</div> + <div class="left-item-animation left-item-msg">{{ $t('message.notFound.foundMsg') }}</div> + <div class="left-item-animation left-item-btn"> + <el-button type="primary" round @click="onGoHome">{{ $t('message.notFound.foundBtn') }}</el-button> + </div> + </div> + </div> + <div class="right"> + <img + src="https://img-blog.csdnimg.cn/9eb1d85a417f4ed1ba7107f149ce3da1.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAbHl0LXRvcA==,size_16,color_FFFFFF,t_70,g_se,x_16" + /> + </div> + </div> + </div> +</template> + +<script lang="ts"> +import { defineComponent, computed } from 'vue'; +import { useRouter } from 'vue-router'; +import { storeToRefs } from 'pinia'; +import { useThemeConfig } from '/@/stores/themeConfig'; +import { useTagsViewRoutes } from '/@/stores/tagsViewRoutes'; + +export default defineComponent({ + name: '404', + setup() { + const storesThemeConfig = useThemeConfig(); + const storesTagsViewRoutes = useTagsViewRoutes(); + const { themeConfig } = storeToRefs(storesThemeConfig); + const { isTagsViewCurrenFull } = storeToRefs(storesTagsViewRoutes); + const router = useRouter(); + const onGoHome = () => { + router.push('/'); + }; + // 设置主内容的高度 + const initTagViewHeight = computed(() => { + let { isTagsview } = themeConfig.value; + if (isTagsViewCurrenFull.value) { + return `30px`; + } else { + if (isTagsview) return `114px`; + else return `80px`; + } + }); + return { + onGoHome, + initTagViewHeight, + }; + }, +}); +</script> + +<style scoped lang="scss"> +.error { + height: 100%; + background-color: var(--el-color-white); + display: flex; + .error-flex { + margin: auto; + display: flex; + height: 350px; + width: 900px; + .left { + flex: 1; + height: 100%; + align-items: center; + display: flex; + .left-item { + .left-item-animation { + opacity: 0; + animation-name: error-num; + animation-duration: 0.5s; + animation-fill-mode: forwards; + } + .left-item-num { + color: var(--el-color-info); + font-size: 55px; + } + .left-item-title { + font-size: 20px; + color: var(--el-text-color-primary); + margin: 15px 0 5px 0; + animation-delay: 0.1s; + } + .left-item-msg { + color: var(--el-text-color-secondary); + font-size: 12px; + margin-bottom: 30px; + animation-delay: 0.2s; + } + .left-item-btn { + animation-delay: 0.2s; + } + } + } + .right { + flex: 1; + opacity: 0; + animation-name: error-img; + animation-duration: 2s; + animation-fill-mode: forwards; + img { + width: 100%; + height: 100%; + } + } + } +} +</style> diff --git a/src/views/facilityManagement/EquipmentStatistics/index.vue b/src/views/facilityManagement/EquipmentStatistics/index.vue new file mode 100644 index 0000000..136eea1 --- /dev/null +++ b/src/views/facilityManagement/EquipmentStatistics/index.vue @@ -0,0 +1,101 @@ +<template> + <div class="box"> + <div class="title">设备设施统计</div> + <div ref="main" style="width: 100%; height: 400px"></div> + </div> +</template> +<script lang="ts"> +import { defineComponent, onMounted, ref } from 'vue'; +import * as echarts from 'echarts'; +import { ElMessage } from 'element-plus'; +import { facilityManagementApi } from '/@/api/facilityManagement'; +export default defineComponent({ + setup() { + const listApi = () => { + facilityManagementApi() + .getequipmentInfoStatistics() + .then((res) => { + if (res.data.code == 200) { + let arr = []; + arr = res.data.data; + let date = []; + for (let i = 0; i < arr.length; i++) { + if (arr[i].stopStatus == 1) { + date[0] = arr[i].count; + } else if (arr[i].stopStatus == 2) { + date[1] = arr[i].count; + }else if (arr[i].stopStatus == 3) { + date[2] = arr[i].count; + }else if (arr[i].stopStatus == 4) { + date[3] = arr[i].count; + }else if (arr[i].stopStatus == -1) { + date[4] = arr[i].count; + } + } + init(date); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + } + }); + }; + onMounted(() => { + listApi(); + }); + const main = ref(); + const init = (data: any) => { + var myChart = echarts.init(main.value); + var option = { + tooltip: {}, + grid: { + left: '3%', + right: '4%', + bottom: '5%', + containLabel: true, + }, + xAxis: { + type: 'category', + data: ['停用 ', '在用', '维修 ', '报废', '超时未保养'], + }, + yAxis: { + type: 'value', + name: '数量', + nameTextStyle: { + color: '#aaa', + nameLocation: 'start', + }, + }, + color: ['#6394f9'], + series: [ + { + data: data, + type: 'bar', + }, + ], + }; + + myChart.setOption(option); + }; + return { + init, + onMounted, + main, + listApi, + }; + }, +}); +</script> +<style scoped> +.box { + background-color: #fff; + box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%); +} +.title { + font-size: 16px; + border-bottom: 1px solid #eee; + padding: 20px; +} +</style> diff --git a/src/views/facilityManagement/InstrumentationInformation/index.vue b/src/views/facilityManagement/InstrumentationInformation/index.vue new file mode 100644 index 0000000..9d64291 --- /dev/null +++ b/src/views/facilityManagement/InstrumentationInformation/index.vue @@ -0,0 +1,391 @@ +<template> + <div> + <el-form ref="ruleFormRef" :model="ruleForm" status-icon label-width="20px" class="topTitle"> + <el-row> + <el-col :span="4"> + <el-form-item size="default"> + <el-input v-model="ruleForm.searchParams.qName" placeholder="装置设施名称" /> + </el-form-item> + </el-col> + <el-col :span="4"> + <el-form-item> + <el-button size="default" type="primary" @click="listApi">查询</el-button> + <el-button size="default" @click="resetForm">重置</el-button> + </el-form-item> + </el-col> + </el-row> + </el-form> + <el-row> + <el-col :span="4"> + <el-input v-model="filterText" style="height: 30px" placeholder="请输入关键字" /> + <div class="tree"> + <!-- <el-tree ref="treeRef" class="filter-tree" :data="data" :props="props" :filter-node-method="filterNode" /> --> + <el-tree ref="treeRef" :data="data" :props="props" @node-click="handleNodeClick" :filter-node-method="filterNode" /> + </div> + </el-col> + <el-col :span="20"> + <div class="btns"> + <div> + <el-button size="default" type="primary" :icon="Plus" @click="openD('新建')">新建</el-button> + <el-button size="default" :disabled="warning" type="warning" plain :icon="EditPen" + @click="openD('修改', deletAll[0])">修改</el-button> + <el-button size="default" :disabled="danger" type="danger" :icon="Delete" @click="onDeleteAll" plain>删除</el-button> + </div> + <div> + <!-- <el-button size="default" :icon="Upload" @click="openUp"></el-button> + <el-button size="default" :icon="Download"></el-button> + <el-button size="default" :icon="Refresh"></el-button> --> + </div> + </div> + <div style="padding-left: 10px"> + <el-table ref="multipleTableRef" :data="tableData" style="width: 100%" @selection-change="handleSelectionChange"> + <el-table-column type="selection" align="center" width="55" /> + <el-table-column type="expand"> + <template #default="scope"> + <el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClicks" style="margin: 0 5%"> + <el-tab-pane label="设备保养" name="first"> + <el-table ref="multipleTableRef" :data="scope.row.takecareDetailList" style="width: 100%"> + <el-table-column property="takecareMemo" align="center" label="保养情况" sortable /> + <el-table-column property="leadingPersonName" align="center" label="保养负责人" sortable /> + <el-table-column property="takecareDate" align="center" :formatter="timeDate" label="保养日期" sortable /> + <el-table-column property="leadingPersonDepartmentName" align="center" label="保养负责人单位" sortable /> + </el-table> + </el-tab-pane> + <el-tab-pane label="设备检查" name="second" + ><el-table ref="multipleTableRef" :data="scope.row.checkDetailList" style="width: 100%"> + <el-table-column property="leadingPersonName" align="center" label="检查人" sortable /> + <el-table-column property="createTime" align="center" :formatter="timeDate" label="检查日期" sortable /> + <el-table-column property="name" align="center" label="检查人部门" sortable /> + <el-table-column property="takecareMemo" align="center" label="检查结果" sortable /> + <el-table-column property="name" align="center" label="检查状态" sortable /> </el-table + ></el-tab-pane> + <el-tab-pane label="设备检测" name="third"> + <el-table ref="multipleTableRef" :data="scope.row.testDetailList" style="width: 100%"> + <el-table-column property="testPersonName" align="center" label="检测人" sortable /> + <el-table-column property="testDate" align="center" :formatter="timeDate" label="检测日期" sortable /> + <el-table-column property="testPersonDepartmentName" align="center" label="检测人单位" sortable /> + <el-table-column property="testMemo" align="center" label="检测内容" sortable /> + <el-table-column align="center" label="检测结果"> + <template #default="scope"> + <span v-if="scope.row.testResult == 1">成功</span> + <span v-if="scope.row.testResult == 2">失败</span> + </template> + </el-table-column> + <el-table-column property="testStatus" align="center" label="检测状态" sortable /> + </el-table> + </el-tab-pane> + <el-tab-pane label="设备维修" name="fourth"> + <el-table ref="multipleTableRef" :data="scope.row.repaireDetailList" style="width: 100%"> + <el-table-column property="exceptionInfo" align="center" label="设施异常项" sortable /> + <el-table-column align="center" label="维修状态"> + <template #default="scope"> + <span v-if="scope.row.repairStatus == 1">维修中</span> + <span v-if="scope.row.repairStatus == 2">已修好</span> + </template> + </el-table-column> + <el-table-column property="repairMemo" align="center" label="维修情况" sortable /> + <el-table-column property="repairPersonName" align="center" label="维修负责人" sortable /> + <el-table-column property="repairPersonDepartmentName" align="center" label="维修负责人单位" sortable /> + <el-table-column property="repairStartDate" align="center" :formatter="timeDate" label="维修开始日期" sortable /> + <el-table-column property="repairEndDate" align="center" :formatter="timeDate" label="维修结束日期" sortable /> + </el-table> + </el-tab-pane> + </el-tabs> + </template> + </el-table-column> + <el-table-column property="qName" label="装置设施名称" align="center" sortable /> + <el-table-column property="positionNum" align="center" label="装置设施位号" sortable /> + <el-table-column property="qUsage" align="center" label="装置设施用途" sortable /> + <el-table-column property="model" label="装置设施型号" align="center" sortable show-overflow-tooltip /> + <el-table-column property="equipmentTypeId" label="类型/类别外键" align="center" sortable show-overflow-tooltip /> + <el-table-column property="setPart" label="设施部位" align="center" sortable show-overflow-tooltip /> + <el-table-column label="操作" align="center" width="250"> + <template #default="scope"> + <el-button link type="primary" size="default" :icon="View" @click="openD('查看', scope.row.id)">查看</el-button> + <el-button link type="primary" size="default" :icon="EditPen" @click="openD('修改', scope.row.id)">修改</el-button> + <el-button link type="primary" size="default" :icon="Delete" @click="onDelete(scope.row.id)">删除</el-button> + </template> + </el-table-column> + </el-table> + <div class="pages"> + <el-pagination + v-model:currentPage="currentPage4" + v-model:page-size="pageSize4" + :page-sizes="[10, 20, 30, 40]" + layout="total, sizes, prev, pager, next, jumper" + :total="total" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + </div> + </el-col> + </el-row> + <!-- <updata ref="Show"></updata> --> + <Dailog ref="openAdd" @navAddorUpdata="onAddorUpdata"></Dailog> + </div> +</template> +<script lang="ts"> +import { defineComponent, ref, reactive, watch, onMounted } from 'vue'; +import { timeDate } from '/@/assets/index.ts'; +import updata from '/@/components/updata/updata.vue'; +import Dailog from '/@/components/equipmentDailog/Dailog.vue'; +import { ElTree, TabsPaneContext, ElMessage, ElMessageBox } from 'element-plus'; +import { facilityManagementApi } from '/@/api/facilityManagement'; +import { EditPen, View, Plus, Delete, Download, Refresh, Upload } from '@element-plus/icons-vue'; +interface Tree { + label: string; + children?: Tree[]; +} +export default defineComponent({ + components: { updata, Dailog }, + setup() { + // 搜索条件 + const ruleForm = reactive({ + pageSize: 10, + pageIndex: 1, + searchParams: { + qName: '', ////名称 + positionNum: '', ////位号 + equipmentTypeId: '', + infoType: 0, ////具体类型(页面左侧的导航栏使用) 0:仪器仪表信息 1:生产设备设施 2:安全设备设施 + }, + }); + // 重置 + const resetForm = () => { + ruleForm.searchParams.qName = ''; + ruleForm.searchParams.positionNum = ''; + ruleForm.searchParams.equipmentTypeId = ''; + listApiTree() + listApi(); + }; + const listApi = () => { + facilityManagementApi() + .getequipmentInfoList(ruleForm) + .then((res) => { + if (res.data.code == 200) { + tableData.value = res.data.data; + currentPage4.value = res.data.pageIndex; + pageSize4.value = res.data.pageSize; + total.value = res.data.total; + } else { + ElMessage.error(res.data.msg); + } + }); + }; + // + onMounted(() => { + listApi(); + }); + const onAddorUpdata = () => { + listApi(); + }; + // 表格 + const tableData = ref(); + const currentPage4 = ref(); + const pageSize4 = ref(); + const total = ref(); + const handleSizeChange = (val: number) => { + // console.log(`${val} items per page`); + ruleForm.pageSize = val; + listApi(); + }; + const handleCurrentChange = (val: number) => { + // console.log(`current page: ${val}`); + ruleForm.pageIndex = val; + listApi(); + }; + // 弹窗 + const openAdd = ref(); + const openD = (title: String, id: number) => { + openAdd.value.openDailog(title, false, id, 0); + }; + // 删除 + const onDelete = (id: number) => { + let arr = []; + arr.push(id); + ElMessageBox.confirm('确定删除所选项吗?', 'Warning', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + facilityManagementApi() + .getequipmentInfoDelete(arr) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + message: res.data.msg, + type: 'success', + }); + listApi(); + } else { + ElMessage.error(res.data.msg); + } + }); + }) + .catch(() => { + ElMessage({ + type: 'info', + message: 'Delete canceled', + }); + }); + }; + // 批量删除 + const warning = ref(true); + const danger = ref(true); + const deletAll = ref(); + const handleSelectionChange = (val: any) => { + let valId = JSON.parse(JSON.stringify(val)); + let arr = []; + for (let i = 0; i < valId.length; i++) { + arr.push(valId[i].id); + } + deletAll.value = arr; + if (val.length == 1) { + warning.value = false; + danger.value = false; + } else if (val.length == 0) { + warning.value = true; + danger.value = true; + } else { + warning.value = true; + danger.value = false; + } + }; + const onDeleteAll = () => { + ElMessageBox.confirm('确定删除所选项吗?', 'Warning', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + facilityManagementApi() + .getequipmentInfoDelete(deletAll.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + message: res.data.msg, + type: 'success', + }); + listApi(); + } else { + ElMessage.error(res.data.msg); + } + }); + }) + .catch(() => { + // ElMessage({ + // type: 'info', + // message: 'Delete canceled', + // }); + }); + }; + const filterText = ref(''); + const treeRef = ref<InstanceType<typeof ElTree>>(); + // 树形 + const listApiTree = () => { + facilityManagementApi() + .getequipmentTypeMngTreeData() + .then((res) => { + if (res.data.code == 200) { + data.value = res.data.data; + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + } + }); + }; + const props = { + label: 'typeName', + children: 'childList', + value: 'id', + }; + watch(filterText, (val) => { + treeRef.value!.filter(val); + }); + + const filterNode = (value: string, data: Tree) => { + if (!value) return true; + return data.typeName.includes(value); + }; + const handleNodeClick = (data: Tree) => { + ruleForm.searchParams.positionNum = data.sortNum; + ruleForm.searchParams.equipmentTypeId = data.id; + listApi(); + }; + const data = ref([]); + onMounted(() => { + listApiTree(); + }); + const handleClicks = (tab: TabsPaneContext, event: Event) => { + console.log(tab, event); + }; + + const activeName = ref('first'); + // const Show=ref() + // const openUp=()=>{ + // Show.value.openDialog() + // } + return { + handleNodeClick, + ruleForm, + timeDate, + resetForm, + listApi, + onAddorUpdata, + tableData, + currentPage4, + pageSize4, + total, + handleSizeChange, + handleCurrentChange, + onDelete, + warning, + danger, + deletAll, + handleSelectionChange, + onDeleteAll, + listApiTree, + handleClicks, + filterText, + treeRef, + props, + filterNode, + data, + openAdd, + openD, + activeName, + Plus, + EditPen, + Delete, + Download, + Refresh, + View, + Upload, + }; + }, +}); +</script> +<style scoped> +.topTitle { + background-color: #fff; + padding: 20px 0px 20px 0px; + margin-bottom: 10px; +} +.tree { + height: 750px; + background-color: #fff; + overflow: hidden; + overflow-y: auto; +} +.btns { + padding: 10px 0px 10px 10px; + display: flex; + justify-content: space-between; + background-color: #fff; +} +</style> diff --git a/src/views/facilityManagement/ProductionEquipment/index.vue b/src/views/facilityManagement/ProductionEquipment/index.vue new file mode 100644 index 0000000..70edf54 --- /dev/null +++ b/src/views/facilityManagement/ProductionEquipment/index.vue @@ -0,0 +1,390 @@ +<template> + <div> + <el-form ref="ruleFormRef" :model="ruleForm" status-icon label-width="20px" class="topTitle"> + <el-row> + <el-col :span="4"> + <el-form-item size="default"> + <el-input v-model="ruleForm.searchParams.qName" placeholder="装置设施名称" /> + </el-form-item> + </el-col> + <el-col :span="4"> + <el-form-item> + <el-button size="default" type="primary" @click="listApi">查询</el-button> + <el-button size="default" @click="resetForm">重置</el-button> + </el-form-item> + </el-col> + </el-row> + </el-form> + <el-row> + <el-col :span="4"> + <el-input v-model="filterText" style="height: 30px" placeholder="请输入关键字" /> + <div class="tree"> + + <!-- <el-tree ref="treeRef" class="filter-tree" :data="data" :props="props" :filter-node-method="filterNode" /> --> + <el-tree ref="treeRef" :data="data" :props="props" @node-click="handleNodeClick" :filter-node-method="filterNode" /> + </div> + </el-col> + <el-col :span="20"> + <div class="btns"> + <div> + <el-button size="default" type="primary" :icon="Plus" @click="openD('新建')">新建</el-button> + <el-button size="default" :disabled="warning" type="warning" plain :icon="EditPen" + @click="openD('修改', deletAll[0])">修改</el-button> + <el-button size="default" :disabled="danger" type="danger" :icon="Delete" @click="onDeleteAll" plain>删除</el-button> + </div> + <div> + <!-- <el-button size="default" :icon="Upload" @click="openUp"></el-button> + <el-button size="default" :icon="Download"></el-button> + <el-button size="default" :icon="Refresh"></el-button> --> + </div> + </div> + <div style="padding-left: 10px"> + <el-table ref="multipleTableRef" :data="tableData" @selection-change="handleSelectionChange" style="width: 100%"> + <el-table-column type="selection" align="center" width="55" /> + <el-table-column type="expand"> + <template #default="scope"> + <el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClicks" style="margin: 0 5%"> + <el-tab-pane label="设备保养" name="first"> + <el-table ref="multipleTableRef" :data="scope.row.takecareDetailList" style="width: 100%"> + <el-table-column property="takecareMemo" align="center" label="保养情况" sortable /> + <el-table-column property="leadingPersonName" align="center" label="保养负责人" sortable /> + <el-table-column property="takecareDate" align="center" label="保养日期" sortable /> + <el-table-column property="leadingPersonDepartmentName" align="center" label="保养负责人单位" sortable /> + </el-table> + </el-tab-pane> + <el-tab-pane label="设备检查" name="second" + ><el-table ref="multipleTableRef" :data="scope.row.checkDetailList" style="width: 100%"> + <el-table-column property="leadingPersonName" align="center" label="检查人" sortable /> + <el-table-column property="createTime" align="center" label="检查日期" sortable /> + <el-table-column property="name" align="center" label="检查人部门" sortable /> + <el-table-column property="takecareMemo" align="center" label="检查结果" sortable /> + <el-table-column property="name" align="center" label="检查状态" sortable /> </el-table + ></el-tab-pane> + <el-tab-pane label="设备检测" name="third"> + <el-table ref="multipleTableRef" :data="scope.row.testDetailList" style="width: 100%"> + <el-table-column property="testPersonName" align="center" label="检测人" sortable /> + <el-table-column property="testDate" align="center" label="检测日期" sortable /> + <el-table-column property="testPersonDepartmentName" align="center" label="检测人单位" sortable /> + <el-table-column property="testMemo" align="center" label="检测内容" sortable /> + <el-table-column align="center" label="检测结果"> + <template #default="scope"> + <span v-if="scope.row.testResult == 1">成功</span> + <span v-if="scope.row.testResult == 2">失败</span> + </template> + </el-table-column> + <el-table-column property="testStatus" align="center" label="检测状态" sortable /> + </el-table> + </el-tab-pane> + <el-tab-pane label="设备维修" name="fourth"> + <el-table ref="multipleTableRef" :data="scope.row.repaireDetailList" style="width: 100%"> + <el-table-column property="exceptionInfo" align="center" label="设施异常项" sortable /> + <el-table-column align="center" label="维修状态"> + <template #default="scope"> + <span v-if="scope.row.repairStatus == 1">维修中</span> + <span v-if="scope.row.repairStatus == 2">已修好</span> + </template> + </el-table-column> + <el-table-column property="repairMemo" align="center" label="维修情况" sortable /> + <el-table-column property="repairPersonName" align="center" label="维修负责人" sortable /> + <el-table-column property="repairPersonDepartmentName" align="center" label="维修负责人单位" sortable /> + <el-table-column property="repairStartDate" align="center" label="维修开始日期" sortable /> + <el-table-column property="repairEndDate" align="center" label="维修结束日期" sortable /> + </el-table> + </el-tab-pane> + </el-tabs> + </template> + </el-table-column> + <el-table-column property="qName" label="装置设施名称" align="center" sortable /> + <el-table-column property="positionNum" align="center" label="装置设施位号" sortable /> + <el-table-column property="qUsage" align="center" label="装置设施用途" sortable /> + <el-table-column property="model" label="装置设施型号" align="center" sortable show-overflow-tooltip /> + <el-table-column property="equipmentTypeId" label="类型/类别外键" align="center" sortable show-overflow-tooltip /> + <el-table-column property="setPart" label="设施部位" align="center" sortable show-overflow-tooltip /> + <el-table-column label="操作" align="center" width="250"> + <template #default="scope"> + <el-button link type="primary" size="default" :icon="View" @click="openD('查看', scope.row.id)">查看</el-button> + <el-button link type="primary" size="default" :icon="EditPen" @click="openD('修改', scope.row.id)">修改</el-button> + <el-button link type="primary" size="default" :icon="Delete" @click="onDelete(scope.row.id)">删除</el-button> + </template> + </el-table-column> + </el-table> + <div class="pages"> + <el-pagination + v-model:currentPage="currentPage4" + v-model:page-size="pageSize4" + :page-sizes="[10, 20, 30, 40]" + layout="total, sizes, prev, pager, next, jumper" + :total="total" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + </div> + </el-col> + </el-row> + <!-- <updata ref="Show"></updata> --> + <Dailog ref="openAdd" @navAddorUpdata="onAddorUpdata"></Dailog> + </div> +</template> +<script lang="ts"> +import { defineComponent, ref, reactive, watch, onMounted } from 'vue'; +import updata from '/@/components/updata/updata.vue'; +import Dailog from '/@/components/equipmentDailog/Dailog.vue'; +import { ElTree, TabsPaneContext, ElMessage, ElMessageBox } from 'element-plus'; +import { facilityManagementApi } from '/@/api/facilityManagement'; +import { EditPen, View, Plus, Delete, Download, Refresh, Upload } from '@element-plus/icons-vue'; +interface Tree { + label: string; + children?: Tree[]; +} +export default defineComponent({ + components: { updata, Dailog }, + setup() { + // 搜索条件 + const ruleForm = reactive({ + pageSize: 10, + pageIndex: 1, + searchParams: { + qName: '', ////名称 + positionNum: '', ////位号 + equipmentTypeId:"", + infoType: 1, ////具体类型(页面左侧的导航栏使用) 0:仪器仪表信息 1:生产设备设施 2:安全设备设施 + }, + }); + // 重置 + const resetForm = () => { + ruleForm.searchParams.qName = ''; + ruleForm.searchParams.positionNum = ''; + ruleForm.searchParams.equipmentTypeId = ''; + listApiTree() + listApi(); + }; + const listApi = () => { + facilityManagementApi() + .getequipmentInfoList(ruleForm) + .then((res) => { + if (res.data.code == 200) { + tableData.value = res.data.data; + currentPage4.value = res.data.pageIndex; + pageSize4.value = res.data.pageSize; + total.value = res.data.total; + } else { + ElMessage.error(res.data.msg); + } + }); + }; + // + onMounted(() => { + listApi(); + }); + const onAddorUpdata = () => { + listApi(); + }; + // 表格 + const tableData = ref(); + const currentPage4 = ref(); + const pageSize4 = ref(); + const total = ref(); + const handleSizeChange = (val: number) => { + // console.log(`${val} items per page`); + ruleForm.pageSize = val; + listApi(); + }; + const handleCurrentChange = (val: number) => { + // console.log(`current page: ${val}`); + ruleForm.pageIndex = val; + listApi(); + }; + // 弹窗 + const openAdd = ref(); + const openD = (title: String, id: number) => { + openAdd.value.openDailog(title,true,id,1); + }; + // 删除 + const onDelete = (id: number) => { + let arr=[] + arr.push(id) + ElMessageBox.confirm('确定删除所选项吗?', 'Warning', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + facilityManagementApi() + .getequipmentInfoDelete(arr) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + message: res.data.msg, + type: 'success', + }); + listApi(); + } else { + ElMessage.error(res.data.msg); + } + }); + }) + .catch(() => { + ElMessage({ + type: 'info', + message: 'Delete canceled', + }); + }); + }; + // 批量删除 + const warning = ref(true); + const danger = ref(true); + const deletAll = ref(); + const handleSelectionChange = (val: any) => { + let valId = JSON.parse(JSON.stringify(val)); + let arr = []; + for (let i = 0; i < valId.length; i++) { + arr.push(valId[i].id); + } + deletAll.value = arr + if (val.length == 1) { + warning.value = false; + danger.value = false; + } else if (val.length == 0) { + warning.value = true; + danger.value = true; + } else { + warning.value = true; + danger.value = false; + } + }; + const onDeleteAll = () => { + ElMessageBox.confirm('确定删除所选项吗?', 'Warning', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + facilityManagementApi() + .getequipmentInfoDelete(deletAll.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + message: res.data.msg, + type: 'success', + }); + listApi(); + } else { + ElMessage.error(res.data.msg); + } + }); + }) + .catch(() => { + // ElMessage({ + // type: 'info', + // message: 'Delete canceled', + // }); + }); + }; + const filterText = ref(''); + const treeRef = ref<InstanceType<typeof ElTree>>(); + // 树形 + const listApiTree = () => { + facilityManagementApi() + .getequipmentTypeMngTreeData() + .then((res) => { + if (res.data.code == 200) { + data.value= res.data.data; + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + } + }); + }; + const props = { + label: 'typeName', + children: 'childList', + value: 'id', + } + watch(filterText, (val) => { + treeRef.value!.filter(val); + }); + + const filterNode = (value: string, data: Tree) => { + if (!value) return true; + return data.typeName.includes(value); + }; + const handleNodeClick=(data: Tree)=>{ + ruleForm.searchParams.equipmentTypeId=data.id + ruleForm.searchParams.equipmentTypeId = data.id; + listApi(); + } + const data=ref([]) + onMounted(() => { + listApiTree(); + }); + const handleClicks = (tab: TabsPaneContext, event: Event) => { + console.log(tab, event); + }; + + const activeName = ref('first'); + // const Show=ref() + // const openUp=()=>{ + // Show.value.openDialog() + // } + return { + handleNodeClick, + ruleForm, + resetForm, + listApi, + onAddorUpdata, + tableData, + currentPage4, + pageSize4, + total, + handleSizeChange, + handleCurrentChange, + onDelete, + warning, + danger, + deletAll, + handleSelectionChange, + onDeleteAll, + listApiTree, + handleClicks, + filterText, + treeRef, + props, + filterNode, + data, + openAdd, + openD, + activeName, + Plus, + EditPen, + Delete, + Download, + Refresh, + View, + Upload, + }; + }, +}); +</script> +<style scoped> +.topTitle { + background-color: #fff; + padding: 20px 0px 20px 0px; + margin-bottom: 10px; +} +.tree { + height: 750px; + background-color: #fff; + overflow: hidden; + overflow-y: auto; +} +.btns { + padding: 10px 0px 10px 10px; + display: flex; + justify-content: space-between; + background-color: #fff; +} +</style> diff --git a/src/views/facilityManagement/claimReturnRecords/components/invalidDealDialog.vue b/src/views/facilityManagement/claimReturnRecords/components/invalidDealDialog.vue new file mode 100644 index 0000000..7f0503e --- /dev/null +++ b/src/views/facilityManagement/claimReturnRecords/components/invalidDealDialog.vue @@ -0,0 +1,85 @@ +<template> + <div> + <el-dialog :title="invalidDealState.title" :close-on-click-modal="false" v-model="invalidDealState.invalidDealDialogVisible" width="30%"> + <el-form + :model="invalidDealState.invalidDealForm" + ref="invalidDealFormRef" + size="default" + label-width="150px"> + <el-row> + <el-col :span="24" class="mb20"> + <el-form-item label="失效原因:" prop="reason"> + <el-select class="input-add" v-model="invalidDealState.invalidDealForm.reason" placeholder="失效原因"> + <el-option + v-for="item in invalidDealState.reasonList" + :key="item.id" + :value="item.id" + :label="item.name" + ></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :span="24" class="mb20"> + <el-form-item label="备注:" prop="remark"> + <el-input type="textarea" :rows="3" v-model="invalidDealState.invalidDealForm.remark" placeholder="备注" class="input-add"> + </el-input> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="invalidDealState.invalidDealDialogVisible = !invalidDealState.invalidDealDialogVisible" size="default">取 消</el-button> + <el-button type="primary" @click="submitInvalidDeal" v-throttle size="default">确 定</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script setup lang="ts"> +import { reactive, ref } from 'vue' +import {InvalidDealStateType, materialType} from '..' + +const invalidDealFormRef = ref() + +const invalidDealState = reactive<InvalidDealStateType>({ + title: '', + invalidDealDialogVisible: false, + invalidDealForm: { + id: null, + reason: null, + remark: null, + }, + reasonList:[ + {id: 0, name:'完好'}, + {id: 1, name:'损坏'}, + {id: 2, name:'丢失'}, + {id: 3, name:'过期'}, + {id: 4, name:'其他'} + ] +}) + +const openInvalidDealDialog = (value: materialType) => { + invalidDealState.invalidDealDialogVisible = true + invalidDealState.invalidDealForm.id = value.id + invalidDealState.invalidDealForm.reason = value.materialStatus + invalidDealState.invalidDealForm.remark = value.remark +} + +const submitInvalidDeal = () => { + emit('refreshInvalidDeal',invalidDealState.invalidDealForm) + invalidDealState.invalidDealDialogVisible = false +} + +const emit = defineEmits(['refreshInvalidDeal']) + +defineExpose({ + openInvalidDealDialog +}) + +</script> + +<style scoped> + +</style> diff --git a/src/views/facilityManagement/claimReturnRecords/components/returnAndWatch.vue b/src/views/facilityManagement/claimReturnRecords/components/returnAndWatch.vue new file mode 100644 index 0000000..49f4fdd --- /dev/null +++ b/src/views/facilityManagement/claimReturnRecords/components/returnAndWatch.vue @@ -0,0 +1,239 @@ +<template> + <div class="system-add-menu-container"> + <el-dialog :title="returnAndWatchState.title" :close-on-click-modal="false" v-model="returnAndWatchState.showReturnAndWatchDialog" width="50%"> + <el-tabs class="active" v-model="returnAndWatchState.activeName"> + <el-tab-pane label="未归还" name="noReturn"> + <el-table + :data="returnAndWatchState.noReturnData" + border fit highlight-current-row lazy + :header-cell-style="{ background: '#fafafa' }" + style="width: 100%" + @selection-change="handleSelectionChange" + > + <el-table-column v-if="returnAndWatchState.ifShow === true" type="selection" width="55"/> + <el-table-column prop="materialName" label="物资名称" show-overflow-tooltip align="center"/> + <el-table-column prop="smdId" label="物资编号" show-overflow-tooltip align="center"/> + <el-table-column prop="materialStatus" label="物资状态" show-overflow-tooltip align="center"> + <template #default="scope"> + <span> + {{ filterMaterialStatus(scope.row.materialStatus) }} + </span> + </template> + </el-table-column> + <el-table-column prop="remark" label="备注" show-overflow-tooltip align="center"/> + <el-table-column label="操作" width="150" align="center"> + <template #default="scope"> + <el-button size="small" v-if="returnAndWatchState.ifShow === true" text type="danger" :icon="Delete" @click="invalidDeal(scope.row)">无效处理</el-button> + </template> + </el-table-column> + </el-table> + <div style="padding-top: 20px" align="center"> + <span> + <el-button type="primary" v-if="returnAndWatchState.ifShow === true" @click="returnConfirm" v-throttle size="default">归 还</el-button> + </span> + </div> + + </el-tab-pane> + <el-tab-pane label="已归还" name="return"> + <el-table + :data="returnAndWatchState.returnData" + border fit highlight-current-row lazy + :header-cell-style="{ background: '#fafafa' }" + style="width: 100%"> + <el-table-column prop="materialName" label="物资名称" show-overflow-tooltip align="center"/> + <el-table-column prop="smdId" label="物资编号" show-overflow-tooltip align="center"/> + <el-table-column prop="materialStatus" label="物资状态" show-overflow-tooltip align="center"> + <template #default="scope"> + <span> + {{ filterMaterialStatus(scope.row.materialStatus) }} + </span> + </template> + </el-table-column> + <el-table-column prop="remark" label="备注" show-overflow-tooltip align="center"/> + </el-table> + </el-tab-pane> + <el-tab-pane label="耗材" name="Invalid"> + <el-table + :data="returnAndWatchState.invalidData" + border fit highlight-current-row lazy + :header-cell-style="{ background: '#fafafa' }" + style="width: 100%"> + <el-table-column prop="materialName" label="物资名称" show-overflow-tooltip align="center"/> + <el-table-column prop="smdId" label="物资编号" show-overflow-tooltip align="center"/> + <el-table-column prop="materialStatus" label="物资状态" show-overflow-tooltip align="center"> + <template #default="scope"> + <span> + {{ filterMaterialStatus(scope.row.materialStatus) }} + </span> + </template> + </el-table-column> + <el-table-column prop="remark" label="备注" show-overflow-tooltip align="center"/> + </el-table> + </el-tab-pane> + </el-tabs> + </el-dialog> + <invalid-deal-dialog ref="invalidDealDialogRef" @refreshInvalidDeal="refreshInvalidDeal"></invalid-deal-dialog> + </div> +</template> + +<script setup lang="ts"> +import {computed, nextTick, onMounted, reactive, ref, toRefs, watch} from 'vue' +import { Edit, Delete, } from '@element-plus/icons-vue'; +import { + claimReturnDataType, InvalidDealFormType, + materialType, + ReturnAndWatchType +} from "/@/views/facilityManagement/claimReturnRecords/index"; +import {ElMessage, ElMessageBox} from "element-plus"; +import {claimReturnRecordsApi} from "/@/api/facilityManagement/claimReturnRecords"; +import InvalidDealDialog from './invalidDealDialog.vue' + +const invalidDealDialogRef = ref() + +const returnAndWatchState = reactive<ReturnAndWatchType>({ + title: '', + ifShow: false, + goodsClassifyTitle: '', + showReturnAndWatchDialog: false, + activeName: 'noReturn', + goodsClassifyForm: { + id: null, + materialClassifyName: '', + parentId: null, + }, + goodsClassifyRules: { + + }, + returnData: [], + noReturnData: [], + invalidData: [], + returnFormList: { + receiveBaseId: null, + materialList: [] + }, + reasonList:[ + {id: 0, name:'完好'}, + {id: 1, name:'损坏'}, + {id: 2, name:'丢失'}, + {id: 3, name:'过期'}, + {id: 4, name:'其他'} + ] +}); + +const openReturnAndWatchDialog = (title: string, value: claimReturnDataType ) => { + returnAndWatchState.showReturnAndWatchDialog = true; + returnAndWatchState.returnFormList.receiveBaseId = value.id; + if(title === '归还'){ + returnAndWatchState.ifShow = true; + returnAndWatchState.title = '归还记录'; + returnAndWatchState.returnData = value.materialList.filter(item => item.revertStatus === 0); + returnAndWatchState.noReturnData = JSON.parse(JSON.stringify(value.materialList.filter(item => item.revertStatus === 1))); + returnAndWatchState.invalidData = value.materialList.filter(item => item.revertStatus !== 0 && item.revertStatus !== 1); + }else { + returnAndWatchState.ifShow = false; + returnAndWatchState.title = '查看物资'; + returnAndWatchState.returnData = value.materialList.filter(item => item.revertStatus === 0); + returnAndWatchState.noReturnData = value.materialList.filter(item => item.revertStatus === 1); + returnAndWatchState.invalidData = value.materialList.filter(item => item.revertStatus !== 0 && item.revertStatus !== 1); + } +}; + +const returnConfirm = () => { + if(returnAndWatchState.returnFormList.materialList.length > 0){ + ElMessageBox.confirm(`此操作将把所选中物资全部归还,是否继续?`, '提示', { + confirmButtonText: '确认', + cancelButtonText: '取消', + type: 'warning' + }) + .then(async () => { + let res = await claimReturnRecordsApi().returnGoods(returnAndWatchState.returnFormList); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + duration: 2000, + message: '物资归还成功' + }); + await refreshReturnTableData() + emit('refreshReturnData') + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }) + .catch(() => {}); + }else{ + ElMessage({ + type:'warning', + message: '请选择要归还的物资' + }) + } +}; + +const refreshReturnTableData = async () => { + let res = await claimReturnRecordsApi().refreshReturnAndNoReturn({id: returnAndWatchState.returnFormList.receiveBaseId}) + if(res.data.code === '200'){ + returnAndWatchState.returnData = res.data.data.materialList.filter((item: materialType) => item.revertStatus === 0); + returnAndWatchState.noReturnData = res.data.data.materialList.filter((item: materialType) => item.revertStatus === 1); + returnAndWatchState.invalidData = res.data.data.materialList.filter((item: materialType) => item.revertStatus !== 0 && item.revertStatus !== 1); + }else{ + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } +} + +const invalidDeal = (value: materialType) => { + invalidDealDialogRef.value.openInvalidDealDialog(value) +}; + +const refreshInvalidDeal = (value: InvalidDealFormType) => { + let returnDataNum = returnAndWatchState.noReturnData.findIndex(item => item.id == value.id) + returnAndWatchState.noReturnData[returnDataNum].materialStatus = value.reason as number + returnAndWatchState.noReturnData[returnDataNum].remark = value.remark as string + for(let i in returnAndWatchState.returnFormList.materialList){ + if(returnAndWatchState.returnFormList.materialList[i].receiveId === value.id){ + returnAndWatchState.returnFormList.materialList[i] = { + receiveId: value.id, + materialStatus: value.reason, + remark: value.remark, + } + } + } +}; + +const handleSelectionChange = (val: materialType []) => { + returnAndWatchState.returnFormList.materialList = val.map((item: materialType) => { + return { + receiveId: item.id, + materialStatus: item.materialStatus, + remark: item.remark, + } + }) +}; + +const filterMaterialStatus = (value: number) => { + return returnAndWatchState.reasonList.find(item => item.id === value)?.name +}; + +const emit = defineEmits(['refreshReturnData']); + +defineExpose({ + openReturnAndWatchDialog, +}); + + +</script> + +<style scoped> +/*:deep(.el-overlay .el-overlay-dialog .el-dialog .el-dialog__body) {*/ +/* padding-bottom: 20px !important;*/ +/*}*/ +:deep(.el-table .big-row) { + font-size: 16px !important; + font-weight: 700; +} + +</style> diff --git a/src/views/facilityManagement/claimReturnRecords/index.ts b/src/views/facilityManagement/claimReturnRecords/index.ts new file mode 100644 index 0000000..bd9130c --- /dev/null +++ b/src/views/facilityManagement/claimReturnRecords/index.ts @@ -0,0 +1,76 @@ +export interface ClaimReturnRecordsType { + tableLoading: boolean, + total: number, + timeValue: Array<string>, + claimReturnData: Array<claimReturnDataType> , + listQuery: { + pageSize: number, + pageIndex: number, + searchParams: { + materialName: string| null, + receiveUname: string | null, + endTime: string | null, + startTime: string | null, + } + }, +} + +export interface ReturnAndWatchType { + title: string, + ifShow: Boolean, + goodsClassifyTitle: string, + showReturnAndWatchDialog: boolean, + activeName: string, + goodsClassifyForm: { + id: null, + materialClassifyName: '', + parentId: null, + }, + goodsClassifyRules: { + + }, + returnData: materialType [], + noReturnData: materialType [], + invalidData: materialType [], + returnFormList: { + receiveBaseId: null | number, + materialList: returnFormListType [] , + }, + reasonList: Type [] +} + +export interface claimReturnDataType { + id: number, + materialList: materialType [], +} + +export interface materialType { + id: number, + materialStatus: number, + revertStatus: number, + remark: string | null, +} + +export interface returnFormListType { + receiveId: number, + materialStatus: number | null, + remark: string | null, +} + +export interface InvalidDealStateType { + title: string, + invalidDealDialogVisible: boolean, + invalidDealForm: InvalidDealFormType, + reasonList: Type [] +} + +export interface InvalidDealFormType { + id: number | null, + reason: number | null, + remark: string | null, +} + +export interface Type { + id: number, + name: string, +} diff --git a/src/views/facilityManagement/claimReturnRecords/index.vue b/src/views/facilityManagement/claimReturnRecords/index.vue new file mode 100644 index 0000000..e4cf148 --- /dev/null +++ b/src/views/facilityManagement/claimReturnRecords/index.vue @@ -0,0 +1,258 @@ +<template> + <div class="home-container"> + <div style="height: 100%"> + <el-row class="homeCard"> + <div class="basic-line"> + <span>领取时间:</span> + <el-date-picker + value-format="YYYY-MM-DD" + v-model="claimReturnRecordsState.timeValue" + type="daterange" + range-separator="To" + start-placeholder="开始时间" + end-placeholder="结束时间" + /> + </div> +<!-- <div class="basic-line">--> +<!-- <span>领取人:</span>--> +<!-- <el-input class="input-box2" v-model="claimReturnRecordsState.listQuery.searchParams.materialName" placeholder="领取人" clearable> </el-input>--> +<!-- </div>--> + <div> + <el-button size="large" type="primary" class="ml10" v-throttle @click="initClaimReturnData"> + <el-icon> + <ele-Search /> + </el-icon> + 查询 + </el-button> + </div> + </el-row> + <div class="homeCard"> + <div class="main-card"> + <el-table element-loading-text="Loading..." v-loading="claimReturnRecordsState.tableLoading" :data="claimReturnRecordsState.claimReturnData" style="width: 100%" height="calc(100% - 100px)" :header-cell-style="{ background: '#fafafa' }"> + <el-table-column type="index" label="序号" width="60" /> + <el-table-column prop="createTime" label="物资领取时间" show-overflow-tooltip></el-table-column> + <el-table-column prop="receiveUname" label="领取人" show-overflow-tooltip></el-table-column> + <el-table-column prop="materialName" label="物资" show-overflow-tooltip></el-table-column> + <el-table-column prop="receiveCount" label="领取数量" show-overflow-tooltip></el-table-column> + <el-table-column prop="revertCount" label="已归还数量" show-overflow-tooltip></el-table-column> + <el-table-column prop="statusName" label="归还情况" show-overflow-tooltip> + <template #default="scope"> + <el-tag :type="scope.row.status === 0 ? 'danger' : scope.row.status === 1 ? 'warning' : scope.row.status === 2 ? 'success' : ''"> + <span> + {{ scope.row.statusName }} + </span> + </el-tag> + </template> + </el-table-column> + <el-table-column label="操作" width="250" align="center"> + <template #default="scope"> + <el-button size="small" text type="success" @click="onOpenReturnGoodsDialog('归还', scope.row)">归还</el-button> + <el-button size="small" text type="primary" @click="onOpenReturnGoodsDialog('查看物资', scope.row)">查看物资</el-button> + </template> + </el-table-column> + </el-table> + <br /> + <el-pagination @size-change="onHandleSizeChange" @current-change="onHandleCurrentChange" :pager-count="5" :page-sizes="[10, 20, 30]" v-model:current-page="claimReturnRecordsState.listQuery.pageIndex" background v-model:page-size="claimReturnRecordsState.listQuery.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="claimReturnRecordsState.total" class="page-position"> </el-pagination> + </div> + </div> + </div> + <return-and-watch ref="returnAndWatchRef" @refreshReturnData="initClaimReturnData"></return-and-watch> + </div> +</template> + +<script setup lang="ts"> +import {onMounted, reactive, watch, ref} from "vue"; +import { + claimReturnDataType, + ClaimReturnRecordsType, + materialType +} from "/@/views/facilityManagement/claimReturnRecords/index"; +import {claimReturnRecordsApi} from "/@/api/facilityManagement/claimReturnRecords"; +import {ElMessage} from "element-plus"; +import ReturnAndWatch from "/@/views/facilityManagement/claimReturnRecords/components/returnAndWatch.vue"; + +const returnAndWatchRef = ref(); + +const claimReturnRecordsState = reactive<ClaimReturnRecordsType>({ + tableLoading: true, + total: 0, + timeValue: [], + claimReturnData: [], + listQuery: { + pageSize: 10, + pageIndex: 1, + searchParams: { + materialName: null, + receiveUname: null, + endTime: null, + startTime: null, + } + }, +}); + +watch(() => claimReturnRecordsState.timeValue, (newVal, oldVal) => { + claimReturnRecordsState.listQuery.searchParams.startTime = newVal?.[0] || null; + claimReturnRecordsState.listQuery.searchParams.endTime = newVal?.[1] || null; +}) + +const initClaimReturnData = async () => { + claimReturnRecordsState.tableLoading = true; + let res = await claimReturnRecordsApi().getClaimReturnRecords(claimReturnRecordsState.listQuery); + if(res.data.code === '200') { + claimReturnRecordsState.claimReturnData = res.data.data; + claimReturnRecordsState.total = res.data.total; + }else { + ElMessage({ + type:'warning', + message: res.data.msg + }); + } + claimReturnRecordsState.tableLoading = false; +}; + +const onOpenReturnGoodsDialog = (title: string, value: claimReturnDataType) => { + returnAndWatchRef.value.openReturnAndWatchDialog(title, value) +} + +const onHandleSizeChange = (val: number) => { + claimReturnRecordsState.listQuery.pageSize = val; + initClaimReturnData(); +}; + +const onHandleCurrentChange = (val: number) => { + claimReturnRecordsState.listQuery.pageIndex = val; + initClaimReturnData(); +}; + +onMounted(() => { + initClaimReturnData() +}) +</script> + +<style scoped lang="scss"> +$homeNavLengh: 8; +.home-container { + height: calc(100vh - 144px); + box-sizing: border-box; + overflow: hidden; +.homeCard { + width: 100%; + padding: 20px; + box-sizing: border-box; + background: #fff; + border-radius: 4px; + +.main-card { + width: 100%; + height: 100%; +.cardTop { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 20px; +.mainCardBtn { + margin: 0; +} +} +.pageBtn { + height: 60px; + display: flex; + align-items: center; + justify-content: right; + +.demo-pagination-block + .demo-pagination-block { + margin-top: 10px; +} +.demo-pagination-block .demonstration { + margin-bottom: 16px; +} +} +} +&:last-of-type { + height: calc(100% - 100px); + } +} +.el-row { + display: flex; + align-items: center; + margin-bottom: 20px; +&:last-child { + margin-bottom: 0; + } +.grid-content { + align-items: center; + min-height: 36px; +} + +.topInfo { + display: flex; + align-items: center; + font-size: 16px; + font-weight: bold; + +& > div { + white-space: nowrap; + margin-right: 20px; + } +} +} +} +.stepItem { + width: 100%; + display: flex; + align-items: flex-start; + margin-bottom: 30px; + margin-left: 30px; + padding-bottom: 30px; + border-left: 2px solid #ccc; +&:first-of-type { + margin-top: 30px; + } +&:last-of-type { + margin-bottom: 0; + border-left: none; + } +.stepNum { + width: 30px; + height: 30px; + border-radius: 15px; + box-sizing: border-box; + color: #333; + border: 1px solid #999; + line-height: 28px; + text-align: center; + margin-right: 10px; + margin-left: -16px; + margin-top: -30px; +} +.stepCard { + width: 100%; + margin-top: -30px; + +.box-card { + width: 100%; +&:deep(.el-card__header) { + padding: 10px 15px; + } +.card-header { + width: 100%; + display: flex; + justify-content: space-between; + align-items: center; +& > div:first-of-type { + margin-right: 80px; + font-size: 18px; + font-weight: bold; + } +} +} +} +&:hover .card-header { + color: #0098f5; + } +&:hover .stepNum { + border: 2px solid #0098f5; + color: #0098f5; + } +} +</style> diff --git a/src/views/facilityManagement/deviceType/component/Dailog.vue b/src/views/facilityManagement/deviceType/component/Dailog.vue new file mode 100644 index 0000000..ce4d7af --- /dev/null +++ b/src/views/facilityManagement/deviceType/component/Dailog.vue @@ -0,0 +1,198 @@ +<template> + <el-dialog v-model="dialogVisible" :fullscreen="full" @close="resetForm(ruleFormRef)" :title="titles" width="50%" draggable> + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-form :model="form" :disabled="disabled" ref="ruleFormRef" :rules="rules" label-width="120px"> + <el-row> + <el-col :span="11"> + <el-form-item label="是否为设备内容" size="default" prop="isContent"> + <el-select v-model="form.isContent" placeholder="请选择" style="width: 100%"> + <el-option label="是" :value="1" /> + <el-option label="否" :value="2" /> + </el-select> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="父级编号" size="default" prop="parentId"> + <el-tree-select clearable check-strictly="true" v-model="form.parentId" :data="data" :props="propst" class="w100" placeholder="请选择" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="11"> + <el-form-item label="类别名称" size="default" prop="typeName"> + <el-input v-model="form.typeName" /> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="排列序列" size="default" prop="sortNum"> + <el-input v-model.number="form.sortNum" /> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="resetForm(ruleFormRef)">关闭</el-button> + <el-button type="primary" @click="submitForm(ruleFormRef)">确定</el-button> + </span> + </template> + </el-dialog> +</template> +<script lang="ts"> +import { defineComponent, ref, reactive } from 'vue'; +import type { FormInstance, FormRules } from 'element-plus'; +import { FullScreen } from '@element-plus/icons-vue'; +import { facilityManagementApi } from '/@/api/facilityManagement'; +import { ElMessage } from 'element-plus'; +import { type } from 'os'; +export default defineComponent({ + setup(prpos, { emit }) { + const dialogVisible = ref(false); + const form = ref({ + isContent: '', ////是否为设备内容 1:是 2:否 + typeName: '', ////类别名称 + parentId: '', ////父级ID,如果没有父级,为0 + isCheck: 0, ////是否检测 1:是 2:否 + isVisit: 0, ////是否巡检 1:是 2:否 + sortNum: '', //排列序列 + // id: '', //设备类型ID ,更新时必填 + }); + const titles = ref(); + const titleT = ref(); + const disabled = ref(false); + const openDailog = (title: string, id: number) => { + listApi(); + titleT.value = title; + dialogVisible.value = true; + titles.value = `${title}设备设施类型管理`; + if (title == '查看') { + disabled.value = true; + detail(id); + } else if (title == '修改') { + detail(id); + } else if (title == '添加') { + form.value.parentId = id; + } + }; + const detail = (id: number) => { + facilityManagementApi() + .getequipmentTypeMngDetail(id) + .then((res) => { + if (res.data.code == 200) { + form.value = res.data.data; + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + } + }); + }; + // 列表 + const listApi = () => { + facilityManagementApi() + .getequipmentTypeMngTreeData() + .then((res) => { + if (res.data.code == 200) { + data.value = res.data.data; + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + } + }); + }; + const data = ref([]); + const propst = { + label: 'typeName', + children: 'childList', + value: 'id', + }; + const ruleFormRef = ref<FormInstance>(); + const rules = reactive<FormRules>({ + isContent: [{ required: true, message: '是否为设备内容不能为空', trigger: 'change' }], + parentId: [], + typeName: [{ required: true, message: '类别名称不能为空', trigger: 'change' }], + sortNum: [ + { required: true, message: '排列序列不能为空', trigger: 'change' }, + { type: 'number', message: '请输入数字!', trigger: 'change' }, + ], + }); + const submitForm = async (formEl: FormInstance | undefined) => { + if (!formEl) return; + await formEl.validate((valid, fields) => { + if (valid) { + if (titleT.value == '新建') { + delete form.value.id; + } + facilityManagementApi() + .getequipmentTypeMngAddOrUpdate(form.value) + .then((res) => { + if (res.data.code == 200) { + dialogVisible.value = false; + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'success', + }); + emit('onAdd'); + formEl.resetFields(); + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + } + }); + } else { + console.log('error submit!', fields); + } + }); + disabled.value=false + }; + const resetForm = (formEl: FormInstance | undefined) => { + if (!formEl) return; + formEl.resetFields(); + dialogVisible.value = false; + disabled.value=false + }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + return { + titleT, + detail, + rules, + ruleFormRef, + listApi, + propst, + submitForm, + resetForm, + data, + disabled, + dialogVisible, + form, + titles, + openDailog, + full, + toggleFullscreen, + FullScreen, + }; + }, +}); +</script> +<style scoped> +.el-row { + padding: 0 0 20px 0; +} +</style> diff --git a/src/views/facilityManagement/deviceType/index.vue b/src/views/facilityManagement/deviceType/index.vue new file mode 100644 index 0000000..11958ec --- /dev/null +++ b/src/views/facilityManagement/deviceType/index.vue @@ -0,0 +1,130 @@ +<template> + <div class="box"> + <el-button type="primary" :icon="Plus" @click="openD('新建', 0)" size="default">新建</el-button> + <el-table :data="tableData" style="width: 100%" row-key="id" :tree-props="propse"> + <el-table-column align="center" label="是否为设备内容"> + <template #default="scope"> + <span v-if="scope.row.isContent == 1">是</span> + <span v-if="scope.row.isContent == 2">否</span> + </template> + </el-table-column> + <el-table-column align="center" label="巡检"> + <template #default="scope"> + <span v-if="scope.row.isVisit == 0">-</span> + <span v-if="scope.row.isVisit == 1">是</span> + <span v-if="scope.row.isVisit == 2">否</span> + </template> + </el-table-column> + <el-table-column align="center" label="检测"> + <template #default="scope"> + <span v-if="scope.row.isCheck == 0">-</span> + <span v-if="scope.row.isCheck == 1">是</span> + <span v-if="scope.row.isCheck == 2">否</span> + </template> + </el-table-column> + <el-table-column align="center" prop="typeName" label="类别名称" /> + <el-table-column align="center" label="操作"> + <template #default="scope"> + <el-button type="primary" link :icon="View" @click="openD('查看', scope.row.id)">查看</el-button> + <el-button type="primary" link :icon="EditPen" @click="openD('修改', scope.row.id)">修改</el-button> + <el-button type="primary" link :icon="Delete" @click="Deletes(scope.row.id)">删除</el-button> + <el-button type="primary" link :icon="CirclePlus" @click="openD('添加', scope.row.id)">添加下级设备设施类型管理</el-button> + </template> + </el-table-column> + </el-table> + <Dailog ref="Show" @onAdd="add"></Dailog> + </div> +</template> +<script lang="ts"> +import { defineComponent, onMounted, ref } from 'vue'; +import { Plus, View, EditPen, Delete, CirclePlus } from '@element-plus/icons-vue'; +import Dailog from './component/Dailog.vue'; +import { facilityManagementApi } from '/@/api/facilityManagement'; +import { ElMessage,ElMessageBox } from 'element-plus'; +export default defineComponent({ + components: { Dailog }, + setup() { + // 列表 + const listApi = () => { + facilityManagementApi() + .getequipmentTypeMngTreeData() + .then((res) => { + if (res.data.code == 200) { + tableData.value = res.data.data; + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + } + }); + }; + onMounted(() => { + listApi(); + }); + // 删除 + const Deletes = (id: number) => { + let arr = []; + arr.push(id); + ElMessageBox.confirm('确定删除所选项吗?', 'Warning', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + facilityManagementApi() + .getequipmentTypeMngDelete(arr) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'success', + }); + listApi(); + } else { + } + }); + }) + .catch(() => { + ElMessage({ + type: 'info', + message: 'Delete canceled', + }); + }); + }; + const add = () => { + listApi(); + }; + const tableData = ref(); + const propse = { + children: 'childList', + }; + const Show = ref(); + const openD = (title: string, id: number) => { + Show.value.openDailog(title, id); + }; + return { + propse, + add, + tableData, + Show, + Deletes, + openD, + listApi, + Plus, + View, + EditPen, + CirclePlus, + Delete, + }; + }, +}); +</script> +<style scoped> +.box { + padding: 20px; + background-color: #fff; +} +</style> diff --git a/src/views/facilityManagement/goodsDetailManage/components/checkOut.vue b/src/views/facilityManagement/goodsDetailManage/components/checkOut.vue new file mode 100644 index 0000000..f839bda --- /dev/null +++ b/src/views/facilityManagement/goodsDetailManage/components/checkOut.vue @@ -0,0 +1,136 @@ +<template> + <div> + <el-dialog :title="checkOutState.title" :close-on-click-modal="false" v-model="checkOutState.checkOutDialogVisible" width="30%"> + <el-form + :model="checkOutState.checkOutForm" + ref="checkOutFormRef" + size="default" + v-loading="checkOutState.loading" + element-loading-text="Loading..." + label-width="150px"> + <el-row> + <el-col :span="24" class="mb20"> + <el-form-item label="当前所选物资:"> + <el-input v-model="checkOutState.materialName" :readonly="true" class="input-add"> + </el-input> + </el-form-item> + </el-col> + <el-col :span="24" class="mb20"> + <el-form-item label="认领人:" prop="receiveUid"> + <el-select class="input-add" v-model="checkOutState.checkOutForm.receiveUid" placeholder="选择认领人"> + <el-option + v-for="item in checkOutState.userList" + :key="item.uid" + :value="item.uid" + :label="item.realName" + ></el-option> + </el-select> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button :disabled="checkOutState.loading" @click="checkOutState.batchOutStorageDialogVisible = !checkOutState.batchOutStorageDialogVisible" size="default">取 消</el-button> + <el-button :disabled="checkOutState.loading" type="primary" @click="submitCheckOutForm" v-throttle size="default">确 定</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script setup lang="ts"> + +import { reactive} from "vue"; +import {checkOutStateType, GoodsDetailDataType} from "/@/views/facilityManagement/goodsDetailManage/index"; +import {teamManageApi} from "/@/api/systemManage/basicDateManage/personShiftManage/teamManage"; +import {ElMessage} from "element-plus/es"; +import {goodsDetailApi} from "/@/api/facilityManagement/goodsDetailManage"; +import {useUserInfo} from "/@/stores/userInfo"; + +const checkOutState = reactive<checkOutStateType>({ + title: '', + loading: false, + checkOutDialogVisible: false, + materialName: '', + checkOutForm: { + id: null, + receiveUid: null, + ids: [], + }, + userList: [], +}) + +const openCheckOutDialog = (title: string, value: GoodsDetailDataType, ids:Array<number>, checkOutName: null | string) => { + checkOutState.title = title; + checkOutState.checkOutDialogVisible = true; + checkOutState.checkOutForm.receiveUid = null; + getUserByDepartment(useUserInfo().userInfos.depId as number) + if(title === '单独出库'){ + checkOutState.materialName = value.name as string + checkOutState.checkOutForm.id = value.id; + delete checkOutState.checkOutForm.ids; + }else{ + checkOutState.materialName = checkOutName as string + checkOutState.checkOutForm.ids = ids + delete checkOutState.checkOutForm.id; + } + + +} + +const submitCheckOutForm = async () => { + if(checkOutState.checkOutForm.receiveUid === null){ + ElMessage({ + type: 'warning', + message: '请选择认领人' + }) + }else{ + checkOutState.loading = true + let res = await (checkOutState.title === '单独出库' ? goodsDetailApi().checkOutBySingle(checkOutState.checkOutForm) : goodsDetailApi().checkOutByMore(checkOutState.checkOutForm)) + if(res.data.code === '200'){ + checkOutState.checkOutDialogVisible = false + emit('refreshGoodsDetail') + ElMessage({ + type: 'success', + message:'认领成功' + }) + }else{ + ElMessage({ + type: 'warning', + message: res.data.msg + }) + } + checkOutState.loading = false + } +} + +const getUserByDepartment = async (value: number) => { + let res = await teamManageApi().getAllMember(value); + if (res.data.code === '200') { + checkOutState.userList = JSON.parse(JSON.stringify(res.data.data)); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } +} + +const emit = defineEmits(['refreshGoodsDetail']) + +defineExpose({ + openCheckOutDialog +}) + +</script> + +<style scoped> +:deep(.el-dialog__header) { + padding: var(--el-dialog-padding-primary); + padding-bottom: 10px; + margin-right: 16px; + word-break: break-all; + text-align: center !important; +} +</style> diff --git a/src/views/facilityManagement/goodsDetailManage/components/goodsDetailAdd.vue b/src/views/facilityManagement/goodsDetailManage/components/goodsDetailAdd.vue new file mode 100644 index 0000000..b95f332 --- /dev/null +++ b/src/views/facilityManagement/goodsDetailManage/components/goodsDetailAdd.vue @@ -0,0 +1,278 @@ +<template> + <div class="system-add-menu-container"> + <el-dialog :title="goodsDetailAddState.title" :close-on-click-modal="false" v-model="goodsDetailAddState.goodsDetailAddVisible" width="30%"> + <el-form + :model="goodsDetailAddState.goodsDetailForm" + :rules="goodsDetailAddState.goodsDetailRules" + ref="goodsDetailFormRef" + size="default" + v-loading="goodsDetailAddState.loading" + element-loading-text="Loading..." + label-width="120px"> + <el-row> + <el-col :span="24" class="mb20"> + <el-form-item label="选择物资" prop="smId"> + <el-row :gutter="6"> +<!-- <el-col :span="8">--> +<!-- <el-select--> +<!-- filterable--> +<!-- placeholder="请选择部门"--> +<!-- clearable--> +<!-- @change="changeDepartment"--> +<!-- v-model="goodsDetailAddState.depId">--> +<!-- <el-option--> +<!-- v-for="item in goodsDetailAddState.departmentList"--> +<!-- :key="item.depId"--> +<!-- :value="item.depId"--> +<!-- :label="item.depName"--> +<!-- ></el-option>--> +<!-- </el-select>--> +<!-- </el-col>--> + <el-col :span="12"> + <el-select v-model="goodsDetailAddState.classifyId" placeholder="选择分类" @change="changeClassify" filterable clearable> + <el-option + v-for="item in goodsDetailAddState.classifyList" + :key="item.materialClassifyId" + :value="item.materialClassifyId" + :label="item.materialClassifyName" + ></el-option> + </el-select> + </el-col> + <el-col :span="12"> + <el-select v-model="goodsDetailAddState.goodsDetailForm.smId" placeholder="选择物资" filterable clearable> + <el-option + v-for="item in goodsDetailAddState.goodsList" + :key="item.smId" + :value="item.smId" + :label="item.materialName" + ></el-option> + </el-select> + </el-col> + </el-row> + </el-form-item> + </el-col> + <el-col :span="24" class="mb20"> + <el-row :gutter="6"> + <el-col :span="12"> + <el-form-item label="RFID起:" prop="startRfid"> + <el-input v-model="goodsDetailAddState.RFID" placeholder="选填"> + </el-input> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-input v-model="goodsDetailAddState.startRfid" @blur="checkLength('start')" @input="onVerifiyNumberInteger($event, 'start')" placeholder="选填"> + </el-input> + </el-col> + </el-row> + </el-col> + <el-col :span="24" class="mb20"> + <el-row :gutter="6"> + <el-col :span="12"> + <el-form-item label="RFID止:" prop="endRfid"> + <el-input v-model="goodsDetailAddState.RFID" placeholder="选填"> + </el-input> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-input @blur="checkLength('end')" @input="onVerifiyNumberInteger($event, 'end')" v-model="goodsDetailAddState.endRfid" placeholder="选填"> + </el-input> + </el-col> + </el-row> + </el-col> + <el-col :span="24" class="mb20"> + <el-form-item label="入库数量:" prop="wareHousingCount"> + <el-input @input="onVerifiyNumberInteger($event, 'wareHousingCount')" v-model="goodsDetailAddState.goodsDetailForm.wareHousingCount" placeholder="入库总数"> + </el-input> + </el-form-item> + </el-col> + <el-col :span="24" class="mb20"> + <el-form-item label="有效期类型:" prop="validType"> + <el-radio-group v-model="goodsDetailAddState.goodsDetailForm.validType"> + <el-radio :label="0">长期</el-radio> + <el-radio :label="1">非长期</el-radio> + </el-radio-group> + </el-form-item> + </el-col> + <el-col :span="24" class="mb20" v-if="goodsDetailAddState.goodsDetailForm.validType === 1"> + <el-form-item label="有效期至:" prop="validTime"> + <el-date-picker + v-model="goodsDetailAddState.goodsDetailForm.validTime" + type="datetime" + format="YYYY-MM-DD HH:mm:ss" + value-format="YYYY-MM-DD HH:mm:ss" + placeholder="选择日期时间" + style="width: 100%" /> + </el-form-item> + </el-col> + + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="goodsDetailAddState.goodsDetailAddVisible = !goodsDetailAddState.goodsDetailAddVisible" size="default">取 消</el-button> + <el-button type="primary" @click="submitGoodsDetail" v-throttle size="default">确 定</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script lang="ts" setup> +import {reactive, ref, watch} from 'vue' +import { + BaseMaterialListType, + ClassificationListType, + DepartmentType, + GoodsDetailDataType, + GoodsDetailAddType +} from "/@/views/facilityManagement/goodsDetailManage/index"; +import {isValidKey} from "/@/views/facilityManagement/safetyGoodsAndEquipment/index"; +import {ElMessage} from "element-plus/es"; +import {goodsDetailApi} from "/@/api/facilityManagement/goodsDetailManage"; +import {verifiyNumberInteger, verifyString} from "/@/utils/toolsValidate"; +import {useUserInfo} from "/@/stores/userInfo"; + +const goodsDetailFormRef = ref() +const userInfo = useUserInfo() + +const goodsDetailAddState = reactive<GoodsDetailAddType>({ + title: '新增入库', + RFID: 'RFIDXXX', + startRfid: '', + endRfid: '', + depId: null, + loading: false, + classifyId: null, + goodsDetailAddVisible: false, + goodsDetailForm: { + id: null, + smId: null, + validType: null, + validTime: null, + startRfid: null, + endRfid: null , + wareHousingCount: null, + }, + goodsDetailRules: { + smId: [{ required: true, message: '请选择物资名称', trigger: 'change' }], + validType: [{ required: true, message: '请选择时间类型', trigger: 'change' }], + validTime: [{ required: true, message: '请选择有效时间', trigger: 'change' }], + wareHousingCount: [{ required: true, message: '请填写入库数量', trigger: 'blur' }], + }, + departmentList: [], + classifyList: [], + goodsList: [], +}) + +watch(() => [goodsDetailAddState.startRfid,goodsDetailAddState.endRfid],(newVal, oldVal) => { + if(goodsDetailAddState.startRfid.length === 8 && goodsDetailAddState.endRfid.length === 8){ + goodsDetailAddState.goodsDetailForm.wareHousingCount = Number(goodsDetailAddState.endRfid) - Number(goodsDetailAddState.startRfid) + 1 + } +},{immediate :false}); + +const openGoodsDetailAddDialog = async (title: string, value: GoodsDetailDataType, departmentList: DepartmentType []) => { + goodsDetailAddState.goodsDetailAddVisible = true; + goodsDetailAddState.departmentList = departmentList; + setTimeout(() => { + goodsDetailFormRef.value.clearValidate(); + }); + goodsDetailAddState.startRfid = ''; + goodsDetailAddState.endRfid = ''; + goodsDetailAddState.goodsDetailForm = { + id: null, + smId: null, + validType: null, + validTime: null, + startRfid: null, + endRfid: null , + wareHousingCount: null, + }; + goodsDetailAddState.classifyList = goodsDetailAddState.departmentList.find(item => item.depId === userInfo.userInfos.depId)?.classificationList as Array<ClassificationListType> +} + +// const changeDepartment = (value: number | null) => { +// goodsDetailAddState.classifyId = null +// goodsDetailAddState.goodsDetailForm.smId = null +// goodsDetailAddState.classifyList = goodsDetailAddState.departmentList.find(item => item.depId === value)?.classificationList as Array<ClassificationListType> +// } + +const changeClassify = (value: number | null) => { + goodsDetailAddState.goodsDetailForm.smId = null + goodsDetailAddState.goodsList = JSON.parse(JSON.stringify( + (goodsDetailAddState.classifyList.find(item => item.materialClassifyId === value) ?? {baseMaterialList:[]})?.baseMaterialList as Array<BaseMaterialListType> + )) +} + +const submitGoodsDetail = () => { + goodsDetailFormRef.value.validate(async (valid: boolean) => { + if(valid){ + goodsDetailAddState.goodsDetailForm.startRfid = `RFID${goodsDetailAddState.startRfid}` + goodsDetailAddState.goodsDetailForm.endRfid = `RFID${goodsDetailAddState.endRfid}` + goodsDetailAddState.loading = true + let res = await goodsDetailApi().addGoodsDetail(goodsDetailAddState.goodsDetailForm) + if(res.data.code === '200'){ + goodsDetailAddState.goodsDetailAddVisible = false + emit('refreshData') + ElMessage({ + type: 'success', + message: '物资新增成功', + duration: 2000 + }); + }else{ + ElMessage({ + type:'warning', + message:res.data.msg + }) + } + goodsDetailAddState.loading = false + }else{ + ElMessage({ + type: 'warning', + message: '请完善基本信息' + }) + } + }) +} + +const checkLength = (value: string) => { + if(value === 'start' && goodsDetailAddState.startRfid.length !== 8){ + ElMessage({ + type:'warning', + message: 'RFID起不符合规范,请重新填入' + }) + goodsDetailAddState.startRfid = '' + goodsDetailAddState.goodsDetailForm.wareHousingCount = null + }else if(value === 'end' && goodsDetailAddState.endRfid.length !== 8){ + ElMessage({ + type:'warning', + message: 'RFID止不符合规范,请重新填入' + }) + goodsDetailAddState.endRfid = '' + goodsDetailAddState.goodsDetailForm.wareHousingCount = null + }else{ + return + } +} + +const onVerifiyNumberInteger = (val: number, title: string) => { + if(title === 'wareHousingCount'){ + goodsDetailAddState.goodsDetailForm.wareHousingCount = Number(verifiyNumberInteger(val.toString())) === 0 ? null : Number(verifiyNumberInteger(val.toString())); + }else if(title === 'start'){ + goodsDetailAddState.startRfid = verifyString(val.toString()); + }else{ + goodsDetailAddState.endRfid = verifyString(val.toString()); + } + +}; + +const emit = defineEmits(['refreshData',]) + +defineExpose({ + openGoodsDetailAddDialog +}) + +</script> + +<style scoped> + +</style> diff --git a/src/views/facilityManagement/goodsDetailManage/components/goodsDetailEdit.vue b/src/views/facilityManagement/goodsDetailManage/components/goodsDetailEdit.vue new file mode 100644 index 0000000..a89541d --- /dev/null +++ b/src/views/facilityManagement/goodsDetailManage/components/goodsDetailEdit.vue @@ -0,0 +1,227 @@ +<template> + <div class="system-add-menu-container"> + <el-dialog :title="goodsDetailEditState.title" :close-on-click-modal="false" v-model="goodsDetailEditState.goodsDetailEditVisible" width="30%"> + <el-form + :model="goodsDetailEditState.goodsDetailForm" + :rules="goodsDetailEditState.goodsDetailRules" + ref="goodsDetailFormRef" + size="default" + v-loading="goodsDetailEditState.loading" + element-loading-text="Loading..." + label-width="120px"> + <el-row> + <el-col :span="24" class="mb20"> + <el-form-item label="选择物资" prop="smId"> + <el-row :gutter="6"> +<!-- <el-col :span="8">--> +<!-- <el-select--> +<!-- filterable--> +<!-- placeholder="请选择部门"--> +<!-- clearable--> +<!-- @change="changeDepartment"--> +<!-- v-model="goodsDetailEditState.depId">--> +<!-- <el-option--> +<!-- v-for="item in goodsDetailEditState.departmentList"--> +<!-- :key="item.depId"--> +<!-- :value="item.depId"--> +<!-- :label="item.depName"--> +<!-- ></el-option>--> +<!-- </el-select>--> +<!-- </el-col>--> + <el-col :span="12"> + <el-select v-model="goodsDetailEditState.classifyId" placeholder="选择分类" @change="changeClassify" filterable clearable> + <el-option + v-for="item in goodsDetailEditState.classifyList" + :key="item.materialClassifyId" + :value="item.materialClassifyId" + :label="item.materialClassifyName" + ></el-option> + </el-select> + </el-col> + <el-col :span="12"> + <el-select v-model="goodsDetailEditState.goodsDetailForm.smId" placeholder="选择物资" filterable clearable> + <el-option + v-for="item in goodsDetailEditState.goodsList" + :key="item.smId" + :value="item.smId" + :label="item.materialName" + ></el-option> + </el-select> + </el-col> + </el-row> + </el-form-item> + </el-col> + <el-col :span="24" class="mb20"> + <el-form-item label="按RFID标记:" prop="rfid"> + <el-input v-model="goodsDetailEditState.goodsDetailForm.rfid" placeholder="选填"> + </el-input> + </el-form-item> + </el-col> + <el-col :span="24" class="mb20"> + <el-form-item label="有效期类型:" prop="validType"> + <el-radio-group v-model="goodsDetailEditState.goodsDetailForm.validType"> + <el-radio :label="0">长期</el-radio> + <el-radio :label="1">非长期</el-radio> + </el-radio-group> + </el-form-item> + </el-col> + <el-col :span="24" class="mb20" v-if="goodsDetailEditState.goodsDetailForm.validType === 1"> + <el-form-item label="有效期至:" prop="validTime"> + <el-date-picker + v-model="goodsDetailEditState.goodsDetailForm.validTime" + type="datetime" + format="YYYY-MM-DD HH:mm:ss" + value-format="YYYY-MM-DD HH:mm:ss" + placeholder="选择日期时间" + style="width: 100%" /> + </el-form-item> + </el-col> + + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="goodsDetailEditState.goodsDetailEditVisible = !goodsDetailEditState.goodsDetailEditVisible" size="default">取 消</el-button> + <el-button type="primary" @click="submitGoodsDetail" v-throttle size="default">确 定</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script lang="ts" setup> +import {reactive, ref, watch} from 'vue' +import { + BaseMaterialListType, + ClassificationListType, + DepartmentType, + GoodsDetailDataType, + GoodsDetailEditType +} from "/@/views/facilityManagement/goodsDetailManage/index"; +import {isValidKey} from "/@/views/facilityManagement/safetyGoodsAndEquipment/index"; +import {ElMessage} from "element-plus/es"; +import {goodsDetailApi} from "/@/api/facilityManagement/goodsDetailManage"; +import {useUserInfo} from "/@/stores/userInfo"; + +const goodsDetailFormRef = ref() +const userInfo = useUserInfo() + +const goodsDetailEditState = reactive<GoodsDetailEditType>({ + title: '编辑', + depId: null, + loading: false, + classifyId: null, + goodsDetailEditVisible: false, + goodsDetailForm: { + id: null, + smId: null, + rfid: null, + validType: null, + validTime: null, + }, + goodsDetailRules: { + smId: [{ required: true, message: '请选择物资名称', trigger: 'change' }], + validType: [{ required: true, message: '请选择时间类型', trigger: 'change' }], + validTime: [{ required: true, message: '请选择有效时间', trigger: 'change' }], + }, + departmentList: [], + classifyList: [], + goodsList: [], +}) + +// watch(() => goodsDetailEditState.depId ,(newVal, oldVal) => { +// goodsDetailEditState.classify = null +// goodsDetailEditState.goodsDetailForm.smId = null +// goodsDetailEditState.classifyList = goodsDetailEditState.departmentList.find(item => item.depId === newVal)?.classificationList as Array<ClassificationListType> +// },{immediate :false}); + +const openGoodsDetailEditDialog = async (title: string, value: GoodsDetailDataType, departmentList: DepartmentType []) => { + goodsDetailEditState.goodsDetailEditVisible = true; + goodsDetailEditState.departmentList = departmentList; + setTimeout(() => { + goodsDetailFormRef.value.clearValidate(); + }); + await changeDepartment(userInfo.userInfos.depId) + await changeClassify(value.bigClassifyId) + goodsDetailEditState.depId = value.depId + goodsDetailEditState.classifyId = value.bigClassifyId + for(let i in goodsDetailEditState.goodsDetailForm){ + if(isValidKey(i, goodsDetailEditState.goodsDetailForm)) { + goodsDetailEditState.goodsDetailForm[i] = value[i]; + } + } + debugger + +} + +const changeDepartment = (value: number | null) => { + goodsDetailEditState.classifyId = null + goodsDetailEditState.goodsDetailForm.smId = null + goodsDetailEditState.classifyList = JSON.parse(JSON.stringify( + (goodsDetailEditState.departmentList.find(item => item.depId === value) ?? {classificationList:[]})?.classificationList as Array<ClassificationListType> + )) +} + +const changeClassify = (value: number | null) => { + goodsDetailEditState.goodsDetailForm.smId = null + goodsDetailEditState.goodsList = goodsDetailEditState.classifyList.find(item => item.materialClassifyId === value)?.baseMaterialList as Array<BaseMaterialListType> +} + +const submitGoodsDetail = () => { + goodsDetailFormRef.value.validate(async (valid: boolean) => { + if(valid){ + goodsDetailEditState.loading = true + if(goodsDetailEditState.title === '新增入库') { + let res = await goodsDetailApi().addGoodsDetail(goodsDetailEditState.goodsDetailForm) + if(res.data.code === '200'){ + goodsDetailEditState.goodsDetailEditVisible = false + emit('refreshData') + ElMessage({ + type: 'success', + message: '物资新增成功', + duration: 2000 + }); + }else{ + ElMessage({ + type:'warning', + message:res.data.msg + }) + } + }else{ + let res = await goodsDetailApi().updateGoodsDetail(goodsDetailEditState.goodsDetailForm) + if(res.data.code === '200'){ + goodsDetailEditState.goodsDetailEditVisible = false + emit('refreshData') + ElMessage({ + type: 'success', + message: '物资编辑成功', + duration: 2000 + }); + }else{ + ElMessage({ + type:'warning', + message:res.data.msg + }) + } + } + goodsDetailEditState.loading = false + }else{ + ElMessage({ + type: 'warning', + message: '请完善基本信息' + }) + } + }) +} + +const emit = defineEmits(['refreshData',]) + +defineExpose({ + openGoodsDetailEditDialog +}) + +</script> + +<style scoped> + +</style> diff --git a/src/views/facilityManagement/goodsDetailManage/index.ts b/src/views/facilityManagement/goodsDetailManage/index.ts new file mode 100644 index 0000000..adde520 --- /dev/null +++ b/src/views/facilityManagement/goodsDetailManage/index.ts @@ -0,0 +1,101 @@ +export interface GoodsDetailStateType { + goodsDetailData: GoodsDetailDataType []; + departmentList: DepartmentType []; + irStatusList: Type []; + listQuery:{ + pageSize: number; + pageIndex: number; + searchParams: { + irStatus: number | null; + rfid: string | null; + smId: number | null; + } + }, + checkOutQuery: { + id: null | number; + claimantId: null | boolean; + }; + checkInQuery: { + id?: null | number; + ids?: Array<number>; + }; + checkOutNames: string; + total: number; +} + +export interface GoodsDetailEditType { + title: string; + depId: null | number; + loading: boolean; + classifyId: null | number; + goodsDetailEditVisible?: boolean; + goodsDetailForm: GoodsDetailEditFormType; + goodsDetailRules: {}; + departmentList: DepartmentType []; + classifyList: Array<ClassificationListType>; + goodsList: Array<BaseMaterialListType>; +} + +export interface GoodsDetailAddType extends GoodsDetailEditType{ + goodsDetailAddVisible: boolean; + RFID: string; + startRfid: string; + endRfid: string; +} + +export interface GoodsDetailEditFormType { + id: null | number; + rfid?: null | string; + startRfid?: null | string; + endRfid?: null | string; + wareHousingCount?: null | number; + smId: null | number; + validType: null | number; + validTime: null | string; +} + +export interface GoodsDetailDataType extends GoodsDetailEditFormType{ + name: string | null; + depId: null | number; + bigClassifyId: null | number; +} + +export interface Type { + id: number; + name: string; +} + +export interface DepartmentType { + depId: number; + depName: string; + classificationList: Array<ClassificationListType>; +} + +export interface ClassificationListType { + baseMaterialList: Array<BaseMaterialListType>; + materialClassifyId: number; + materialClassifyName: string; +} + +export interface BaseMaterialListType { + materialName: string; + smId: number; +} + + +export interface checkOutStateType { + title: string; + loading: boolean; + checkOutDialogVisible: boolean; + materialName: string; + checkOutForm: { + id?: null | number; + receiveUid: null | number; + ids?: Array<number>; + }; + // checkOutMoreForm: { + // ids: Array<number>; + // claimantId: null | boolean; + // } + userList: [] +} diff --git a/src/views/facilityManagement/goodsDetailManage/index.vue b/src/views/facilityManagement/goodsDetailManage/index.vue new file mode 100644 index 0000000..911bd66 --- /dev/null +++ b/src/views/facilityManagement/goodsDetailManage/index.vue @@ -0,0 +1,444 @@ +<template> + <div class="home-container"> + <div style="height: 100%"> + <el-row class="homeCard"> + <div class="basic-line"> + <span>在库状态:</span> + <el-select class="input-box" v-model="goodsDetailState.listQuery.searchParams.irStatus" placeholder="请选择在库状态" clearable filterable> + <el-option + v-for="item in goodsDetailState.irStatusList" + :key="item.id" + :value="item.id" + :label="item.name" + > + </el-option> + </el-select> + </div> + <div class="basic-line"> + <span>rfid:</span> + <el-input class="input-box" v-model="goodsDetailState.listQuery.searchParams.rfid" placeholder="rfid" clearable> </el-input> + </div> + + <div style="padding-bottom: 10px"> + <el-button size="large" type="primary" class="ml10" v-throttle @click="refreshGoodsDetailData"> + <el-icon> + <ele-Search /> + </el-icon> + 查询 + </el-button> + </div> + </el-row> + <div class="homeCard"> + <el-row class="cardTop"> + <el-col :span="12" class="mainCardBtn"> + <el-button type="primary" size="default" @click="openGoodsDetailAdd('新增入库','')">新增入库</el-button> + <el-button type="danger" size="default" @click="deleteBatchGoodsDetail('批量删除','')">批量删除</el-button> + <el-button type="warning" size="default" @click="checkInAndOut('批量出库','')">批量出库</el-button> +<!-- <el-button type="success" size="default" @click="checkInAndOut('批量重新入库','')">批量重新入库</el-button>--> + </el-col> + </el-row> + <div class="main-card"> + <el-table + :data="goodsDetailState.goodsDetailData" + style="width: 100%" height="calc(100% - 100px)" + :header-cell-style="{ background: '#fafafa' }" + @selection-change="handleSelectionChange" + > + <el-table-column type="selection" width="55" /> + <el-table-column prop="materialNo" label="物资编号" show-overflow-tooltip></el-table-column> + <el-table-column prop="bigClassifyName" label="分类" show-overflow-tooltip></el-table-column> + <el-table-column prop="depName" label="仓库/部门" show-overflow-tooltip></el-table-column> + <el-table-column prop="name" label="物资名称" show-overflow-tooltip></el-table-column> + <el-table-column prop="rfid" label="绑定RFID" show-overflow-tooltip></el-table-column> + <el-table-column prop="consumableName" label="是否是耗材" show-overflow-tooltip></el-table-column> + <el-table-column prop="validTypeName" label="保质期" show-overflow-tooltip></el-table-column> + <el-table-column prop="irStatusName" label="当前状态" show-overflow-tooltip></el-table-column> + <el-table-column prop="wareHousingTime" label="入库时间" show-overflow-tooltip></el-table-column> + <el-table-column prop="deliveryTime" label="出库时间" show-overflow-tooltip></el-table-column> + <el-table-column prop="validStatusName" label="有效" show-overflow-tooltip></el-table-column> + <el-table-column label="操作" width="250" align="center"> + <template #default="scope"> + <el-button size="small" text type="primary" :icon="Edit" @click="openGoodsDetailEdit('编辑', scope.row)">编辑</el-button> + <el-button v-if="scope.row.irStatus === 1" size="small" text type="success" :icon="Edit" @click="checkInAndOut('重新入库', scope.row)">重新入库</el-button> + <el-button v-if="scope.row.irStatus === 0" size="small" text type="warning" :icon="Edit" @click="checkInAndOut('单独出库', scope.row)">单独出库</el-button> + <el-button size="small" text type="danger" :icon="Delete" @click="deleteSingleGoodsDetail(scope.row)">删除</el-button> + </template> + </el-table-column> + </el-table> + <br /> + <el-pagination @size-change="onHandleSizeChange" @current-change="onHandleCurrentChange" :pager-count="5" :page-sizes="[10, 20, 30]" v-model:current-page="goodsDetailState.listQuery.pageIndex" background v-model:page-size="goodsDetailState.listQuery.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="goodsDetailState.total" class="page-position"> </el-pagination> + </div> + </div> + </div> + <goods-detail-edit ref="goodsDetailEditRef" @refreshData="initGoodsDetailData"></goods-detail-edit> + <goods-detail-add ref="goodsDetailAddRef" @refreshData="initGoodsDetailData"></goods-detail-add> + <check-out ref="checkOutRef" @refreshGoodsDetail="initGoodsDetailData"></check-out> + </div> +</template> + +<script setup lang="ts"> +import {onMounted, reactive, ref} from 'vue' +import { Edit, Delete, } from '@element-plus/icons-vue'; +import {ElMessage, ElMessageBox} from "element-plus"; +import { + GoodsDetailDataType, + GoodsDetailStateType +} from "/@/views/facilityManagement/goodsDetailManage/index"; +import {goodsDetailApi} from "/@/api/facilityManagement/goodsDetailManage"; +import { useRoute } from "vue-router"; +import GoodsDetailEdit from './components/goodsDetailEdit.vue' +import CheckOut from "/@/views/facilityManagement/goodsDetailManage/components/checkOut.vue"; +import GoodsDetailAdd from "/@/views/facilityManagement/goodsDetailManage/components/goodsDetailAdd.vue"; + +const route = useRoute() +const goodsDetailEditRef = ref() +const goodsDetailAddRef = ref() +const checkOutRef = ref() + +const goodsDetailState = reactive<GoodsDetailStateType>({ + goodsDetailData:[], + departmentList:[], + irStatusList:[{id: 0, name:'在库'}, {id: 1, name:'已出库'}], + listQuery:{ + pageSize: 10, + pageIndex: 1, + searchParams: { + irStatus: null, + rfid: null, + smId: null + } + }, + checkOutQuery: { + id: null, + claimantId: null, + }, + checkInQuery: { + ids: [], + }, + checkOutNames: '', + total:0, +}) + +const initGoodsDetailData = async () => { + let res = await goodsDetailApi().getGoodsDetailList(goodsDetailState.listQuery) + if(res.data.code === '200'){ + goodsDetailState.goodsDetailData = res.data.data; + goodsDetailState.total = res.data.total; + }else{ + ElMessage({ + type:'warning', + message:res.data.msg + }) + } +}; + +const openGoodsDetailEdit = (title: string, value: GoodsDetailDataType) => { + goodsDetailEditRef.value.openGoodsDetailEditDialog(title, value, goodsDetailState.departmentList) +}; + +const openGoodsDetailAdd = (title: string, value: GoodsDetailDataType) => { + goodsDetailAddRef.value.openGoodsDetailAddDialog(title, value, goodsDetailState.departmentList) +}; + +const checkInAndOut = (title: string, value:GoodsDetailDataType) => { + if(title === '重新入库'){ + goodsDetailState.checkInQuery = {} + goodsDetailState.checkInQuery.id = value.id + ElMessageBox.confirm(`此操作将重新入库:“${value.name}”,是否继续?`, '提示', { + confirmButtonText: '确认', + cancelButtonText: '取消', + type: 'warning' + }) + .then(async () => { + let res = await goodsDetailApi().checkInOne(goodsDetailState.checkInQuery); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + duration: 2000, + message: '重新入库成功' + }); + await initGoodsDetailData(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }) + .catch(() => {}); + }else if(title === '批量重新入库'){ + if(goodsDetailState.checkInQuery.ids?.length){ + ElMessageBox.confirm(`此操作将把所选中全部重新入库,是否继续?`, '提示', { + confirmButtonText: '确认', + cancelButtonText: '取消', + type: 'warning' + }) + .then(async () => { + let res = await goodsDetailApi().checkInMore(goodsDetailState.checkInQuery); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + duration: 2000, + message: '批量重新入库成功' + }); + await initGoodsDetailData(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }) + .catch(() => {}); + }else{ + ElMessage({ + type:'warning', + message: '请选择要批量重新入库的物资' + }) + } + }else if(title ==='单独出库'){ + checkOutRef.value.openCheckOutDialog(title, value, [], null); + }else{ + if(goodsDetailState.checkInQuery.ids?.length){ + checkOutRef.value.openCheckOutDialog(title, null, goodsDetailState.checkInQuery.ids, goodsDetailState.checkOutNames); + }else{ + ElMessage({ + type:'warning', + message: '请选择要出库的物资' + }) + } + } +} + +const handleSelectionChange = (val: Array<GoodsDetailDataType>) => { + goodsDetailState.checkInQuery.ids = val.map((item) => { + return item.id; + }) as Array<number>; + goodsDetailState.checkOutNames = val.map((item) => { + return item.name + }).join(',') +}; + +const getGoodsByLevel = async () => { + let res = await goodsDetailApi().getGoodsListByLevel(); + if (res.data.code === '200') { + goodsDetailState.departmentList = res.data.data; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } +}; + +const deleteSingleGoodsDetail = (row: any) => { + ElMessageBox.confirm(`此操作将永久删除该物资:“${row.name}”,是否继续?`, '提示', { + confirmButtonText: '确认', + cancelButtonText: '取消', + type: 'warning' + }) + .then(async () => { + let res = await goodsDetailApi().deleteSingleGoods({ id: row.id }); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + duration: 2000, + message: '删除成功' + }); + await initGoodsDetailData(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }) + .catch(() => {}); +}; + +const deleteBatchGoodsDetail = (row: any) => { + ElMessageBox.confirm(`此操作将永久删除这些物资,是否继续?`, '提示', { + confirmButtonText: '确认', + cancelButtonText: '取消', + type: 'warning' + }) + .then(async () => { + let res = await goodsDetailApi().deleteBatchGoods({ ids: goodsDetailState.checkInQuery.ids }); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + duration: 2000, + message: '删除成功' + }); + await initGoodsDetailData(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }) + .catch(() => {}); +}; + +const refreshGoodsDetailData = () => { + initGoodsDetailData(); +}; +// 分页改变 +const onHandleSizeChange = (val: number) => { + goodsDetailState.listQuery.pageSize = val; + initGoodsDetailData(); +}; +// 分页改变 +const onHandleCurrentChange = (val: number) => { + goodsDetailState.listQuery.pageIndex = val; + initGoodsDetailData(); +}; + +// const getDepartmentData = async () => { +// let res = await departmentApi().getDepartmentList(); +// if (res.data.code === '200') { +// goodsDetailState.departmentList = res.data.data; +// } else { +// ElMessage({ +// type: 'warning', +// message: res.data.msg +// }); +// } +// }; + +onMounted(() => { + goodsDetailState.listQuery.searchParams.smId = (Number(route.query.id) || null) + initGoodsDetailData(); + // getDepartmentData(); + getGoodsByLevel(); +}) +</script> + +<style scoped lang="scss"> +$homeNavLengh: 8; +.home-container { + height: calc(100vh - 144px); + box-sizing: border-box; + overflow: hidden; + .homeCard { + width: 100%; + padding: 20px; + box-sizing: border-box; + background: #fff; + border-radius: 4px; + + .main-card { + width: 100%; + height: 100%; + .cardTop { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 20px; + .mainCardBtn { + margin: 0; + } + } + .pageBtn { + height: 60px; + display: flex; + align-items: center; + justify-content: right; + + .demo-pagination-block + .demo-pagination-block { + margin-top: 10px; + } + .demo-pagination-block .demonstration { + margin-bottom: 16px; + } + } + } + &:last-of-type { + height: calc(100% - 100px); + } + } + .el-row { + display: flex; + align-items: center; + margin-bottom: 20px; + &:last-child { + margin-bottom: 0; + } + .grid-content { + align-items: center; + min-height: 36px; + } + + .topInfo { + display: flex; + align-items: center; + font-size: 16px; + font-weight: bold; + + & > div { + white-space: nowrap; + margin-right: 20px; + } + } + } +} +.stepItem { + width: 100%; + display: flex; + align-items: flex-start; + margin-bottom: 30px; + margin-left: 30px; + padding-bottom: 30px; + border-left: 2px solid #ccc; + &:first-of-type { + margin-top: 30px; + } + &:last-of-type { + margin-bottom: 0; + border-left: none; + } + .stepNum { + width: 30px; + height: 30px; + border-radius: 15px; + box-sizing: border-box; + color: #333; + border: 1px solid #999; + line-height: 28px; + text-align: center; + margin-right: 10px; + margin-left: -16px; + margin-top: -30px; + } + .stepCard { + width: 100%; + margin-top: -30px; + + .box-card { + width: 100%; + &:deep(.el-card__header) { + padding: 10px 15px; + } + .card-header { + width: 100%; + display: flex; + justify-content: space-between; + align-items: center; + & > div:first-of-type { + margin-right: 80px; + font-size: 18px; + font-weight: bold; + } + } + } + } + &:hover .card-header { + color: #0098f5; + } + &:hover .stepNum { + border: 2px solid #0098f5; + color: #0098f5; + } +} +</style> diff --git a/src/views/facilityManagement/goodsTypeManage/index.vue b/src/views/facilityManagement/goodsTypeManage/index.vue new file mode 100644 index 0000000..a994107 --- /dev/null +++ b/src/views/facilityManagement/goodsTypeManage/index.vue @@ -0,0 +1,435 @@ +<template> + <div class="home-container"> + <div style="height: 100%"> + <el-row class="homeCard"> + <div class="basic-line"> + </div> + <div class="basic-line"> + </div> + <div style="padding-bottom: 10px"> + <el-button size="default" type="primary" @click="onOpenGoodsClassifyDialog('新增', '')"> + <el-icon> + <ele-FolderAdd /> + </el-icon> + 新增分类 + </el-button> + </div> + </el-row> + <div class="homeCard"> + <div class="main-card"> + <el-table + :data="addGoodsState.goodsData" + style="width: 100%" + height="calc(100% - 100px)" + :header-cell-style="{ background: '#fafafa' }" + border + row-key="id" + :load="load" + :row-class-name="tableRowClassName" + :tree-props="{ children: 'childList', hasChildren: true }" + > + <el-table-column prop="materialClassifyName" label="分类名称" show-overflow-tooltip align="center"/> + <el-table-column prop="consumableName" label="是否耗材" show-overflow-tooltip align="center"/> + <el-table-column prop="materialClassifyName" label="类别" show-overflow-tooltip align="center"> + <template #default="scope"> + <div v-if="scope.row.parentId === 0">{{'分类名称'}}</div> + <div v-if="scope.row.parentId !== 0">{{'物资名称'}}</div> + </template> + </el-table-column> + <el-table-column label="操作" width="150" align="center"> + <template #default="scope"> + <el-button v-if="scope.row.parentId === 0" size="small" text type="primary" @click="onOpenGoodsClassifyDialog('新增物资', scope.row)"> + <el-icon> + <ele-FolderAdd /> + </el-icon> + 新增物资 + </el-button> + <el-button size="small" text type="primary" :icon="Edit" @click="onOpenGoodsClassifyDialog('编辑', scope.row)">编辑</el-button> + <el-button size="small" text type="danger" :icon="Delete" @click="deleteGoodsClassify(scope.row)">删除</el-button> + </template> + </el-table-column> + </el-table> + <br /> + <el-pagination @size-change="onHandleSizeChange" @current-change="onHandleCurrentChange" :pager-count="5" :page-sizes="[5, 10, 20]" v-model:current-page="addGoodsState.listQuery.pageIndex" background v-model:page-size="addGoodsState.listQuery.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="addGoodsState.total" class="page-position" style="padding-top: 20px;"> </el-pagination> + </div> + </div> + </div> + <el-dialog :title="addGoodsState.goodsClassifyTitle" :close-on-click-modal="false" v-model="addGoodsState.showAddGoodsClassifyDialog" width="30%"> + <el-form + :model="addGoodsState.goodsClassifyForm" + :rules="addGoodsState.goodsClassifyRules" + ref="goodsClassifyRef" + size="default" + label-width="120px"> + <el-row> + <el-col :span="24" class="mb20" v-if="!addGoodsState.goodsClassifyForm.parentId"> + <el-form-item label="分类名称" prop="materialClassifyName"> + <el-input v-model="addGoodsState.goodsClassifyForm.materialClassifyName" placeholder="输入分类名称" class="input-add"> + </el-input> + </el-form-item> + </el-col> + <el-col :span="24" class="mb20" v-if="addGoodsState.goodsClassifyForm.parentId"> + <el-form-item label="物资名称" prop="materialClassifyName"> + <el-input v-model="addGoodsState.goodsClassifyForm.materialClassifyName" placeholder="输入物资名称" class="input-add"> + </el-input> + </el-form-item> + </el-col> + <el-col :span="24" class="mb20" v-if="addGoodsState.goodsClassifyForm.parentId"> + <el-form-item label="是否耗材" prop="consumable"> + <el-select class="input-add" v-model="addGoodsState.goodsClassifyForm.consumable" placeholder="是否耗材" clearable filterable> + <el-option + v-for="item in addGoodsState.consumableList" + :key="item.id" + :value="item.id" + :label="item.name" + > + </el-option> + </el-select> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="addGoodsState.showAddGoodsClassifyDialog = !addGoodsState.showAddGoodsClassifyDialog" size="default">取 消</el-button> + <el-button type="primary" @click="submitGoodsClassify" v-throttle size="default">确 定</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script setup lang="ts"> +import {computed, nextTick, onMounted, reactive, ref, watch} from 'vue' +import { Edit, Delete, } from '@element-plus/icons-vue'; +import {AddGoodsStateType, BigClassifyType} from "/@/views/facilityManagement/safetyGoodsAndEquipment/index"; +import {mount} from "sortablejs"; +import {goodsAndEquipmentApi} from "/@/api/facilityManagement/safetyGoodsAndEquipment"; +import {ElMessage, valueEquals} from "element-plus/es"; +import {ElMessageBox} from "element-plus"; +import {inspectTaskApi} from "/@/api/intellectInspectSystem/inspectTask"; + +const addGoodsState = reactive<AddGoodsStateType>({ + title:'', + goodsClassifyTitle:'', + showAddGoodsDialog: false, + showAddGoodsClassifyDialog: false, + activeName: 'goodsInformation', + goodsData: [], + goodsBigClassifyList: [], + consumableList: [ + {id: 0, name: '是'}, + {id: 1, name: '否'}, + ], + total:0, + listQuery:{ + pageSize: 10, + pageIndex: 1, + searchParams: { + classifyName:'' + } + }, + goodsClassifyForm: { + id: null, + materialClassifyName: '', + parentId: null, + consumable: null, + }, + goodsClassifyRules: { + + }, +}); + +const openAddGoodsDialog = (goodsBigClassifyList: BigClassifyType []) => { + addGoodsState.showAddGoodsDialog = true + addGoodsState.goodsBigClassifyList = goodsBigClassifyList + getGoodsClassifyDataByPage() +} + +const onOpenGoodsClassifyDialog = (title: string, value:BigClassifyType ) => { + addGoodsState.showAddGoodsClassifyDialog = true + addGoodsState.goodsClassifyForm = { + id: null, + materialClassifyName: '', + parentId: null, + } + if(title === '新增') { + addGoodsState.goodsClassifyTitle = '新增分类' + }else if(title === '新增物资'){ + addGoodsState.goodsClassifyTitle = `新增${value.materialClassifyName}` + addGoodsState.goodsClassifyForm.parentId = value.id + } else if(title === '编辑' && value.parentId === 0){ + addGoodsState.goodsClassifyTitle = '编辑分类' + addGoodsState.goodsClassifyForm = { + id: value.id, + materialClassifyName: value.materialClassifyName, + consumable: null, + parentId: null, + } + }else { + addGoodsState.goodsClassifyTitle = `编辑${addGoodsState.goodsBigClassifyList.find(item => item.id === value.parentId)?.materialClassifyName as string}` + addGoodsState.goodsClassifyForm.parentId = addGoodsState.goodsBigClassifyList.find(item => item.id === value.parentId)?.id as number + addGoodsState.goodsClassifyForm.materialClassifyName = value.materialClassifyName + addGoodsState.goodsClassifyForm.consumable = value.consumable + addGoodsState.goodsClassifyForm.id = value.id + } +} + +const submitGoodsClassify = async () => { + if(addGoodsState.goodsClassifyTitle.substring(0,2) === '新增'){ + let res = await goodsAndEquipmentApi().addGoodsClassify(addGoodsState.goodsClassifyForm); + if(res.data.code === '200'){ + addGoodsState.showAddGoodsClassifyDialog = false; + await getGoodsClassifyDataByPage(); + ElMessage({ + type: 'success', + message: '新增成功', + duration: 2000 + }); + }else{ + ElMessage({ + type:'warning', + message:res.data.msg + }) + } + }else{ + let res = await goodsAndEquipmentApi().updateGoodsClassify(addGoodsState.goodsClassifyForm); + if(res.data.code === '200'){ + addGoodsState.showAddGoodsClassifyDialog = false; + await getGoodsClassifyDataByPage(); + emit('refreshClassify') + ElMessage({ + type: 'success', + message: '编辑成功', + duration: 2000 + }); + }else{ + ElMessage({ + type:'warning', + message:res.data.msg + }) + } + } +}; + +const deleteGoodsClassify = (row: BigClassifyType) => { + ElMessageBox.confirm(`此操作将永久删除该:“${row.materialClassifyName}”,是否继续?`, '提示', { + confirmButtonText: '确认', + cancelButtonText: '取消', + type: 'warning' + }) + .then(async () => { + let res = await goodsAndEquipmentApi().deleteGoodsClassify({ id: row.id }); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + duration: 2000, + message: '删除成功' + }); + await getGoodsClassifyDataByPage(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }) + .catch(() => {}); +}; + +const getGoodsClassifyDataByPage = async () => { + let res = await goodsAndEquipmentApi().getAllSafetyEquipmentByPage(addGoodsState.listQuery); + if(res.data.code === '200'){ + addGoodsState.goodsData = res.data.data + addGoodsState.total = res.data.total + }else{ + ElMessage({ + message:res.data.msg, + type:'warning' + }) + } +} + +const getAllSafetyEquipmentList = async () => { + let res = await goodsAndEquipmentApi().getAllSafetyEquipment(); + if(res.data.code === '200'){ + addGoodsState.goodsBigClassifyList = JSON.parse(JSON.stringify(res.data.data)) + }else{ + ElMessage({ + message:res.data.msg, + type:'warning' + }) + } +} + +const tableRowClassName = ( row: {rowIndex: number, row: BigClassifyType } ) => { + if (row.row.parentId === 0) { + return 'big-row'; + } else{ + return 'small-row'; + } +} + +const onHandleSizeChange = (val: number) => { + addGoodsState.listQuery.pageSize = val + getGoodsClassifyDataByPage() +} + +const onHandleCurrentChange = (val: number) => { + addGoodsState.listQuery.pageIndex = val + getGoodsClassifyDataByPage() +} + +const load = ( + row: BigClassifyType, + treeNode: unknown, + resolve: (date: BigClassifyType[]) => void +) => { + setTimeout(() => { + resolve([]) + }, 1000) +} + +const emit = defineEmits(['refreshClassify']) + +defineExpose({ + openAddGoodsDialog, +}); + +onMounted( () => { + getGoodsClassifyDataByPage(); + getAllSafetyEquipmentList(); +}) +</script> + +<style scoped lang="scss"> +$homeNavLengh: 8; +.home-container { + height: calc(100vh - 144px); + box-sizing: border-box; + overflow: hidden; + .homeCard { + width: 100%; + padding: 20px; + box-sizing: border-box; + background: #fff; + border-radius: 4px; + + .main-card { + width: 100%; + height: 100%; + .cardTop { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 20px; + .mainCardBtn { + margin: 0; + } + } + .pageBtn { + height: 60px; + display: flex; + align-items: center; + justify-content: right; + + .demo-pagination-block + .demo-pagination-block { + margin-top: 10px; + } + .demo-pagination-block .demonstration { + margin-bottom: 16px; + } + } + } + &:last-of-type { + height: calc(100% - 100px); + } + } + .el-row { + display: flex; + align-items: center; + margin-bottom: 20px; + &:last-child { + margin-bottom: 0; + } + .grid-content { + align-items: center; + min-height: 36px; + } + + .topInfo { + display: flex; + align-items: center; + font-size: 16px; + font-weight: bold; + + & > div { + white-space: nowrap; + margin-right: 20px; + } + } + } +} +.stepItem { + width: 100%; + display: flex; + align-items: flex-start; + margin-bottom: 30px; + margin-left: 30px; + padding-bottom: 30px; + border-left: 2px solid #ccc; + &:first-of-type { + margin-top: 30px; + } + &:last-of-type { + margin-bottom: 0; + border-left: none; + } + .stepNum { + width: 30px; + height: 30px; + border-radius: 15px; + box-sizing: border-box; + color: #333; + border: 1px solid #999; + line-height: 28px; + text-align: center; + margin-right: 10px; + margin-left: -16px; + margin-top: -30px; + } + .stepCard { + width: 100%; + margin-top: -30px; + + .box-card { + width: 100%; + &:deep(.el-card__header) { + padding: 10px 15px; + } + .card-header { + width: 100%; + display: flex; + justify-content: space-between; + align-items: center; + & > div:first-of-type { + margin-right: 80px; + font-size: 18px; + font-weight: bold; + } + } + } + } + &:hover .card-header { + color: #0098f5; + } + &:hover .stepNum { + border: 2px solid #0098f5; + color: #0098f5; + } +} +:deep(.el-table .big-row) { + font-size: 16px !important; + font-weight: 700; +} +</style> diff --git a/src/views/facilityManagement/keyEquipment/index.vue b/src/views/facilityManagement/keyEquipment/index.vue new file mode 100644 index 0000000..36c634d --- /dev/null +++ b/src/views/facilityManagement/keyEquipment/index.vue @@ -0,0 +1,449 @@ +<template> + <div> + <el-form ref="ruleFormRef" :model="ruleForm" status-icon label-width="20px" class="topTitle"> + <el-row> + <el-col :span="4"> + <el-form-item size="default"> + <el-input v-model="ruleForm.searchParams.name" placeholder="装置/部位名称"/> + </el-form-item> + </el-col> + <el-col :span="4"> + <el-form-item> + <el-button size="default" type="primary" @click="listApi">查询</el-button> + <el-button size="default" @click="resetForm">重置</el-button> + </el-form-item> + </el-col> + </el-row> + </el-form> + <el-row> + <el-col :span="4"> + <el-input v-model="filterText" style="height: 30px" placeholder="请输入关键字"/> + <div class="tree"> + <!-- <el-input v-model="filterText" style="height: 30px" placeholder="Filter keyword" />--> + <el-tree ref="treeRef" :data="data" :props="props" @node-click="handleNodeClick" + :filter-node-method="filterNode"/> + </div> + </el-col> + <el-col :span="20"> + <div class="btns"> + <div> + <el-button size="default" type="primary" :icon="Plus" @click="openD('新建')">新建</el-button> + <el-button size="default" :disabled="warning" type="warning" plain :icon="EditPen" + @click="openD('修改', deletAll[0])">修改</el-button> + <el-button size="default" :disabled="danger" type="danger" :icon="Delete" @click="onDeleteAll" + plain>删除 + </el-button> + </div> + <div> + <!-- <el-button size="default" :icon="Upload" @click="openUp"></el-button> + <el-button size="default" :icon="Download"></el-button> + <el-button size="default" :icon="Refresh"></el-button> --> + </div> + </div> + <div style="padding-left: 10px"> + <el-table ref="multipleTableRef" :data="tableData" @selection-change="handleSelectionChange" + style="width: 100%"> + <el-table-column type="selection" align="center" width="55"/> + <el-table-column type="expand"> + <template #default="scope"> + <el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick" + style="margin: 0 5%"> + <el-tab-pane label="设备保养" name="first"> + <el-table ref="multipleTableRef" :data="scope.row.takecareDetailList" + style="width: 100%"> + <el-table-column property="takecareMemo" align="center" label="保养情况" + sortable/> + <el-table-column property="leadingPersonName" align="center" label="保养负责人" + sortable/> + <el-table-column property="takecareDate" align="center" + :formatter="timeDate" label="保养日期" sortable/> + <el-table-column property="leadingPersonDepartmentName" align="center" + label="保养负责人单位" sortable/> + </el-table> + </el-tab-pane> + <el-tab-pane label="设备检查" name="second" + > + <el-table ref="multipleTableRef" :data="scope.row.checkDetailList" + style="width: 100%"> + <el-table-column property="testPersonName" align="center" label="检查人" + sortable/> + <el-table-column property="testDate" align="center" :formatter="timeDate" + label="检查日期" sortable/> + <el-table-column property="testPersonDepartmentName" align="center" label="检查人部门" sortable/> + <el-table-column property="testResult" align="center" label="检查结果" + sortable> + <template #default="scope"> + <span v-if="scope.row.testResult == 1">成功</span> + <span v-if="scope.row.testResult == 2">失败</span> + </template> + </el-table-column> + <el-table-column property="testStatus" align="center" label="检查状态" sortable/> + </el-table + > + </el-tab-pane> + <el-tab-pane label="设备检测" name="third"> + <el-table ref="multipleTableRef" :data="scope.row.testDetailList" + style="width: 100%"> + <el-table-column property="repairPersonName" align="center" label="检测人" + sortable/> + <el-table-column property="repairStarDate" align="center" :formatter="timeDate" + label="检测日期" sortable/> + <el-table-column property="repairPersonDepartmentName" align="center" + label="检测人单位" sortable/> + <el-table-column property="testMemo" align="center" label="检测内容" sortable/> + <el-table-column property="testResult" align="center" label="检测结果" + sortable/> + <el-table-column property="testStatus" align="center" label="检测状态" + sortable/> + </el-table> + </el-tab-pane> + <el-tab-pane label="设备维修" name="fourth"> + <el-table ref="multipleTableRef" :data="scope.row.repaireDetailList" + style="width: 100%"> + <el-table-column property="exceptionInfo" align="center" label="设施异常项" + sortable/> + <el-table-column property="repairStatus" align="center" label="维修状态" + sortable> + <template #default="scope"> + <span v-if="scope.row.repairStatus == 1">维修中</span> + <span v-if="scope.row.repairStatus == 2">已维修</span> + </template> + + </el-table-column> + <el-table-column property="repairMemo" align="center" label="维修情况" + sortable/> + <el-table-column property="repairPersonName" align="center" label="维修负责人" + sortable/> + <el-table-column property="repairPersonDepartmentName" align="center" + label="维修负责人单位" sortable/> + <el-table-column property="repairStartDate" align="center" + :formatter="timeDate" label="维修开始日期" sortable/> + <el-table-column property="repairEndDate" align="center" + :formatter="timeDate" label="维修结束日期" sortable/> + </el-table> + </el-tab-pane> + </el-tabs> + </template> + </el-table-column> + <el-table-column property="equipmentTypeName" align="center" label="类型/类别外键" sortable/> + <el-table-column property="name" align="center" label="装置/部位名称" sortable/> + <el-table-column property="departmentName" label="所属部门" align="center" sortable + show-overflow-tooltip/> + <el-table-column property="position" label="具体位置" align="center" sortable + show-overflow-tooltip/> + <el-table-column property="leadingPersonName" label="负责人姓名" align="center" sortable + show-overflow-tooltip/> + <el-table-column property="partType" label="装置部位分类" align="center" sortable + show-overflow-tooltip> + <template #default="scope"> + <span v-if="scope.row.partType == 1">关键装置</span> + <span v-if="scope.row.partType == 2">重点部位</span> + </template> + </el-table-column> + <el-table-column label="操作" align="center" width="250"> + <template #default="scope"> + <el-button link type="primary" size="default" :icon="View" + @click="openD('查看', scope.row.id)">查看 + </el-button> + <el-button link type="primary" size="default" :icon="EditPen" + @click="openD('修改', scope.row.id)">修改 + </el-button> + <el-button link type="primary" size="default" :icon="Delete" + @click="onDelete(scope.row.id)">删除 + </el-button> + </template> + </el-table-column> + </el-table> + <div class="pages"> + <el-pagination + v-model:currentPage="currentPage4" + v-model:page-size="pageSize4" + :page-sizes="[10, 20, 30, 40]" + layout="total, sizes, prev, pager, next, jumper" + :total="total" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + </div> + </el-col> + </el-row> + <!-- <updata ref="Show"></updata>--> + <DailogS ref="ShowD" @navAddorUpdata="onAddorUpdata"></DailogS> + </div> +</template> +<script lang="ts"> + import {defineComponent, ref, reactive, watch, onMounted} from 'vue'; + // import updata from '/@/components/updata/updata.vue' + import DailogS from '/@/components/equipmentDailog/DailogS.vue'; + import {ElTree, TabsPaneContext, ElMessage, ElMessageBox} from 'element-plus'; + import {EditPen, Plus, Delete, Download, Refresh, Upload, View} from '@element-plus/icons-vue'; + import {facilityManagementApi} from '/@/api/facilityManagement'; + import {timeDate} from '/@/assets/index.ts' + + interface Tree { + label: string; + children?: Tree[]; + } + + export default defineComponent({ + components: { + // updata, + DailogS, + }, + setup() { + const ruleForm = reactive({ + pageSize: 10, + pageIndex: 1, + searchParams: { + // equipmentTypeId: '', ////类型/类别外键 + name: '', ////装置/部位名称 + // departmentId: '',////所属部门 + // position: '', ////具体位置 + // leadingPersonName: '', ////负责人姓名 + // connectPersonId: '',////装置部位分类 + // infoTpe: 0, ////具体类型(页面左侧的导航栏使用) 0:仪器仪表信息 1:生产设备设施 2:安全设备设施 3:重点监管装置/设备 + equipmentTypeId: '' + }, + }); + // 重置 + const resetForm = () => { + ruleForm.searchParams.equipmentTypeId = ''; + listApi(); + }; + const listApi = () => { + // delete ruleForm.qName + facilityManagementApi() + .getkeypointEquipmentInfoAddOrList(ruleForm) + .then((res) => { + if (res.data.code == 200) { + tableData.value = res.data.data; + currentPage4.value = res.data.pageIndex; + pageSize4.value = res.data.pageSize; + total.value = res.data.total; + } else { + ElMessage.error(res.data.msg); + } + }); + }; + onMounted(() => { + listApi(); + }); + const onAddorUpdata = () => { + listApi(); + }; + const tableData = ref(); + const currentPage4 = ref(); + const pageSize4 = ref(); + const total = ref(); + const handleSizeChange = (val: number) => { + // console.log(`${val} items per page`); + ruleForm.pageSize = val; + listApi(); + }; + const handleCurrentChange = (val: number) => { + // console.log(`current page: ${val}`); + ruleForm.pageIndex = val; + listApi(); + }; + const filterText = ref(''); + const treeRef = ref<InstanceType<typeof ElTree>>(); + // 树形 + const listApiTree = () => { + facilityManagementApi() + .getequipmentTypeMngTreeData() + .then((res) => { + if (res.data.code == 200) { + console.log(res.data.data); + data.value = res.data.data; + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + } + }); + }; + const props = { + label: 'typeName', + children: 'childList', + value: 'id', + } + watch(filterText, (val) => { + treeRef.value!.filter(val); + }); + const filterNode = (value: string, data: Tree) => { + if (!value) return true; + return data.typeName.includes(value); + }; + const handleNodeClick = (data: Tree) => { + console.log(data) + ruleForm.searchParams.equipmentTypeId = data.id; + + listApi(); + }; + const data = ref([]); + onMounted(() => { + listApiTree(); + }); + // 删除 + const onDelete = (id: number) => { + let arr = [] + arr.push(id) + ElMessageBox.confirm('确定删除所选项吗?', 'Warning', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + facilityManagementApi() + .getkeypointEquipmentInfoDetele(arr) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + message: res.data.msg, + type: 'success', + }); + listApi(); + } else { + ElMessage.error(res.data.msg); + } + }); + }) + .catch(() => { + ElMessage({ + type: 'info', + message: 'Delete canceled', + }); + }); + }; + // 批量删除 + // const warning = ref(true); + const danger = ref(true); + const deletAll = ref(); + const handleSelectionChange = (val: any) => { + let valId = JSON.parse(JSON.stringify(val)); + let arr = []; + for (let i = 0; i < valId.length; i++) { + arr.push(valId[i].id); + } + deletAll.value = arr; + if (val.length == 1) { + // warning.value = false; + danger.value = false; + } else if (val.length == 0) { + // warning.value = true; + danger.value = true; + } else { + // warning.value = true; + danger.value = false; + } + }; + const onDeleteAll = () => { + ElMessageBox.confirm('确定删除所选项吗?', 'Warning', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + facilityManagementApi() + .getkeypointEquipmentInfoDetele(deletAll.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + message: res.data.msg, + type: 'success', + }); + listApi(); + } else { + ElMessage.error(res.data.msg); + } + }); + }) + .catch(() => { + // ElMessage({ + // type: 'info', + // message: 'Delete canceled', + // }); + }); + }; + + const activeName = ref('first'); + + const handleClick = (tab: TabsPaneContext, event: Event) => { + console.log(tab, event); + }; + // const Show=ref() + // const openUp=()=>{ + // Show.value.openDialog() + // } + // 新增弹窗 + const ShowD = ref(); + const openD = (title: String, id: number) => { + ShowD.value.openDailog(title, false, id, 2); + }; + return { + activeName, + handleClick, + ruleForm, + filterText, + treeRef, + props, + filterNode, + data, + tableData, + // Show, + // openUp, + ShowD, + danger, + openD, + // openEdit, + Plus, + EditPen, + listApiTree, + Delete, + View, + Download, + Refresh, + Upload, + resetForm, + listApi, + handleCurrentChange, + handleSizeChange, + onAddorUpdata, + total, + currentPage4, + pageSize4, + onDelete, + // warning, + handleSelectionChange, + onDeleteAll, + handleNodeClick, + timeDate, + deletAll + }; + }, + }); +</script> +<style scoped> + .topTitle { + background-color: #fff; + padding: 20px 0px 20px 0px; + margin-bottom: 10px; + } + + .tree { + height: 750px; + background-color: #fff; + overflow: hidden; + overflow-y: auto; + } + + .btns { + padding: 10px 0px 10px 10px; + display: flex; + justify-content: space-between; + background-color: #fff; + } +</style> diff --git a/src/views/facilityManagement/safetyEquipment/index.vue b/src/views/facilityManagement/safetyEquipment/index.vue new file mode 100644 index 0000000..d7f3ac5 --- /dev/null +++ b/src/views/facilityManagement/safetyEquipment/index.vue @@ -0,0 +1,391 @@ +<template> + <div> + <el-form ref="ruleFormRef" :model="ruleForm" status-icon label-width="20px" class="topTitle"> + <el-row> + <el-col :span="4"> + <el-form-item size="default"> + <el-input v-model="ruleForm.searchParams.qName" placeholder="装置设施名称" /> + </el-form-item> + </el-col> + <el-col :span="4"> + <el-form-item> + <el-button size="default" type="primary" @click="listApi">查询</el-button> + <el-button size="default" @click="resetForm">重置</el-button> + </el-form-item> + </el-col> + </el-row> + </el-form> + <el-row> + <el-col :span="4"> + <el-input v-model="filterText" style="height: 30px" placeholder="请输入关键字" /> + <div class="tree"> + <!-- <el-tree ref="treeRef" class="filter-tree" :data="data" :props="props" :filter-node-method="filterNode" /> --> + <el-tree ref="treeRef" :data="data" :props="props" @node-click="handleNodeClick" :filter-node-method="filterNode" /> + </div> + </el-col> + <el-col :span="20"> + <div class="btns"> + <div> + <el-button size="default" type="primary" :icon="Plus" @click="openD('新建')">新建</el-button> + <el-button size="default" :disabled="warning" type="warning" plain :icon="EditPen" + @click="openD('修改', deletAll[0])">修改</el-button> + <el-button size="default" :disabled="danger" type="danger" :icon="Delete" @click="onDeleteAll" plain>删除</el-button> + </div> + <div> + <!-- <el-button size="default" :icon="Upload" @click="openUp"></el-button> + <el-button size="default" :icon="Download"></el-button> + <el-button size="default" :icon="Refresh"></el-button> --> + </div> + </div> + <div style="padding-left: 10px"> + <el-table ref="multipleTableRef" :data="tableData" @selection-change="handleSelectionChange" style="width: 100%"> + <el-table-column type="selection" align="center" width="55" /> + <el-table-column type="expand"> + <template #default="scope"> + <el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClicks" style="margin: 0 5%"> + <el-tab-pane label="设备保养" name="first"> + <el-table ref="multipleTableRef" :data="scope.row.takecareDetailList" style="width: 100%"> + <el-table-column property="takecareMemo" align="center" label="保养情况" sortable /> + <el-table-column property="leadingPersonName" align="center" label="保养负责人" sortable /> + <el-table-column property="takecareDate" align="center" :formatter="timeDate" label="保养日期" sortable /> + <el-table-column property="leadingPersonDepartmentName" align="center" label="保养负责人单位" sortable /> + </el-table> + </el-tab-pane> + <el-tab-pane label="设备检查" name="second" + ><el-table ref="multipleTableRef" :data="scope.row.checkDetailList" style="width: 100%"> + <el-table-column property="leadingPersonName" align="center" label="检查人" sortable /> + <el-table-column property="createTime" align="center" :formatter="timeDate" label="检查日期" sortable /> + <el-table-column property="name" align="center" label="检查人部门" sortable /> + <el-table-column property="takecareMemo" align="center" label="检查结果" sortable /> + <el-table-column property="name" align="center" label="检查状态" sortable /> </el-table + ></el-tab-pane> + <el-tab-pane label="设备检测" name="third"> + <el-table ref="multipleTableRef" :data="scope.row.testDetailList" style="width: 100%"> + <el-table-column property="testPersonName" align="center" label="检测人" sortable /> + <el-table-column property="testDate" align="center" :formatter="timeDate" label="检测日期" sortable /> + <el-table-column property="testPersonDepartmentName" align="center" label="检测人单位" sortable /> + <el-table-column property="testMemo" align="center" label="检测内容" sortable /> + <el-table-column align="center" label="检测结果"> + <template #default="scope"> + <span v-if="scope.row.testResult == 1">成功</span> + <span v-if="scope.row.testResult == 2">失败</span> + </template> + </el-table-column> + <el-table-column property="testStatus" align="center" label="检测状态" sortable /> + </el-table> + </el-tab-pane> + <el-tab-pane label="设备维修" name="fourth"> + <el-table ref="multipleTableRef" :data="scope.row.repaireDetailList" style="width: 100%"> + <el-table-column property="exceptionInfo" align="center" label="设施异常项" sortable /> + <el-table-column align="center" label="维修状态"> + <template #default="scope"> + <span v-if="scope.row.repairStatus == 1">维修中</span> + <span v-if="scope.row.repairStatus == 2">已修好</span> + </template> + </el-table-column> + <el-table-column property="repairMemo" align="center" label="维修情况" sortable /> + <el-table-column property="repairPersonName" align="center" label="维修负责人" sortable /> + <el-table-column property="repairPersonDepartmentName" align="center" label="维修负责人单位" sortable /> + <el-table-column property="repairStartDate" align="center" :formatter="timeDate" label="维修开始日期" sortable /> + <el-table-column property="repairEndDate" align="center" :formatter="timeDate" label="维修结束日期" sortable /> + </el-table> + </el-tab-pane> + </el-tabs> + </template> + </el-table-column> + <el-table-column property="qName" label="装置设施名称" align="center" sortable /> + <el-table-column property="positionNum" align="center" label="装置设施位号" sortable /> + <el-table-column property="qUsage" align="center" label="装置设施用途" sortable /> + <el-table-column property="model" label="装置设施型号" align="center" sortable show-overflow-tooltip /> + <el-table-column property="equipmentTypeId" label="类型/类别外键" align="center" sortable show-overflow-tooltip /> + <el-table-column property="setPart" label="设施部位" align="center" sortable show-overflow-tooltip /> + <el-table-column label="操作" align="center" width="250"> + <template #default="scope"> + <el-button link type="primary" size="default" :icon="View" @click="openD('查看', scope.row.id)">查看</el-button> + <el-button link type="primary" size="default" :icon="EditPen" @click="openD('修改', scope.row.id)">修改</el-button> + <el-button link type="primary" size="default" :icon="Delete" @click="onDelete(scope.row.id)">删除</el-button> + </template> + </el-table-column> + </el-table> + <div class="pages"> + <el-pagination + v-model:currentPage="currentPage4" + v-model:page-size="pageSize4" + :page-sizes="[10, 20, 30, 40]" + layout="total, sizes, prev, pager, next, jumper" + :total="total" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + </div> + </el-col> + </el-row> + <!-- <updata ref="Show"></updata> --> + <Dailog ref="openAdd" @navAddorUpdata="onAddorUpdata"></Dailog> + </div> +</template> +<script lang="ts"> +import { defineComponent, ref, reactive, watch, onMounted } from 'vue'; +import updata from '/@/components/updata/updata.vue'; +import Dailog from '/@/components/equipmentDailog/Dailog.vue'; +import { ElTree, TabsPaneContext, ElMessage, ElMessageBox } from 'element-plus'; +import { facilityManagementApi } from '/@/api/facilityManagement'; +import { timeDate } from '/@/assets/index.ts'; +import { EditPen, View, Plus, Delete, Download, Refresh, Upload } from '@element-plus/icons-vue'; +interface Tree { + label: string; + children?: Tree[]; +} +export default defineComponent({ + components: { updata, Dailog }, + setup() { + // 搜索条件 + const ruleForm = reactive({ + pageSize: 10, + pageIndex: 1, + searchParams: { + qName: '', ////名称 + positionNum: '', ////位号 + equipmentTypeId: '', + infoType: 2, ////具体类型(页面左侧的导航栏使用) 0:仪器仪表信息 1:生产设备设施 2:安全设备设施 + }, + }); + // 重置 + const resetForm = () => { + ruleForm.searchParams.qName = ''; + ruleForm.searchParams.positionNum = ''; + ruleForm.searchParams.equipmentTypeId = ''; + listApiTree() + listApi(); + }; + const listApi = () => { + facilityManagementApi() + .getequipmentInfoList(ruleForm) + .then((res) => { + if (res.data.code == 200) { + tableData.value = res.data.data; + currentPage4.value = res.data.pageIndex; + pageSize4.value = res.data.pageSize; + total.value = res.data.total; + } else { + ElMessage.error(res.data.msg); + } + }); + }; + // + onMounted(() => { + listApi(); + }); + const onAddorUpdata = () => { + listApi(); + }; + // 表格 + const tableData = ref(); + const currentPage4 = ref(); + const pageSize4 = ref(); + const total = ref(); + const handleSizeChange = (val: number) => { + // console.log(`${val} items per page`); + ruleForm.pageSize = val; + listApi(); + }; + const handleCurrentChange = (val: number) => { + // console.log(`current page: ${val}`); + ruleForm.pageIndex = val; + listApi(); + }; + // 弹窗 + const openAdd = ref(); + const openD = (title: String, id: number) => { + openAdd.value.openDailog(title, false, id, 2); + }; + // 删除 + const onDelete = (id: number) => { + let arr = []; + arr.push(id); + ElMessageBox.confirm('确定删除所选项吗?', 'Warning', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + facilityManagementApi() + .getequipmentInfoDelete(arr) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + message: res.data.msg, + type: 'success', + }); + listApi(); + } else { + ElMessage.error(res.data.msg); + } + }); + }) + .catch(() => { + ElMessage({ + type: 'info', + message: 'Delete canceled', + }); + }); + }; + // 批量删除 + const warning = ref(true); + const danger = ref(true); + const deletAll = ref(); + const handleSelectionChange = (val: any) => { + let valId = JSON.parse(JSON.stringify(val)); + let arr = []; + for (let i = 0; i < valId.length; i++) { + arr.push(valId[i].id); + } + deletAll.value = arr; + if (val.length == 1) { + warning.value = false; + danger.value = false; + } else if (val.length == 0) { + warning.value = true; + danger.value = true; + } else { + warning.value = true; + danger.value = false; + } + }; + const onDeleteAll = () => { + ElMessageBox.confirm('确定删除所选项吗?', 'Warning', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + facilityManagementApi() + .getequipmentInfoDelete(deletAll.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + message: res.data.msg, + type: 'success', + }); + listApi(); + } else { + ElMessage.error(res.data.msg); + } + }); + }) + .catch(() => { + // ElMessage({ + // type: 'info', + // message: 'Delete canceled', + // }); + }); + }; + const filterText = ref(''); + const treeRef = ref<InstanceType<typeof ElTree>>(); + // 树形 + const listApiTree = () => { + facilityManagementApi() + .getequipmentTypeMngTreeData() + .then((res) => { + if (res.data.code == 200) { + data.value = res.data.data; + } else { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'error', + }); + } + }); + }; + const props = { + label: 'typeName', + children: 'childList', + value: 'id', + }; + watch(filterText, (val) => { + treeRef.value!.filter(val); + }); + + const filterNode = (value: string, data: Tree) => { + if (!value) return true; + return data.typeName.includes(value); + }; + const handleNodeClick = (data: Tree) => { + ruleForm.searchParams.equipmentTypeId = data.id; + ruleForm.searchParams.equipmentTypeId = data.id; + listApi(); + }; + const data = ref([]); + onMounted(() => { + listApiTree(); + }); + const handleClicks = (tab: TabsPaneContext, event: Event) => { + console.log(tab, event); + }; + + const activeName = ref('first'); + // const Show=ref() + // const openUp=()=>{ + // Show.value.openDialog() + // } + return { + handleNodeClick, + ruleForm, + resetForm, + listApi, + onAddorUpdata, + tableData, + currentPage4, + pageSize4, + total, + handleSizeChange, + handleCurrentChange, + onDelete, + warning, + danger, + deletAll, + handleSelectionChange, + onDeleteAll, + listApiTree, + handleClicks, + filterText, + treeRef, + props, + filterNode, + data, + openAdd, + openD, + activeName, + Plus, + EditPen, + Delete, + Download, + Refresh, + View, + Upload, + timeDate, + }; + }, +}); +</script> +<style scoped> +.topTitle { + background-color: #fff; + padding: 20px 0px 20px 0px; + margin-bottom: 10px; +} +.tree { + height: 750px; + background-color: #fff; + overflow: hidden; + overflow-y: auto; +} +.btns { + padding: 10px 0px 10px 10px; + display: flex; + justify-content: space-between; + background-color: #fff; +} +</style> diff --git a/src/views/facilityManagement/safetyGoodsAndEquipment/components/addGoodsDialog.vue b/src/views/facilityManagement/safetyGoodsAndEquipment/components/addGoodsDialog.vue new file mode 100644 index 0000000..55a5571 --- /dev/null +++ b/src/views/facilityManagement/safetyGoodsAndEquipment/components/addGoodsDialog.vue @@ -0,0 +1,270 @@ +<template> + <div class="system-add-menu-container"> + <el-dialog :title="addGoodsState.title" :close-on-click-modal="false" v-model="addGoodsState.showAddGoodsDialog" width="50%"> + <el-tabs class="active" v-model="addGoodsState.activeName"> + <el-tab-pane label="物资信息" name="goodsInformation"> + <div class="filter-container" style="padding-bottom: 20px"> + <el-button size="default" type="primary" @click="onOpenGoodsClassifyDialog('新增', '')"> + <el-icon> + <ele-FolderAdd /> + </el-icon> + 新增分类 + </el-button> + </div> + + <el-table + :data="addGoodsState.goodsData" + border fit highlight-current-row lazy + row-key="id" + :load="load" + :row-class-name="tableRowClassName" + :header-cell-style="{ background: '#fafafa' }" + :tree-props="{ children: 'childList', hasChildren: true }" + style="width: 100%"> + <el-table-column prop="materialClassifyName" label="分类名称" show-overflow-tooltip align="center"/> + <el-table-column prop="materialClassifyName" label="类别" show-overflow-tooltip align="center"> + <template #default="scope"> + <div v-if="scope.row.parentId === 0">{{'分类名称'}}</div> + <div v-if="scope.row.parentId !== 0">{{'物资名称'}}</div> + </template> + </el-table-column> + <el-table-column label="操作" width="150" align="center"> + <template #default="scope"> + <el-button v-if="scope.row.parentId === 0" size="small" text type="primary" @click="onOpenGoodsClassifyDialog('新增物资', scope.row)"> + <el-icon> + <ele-FolderAdd /> + </el-icon> + 新增物资 + </el-button> + <el-button size="small" text type="primary" :icon="Edit" @click="onOpenGoodsClassifyDialog('编辑', scope.row)">编辑</el-button> + <el-button size="small" text type="danger" :icon="Delete" @click="deleteGoodsClassify(scope.row)">删除</el-button> + </template> + </el-table-column> + </el-table> + <el-pagination @size-change="onHandleSizeChange" @current-change="onHandleCurrentChange" :pager-count="5" :page-sizes="[5, 10, 20]" v-model:current-page="addGoodsState.listQuery.pageIndex" background v-model:page-size="addGoodsState.listQuery.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="addGoodsState.total" class="page-position" style="padding-top: 20px;"> </el-pagination> + </el-tab-pane> + </el-tabs> + </el-dialog> + <el-dialog :title="addGoodsState.goodsClassifyTitle" :close-on-click-modal="false" v-model="addGoodsState.showAddGoodsClassifyDialog" width="30%"> + <el-form + :model="addGoodsState.goodsClassifyForm" + :rules="addGoodsState.goodsClassifyRules" + ref="goodsClassifyRef" + size="default" + label-width="120px"> + <el-row> + <el-col :span="24" class="mb20" v-if="!addGoodsState.goodsClassifyForm.parentId"> + <el-form-item label="分类名称" prop="materialClassifyName"> + <el-input v-model="addGoodsState.goodsClassifyForm.materialClassifyName" placeholder="输入分类名称" class="input-add"> + </el-input> + </el-form-item> + </el-col> + <el-col :span="24" class="mb20" v-if="addGoodsState.goodsClassifyForm.parentId"> + <el-form-item label="物资名称" prop="materialClassifyName"> + <el-input v-model="addGoodsState.goodsClassifyForm.materialClassifyName" placeholder="输入物资名称" class="input-add"> + </el-input> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="addGoodsState.showAddGoodsClassifyDialog = !addGoodsState.showAddGoodsClassifyDialog" size="default">取 消</el-button> + <el-button type="primary" @click="submitGoodsClassify" v-throttle size="default">确 定</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script setup lang="ts"> +import {computed, nextTick, onMounted, reactive, ref, watch} from 'vue' +import { Edit, Delete, } from '@element-plus/icons-vue'; +import {AddGoodsStateType, BigClassifyType} from "/@/views/facilityManagement/safetyGoodsAndEquipment/index"; +import {mount} from "sortablejs"; +import {goodsAndEquipmentApi} from "/@/api/facilityManagement/safetyGoodsAndEquipment"; +import {ElMessage, valueEquals} from "element-plus/es"; +import {ElMessageBox} from "element-plus"; +import {inspectTaskApi} from "/@/api/intellectInspectSystem/inspectTask"; + +const addGoodsState = reactive<AddGoodsStateType>({ + title:'', + goodsClassifyTitle:'', + showAddGoodsDialog: false, + showAddGoodsClassifyDialog: false, + activeName: 'goodsInformation', + goodsData: [], + goodsBigClassifyList: [], + total:0, + listQuery:{ + pageSize: 5, + pageIndex: 1, + searchParams: { + classifyName:'' + } + }, + goodsClassifyForm: { + id: null, + materialClassifyName: '', + parentId: null, + }, + goodsClassifyRules: { + + }, +}); + +const openAddGoodsDialog = (goodsBigClassifyList: BigClassifyType []) => { + addGoodsState.showAddGoodsDialog = true + addGoodsState.goodsBigClassifyList = goodsBigClassifyList + getGoodsClassifyDataByPage() +} + +const onOpenGoodsClassifyDialog = (title: string, value:BigClassifyType ) => { + addGoodsState.showAddGoodsClassifyDialog = true + addGoodsState.goodsClassifyForm = { + id: null, + materialClassifyName: '', + parentId: null, + } + if(title === '新增') { + addGoodsState.goodsClassifyTitle = '新增分类' + }else if(title === '新增物资'){ + addGoodsState.goodsClassifyTitle = `新增${value.materialClassifyName}` + addGoodsState.goodsClassifyForm.parentId = value.id + } else if(title === '编辑' && value.parentId === 0){ + addGoodsState.goodsClassifyTitle = '编辑分类' + addGoodsState.goodsClassifyForm = { + id: value.id, + materialClassifyName: value.materialClassifyName, + parentId: null, + } + }else { + addGoodsState.goodsClassifyTitle = `编辑${addGoodsState.goodsBigClassifyList.find(item => item.id === value.parentId)?.materialClassifyName as string}` + addGoodsState.goodsClassifyForm.parentId = addGoodsState.goodsBigClassifyList.find(item => item.id === value.parentId)?.id as number + addGoodsState.goodsClassifyForm.materialClassifyName = value.materialClassifyName + addGoodsState.goodsClassifyForm.id = value.id + } +} + +const submitGoodsClassify = async () => { + if(addGoodsState.goodsClassifyTitle.substring(0,2) === '新增'){ + let res = await goodsAndEquipmentApi().addGoodsClassify(addGoodsState.goodsClassifyForm); + if(res.data.code === '200'){ + addGoodsState.showAddGoodsClassifyDialog = false; + await getGoodsClassifyDataByPage(); + ElMessage({ + type: 'success', + message: '新增成功', + duration: 2000 + }); + }else{ + ElMessage({ + type:'warning', + message:res.data.msg + }) + } + }else{ + let res = await goodsAndEquipmentApi().updateGoodsClassify(addGoodsState.goodsClassifyForm); + if(res.data.code === '200'){ + addGoodsState.showAddGoodsClassifyDialog = false; + await getGoodsClassifyDataByPage(); + emit('refreshClassify') + ElMessage({ + type: 'success', + message: '编辑成功', + duration: 2000 + }); + }else{ + ElMessage({ + type:'warning', + message:res.data.msg + }) + } + } +}; + +const deleteGoodsClassify = (row: BigClassifyType) => { + ElMessageBox.confirm(`此操作将永久删除该:“${row.materialClassifyName}”,是否继续?`, '提示', { + confirmButtonText: '确认', + cancelButtonText: '取消', + type: 'warning' + }) + .then(async () => { + let res = await goodsAndEquipmentApi().deleteGoodsClassify({ id: row.id }); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + duration: 2000, + message: '删除成功' + }); + await getGoodsClassifyDataByPage(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }) + .catch(() => {}); +}; + +const getGoodsClassifyDataByPage = async () => { + let res = await goodsAndEquipmentApi().getAllSafetyEquipmentByPage(addGoodsState.listQuery); + if(res.data.code === '200'){ + addGoodsState.goodsData = res.data.data + addGoodsState.total = res.data.total + }else{ + ElMessage({ + message:res.data.msg, + type:'warning' + }) + } +} + +const tableRowClassName = ( row: {rowIndex: number, row: BigClassifyType } ) => { + if (row.row.parentId === 0) { + return 'big-row'; + } else{ + return 'small-row'; + } +} + +const onHandleSizeChange = (val: number) => { + addGoodsState.listQuery.pageSize = val + getGoodsClassifyDataByPage() +} + +const onHandleCurrentChange = (val: number) => { + addGoodsState.listQuery.pageIndex = val + getGoodsClassifyDataByPage() +} + +const load = ( + row: BigClassifyType, + treeNode: unknown, + resolve: (date: BigClassifyType[]) => void +) => { + setTimeout(() => { + resolve([]) + }, 1000) +} + +const emit = defineEmits(['refreshClassify']) + +defineExpose({ + openAddGoodsDialog, +}); + + +</script> + +<style scoped> +/*:deep(.el-overlay .el-overlay-dialog .el-dialog .el-dialog__body) {*/ +/* padding-bottom: 20px !important;*/ +/*}*/ +:deep(.el-table .big-row) { + font-size: 16px !important; + font-weight: 700; +} + +</style> diff --git a/src/views/facilityManagement/safetyGoodsAndEquipment/components/batchInStorage.vue b/src/views/facilityManagement/safetyGoodsAndEquipment/components/batchInStorage.vue new file mode 100644 index 0000000..a6d17da --- /dev/null +++ b/src/views/facilityManagement/safetyGoodsAndEquipment/components/batchInStorage.vue @@ -0,0 +1,145 @@ +<template> + <div> + <el-dialog :title="batchInStorageState.title" :close-on-click-modal="false" v-model="batchInStorageState.batchInStorageDialogVisible" width="30%"> + <el-form + :model="batchInStorageState.inStorageData" + :rules="batchInStorageState.inStorageDataRules" + ref="inStorageDataRef" + size="default" + v-loading="batchInStorageState.loading" + element-loading-text="Loading..." + label-width="150px"> + <el-row> + <el-col :span="24" class="mb20"> + <el-form-item label="当前所选物资/设备:"> + <el-input v-model="batchInStorageState.materialName" :readonly="true" class="input-add"> + </el-input> + </el-form-item> + </el-col> + <el-col :span="24" class="mb20"> + <el-form-item label="按RFID标记:" prop="rfid"> + <el-input v-model="batchInStorageState.inStorageData.rfid" placeholder="选填" class="input-add"> + </el-input> + </el-form-item> + </el-col> + <el-col :span="24" class="mb20"> + <el-form-item label="入库数量:" prop="wareHousingCount"> + <el-input @input="onVerifiyNumberInteger($event, 'noticeTime')" v-model="batchInStorageState.inStorageData.wareHousingCount" placeholder="输入入库数量" class="input-add"> + </el-input> + </el-form-item> + </el-col> + <el-col :span="24" class="mb20"> + <el-form-item label="有效期类型:" prop="validType"> + <el-radio-group v-model="batchInStorageState.inStorageData.validType"> + <el-radio :label="0">长期</el-radio> + <el-radio :label="1">非长期</el-radio> + </el-radio-group> + </el-form-item> + </el-col> + <el-col :span="24" class="mb20" v-if="batchInStorageState.inStorageData.validType === 1"> + <el-form-item label="有效期至:" prop="validTime"> + <el-date-picker + v-model="batchInStorageState.inStorageData.validTime" + type="datetime" + format="YYYY-MM-DD HH:mm:ss" + value-format="YYYY-MM-DD HH:mm:ss" + placeholder="选择日期时间" + style="width: 90%" /> + </el-form-item> + </el-col> + + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button :disabled="batchInStorageState.loading" @click="batchInStorageState.batchInStorageDialogVisible = !batchInStorageState.batchInStorageDialogVisible" size="default">取 消</el-button> + <el-button :disabled="batchInStorageState.loading" type="primary" @click="submitInStorageData" v-throttle size="default">确 定</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script setup lang="ts"> +import { reactive, ref} from 'vue' +import {BatchInStorageStateType, DataType} from "/@/views/facilityManagement/safetyGoodsAndEquipment/index"; +import {verifiyNumberInteger} from "/@/utils/toolsValidate"; +import {ElMessage} from "element-plus"; +import { goodsAndEquipmentApi } from '../../../../api/facilityManagement/safetyGoodsAndEquipment/index' + +const inStorageDataRef = ref() + +const batchInStorageState = reactive<BatchInStorageStateType>({ + title: '批量入库', + loading: false, + materialName: '', + batchInStorageDialogVisible: false, + inStorageData:{ + smId: null, + wareHousingCount: null, + validType: null, + validTime: null, + rfid: null, + }, + inStorageDataRules: { + wareHousingCount: [{ required: true, message: '请填写物资数量', trigger: 'blur' }], + validType: [{ required: true, message: '请选择有效期类型', trigger: 'change' }], + validTime: [{ required: true, message: '请选择有效期至', trigger: 'change' }], + }, +}) + +const openBatchInStorageDialog = (value: DataType) => { + batchInStorageState.batchInStorageDialogVisible = true + batchInStorageState.inStorageData.smId = value.id + batchInStorageState.materialName = value.materialName +} + +const submitInStorageData = () => { + batchInStorageState.loading = true; + inStorageDataRef.value.validate(async (valid: boolean) => { + if(valid){ + let res = await goodsAndEquipmentApi().batchInStorageGoods(batchInStorageState.inStorageData); + if(res.data.code === '200'){ + batchInStorageState.batchInStorageDialogVisible = false; + emit('refreshData') + ElMessage({ + type: 'success', + message: '入库成功', + duration: 2000 + }); + }else{ + ElMessage({ + type: 'warning', + message:res.data.msg + }); + } + }else{ + ElMessage({ + type: 'warning', + message: '请完善基本信息' + }); + } + }); + batchInStorageState.loading = false; +}; + +const emit = defineEmits(['refreshData',]); + +defineExpose({ + openBatchInStorageDialog, +}) + +const onVerifiyNumberInteger = (val: number, title: string) => { + batchInStorageState.inStorageData.wareHousingCount = Number(verifiyNumberInteger(val.toString())) === 0 ? null : Number(verifiyNumberInteger(val.toString())); +}; +</script> + +<style scoped> +:deep(.el-dialog__header) { + padding: var(--el-dialog-padding-primary); + padding-bottom: 10px; + margin-right: 16px; + word-break: break-all; + text-align: center !important; +} +</style> diff --git a/src/views/facilityManagement/safetyGoodsAndEquipment/components/batchOutStorage.vue b/src/views/facilityManagement/safetyGoodsAndEquipment/components/batchOutStorage.vue new file mode 100644 index 0000000..235beb3 --- /dev/null +++ b/src/views/facilityManagement/safetyGoodsAndEquipment/components/batchOutStorage.vue @@ -0,0 +1,154 @@ +<template> + <div> + <el-dialog :title="batchOutStorageState.title" :close-on-click-modal="false" v-model="batchOutStorageState.batchOutStorageDialogVisible" width="30%"> + <el-form + :model="batchOutStorageState.outStorageData" + :rules="batchOutStorageState.outStorageDataRules" + ref="outStorageDataRef" + size="default" + v-loading="batchOutStorageState.loading" + element-loading-text="Loading..." + label-width="150px"> + <el-row> + <el-col :span="24" class="mb20"> + <el-form-item label="当前所选物资/设备:"> + <el-input v-model="batchOutStorageState.materialName" :readonly="true" class="input-add"> + </el-input> + </el-form-item> + </el-col> + <el-col :span="24" class="mb20"> + <el-form-item label="按RFID标记:" prop="rfid"> + <el-input v-model="batchOutStorageState.outStorageData.rfid" placeholder="选填" class="input-add"> + </el-input> + </el-form-item> + </el-col> + <el-col :span="24" class="mb20"> + <el-form-item label="出库数量:" prop="count"> + <el-input @Output="onVerifiyNumberInteger($event, 'noticeTime')" v-model="batchOutStorageState.outStorageData.count" placeholder="输入出库数量" class="input-add"> + </el-input> + </el-form-item> + </el-col> + <el-col :span="24" class="mb20"> + <el-form-item label="认领人:" prop="receiveUid"> + <el-select class="input-add" v-model="batchOutStorageState.outStorageData.receiveUid" placeholder="选择认领人"> + <el-option + v-for="item in batchOutStorageState.userList" + :key="item.uid" + :value="item.uid" + :label="item.realName" + ></el-option> + </el-select> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button :disabled="batchOutStorageState.loading" @click="batchOutStorageState.batchOutStorageDialogVisible = !batchOutStorageState.batchOutStorageDialogVisible" size="default">取 消</el-button> + <el-button :disabled="batchOutStorageState.loading" type="primary" @click="submitOutStorageData" v-throttle size="default">确 定</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script setup lang="ts"> +import {onMounted, reactive, ref} from 'vue' +import {BatchOutStorageStateType, DataType} from "/@/views/facilityManagement/safetyGoodsAndEquipment/index"; +import {verifiyNumberInteger} from "/@/utils/toolsValidate"; +import {ElMessage} from "element-plus"; +import { goodsAndEquipmentApi } from '../../../../api/facilityManagement/safetyGoodsAndEquipment/index' +import {teamManageApi} from "/@/api/systemManage/basicDateManage/personShiftManage/teamManage"; + +const outStorageDataRef = ref() + +const batchOutStorageState = reactive<BatchOutStorageStateType>({ + title: '批量出库', + loading: false, + materialName: '', + batchOutStorageDialogVisible: false, + outStorageData:{ + smId: null, + count: null, + receiveUid: null, + rfid: null, + }, + outStorageDataRules: { + count: [{ required: true, message: '请填写出库数量', trigger: 'blur' }], + receiveUid: [{ required: true, message: '请选择认领人', trigger: 'change' }], + }, + userList: [], +}) + +const openBatchOutStorageDialog = (value: DataType) => { + batchOutStorageState.batchOutStorageDialogVisible = true + batchOutStorageState.outStorageData.smId = value.id + batchOutStorageState.materialName = value.materialName +} + +const submitOutStorageData = () => { + batchOutStorageState.loading = true; + outStorageDataRef.value.validate(async (valid: boolean) => { + if(valid){ + let res = await goodsAndEquipmentApi().batchOutStorageGoods(batchOutStorageState.outStorageData); + if(res.data.code === '200'){ + batchOutStorageState.batchOutStorageDialogVisible = false; + emit('refreshData') + ElMessage({ + type: 'success', + message: '出库成功', + duration: 2000 + }); + }else{ + ElMessage({ + type: 'warning', + message:res.data.msg + }); + } + }else{ + ElMessage({ + type: 'warning', + message: '请完善基本信息' + }); + } + }); + batchOutStorageState.loading = false +}; + +const emit = defineEmits(['refreshData',]); + +defineExpose({ + openBatchOutStorageDialog, +}) + +const onVerifiyNumberInteger = (val: number, title: string) => { + batchOutStorageState.outStorageData.count = Number(verifiyNumberInteger(val.toString())) === 0 ? null : Number(verifiyNumberInteger(val.toString())); + +}; + +const getUserByDepartment = async () => { + let res = await teamManageApi().getAllMember(1); + if (res.data.code === '200') { + batchOutStorageState.userList = JSON.parse(JSON.stringify(res.data.data)); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } +} + +onMounted(() => { + getUserByDepartment() +}) +</script> + +<style scoped> +:deep(.el-dialog__header) { + paddOutg: var(--el-dialog-padding-primary); + paddOutg-bottom: 10px; + margOut-right: 16px; + word-break: break-all; + text-align: center !important; +} +</style> diff --git a/src/views/facilityManagement/safetyGoodsAndEquipment/components/safetyGoodsAndEquipmentDialog.vue b/src/views/facilityManagement/safetyGoodsAndEquipment/components/safetyGoodsAndEquipmentDialog.vue new file mode 100644 index 0000000..54fc08e --- /dev/null +++ b/src/views/facilityManagement/safetyGoodsAndEquipment/components/safetyGoodsAndEquipmentDialog.vue @@ -0,0 +1,238 @@ +<template> + <div class="system-add-menu-container"> + <el-dialog :title="dialogState.title" :close-on-click-modal="false" v-model="dialogState.showSafetyGoodsAndEquipmentDialog" width="600px"> + <el-form + :model="dialogState.safetyGoodsAndEquipmentForm" + :rules="dialogState.safetyGoodsAndEquipmentRules" + ref="safetyGoodsAndEquipmentRef" + size="default" + v-loading="dialogState.loading" + element-loading-text="Loading..." + label-width="120px"> + <el-row> + <el-col :span="24" class="mb20"> + <el-form-item label="物资大类" prop="bigClassifyId"> + <el-select v-model="dialogState.safetyGoodsAndEquipmentForm.bigClassifyId" @change="changeSmallClassify(null)" placeholder="物资大类" class="input-add"> + <el-option + v-for="item in dialogState.goodsBigClassifyList" + :key="item.id" + :value="item.id" + :label="item.materialClassifyName" + ></el-option> + </el-select> + </el-form-item> + </el-col> +<!-- <el-col :span="5">--> +<!-- <el-button type="primary" @click="openAddGoods">添加物资</el-button>--> +<!-- </el-col>--> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="物资小类" prop="smallClassifyId"> + <el-select class="input-add" v-model="dialogState.safetyGoodsAndEquipmentForm.smallClassifyId" placeholder="请先选择物资大类"> + <el-option + v-for="item in dialogState.goodsSmallClassifyList" + :key="item.id" + :value="item.id" + :label="item.materialClassifyName" + ></el-option> + </el-select> + </el-form-item> + </el-col> + + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="部门" prop="depId"> + <el-cascader + :disabled="true" + :options="dialogState.departmentList" + :props="{ emitPath: false, checkStrictly: true, value: 'depId', label: 'depName' }" + placeholder="请选择部门" + clearable + class="input-add" + v-model="dialogState.safetyGoodsAndEquipmentForm.depId"> + </el-cascader> + </el-form-item> + </el-col> +<!-- <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">--> +<!-- <el-form-item label="是否耗材" prop="consumable">--> +<!-- <el-select class="input-add" v-model="dialogState.safetyGoodsAndEquipmentForm.consumable" placeholder="是否耗材" clearable filterable>--> +<!-- <el-option--> +<!-- v-for="item in dialogState.consumableList"--> +<!-- :key="item.id"--> +<!-- :value="item.id"--> +<!-- :label="item.name"--> +<!-- >--> +<!-- </el-option>--> +<!-- </el-select>--> +<!-- </el-form-item>--> +<!-- </el-col>--> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="dialogState.showSafetyGoodsAndEquipmentDialog = !dialogState.showSafetyGoodsAndEquipmentDialog" size="default">取 消</el-button> + <el-button type="primary" @click="submitSafetyGoodsAndEquipment" v-throttle size="default">确 定</el-button> + </span> + </template> + </el-dialog> + <add-goods-dialog ref="addGoodsDialogRef" @refreshClassify="getAllSafetyEquipmentList"></add-goods-dialog> + </div> +</template> + +<script setup lang="ts"> +import {computed, nextTick, reactive, ref, watch} from 'vue' +import { + BigClassifyType, + DataType, DepartmentType, + isValidKey, + SafetyGoodsAndEquipmentDialogStateType, safetyGoodsAndEquipmentFormType +} from "/@/views/facilityManagement/safetyGoodsAndEquipment/index"; +import { goodsAndEquipmentApi } from "/@/api/facilityManagement/safetyGoodsAndEquipment"; +import {ElMessage} from "element-plus"; +import AddGoodsDialog from "./addGoodsDialog.vue"; +import {useUserInfo} from "/@/stores/userInfo"; + +const safetyGoodsAndEquipmentRef = ref(); +const addGoodsDialogRef = ref(); +const userInfo = useUserInfo() + +const dialogState = reactive<SafetyGoodsAndEquipmentDialogStateType>({ + safetyGoodsAndEquipmentForm: { + id: null, + bigClassifyId: null, + smallClassifyId: null, + depId: null, + // consumable: null, + }, + safetyGoodsAndEquipmentRules: { + bigClassifyId: [{ required: true, message: '请选择物资大类', trigger: 'change' }], + smallClassifyId: [{ required: true, message: '请选择物资小类', trigger: 'change' }], + // depId: [{ required: true, message: '请选择部门', trigger: 'change' }], + // consumable: [{ required: true, message: '请选择是否耗材', trigger: 'change' }], + }, + showSafetyGoodsAndEquipmentDialog: false, + title: '', + loading: false, + depList: [], + goodsBigClassifyList: [], + goodsSmallClassifyList: [], + departmentList: [], + consumableList: [ + {id: 0, name: '是'}, + {id: 1, name: '否'}, + ], +}); + +watch(() => dialogState.safetyGoodsAndEquipmentForm.bigClassifyId ,(newVal, oldVal) => { + +},); + +// const openAddGoods = () => { +// addGoodsDialogRef.value.openAddGoodsDialog(dialogState.goodsBigClassifyList) +// } + +const openSafetyGoodsAndEquipmentDialog = + (title: string, value: safetyGoodsAndEquipmentFormType, goodsBigClassifyList: BigClassifyType [], departmentList : DepartmentType []) => { + dialogState.title = title; + dialogState.showSafetyGoodsAndEquipmentDialog = true; + dialogState.goodsBigClassifyList = goodsBigClassifyList; + dialogState.departmentList = departmentList; + dialogState.safetyGoodsAndEquipmentForm = { + id: null, + bigClassifyId: null, + smallClassifyId: null, + depId: userInfo.userInfos.depId, + // consumable: null, + }; + nextTick( () => { + safetyGoodsAndEquipmentRef.value.clearValidate(); + }) + if(title === '新增') { + dialogState.title = '新增' + }else { + dialogState.title = '编辑' + changeSmallClassify(value.bigClassifyId) + for(let key in dialogState.safetyGoodsAndEquipmentForm) { + if(isValidKey(key, dialogState.safetyGoodsAndEquipmentForm)){ + dialogState.safetyGoodsAndEquipmentForm[key] = value[key]; + } + } + } +}; + +const changeSmallClassify = (id: number | null) => { + dialogState.safetyGoodsAndEquipmentForm.smallClassifyId = null; + dialogState.goodsSmallClassifyList = dialogState.goodsBigClassifyList[dialogState.goodsBigClassifyList. + findIndex(item => item.id === (dialogState.safetyGoodsAndEquipmentForm.bigClassifyId || id))].childList as Array<BigClassifyType>; +} + +const submitSafetyGoodsAndEquipment = () => { + safetyGoodsAndEquipmentRef.value.validate(async (valid: boolean) => { + if(valid){ + dialogState.loading = true + if(dialogState.title === '新增') { + let res = await goodsAndEquipmentApi().addGoodsEquipment(dialogState.safetyGoodsAndEquipmentForm) + if(res.data.code === '200'){ + dialogState.showSafetyGoodsAndEquipmentDialog = false + emit('refreshData') + ElMessage({ + type: 'success', + message: '安全物资设备新增成功', + duration: 2000 + }); + }else{ + ElMessage({ + type:'warning', + message:res.data.msg + }) + } + }else{ + let res = await goodsAndEquipmentApi().updateGoodsEquipment(dialogState.safetyGoodsAndEquipmentForm) + if(res.data.code === '200'){ + dialogState.showSafetyGoodsAndEquipmentDialog = false + emit('refreshData') + ElMessage({ + type: 'success', + message: '安全物资设备编辑成功', + duration: 2000 + }); + }else{ + ElMessage({ + type:'warning', + message:res.data.msg + }) + } + } + dialogState.loading = false + }else{ + ElMessage({ + type: 'warning', + message: '请完善基本信息' + }) + } + }) +}; + +const getAllSafetyEquipmentList = async () => { + let res = await goodsAndEquipmentApi().getAllSafetyEquipment(); + if(res.data.code === '200'){ + dialogState.goodsBigClassifyList = res.data.data + }else{ + ElMessage({ + message:res.data.msg, + type:'warning' + }) + } +}; + +const emit = defineEmits(['refreshData',]) + +defineExpose({ + openSafetyGoodsAndEquipmentDialog, +}); + +</script> + +<style scoped> +.input-length{ + width: 100% !important; +} +</style> diff --git a/src/views/facilityManagement/safetyGoodsAndEquipment/index.ts b/src/views/facilityManagement/safetyGoodsAndEquipment/index.ts new file mode 100644 index 0000000..63748a4 --- /dev/null +++ b/src/views/facilityManagement/safetyGoodsAndEquipment/index.ts @@ -0,0 +1,129 @@ +export type TableDataType = { + goodsAndEquipmentData: DataType []; + goodsBigClassifyList: BigClassifyType []; + departmentList: DepartmentType []; + listQuery: { + pageSize: number; + pageIndex: number; + searchParams: { + bigClassifyId: number | null; + materialName: string; + } + }; + total: number; +} + +export type SafetyGoodsAndEquipmentDialogStateType = { + safetyGoodsAndEquipmentForm: safetyGoodsAndEquipmentFormType, + safetyGoodsAndEquipmentRules: { + + }, + showSafetyGoodsAndEquipmentDialog: Boolean, + title: string, + loading: Boolean, + depList: DepartmentType []; + consumableList: Type []; + departmentList: DepListType []; + goodsBigClassifyList: BigClassifyType []; + goodsSmallClassifyList: BigClassifyType []; +} + +export type AddGoodsStateType = { + title: string; + goodsClassifyTitle: string; + showAddGoodsDialog: boolean; + showAddGoodsClassifyDialog: boolean; + activeName: string; + goodsData: BigClassifyType []; + goodsBigClassifyList: BigClassifyType []; + consumableList?: Type []; + total: number; + listQuery: { + pageSize: number; + pageIndex: number; + searchParams: { + classifyName: string; + } + }; + goodsClassifyForm: { + id: null | number; + materialClassifyName: string; + parentId: number | null; + consumable?: number | null; + }; + goodsClassifyRules: { + + } +} + +export type BatchInStorageStateType = { + title: string; + loading: boolean; + materialName: string; + batchInStorageDialogVisible: boolean; + inStorageData: { + smId: null | number, + wareHousingCount: null | number, + validType: null | number, + validTime: null | string, + rfid: null | string, + }, + inStorageDataRules: { + }, +} + +export type BatchOutStorageStateType = { + title: string; + loading: boolean; + materialName: string; + batchOutStorageDialogVisible: boolean; + outStorageData: { + smId: null | number, + count: null | number, + receiveUid: null | number, + rfid: null | string, + }; + outStorageDataRules: { + }; + userList: []; +} + +export type Type = { + id: number; + name: string; +} + +export type safetyGoodsAndEquipmentFormType = { + id: null | number, + bigClassifyId: null | number, + smallClassifyId: null | number, + depId: null | number, + // consumable: null | number, +} + +export type DataType = { + id: number | null; + materialName: string; +} + +export type DepListType = { + +} + +export function isValidKey(key: string | number | symbol, object:object): key is keyof typeof object{ + return key in object; +} + +export type DepartmentType = { + +} + +export type BigClassifyType = { + id: number; + materialClassifyName: string; + consumable?: number | null; + parentId?: number; + childList?: BigClassifyType []; +} + + diff --git a/src/views/facilityManagement/safetyGoodsAndEquipment/index.vue b/src/views/facilityManagement/safetyGoodsAndEquipment/index.vue new file mode 100644 index 0000000..16b16e9 --- /dev/null +++ b/src/views/facilityManagement/safetyGoodsAndEquipment/index.vue @@ -0,0 +1,343 @@ +<template> + <div class="home-container"> + <div style="height: 100%"> + <el-row class="homeCard"> + <div class="basic-line"> + <span>分类名称:</span> + <el-select class="input-box" v-model="tableData.listQuery.searchParams.bigClassifyId" placeholder="分类名称" filterable clearable> + <el-option + v-for="item in tableData.goodsBigClassifyList" + :key="item.id" + :value="item.id" + :label="item.materialClassifyName" + ></el-option> + </el-select> + </div> + <div class="basic-line"> + <span>物资名称:</span> + <el-input class="input-box" v-model="tableData.listQuery.searchParams.materialName" placeholder="物资名称" clearable> </el-input> + </div> + <div style="padding-bottom: 10px"> + <el-button size="large" type="primary" class="ml10" v-throttle @click="refreshGoodsAndEquipmentData"> + <el-icon> + <ele-Search /> + </el-icon> + 查询 + </el-button> + <el-button size="large" type="success" class="ml10" @click="onOpenDialogRef('新增', '')"> + <el-icon> + <ele-FolderAdd /> + </el-icon> + 新增 + </el-button> +<!-- <el-button size="large" class="ml10" @click="openAddGoods()">--> +<!-- 管理分类--> +<!-- </el-button>--> + </div> + </el-row> + <div class="homeCard"> + <div class="main-card"> + <el-table :data="tableData.goodsAndEquipmentData" style="width: 100%" height="calc(100% - 100px)" :header-cell-style="{ background: '#fafafa' }"> + <el-table-column type="index" label="序号" width="60" /> + <el-table-column prop="bigClassifyName" label="大类物资类型名称" show-overflow-tooltip></el-table-column> + <el-table-column prop="materialName" label="物资名称" show-overflow-tooltip></el-table-column> + <el-table-column prop="serialNum" label="序列号" show-overflow-tooltip></el-table-column> + <el-table-column prop="depName" label="部门名称" show-overflow-tooltip></el-table-column> + <el-table-column prop="consumableName" label="是否是耗材" show-overflow-tooltip></el-table-column> + <el-table-column prop="stockCount" label="库存" show-overflow-tooltip></el-table-column> + <el-table-column label="操作" width="250" align="center"> + <template #default="scope"> + <el-button size="small" text type="success" :icon="Edit" @click="openBatchInStorage('批量入库', scope.row)">批量入库</el-button> + <el-button size="small" text type="warning" :icon="Edit" @click="openBatchOutStorage('批量出库', scope.row)">批量出库</el-button> + <el-button size="small" text type="primary" :icon="Edit" @click="linkToGoodsDetail('查看明细', scope.row)">查看明细</el-button> +<!-- <el-button size="small" text :icon="Edit" @click="onOpenDialogRef('编辑', scope.row)">编辑</el-button>--> + <el-button size="small" text type="danger" :icon="Delete" @click="onDelGoodsEquipment(scope.row)">删除</el-button> + </template> + </el-table-column> + </el-table> + <br /> + <el-pagination @size-change="onHandleSizeChange" @current-change="onHandleCurrentChange" :pager-count="5" :page-sizes="[10, 20, 30]" v-model:current-page="tableData.listQuery.pageIndex" background v-model:page-size="tableData.listQuery.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="tableData.total" class="page-position"> </el-pagination> + </div> + </div> + </div> + <safety-goods-and-equipment-dialog ref="safetyGoodsAndEquipmentDialogRef" @refreshData="refreshGoodsAndEquipmentData"></safety-goods-and-equipment-dialog> + <batch-out-storage ref="batchOutStorageRef" @refreshData="refreshGoodsAndEquipmentData"></batch-out-storage> + <batch-in-storage ref="batchInStorageRef" @refreshData="refreshGoodsAndEquipmentData"></batch-in-storage> + <add-goods-dialog ref="addGoodsDialogRef" @refreshClassify="getAllSafetyEquipmentList"></add-goods-dialog> + </div> +</template> + +<script setup lang="ts"> +import {onMounted, reactive, ref} from 'vue' +import {BigClassifyType, DataType, TableDataType} from "/@/views/facilityManagement/safetyGoodsAndEquipment/index"; +import { Edit, View, Plus, Delete, Refresh, Search, Download } from '@element-plus/icons-vue'; +import {goodsAndEquipmentApi} from "/@/api/facilityManagement/safetyGoodsAndEquipment"; +import {ElMessage, ElMessageBox} from "element-plus"; +import SafetyGoodsAndEquipmentDialog from './components/safetyGoodsAndEquipmentDialog.vue' +import {departmentApi} from "/@/api/systemManage/department"; +import router from "/@/router"; +import BatchInStorage from './components/batchInStorage.vue' +import BatchOutStorage from './components/batchOutStorage.vue' +import AddGoodsDialog from "./components/addGoodsDialog.vue"; + +const safetyGoodsAndEquipmentDialogRef = ref() +const batchInStorageRef = ref() +const batchOutStorageRef = ref() +const addGoodsDialogRef = ref() + +const tableData = reactive<TableDataType>({ + goodsAndEquipmentData:[], + goodsBigClassifyList:[], + departmentList:[], + listQuery:{ + pageSize: 10, + pageIndex: 1, + searchParams: { + bigClassifyId:null, + materialName:'' + } + }, + total:0, +}) + +const initGoodsAndEquipmentData = async () => { + let res = await goodsAndEquipmentApi().getGoodsEquipmentData(tableData.listQuery) + if(res.data.code === '200'){ + tableData.goodsAndEquipmentData = res.data.data; + tableData.total = res.data.total; + }else{ + ElMessage({ + type:'warning', + message:res.data.msg + }) + } +}; + +const onOpenDialogRef = (title: string, value: DataType) => { + safetyGoodsAndEquipmentDialogRef.value.openSafetyGoodsAndEquipmentDialog(title,value,tableData.goodsBigClassifyList, tableData.departmentList); +}; + +const openBatchInStorage = (title: string, value: DataType) => { + batchInStorageRef.value.openBatchInStorageDialog(value) +} + +const openBatchOutStorage = (title: string, value: DataType) => { + batchOutStorageRef.value.openBatchOutStorageDialog(value) +} + +// const openAddGoods = () => { +// addGoodsDialogRef.value.openAddGoodsDialog(tableData.goodsBigClassifyList) +// } + +const linkToGoodsDetail = (title: string, value: DataType) => { + router.push({ path: '/goodsDetailManage', query:{ id: value.id } }); +} + +const onDelGoodsEquipment = (value: DataType) => { + ElMessageBox.confirm(`此操作将永久删除该:“${value.materialName}”,是否继续?`, '提示', { + confirmButtonText: '确认', + cancelButtonText: '取消', + type: 'warning' + }) + .then(async () => { + let res = await goodsAndEquipmentApi().deleteGoodsEquipment({ id: value.id }); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + duration: 2000, + message: '删除成功' + }); + await initGoodsAndEquipmentData(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }) + .catch(() => {}); +}; + +const refreshGoodsAndEquipmentData = () => { + initGoodsAndEquipmentData(); +}; +// 分页改变 +const onHandleSizeChange = (val: number) => { + tableData.listQuery.pageSize = val; + initGoodsAndEquipmentData(); +}; +// 分页改变 +const onHandleCurrentChange = (val: number) => { + tableData.listQuery.pageIndex = val; + initGoodsAndEquipmentData(); +}; + +const getAllSafetyEquipmentList = async () => { + let res = await goodsAndEquipmentApi().getAllSafetyEquipment(); + if(res.data.code === '200'){ + tableData.goodsBigClassifyList = JSON.parse(JSON.stringify(res.data.data)) + }else{ + ElMessage({ + message:res.data.msg, + type:'warning' + }) + } +} + +const getDepartmentData = async () => { + let res = await departmentApi().getDepartmentList(); + if (res.data.code === '200') { + tableData.departmentList = res.data.data; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } +}; + +onMounted(() => { + initGoodsAndEquipmentData(); + getAllSafetyEquipmentList(); + getDepartmentData(); +}) +</script> + +<style scoped lang="scss"> +$homeNavLengh: 8; +.home-container { + height: calc(100vh - 144px); + box-sizing: border-box; + overflow: hidden; +.homeCard { + width: 100%; + padding: 20px; + box-sizing: border-box; + background: #fff; + border-radius: 4px; + +.main-card { + width: 100%; + height: 100%; +.cardTop { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 20px; + .mainCardBtn { + margin: 0; + } +} +.pageBtn { + height: 60px; + display: flex; + align-items: center; + justify-content: right; + +.demo-pagination-block + .demo-pagination-block { + margin-top: 10px; +} +.demo-pagination-block .demonstration { + margin-bottom: 16px; +} +} +} +&:last-of-type { + height: calc(100% - 100px); + } +} +.el-row { + display: flex; + align-items: center; + margin-bottom: 20px; +&:last-child { + margin-bottom: 0; + } +.grid-content { + align-items: center; + min-height: 36px; +} + +.topInfo { + display: flex; + align-items: center; + font-size: 16px; + font-weight: bold; + +& > div { + white-space: nowrap; + margin-right: 20px; + } +} +} +} +.stepItem { + width: 100%; + display: flex; + align-items: flex-start; + margin-bottom: 30px; + margin-left: 30px; + padding-bottom: 30px; + border-left: 2px solid #ccc; +&:first-of-type { + margin-top: 30px; + } +&:last-of-type { + margin-bottom: 0; + border-left: none; + } +.stepNum { + width: 30px; + height: 30px; + border-radius: 15px; + box-sizing: border-box; + color: #333; + border: 1px solid #999; + line-height: 28px; + text-align: center; + margin-right: 10px; + margin-left: -16px; + margin-top: -30px; +} +.stepCard { + width: 100%; + margin-top: -30px; + +.box-card { + width: 100%; +&:deep(.el-card__header) { + padding: 10px 15px; + } +.card-header { + width: 100%; + display: flex; + justify-content: space-between; + align-items: center; +& > div:first-of-type { + margin-right: 80px; + font-size: 18px; + font-weight: bold; + } +} +} +} +&:hover .card-header { + color: #0098f5; + } +&:hover .stepNum { + border: 2px solid #0098f5; + color: #0098f5; + } +} + +:deep(.el-textarea.is-disabled .el-textarea__inner) { + background-color: var(--el-card-bg-color); + color: var(--el-input-text-color, var(--el-text-color-regular)); +} +:deep(.el-input.is-disabled .el-input__inner) { + color: var(--el-input-text-color, var(--el-text-color-regular)); +} +:deep(.el-input.is-disabled .el-input__wrapper) { + background-color: var(--el-card-bg-color); +} +</style> diff --git a/src/views/facilityManagement/securities/index.vue b/src/views/facilityManagement/securities/index.vue new file mode 100644 index 0000000..34c9f62 --- /dev/null +++ b/src/views/facilityManagement/securities/index.vue @@ -0,0 +1,860 @@ +<template> + <div class="home-container"> + <div style="height: 100%"> + <el-row class="homeCard"> + <el-col :span="5" style="display:flex;align-items: center"> + <span style="white-space: nowrap">分类:</span> + <div class="grid-content topInfo"> + <el-select v-model="searchType"> + <el-option + v-for="item in goodsType" + :key="item.id" + :label="item.name" + :value="item.id" + /> + </el-select> + </div> + </el-col> + <el-col :span="5" style="display:flex;align-items: center"> + <span style="white-space: nowrap">名称:</span> + <div class="grid-content topInfo"> + <el-input v-model="searchName"/> + </div> + </el-col> + <el-button type="primary" style="margin-left: 20px" @click="searchRecord">查询</el-button> + <el-button plain @click="clearSearch">重置</el-button> + </el-row> + <div class="homeCard"> + <div class="main-card"> + <el-row class="cardTop"> + <el-col :span="12" class="mainCardBtn"> + <el-button type="primary" :icon="Plus" size="default" @click="dialogAddRecord = true">新增</el-button> + <el-button type="success" size="default" @click="dialogAddType = true">管理分类</el-button> + </el-col> + <el-button type="primary" :icon="Refresh" size="default" @click="reLoadData()" /> + </el-row> + <el-table ref="multipleTableRef" :data="goodsData" style="width: 100%" height="calc(100% - 100px)" :header-cell-style="{ background: '#fafafa' }"> + <el-table-column property="id" label="id" width="180" /> + <el-table-column property="type" label="分类" /> + <el-table-column property="depName" label="仓库/部门" /> + <el-table-column property="name" label="名称" /> + <el-table-column property="consumable" label="是否耗材" align="center"/> + <el-table-column property="stock" label="有效库存" align="center"/> + <el-table-column fixed="right" label="操作" align="center" width="400"> + <template #default="scope"> + <el-button link type="success" size="small" :icon="View" @click="incomeBtn(scope.row)">批量入库</el-button> + <el-button link type="success" size="small" :icon="View" @click="outcomeBtn(scope.row)">批量出库</el-button> + <el-button link type="primary" size="small" :icon="View" @click="viewRecord(scope.row)">查看明细</el-button> + <el-button link type="primary" size="small" :icon="Edit" @click="editRecordBtn(scope.$index, scope.row)">修改</el-button> + <el-button link type="danger" size="small" :icon="Delete" @click="deleteRecordBtn(scope.row)">删除</el-button> + </template> + </el-table-column> + </el-table> + <div class="pageBtn"> + <el-pagination v-model:currentPage="pageIndex1" v-model:page-size="pageSize1" :page-sizes="[10, 15]" small="false" background layout="total, sizes, prev, pager, next, jumper" :total="totalSize1" @size-change="handleSizeChange1" @current-change="handleCurrentChange1" /> + </div> + </div> + </div> + </div> + +<!-- 查看详情--> + <el-dialog v-model="dialogDetails" title="物资明细" center> + + <template #footer> + <span class="dialog-footer"> + <el-button type="primary" @click="dialogDetails = false" + >确认</el-button + > + </span> + </template> + </el-dialog> + +<!-- 新增修改--> + <el-dialog v-model="dialogAddRecord" title="安全物资与设备编辑" @close="closeAdd" @open="openAdd" center> + <el-form :model="addRecord" label-width="120px" ref="addRef" :rules="addRules"> + <el-form-item label="名称" prop="name"> + <el-input v-model="addRecord.name"> </el-input> + </el-form-item> + <div style="display: flex;margin-bottom: 22px;justify-content: space-between;align-items: center"> + <el-form-item label="选择分类" prop="type" style="display: flex"> + <el-select v-model="addRecord.type"> + <el-option v-for="(item, index) in goodsType" :label="item.name" :key="index" :value="item.id">{{ item.name }}</el-option> + </el-select> + </el-form-item> + <el-button style="margin-left: 20px" type="primary" :icon="Plus" size="default" @click="dialogAddType = true">添加分类</el-button> + </div> + <el-form-item label="所属部门/仓库" prop="depName"> + <el-cascader v-model="addRecord.depName" :options="departmentList" :props="casProps" :show-all-levels="false" @change="handleChange" /> + </el-form-item> + <el-form-item label="是否耗材" prop="consumable"> + <el-select v-model="addRecord.consumable"> + <el-option label="是" value="1">是</el-option> + <el-option label="否" value="0">否</el-option> + </el-select> + </el-form-item> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button type="warning" @click="dialogAddRecord = false" size="default" plain>取消</el-button> + <el-button type="primary" @click="confirmAddRecord(addRef)" size="default">确认</el-button> + </span> + </template> + </el-dialog> + +<!-- 批量入库--> + <el-dialog v-model="dialogEnter" title="批量入库" center width="40%"> + <el-form :model="addRecord" label-width="150px" ref="addRef" :rules="addRules"> + <el-form-item label="当前所选物资/设备" prop="name"> + <el-input v-model="addRecord.name" readonly/> + </el-form-item> + <el-form-item label="按RFID标记(选填):" prop="name"> + <el-input v-model="addRecord.name" readonly/> + </el-form-item> + <el-form-item label="输入入库数量" prop="name"> + <el-input v-model="addRecord.name" readonly/> + </el-form-item> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button type="warning" @click="dialogEnter = false" size="default" plain>取消</el-button> + <el-button type="primary" @click="confirmAddRecord(addRef)" size="default">提交</el-button> + </span> + </template> + </el-dialog> + +<!-- 批量出库--> + <el-dialog v-model="dialogOut" title="批量出库" center width="40%"> + <el-form :model="addRecord" label-width="150px" ref="addRef" :rules="addRules"> + <el-form-item label="当前所选物资/设备" prop="name"> + <el-input v-model="addRecord.name" readonly/> + </el-form-item> + <el-form-item label="按RFID标记(选填):" prop="name"> + <el-input v-model="addRecord.name" readonly/> + </el-form-item> + <el-form-item label="输入出库数量" prop="name"> + <el-input v-model="addRecord.name" readonly/> + </el-form-item> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button type="warning" @click="dialogOut = false" size="default" plain>取消</el-button> + <el-button type="primary" @click="confirmAddRecord(addRef)" size="default">提交</el-button> + </span> + </template> + </el-dialog> + +<!-- 分类管理--> + <el-dialog v-model="dialogAddType" center width="40%"> + <div style="margin-bottom: 20px"> + <el-button type="primary" :icon="Plus" size="default">新增</el-button> + </div> + <el-table :data="goodsData" style="width: 100%" :header-cell-style="{ background: '#fafafa' }"> + <el-table-column property="type" label="分类名称"/> + <el-table-column fixed="right" label="操作" align="center"> + <template #default="scope"> + <el-button link type="primary" size="small" :icon="Edit" @click="editRecordBtn(scope.$index, scope.row)">编辑</el-button> + <el-button link type="danger" size="small" :icon="Delete" @click="deleteRecordBtn(scope.row)">删除</el-button> + </template> + </el-table-column> + </el-table> + <template #footer> + <span class="dialog-footer"> + <el-button type="primary" @click="dialogAddType = false" size="default">确认</el-button> + </span> + </template> + </el-dialog> + +<!-- 删除--> + <el-dialog v-model="deleteDialog" title="提示" width="30%" center> + <span>您确定要删除该条记录吗?</span> + <template #footer> + <span class="dialog-footer"> + <el-button @click="deleteDialog = false" size="default">取消</el-button> + <el-button type="primary" @click="conFirmDelete" size="default">确认</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script lang="ts"> +import {toRefs, reactive, defineComponent, ref, onMounted, defineAsyncComponent} from 'vue'; +import { storeToRefs } from 'pinia'; +import { initBackEndControlRoutes } from '/@/router/backEnd'; +import { useUserInfo } from '/@/stores/userInfo'; +import { Session } from '/@/utils/storage'; +import { useRouter } from 'vue-router'; +import { Edit, View, Plus, Delete, Refresh, Search, Finished, Download } from '@element-plus/icons-vue'; +import { ElTable } from 'element-plus'; +import { FormInstance, FormRules, ElMessage } from 'element-plus'; +import { workApplyApi } from '/@/api/specialWorkSystem/workApply'; +import type { TabsPaneContext } from 'element-plus'; +import {teamManageApi} from "/@/api/systemManage/basicDateManage/personShiftManage/teamManage"; +import Cookies from 'js-cookie'; +import axios from 'axios'; +import {holidayGroupApi} from "/@/api/systemManage/basicDateManage/personShiftManage/holidayTimeGroup"; + +// 定义接口来定义对象的类型 +interface stateType { + goodsData: Array<any>; + multipleSelection: Array<any>; + goodsType: Array<any>; + dialogDetails: boolean; + dialogAddRecord: boolean; + dialogEnter: boolean; + dialogOut: boolean; + deleteDialog: boolean; + dialogAddType: boolean; + pageIndex1: number; + pageSize1: number; + chosenIndex: null | number; + deleteId: null | number; + searchType: string; + searchName: string; + totalSize1: number; + addRecord: Object; + details: Object; + casProps: Object; + workType: Array<type>; + departmentList: Array<any>; + departmentRecursionList: Array<DepartmentState>; +} +interface type { + id: number; + name: string; +} +interface DepartmentState { + depId: number; + depName: string; +} +export default defineComponent({ + name: 'securities', + components: {}, + setup() { + const userInfo = useUserInfo(); + const { userInfos } = storeToRefs(userInfo); + const router = useRouter(); + const state = reactive<stateType>({ + pageIndex1: 1, + pageSize1: 10, + totalSize1: 0, + departmentList: [], + departmentRecursionList: [], + chosenIndex: null, + searchType: '', + searchName: '', + goodsData: [ + { + id: '001', + type: '安全防护', + depName: '甲醛事业部', + name: '安全帽', + consumable: 0, + stock: 109 + }, + { + id: '002', + type: '消防', + depName: '甲醛事业部', + name: '干粉灭火器', + consumable: 1, + stock: 223 + } + ], + multipleSelection: [], + goodsType:[ + { + id: '001', + name: '安全防护' + }, + { + id: '002', + name: '消防' + } + ], + casProps: { + expandTrigger: 'hover', + emitPath: false, + value: 'depId', + label: 'depName', + checkStrictly: true + }, + dialogEnter: false, + dialogOut: false, + dialogAddRecord: false, + dialogDetails: false, + deleteDialog: false, + dialogAddType: false, + addRecord: {}, + details: {}, + deleteId: null, + workType: [ + { id: 1, name: '动火作业' }, + { id: 2, name: '受限空间作业' }, + { id: 3, name: '吊装作业' }, + { id: 4, name: '动土作业' }, + { id: 5, name: '断路作业' }, + { id: 6, name: '高处作业' }, + { id: 7, name: '临时用电作业' }, + { id: 8, name: '盲板抽堵作业' } + ] + }); + + const addRef = ref<FormInstance>(); + const addRules = reactive<FormRules>({ + name: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + type: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + depName: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + consumable: [{ required: true, message: '该内容不能为空', trigger: 'blur' }] + }); + // 刷新 + const reLoadData = async () => { + getListByPage(); + }; + const editRecordBtn = (index: number, row: {}) => { + state.dialogAddRecord = true; + state.chosenIndex = index; + state.addRecord = JSON.parse(JSON.stringify(row)); + }; + // 添加方法 + const addRecordBtn = async (data: any) => { + // let res = await holidayGroupApi().addRecord(data); + // if (res.data.code === '200') { + // ElMessage({ + // type: 'success', + // message: '添加成功!' + // }); + // getListByPage(); + // } else { + // ElMessage({ + // type: 'warning', + // message: res.data.msg + // }); + // } + }; + + // 修改方法 + const editRecord = async (data: any) => { + // let res = await holidayGroupApi().updateRecord(data); + // if (res.data.code === '200') { + // ElMessage({ + // type: 'success', + // message: '修改成功!' + // }); + // getListByPage(); + // } else { + // ElMessage({ + // type: 'warning', + // message: res.data.msg + // }); + // } + }; + // 新增修改记录 + const confirmAddRecord = async (formEl: FormInstance | undefined) => { + if (!formEl) return; + await formEl.validate(async (valid, fields) => { + if (valid) { + if (state.chosenIndex == null) { + // await addRecord(data); + } else { + // (data.id = state.addRecord.id), await editRecord(data); + } + state.dialogAddRecord = false; + } else { + console.log('error submit!', fields); + } + }); + }; + const closeAdd = () => { + state.addRecord = { + id: null, + name: '', + startTime: '', + endTime: '', + info: '' + }; + state.chosenIndex = null; + }; + + // 批量入库 + const incomeBtn =(row) =>{ + state.dialogEnter = true + }; + + // 批量出库 + const outcomeBtn =(row) =>{ + state.dialogOut = true + }; + + // 获取部门列表 + const getAllDepartment = async () => { + let res = await teamManageApi().getAllDepartment(); + if (res.data.code === '200') { + state.departmentList = JSON.parse(JSON.stringify(res.data.data)) + // recursion(state.departmentList); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // const recursion = (value: any) => { + // for (let i of value) { + // if (i.children.length !== 0) { + // state.departmentRecursionList.push(i); + // recursion(i.children); + // } else { + // state.departmentRecursionList.push(i); + // } + // } + // }; + + // 分页获取 + const getListByPage = async () => { + const data = { pageSize: state.pageSize1, pageIndex: state.pageIndex1, searchParams: { workType: state.searchWord } }; + let res = await workApplyApi().getApplyListPage(data); + if (res.data.code === '200') { + // state.applyData = JSON.parse(JSON.stringify(res.data.data)); + // console.log(state.applyData,'applyData') + // state.applyData = state.applyData.map((item) => { + // if (item.operators == null || item.operators == []) { + // item.operators = []; + // } else { + // item.operators = Array.from(item.operators, ({ operatorUname }) => operatorUname); + // } + // return item; + // }); + state.totalSize1 = res.data.total; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 表格数据格式化 + // const toNames = (row, column, cellValue, index) => { + // if (row.list == []) { + // return []; + // } else { + // const nameList = []; + // for (let i = 0; i < row.list.length; i++) { + // for (let t = 0; t < state.workTimeList.length; t++) { + // if (row.list[i] == state.workTimeList[t].id) { + // nameList.push(state.workTimeList[t].name); + // } + // } + // } + // return nameList.join(); + // } + // }; + + // 关键词查询记录 + const searchRecord = async () => { + if (state.searchType == '' && state.searchName == '') { + ElMessage({ + type: 'warning', + message: '请输入查询关键词' + }); + } else { + getListByPage(); + } + }; + // 重置搜索 + const clearSearch = async () => { + state.searchType = ''; + state.searchName = ''; + getListByPage(); + }; + + const deleteRecordBtn = (row) => { + state.deleteId = row.workApplyId; + state.deleteDialog = true; + }; + + // 删除方法 + const deleteRecord = async (data: any) => { + let res = await workApplyApi().cancelApply(data); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '删除成功!' + }); + getListByPage(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + const conFirmDelete = () => { + deleteRecord({ workApplyId: state.deleteId }); + state.deleteDialog = false; + }; + + const handleSizeChange1 = (val: number) => { + state.pageSize1 = val; + getListByPage(); + }; + const handleCurrentChange1 = (val: number) => { + state.pageIndex1 = val; + getListByPage(); + }; + + // 查看记录 + const viewRecord = (row: any) => { + state.details = JSON.parse(JSON.stringify(row)); + }; + + // 折线图 + const renderMenu = async (value: string) => { + Session.set('projectId', value); + userInfos.value.projectId = value; + await initBackEndControlRoutes(); + }; + + // 页面载入时执行方法 + onMounted(() => { + getListByPage(); + getAllDepartment() + }); + + return { + View, + Edit, + Delete, + Refresh, + Plus, + Finished, + Download, + addRef, + addRules, + addRecordBtn, + incomeBtn, + outcomeBtn, + editRecordBtn, + editRecord, + reLoadData, + searchRecord, + clearSearch, + viewRecord, + deleteRecordBtn, + confirmAddRecord, + closeAdd, + conFirmDelete, + getListByPage, + handleSizeChange1, + handleCurrentChange1, + ...toRefs(state) + }; + } +}); +</script> + +<style scoped lang="scss"> +$homeNavLengh: 8; +.home-container { + height: calc(100vh - 144px); + box-sizing: border-box; + overflow: hidden; + .demo-tabs { + width: 100%; + height: 100%; + + &::v-deep(.el-tabs__content) { + height: calc(100% - 60px); + } + + .el-tab-pane { + height: 100%; + } + } + .homeCard { + width: 100%; + padding: 20px; + box-sizing: border-box; + background: #fff; + border-radius: 4px; + + .main-card { + width: 100%; + height: 100%; + .cardTop { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 20px; + .mainCardBtn { + margin: 0; + } + } + .pageBtn { + height: 60px; + display: flex; + align-items: center; + justify-content: right; + + .demo-pagination-block + .demo-pagination-block { + margin-top: 10px; + } + .demo-pagination-block .demonstration { + margin-bottom: 16px; + } + } + } + &:last-of-type { + height: calc(100% - 100px); + } + } + .stepItem { + display: flex; + align-items: flex-start; + margin-top: 30px; + margin-left: 30px; + padding-bottom: 30px; + padding-left: 40px; + border-left: 1px solid #a0cfff; + position: relative; + &:first-of-type { + margin-top: 30px; + } + &:first-of-type { + margin-bottom: 0; + border-left: none; + } + .stepNum { + position: absolute; + width: 40px; + height: 40px; + border-radius: 20px; + box-sizing: border-box; + font-size: 18px; + color: #333; + border: 1px solid #a0cfff; + line-height: 38px; + text-align: center; + left: -20px; + top: -30px; + background: #d9ecff; + } + .stepCard { + width: 100%; + margin-top: -30px; + + .box-card { + width: 100%; + + .card-header { + display: flex; + justify-content: space-between; + align-items: center; + + span { + font-weight: bold; + margin-left: 10px; + } + } + + .text { + width: 100%; + font-size: 14px; + margin-bottom: 10px; + padding-left: 10px; + + span { + color: #409eff; + } + + .bold-text{ + font-weight: bolder; + } + + &:last-of-type { + margin-bottom: 0; + } + } + .approveUnit { + width: 100%; + font-size: 14px; + margin-bottom: 20px; + padding: 10px 15px; + border: 1px solid #fff; + background: #ecf8ff; + border-radius: 6px; + .item-tit { + width: 100%; + display: flex; + color: #409eff; + align-items: flex-start; + justify-content: space-between; + padding-bottom: 10px; + border-bottom: 1px solid #a0cfff; + + & > span { + flex: 1; + &:last-of-type{ + text-align: center; + } + } + & > div { + flex: 1; + text-align: center; + } + } + .item-cont { + width: 100%; + display: flex; + align-items: center; + justify-content: space-between; + padding: 10px 0; + border-bottom: 1px solid #c6e2ff; + + & > span { + flex: 1; + &:last-of-type{ + text-align: center; + } + } + & > div { + flex: 1; + text-align: center; + + & > div { + text-align: left; + width: 100%; + display: flex; + justify-content: center; + align-items: center; + span { + width: 45%; + &:first-of-type { + width: 30%; + } + } + } + } + &:last-of-type { + border-bottom: 0; + } + } + } + .approveItem { + width: 100%; + font-size: 14px; + margin-bottom: 20px; + padding: 10px 15px; + background: #ecf8ff; + border: 1px solid #fff; + border-radius: 6px; + .item-tit { + width: 100%; + display: flex; + color: #409eff; + align-items: flex-start; + justify-content: space-between; + padding-bottom: 10px; + border-bottom: 1px solid #a0cfff; + + & > span { + flex: 1; + } + & > div { + flex: 2; + text-align: center; + } + } + .item-cont { + width: 100%; + display: flex; + align-items: center; + justify-content: space-between; + padding: 10px 0; + border-bottom: 1px solid #c6e2ff; + + & > span { + flex: 1; + } + & > div { + flex: 2; + text-align: center; + + & > div { + text-align: left; + width: 100%; + display: flex; + justify-content: center; + align-items: flex-start; + margin-bottom: 10px; + span { + width: 50%; + &:first-of-type { + width: 25%; + } + } + } + } + &:last-of-type { + border-bottom: 0; + } + } + } + } + } + &:hover .card-header { + color: #0098f5; + } + &:hover .stepNum { + border: 2px solid #0098f5; + color: #0098f5; + } + } + .el-row { + display: flex; + align-items: center; + margin-bottom: 20px; + &:last-child { + margin-bottom: 0; + } + .grid-content { + align-items: center; + min-height: 36px; + } + + .topInfo { + width: 100%; + display: flex; + align-items: center; + font-size: 16px; + font-weight: bold; + + & > div { + white-space: nowrap; + margin-right: 20px; + } + } + } +} +.el-card { + border: 0; +} +.el-input{ + width: 100% !important; +} +::v-deep(.el-date-editor){ + width: 100%; +} +::v-deep(.el-select){ + width: 100%; +} +:deep(.el-cascader){ + width: 100% !important; +} +.el-form-item{ + width: 100% !important; +} +</style> diff --git a/src/views/goalManagement/Goalsummary/index.vue b/src/views/goalManagement/Goalsummary/index.vue new file mode 100644 index 0000000..a345459 --- /dev/null +++ b/src/views/goalManagement/Goalsummary/index.vue @@ -0,0 +1,227 @@ +<template> + <div> + <el-form ref="ruleFormRef" :model="ruleForm" status-icon label-width="20px" class="topTitle"> + <el-row> + <el-col :span="4"> + <el-form-item size="default"> + <el-input v-model="ruleForm.searchParams.year" placeholder="年度" /> + </el-form-item> + </el-col> + <el-col :span="4" > + <el-form-item size="default"> + <el-tree-select v-model="ruleForm.searchParams.departmentId" :data="data" class="w100" placeholder="请选择" /> + </el-form-item> + </el-col> + <el-col :span="4"> + <el-form-item> + <el-button size="default" type="primary" @click="listApi">查询</el-button> + <el-button size="default" @click="resetForm">重置</el-button> + </el-form-item> + </el-col> + </el-row> + </el-form> + <div class="minCenter"> + <div class="btns"> + <p>汇总日期:2022-07-04 23:00:07</p> + <div> + <el-button type="primary" size="default" :icon="Download" @click="exportExcel('tab1', '会员明细.xlsx')">导出</el-button> + </div> + </div> + <el-table :data="tableData" style="width: 100%" id="tab1"> + <el-table-column label="责任部门" align="center"> + <template #default="scope">{{ scope.row.departmentId }}</template> + </el-table-column> + <el-table-column property="targetValue" align="center" label="安全目标指标" /> + <el-table-column property="examineValue" label="考核指标" align="center" show-overflow-tooltip /> + <el-table-column property="yiYue" label="1月" align="center" show-overflow-tooltip /> + <el-table-column property="february" label="2月" align="center" show-overflow-tooltip /> + <el-table-column property="erYue" label="3月" align="center" show-overflow-tooltip /> + <el-table-column property="sanYue" label="4月" align="center" show-overflow-tooltip /> + <el-table-column property="siYue" label="5月" align="center" show-overflow-tooltip /> + <el-table-column property="wuYue" label="6月" align="center" show-overflow-tooltip /> + <el-table-column property="liuYue" label="7月" align="center" show-overflow-tooltip /> + <el-table-column property="qiYue" label="8月" align="center" show-overflow-tooltip /> + <el-table-column property="baYue" label="9月" align="center" show-overflow-tooltip /> + <el-table-column property="jiuYue" label="10月" align="center" show-overflow-tooltip /> + <el-table-column property="shiYue" label="11月" align="center" show-overflow-tooltip /> + <el-table-column property="shiyiYue" label="12月" align="center" show-overflow-tooltip /> + <el-table-column label="考核结果" align="center"> + <template #default="scope">{{ scope.row.examineResult }}</template> + </el-table-column> + </el-table> + <div class="pages"> + <el-pagination + v-model:currentPage="currentPage4" + v-model:page-size="pageSize4" + :page-sizes="[10, 20, 30, 40]" + layout="total, sizes, prev, pager, next, jumper" + :total="total" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + </div> + </div> +</template> +<script lang="ts"> +import { ref, toRefs, reactive, onMounted, defineComponent } from 'vue'; +import { ElMessageBox, ElMessage, ElButton, ElInput, TabsPaneContext, FormInstance } from 'element-plus'; +import { Plus, Delete, Upload, Download, Refresh, View } from '@element-plus/icons-vue'; +import { goalManagementApi } from '/@/api/goalManagement'; + +import * as XLSX from 'xlsx'; + +export default defineComponent({ + components: { ElButton, ElInput }, + setup() { + // 搜索条件 + const ruleForm = reactive({ + pageSize: 10, + pageIndex: 1, + searchParams: { + year: '', //年度 + departmentId: '', //责任部门 + }, + }); + // 下方导航与表格 + const tableData = ref([]); + const currentPage4 = ref(); + const pageSize4 = ref(); + const total = ref(); + const resetForm = () => { + ruleForm.searchParams.year = ''; + ruleForm.searchParams.departmentId = ''; + }; + const listApi = () => { + goalManagementApi() + .gettargetDutySummaryList(ruleForm) + .then((res) => { + if (res.data.code == 200) { + tableData.value = res.data.data; + currentPage4.value = res.data.pageIndex; + pageSize4.value = res.data.pageSize; + total.value = res.data.total; + } else { + ElMessage.error(res.data.msg); + } + }); + }; + onMounted(() => { + listApi(); + }); + + const handleSizeChange = (val: number) => { + // console.log(`${val} items per page`); + ruleForm.pageSize = val; + listApi(); + }; + const handleCurrentChange = (val: number) => { + // console.log(`current page: ${val}`); + ruleForm.pageIndex = val; + listApi(); + }; + const data = [ + { + value: '1', + label: '广汇能源综合物流发展有限责任公司', + children: [ + { + value: '11', + label: '经营班子', + children: [], + }, + ], + }, + { + value: '2', + label: '生产运行部', + children: [ + { + value: '21', + label: '灌装一班', + children: [], + }, + { + value: '22', + label: '工艺四班', + children: [], + }, + ], + }, + { + value: '3', + label: '设备部', + children: [ + { + value: '31', + label: '仪表班', + children: [], + }, + { + value: '32', + label: '机修班', + children: [], + }, + ], + }, + ]; + + const exportExcel = (id:string,name:string) => { + let workbook = XLSX.utils.table_to_book(document.getElementById(id)); //需要在table上定义一个id + try { + XLSX.writeFile(workbook, name); + console.log('导出成功!'); + } catch (e) { + console.log('导出失败!'); + } + } + return { + ruleForm, + tableData, + currentPage4, + pageSize4, + total, + data, + resetForm, + listApi, + handleSizeChange, + handleCurrentChange, + Plus, + Delete, + Upload, + Download, + Refresh, + View, + exportExcel + }; + }, +}); +</script> +<style scoped> +.topTitle { + background-color: #fff; + padding: 20px 0px 20px 0px; + margin-bottom: 10px; +} +.minCenter { + width: 100%; + background-color: #fff; + margin-top: 10px; + padding: 0 20px; +} +.btns { + padding: 10px 0px 10px 0px; + display: flex; + justify-content: left; +} +.btns p { + font-size: 18px; + line-height: 40px; + margin-right: 20px; +} +.pages { + padding: 20px 0; + display: flex; + justify-content: right; +} +</style> \ No newline at end of file diff --git a/src/views/goalManagement/IncentiveRecording/component/DailogAdd.vue b/src/views/goalManagement/IncentiveRecording/component/DailogAdd.vue new file mode 100644 index 0000000..c0a5906 --- /dev/null +++ b/src/views/goalManagement/IncentiveRecording/component/DailogAdd.vue @@ -0,0 +1,204 @@ +<template> + <el-dialog v-model="dialogVisible" :before-close="resetForm" :fullscreen="full" :title="titles" width="50%" draggable> + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-form :model="form" :disabled="disabled" label-width="120px"> + <el-row> + <el-col :span="24"> + <el-form-item label="员工姓名" size="default"> + <el-input v-model="form.personName" placeholder="请选择"> + <template #append> <el-button :icon="Search" @click="daiInpts(0)" /> </template + ></el-input> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="11"> + <el-form-item label="奖惩名称" size="default"> + <el-input v-model="form.rewardPunishmentStandardName" placeholder="请选择"> + <template #append> <el-button :icon="Search" @click="daiInpt" /> </template + ></el-input> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="奖惩类型" size="default"> + <el-select v-model="form.standardType" disabled size="default" style="width: 100%" placeholder="请选择"> + <el-option label="奖励" :value="1" /> + <el-option label="惩罚" :value="2" /> + </el-select> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="24"> + <el-form-item label="奖惩内容" size="default"> + <el-input disabled v-model="form.content" placeholder="请填写奖惩内容" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="24"> + <el-form-item label="依据" size="default"> + <el-input disabled v-model="form.reason" placeholder="请填写奖惩依据" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="24"> + <el-form-item label="备注信息"> + <el-input v-model="form.memo" type="textarea" /> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="resetForm" size="default">关闭</el-button> + <el-button type="primary" @click="submitForm" size="default" :disabled="disabled">确定</el-button> + </span> + </template> + </el-dialog> + <DailogSearchUser ref="Show" @SearchUser="UserId"></DailogSearchUser> + <DailogSearch ref="Shows" @backNum="numberId"></DailogSearch> +</template> +<script lang="ts"> +import { defineComponent, ref, reactive } from 'vue'; +import { Search, FullScreen } from '@element-plus/icons-vue'; +import DailogSearch from './DailogSearch.vue'; +import { goalManagementApi } from '/@/api/goalManagement'; +import DailogSearchUser from '/@/components/DailogSearchUser/index.vue'; +import { ElMessageBox, ElMessage, ElButton, ElInput, TabsPaneContext } from 'element-plus'; +export default defineComponent({ + components: { DailogSearch, DailogSearchUser }, + setup(props, { emit }) { + const dialogVisible = ref<boolean>(false); + const form = ref({ + rewardPunishmentStandardId: '', //奖惩标准/外键 + rewardPunishmentStandardName: '', + memo: '', ////备注信息 + personId: '', ////员工(多个用逗号隔开) + personName: '', + }); + const titles = ref(); + const disabled = ref(false); + // 打开弹窗 + const openDailog = (title: string, value: any, data: any) => { + dialogVisible.value = true; + titles.value = `${title}奖惩标准设定`; + disabled.value = title == '查看' ? true : false; + if (title == '查看' || title == '修改') + goalManagementApi() + .getrewardPunishmentDetail(data.id) + .then((res) => { + if (res.data.code == 200) { + form.value = res.data.data; + form.value.standardType = data.standardType; + form.value.content = data.content; + form.value.reason = data.reason; + } else { + ElMessage.error(res.data.msg); + } + }); + }; + // 提交 + const submitForm = () => { + dialogVisible.value = false; + delete form.value.standardType; + delete form.value.content; + delete form.value.reason; + delete form.value.rewardPunishmentStandardName + goalManagementApi() + .getrewardPunishmentAddOrUpdate(form.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + message: res.data.msg, + type: 'success', + }); + emit('navAddorUpdata'); + } else { + ElMessage.error(res.data.msg); + } + }); + form.value = { + rewardPunishmentStandardId: '', //奖惩标准/外键 + rewardPunishmentStandardName: '', + memo: '', ////备注信息 + personId: '', ////员工(多个用逗号隔开) + personName: '', + }; + }; + // 取消 + const resetForm = () => { + dialogVisible.value = false; + form.value = { + rewardPunishmentStandardId: '', //奖惩标准/外键 + rewardPunishmentStandardName: '', + memo: '', ////备注信息 + personId: '', ////员工(多个用逗号隔开) + personName: '', + }; + }; + + // 安全目标指标弹窗 + const Shows = ref(); + const daiInpt = () => { + Shows.value.openDailog(); + }; + const Show = ref(); + const daiInpts = (type: any) => { + Show.value.openDailog(type); + }; + const numberId = (val: any) => { + console.log(val); + form.value.rewardPunishmentStandardId = val.id; + form.value.rewardPunishmentStandardName = val.qname; + form.value.standardType = val.standardType; + form.value.content = val.content; + form.value.reason = val.reason; + }; + const UserId = (val: any) => { + let arr = []; + let arrId = []; + for (let i = 0; i < val.length; i++) { + arr.push(val[i].realName); + arrId.push(val[i].uid); + } + form.value.personName = arr.toString(); + form.value.personId = arrId.toString(); + }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + return { + dialogVisible, + UserId, + form, + titles, + disabled, + openDailog, + submitForm, + numberId, + resetForm, + Shows, + daiInpt, + Show, + daiInpts, + full, + toggleFullscreen, + Search, + FullScreen, + }; + }, +}); +</script> +<style scoped> +.el-row { + padding: 0 0 20px 0; +} +</style> \ No newline at end of file diff --git a/src/views/goalManagement/IncentiveRecording/component/DailogSearch.vue b/src/views/goalManagement/IncentiveRecording/component/DailogSearch.vue new file mode 100644 index 0000000..aabfa03 --- /dev/null +++ b/src/views/goalManagement/IncentiveRecording/component/DailogSearch.vue @@ -0,0 +1,204 @@ +<template> + <el-dialog v-model="dialogVisible" :fullscreen="full" title="奖惩类型" width="50%" draggable> + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-row> + <el-col :span="17"> + <el-form ref="ruleFormRef" :model="ruleForm" status-icon> + <el-row> + <el-col :span="12"> + <el-form-item size="default"> + <el-input v-model="ruleForm.searchParams.standardType" placeholder="奖惩类型" /> + </el-form-item> + </el-col> + <!-- <el-col :span="6" :offset="1"> + <el-form-item> + <el-input v-model="ruleForm.checkPass" placeholder="目标指标编号" /> + </el-form-item> + </el-col> --> + <el-col :span="11" :offset="1"> + <el-form-item> + <el-button size="default" type="primary" @click="listApi">查询</el-button> + <el-button size="default" @click="resetForm">重置</el-button> + </el-form-item> + </el-col> + </el-row> + </el-form> + <el-button size="default" :icon="Delete" @click="clear">清除选择</el-button> + <el-table :data="tableData" style="width: 100%; margin-top: 20px"> + <el-table-column align="center"> + <template #default="scope"> + <el-radio-group v-model="radio1"> + <el-radio :label="scope.row.id" @click="radio(scope.row)" size="large">{{ null }}</el-radio> + </el-radio-group> + </template> + </el-table-column> + <el-table-column align="center" prop="qname" label="奖惩名称" width="180" /> + <el-table-column align="center" label="奖惩类型" width="180"> + <template #default="scope"> + <span v-if="scope.row.standardType == 1">奖励</span> + <span v-if="scope.row.standardType == 2">惩罚</span> + <span></span> + </template> + </el-table-column> + <el-table-column align="center" prop="content" label="奖惩内容" /> + </el-table> + <el-pagination + style="padding: 20px 0; border-bottom: 1px solid #dedede" + v-model:currentPage="currentPage4" + v-model:page-size="pageSize4" + :page-sizes="[10, 20, 30, 40]" + layout="total, sizes, prev, pager, next, jumper" + :total="total" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </el-col> + <el-col :span="7"> + <div v-if="dynamicTags[0] == '' ? false : true"> + <el-tag + v-for="tag in dynamicTags" + :key="tag" + class="mx-1" + style="margin: 5px" + closable + :disable-transitions="false" + @close="handleClose(tag)" + > + {{ tag.qname }} + </el-tag> + </div> + </el-col> + </el-row> + <template #footer> + <span class="dialog-footer"> + <el-button @click="dialogVisible = false" size="default">关闭</el-button> + <el-button type="primary" @click="submitForm" size="default">确定</el-button> + </span> + </template> + </el-dialog> +</template> +<script lang="ts"> +import { defineComponent, reactive, ref, onMounted } from 'vue'; +import { Delete, FullScreen } from '@element-plus/icons-vue'; +import { ElMessageBox, ElMessage, ElButton, ElInput, TabsPaneContext, FormInstance } from 'element-plus'; +import { goalManagementApi } from '/@/api/goalManagement'; +export default defineComponent({ + setup(props, { emit }) { + // 搜索条件 + const ruleForm = reactive({ + pageSize: 10, + pageIndex: 1, + searchParams: { + standardType: '', ////奖惩类型 1:奖励 2:惩罚 + }, + }); + // 重置 + const resetForm = () => { + ruleForm.searchParams.standardType = ''; + listApi(); + }; + const listApi = () => { + goalManagementApi() + .getrewardPunishmentStandardList(ruleForm) + .then((res) => { + if (res.data.code == 200) { + tableData.value = res.data.data; + currentPage4.value = res.data.pageIndex; + pageSize4.value = res.data.pageSize; + total.value = res.data.total; + } else { + ElMessage.error(res.data.msg); + } + }); + }; + // + const handleClick = (val: any) => { + let targetType = JSON.parse(JSON.stringify(val)); + ruleForm.searchParams.standardType = targetType.paneName; + listApi(); + }; + onMounted(() => {}); + // const onAddorUpdata = () => { + // listApi(); + // }; + // 表格 + const tableData = ref(); + const currentPage4 = ref(); + const pageSize4 = ref(); + const total = ref(); + const handleSizeChange = (val: number) => { + // console.log(`${val} items per page`); + ruleForm.pageSize = val; + listApi(); + }; + const handleCurrentChange = (val: number) => { + // console.log(`current page: ${val}`); + ruleForm.pageIndex = val; + listApi(); + }; + // 打开弹窗 + const dialogVisible = ref(false); + const openDailog = () => { + dialogVisible.value = true; + listApi(); + }; + // 右方点击添加后显示标签 + const dynamicTags = ref(['']); + const handleClose = (tag: string) => { + dynamicTags.value.splice(dynamicTags.value.indexOf(tag), 1); + radio1.value = ''; + }; + const radio1 = ref(''); + const radio = (event: any) => { + dynamicTags.value[0] = event; + }; + const clear = () => { + dynamicTags.value = ['']; + radio1.value = ''; + }; + const submitForm = () => { + let obj = JSON.parse(JSON.stringify(dynamicTags.value)); + emit('backNum', obj[0]); + dialogVisible.value = false; + }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + return { + submitForm, + radio, + radio1, + clear, + dialogVisible, + openDailog, + ruleForm, + resetForm, + tableData, + currentPage4, + pageSize4, + total, + handleSizeChange, + handleCurrentChange, + dynamicTags, + listApi, + handleClick, + handleClose, + Delete, + full, + toggleFullscreen, + FullScreen, + }; + }, +}); +</script> +<style scoped> +.el-row { + padding: 0 0 20px 0; +} +</style> diff --git a/src/views/goalManagement/IncentiveRecording/index.vue b/src/views/goalManagement/IncentiveRecording/index.vue new file mode 100644 index 0000000..829190a --- /dev/null +++ b/src/views/goalManagement/IncentiveRecording/index.vue @@ -0,0 +1,302 @@ +<template> + <div> + <el-form ref="ruleFormRef" :model="ruleForm" status-icon label-width="20px" class="topTitle"> + <el-row> + <el-col :span="4"> + <el-form-item size="default"> + <el-input v-model="personName" placeholder="请选择被奖惩者"> + <template #append> + <el-button :icon="Search" @click="openSearch" /> + </template> + </el-input> + </el-form-item> + </el-col> + <!-- <el-col :span="4"> + <el-form-item> + <el-input v-model="ruleForm.checkPass" placeholder="目标指标编号" /> + </el-form-item> + </el-col> --> + <el-col :span="4"> + <el-form-item> + <el-button size="default" type="primary" @click="listApi">查询</el-button> + <el-button size="default" @click="resetForm">重置</el-button> + </el-form-item> + </el-col> + </el-row> + </el-form> + <div class="minCenter"> + <div class="btns"> + <div> + <el-button size="default" type="primary" :icon="Plus" @click="openD('新建')">新建</el-button> + <el-button size="default" :disabled="warning" type="warning" plain :icon="EditPen" + @click="openD('修改', editRow)">修改</el-button> + <el-button size="default" :disabled="danger" type="danger" :icon="Delete" plain @click="onDeleteAll">删除 </el-button> + </div> + <div> + <!-- <el-button size="default" :icon="Download"></el-button> + <el-button size="default" :icon="Refresh"></el-button> --> + </div> + </div> + <el-table ref="multipleTableRef" :data="tableData" style="width: 100%" @selection-change="handleSelectionChange"> + <el-table-column type="selection" align="center" width="55" /> + <el-table-column property="createTime" align="center" label="奖惩日期" :formatter="timeDate" sortable /> + <el-table-column label="奖惩类型" align="center" sortable> + <template #default="scope"> + <span v-if="scope.row.standardType == 1">奖励</span> + <span v-if="scope.row.standardType == 2">惩罚</span> + </template> + </el-table-column> + <el-table-column property="personName" align="center" label="被奖惩者" sortable /> + <el-table-column property="content" label="奖惩内容" align="center" sortable show-overflow-tooltip /> + <el-table-column property="reason" label="奖惩依据" align="center" sortable show-overflow-tooltip /> + <el-table-column label="操作" align="center" sortable show-overflow-tooltip> + <template #default="scope"> + <el-button link type="primary" size="default" :icon="View" @click="openD('查看', scope.row)">查看 </el-button> + <el-button link type="primary" size="default" :icon="EditPen" @click="openD('修改', scope.row)">修改</el-button> + <el-button link type="primary" size="default" :icon="Delete" @click="onDelete(scope.row.id)">删除 </el-button> + </template> + </el-table-column> + </el-table> + <div class="pages"> + <el-pagination + v-model:currentPage="currentPage4" + v-model:page-size="pageSize4" + :page-sizes="[10, 20, 30, 40]" + layout="total, sizes, prev, pager, next, jumper" + :total="total" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + <DailogAdd ref="openAdd" @navAddorUpdata="onAddorUpdata"></DailogAdd> + <DailogSearchUser ref="openUser" @SearchUser="userId"></DailogSearchUser> + </div> + </div> +</template> +<script lang="ts"> +import DailogAdd from './component/DailogAdd.vue'; +import {timeDate} from '/@/assets/index.ts' +import DailogSearchUser from '/@/components/DailogSearchUser/index.vue'; +import { ref, toRefs, reactive, onMounted, defineComponent } from 'vue'; +import { ElMessageBox, ElMessage, ElButton, ElInput, TabsPaneContext, FormInstance } from 'element-plus'; +import { Plus, Delete, Upload, Download, Refresh, View, EditPen, Search } from '@element-plus/icons-vue'; +import { goalManagementApi } from '/@/api/goalManagement'; +export default defineComponent({ + components: { ElButton, ElInput, DailogAdd, DailogSearchUser }, + setup() { + // 搜索条件 + const ruleForm = reactive({ + pageSize: 10, + pageIndex: 1, + searchParams: { + personId: '', ////员工 + }, + }); + // 重置 + const personName=ref() + const resetForm = () => { + ruleForm.searchParams.personId = ''; + personName.value = ''; + listApi(); + }; + const listApi = () => { + goalManagementApi() + .getrewardPunishmentList(ruleForm) + .then((res) => { + if (res.data.code == 200) { + tableData.value = res.data.data; + currentPage4.value = res.data.pageIndex; + pageSize4.value = res.data.pageSize; + total.value = res.data.total; + } else { + ElMessage.error(res.data.msg); + } + }); + }; + // + const handleClick = (val: any) => { + let targetType = JSON.parse(JSON.stringify(val)); + ruleForm.searchParams.personId = targetType.paneName; + listApi(); + }; + onMounted(() => { + listApi(); + }); + const onAddorUpdata = () => { + listApi(); + }; + // 表格 + const tableData = ref(); + const currentPage4 = ref(); + const pageSize4 = ref(); + const total = ref(); + const handleSizeChange = (val: number) => { + // console.log(`${val} items per page`); + ruleForm.pageSize = val; + listApi(); + }; + const handleCurrentChange = (val: number) => { + // console.log(`current page: ${val}`); + ruleForm.pageIndex = val; + listApi(); + }; + // 弹窗 + const openAdd = ref(); + const openD = (title: String, id: number) => { + openAdd.value.openDailog(title, ruleForm.searchParams.personId, id); + }; + // 删除 + const onDelete = (id: number) => { + let arr=[] + arr.push(id) + ElMessageBox.confirm('确定删除所选项吗?', 'Warning', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + goalManagementApi() + .getrewardPunishmentDelete(arr) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + message: res.data.msg, + type: 'success', + }); + listApi(); + } else { + ElMessage.error(res.data.msg); + } + }); + }) + .catch(() => { + ElMessage({ + type: 'info', + message: 'Delete canceled', + }); + }); + }; + // 批量删除 + const warning = ref(true); + const danger = ref(true); + const deletAll = ref(); + const editRow = ref() + const handleSelectionChange = (val: any) => { + editRow.value = val[0] + let valId = JSON.parse(JSON.stringify(val)); + let arr = []; + for (let i = 0; i < valId.length; i++) { + arr.push(valId[i].id); + } + deletAll.value = arr + if (val.length == 1) { + warning.value = false; + danger.value = false; + } else if (val.length == 0) { + warning.value = true; + danger.value = true; + } else { + warning.value = true; + danger.value = false; + } + }; + const onDeleteAll = () => { + ElMessageBox.confirm('确定删除所选项吗?', 'Warning', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + goalManagementApi() + .getrewardPunishmentDelete(deletAll.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + message: res.data.msg, + type: 'success', + }); + listApi(); + } else { + ElMessage.error(res.data.msg); + } + }); + }) + .catch(() => { + // ElMessage({ + // type: 'info', + // message: 'Delete canceled', + // }); + }); + }; + const openUser = ref(); + const openSearch = () => { + openUser.value.openDailog(); + }; + const userId = (val: any) => { + ruleForm.searchParams.personId = val.uid; + personName.value = val.realName; + }; + return { + timeDate, + personName, + ruleForm, + userId, + resetForm, + listApi, + handleClick, + onAddorUpdata, + tableData, + currentPage4, + pageSize4, + total, + handleSizeChange, + handleCurrentChange, + openD, + onDelete, + openAdd, + warning, + danger, + deletAll, + openSearch, + handleSelectionChange, + onDeleteAll, + openUser, + Plus, + Delete, + Upload, + Download, + Refresh, + View, + EditPen, + Search, + editRow + }; + }, +}); +</script> +<style scoped> +.minCenter { + width: 100%; + background-color: #fff; + margin-top: 10px; + padding: 0 20px; +} + +.topTitle { + background-color: #fff; + padding: 20px 0px 20px 0px; + margin-bottom: 10px; +} + +.btns { + padding: 10px 0px 10px 0px; + display: flex; + justify-content: space-between; +} + +.pages { + padding: 20px 0; + display: flex; + justify-content: right; +} +</style> \ No newline at end of file diff --git a/src/views/goalManagement/Incentivestandard/component/DailogAdd.vue b/src/views/goalManagement/Incentivestandard/component/DailogAdd.vue new file mode 100644 index 0000000..e910cb5 --- /dev/null +++ b/src/views/goalManagement/Incentivestandard/component/DailogAdd.vue @@ -0,0 +1,147 @@ +<template> + <el-dialog v-model="dialogVisible" :before-close="resetForm" :fullscreen="full" :title="titles" width="50%" draggable> + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-form :model="form" :disabled="disabled" label-width="120px"> + <el-row> + <el-col :span="11"> + <el-form-item label="奖惩类型" size="default"> + <el-select v-model="form.standardType" style="width: 100%" placeholder="请选择"> + <el-option label="奖励" :value="1" /> + <el-option label="惩罚" :value="2" /> + </el-select> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="奖惩内容" size="default"> + <el-input v-model="form.content" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="11"> + <el-form-item label="奖惩名称" size="default"> + <el-input v-model="form.qName" /> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="依据" size="default"> + <el-input v-model="form.reason" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="24"> + <el-form-item label="备注信息"> + <el-input v-model="form.memo" type="textarea" /> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="resetForm" size="default">关闭</el-button> + <el-button type="primary" @click="submitForm" size="default" :disabled="disabled">确定</el-button> + </span> + </template> + </el-dialog> +</template> +<script lang="ts"> +import { defineComponent, ref, reactive } from 'vue'; +import { Search, FullScreen } from '@element-plus/icons-vue'; +import { goalManagementApi } from '/@/api/goalManagement'; +import { ElMessageBox, ElMessage, ElButton, ElInput, TabsPaneContext } from 'element-plus'; +export default defineComponent({ + setup(props, { emit }) { + let Shows = ref(false); + const dialogVisible = ref<boolean>(false); + const form = ref({ + qName: "", ////奖惩名称 + reason: "", ////依据 + memo: "", ////备注信息 + content: "", ////奖惩内容 + standardType: null ////奖惩类型 1:奖励 2:惩罚 + }); + const titles = ref(); + const disabled = ref(false); + // 打开弹窗 + const openDailog = (title: string, value: any, id: number) => { + dialogVisible.value = true; + titles.value = `${title}奖惩标准设定`; + disabled.value = title == '查看' ? true : false; + if (title == '查看' || title == '修改') + goalManagementApi() + .getrewardPunishmentStandardDetail(id) + .then((res) => { + if (res.data.code == 200) { + form.value = res.data.data; + } else { + ElMessage.error(res.data.msg); + } + }); + }; + // 提交 + const submitForm = () => { + dialogVisible.value = false; + goalManagementApi() + .getrewardPunishmentStandardaddOrUpdate(form.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + message: res.data.msg, + type: 'success', + }); + emit('navAddorUpdata'); + } else { + ElMessage.error(res.data.msg); + } + }); + form.value = { + qName: "", ////奖惩名称 + reason: "", ////依据 + memo: "", ////备注信息 + content: "", ////奖惩内容 + standardType: null, ////奖惩类型 1:奖励 2:惩罚 + } + }; + // 取消 + const resetForm = () => { + dialogVisible.value = false; + form.value = { + qName: "", ////奖惩名称 + reason: "", ////依据 + memo: "", ////备注信息 + content: "", ////奖惩内容 + standardType: null, ////奖惩类型 1:奖励 2:惩罚 + }; + }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + + return { + form, + titles, + dialogVisible, + openDailog, + disabled, + Search, + submitForm, + resetForm, + full, + toggleFullscreen, + FullScreen, + }; + }, +}); +</script> +<style scoped> +.el-row { + padding: 0 0 20px 0; +} +</style> \ No newline at end of file diff --git a/src/views/goalManagement/Incentivestandard/index.vue b/src/views/goalManagement/Incentivestandard/index.vue new file mode 100644 index 0000000..c0aadc8 --- /dev/null +++ b/src/views/goalManagement/Incentivestandard/index.vue @@ -0,0 +1,283 @@ +<template> + <div> + <el-form ref="ruleFormRef" :model="ruleForm" status-icon label-width="20px" class="topTitle"> + <el-row> + <el-col :span="4"> + <el-form-item> + <el-select v-model="ruleForm.searchParams.standardType" size="default" style="width: 100%" placeholder="请选择"> + <el-option label="奖励" value="1" /> + <el-option label="惩罚" value="2" /> + </el-select> + </el-form-item> + </el-col> + <!-- <el-col :span="4"> + <el-form-item> + <el-input v-model="ruleForm.checkPass" placeholder="目标指标编号" /> + </el-form-item> + </el-col> --> + <el-col :span="4"> + <el-form-item> + <el-button size="default" type="primary" @click="listApi">查询</el-button> + <el-button size="default" @click="resetForm">重置</el-button> + </el-form-item> + </el-col> + </el-row> + </el-form> + <div class="minCenter"> + <div class="btns"> + <div> + <el-button size="default" type="primary" :icon="Plus" @click="openD('新建')" >新建</el-button> + <el-button size="default" type="warning" :disabled="warning" plain :icon="EditPen" + @click="openD('修改', deletAll[0])">修改 </el-button> + <el-button size="default" type="danger" :disabled="danger" :icon="Delete" plain @click="handleSelectionChange">删除</el-button> + </div> + <div> + <!-- <el-button size="default" :icon="Upload" @click="upButton"></el-button> + <el-button size="default" :icon="Download"></el-button> + <el-button size="default" :icon="Refresh"></el-button> --> + </div> + </div> + <el-table ref="multipleTableRef" :data="tableData" @selection-change="handleSelectionChange" style="width: 100%"> + <el-table-column type="selection" align="center" width="55" /> + <el-table-column property="qname" align="center" label="奖惩名称" sortable /> + <el-table-column property="name" align="center" label="奖惩类型" sortable> + <template #default="scope"> + <span v-if="scope.row.standardType == 1">奖励</span> + <span v-if="scope.row.standardType == 2">惩罚</span> + </template> + </el-table-column> + <el-table-column property="content" label="奖惩内容" align="center" sortable show-overflow-tooltip /> + <el-table-column property="reason" label="依据" align="center" sortable show-overflow-tooltip /> + <el-table-column property="memo" label="备注信息" align="center" sortable show-overflow-tooltip /> + <el-table-column label="操作" align="center" sortable show-overflow-tooltip> + <template #default="scope"> + <el-button link type="primary" size="default" :icon="View" @click="openD('查看', scope.row.id)">查看 </el-button> + <el-button link type="primary" size="default" :icon="EditPen" @click="openD('修改', scope.row.id)">修改</el-button> + <el-button link type="primary" size="default" :icon="Delete" @click="onDelete(scope.row.id)">删除 </el-button> + </template> + </el-table-column> + </el-table> + <div class="pages"> + <el-pagination + v-model:currentPage="currentPage4" + v-model:page-size="pageSize4" + :page-sizes="[10, 20, 30, 40]" + layout="total, sizes, prev, pager, next, jumper" + :total="total" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + <DailogAdd ref="openAdd" @navAddorUpdata="onAddorUpdata"></DailogAdd> + <!-- <upData ref="upShow"></upData> --> + </div> + </div> +</template> +<script lang="ts"> +import DailogAdd from './component/DailogAdd.vue'; +import upData from '../../../components/updata/updata.vue'; +import { ref, toRefs, reactive, onMounted, defineComponent } from 'vue'; +import { ElMessageBox, ElMessage, ElButton, ElInput, TabsPaneContext, FormInstance } from 'element-plus'; +import { Plus, Delete, Upload, Download, Refresh, View, EditPen } from '@element-plus/icons-vue'; +import type { TableColumnCtx } from 'element-plus/es/components/table/src/table-column/defaults'; +import { goalManagementApi } from '/@/api/goalManagement'; +export default defineComponent({ + components: { ElButton, ElInput, upData, DailogAdd }, + setup() { + // 搜索条件 + const ruleForm = reactive({ + pageSize: 10, + pageIndex: 1, + searchParams: { + standardType: '', ////奖惩类型 1:奖励 2:惩罚 + }, + }); + // 重置 + const resetForm = () => { + ruleForm.searchParams.standardType = ''; + listApi(); + }; + const listApi = () => { + goalManagementApi() + .getrewardPunishmentStandardList(ruleForm) + .then((res) => { + if (res.data.code == 200) { + tableData.value = res.data.data; + currentPage4.value = res.data.pageIndex; + pageSize4.value = res.data.pageSize; + total.value = res.data.total; + } else { + ElMessage.error(res.data.msg); + } + }); + }; + // + const handleClick = (val: any) => { + let targetType = JSON.parse(JSON.stringify(val)); + ruleForm.searchParams.standardType = targetType.paneName; + listApi(); + }; + onMounted(() => { + listApi(); + }); + const onAddorUpdata = () => { + listApi(); + }; + // 表格 + const tableData = ref(); + const currentPage4 = ref(); + const pageSize4 = ref(); + const total = ref(); + const handleSizeChange = (val: number) => { + // console.log(`${val} items per page`); + ruleForm.pageSize = val; + listApi(); + }; + const handleCurrentChange = (val: number) => { + // console.log(`current page: ${val}`); + ruleForm.pageIndex = val; + listApi(); + }; + // 弹窗 + const openAdd = ref(); + const openD = (title: String, id: number) => { + openAdd.value.openDailog(title, ruleForm.searchParams.standardType, id); + }; + // 删除 + const onDelete = (id: number) => { + let arr=[] + arr.push(id) + ElMessageBox.confirm('确定删除所选项吗?', 'Warning', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + goalManagementApi() + .getrewardPunishmentStandardDelete(arr) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + message: res.data.msg, + type: 'success', + }); + listApi(); + } else { + ElMessage.error(res.data.msg); + } + }); + }) + .catch(() => { + ElMessage({ + type: 'info', + message: 'Delete canceled', + }); + }); + }; + // 批量删除 + const warning = ref(true); + const danger = ref(true); + const deletAll = ref(); + const handleSelectionChange = (val: any) => { + let valId = JSON.parse(JSON.stringify(val)); + let arr = []; + for (let i = 0; i < valId.length; i++) { + arr.push(valId[i].id); + } + deletAll.value = arr; + if (val.length == 1) { + warning.value = false; + danger.value = false; + } else if (val.length == 0) { + warning.value = true; + danger.value = true; + } else { + warning.value = true; + danger.value = false; + } + }; + const onDeleteAll = () => { + ElMessageBox.confirm('确定删除所选项吗?', 'Warning', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + goalManagementApi() + .getrewardPunishmentStandardDelete(deletAll.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + message: res.data.msg, + type: 'success', + }); + listApi(); + } else { + ElMessage.error(res.data.msg); + } + }); + }) + .catch(() => { + // ElMessage({ + // type: 'info', + // message: 'Delete canceled', + // }); + }); + }; + return { + ruleForm, + resetForm, + listApi, + handleClick, + onAddorUpdata, + tableData, + currentPage4, + pageSize4, + total, + handleSizeChange, + handleCurrentChange, + openAdd, + openD, + onDelete, + warning, + danger, + deletAll, + handleSelectionChange, + onDeleteAll, + Plus, + Delete, + Upload, + Download, + Refresh, + View, + EditPen, + }; + }, +}); +</script> +<style scoped> +.minCenter { + width: 100%; + background-color: #fff; + margin-top: 10px; + padding: 0 20px; +} + +.topTitle { + background-color: #fff; + padding: 20px 0px 20px 0px; + margin-bottom: 10px; +} + +.btns { + padding: 10px 0px 10px 0px; + display: flex; + justify-content: space-between; +} + +.pages { + padding: 20px 0; + display: flex; + justify-content: right; +} +</style> \ No newline at end of file diff --git a/src/views/goalManagement/TargetBook/component/DailogAdd.vue b/src/views/goalManagement/TargetBook/component/DailogAdd.vue new file mode 100644 index 0000000..fa0bc2a --- /dev/null +++ b/src/views/goalManagement/TargetBook/component/DailogAdd.vue @@ -0,0 +1,246 @@ +<template> + <el-dialog v-model="dialogVisible" :before-close="resetForm" :fullscreen="full" :title="titles" width="50%" draggable @close="resetForm"> + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-form :model="form" :disabled="disabled" label-width="120px"> + <el-row> + <el-col :span="24"> + <el-form-item label="岗位" size="default"> + <el-input v-model="form.jobName" placeholder="请选择"> + <template #append> <el-button :icon="Search" @click="daiInpt" /> </template + ></el-input> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="24"> + <el-form-item label="责任书签订日期" size="default"> + <el-date-picker v-model="form.signDate" style="width:100%" format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss" type="datetime" placeholder="请选择日期时间" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="24"> + <el-form-item label="备注信息"> + <el-input v-model="form.memo" type="textarea" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="24"> + <el-form-item label="责任书附件"> + <uploaderFile :fileList="fileList" :systemName="'GOAL_MANAGE'" :disabled="disabled" + @successUploader="successUploader" @deleteFile="deleteFile"></uploaderFile> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="resetForm" size="default">关闭</el-button> + <el-button type="primary" @click="submitForm" size="default">确定</el-button> + </span> + </template> + </el-dialog> + <DailogSearch ref="Shows" @backNum="IdNumber"></DailogSearch> +</template> +<script lang="ts"> +import { defineComponent, ref, reactive } from 'vue'; +import { Search, FullScreen } from '@element-plus/icons-vue'; +import DailogSearch from './DailogSearch.vue'; +import { ElMessage, ElMessageBox } from 'element-plus'; +import type { UploadProps, UploadUserFile } from 'element-plus'; +import { goalManagementApi } from '/@/api/goalManagement'; +import uploaderFile from '/@/components/uploaderFile/index.vue'; +export default defineComponent({ + components: { DailogSearch,uploaderFile }, + setup(props, { emit }) { + const dialogVisible = ref<boolean>(false); + const form = ref({ + indexNum: '', //目标指标编号 + memo: '', ////备注信息 + signDate: '', //责任书签订日期 + extraFile: '', //责任书附件 + jobId: '', //岗位 + }); + const titles = ref(); + const disabled = ref(false); + // 打开弹窗 + const openDailog = (title: string, value: any, id: number) => { + dialogVisible.value = true; + titles.value =`${title}目标责任书`; + disabled.value = title == '查看' ? true : false; + if (title == '查看' || title == '修改') + goalManagementApi() + .gettargetDutyfileInfoDetail(id) + .then((res) => { + if (res.data.code == 200) { + form.value = res.data.data; + form.value.signDate=timeC(form.value.signDate) + + + if(res.data.data.extraFile!=null&&res.data.data.extraFile!=''){ + var extraFileList = res.data.data.extraFile.split(',') + for(var a = 0;a<extraFileList.length;a++){ + fileList.value.push( + { + name:extraFileList[a] + } + ) + } + }else { + fileList.value = [] + } + } else { + ElMessage.error(res.data.msg); + } + }); + }; + // 上传成功组装数据 + const successUploader = (list) =>{ + console.log('successUploader',list) + fileList.value = list + var formFileList = '' + for(var a = 0;a<fileList.value.length;a++){ + if(a==fileList.value.length-1){ + formFileList+=fileList.value[a].name + }else { + formFileList+=fileList.value[a].name+',' + } + } + form.value.extraFile = formFileList + } + const deleteFile = (list) =>{ + console.log('deleteFile',list) + fileList.value = list + const formFileList = '' + for(var a = 0;a<fileList.value.length;a++){ + if(a==fileList.value.length-1){ + formFileList.value+=fileList.value[a].name + }else { + formFileList.value+=fileList.value[a].name+',' + } + } + form.value.extraFile = formFileList + } + const timeC = (timestamp: any) => { + let a = new Date(timestamp).getTime(); + const date = new Date(a); + const Y = date.getFullYear() + '-'; + const M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-'; + const D = (date.getDate() < 10 ? '0' + date.getDate() : date.getDate()) + ' '; + const h = (date.getHours() < 10 ? '0' + date.getHours() : date.getHours()) + ':'; + const m = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes(); + const s = date.getSeconds(); // 秒 + const dateString = Y + M + D + h + m +`:${s}`; + // console.log('dateString', dateString); // > dateString 2021-07-06 14:23 + return dateString; + }; + // 提交 + const submitForm = () => { + dialogVisible.value = false; + delete form.value.jobName + goalManagementApi() + .gettargetDutyfileInfoAddorUpdata(form.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + message: res.data.msg, + type: 'success', + }); + emit('navAddorUpdata'); + } else { + ElMessage.error(res.data.msg); + } + }); + form.value = { + indexNum: '', //目标指标编号 + memo: '', ////备注信息 + signDate: '', //责任书签订日期 + extraFile: '666', //责任书附件 + jobId: '', //岗位 + }; + }; + // 取消 + const resetForm = () => { + dialogVisible.value = false; + form.value = { + indexNum: '', //目标指标编号 + memo: '', ////备注信息 + signDate: '', //责任书签订日期 + extraFile: '666', //责任书附件 + jobId: '', //岗位 + }; + fileList.value = [] + }; + // 安全目标指标弹窗 + const Shows = ref(); + const daiInpt = () => { + Shows.value.openDailog(); + }; + const IdNumber=(val:any)=>{ + form.value.jobId=val.id + form.value.jobName=val.date + } + // 点击上传 + const fileList = ref([ + ]); + + const handleRemove: UploadProps['onRemove'] = (file, uploadFiles) => { + console.log(file, uploadFiles); + }; + + const handlePreview: UploadProps['onPreview'] = (uploadFile) => { + console.log(uploadFile); + }; + + const handleExceed: UploadProps['onExceed'] = (files, uploadFiles) => { + ElMessage.warning(`The limit is 3, you selected ${files.length} files this time, add up to ${files.length + uploadFiles.length} totally`); + }; + + const beforeRemove: UploadProps['beforeRemove'] = (uploadFile, uploadFiles) => { + return ElMessageBox.confirm(`Cancel the transfert of ${uploadFile.name} ?`).then( + () => true, + () => false + ); + }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + return { + timeC, + IdNumber, + dialogVisible, + form, + disabled, + titles, + openDailog, + daiInpt, + submitForm, + resetForm, + Shows, + Search, + fileList, + handleRemove, + handlePreview, + handleExceed, + beforeRemove, + full, + toggleFullscreen, + FullScreen, + successUploader, + deleteFile + }; + }, +}); +</script> +<style scoped> +.el-row { + padding: 0 0 20px 0; +} +</style> \ No newline at end of file diff --git a/src/views/goalManagement/TargetBook/component/DailogSearch.vue b/src/views/goalManagement/TargetBook/component/DailogSearch.vue new file mode 100644 index 0000000..54a6871 --- /dev/null +++ b/src/views/goalManagement/TargetBook/component/DailogSearch.vue @@ -0,0 +1,175 @@ +<template> + <el-dialog v-model="dialogVisible" :fullscreen="full" title="选择岗位" width="50%" draggable> + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-row> + <el-col :span="17"> + <el-form ref="ruleFormRef" :model="ruleForm" status-icon> + <el-row> + <el-col :span="12"> + <el-form-item size="default"> + <el-input v-model="ruleForm.pass" placeholder="岗位名称" /> + </el-form-item> + </el-col> + <!-- <el-col :span="6" :offset="1"> + <el-form-item> + <el-input v-model="ruleForm.checkPass" placeholder="目标指标编号" /> + </el-form-item> + </el-col> --> + <el-col :span="11" :offset="1"> + <el-form-item> + <el-button size="default" type="primary" @click="submitForm(ruleFormRef)">查询</el-button> + <el-button size="default" @click="resetForm(ruleFormRef)">重置</el-button> + </el-form-item> + </el-col> + </el-row> + </el-form> + <el-button size="default" :icon="Delete">清除选择</el-button> + <el-table :data="tableData" style="width: 100%; margin-top: 20px" > + <el-table-column align="center" width="70px"> + <template #default="scope"> + <el-radio-group v-model="radio1"> + <el-radio :label="scope.row.id" @click="radio(scope.row)" size="large">{{ null }}</el-radio> + </el-radio-group> + </template> + </el-table-column> + <el-table-column align="center" prop="date" label="岗位名称" /> + </el-table> + <el-pagination + style="padding: 20px 0; border-bottom: 1px solid #dedede" + v-model:currentPage="currentPage4" + v-model:page-size="pageSize4" + :page-sizes="[100, 200, 300, 400]" + :small="small" + :disabled="disabled" + :background="background" + layout="total, sizes, prev, pager, next, jumper" + :total="1" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </el-col> + <el-col :span="7"> + <div v-if="dynamicTags[0]==''?false:true"> + <el-tag + v-for="tag in dynamicTags" + :key="tag" + class="mx-1" + style="margin: 5px" + closable + :disable-transitions="false" + @close="handleClose(tag)" + > + {{ tag.date }} + </el-tag> + </div> + </el-col> + </el-row> + <template #footer> + <span class="dialog-footer"> + <el-button @click="dialogVisible = false" size="default">关闭</el-button> + <el-button type="primary" @click="submitForm" size="default">确定</el-button> + </span> + </template> + </el-dialog> +</template> +<script lang="ts"> +import { defineComponent, reactive, ref } from 'vue'; +import { Delete, FullScreen } from '@element-plus/icons-vue'; +export default defineComponent({ + setup(props,{emit}) { + const dialogVisible = ref<boolean>(false); + const openDailog = () => { + dialogVisible.value = true; + }; + // 搜索条件 + const ruleForm = reactive({ + pass: '', + checkPass: '', + }); + // 表格 + const tableData = [ + { id:1, + date: '岗位1', + name: 'Tom', + address: 'No. 189, Grove St, Los Angeles', + }, + { + id:2, + date: '岗位2', + name: 'Tom', + address: 'No. 189, Grove St, Los Angeles', + }, + { + id:3, + date: '岗位3', + name: 'Tom', + address: 'No. 189, Grove St, Los Angeles', + }, + { id:4, + date: '岗位4', + name: 'Tom', + address: 'No. 189, Grove St, Los Angeles', + }, + ]; + const pageSize4 = ref(100); + const handleSizeChange = (val: number) => { + console.log(`${val} items per page`); + }; + const handleCurrentChange = (val: number) => { + console.log(`current page: ${val}`); + }; + // 右方点击添加后显示标签 + const dynamicTags = ref(['']); + const handleClose = (tag: string) => { + dynamicTags.value.splice(dynamicTags.value.indexOf(tag), 1); + radio1.value = ''; + }; + const radio1 = ref(''); + const radio = (event: any) => { + dynamicTags.value[0] = event; + }; + const clear=()=>{ + dynamicTags.value=[''] + radio1.value="" + } + const submitForm=()=>{ + let obj=JSON.parse(JSON.stringify(dynamicTags.value)) + emit("backNum",obj[0]) + dialogVisible.value = false + } + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + return { + radio1, + radio, + clear, + dialogVisible, + openDailog, + ruleForm, + tableData, + pageSize4, + handleSizeChange, + handleCurrentChange, + dynamicTags, + handleClose, + submitForm, + Delete, + full, + toggleFullscreen, + FullScreen, + }; + }, +}); +</script> +<style scoped> +.el-row { + padding: 0 0 20px 0; +} +</style> diff --git a/src/views/goalManagement/TargetBook/index.vue b/src/views/goalManagement/TargetBook/index.vue new file mode 100644 index 0000000..593acf8 --- /dev/null +++ b/src/views/goalManagement/TargetBook/index.vue @@ -0,0 +1,289 @@ +<template> + <div> + <el-form ref="ruleFormRef" :model="ruleForm" status-icon label-width="20px" class="topTitle"> + <el-row> + <el-col :span="4"> + <el-form-item size="default"> + <el-input v-model="jobName" placeholder="请选择岗位"> + <template #append> <el-button :icon="Search" @click="openSearch" /> </template + ></el-input> + </el-form-item> + </el-col> + <!-- <el-col :span="4"> + <el-form-item> + <el-input v-model="ruleForm.checkPass" placeholder="目标指标编号" /> + </el-form-item> + </el-col> --> + <el-col :span="4"> + <el-form-item> + <el-button size="default" type="primary" @click="listApi">查询</el-button> + <el-button size="default" @click="resetForm">重置</el-button> + </el-form-item> + </el-col> + </el-row> + </el-form> + <div class="minCenter"> + <div class="btns"> + <div> + <el-button size="default" type="primary" :icon="Plus" @click="openD('新建')">新建</el-button> + <el-button size="default" :disabled="warning" type="warning" plain :icon="EditPen" + @click="openD('修改', deletAll[0])">修改</el-button> + <el-button size="default" :disabled="danger" type="danger" :icon="Delete" plain @click="onDeleteAll">删除</el-button> + </div> + <div> + <!-- <el-button size="default" :icon="Download"></el-button> + <el-button size="default" :icon="Refresh"></el-button> --> + </div> + </div> + <el-table ref="multipleTableRef" :data="tableData" @selection-change="handleSelectionChange" style="width: 100%"> + <el-table-column type="selection" align="center" width="55" /> + <el-table-column type="index" label="序号" align="center" width="70" /> + <el-table-column property="jobId" align="center" label="岗位" sortable /> + <el-table-column property="signDate" align="center" label="责任书签订日期" :formatter="timeDate" sortable /> + <el-table-column property="extraFile" align="center" label="附件" sortable /> + <el-table-column property="memo" label="备注信息" align="center" sortable show-overflow-tooltip /> + <el-table-column label="操作" align="center" style="width: 300px"> + <template #default="scope"> + <el-button link type="primary" size="default" :icon="View" @click="openD('查看', scope.row.id)">查看</el-button> + <el-button link type="primary" size="default" :icon="EditPen" @click="openD('修改', scope.row.id)">修改</el-button> + <el-button link type="primary" size="default" :icon="Delete" @click="onDelete(scope.row.id)">删除</el-button> + </template> + </el-table-column> + </el-table> + <div class="pages"> + <el-pagination + v-model:currentPage="currentPage4" + v-model:page-size="pageSize4" + :page-sizes="[10, 20, 30, 40]" + layout="total, sizes, prev, pager, next, jumper" + :total="total" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + <DailogAdd ref="openAdd" @navAddorUpdata="onAddorUpdata"></DailogAdd> + <DailogSearch ref="openUser" @backNum="IdNumber"></DailogSearch> + </div> + </div> +</template> +<script lang="ts"> +import DailogAdd from './component/DailogAdd.vue'; +import {timeDate} from '/@/assets/index.ts' +import DailogSearch from './component/DailogSearch.vue'; +import { ref, toRefs, reactive, onMounted, defineComponent } from 'vue'; +import { ElMessageBox, ElMessage, ElButton, ElInput, TabsPaneContext, FormInstance } from 'element-plus'; +import { Plus, Delete, Upload, Download, Refresh, View, EditPen, Search } from '@element-plus/icons-vue'; +import { goalManagementApi } from '/@/api/goalManagement'; +import type { TableColumnCtx } from 'element-plus/es/components/table/src/table-column/defaults'; +export default defineComponent({ + components: { ElButton, ElInput, DailogAdd, DailogSearch }, + setup() { + // 搜索条件 + const ruleForm = reactive({ + pageSize: 10, + pageIndex: 1, + searchParams: { + jobId: '', ////岗位号/外键 + }, + }); + // 重置 + const resetForm = () => { + ruleForm.searchParams.jobId = ''; + jobName.value="" + listApi(); + }; + const listApi = () => { + goalManagementApi() + .gettargetDutyfileInfoList(ruleForm) + .then((res) => { + if (res.data.code == 200) { + tableData.value = res.data.data; + currentPage4.value = res.data.pageIndex; + pageSize4.value = res.data.pageSize; + total.value = res.data.total; + } else { + ElMessage.error(res.data.msg); + } + }); + }; + // + const handleClick = (val: any) => { + let targetType = JSON.parse(JSON.stringify(val)); + ruleForm.searchParams.jobId = targetType.paneName; + listApi(); + }; + onMounted(() => { + listApi(); + }); + const onAddorUpdata = () => { + listApi(); + }; + const jobName=ref() + const IdNumber=(val:any)=>{ + ruleForm.jobId=val.id + jobName.value=val.date + } + // 表格 + const tableData = ref(); + const currentPage4 = ref(); + const pageSize4 = ref(); + const total = ref(); + const handleSizeChange = (val: number) => { + // console.log(`${val} items per page`); + ruleForm.pageSize = val; + listApi(); + }; + const handleCurrentChange = (val: number) => { + // console.log(`current page: ${val}`); + ruleForm.pageIndex = val; + listApi(); + }; + // 弹窗 + const openAdd = ref(); + const openD = (title: String, id: number) => { + openAdd.value.openDailog(title, ruleForm.searchParams.jobId, id); + }; + // 删除 + const onDelete = (id: number) => { + let arr=[] + arr.push(id) + ElMessageBox.confirm('确定删除所选项吗?', 'Warning', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + goalManagementApi() + .gettargetDutyfileInfoDelete(arr) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + message: res.data.msg, + type: 'success', + }); + listApi(); + } else { + ElMessage.error(res.data.msg); + } + }); + }) + .catch(() => { + ElMessage({ + type: 'info', + message: 'Delete canceled', + }); + }); + }; + // 批量删除 + const warning = ref(true); + const danger = ref(true); + const deletAll = ref(); + const handleSelectionChange = (val: any) => { + let valId = JSON.parse(JSON.stringify(val)); + let arr = []; + for (let i = 0; i < valId.length; i++) { + arr.push(valId[i].id); + } + deletAll.value = arr + if (val.length == 1) { + warning.value = false; + danger.value = false; + } else if (val.length == 0) { + warning.value = true; + danger.value = true; + } else { + warning.value = true; + danger.value = false; + } + }; + const onDeleteAll = () => { + ElMessageBox.confirm('确定删除所选项吗?', 'Warning', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + goalManagementApi() + .gettargetDutyfileInfoDelete(deletAll.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + message: res.data.msg, + type: 'success', + }); + listApi(); + } else { + ElMessage.error(res.data.msg); + } + }); + }) + .catch(() => { + // ElMessage({ + // type: 'info', + // message: 'Delete canceled', + // }); + }); + }; + const openUser = ref(); + const openSearch = () => { + openUser.value.openDailog(); + }; + return { + IdNumber, + ruleForm, + resetForm, + listApi, + handleClick, + onAddorUpdata, + tableData, + currentPage4, + pageSize4, + total, + handleSizeChange, + handleCurrentChange, + openAdd, + openD, + onDelete, + warning, + danger, + deletAll, + handleSelectionChange, + onDeleteAll, + openUser, + openSearch, + timeDate, + Plus, + Delete, + Upload, + Download, + Refresh, + View, + EditPen, + Search, + }; + }, +}); +</script> +<style scoped> +.minCenter { + width: 100%; + background-color: #fff; + margin-top: 10px; + padding: 0 20px; +} +.topTitle { + background-color: #fff; + padding: 20px 0px 20px 0px; + margin-bottom: 10px; +} +.btns { + padding: 10px 0px 10px 0px; + display: flex; + justify-content: space-between; +} +.pages { + padding: 20px 0; + display: flex; + justify-content: right; +} +</style> \ No newline at end of file diff --git a/src/views/goalManagement/index.vue b/src/views/goalManagement/index.vue new file mode 100644 index 0000000..8d45119 --- /dev/null +++ b/src/views/goalManagement/index.vue @@ -0,0 +1,14 @@ +<template> + <router-view></router-view> +</template> + +<script> +export default { + name: "index" +} +</script> + +<style scoped> + +</style> + diff --git a/src/views/goalManagement/performanceAppraisal/component/DailogAq.vue b/src/views/goalManagement/performanceAppraisal/component/DailogAq.vue new file mode 100644 index 0000000..1bf1044 --- /dev/null +++ b/src/views/goalManagement/performanceAppraisal/component/DailogAq.vue @@ -0,0 +1,455 @@ +<template> + <el-dialog v-model="dialogVisible" :fullscreen="full" @close="handleClose(ruleFormRef)" :title="titles" width="50%" draggable> + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-form :model="form" label-width="120px" ref="ruleFormRef" :rules="rules"> + <el-row> + <el-col :span="11"> + <el-form-item label="考核标题" size="default" prop="title"> + <el-input v-model="form.title" placeholder="请填写考核标题"></el-input> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="考核日期" size="default" prop="examineDate"> + <el-date-picker + v-model="form.examineDate" + format="YYYY-MM-DD HH:mm:ss" + value-format="YYYY-MM-DD HH:mm:ss" + type="datetime" + placeholder="请选择" + style="width: 100%" + /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="11"> + <el-form-item label="合格分数" size="default" prop="acceptanceNumber"> + <el-input v-model="form.acceptanceNumber" disabled /> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="总分" size="default" prop="examineTotalNumber"> + <el-input v-model="form.examineTotalNumber" disabled /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="11"> + <el-form-item label="考核部门" size="default" prop="examineDepartmentId"> + <el-tree-select + v-model="form.examineDepartmentId" + :data="data" + class="w100" + @node-click="nameData1" + :props="propse" + check-strictly + placeholder="请选择" + /> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="考核人" size="default" prop="examinePersonName"> + <el-input v-model="form.examinePersonName"> + <template #append> <el-button :icon="Search" @click="daiInpt(1)" /></template> + </el-input> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="11"> + <el-form-item label="被考核部门" size="default" prop="beExaminedDepartmentId"> + <el-tree-select + v-model="form.beExaminedDepartmentId" + :data="data" + @node-click="nameData2" + class="w100" + :props="propse" + check-strictly + placeholder="请选择" + /> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="被考核人" size="default" prop="beExaminedPersonName"> + <el-input v-model="form.beExaminedPersonName"> + <template #append> <el-button :icon="Search" @click="daiInpt(0)" /></template> + </el-input> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="24"> + <el-form-item label="附件"> + <uploaderFile :fileList="fileList" :systemName="'GOAL_MANAGE'" :disabled="disabled" + @successUploader="successUploader" @deleteFile="deleteFile"></uploaderFile> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="11"> + <el-form-item label="考核模板" size="default" prop="examineTemplateName"> + <el-input v-model="form.examineTemplateName"> + <template #append> <el-button :icon="Search" @click="daiAdd" /></template> + </el-input> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="备注信息" prop="memo"> + <el-input v-model="form.memo" type="textarea"> </el-input> + </el-form-item> + </el-col> + </el-row> + </el-form> + <el-tabs v-model="activeName" class="demo-tabs"> + <el-tab-pane label="考核项目" name="1"> + <!-- <el-button type="primary" size="default" @click="daiAdd">新增</el-button> --> + </el-tab-pane> + </el-tabs> + <el-table :data="form.numberDetailJson" style="width: 100%"> + <el-table-column align="center" prop="itemDetail" label="考核项目" /> + <el-table-column align="center" prop="content" label="考核内容" /> + <el-table-column align="center" label="考核分数"> + <template #default="scope"> + <el-input @blur="numberC" v-model.number="scope.row.number"> </el-input> + </template> + </el-table-column> + <!-- <el-table-column align="center" prop="address" label="制定日期" /> + <el-table-column align="center" prop="address" label="上报人" /> + <el-table-column align="center" label="操作"> + <template #default> + <el-button link type="primary">查看</el-button> + </template> + </el-table-column> --> + </el-table> + <template #footer> + <span class="dialog-footer"> + <el-button @click="resetForm(ruleFormRef)" size="default">关闭</el-button> + <el-button type="primary" @click="submitForm(ruleFormRef)" size="default">确定</el-button> + </span> + </template> + </el-dialog> + <DailogSearch ref="Show" @typeDome="onType"></DailogSearch> + <DailogSearchUser ref="Shows" @SearchUser="userId"></DailogSearchUser> +</template> +<script lang="ts"> +import { defineComponent, ref, reactive } from 'vue'; +import { Search, FullScreen } from '@element-plus/icons-vue'; +import DailogSearch from './DailogSearch.vue'; +import DailogSearchUser from '/@/components/DailogSearchUser/index.vue'; +import { ElMessage, ElMessageBox } from 'element-plus'; +import { goalManagementApi } from '/@/api/goalManagement'; +import type { UploadProps, UploadUserFile } from 'element-plus'; +import type { FormInstance, FormRules } from 'element-plus'; +import uploaderFile from '/@/components/uploaderFile/index.vue'; +export default defineComponent({ + components: { DailogSearchUser, DailogSearch,uploaderFile }, + setup(props, { emit }) { + const dialogVisible = ref<boolean>(false); + const ruleFormRef = ref<FormInstance>(); + const form = ref({ + beExaminedDepartmentId: '', ////被考核部门ID/外键 + beExaminedDepartmentName: '', + beExaminedPersonId: '', ////被考核人ID/外键(可能有多个,用逗号隔开) + beExaminedPersonName: '', + examineDate: '', ////考核日期 + examineDepartmentId: '', ////考核部门ID/外键 + examineDepartmentName: '', + examinePersonId: '', ////考核人ID/外键 + examinePersonName: '', + examineTemplateId: '', ////绩效考核模板ID/外键 + examineTemplateName: '', + examineTotalNumber: '', ////总分 + acceptanceNumber: '', ///合格分数 + extraFile: '', //责任书附件 + itemDetail: '', ////考核项目 + memo: '', ////备注信息 + numberDetailJson: [], ////各个考核项目的具体得分,json格式。形式为:[{“id”:"123","number":"123"}] + title: '', ////考核标题 + }); + const titles = ref(); + const titleT = ref(); + const disabled = ref(false); + // 打开弹窗 + const openDailog = (title: string, value: any, id: number) => { + department(); + dialogVisible.value = true; + titles.value = `${title}安全考核管理`; + titleT.value=title + disabled.value = title == '查看' ? true : false; + if (title == '查看' || title == '修改') + goalManagementApi() + .getexamineMngDetail(id) + .then((res) => { + if (res.data.code == 200) { + form.value = res.data.data; + form.value.examineDate = timeC(form.value.examineDate); + form.value.numberDetailJson = form.value.currentExamineDtoList; + + + if(res.data.data.extraFile!=null&&res.data.data.extraFile!=''){ + var extraFileList = res.data.data.extraFile.split(',') + for(var a = 0;a<extraFileList.length;a++){ + fileList.value.push( + { + name:extraFileList[a] + } + ) + } + }else { + fileList.value = [] + } + + // fileList.value = (res.data.data.fileList?res.data.data.fileList:[]) + } else { + ElMessage.error(res.data.msg); + } + }); + }; + // 上传成功组装数据 + const successUploader = (list) =>{ + console.log('successUploader',list) + fileList.value = list + var formFileList = '' + for(var a = 0;a<fileList.value.length;a++){ + if(a==fileList.value.length-1){ + formFileList+=fileList.value[a].name + }else { + formFileList+=fileList.value[a].name+',' + } + } + form.value.extraFile = formFileList + } + const deleteFile = (list) =>{ + console.log('deleteFile',list) + fileList.value = list + const formFileList = '' + for(var a = 0;a<fileList.value.length;a++){ + if(a==fileList.value.length-1){ + formFileList.value+=fileList.value[a].name + }else { + formFileList.value+=fileList.value[a].name+',' + } + } + form.value.extraFile = formFileList + } + + const timeC = (timestamp: any) => { + let a = new Date(timestamp).getTime(); + const date = new Date(a); + const Y = date.getFullYear() + '-'; + const M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-'; + const D = (date.getDate() < 10 ? '0' + date.getDate() : date.getDate()) + ' '; + const h = (date.getHours() < 10 ? '0' + date.getHours() : date.getHours()) + ':'; + const m = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes(); + const s = date.getSeconds(); // 秒 + const dateString = Y + M + D + h + m + `:${s}`; + // console.log('dateString', dateString); // > dateString 2021-07-06 14:23 + return dateString; + }; + // 验证 + const rules = reactive<FormRules>({ + title: [{ required: true, message: '考核标题不能为空', trigger: 'blur' }], + examineDate: [{ required: true, message: '考核日期不能为空', trigger: 'blur' }], + examineDepartmentId: [{ required: true, message: '考核部门不能为空', trigger: 'blur' }], + examinePersonName: [], + examinePersonId: [], + beExaminedDepartmentId: [{ required: true, message: '被考核部门不能为空', trigger: 'blur' }], + beExaminedPersonName: [], + beExaminedPersonId: [], + examineTemplateId: [], + examineTemplateName: [{ required: true, message: '考核模板不能为空', trigger: 'blur' }], + memo: [], + }); + // 接收 + const onType = (data: any, val: any) => { + form.value.examineTotalNumber = ''; + form.value.examineTemplateId = data.id; + form.value.examineTemplateName = data.title; + form.value.acceptanceNumber = data.acceptanceNumber; + form.value.numberDetailJson = val.examineItemList; + }; + const numberC = () => { + let arr = 0; + for (let i = 0; i < form.value.numberDetailJson.length; i++) { + if (form.value.numberDetailJson[i].number != undefined) { + arr = parseInt(arr) + parseInt(form.value.numberDetailJson[i].number); + } else { + arr = parseInt(arr) + 0; + } + } + form.value.examineTotalNumber = arr; + }; + // 提交 + const submitForm = async (formEl: FormInstance | undefined) => { + if (!formEl) return; + await formEl.validate((valid, fields) => { + if (valid) { + if(titleT.value=='新建'){ + delete form.value.id + } + dialogVisible.value = false; + let arr = []; + for (let i = 0; i < form.value.numberDetailJson.length; i++) { + arr.push({ + id: form.value.numberDetailJson[i].id, + number: form.value.numberDetailJson[i].number, + }); + } + form.value.numberDetailJson = JSON.stringify(arr); + goalManagementApi() + .getexamineMngAddOrUpdate(form.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + message: res.data.msg, + type: 'success', + }); + emit('navAddorUpdata'); + } else { + ElMessage.error(res.data.msg); + } + }); + } else { + console.log('error submit!', fields); + } + }); + }; + // 取消 + const resetForm = (formEl: FormInstance | undefined) => { + if (!formEl) return; + dialogVisible.value = false; + formEl.resetFields(); + }; + const handleClose = (formEl: FormInstance | undefined) => { + if (!formEl) return; + formEl.resetFields(); + fileList.value=[] + }; + const activeName = ref('1'); + // 新增弹窗 + const Show = ref(); + const daiAdd = () => { + Show.value.openDailog(); + }; + // 安全目标指标弹窗 + const Shows = ref(); + const daiInpt = (type: any) => { + Shows.value.openDailog(type); + }; + // 点击上传 + const fileList = ref<UploadUserFile[]>([]); + + const handleRemove: UploadProps['onRemove'] = (file, uploadFiles) => { + console.log(file, uploadFiles); + }; + + const handlePreview: UploadProps['onPreview'] = (uploadFile) => { + console.log(uploadFile); + }; + + const handleExceed: UploadProps['onExceed'] = (files, uploadFiles) => { + ElMessage.warning(`The limit is 3, you selected ${files.length} files this time, add up to ${files.length + uploadFiles.length} totally`); + }; + + const beforeRemove: UploadProps['beforeRemove'] = (uploadFile, uploadFiles) => { + return ElMessageBox.confirm(`Cancel the transfert of ${uploadFile.name} ?`).then( + () => true, + () => false + ); + }; + const userId = (val: any, type: any) => { + if (type == 1) { + form.value.examinePersonId = val.uid; + form.value.examinePersonName = val.realName; + } else if (type == 0) { + let uid = []; + let realName = []; + for (let i = 0; i < val.length; i++) { + uid.push(val[i].uid); + realName.push(val[i].realName); + } + form.value.beExaminedPersonId = uid.toString(); + form.value.beExaminedPersonName = realName.toString(); + console.log(form.value.beExaminedPersonId, form.value.beExaminedPersonName); + } + }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + //部门 + const department = () => { + goalManagementApi() + .getTreedepartment() + .then((res) => { + if (res.data.code == 200) { + data.value = res.data.data; + } else { + ElMessage.error(res.data.msg); + } + }); + }; + const propse = { + label: 'depName', + children: 'children', + value: 'depId', + }; + const data = ref(); + const nameData1 = (val: any) => { + form.value.examineDepartmentName = val.depName; + }; + const nameData2 = (val: any) => { + form.value.beExaminedDepartmentName = val.depName; + console.log(form.value); + }; + return { + titleT, + rules, + timeC, + numberC, + onType, + handleClose, + nameData1, + nameData2, + ruleFormRef, + department, + propse, + data, + userId, + activeName, + dialogVisible, + form, + titles, + disabled, + openDailog, + submitForm, + resetForm, + Show, + daiAdd, + Shows, + daiInpt, + Search, + fileList, + handleRemove, + handlePreview, + handleExceed, + beforeRemove, + full, + toggleFullscreen, + FullScreen, + successUploader, + deleteFile + }; + }, +}); +</script> +<style scoped> +.el-row { + padding: 0 0 20px 0; +} +</style> \ No newline at end of file diff --git a/src/views/goalManagement/performanceAppraisal/component/DailogKh.vue b/src/views/goalManagement/performanceAppraisal/component/DailogKh.vue new file mode 100644 index 0000000..7d58a68 --- /dev/null +++ b/src/views/goalManagement/performanceAppraisal/component/DailogKh.vue @@ -0,0 +1,247 @@ +<template> + <el-dialog v-model="dialogVisible" :before-close="resetForm" :fullscreen="full" title="新建考核标准设定" width="60%" draggable> + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-form :model="form" label-width="120px"> + <el-row> + <el-col :span="11"> + <el-form-item label="标准标题" size="default"> + <el-input v-model="form.title"> </el-input> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="适用范围" size="default"> + <el-select v-model="form.applyRange" style="width: 100%" placeholder="请选择"> + <el-option label="安全生产责任制考核1" value="1" /> + <el-option label="安全生产责任制考核2" value="2" /> + </el-select> + </el-form-item> + </el-col> + </el-row> + <div v-if="clickType"> + <el-row> + <el-col :span="11"> + <el-form-item label="设定人" size="default"> + <el-input v-model="form.setPersonId" disabled> + <template #append> <el-button :icon="Search" @click="daiInpt" /></template> + </el-input> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="设定人部门" size="default"> + <el-select v-model="form.setPersonDepartmentId" disabled style="width: 100%" placeholder="请选择"> + <el-option label="Zone one" value="shanghai" /> + <el-option label="Zone two" value="beijing" /> + </el-select> + </el-form-item> + </el-col> + </el-row> + </div> + <el-row> + <el-col :span="11"> + <el-form-item label="模板分类编码" size="default"> + <el-input v-model="form.templateCode" /> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="合格分数" size="default"> + <el-input v-model="form.acceptanceNumber" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="11"> + <el-form-item label="备注信息"> + <el-input v-model="form.memo" type="textarea" /> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2" v-if="clickType"> + <el-form-item label="设定日期" size="default"> + <el-date-picker disabled v-model="form.setTimem" format="YYYY-MM-DD HH:mm:ss" type="datetime" placeholder="请选择" style="width: 100%" /> + </el-form-item> + </el-col> + </el-row> + </el-form> + <el-tabs v-model="activeName" class="demo-tabs"> + <el-tab-pane label="考核项目" name="1"> + <el-button type="primary" size="default" @click="daiAdd('新增','')">新增</el-button> + </el-tab-pane> + </el-tabs> + <el-table :data="form.examineItemList" style="width: 100%"> + <el-table-column align="center" prop="itemType" label="类型" width="180" /> + <el-table-column align="center" prop="itemDetail" label="考核项目" width="180" /> + <el-table-column align="center" prop="content" label="考核内容" /> + <el-table-column align="center" prop="judgeStandard" label="评定标准" /> + <el-table-column align="center" prop="memo" label="考核说明" /> + <el-table-column align="center" label="操作"> + <template #default="scope"> + <el-button link type="primary" @click="daiAdd('查看', scope.row)">查看</el-button> + <el-button link type="primary" @click="daiAdd('修改', scope.row)">修改</el-button> + <el-button link type="primary" @click="deleteA(scope.row)">删除</el-button> + </template> + </el-table-column> + </el-table> + <template #footer> + <span class="dialog-footer"> + <el-button @click="resetForm" size="default">关闭</el-button> + <el-button type="primary" @click="submitForm" size="default">确定</el-button> + </span> + </template> + </el-dialog> + <DailogKhS ref="Show" @onAdd="AddObj"></DailogKhS> +</template> +<script lang="ts"> +import { defineComponent, ref, reactive } from 'vue'; +import { Search, FullScreen } from '@element-plus/icons-vue'; +import DailogKhS from './DailogKhS.vue'; +import { ElMessage, ElMessageBox } from 'element-plus'; +import { goalManagementApi } from '/@/api/goalManagement'; +export default defineComponent({ + components: { DailogKhS }, + setup(props, { emit }) { + const dialogVisible = ref<boolean>(false); + const form = ref({ + examineItemList: [], //考核项目列表 + setTimem: 1658386392466, + memo: '', ////备注信息 + templateCode: '', ////模板分类编码 + title: '', ////标准标题 + setPersonId: 1, //设定人 + acceptanceNumber: '', ////合格分数 + setPersonDepartmentId: 2, //设定人部门 + applyRange: '', ////适用范围 + }); + const titles = ref(); + const titleT = ref(); + const disabled = ref(false); + const clickType = ref(false); + // 打开弹窗 + const openDailog = (title: string, value: any, id: number) => { + dialogVisible.value = true; + titles.value = `${title}安全考核管理`; + titleT.value=title + disabled.value = title == '查看' ? true : false; + if (title == '查看' || title == '修改') { + goalManagementApi() + .getexamineTemplateDetail(id) + .then((res) => { + if (res.data.code == 200) { + form.value = res.data.data; + } else { + ElMessage.error(res.data.msg); + } + }); + } else { + clickType.value = false; + } + }; + // 接受传值 + const AddObj = (val: any) => { + if (index.value == -1) { + form.value.examineItemList.push(val); + } else { + form.value.examineItemList[index.value] = val; + } + }; + // 删除 + const deleteA = (tag: any) => { + form.value.examineItemList.splice(form.value.examineItemList.indexOf(tag), 1); + }; + // 提交 + const submitForm = () => { + if(titleT.value=='新建'){ + delete form.value.id + } + dialogVisible.value = false; + goalManagementApi() + .getexamineTemplateAddOrUpdate(form.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + message: res.data.msg, + type: 'success', + }); + emit('navAddorUpdata'); + } else { + ElMessage.error(res.data.msg); + } + }); + form.value = { + examineItemList: [], //考核项目列表 + setTimem: 1658386392466, + memo: '', ////备注信息 + templateCode: '', ////模板分类编码 + title: '', ////标准标题 + setPersonId: 1, //设定人 + acceptanceNumber: '', ////合格分数 + setPersonDepartmentId: 2, //设定人部门 + applyRange: '', ////适用范围 + }; + }; + // 取消 + const resetForm = () => { + dialogVisible.value = false; + form.value = { + examineItemList: [], //考核项目列表 + setTimem: 1658386392466, + memo: '', ////备注信息 + templateCode: '', ////模板分类编码 + title: '', ////标准标题 + setPersonId: 1, //设定人 + acceptanceNumber: '', ////合格分数 + setPersonDepartmentId: 2, //设定人部门 + applyRange: '', ////适用范围 + }; + }; + const activeName = ref('1'); + // 新增弹窗 + const index = ref<any>(); + const Show = ref(); + const daiAdd = (title: string, data: any) => { + index.value = form.value.examineItemList.indexOf(data); + Show.value.openDailog(title, data); + }; + // 安全目标指标弹窗 + const Shows = ref(); + const daiInpt = () => { + Shows.value.openDailog(); + }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + return { + titleT, + index, + form, + dialogVisible, + deleteA, + AddObj, + openDailog, + activeName, + titles, + disabled, + submitForm, + resetForm, + Show, + daiAdd, + Shows, + daiInpt, + Search, + full, + clickType, + toggleFullscreen, + FullScreen, + }; + }, +}); +</script> +<style scoped> +.el-row { + padding: 0 0 20px 0; +} +</style> \ No newline at end of file diff --git a/src/views/goalManagement/performanceAppraisal/component/DailogKhS.vue b/src/views/goalManagement/performanceAppraisal/component/DailogKhS.vue new file mode 100644 index 0000000..f186ab3 --- /dev/null +++ b/src/views/goalManagement/performanceAppraisal/component/DailogKhS.vue @@ -0,0 +1,133 @@ +<template> + <el-dialog v-model="dialogVisible" :before-close="resetForm" :fullscreen="full" :title="titles" width="50%" draggable> + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-form :model="form" :disabled="disabled" label-width="120px"> + <el-row> + <el-col :span="24"> + <el-form-item label="类型"> + <el-input v-model="form.itemType" type="textarea"></el-input> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="24"> + <el-form-item label="考核项目"> + <el-input v-model="form.itemDetail" type="textarea"> </el-input> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="24"> + <el-form-item label="考核内容"> + <el-input v-model="form.content" type="textarea"> </el-input> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="24"> + <el-form-item label="评定标准"> + <el-input v-model="form.judgeStandard" type="textarea"> </el-input> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="24"> + <el-form-item label="考核说明"> + <el-input v-model="form.memo" type="textarea"> </el-input> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> +<!-- <el-button type="primary" @click="dialogVisible = false" size="default">继续添加</el-button>--> + <el-button @click="resetForm" size="default">关闭</el-button> + <el-button type="primary" @click="submitForm" size="default">确定</el-button> + </span> + </template> + </el-dialog> + <!-- <DailogAdd ref="Show"></DailogAdd> + <DailogSearch ref="Shows"></DailogSearch> --> +</template> +<script lang="ts"> +import { defineComponent, ref, reactive } from 'vue'; +import { Search, FullScreen } from '@element-plus/icons-vue'; +// import DailogAdd from './DailogAdd.vue' +// import DailogSearch from '../../../../components/DailogSearch/DailogSearch.vue' +export default defineComponent({ + // components:{DailogAdd,DailogSearch}, + setup(props, { emit }) { + const dialogVisible = ref<boolean>(false); + const form = ref({ + itemType: '', ////类型 + memo: '', //备注 + itemDetail: '', ////考核项目 + content: '', ////考核内容 + judgeStandard: '', ////评定标准 + }); + const disabled=ref(false) + const titles=ref() + const openDailog = (title: string, value: any) => { + dialogVisible.value = true; + titles.value=`${title}考核项目` + if (title == '查看') { + form.value = value; + disabled.value=true + }else if(title == '修改'){ + disabled.value=false + form.value = value; + } + }; + // 提交 + const submitForm = () => { + dialogVisible.value = false; + emit('onAdd', form.value); + form.value = { + itemType: '', ////类型 + memo: '', //备注 + itemDetail: '', ////考核项目 + content: '', ////考核内容 + judgeStandard: '', ////评定标准 + }; + }; + // 取消 + const resetForm = () => { + dialogVisible.value = false; + form.value = { + itemType: '', ////类型 + memo: '', //备注 + itemDetail: '', ////考核项目 + content: '', ////考核内容 + judgeStandard: '', ////评定标准 + }; + }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + return { + form, + disabled, + titles, + dialogVisible, + openDailog, + submitForm, + resetForm, + Search, + full, + toggleFullscreen, + FullScreen, + }; + }, +}); +</script> +<style scoped> +.el-row { + padding: 0 0 20px 0; +} +</style> \ No newline at end of file diff --git a/src/views/goalManagement/performanceAppraisal/component/DailogSearch.vue b/src/views/goalManagement/performanceAppraisal/component/DailogSearch.vue new file mode 100644 index 0000000..d50ea80 --- /dev/null +++ b/src/views/goalManagement/performanceAppraisal/component/DailogSearch.vue @@ -0,0 +1,196 @@ +<template> + <el-dialog v-model="dialogVisible" :fullscreen="full" title="选择安全目标指标" width="50%" draggable> + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-row> + <el-col :span="17"> + <el-form ref="ruleFormRef" :model="ruleForm" status-icon> + <el-row> + <el-col :span="12"> + <el-form-item size="default"> + <el-input v-model="ruleForm.searchParams.title" placeholder="标准标题" /> + </el-form-item> + </el-col> + <!-- <el-col :span="6" :offset="1"> + <el-form-item> + <el-input v-model="ruleForm.checkPass" placeholder="目标指标编号" /> + </el-form-item> + </el-col> --> + <el-col :span="11" :offset="1"> + <el-form-item> + <el-button size="default" type="primary" @click="listApi()">查询</el-button> + <el-button size="default" @click="reset">重置</el-button> + </el-form-item> + </el-col> + </el-row> + </el-form> + <el-button size="default" :icon="Delete" @click="clear">清除选择</el-button> + <el-table :data="tableData" style="width: 100%; margin-top: 20px" > + <el-table-column align="center" width="70px"> + <template #default="scope"> + <el-radio-group v-model="radio1"> + <el-radio :label="scope.row.id" @click="radio(scope.row)" size="large">{{ null }}</el-radio> + </el-radio-group> + </template> + </el-table-column> + <el-table-column align="center" prop="title" label="标准标题" /> + </el-table> + <el-pagination + style="padding: 20px 0; border-bottom: 1px solid #dedede" + v-model:currentPage="currentPage4" + v-model:page-size="pageSize4" + :page-sizes="[10, 20, 30, 40]" + layout="total, sizes, prev, pager, next, jumper" + :total="total" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </el-col> + <el-col :span="7"> + <div v-if="dynamicTags[0]==''?false:true"> + <el-tag + v-for="tag in dynamicTags" + :key="tag" + class="mx-1" + style="margin: 5px" + closable + :disable-transitions="false" + @close="handleClose(tag)" + > + {{ tag.title }} + </el-tag> + </div> + </el-col> + </el-row> + <template #footer> + <span class="dialog-footer"> + <el-button @click="dialogVisible = false" size="default">关闭</el-button> + <el-button type="primary" @click="submitForm" size="default">确定</el-button> + </span> + </template> + </el-dialog> +</template> +<script lang="ts"> +import { defineComponent, reactive, ref } from 'vue'; +import { Delete, FullScreen } from '@element-plus/icons-vue'; +import { ElMessageBox, ElMessage, ElButton, ElInput, TabsPaneContext, FormInstance } from 'element-plus'; +import { goalManagementApi } from '/@/api/goalManagement'; +export default defineComponent({ + setup(props,{emit}) { + const dialogVisible = ref<boolean>(false); + const openDailog = () => { + dialogVisible.value = true; + listApi() + }; + // 搜索条件 + const ruleForm = reactive({ + pageSize: 10, + pageIndex: 1, + searchParams: { + title: '', //标准标题 + }, + }); + const listApi = () => { + goalManagementApi() + .getexamineTemplateList(ruleForm) + .then((res) => { + if (res.data.code == 200) { + tableData.value = res.data.data; + currentPage4.value = res.data.pageIndex; + pageSize4.value = res.data.pageSize; + total.value = res.data.total; + } else { + ElMessage.error(res.data.msg); + } + }); + }; + // 重置 + const reset=()=>{ + ruleForm.searchParams.title="" + listApi() + } + const tableData = ref(); + const currentPage4 = ref(); + const pageSize4 = ref(); + const total = ref(); + const handleSizeChange = (val: number) => { + // console.log(`${val} items per page`); + ruleForm.pageSize = val; + listApi(); + }; + const handleCurrentChange = (val: number) => { + // console.log(`current page: ${val}`); + ruleForm.pageIndex = val; + listApi(); + }; + // 提交 + const submitForm=()=>{ + dialogVisible.value = false + emit("typeDome",dynamicTags.value[0],list.value) + clear() + } + // 右方点击添加后显示标签 + const dynamicTags = ref(['']); + const handleClose = (tag: string) => { + dynamicTags.value.splice(dynamicTags.value.indexOf(tag), 1); + radio1.value = ''; + }; + const radio1 = ref(''); + const list=ref([]) + const radio = (event: any) => { + + goalManagementApi() + .getexamineTemplateDetail(event.id) + .then((res) => { + if (res.data.code == 200) { + list.value = res.data.data; + } else { + ElMessage.error(res.data.msg); + } + }); + dynamicTags.value[0] = event; + }; + const clear=()=>{ + dynamicTags.value=[''] + radio1.value="" + } + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + return { + submitForm, + list, + reset, + dialogVisible, + listApi, + openDailog, + ruleForm, + tableData, + currentPage4, + pageSize4, + total, + handleSizeChange, + handleCurrentChange, + dynamicTags, + handleClose, + Delete, + full, + toggleFullscreen, + radio1, + radio, + clear, + FullScreen, + }; + }, +}); +</script> +<style scoped> +.el-row { + padding: 0 0 20px 0; +} +</style> diff --git a/src/views/goalManagement/performanceAppraisal/index.vue b/src/views/goalManagement/performanceAppraisal/index.vue new file mode 100644 index 0000000..53838f6 --- /dev/null +++ b/src/views/goalManagement/performanceAppraisal/index.vue @@ -0,0 +1,526 @@ +<template> + <div> + <div class="minCenter"> + <el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick"> + <el-tab-pane label="安全考核管理" name="1"> + <el-form :model="ruleForm" status-icon label-width="20px" class="topTitle"> + <el-row> + <el-col :span="4"> + <el-form-item size="default"> + <el-tree-select v-model="ruleForm.searchParams.examineDepartmentId" :data="data" check-strictly="true" class="w100" :props="propse" placeholder="请选择" /> + </el-form-item> + </el-col> + <el-col :span="4"> + <el-form-item> + <el-button size="default" type="primary" @click="listApi">查询</el-button> + <el-button size="default" @click="resetForm">重置</el-button> + </el-form-item> + </el-col> + </el-row> + </el-form> + <div class="btns"> + <div> + <el-button size="default" type="primary" :icon="Plus" @click="openD('新建')">新建</el-button> + <el-button size="default" :disabled="warning" type="warning" plain :icon="EditPen" + @click="openD('修改', deletAll[0])">修改</el-button> + <el-button size="default" :disabled="danger" type="danger" plain :icon="Delete" @click="onDeleteAll">删除</el-button> + </div> + </div> + <el-table ref="multipleTableRef" :data="tableData" style="width: 100%" @selection-change="handleSelectionChange"> + <el-table-column type="selection" align="center" width="55" /> + <el-table-column type="expand"> + <template #default="scope"> + <div class="tableC"> + <el-table :data="scope.row.currentExamineDtoList" style="width: 100%"> + <el-table-column align="center" prop="itemDetail" label="考核项目" /> + <el-table-column align="center" prop="content" label="考核内容" /> + <el-table-column align="center" prop="number" label="考核分数" /> + </el-table> + </div> + </template> + </el-table-column> + <el-table-column property="examineDate" align="center" :formatter="timeDate" label="考核日期" sortable /> + <el-table-column property="examineDepartmentName" align="center" label="考核部门" sortable /> + <el-table-column property="examinePersonName" label="考核人" align="center" sortable show-overflow-tooltip /> + <el-table-column property="beExaminedDepartmentName" label="被考核部门" align="center" sortable show-overflow-tooltip /> + <el-table-column property="examineTotalNumber" label="总分" align="center" sortable show-overflow-tooltip /> + <el-table-column property="numberDetailJson.number" label="考核结果" align="center" sortable show-overflow-tooltip /> + <el-table-column property="extraFile" label="附件" align="center" sortable show-overflow-tooltip /> + <el-table-column label="操作" align="center" width="250px"> + <template #default="scope"> + <el-button link type="primary" size="default" :icon="View" @click="openD('查看', scope.row.id)">查看</el-button> + <el-button link type="primary" size="default" :icon="EditPen" @click="openD('修改', scope.row.id)">修改</el-button> + <el-button link type="primary" size="default" :icon="Delete" @click="onDelete(scope.row.id)">删除</el-button> + </template> + </el-table-column> + </el-table> + <div class="pages"> + <el-pagination + v-model:currentPage="currentPage4" + v-model:page-size="pageSize4" + :page-sizes="[10, 20, 30, 40]" + layout="total, sizes, prev, pager, next, jumper" + :total="total" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + </el-tab-pane> + <el-tab-pane label="考核标准设定" name="2"> + <el-form :model="ruleForms" status-icon label-width="20px" class="topTitle"> + <el-row> + <el-col :span="4"> + <el-form-item size="default"> + <el-input v-model="ruleForms.searchParams.title" placeholder="标准标题" /> + </el-form-item> + </el-col> + <el-col :span="4"> + <el-form-item> + <el-button size="default" type="primary" @click="listApis">查询</el-button> + <el-button size="default" @click="resetForms">重置</el-button> + </el-form-item> + </el-col> + </el-row> + </el-form> + <div class="btns"> + <div> + <el-button size="default" type="primary" :icon="Plus" @click="openDs('新建')">新建</el-button> + <!-- <el-button size="default" :disabled="warnings" type="warning" plain :icon="EditPen">修改</el-button> --> + <el-button size="default" :disabled="dangers" type="danger" plain :icon="Delete" @click="onDeleteAlls">删除</el-button> + </div> + </div> + <el-table ref="multipleTableRef" :data="tableDatas" style="width: 100%" @selection-change="handleSelectionChanges"> + <el-table-column type="selection" align="center" width="55" /> + <el-table-column type="expand"> + <template #default="scope"> + <div class="tableC"> + <el-table :data="scope.row.examineItemList" style="width: 100%"> + <el-table-column align="center" prop="itemType" label="类型" /> + <el-table-column align="center" prop="itemDetail" label="考核项目" /> + <el-table-column align="center" prop="content" label="考核内容" /> + <el-table-column align="center" prop="judgeStandard" label="评定标准" /> + <el-table-column align="center" prop="memo" label="考核说明" /> + </el-table> + </div> + </template> + </el-table-column> + <el-table-column label="标准标题" property="title" align="center" sortable /> + <el-table-column property="applyRange" align="center" label="适用范围" sortable /> + <el-table-column property="setPersonName" label="设定人" align="center" sortable show-overflow-tooltip /> + <el-table-column property="setPersonDepartmentName" label="设定人部门" align="center" sortable show-overflow-tooltip /> + <el-table-column property="setTimem" label="设定日期" align="center" :formatter="timeDate" sortable show-overflow-tooltip /> + <el-table-column property="templateCode" label="模板分类编码" align="center" sortable show-overflow-tooltip /> + <el-table-column property="acceptanceNumber" label="合格分数" align="center" sortable show-overflow-tooltip /> + <el-table-column label="操作" align="center" width="250px"> + <template #default="scope"> + <el-button link type="primary" size="default" :icon="View" @click="openDs('查看', scope.row.id)">查看</el-button> + <el-button link type="primary" size="default" :icon="EditPen" @click="openDs('修改', scope.row.id)">修改</el-button> + <el-button link type="primary" size="default" :icon="Delete" @click="onDeletes(scope.row.id)">删除</el-button> + </template> + </el-table-column> + </el-table> + <div class="pages"> + <el-pagination + v-model:currentPage="currentPage4s" + v-model:page-size="pageSize4s" + :page-sizes="[10, 20, 30, 40]" + layout="total, sizes, prev, pager, next, jumper" + :total="totals" + @size-change="handleSizeChanges" + @current-change="handleCurrentChanges" + /> + </div> + </el-tab-pane> + </el-tabs> + </div> + <DailogAq ref="openAdd" @navAddorUpdata="onAddorUpdata"></DailogAq> + <DailogKh ref="openAdds" @navAddorUpdata="onAddorUpdatas"></DailogKh> + </div> +</template> +<script lang="ts"> +import {timeDate} from '/@/assets/index.ts' +import DailogAq from './component/DailogAq.vue'; +import DailogKh from './component/DailogKh.vue'; +import { ref, toRefs, reactive, onMounted, defineComponent } from 'vue'; +import { ElMessageBox, ElMessage, ElButton, ElInput, FormInstance } from 'element-plus'; +import { Plus, Delete, Upload, Download, Refresh, View, EditPen } from '@element-plus/icons-vue'; +import type { TabsPaneContext } from 'element-plus' +import { goalManagementApi } from '/@/api/goalManagement'; +export default defineComponent({ + components: { ElButton, ElInput, DailogAq, DailogKh }, + setup() { + // 搜索条件 安全考核管理 + const ruleForm = reactive({ + pageSize: 10, + pageIndex: 1, + searchParams: { + examineDepartmentId: '', + }, + }); + // 重置 + const resetForm = () => { + ruleForm.searchParams.examineDepartmentId = ''; + listApi() + }; + const listApi = () => { + goalManagementApi() + .getexamineMngList(ruleForm) + .then((res) => { + if (res.data.code == 200) { + tableData.value = res.data.data; + currentPage4.value = res.data.pageIndex; + pageSize4.value = res.data.pageSize; + total.value = res.data.total; + } else { + ElMessage.error(res.data.msg); + } + }); + }; + + onMounted(() => { + listApi(); + }); + const onAddorUpdata = () => { + listApi(); + }; + // 表格 + const tableData = ref(); + const currentPage4 = ref(); + const pageSize4 = ref(); + const total = ref(); + const handleSizeChange = (val: number) => { + // console.log(`${val} items per page`); + ruleForm.pageSize = val; + listApi(); + }; + const handleCurrentChange = (val: number) => { + // console.log(`current page: ${val}`); + ruleForm.pageIndex = val; + listApi(); + }; + // 弹窗 + const openAdd = ref(); + const openD= (title: String, id: number) => { + openAdd.value.openDailog(title, ruleForm.searchParams.examineDepartmentId, id); + }; + // 删除 + const onDelete = (id: number) => { + let arr=[] + arr.push(id) + ElMessageBox.confirm('确定删除所选项吗?', 'Warning', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + goalManagementApi() + .getexamineMngDelete(arr) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + message: res.data.msg, + type: 'success', + }); + listApi(); + } else { + ElMessage.error(res.data.msg); + } + }); + }) + .catch(() => { + ElMessage({ + type: 'info', + message: 'Delete canceled', + }); + }); + }; + // 批量删除 + const warning = ref(true); + const danger = ref(true); + const deletAll = ref(); + const handleSelectionChange = (val: any) => { + let valId = JSON.parse(JSON.stringify(val)); + let arr = []; + for (let i = 0; i < valId.length; i++) { + arr.push(valId[i].id); + } + deletAll.value = arr + if (val.length == 1) { + warning.value = false; + danger.value = false; + } else if (val.length == 0) { + warning.value = true; + danger.value = true; + } else { + warning.value = true; + danger.value = false; + } + }; + const onDeleteAll = () => { + ElMessageBox.confirm('确定删除所选项吗?', 'Warning', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + goalManagementApi() + .getexamineMngDelete(deletAll.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + message: res.data.msg, + type: 'success', + }); + listApi(); + } else { + ElMessage.error(res.data.msg); + } + }); + }) + .catch(() => { + // ElMessage({ + // type: 'info', + // message: 'Delete canceled', + // }); + }); + }; + // 切换 + const activeName = ref('1'); + const handleClick = (val: TabsPaneContext) => { + console.log(val) + if (val.props.name == '1') { + listApi(); + }else{ + listApis(); + } + }; + // 搜索条件 考核标准设定 + const ruleForms = reactive({ + pageSize: 10, + pageIndex: 1, + searchParams: { + title: '', //标准标题 + }, + }); + // 重置 + const resetForms = () => { + ruleForms.searchParams.title = ''; + listApis() + }; + const listApis = () => { + goalManagementApi() + .getexamineTemplateList(ruleForms) + .then((res) => { + if (res.data.code == 200) { + tableDatas.value = res.data.data; + currentPage4s.value = res.data.pageIndex; + pageSize4s.value = res.data.pageSize; + totals.value = res.data.total; + } else { + ElMessage.error(res.data.msg); + } + }); + }; + onMounted(() => { + listApis(); + department() + }); + const onAddorUpdatas = () => { + listApis(); + }; + // 表格 + const tableDatas = ref(); + const currentPage4s = ref(); + const pageSize4s = ref(); + const totals = ref(); + const handleSizeChanges = (val: number) => { + // console.log(`${val} items per page`); + ruleForms.pageSize = val; + listApis(); + }; + const handleCurrentChanges = (val: number) => { + // console.log(`current page: ${val}`); + ruleForms.pageIndex = val; + listApis(); + }; + // 弹窗 + const openAdds = ref(); + const openDs = (title: String, id: number) => { + openAdds.value.openDailog(title, ruleForm.searchParams.examineDepartmentId, id); + }; + // 删除 + const onDeletes = (id: number) => { + let arr=[] + arr.push(id) + ElMessageBox.confirm('确定删除所选项吗?', 'Warning', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + goalManagementApi() + .getexamineTemplateDelete(arr) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + message: res.data.msg, + type: 'success', + }); + listApis(); + } else { + ElMessage.error(res.data.msg); + } + }); + }) + .catch(() => { + ElMessage({ + type: 'info', + message: 'Delete canceled', + }); + }); + }; + // 批量删除 + const warnings = ref(true); + const dangers = ref(true); + const deletAlls = ref(); + const handleSelectionChanges = (val: any) => { + let valId = JSON.parse(JSON.stringify(val)); + let arr = []; + for (let i = 0; i < valId.length; i++) { + arr.push(valId[i].id); + } + deletAlls.value = arr; + if (val.length == 1) { + warnings.value = false; + dangers.value = false; + } else if (val.length == 0) { + warnings.value = true; + dangers.value = true; + } else { + warnings.value = true; + dangers.value = false; + } + }; + const onDeleteAlls = () => { + ElMessageBox.confirm('确定删除所选项吗?', 'Warning', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + goalManagementApi() + .getexamineTemplateDelete(deletAll.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + message: res.data.msg, + type: 'success', + }); + listApis(); + } else { + ElMessage.error(res.data.msg); + } + }); + }) + .catch(() => { + // ElMessage({ + // type: 'info', + // message: 'Delete canceled', + // }); + }); + }; + //部门树 + const department = () => { + goalManagementApi() + .getTreedepartment() + .then((res) => { + if (res.data.code == 200) { + data.value = res.data.data; + } else { + ElMessage.error(res.data.msg); + } + }); + }; + const propse = { + label: 'depName', + children: 'children', + value: 'depId', + }; + const data = ref(); + return { + timeDate, + department, + propse, + data, + activeName, + ruleForm, + resetForm, + listApi, + handleClick, + onAddorUpdata, + tableData, + currentPage4, + pageSize4, + total, + handleSizeChange, + handleCurrentChange, + openAdd, + openD, + onDelete, + warning, + danger, + deletAll, + handleSelectionChange, + onDeleteAll, + ruleForms, + resetForms, + listApis, + onAddorUpdatas, + tableDatas, + currentPage4s, + pageSize4s, + totals, + handleSizeChanges, + handleCurrentChanges, + openAdds, + openDs, + onDeletes, + warnings, + dangers, + deletAlls, + handleSelectionChanges, + onDeleteAlls, + Plus, + Delete, + Upload, + Download, + Refresh, + View, + EditPen, + }; + }, +}); +</script> +<style scoped> +.minCenter { + width: 100%; + background-color: #fff; + margin-top: 10px; + padding: 0 20px; +} +.btns { + padding: 20px; +} +.topTitle { + padding: 5px 0 20px 0; + border-bottom: 1px solid #dedede; +} +.pages { + padding: 20px 0; + display: flex; + justify-content: right; +} +.tableC { + margin: 0 10%; +} +</style> diff --git a/src/views/goalManagement/processForms/component/formInformationTop.vue b/src/views/goalManagement/processForms/component/formInformationTop.vue new file mode 100644 index 0000000..5f34405 --- /dev/null +++ b/src/views/goalManagement/processForms/component/formInformationTop.vue @@ -0,0 +1,144 @@ +<template> + <el-form ref="form" :model="form" label-width="120px"> + <el-row> + <el-col :span="11"> + <el-form-item label="安全目标指标" size="default"> + <el-input v-model="form.name"></el-input> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="目标指标编号" size="default"> + <el-input v-model="form.name"></el-input> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="11"> + <el-form-item label="年度" size="default"> + <el-input v-model="form.name"></el-input> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="指标值" size="default"> + <el-input v-model="form.name"></el-input> + </el-form-item> + </el-col> + </el-row> + </el-form> + <el-tabs v-model="activeName" style="padding: 0 20px"> + <el-tab-pane label="考核指标" name="1"> + <el-table :data="tableData" style="width: 100%"> + <el-table-column align="center" type="index" label="序号" width="70" /> + <el-table-column align="center" prop="date" label="责任部门" /> + <el-table-column align="center" prop="name" label="考核指标" /> + <el-table-column align="center" prop="address" label="制定部门" /> + <el-table-column align="center" prop="address" label="制定日期" /> + <el-table-column align="center" label="检查值"> + <template #default> + <el-input v-model="form.name" placeholder=""></el-input> + </template> + </el-table-column> + <el-table-column align="center" prop="address" label="检查人" /> + <el-table-column align="center" prop="address" label="检查时间" /> + </el-table> + <div class="tiao"> + <div class="typeS">审批</div> + </div> + <el-row style="padding:20px 0"> + <el-col :span="6" style="text-align:right">一级审批:</el-col> + <el-col :span="18">同意</el-col> + </el-row> + <el-row style="padding:0 0 20px 0"> + <el-col :span="6"></el-col> + <el-col :span="18"><span class="logoColor">同意</span><span style="margin-right: 8px;">杜建喜</span><span>2021-05-24 04:47:42</span></el-col> + </el-row> + </el-tab-pane> + </el-tabs> +</template> +<script lang="ts"> +import { defineComponent,ref,reactive } from 'vue' + +export default defineComponent({ + setup() { + const form = reactive({ + name: '', + region: '', + date1: '', + date2: '', + delivery: false, + type: [], + resource: '', + desc: '', + }); + const tableData = [ + { + date: '2016-05-03', + name: 'Tom', + address: 'No. 189, Grove St, Los Angeles', + }, + ]; + const activeName = ref('1'); + return{ + form, + tableData, + activeName + } + }, +}) +</script> +<style scoped> +.title { + text-align: center; + font-size: 16px; + margin-bottom: 20px; +} +.box{ + border: 1px solid #dcdfe6; + box-shadow: 0 2px 4px 0 rgb(0 0 0 / 12%), 0 0 6px 0 rgb(0 0 0 / 4%); +} +.navType { + background-color: #fff; +} +.tiao{ + width: 100%; + height: 1px; + background-color: #dcdfe6; + margin: 30px 0 ; + position: relative; +} +.typeS{ + width: 80px; + background-color: #fff; + position: absolute; + left: 30px; + top: -9px; + font-size: 14px; + text-align: center; +} +.logoColor{ + background-color: #67c23a; + color: #fff; + padding: 5px 8px; + border-radius: 5px; + margin-right: 5px; +} +.btns{ + width: 100%; + padding:20px 0; + background-color: #fff; + position: fixed; + bottom: 0px; + left: 0px; + text-align: center; + box-shadow: 0 -3px 5px 0 rgb(0 0 0 / 12%); + +} +.title2{ + padding: 20px 0 20px 10px; + width: 100%; + border: 1px solid #dcdfe6; +} +.el-row{ + padding:0 0 20px 0 ; +} +</style> diff --git a/src/views/goalManagement/processForms/component/formInformationTops.vue b/src/views/goalManagement/processForms/component/formInformationTops.vue new file mode 100644 index 0000000..ba671e5 --- /dev/null +++ b/src/views/goalManagement/processForms/component/formInformationTops.vue @@ -0,0 +1,162 @@ +<template> + <el-form ref="form" :model="form" label-width="120px"> + <el-row> + <el-col :span="11"> + <el-form-item label="安全目标指标" size="default"> + <el-input v-model="form.name"></el-input> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="目标指标编号" size="default"> + <el-input v-model="form.name"></el-input> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="11"> + <el-form-item label="年度" size="default"> + <el-input v-model="form.name"></el-input> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="责任部门" size="default"> + <el-input v-model="form.name"></el-input> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="11"> + <el-form-item label="改进期限" size="default"> + <el-date-picker v-model="form.date1" type="date" placeholder="Pick a date" style="width: 100%" /> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="发起人" size="default"> + <el-input v-model="form.name"></el-input> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="11"> + <el-form-item label="发起时间" size="default"> + <el-date-picker v-model="form.date1" type="date" placeholder="Pick a date" style="width: 100%" /> + </el-form-item> + </el-col> + </el-row> + </el-form> + <el-tabs v-model="activeName" style="padding: 0 20px"> + <el-tab-pane label="考核指标" name="1"> + <el-table :data="tableData" style="width: 100%"> + <el-table-column align="center" type="index" label="序号" width="70" /> + <el-table-column align="center" prop="date" label="责任部门" /> + <el-table-column align="center" prop="name" label="考核指标" /> + <el-table-column align="center" prop="address" label="制定部门" /> + <el-table-column align="center" prop="address" label="制定日期" /> + <el-table-column align="center" label="检查值"> + <template #default> + <el-input v-model="form.name" placeholder=""></el-input> + </template> + </el-table-column> + <el-table-column align="center" prop="address" label="检查人" /> + <el-table-column align="center" prop="address" label="检查时间" /> + </el-table> + <div class="tiao"> + <div class="typeS">审批</div> + </div> + <el-row style="padding: 20px 0"> + <el-col :span="6" style="text-align: right">一级审批:</el-col> + <el-col :span="18">同意</el-col> + </el-row> + <el-row style="padding: 0 0 20px 0"> + <el-col :span="6"></el-col> + <el-col :span="18"><span class="logoColor">同意</span><span style="margin-right: 8px">杜建喜</span><span>2021-05-24 04:47:42</span></el-col> + </el-row> + </el-tab-pane> + </el-tabs> +</template> +<script lang="ts"> +import { defineComponent, ref, reactive } from 'vue'; + +export default defineComponent({ + setup() { + const form = reactive({ + name: '', + region: '', + date1: '', + date2: '', + delivery: false, + type: [], + resource: '', + desc: '', + }); + const tableData = [ + { + date: '2016-05-03', + name: 'Tom', + address: 'No. 189, Grove St, Los Angeles', + }, + ]; + const activeName = ref('1'); + return { + form, + tableData, + activeName, + }; + }, +}); +</script> +<style scoped> +.title { + text-align: center; + font-size: 16px; + margin-bottom: 20px; +} +.box { + border: 1px solid #dcdfe6; + box-shadow: 0 2px 4px 0 rgb(0 0 0 / 12%), 0 0 6px 0 rgb(0 0 0 / 4%); +} +.navType { + background-color: #fff; +} +.tiao { + width: 100%; + height: 1px; + background-color: #dcdfe6; + margin: 30px 0; + position: relative; +} +.typeS { + width: 80px; + background-color: #fff; + position: absolute; + left: 30px; + top: -9px; + font-size: 14px; + text-align: center; +} +.logoColor { + background-color: #67c23a; + color: #fff; + padding: 5px 8px; + border-radius: 5px; + margin-right: 5px; +} +.btns { + width: 100%; + padding: 20px 0; + background-color: #fff; + position: fixed; + bottom: 0px; + left: 0px; + text-align: center; + box-shadow: 0 -3px 5px 0 rgb(0 0 0 / 12%); +} +.title2 { + padding: 20px 0 20px 10px; + width: 100%; + border: 1px solid #dcdfe6; +} +.el-row{ + padding:20px 0 0px 0; +} +</style> diff --git a/src/views/goalManagement/processForms/component/lowerPlate.vue b/src/views/goalManagement/processForms/component/lowerPlate.vue new file mode 100644 index 0000000..3eea9f5 --- /dev/null +++ b/src/views/goalManagement/processForms/component/lowerPlate.vue @@ -0,0 +1,120 @@ +<template> + <div class="box"> + <el-form ref="formS" :model="form" :rules="rules" label-width="120px"> + <el-row> + <el-col :span="15"> + <el-form-item label="流程标题" size="default"> + <el-input v-model="form.names" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="15"> + <el-form-item label="下级审批日期" size="default"> + <el-date-picker v-model="form.date1" type="date" placeholder="Pick a date" style="width: 100%" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="15"> + <el-form-item label=""> + <el-checkbox v-model="form.delivery" label="是否抄送" @change="typeChang"/> + </el-form-item> + </el-col> + </el-row> + <el-row v-if="form.delivery"> + <el-col :span="15"> + <el-form-item label="抄送给" prop="resource" size="default"> + <el-input v-model="form.resource" placeholder=""> + <template #append> <el-button :icon="Search" @click="openDai" /> </template + ></el-input> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="15"> + <el-form-item label=""> + <el-checkbox v-model="form.type" label="指定下一步处理者(不设置就使用默认处理人)"/> + </el-form-item> + </el-col> + </el-row> + <el-row v-if="form.type"> + <el-col :span="15"> + <el-form-item label="指定" prop="desc" size="default"> + <el-input v-model="form.desc" placeholder=""> + <template #append> <el-button :icon="Search" @click="openDai" /> </template + ></el-input> + </el-form-item> + </el-col> + </el-row> + </el-form> + </div> + <DailogSearchUser ref="ShowUser"></DailogSearchUser> +</template> +<script lang="ts"> +import { defineComponent, ref, reactive } from 'vue'; +import DailogSearchUser from '/@/components/DailogSearchUser/index.vue' +import { Search } from '@element-plus/icons-vue'; +import type { FormInstance, FormRules } from 'element-plus' +export default defineComponent({ + components:{DailogSearchUser}, + setup() { + const formS=ref<FormInstance>() + let form = reactive({ + names: '', + region: '', + date1: '', + date2: '', + delivery: "", + type: "", + resource: '', + desc: '', + }); + const typeChang=()=>{ + console.log('tag',form) + } + const rules = reactive<FormRules>({ + resource: [ + { + type: 'array', + required: true, + message: '用户不能为空', + trigger: 'change', + }, + ], + desc: [ + { + required: true, + message: '用户不能为空', + trigger: 'change', + }, + ]}) + const ShowUser=ref() + const openDai =()=>{ + ShowUser.value.openDailog() + } + return { + form, + rules, + formS, + typeChang, + ShowUser, + openDai, + Search, + }; + }, +}); +</script> + +<style scoped> +.box { + margin: 30px 0 100px 0; + background-color: #fff; + border: 1px solid #dcdfe6; + box-shadow: 0 2px 4px 0 rgb(0 0 0 / 12%), 0 0 6px 0 rgb(0 0 0 / 4%); + padding: 20px; +} +.el-row { + padding: 0 0 20px 0; +} +</style> \ No newline at end of file diff --git a/src/views/goalManagement/processForms/processForms.vue b/src/views/goalManagement/processForms/processForms.vue new file mode 100644 index 0000000..331337a --- /dev/null +++ b/src/views/goalManagement/processForms/processForms.vue @@ -0,0 +1,124 @@ +<template> + <div> + <h4 class="title">胡海涛2022-07-01 16:08:42发起了目标检查上报(检查)--检查</h4> + <div class="box"> + <el-menu + :default-active="activeIndex" + class="el-menu-demo" + background-color="#ebeef5" + text-color="#fff" + active-text-color="#fff" + mode="horizontal" + @select="handleSelect" + > + <el-menu-item index="1">表单信息</el-menu-item> + <!-- <el-menu-item index="2">流程图</el-menu-item> --> + </el-menu> + <div v-if="activeIndex == 1" class="navType"> + <formInformationTop v-if="false"></formInformationTop> + <formInformationTops></formInformationTops> + </div> + <!-- <div v-if="activeIndex == 2" class="navType" style="padding:20px 20px 0 20px"> + <div class="title2">流程图</div> + <div style="width:100%;height:400px"></div> + </div> --> + </div> + <lowerPlate></lowerPlate> + <div class="btns"> + <el-button type="primary">发起上报</el-button> + </div> + </div> +</template> +<script lang="ts"> +import { defineComponent, reactive, ref,onMounted } from 'vue'; +import { useRouter } from 'vue-router'; +import formInformationTop from './component/formInformationTop.vue' +import formInformationTops from './component/formInformationTops.vue' +import lowerPlate from './component/lowerPlate.vue' +export default defineComponent({ + components:{lowerPlate,formInformationTop,formInformationTops}, + setup() { + const activeIndex = ref('1'); + const handleSelect = (key: string, keyPath: string[]) => { + // console.log(key, keyPath); + activeIndex.value = key; + }; + const form = reactive({ + name: '', + region: '', + date1: '', + date2: '', + delivery: false, + type: [], + resource: '', + desc: '', + }); + + const router=useRouter() + const Type=onMounted(()=>{ + console.log("xxxxxxx",router) + }) + + return { + activeIndex, + handleSelect, + form, + router, + Type + }; + }, +}); +</script> +<style scoped> +.title { + text-align: center; + font-size: 16px; + margin-bottom: 20px; +} +.box{ + border: 1px solid #dcdfe6; + box-shadow: 0 2px 4px 0 rgb(0 0 0 / 12%), 0 0 6px 0 rgb(0 0 0 / 4%); +} +.navType { + background-color: #fff; +} +.tiao{ + width: 100%; + height: 1px; + background-color: #dcdfe6; + margin: 30px 0 ; + position: relative; +} +.typeS{ + width: 80px; + background-color: #fff; + position: absolute; + left: 30px; + top: -9px; + font-size: 14px; + text-align: center; +} +.logoColor{ + background-color: #67c23a; + color: #fff; + padding: 5px 8px; + border-radius: 5px; + margin-right: 5px; +} +.btns{ + width: 100%; + padding:20px 0; + background-color: #fff; + position: fixed; + bottom: 0px; + left: 0px; + text-align: center; + box-shadow: 0 -3px 5px 0 rgb(0 0 0 / 12%); + +} +.title2{ + padding: 20px 0 20px 10px; + width: 100%; + border: 1px solid #dcdfe6; +} +</style> diff --git a/src/views/goalManagement/safetyAssessment/component/Dailog.vue b/src/views/goalManagement/safetyAssessment/component/Dailog.vue new file mode 100644 index 0000000..21771af --- /dev/null +++ b/src/views/goalManagement/safetyAssessment/component/Dailog.vue @@ -0,0 +1,264 @@ +<template> + <el-dialog v-model="dialogVisible" :before-close="resetForm" :fullscreen="full" title="目标分解" width="60%" draggable> + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-form :model="form" label-width="120px"> + <el-row> + <el-col :span="11"> + <el-form-item label="安全目标指标" size="default"> + <el-input v-model="form.qName" :disabled="disabled"> + <template #append> + <el-button :icon="Search" @click="daiInpt" /> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="目标指标编号" size="default"> + <el-input v-model="form.indexNum" disabled /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="11"> + <el-form-item label="年度" size="default"> + <el-input v-model="form.year" disabled /> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="指标值" size="default"> + <el-input v-model="form.value" disabled /> + </el-form-item> + </el-col> + </el-row> + </el-form> + <el-tabs v-model="activeName" class="demo-tabs"> + <el-tab-pane label="目标指标分解" name="1"> + <!-- <el-button type="primary" size="default" @click="daiAdd('新增')" :disabled="disabled">新增</el-button> --> + </el-tab-pane> + </el-tabs> + <el-table :data="formUp.targetDivideDetailList" style="width: 100%"> + <el-table-column align="center" property="dutyDepartmentName" label="责任部门" width="180" /> + <el-table-column align="center" property="value" label="考核指标" width="180" /> + <el-table-column align="center" property="makerDepartmentName" label="制定人部门" /> + <el-table-column align="center" property="makeDate" :formatter="timeDate" label="制定日期" /> + <el-table-column align="center" property="commitPersonName" label="上报人" /> + <el-table-column align="center" label="操作"> + <template #default="scope"> + <el-button link type="primary" @click="daiAdd('查看', scope.row)">查看</el-button> + <el-button link :disabled="disabled" type="primary" @click="daiAdd('修改', scope.row)">考核</el-button> + </template> + </el-table-column> + </el-table> + <template #footer> + <span class="dialog-footer"> + <el-button @click="resetForm" size="default">关闭</el-button> + <el-button type="primary" v-if="disabled == false" @click="submitForm" size="default">确定</el-button> + </span> + </template> + </el-dialog> + <DailogAdd ref="Show" @onAdd="add"></DailogAdd> + <DailogSearch ref="Shows" @backNum="onNumber"></DailogSearch> +</template> +<script lang="ts"> +import { defineComponent, ref, reactive } from 'vue'; +import { timeDate } from '/@/assets/index.ts'; +import { Search, FullScreen } from '@element-plus/icons-vue'; +import DailogAdd from './DailogAdd.vue'; +import { ElMessageBox, ElMessage, ElButton, ElInput, TabsPaneContext } from 'element-plus'; +import DailogSearch from '../../../../components/DailogSearch/DailogSearch.vue'; +import { goalManagementApi } from '/@/api/goalManagement'; +import { emit } from 'process'; +import { deepClone } from '/@/utils/other'; +export default defineComponent({ + components: { DailogAdd, DailogSearch }, + setup(props, { emit }) { + const dialogVisible = ref<boolean>(false); + const form = ref({ + qName: '', + indexNum: '', + year: '', + value: '', + targetDivideDetailList: [], + }); + const targetType = ref(); + const disabled = ref(false); + const titles = ref(); + const numId=ref() + const openDailog = (title: string, type: any, id: number) => { + dialogVisible.value = true; + titles.value = title; + targetType.value = type; + + disabled.value = title == '查看' ? true : false; + if (title == '查看' || title == '修改') { + goalManagementApi() + .getTargetMngDetail(id) + .then((res) => { + if (res.data.code == 200) { + form.value = res.data.data; + formUp.targetDivideDetailList = form.value.targetDivideDetailList; + for(let i=0;i<formUp.targetDivideDetailList.length;i++){ + formUp.targetDivideDetailList[i].makeDate=timeC(formUp.targetDivideDetailList[i].makeDate) + } + } else { + ElMessage.error(res.data.msg); + } + }); + } + numId.value=id + }; + const timeC = (timestamp: any) => { + let a = new Date(timestamp).getTime(); + const date = new Date(a); + const Y = date.getFullYear() + '-'; + const M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-'; + const D = (date.getDate() < 10 ? '0' + date.getDate() : date.getDate()) + ' '; + const h = (date.getHours() < 10 ? '0' + date.getHours() : date.getHours()) + ':'; + const m = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes(); + const s = date.getSeconds(); // 秒 + const dateString = Y + M + D + h + m +`:${s}`; + // console.log('dateString', dateString); // > dateString 2021-07-06 14:23 + return dateString; + }; + const onNumber = (val: object) => { + form.value = val; + }; + // 导航 + const activeName = ref('1'); + // 表格 + const tableData = ref([]); + // 新增弹窗 + const index = ref<any>(); + const Show = ref(); + const daiAdd = (title: string, data: any) => { + index.value = formUp.targetDivideDetailList.indexOf(data); + Show.value.openDailog(title, data); + }; + const formUp = reactive({ + targetId: '', //关联的目标指标/外键 + delTargetDivideDetails: '', //要删除的目标指标分解ID,多个用逗号隔开 + targetDivideDetailList: [], //目标指标分解列表 + }); + + const add = (val: any) => { + goalManagementApi() + .getTargetMngDetail(numId.value) + .then((res) => { + if (res.data.code == 200) { + form.value = res.data.data; + formUp.targetDivideDetailList = form.value.targetDivideDetailList; + for(let i=0;i<formUp.targetDivideDetailList.length;i++){ + formUp.targetDivideDetailList[i].makeDate=timeC(formUp.targetDivideDetailList[i].makeDate) + } + } else { + ElMessage.error(res.data.msg); + } + }); + + // let obj=JSON.parse(JSON.stringify(form.value)) + }; + // 新增 + const submitForm = () => { + formUp.delTargetDivideDetails = arr.value.toString(); + formUp.targetId = form.value.id; + dialogVisible.value = false; + for(let i=0;i<formUp.targetDivideDetailList.length;i++){ + delete formUp.targetDivideDetailList[i].dutyDepartmentName + delete formUp.targetDivideDetailList[i].makerDepartmentName + } + goalManagementApi() + .gettargetDivideDetail(formUp) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + message: res.data.msg, + type: 'success', + }); + emit('addList'); + } else { + ElMessage.error(res.data.msg); + } + }); + form.value = { + qName: '', + indexNum: '', + year: '', + value: '', + targetDivideDetailList: [], + }; + tableData.value = []; + formUp.targetId = ''; + formUp.delTargetDivideDetails = ''; + formUp.targetDivideDetailList = []; + }; + const arr = ref([]); + // 安全目标指标弹窗 + const Shows = ref(); + const daiInpt = () => { + Shows.value.openDailog(targetType.value); + }; + // 关闭 + const resetForm = () => { + dialogVisible.value = false; + form.value = { + qName: '', + indexNum: '', + year: '', + value: '', + targetDivideDetailList: [], + }; + tableData.value = []; + formUp.targetId = ''; + formUp.delTargetDivideDetails = ''; + formUp.targetDivideDetailList = []; + }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + // 时间格式处理 + // const timeDate = (data: any) => { + // let result = new Date(data).getTime(); + // return result; + // }; + return { + timeC, + index, + timeDate, + arr, + form, + dialogVisible, + openDailog, + activeName, + tableData, + Show, + daiAdd, + Shows, + daiInpt, + Search, + full, + toggleFullscreen, + FullScreen, + onNumber, + targetType, + disabled, + resetForm, + titles, + add, + formUp, + submitForm, + numId + }; + }, +}); +</script> +<style scoped> +.el-row { + padding: 0 0 20px 0; +} +</style> \ No newline at end of file diff --git a/src/views/goalManagement/safetyAssessment/component/DailogAdd.vue b/src/views/goalManagement/safetyAssessment/component/DailogAdd.vue new file mode 100644 index 0000000..dc63830 --- /dev/null +++ b/src/views/goalManagement/safetyAssessment/component/DailogAdd.vue @@ -0,0 +1,281 @@ +<template> + <el-dialog v-model="dialogVisible" :fullscreen="full" :title="titles" width="50%" draggable @close="resetForm(ruleFormRef)"> + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-form :model="form" :disabled="disabled" label-width="120px" ref="ruleFormRef" :rules="rules"> + <!-- <el-row> + <el-col :span="11"> + <el-form-item label="责任部门" prop="dutyDepartmentId" size="default"> + <el-tree-select v-model="form.dutyDepartmentId" check-strictly="true" @current-change="dutyName" :data="data" class="w100" :props="propse" placeholder="请选择" /> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="考核指标" prop="examineValue" size="default"> + <el-input v-model.number="form.examineValue" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="11"> + <el-form-item label="制定人部门" prop="makerDepartmentId" size="default"> + <el-tree-select v-model="form.makerDepartmentId" :data="data" check-strictly="true" + @current-change="makerDepartmentName" class="w100" :props="propse" placeholder="请选择" /> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="制定日期" prop="makeDate" size="default"> + <el-date-picker v-model="form.makeDate" format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss" type="datetime" placeholder="请选择" style="width: 100%" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="11"> + <el-form-item label="上报值" prop="uploadValue" size="default"> + <el-input v-model="form.uploadValue"> + <template #append> <el-button :icon="Search" @click="openUser" /> </template> + </el-input> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="上报时间" prop="uploadDate" size="default"> + <el-date-picker v-model="form.uploadDate" format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss" type="datetime" placeholder="请选择" style="width: 100%" /> + </el-form-item> + </el-col> + </el-row> --> + <el-row> + <el-col :span="11"> + <el-form-item label="考核结果" prop="examineResult" size="default"> + <el-select v-model="form.examineResult" placeholder="请选择" style="width: 100%"> + <el-option label="合格" :value="1" /> + <el-option label="不合格" :value="2" /> + </el-select> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="考核人" prop="examinePersonName" size="default"> + <el-input v-model="form.examinePersonName"> + <template #append> <el-button :icon="Search" @click="openUser" /> </template> + </el-input> + </el-form-item> + </el-col> + </el-row> + <!-- <el-row> + <el-col :span="11"> + <el-form-item label="考核时间" prop="examineDate" size="default"> + <el-date-picker v-model="form.examineDate" format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss" type="datetime" placeholder="请选择" style="width: 100%" /> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"></el-col> + </el-row> --> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="resetForm(ruleFormRef)" size="default">关闭</el-button> + <el-button type="primary" @click="submitForm(ruleFormRef)" size="default">确定</el-button> + </span> + </template> + </el-dialog> + <DailogSearchUser ref="Show" @SearchUser="onUser"></DailogSearchUser> +</template> +<script lang="ts"> +import { defineComponent, ref, reactive, onMounted } from 'vue'; +import { Search, FullScreen } from '@element-plus/icons-vue'; +import type { FormInstance, FormRules } from 'element-plus'; +import DailogSearchUser from '../../../../components/DailogSearchUser/index.vue'; +import { ElMessageBox, ElMessage, ElButton, ElInput, TabsPaneContext } from 'element-plus'; +import { goalManagementApi } from '/@/api/goalManagement'; +export default defineComponent({ + components: { DailogSearchUser }, + setup(props, { emit }) { + const ruleFormRef = ref<FormInstance>(); + const form = ref({ + targetDivideDetailId: "", //关联的目标分解/外键 + examinePersonId: "", + examinePersonName: '', + examineResult: "", //考核结果 1:合格 2:不合格 + id: "", //目标指标ID + }); + //部门 + // const department = () => { + // goalManagementApi() + // .getTreedepartment() + // .then((res) => { + // if (res.data.code == 200) { + // data.value = res.data.data; + // } else { + // ElMessage.error(res.data.msg); + // } + // }); + // }; + // const propse = { + // label: 'depName', + // children: 'children', + // value: 'depId', + // }; + // onMounted(() => { + // department(); + // }); + const disabled = ref(false); + // 开启弹窗 + const titles = ref(); + const dialogVisible = ref(false); + const openDailog = (title: string, data: any) => { + titles.value = `${title}目标考核`; + if (title == '查看') { + disabled.value = true; + form.value = data; + // form.value.id = data.targetId; + form.value.targetDivideDetailId=data.id + form.value.examinePersonName = data.examinePersonName; + form.value.examinePersonId=data.examinePersonId + form.value.examineResult=data.examineResult + } else if (title == '修改') { + console.log(data) + disabled.value = false; + // form.value.id = data.targetId; + form.value.targetDivideDetailId=data.id + form.value.examinePersonName = data.examinePersonName; + form.value.examinePersonId=data.examinePersonId + form.value.examineResult=data.examineResult + } else { + disabled.value = false; + } + dialogVisible.value = true; + }; + // 开启用户弹窗 + const Show = ref(); + const openUser = () => { + Show.value.openDailog(); + }; + const rules = reactive<FormRules>({ + // dutyDepartmentId: [ + // { + // required: true, + // message: '责任部门不能为空', + // trigger: 'blur', + // }, + // ], + // makerDepartmentId: [ + // { + // required: true, + // message: '制定人部门不能为空', + // trigger: 'blur', + // }, + // ], + // commitPersonId: [ + // { + // required: true, + // message: '上报人不能为空', + // trigger: 'blur', + // }, + // ], + // examineValue: [ + // { + // required: true, + // message: '考核指标值不能为空', + // trigger: 'blur', + // }, + // { + // type: 'number', + // message: '考核指标值只能为数字类型', + // trigger: 'blur', + // }, + // ], + // makeDate: [ + // { + // required: true, + // message: '制定日期不能为空', + // trigger: 'blur', + // }, + // ], + examinePersonName: [], + examineResult:[] + + }); + // const dutyName = (data: any) => { + // form.value.dutyDepartmentName = data.depName; + // }; + // const makerDepartmentName = (data: any) => { + // form.value.makerDepartmentName = data.depName; + // }; + + const submitForm = async (formEl: FormInstance | undefined) => { + if (!formEl) return; + await formEl.validate((valid, fields) => { + if (valid) { + console.log(form.value) + dialogVisible.value = false; + goalManagementApi().gettargetExamineAddOrUpdate(form.value).then(res=>{ + if(res.data.code==200){ + ElMessage({ + message: res.data.msg, + type: 'success', + }); + }else{ + ElMessage.error(res.data.msg); + } + }) + // handleClose(formEl) + } else { + console.log('error submit!', fields); + } + }); + emit('onAdd'); + }; + + const resetForm = (formEl: FormInstance | undefined) => { + // console.log(formEl); + if (!formEl) return; + // formEl.resetFields(); + dialogVisible.value = false; + form.value = {}; + }; + // const handleClose = (formEl: any) => { + // formEl.resetFields(); + // }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + // const data = ref(); + const onUser = (e: any) => { + console.log(e); + form.value.examinePersonId = e.uid; + form.value.examinePersonName = e.realName; + }; + return { + disabled, + titles, + // handleClose, + form, + // propse, + // department, + dialogVisible, + openDailog, + Show, + openUser, + Search, + full, + toggleFullscreen, + FullScreen, + // data, + onUser, + ruleFormRef, + rules, + submitForm, + resetForm, + // dutyName, + // makerDepartmentName, + }; + }, +}); +</script> +<style scoped> +.el-row { + padding: 0 0 20px 0; +} +</style> diff --git a/src/views/goalManagement/safetyAssessment/index.vue b/src/views/goalManagement/safetyAssessment/index.vue new file mode 100644 index 0000000..f52ba71 --- /dev/null +++ b/src/views/goalManagement/safetyAssessment/index.vue @@ -0,0 +1,241 @@ +<template> + <div> + <el-form ref="ruleFormRef" :model="ruleForm" status-icon label-width="20px" class="topTitle"> + <el-row> + <el-col :span="4"> + <el-form-item size="default"> + <el-input v-model="ruleForm.searchParams.indexNum" placeholder="请输入目标指标" /> + </el-form-item> + </el-col> + <!-- <el-col :span="4"> + <el-form-item> + <el-input v-model="ruleForm.checkPass" placeholder="目标指标编号" /> + </el-form-item> + </el-col> --> + <el-col :span="4"> + <el-form-item> + <el-button size="default" type="primary" @click="listApi">查询</el-button> + <el-button size="default" @click="resetForm">重置</el-button> + </el-form-item> + </el-col> + </el-row> + </el-form> + <div class="minCenter"> + <el-tabs v-model="ruleForm.searchParams.targetType" class="demo-tabs" @tab-click="handleClick"> + <div class="btns"> + <div> + <!-- <el-button size="default" type="primary" :icon="Plus" @click="openD('新建')">新建</el-button> --> + </div> + <div> + <!-- <el-button size="default" :icon="Refresh"></el-button> --> + </div> + </div> + <el-tab-pane label="目标定制(年)" name="1"> </el-tab-pane> + <el-tab-pane label="目标定制(月)" name="2"></el-tab-pane> + <el-tab-pane label="目标定制(半年)" name="3"></el-tab-pane> + <el-tab-pane label="目标定制(季度)" name="4"></el-tab-pane> + </el-tabs> + <el-table ref="multipleTableRef" :data="tableData" style="width: 100%"> + <el-table-column label="序号" align="center" type="index" width="70" /> + <el-table-column type="expand"> + <template #default="scope"> + <div class="tableC"> + <el-tabs v-model="activeNames"> + <el-tab-pane label="目标指标分解" name="1"> + <el-table :data="scope.row.targetDivideDetailList" style="width: 100%"> + <el-table-column align="center" prop="dutyDepartmentName" label="责任部门" /> + <el-table-column align="center" prop="value" label="考核指标" /> + <el-table-column align="center" prop="makerDepartmentName" label="制定人部门" /> + <el-table-column align="center" prop="makeDate" :formatter="timeDate" label="制定日期" /> + <el-table-column align="center" prop="commitPersonName" label="上报人" /> + </el-table> + </el-tab-pane> + </el-tabs> + </div> + </template> + </el-table-column> + <el-table-column label="安全目标指标" align="center" property="qName" sortable /> + <el-table-column property="indexNum" align="center" label="考核指标编号" sortable /> + <el-table-column property="year" label="年度" align="center" sortable show-overflow-tooltip /> + <el-table-column property="value" label="指标值" align="center" sortable show-overflow-tooltip /> + <el-table-column label="操作" align="center" width="300" sortable show-overflow-tooltip> + <template #default="scope"> + <el-button link type="primary" size="default" :icon="View" @click="openD('查看', scope.row.id)">查看</el-button> + <el-button link type="primary" size="default" :icon="View" @click="openD('修改', scope.row.id)">考核</el-button> + <!--<el-button link type="primary" size="default" :icon="Delete" @click="onDelete(scope.row.id)">删除</el-button>--> + </template> + </el-table-column> + </el-table> + <div class="pages"> + <el-pagination + v-model:currentPage="currentPage4" + v-model:page-size="pageSize4" + :page-sizes="[10, 20, 30, 40]" + layout="total, sizes, prev, pager, next, jumper" + :total="total" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + <Dailog ref="openAdd"></Dailog> + </div> + </div> +</template> +<script lang="ts"> +import { timeDate } from '/@/assets/index.ts'; +import Dailog from './component/Dailog.vue'; +import { ref, toRefs, reactive, onMounted, defineComponent } from 'vue'; +import { ElMessageBox, ElMessage, ElButton, ElInput, TabsPaneContext, FormInstance } from 'element-plus'; +import { Plus, Delete, Upload, Download, Refresh, View } from '@element-plus/icons-vue'; +import { goalManagementApi } from '/@/api/goalManagement'; +import type { TableColumnCtx } from 'element-plus/es/components/table/src/table-column/defaults'; +export default defineComponent({ + components: { ElButton, ElInput, Dailog }, + setup() { + // 搜索条件 + const ruleForm = reactive({ + pageSize: 10, + pageIndex: 1, + searchParams: { + qName: '', ////安全目标指标 + indexNum: '', ////目标指标编号 + targetType: '1', ////指标类型 1:年指标 2:月指标 + divideStatus: 1, ////分解状态 1:已分解 2:未分解 + }, + }); + // 重置 + const resetForm = () => { + ruleForm.searchParams.qName = ''; + ruleForm.searchParams.indexNum = ''; + }; + const listApi = () => { + goalManagementApi() + .gettargetExamineList(ruleForm) + .then((res) => { + if (res.data.code == 200) { + tableData.value = res.data.data; + currentPage4.value = res.data.pageIndex; + pageSize4.value = res.data.pageSize; + total.value = res.data.total; + } else { + ElMessage.error(res.data.msg); + } + }); + }; + // + const handleClick = (val: any) => { + let targetType = JSON.parse(JSON.stringify(val)); + ruleForm.searchParams.targetType = targetType.paneName; + listApi(); + }; + onMounted(() => { + listApi(); + }); + const onAddorUpdata = () => { + listApi(); + }; + // 表格 + const tableData = ref(); + const currentPage4 = ref(); + const pageSize4 = ref(); + const total = ref(); + const handleSizeChange = (val: number) => { + // console.log(`${val} items per page`); + ruleForm.pageSize = val; + listApi(); + }; + const handleCurrentChange = (val: number) => { + // console.log(`current page: ${val}`); + ruleForm.pageIndex = val; + listApi(); + }; + // 删除 + const onDelete = (id: number) => { + var arr=[] + arr.push(id) + ElMessageBox.confirm('确定删除所选项吗?', 'Warning', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + goalManagementApi() + .getTargetMngDelete(arr) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + message: res.data.msg, + type: 'success', + }); + listApi(); + } else { + ElMessage.error(res.data.msg); + } + }); + }) + .catch(() => { + ElMessage({ + type: 'info', + message: 'Delete canceled', + }); + }); + }; + // 弹窗 + const openAdd = ref(); + const openD = (title: String, id: number) => { + openAdd.value.openDailog(title, ruleForm.searchParams.targetType,id); + }; + const activeNames=ref("1") + return { + timeDate, + activeNames, + listApi, + ruleForm, + resetForm, + handleClick, + tableData, + currentPage4, + pageSize4, + handleSizeChange, + handleCurrentChange, + onAddorUpdata, + total, + openAdd, + openD, + onDelete, + Plus, + Delete, + Upload, + Download, + Refresh, + View, + }; + }, +}); +</script> +<style scoped> +.topTitle { + background-color: #fff; + padding: 20px 0px 20px 0px; + margin-bottom: 10px; +} +.minCenter { + width: 100%; + background-color: #fff; + margin-top: 10px; + padding: 0 20px; +} +.btns { + padding: 10px 0px 10px 0px; + display: flex; + justify-content: space-between; +} +.pages { + padding: 20px 0; + display: flex; + justify-content: right; +} +.tableC { + margin: 0 10%; +} +</style> \ No newline at end of file diff --git a/src/views/goalManagement/targetClassification/index.vue b/src/views/goalManagement/targetClassification/index.vue new file mode 100644 index 0000000..8c59970 --- /dev/null +++ b/src/views/goalManagement/targetClassification/index.vue @@ -0,0 +1,261 @@ +<template> + <div> + <!-- <el-form :model="ruleForm" status-icon label-width="20px" class="topTitle"> + <el-row> + <el-col :span="4"> + <el-form-item> + <el-input v-model="ruleForm.searchParams.qName" size="default" placeholder="安全目标指标" /> + </el-form-item> + </el-col> + <el-col :span="4"> + <el-form-item> + <el-input v-model="ruleForm.searchParams.indexNum" size="default" placeholder="目标指标编号" /> + </el-form-item> + </el-col> + <el-col :span="16"> + <el-form-item> + <el-button type="primary" size="default" @click="listApi">查询</el-button> + <el-button size="default" @click="resetForm">重置</el-button> + </el-form-item> + </el-col> + </el-row> + </el-form> --> + <div class="minCenter"> + <div class="btns"> + <div> + <el-button size="default" type="primary" :icon="Plus" @click="openD('新建')">新建</el-button> + <el-button size="default" type="warning" :disabled="warning" :icon="EditPen" plain @click="openD('修改', deletAll[0])">修改</el-button> + <el-button size="default" type="danger" :disabled="danger" :icon="Delete" plain @click="onDeleteAll">删除</el-button> + </div> + </div> + <el-table ref="multipleTableRef" :data="tableData" @selection-change="handleSelectionChange" style="width: 100%"> + <el-table-column label="序号" align="center" type="index" width="70" /> + <el-table-column type="selection" align="center" width="55" /> + <el-table-column label="名称" align="center" property="typeName" sortable /> + <el-table-column property="memo" align="center" label="描述" sortable /> + <!-- <el-table-column property="year" label="年度" align="center" sortable show-overflow-tooltip /> + <el-table-column property="value" label="指标值" align="center" sortable show-overflow-tooltip /> --> + <el-table-column label="操作" align="center" sortable show-overflow-tooltip> + <template #default="scope"> + <el-button link type="primary" size="small" :icon="View" @click="openD('查看', scope.row.id)">查看</el-button> + <el-button link type="primary" size="small" :icon="EditPen" @click="openD('修改', scope.row.id)">修改</el-button> + <el-button link type="primary" size="small" :icon="Delete" @click="onDelete(scope.row.id)">删除</el-button> + </template> + </el-table-column> + </el-table> + <div class="pages"> + <el-pagination + v-model:currentPage="currentPage4" + v-model:page-size="pageSize4" + :page-sizes="[10, 20, 30, 40]" + layout="total, sizes, prev, pager, next, jumper" + :total="total" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + </div> + <DailogClass ref="Show" @onAdd="add"></DailogClass> + </div> +</template> +<script lang="ts"> +import DailogClass from '/@/components/DailogClass/index.vue'; +import { ref, toRefs, reactive, onMounted, defineComponent } from 'vue'; +import { ElMessageBox, ElMessage, ElButton, ElInput, TabsPaneContext, FormInstance } from 'element-plus'; +import { Plus, Delete, Upload, Download, Refresh, View, EditPen } from '@element-plus/icons-vue'; +import { goalManagementApi } from '/@/api/goalManagement'; +export default defineComponent({ + components: { ElButton, ElInput,DailogClass }, + setup() { + // 搜索条件 + const ruleForm = reactive({ + pageSize: 10, + pageIndex: 1, + searchParams: { + typeName: '', ////分类名称 + }, + }); + // 下方导航与表格 + const tableData = ref([]); + const currentPage4 = ref(); + const pageSize4 = ref(); + const total = ref(); + // const resetForm = () => { + // ruleForm.searchParams.qName = ''; + // ruleForm.searchParams.indexNum = ''; + // listApi(); + // }; + const listApi = () => { + goalManagementApi() + .gettargetClassList(ruleForm) + .then((res) => { + if (res.data.code == 200) { + tableData.value = res.data.data; + currentPage4.value = res.data.pageIndex; + pageSize4.value = res.data.pageSize; + total.value = res.data.total; + } else { + ElMessage.error(res.data.msg); + } + }); + }; + onMounted(() => { + listApi(); + }); + + const handleSizeChange = (val: number) => { + // console.log(`${val} items per page`); + ruleForm.pageSize = val; + listApi(); + }; + const handleCurrentChange = (val: number) => { + // console.log(`current page: ${val}`); + ruleForm.pageIndex = val; + listApi(); + }; + const activeNames = ref('1'); + // 打开弹窗 + const Show = ref(); + const openD = (title: String, id: number) => { + Show.value.openDailog(title, ruleForm.searchParams.targetType,id); + }; + // 删除 + const onDelete = (id: number) => { + let arr = []; + arr.push(id); + ElMessageBox.confirm('确定删除所选项吗?', 'Warning', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + goalManagementApi() + .gettargetClassDelete(arr) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + message: res.data.msg, + type: 'success', + }); + listApi(); + } else { + ElMessage.error(res.data.msg); + } + }); + }) + .catch(() => { + // ElMessage({ + // type: 'info', + // message: 'Delete canceled', + // }); + }); + }; + // 批量删除 + const warning = ref(true); + const danger = ref(true); + const deletAll = ref(); + const handleSelectionChange = (val: any) => { + let valId = JSON.parse(JSON.stringify(val)); + let arr = []; + for (let i = 0; i < valId.length; i++) { + arr.push(valId[i].id); + } + deletAll.value = arr; + if (val.length == 1) { + warning.value = false; + danger.value = false; + } else if (val.length == 0) { + warning.value = true; + danger.value = true; + } else { + warning.value = true; + danger.value = false; + } + }; + const onDeleteAll = () => { + ElMessageBox.confirm('确定删除所选项吗?', 'Warning', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + goalManagementApi() + .gettargetClassDelete(deletAll.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + message: res.data.msg, + type: 'success', + }); + listApi(); + } else { + ElMessage.error(res.data.msg); + } + }); + }) + .catch(() => { + ElMessage({ + type: 'info', + message: 'Delete canceled', + }); + }); + }; + const add = () => { + listApi(); + }; + return { + listApi, + add, + // resetForm, + tableData, + currentPage4, + pageSize4, + total, + ruleForm, + handleSizeChange, + handleCurrentChange, + Show, + openD, + activeNames, + onDelete, + warning, + danger, + deletAll, + handleSelectionChange, + onDeleteAll, + Plus, + Delete, + Upload, + Download, + Refresh, + View, + EditPen, + }; + }, +}); +</script> +<style scoped> +.topTitle { + background-color: #fff; + padding: 20px 0px 20px 0px; +} +.minCenter { + width: 100%; + background-color: #fff; + margin-top: 10px; + padding: 0 20px; +} +.btns { + padding: 20px 0px 10px 0px; + display: flex; + justify-content: space-between; +} +.pages { + padding: 20px 0; + display: flex; + justify-content: right; +} +.tableC { + margin: 0 10%; +} +</style> diff --git a/src/views/goalManagement/targetDecompositionHalfYear/index.vue b/src/views/goalManagement/targetDecompositionHalfYear/index.vue new file mode 100644 index 0000000..1ed6ed9 --- /dev/null +++ b/src/views/goalManagement/targetDecompositionHalfYear/index.vue @@ -0,0 +1,286 @@ +<template> + <div> + <el-form :model="ruleForm" status-icon label-width="20px" class="topTitle"> + <el-row> + <el-col :span="4"> + <el-form-item> + <el-input v-model="ruleForm.searchParams.qName" size="default" placeholder="安全目标指标" /> + </el-form-item> + </el-col> + <el-col :span="4"> + <el-form-item> + <el-input v-model="ruleForm.searchParams.indexNum" size="default" placeholder="目标指标编号" /> + </el-form-item> + </el-col> + <el-col :span="16"> + <el-form-item> + <el-button type="primary" size="default" @click="listApi">查询</el-button> + <el-button size="default" @click="resetForm">重置</el-button> + </el-form-item> + </el-col> + </el-row> + </el-form> + <div class="minCenter"> + <div class="btns"> + <div> + <!--<el-button size="default" type="primary" :icon="Plus" @click="openD('新建')">新建</el-button>--> + <el-button size="default" type="warning" :disabled="warning" :icon="EditPen" plain + @click="openD('修改', deletAll[0])">修改</el-button> + <el-button size="default" type="danger" :disabled="danger" :icon="Delete" plain @click="onDeleteAll">删除</el-button> + </div> + </div> + <el-table ref="multipleTableRef" :data="tableData" @selection-change="handleSelectionChange" style="width: 100%"> + <el-table-column label="序号" align="center" type="index" width="70" /> + <el-table-column type="selection" align="center" width="55" /> + <el-table-column type="expand"> + <template #default="scope"> + <div class="tableC"> + <el-tabs v-model="activeNames"> + <el-tab-pane label="目标指标分解" name="1"> + <el-table :data="scope.row.targetDivideDetailList" style="width: 100%"> + <el-table-column align="center" prop="dutyDepartmentName" label="责任部门" /> + <el-table-column align="center" prop="value" label="考核指标" /> + <el-table-column align="center" prop="makerDepartmentName" label="制定人部门" /> + <el-table-column align="center" prop="makeDate" :formatter="timeDate" label="制定日期" /> + <el-table-column align="center" prop="commitPersonName" label="上报人" /> + </el-table> + </el-tab-pane> + </el-tabs> + </div> + </template> + </el-table-column> + <el-table-column label="安全目标指标" align="center" property="qName" sortable /> + <el-table-column property="indexNum" align="center" label="目标指标编号" sortable /> + <el-table-column property="year" label="年度" align="center" sortable show-overflow-tooltip /> + <el-table-column property="value" label="指标值" align="center" sortable show-overflow-tooltip /> + <el-table-column label="操作" align="center" sortable show-overflow-tooltip> + <template #default="scope"> + <el-button link type="primary" size="small" :icon="View" @click="openD('查看', scope.row.id)">查看</el-button> + <el-button link type="primary" size="small" :icon="EditPen" @click="openD('修改', scope.row.id)">修改</el-button> + <el-button link type="primary" size="small" :icon="Delete" @click="onDelete(scope.row.id)">删除</el-button> + </template> + </el-table-column> + </el-table> + <div class="pages"> + <el-pagination + v-model:currentPage="currentPage4" + v-model:page-size="pageSize4" + :page-sizes="[10, 20, 30, 40]" + layout="total, sizes, prev, pager, next, jumper" + :total="total" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + </div> + <Dailog ref="Show" @addList="add"></Dailog> + </div> +</template> +<script lang="ts"> +import { timeDate } from '/@/assets/index.ts'; +import search from '../targetSettings/component/search.vue'; +import Dailog from '../targetDecompositionYear/component/Dailog.vue'; +import { ref, toRefs, reactive, onMounted, defineComponent } from 'vue'; +import { ElMessageBox, ElMessage, ElButton, ElInput, TabsPaneContext, FormInstance } from 'element-plus'; +import { Plus, Delete, Upload, Download, Refresh, View, EditPen } from '@element-plus/icons-vue'; +import { goalManagementApi } from '/@/api/goalManagement'; +import type { TableColumnCtx } from 'element-plus/es/components/table/src/table-column/defaults'; +export default defineComponent({ + components: { ElButton, ElInput, Dailog }, + setup() { + // 搜索条件 + const ruleForm = reactive({ + pageSize: 10, + pageIndex: 1, + searchParams: { + qName: '', ////安全目标指标 + indexNum: '', ////目标指标编号 + targetType: '3', ////指标类型 1:年指标 2:月指标 + divideStatus: '', ////分解状态 1:已分解 2:未分解 + }, + }); + // 下方导航与表格 + const tableData = ref([]); + const currentPage4 = ref(); + const pageSize4 = ref(); + const total = ref(); + const resetForm = () => { + ruleForm.searchParams.qName = ''; + ruleForm.searchParams.indexNum = ''; + listApi() + }; + const listApi = () => { + goalManagementApi() + .getTargetMngList(ruleForm) + .then((res) => { + if (res.data.code == 200) { + tableData.value = res.data.data; + currentPage4.value = res.data.pageIndex; + pageSize4.value = res.data.pageSize; + total.value = res.data.total; + } else { + ElMessage.error(res.data.msg); + } + }); + }; + onMounted(() => { + listApi(); + }); + + const handleSizeChange = (val: number) => { + // console.log(`${val} items per page`); + ruleForm.pageSize = val; + listApi(); + }; + const handleCurrentChange = (val: number) => { + // console.log(`current page: ${val}`); + ruleForm.pageIndex = val; + listApi(); + }; + const activeNames = ref('1'); + // 打开弹窗 + const Show = ref(); + const openD = (title: String, id: number) => { + Show.value.openDailog(title, ruleForm.searchParams.targetType, id); + }; + // 删除 + const onDelete = (id: number) => { + let arr=[] + arr.push(id) + ElMessageBox.confirm('确定删除所选项吗?', 'Warning', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + goalManagementApi() + .getTargetMngDelete(arr) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + message: res.data.msg, + type: 'success', + }); + listApi(); + } else { + ElMessage.error(res.data.msg); + } + }); + }) + .catch(() => { + // ElMessage({ + // type: 'info', + // message: 'Delete canceled', + // }); + }); + }; + // 批量删除 + const warning = ref(true); + const danger = ref(true); + const deletAll = ref(); + const handleSelectionChange = (val: any) => { + let valId = JSON.parse(JSON.stringify(val)); + let arr = []; + for (let i = 0; i < valId.length; i++) { + arr.push(valId[i].id); + } + deletAll.value = arr + if (val.length == 1) { + warning.value = false; + danger.value = false; + } else if (val.length == 0) { + warning.value = true; + danger.value = true; + } else { + warning.value = true; + danger.value = false; + } + }; + const onDeleteAll = () => { + ElMessageBox.confirm('确定删除所选项吗?', 'Warning', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + goalManagementApi() + .getTargetMngDelete(deletAll.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + message: res.data.msg, + type: 'success', + }); + listApi(); + } else { + ElMessage.error(res.data.msg); + } + }); + }) + .catch(() => { + ElMessage({ + type: 'info', + message: 'Delete canceled', + }); + }); + }; + const add=()=>{ + listApi() + } + return { + timeDate, + add, + listApi, + resetForm, + tableData, + currentPage4, + pageSize4, + total, + ruleForm, + handleSizeChange, + handleCurrentChange, + Show, + openD, + activeNames, + onDelete, + warning, + danger, + deletAll, + handleSelectionChange, + onDeleteAll, + Plus, + Delete, + Upload, + Download, + Refresh, + View, + EditPen, + }; + }, +}); +</script> +<style scoped> +.minCenter { + width: 100%; + background-color: #fff; + margin-top: 10px; + padding: 0 20px; +} +.btns { + padding: 0px 0px 10px 0px; + display: flex; + justify-content: space-between; +} +.pages { + padding: 20px 0; + display: flex; + justify-content: right; +} +.tableC { + margin: 0 10%; +} +.topTitle { + background-color: #fff; + padding: 20px 0px 20px 0px; +} +</style> \ No newline at end of file diff --git a/src/views/goalManagement/targetDecompositionMonth/index.vue b/src/views/goalManagement/targetDecompositionMonth/index.vue new file mode 100644 index 0000000..f0510a7 --- /dev/null +++ b/src/views/goalManagement/targetDecompositionMonth/index.vue @@ -0,0 +1,286 @@ +<template> + <div> + <el-form :model="ruleForm" status-icon label-width="20px" class="topTitle"> + <el-row> + <el-col :span="4"> + <el-form-item> + <el-input v-model="ruleForm.searchParams.qName" size="default" placeholder="安全目标指标" /> + </el-form-item> + </el-col> + <el-col :span="4"> + <el-form-item> + <el-input v-model="ruleForm.searchParams.indexNum" size="default" placeholder="目标指标编号" /> + </el-form-item> + </el-col> + <el-col :span="16"> + <el-form-item> + <el-button type="primary" size="default" @click="listApi">查询</el-button> + <el-button size="default" @click="resetForm">重置</el-button> + </el-form-item> + </el-col> + </el-row> + </el-form> + <div class="minCenter"> + <div class="btns"> + <div> + <!--<el-button size="default" type="primary" :icon="Plus" @click="openD('新建')">新建</el-button>--> + <el-button size="default" type="warning" :disabled="warning" :icon="EditPen" plain + @click="openD('修改', deletAll[0])">修改</el-button> + <el-button size="default" type="danger" :disabled="danger" :icon="Delete" plain @click="onDeleteAll">删除</el-button> + </div> + </div> + <el-table ref="multipleTableRef" :data="tableData" @selection-change="handleSelectionChange" style="width: 100%"> + <el-table-column label="序号" align="center" type="index" width="70" /> + <el-table-column type="selection" align="center" width="55" /> + <el-table-column type="expand"> + <template #default="scope"> + <div class="tableC"> + <el-tabs v-model="activeNames"> + <el-tab-pane label="目标指标分解" name="1"> + <el-table :data="scope.row.targetDivideDetailList" style="width: 100%"> + <el-table-column align="center" prop="dutyDepartmentName" label="责任部门" /> + <el-table-column align="center" prop="value" label="考核指标" /> + <el-table-column align="center" prop="makerDepartmentName" label="制定人部门" /> + <el-table-column align="center" prop="makeDate" :formatter="timeDate" label="制定日期" /> + <el-table-column align="center" prop="commitPersonName" label="上报人" /> + </el-table> + </el-tab-pane> + </el-tabs> + </div> + </template> + </el-table-column> + <el-table-column label="安全目标指标" align="center" property="qName" sortable /> + <el-table-column property="indexNum" align="center" label="目标指标编号" sortable /> + <el-table-column property="year" label="年度" align="center" sortable show-overflow-tooltip /> + <el-table-column property="value" label="指标值" align="center" sortable show-overflow-tooltip /> + <el-table-column label="操作" align="center" sortable show-overflow-tooltip> + <template #default="scope"> + <el-button link type="primary" size="small" :icon="View" @click="openD('查看', scope.row.id)">查看</el-button> + <el-button link type="primary" size="small" :icon="EditPen" @click="openD('修改', scope.row.id)">修改</el-button> + <el-button link type="primary" size="small" :icon="Delete" @click="onDelete(scope.row.id)">删除</el-button> + </template> + </el-table-column> + </el-table> + <div class="pages"> + <el-pagination + v-model:currentPage="currentPage4" + v-model:page-size="pageSize4" + :page-sizes="[10, 20, 30, 40]" + layout="total, sizes, prev, pager, next, jumper" + :total="total" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + </div> + <Dailog ref="Show" @addList="add"></Dailog> + </div> +</template> +<script lang="ts"> +import { timeDate } from '/@/assets/index.ts'; +import search from '../targetSettings/component/search.vue'; +import Dailog from '../targetDecompositionYear/component/Dailog.vue'; +import { ref, toRefs, reactive, onMounted, defineComponent } from 'vue'; +import { ElMessageBox, ElMessage, ElButton, ElInput, TabsPaneContext, FormInstance } from 'element-plus'; +import { Plus, Delete, Upload, Download, Refresh, View, EditPen } from '@element-plus/icons-vue'; +import { goalManagementApi } from '/@/api/goalManagement'; +import type { TableColumnCtx } from 'element-plus/es/components/table/src/table-column/defaults'; +export default defineComponent({ + components: { ElButton, ElInput, Dailog }, + setup() { + // 搜索条件 + const ruleForm = reactive({ + pageSize: 10, + pageIndex: 1, + searchParams: { + qName: '', ////安全目标指标 + indexNum: '', ////目标指标编号 + targetType: '2', ////指标类型 1:年指标 2:月指标 + divideStatus: '', ////分解状态 1:已分解 2:未分解 + }, + }); + // 下方导航与表格 + const tableData = ref([]); + const currentPage4 = ref(); + const pageSize4 = ref(); + const total = ref(); + const resetForm = () => { + ruleForm.searchParams.qName = ''; + ruleForm.searchParams.indexNum = ''; + listApi() + }; + const listApi = () => { + goalManagementApi() + .getTargetMngList(ruleForm) + .then((res) => { + if (res.data.code == 200) { + tableData.value = res.data.data; + currentPage4.value = res.data.pageIndex; + pageSize4.value = res.data.pageSize; + total.value = res.data.total; + } else { + ElMessage.error(res.data.msg); + } + }); + }; + onMounted(() => { + listApi(); + }); + + const handleSizeChange = (val: number) => { + // console.log(`${val} items per page`); + ruleForm.pageSize = val; + listApi(); + }; + const handleCurrentChange = (val: number) => { + // console.log(`current page: ${val}`); + ruleForm.pageIndex = val; + listApi(); + }; + const activeNames = ref('1'); + // 打开弹窗 + const Show = ref(); + const openD = (title: String, id: number) => { + Show.value.openDailog(title, ruleForm.searchParams.targetType, id); + }; + // 删除 + const onDelete = (id: number) => { + let arr=[] + arr.push(id) + ElMessageBox.confirm('确定删除所选项吗?', 'Warning', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + goalManagementApi() + .getTargetMngDelete(arr) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + message: res.data.msg, + type: 'success', + }); + listApi(); + } else { + ElMessage.error(res.data.msg); + } + }); + }) + .catch(() => { + // ElMessage({ + // type: 'info', + // message: 'Delete canceled', + // }); + }); + }; + // 批量删除 + const warning = ref(true); + const danger = ref(true); + const deletAll = ref(); + const handleSelectionChange = (val: any) => { + let valId = JSON.parse(JSON.stringify(val)); + let arr = []; + for (let i = 0; i < valId.length; i++) { + arr.push(valId[i].id); + } + deletAll.value = arr + if (val.length == 1) { + warning.value = false; + danger.value = false; + } else if (val.length == 0) { + warning.value = true; + danger.value = true; + } else { + warning.value = true; + danger.value = false; + } + }; + const onDeleteAll = () => { + ElMessageBox.confirm('确定删除所选项吗?', 'Warning', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + goalManagementApi() + .getTargetMngDelete(deletAll.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + message: res.data.msg, + type: 'success', + }); + listApi(); + } else { + ElMessage.error(res.data.msg); + } + }); + }) + .catch(() => { + ElMessage({ + type: 'info', + message: 'Delete canceled', + }); + }); + }; + const add=()=>{ + listApi() + } + return { + timeDate, + add, + listApi, + resetForm, + tableData, + currentPage4, + pageSize4, + total, + ruleForm, + handleSizeChange, + handleCurrentChange, + Show, + openD, + activeNames, + onDelete, + warning, + danger, + deletAll, + handleSelectionChange, + onDeleteAll, + Plus, + Delete, + Upload, + Download, + Refresh, + View, + EditPen, + }; + }, +}); +</script> +<style scoped> +.minCenter { + width: 100%; + background-color: #fff; + margin-top: 10px; + padding: 0 20px; +} +.btns { + padding: 0px 0px 10px 0px; + display: flex; + justify-content: space-between; +} +.pages { + padding: 20px 0; + display: flex; + justify-content: right; +} +.tableC { + margin: 0 10%; +} +.topTitle { + background-color: #fff; + padding: 20px 0px 20px 0px; +} +</style> diff --git a/src/views/goalManagement/targetDecompositionQuarter/index.vue b/src/views/goalManagement/targetDecompositionQuarter/index.vue new file mode 100644 index 0000000..4f0f36d --- /dev/null +++ b/src/views/goalManagement/targetDecompositionQuarter/index.vue @@ -0,0 +1,286 @@ +<template> + <div> + <el-form :model="ruleForm" status-icon label-width="20px" class="topTitle"> + <el-row> + <el-col :span="4"> + <el-form-item> + <el-input v-model="ruleForm.searchParams.qName" size="default" placeholder="安全目标指标" /> + </el-form-item> + </el-col> + <el-col :span="4"> + <el-form-item> + <el-input v-model="ruleForm.searchParams.indexNum" size="default" placeholder="目标指标编号" /> + </el-form-item> + </el-col> + <el-col :span="16"> + <el-form-item> + <el-button type="primary" size="default" @click="listApi">查询</el-button> + <el-button size="default" @click="resetForm">重置</el-button> + </el-form-item> + </el-col> + </el-row> + </el-form> + <div class="minCenter"> + <div class="btns"> + <div> + <!--<el-button size="default" type="primary" :icon="Plus" @click="openD('新建')">新建</el-button>--> + <el-button size="default" type="warning" :disabled="warning" :icon="EditPen" plain + @click="openD('修改', deletAll[0])">修改</el-button> + <el-button size="default" type="danger" :disabled="danger" :icon="Delete" plain @click="onDeleteAll">删除</el-button> + </div> + </div> + <el-table ref="multipleTableRef" :data="tableData" @selection-change="handleSelectionChange" style="width: 100%"> + <el-table-column label="序号" align="center" type="index" width="70" /> + <el-table-column type="selection" align="center" width="55" /> + <el-table-column type="expand"> + <template #default="scope"> + <div class="tableC"> + <el-tabs v-model="activeNames"> + <el-tab-pane label="目标指标分解" name="1"> + <el-table :data="scope.row.targetDivideDetailList" style="width: 100%"> + <el-table-column align="center" prop="dutyDepartmentName" label="责任部门" /> + <el-table-column align="center" prop="value" label="考核指标" /> + <el-table-column align="center" prop="makerDepartmentName" label="制定人部门" /> + <el-table-column align="center" prop="makeDate" :formatter="timeDate" label="制定日期" /> + <el-table-column align="center" prop="commitPersonName" label="上报人" /> + </el-table> + </el-tab-pane> + </el-tabs> + </div> + </template> + </el-table-column> + <el-table-column label="安全目标指标" align="center" property="qName" sortable /> + <el-table-column property="indexNum" align="center" label="目标指标编号" sortable /> + <el-table-column property="year" label="年度" align="center" sortable show-overflow-tooltip /> + <el-table-column property="value" label="指标值" align="center" sortable show-overflow-tooltip /> + <el-table-column label="操作" align="center" sortable show-overflow-tooltip> + <template #default="scope"> + <el-button link type="primary" size="small" :icon="View" @click="openD('查看', scope.row.id)">查看</el-button> + <el-button link type="primary" size="small" :icon="EditPen" @click="openD('修改', scope.row.id)">修改</el-button> + <el-button link type="primary" size="small" :icon="Delete" @click="onDelete(scope.row.id)">删除</el-button> + </template> + </el-table-column> + </el-table> + <div class="pages"> + <el-pagination + v-model:currentPage="currentPage4" + v-model:page-size="pageSize4" + :page-sizes="[10, 20, 30, 40]" + layout="total, sizes, prev, pager, next, jumper" + :total="total" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + </div> + <Dailog ref="Show" @addList="add"></Dailog> + </div> +</template> +<script lang="ts"> +import { timeDate } from '/@/assets/index.ts'; +import search from '../targetSettings/component/search.vue'; +import Dailog from '../targetDecompositionYear/component/Dailog.vue'; +import { ref, toRefs, reactive, onMounted, defineComponent } from 'vue'; +import { ElMessageBox, ElMessage, ElButton, ElInput, TabsPaneContext, FormInstance } from 'element-plus'; +import { Plus, Delete, Upload, Download, Refresh, View, EditPen } from '@element-plus/icons-vue'; +import { goalManagementApi } from '/@/api/goalManagement'; +import type { TableColumnCtx } from 'element-plus/es/components/table/src/table-column/defaults'; +export default defineComponent({ + components: { ElButton, ElInput, Dailog }, + setup() { + // 搜索条件 + const ruleForm = reactive({ + pageSize: 10, + pageIndex: 1, + searchParams: { + qName: '', ////安全目标指标 + indexNum: '', ////目标指标编号 + targetType: '4', ////指标类型 1:年指标 2:月指标 + divideStatus: '', ////分解状态 1:已分解 2:未分解 + }, + }); + // 下方导航与表格 + const tableData = ref([]); + const currentPage4 = ref(); + const pageSize4 = ref(); + const total = ref(); + const resetForm = () => { + ruleForm.searchParams.qName = ''; + ruleForm.searchParams.indexNum = ''; + listApi() + }; + const listApi = () => { + goalManagementApi() + .getTargetMngList(ruleForm) + .then((res) => { + if (res.data.code == 200) { + tableData.value = res.data.data; + currentPage4.value = res.data.pageIndex; + pageSize4.value = res.data.pageSize; + total.value = res.data.total; + } else { + ElMessage.error(res.data.msg); + } + }); + }; + onMounted(() => { + listApi(); + }); + + const handleSizeChange = (val: number) => { + // console.log(`${val} items per page`); + ruleForm.pageSize = val; + listApi(); + }; + const handleCurrentChange = (val: number) => { + // console.log(`current page: ${val}`); + ruleForm.pageIndex = val; + listApi(); + }; + const activeNames = ref('1'); + // 打开弹窗 + const Show = ref(); + const openD = (title: String, id: number) => { + Show.value.openDailog(title, ruleForm.searchParams.targetType, id); + }; + // 删除 + const onDelete = (id: number) => { + let arr=[] + arr.push(id) + ElMessageBox.confirm('确定删除所选项吗?', 'Warning', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + goalManagementApi() + .getTargetMngDelete(arr) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + message: res.data.msg, + type: 'success', + }); + listApi(); + } else { + ElMessage.error(res.data.msg); + } + }); + }) + .catch(() => { + // ElMessage({ + // type: 'info', + // message: 'Delete canceled', + // }); + }); + }; + // 批量删除 + const warning = ref(true); + const danger = ref(true); + const deletAll = ref(); + const handleSelectionChange = (val: any) => { + let valId = JSON.parse(JSON.stringify(val)); + let arr = []; + for (let i = 0; i < valId.length; i++) { + arr.push(valId[i].id); + } + deletAll.value = arr + if (val.length == 1) { + warning.value = false; + danger.value = false; + } else if (val.length == 0) { + warning.value = true; + danger.value = true; + } else { + warning.value = true; + danger.value = false; + } + }; + const onDeleteAll = () => { + ElMessageBox.confirm('确定删除所选项吗?', 'Warning', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + goalManagementApi() + .getTargetMngDelete(deletAll.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + message: res.data.msg, + type: 'success', + }); + listApi(); + } else { + ElMessage.error(res.data.msg); + } + }); + }) + .catch(() => { + ElMessage({ + type: 'info', + message: 'Delete canceled', + }); + }); + }; + const add=()=>{ + listApi() + } + return { + timeDate, + add, + listApi, + resetForm, + tableData, + currentPage4, + pageSize4, + total, + ruleForm, + handleSizeChange, + handleCurrentChange, + Show, + openD, + activeNames, + onDelete, + warning, + danger, + deletAll, + handleSelectionChange, + onDeleteAll, + Plus, + Delete, + Upload, + Download, + Refresh, + View, + EditPen, + }; + }, +}); +</script> +<style scoped> +.minCenter { + width: 100%; + background-color: #fff; + margin-top: 10px; + padding: 0 20px; +} +.btns { + padding: 0px 0px 10px 0px; + display: flex; + justify-content: space-between; +} +.pages { + padding: 20px 0; + display: flex; + justify-content: right; +} +.tableC { + margin: 0 10%; +} +.topTitle { + background-color: #fff; + padding: 20px 0px 20px 0px; +} +</style> diff --git a/src/views/goalManagement/targetDecompositionYear/component/Dailog.vue b/src/views/goalManagement/targetDecompositionYear/component/Dailog.vue new file mode 100644 index 0000000..c728ad6 --- /dev/null +++ b/src/views/goalManagement/targetDecompositionYear/component/Dailog.vue @@ -0,0 +1,262 @@ +<template> + <el-dialog v-model="dialogVisible" :before-close="resetForm" :fullscreen="full" title="目标分解" width="60%" draggable> + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-form :model="form" label-width="120px"> + <el-row> + <el-col :span="11"> + <el-form-item label="安全目标指标" size="default"> + <el-input v-model="form.qName" :disabled="disabled"> + <template #append> + <el-button :icon="Search" @click="daiInpt" /> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="目标指标编号" size="default"> + <el-input v-model="form.indexNum" disabled /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="11"> + <el-form-item label="年度" size="default"> + <el-input v-model="form.year" disabled /> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="指标值" size="default"> + <el-input v-model="form.value" disabled /> + </el-form-item> + </el-col> + </el-row> + </el-form> + <el-tabs v-model="activeName" class="demo-tabs"> + <el-tab-pane label="目标指标分解" name="1"> + <el-button type="primary" size="default" @click="daiAdd('新增')" :disabled="disabled">新增</el-button> + </el-tab-pane> + </el-tabs> + <el-table :data="formUp.targetDivideDetailList" style="width: 100%"> + <el-table-column align="center" property="dutyDepartmentName" label="责任部门" width="180" /> + <el-table-column align="center" property="value" label="考核指标" width="180" /> + <el-table-column align="center" property="makerDepartmentName" label="制定人部门" /> + <el-table-column align="center" property="makeDate" :formatter="timeDate" label="制定日期" /> + <el-table-column align="center" property="commitPersonName" label="上报人" /> + <el-table-column align="center" label="操作"> + <template #default="scope"> + <el-button link type="primary" @click="daiAdd('查看', scope.row)">查看</el-button> + <el-button link :disabled="disabled" type="primary" @click="daiAdd('修改', scope.row)">修改</el-button> + <el-button link :disabled="disabled" type="primary" @click="Delete(scope.row)">删除</el-button> + </template> + </el-table-column> + </el-table> + <template #footer> + <span class="dialog-footer"> + <el-button @click="resetForm" size="default">关闭</el-button> + <el-button type="primary" v-if="disabled == false" @click="submitForm" size="default">确定</el-button> + </span> + </template> + </el-dialog> + <DailogAdd ref="Show" @onAdd="add"></DailogAdd> + <DailogSearch ref="Shows" @backNum="onNumber"></DailogSearch> +</template> +<script lang="ts"> +import { defineComponent, ref, reactive } from 'vue'; +import { timeDate } from '/@/assets/index.ts'; +import { Search, FullScreen } from '@element-plus/icons-vue'; +import DailogAdd from './DailogAdd.vue'; +import { ElMessageBox, ElMessage, ElButton, ElInput, TabsPaneContext } from 'element-plus'; +import DailogSearch from '../../../../components/DailogSearch/DailogSearch.vue'; +import { goalManagementApi } from '/@/api/goalManagement'; +import { emit } from 'process'; +import { deepClone } from '/@/utils/other'; +export default defineComponent({ + components: { DailogAdd, DailogSearch }, + setup(props, { emit }) { + const dialogVisible = ref<boolean>(false); + const form = ref({ + qName: '', + indexNum: '', + year: '', + value: '', + targetDivideDetailList: [], + }); + const targetType = ref(); + const disabled = ref(false); + const titles = ref(); + const openDailog = (title: string, type: any, id: number) => { + dialogVisible.value = true; + titles.value = title; + targetType.value = type; + disabled.value = title == '查看' ? true : false; + if (title == '查看' || title == '修改') { + goalManagementApi() + .getTargetMngDetail(id) + .then((res) => { + if (res.data.code == 200) { + form.value = res.data.data; + formUp.targetDivideDetailList = form.value.targetDivideDetailList; + for(let i=0;i<formUp.targetDivideDetailList.length;i++){ + formUp.targetDivideDetailList[i].makeDate=timeC(formUp.targetDivideDetailList[i].makeDate) + } + } else { + ElMessage.error(res.data.msg); + } + }); + } + }; + const timeC = (timestamp: any) => { + let a = new Date(timestamp).getTime(); + const date = new Date(a); + const Y = date.getFullYear() + '-'; + const M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-'; + const D = (date.getDate() < 10 ? '0' + date.getDate() : date.getDate()) + ' '; + const h = (date.getHours() < 10 ? '0' + date.getHours() : date.getHours()) + ':'; + const m = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes(); + const s = date.getSeconds(); // 秒 + const dateString = Y + M + D + h + m +`:${s}`; + // console.log('dateString', dateString); // > dateString 2021-07-06 14:23 + return dateString; + }; + const onNumber = (val: object) => { + form.value = val; + }; + // 导航 + const activeName = ref('1'); + // 表格 + const tableData = ref([]); + // 新增弹窗 + const index = ref<any>(); + const Show = ref(); + const daiAdd = (title: string, data: any) => { + index.value = formUp.targetDivideDetailList.indexOf(data); + Show.value.openDailog(title, data); + }; + const formUp = reactive({ + targetId: '', //关联的目标指标/外键 + delTargetDivideDetails: '', //要删除的目标指标分解ID,多个用逗号隔开 + targetDivideDetailList: [], //目标指标分解列表 + }); + + const add = (val: any) => { + const item = deepClone(val); + console.log(item) + if (index.value == -1) { + formUp.targetDivideDetailList.push(item); + } else { + formUp.targetDivideDetailList[index.value] = item; + } + + // let obj=JSON.parse(JSON.stringify(form.value)) + }; + // 新增 + const submitForm = () => { + formUp.delTargetDivideDetails = arr.value.toString(); + formUp.targetId = form.value.id; + dialogVisible.value = false; + for(let i=0;i<formUp.targetDivideDetailList.length;i++){ + delete formUp.targetDivideDetailList[i].dutyDepartmentName + delete formUp.targetDivideDetailList[i].makerDepartmentName + } + goalManagementApi() + .gettargetDivideDetail(formUp) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + message: res.data.msg, + type: 'success', + }); + emit('addList'); + } else { + ElMessage.error(res.data.msg); + } + }); + form.value = { + qName: '', + indexNum: '', + year: '', + value: '', + targetDivideDetailList: [], + }; + tableData.value = []; + formUp.targetId = ''; + formUp.delTargetDivideDetails = ''; + formUp.targetDivideDetailList = []; + }; + const arr = ref([]); + // 删除 + const Delete = (data: any) => { + formUp.targetDivideDetailList.splice(form.value.targetDivideDetailList.indexOf(data), 1); + formUp.targetId = data.targetId; + arr.value.push(data.id); + }; + // 安全目标指标弹窗 + const Shows = ref(); + const daiInpt = () => { + Shows.value.openDailog(targetType.value); + }; + // 关闭 + const resetForm = () => { + dialogVisible.value = false; + form.value = { + qName: '', + indexNum: '', + year: '', + value: '', + targetDivideDetailList: [], + }; + tableData.value = []; + formUp.targetId = ''; + formUp.delTargetDivideDetails = ''; + formUp.targetDivideDetailList = []; + }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + // 时间格式处理 + // const timeDate = (data: any) => { + // let result = new Date(data).getTime(); + // return result; + // }; + return { + timeC, + index, + timeDate, + arr, + form, + dialogVisible, + openDailog, + activeName, + tableData, + Show, + daiAdd, + Shows, + daiInpt, + Search, + full, + toggleFullscreen, + FullScreen, + onNumber, + targetType, + disabled, + resetForm, + titles, + add, + formUp, + submitForm, + Delete, + }; + }, +}); +</script> +<style scoped> +.el-row { + padding: 0 0 20px 0; +} +</style> diff --git a/src/views/goalManagement/targetDecompositionYear/component/DailogAdd.vue b/src/views/goalManagement/targetDecompositionYear/component/DailogAdd.vue new file mode 100644 index 0000000..52680b0 --- /dev/null +++ b/src/views/goalManagement/targetDecompositionYear/component/DailogAdd.vue @@ -0,0 +1,308 @@ +<template> + <el-dialog v-model="dialogVisible" :fullscreen="full" :title="titles" width="50%" draggable @close="resetForm(ruleFormRef)"> + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-form :model="form" :disabled="disabled" label-width="120px" ref="ruleFormRef" :rules="rules"> + <el-row> + <el-col :span="11"> + <el-form-item label="目标分类" prop="targetTypeId" size="default"> + <el-select v-model="form.targetTypeId" class="m-2" placeholder="请选择" style="width:100%"> + <el-option v-for="item in options" :key="item.id" :label="item.typeName" :value="item.id" /> + </el-select> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="责任人" prop="dutyPersonName" size="default"> + <el-input v-model="form.dutyPersonName"> + <template #append> <el-button :icon="Search" @click="openUser(1)" /> </template + ></el-input> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="11"> + <el-form-item label="责任部门" prop="dutyDepartmentId" size="default"> + <el-tree-select + v-model="form.dutyDepartmentId" + check-strictly="true" + @current-change="dutyName" + :data="data" + class="w100" + :props="propse" + placeholder="请选择" + /> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="考核指标" prop="value" size="default"> + <el-input v-model.number="form.value" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="11"> + <el-form-item label="制定人部门" prop="makerDepartmentId" size="default"> + <el-tree-select + v-model="form.makerDepartmentId" + :data="data" + @current-change="makerName" + check-strictly="true" + class="w100" + :props="propse" + placeholder="请选择" + /> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="制定日期" prop="makeDate" size="default"> + <el-date-picker + v-model="form.makeDate" + format="YYYY-MM-DD HH:mm:ss" + value-format="YYYY-MM-DD HH:mm:ss" + type="datetime" + placeholder="请选择" + style="width: 100%" + /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="11"> + <el-form-item label="上报人" prop="commitPersonName" size="default"> + <el-input v-model="form.commitPersonName"> + <template #append> <el-button :icon="Search" @click="openUser(2)" /> </template + ></el-input> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="计划措施" prop="commitPersonName" size="default"> + <el-input v-model="form.planDesc"></el-input> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="resetForm(ruleFormRef)" size="default">关闭</el-button> + <el-button type="primary" @click="submitForm(ruleFormRef)" :disabled="disabled" size="default">确定</el-button> + </span> + </template> + </el-dialog> + <DailogSearchUser ref="Show" @SearchUser="onUser"></DailogSearchUser> +</template> +<script lang="ts"> +import { defineComponent, ref, reactive, onMounted } from 'vue'; +import { Search, FullScreen } from '@element-plus/icons-vue'; +import type { FormInstance, FormRules } from 'element-plus'; +import DailogSearchUser from '../../../../components/DailogSearchUser/index.vue'; +import { ElMessageBox, ElMessage, ElButton, ElInput, TabsPaneContext } from 'element-plus'; +import { goalManagementApi } from '/@/api/goalManagement'; +export default defineComponent({ + components: { DailogSearchUser }, + setup(props, { emit }) { + const ruleFormRef = ref<FormInstance>(); + const form = ref({ + dutyDepartmentId: '', ////责任部门/外键 + makerDepartmentId: '', ////制定人部门/外键 + commitPersonId: '', ////上报人/外键 + commitPersonName: '', + value: '', ////考核指标值 + makeDate: '', ////制定日期 + targetTypeId: '', ///目标分类 + dutyPersonId: '', ///责任人id + dutyPersonName: '', ///责任人 + planDesc: '', ///计划措施 + }); + //部门 + const department = () => { + goalManagementApi() + .getTreedepartment() + .then((res) => { + if (res.data.code == 200) { + data.value = res.data.data; + } else { + ElMessage.error(res.data.msg); + } + }); + }; + const propse = { + label: 'depName', + children: 'children', + value: 'depId', + }; + onMounted(() => { + department(); + allList() + }); + const disabled = ref(false); + // 开启弹窗 + const titles = ref(); + const dialogVisible = ref(false); + const openDailog = (title: string, data: any) => { + titles.value = `${title}目标指标分解`; + if (title == '查看') { + disabled.value = true; + form.value = data; + } else if (title == '修改') { + disabled.value = false; + form.value = data; + } else { + disabled.value = false; + } + dialogVisible.value = true; + }; + // 分类 All + const allList=()=>{ + goalManagementApi().gettargetClassAll({}).then(res=>{ + if(res.data.code==200){ + options.value=res.data.data + }else{ + ElMessage.error(res.data.msg); + } + }) + } + // 开启用户弹窗 + const Show = ref(); + const openUser = (type:any) => { + Show.value.openDailog(type); + }; + const rules = reactive<FormRules>({ + targetTypeId: [ + { + required: true, + message: '目标分类不能为空', + trigger: 'blur', + }, + ], + dutyPersonName: [ + { + required: true, + message: '责任人不能为空', + trigger: 'blur', + }, + ], + dutyDepartmentId: [ + { + required: true, + message: '责任部门不能为空', + trigger: 'blur', + }, + ], + makerDepartmentId: [ + { + required: true, + message: '制定人部门不能为空', + trigger: 'blur', + }, + ], + commitPersonId: [ + { + required: true, + message: '上报人不能为空', + trigger: 'blur', + }, + ], + value: [ + { + required: true, + message: '考核指标值不能为空', + trigger: 'blur', + }, + { + type: 'number', + message: '考核指标值只能为数字类型', + trigger: 'blur', + }, + ], + makeDate: [ + { + required: true, + message: '制定日期不能为空', + trigger: 'blur', + }, + ], + commitPersonName: [], + }); + const submitForm = async (formEl: FormInstance | undefined) => { + if (!formEl) return; + await formEl.validate((valid, fields) => { + if (valid) { + emit('onAdd', form.value); + dialogVisible.value = false; + // handleClose(formEl) + } else { + console.log('error submit!', fields); + } + }); + }; + + const resetForm = (formEl: FormInstance | undefined) => { + // console.log(formEl); + if (!formEl) return; + formEl.clearValidate(); + dialogVisible.value = false; + form.value = {}; + }; + // const handleClose = (formEl: any) => { + // formEl.resetFields(); + // }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + const data = ref(); + const onUser = (e: any, type: any) => { + console.log(e); + if (type == 1) { + form.value.dutyPersonId = e.uid; + form.value.dutyPersonName = e.realName; + } else if (type == 2) { + form.value.commitPersonId = e.uid; + form.value.commitPersonName = e.realName; + } + }; + const makerName = (data: any) => { + form.value.makerDepartmentName = data.depName; + }; + const dutyName = (data: any) => { + form.value.dutyDepartmentName = data.depName; + }; + const options = ref([]); + return { + options, + allList, + disabled, + makerName, + dutyName, + titles, + // handleClose, + form, + propse, + department, + dialogVisible, + openDailog, + Show, + openUser, + Search, + full, + toggleFullscreen, + FullScreen, + data, + onUser, + ruleFormRef, + rules, + submitForm, + resetForm, + }; + }, +}); +</script> +<style scoped> +.el-row { + padding: 0 0 20px 0; +} +</style> diff --git a/src/views/goalManagement/targetDecompositionYear/index.vue b/src/views/goalManagement/targetDecompositionYear/index.vue new file mode 100644 index 0000000..e840ca6 --- /dev/null +++ b/src/views/goalManagement/targetDecompositionYear/index.vue @@ -0,0 +1,284 @@ +<template> + <div> + <el-form :model="ruleForm" status-icon label-width="20px" class="topTitle"> + <el-row> + <el-col :span="4"> + <el-form-item> + <el-input v-model="ruleForm.searchParams.qName" size="default" placeholder="安全目标指标" /> + </el-form-item> + </el-col> + <el-col :span="4"> + <el-form-item> + <el-input v-model="ruleForm.searchParams.indexNum" size="default" placeholder="目标指标编号" /> + </el-form-item> + </el-col> + <el-col :span="16"> + <el-form-item> + <el-button type="primary" size="default" @click="listApi">查询</el-button> + <el-button size="default" @click="resetForm">重置</el-button> + </el-form-item> + </el-col> + </el-row> + </el-form> + <div class="minCenter"> + <div class="btns"> + <div> + <!--<el-button size="default" type="primary" :icon="Plus" @click="openD('新建')">新建</el-button>--> + <el-button size="default" type="warning" :disabled="warning" :icon="EditPen" plain + @click="openD('修改', deletAll[0])">修改</el-button> + <el-button size="default" type="danger" :disabled="danger" :icon="Delete" plain @click="onDeleteAll">删除</el-button> + </div> + </div> + <el-table ref="multipleTableRef" :data="tableData" @selection-change="handleSelectionChange" style="width: 100%"> + <el-table-column label="序号" align="center" type="index" width="70" /> + <el-table-column type="selection" align="center" width="55" /> + <el-table-column type="expand"> + <template #default="scope"> + <div class="tableC"> + <el-tabs v-model="activeNames"> + <el-tab-pane label="目标指标分解" name="1"> + <el-table :data="scope.row.targetDivideDetailList" style="width: 100%"> + <el-table-column align="center" prop="dutyDepartmentName" label="责任部门" /> + <el-table-column align="center" prop="value" label="考核指标" /> + <el-table-column align="center" prop="makerDepartmentName" label="制定人部门" /> + <el-table-column align="center" prop="makeDate" :formatter="timeDate" label="制定日期" /> + <el-table-column align="center" prop="commitPersonName" label="上报人" /> + </el-table> + </el-tab-pane> + </el-tabs> + </div> + </template> + </el-table-column> + <el-table-column label="安全目标指标" align="center" property="qName" sortable /> + <el-table-column property="indexNum" align="center" label="目标指标编号" sortable /> + <el-table-column property="year" label="年度" align="center" sortable show-overflow-tooltip /> + <el-table-column property="value" label="指标值" align="center" sortable show-overflow-tooltip /> + <el-table-column label="操作" align="center" sortable show-overflow-tooltip> + <template #default="scope"> + <el-button link type="primary" size="small" :icon="View" @click="openD('查看', scope.row.id)">查看</el-button> + <el-button link type="primary" size="small" :icon="EditPen" @click="openD('修改', scope.row.id)">修改</el-button> + <el-button link type="primary" size="small" :icon="Delete" @click="onDelete(scope.row.id)">删除</el-button> + </template> + </el-table-column> + </el-table> + <div class="pages"> + <el-pagination + v-model:currentPage="currentPage4" + v-model:page-size="pageSize4" + :page-sizes="[10, 20, 30, 40]" + layout="total, sizes, prev, pager, next, jumper" + :total="total" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + </div> + <Dailog ref="Show" @addList="add"></Dailog> + </div> +</template> +<script lang="ts"> +import { timeDate } from '/@/assets/index.ts'; +import Dailog from './component/Dailog.vue'; +import { ref, toRefs, reactive, onMounted, defineComponent } from 'vue'; +import { ElMessageBox, ElMessage, ElButton, ElInput, TabsPaneContext, FormInstance } from 'element-plus'; +import { Plus, Delete, Upload, Download, Refresh, View, EditPen } from '@element-plus/icons-vue'; +import { goalManagementApi } from '/@/api/goalManagement'; +export default defineComponent({ + components: { ElButton, ElInput, Dailog }, + setup() { + // 搜索条件 + const ruleForm = reactive({ + pageSize: 10, + pageIndex: 1, + searchParams: { + qName: '', ////安全目标指标 + indexNum: '', ////目标指标编号 + targetType: '1', ////指标类型 1:年指标 2:月指标 + divideStatus: '', ////分解状态 1:已分解 2:未分解 + }, + }); + // 下方导航与表格 + const tableData = ref([]); + const currentPage4 = ref(); + const pageSize4 = ref(); + const total = ref(); + const resetForm = () => { + ruleForm.searchParams.qName = ''; + ruleForm.searchParams.indexNum = ''; + listApi() + }; + const listApi = () => { + goalManagementApi() + .getTargetMngList(ruleForm) + .then((res) => { + if (res.data.code == 200) { + tableData.value = res.data.data; + currentPage4.value = res.data.pageIndex; + pageSize4.value = res.data.pageSize; + total.value = res.data.total; + } else { + ElMessage.error(res.data.msg); + } + }); + }; + onMounted(() => { + listApi(); + }); + + const handleSizeChange = (val: number) => { + // console.log(`${val} items per page`); + ruleForm.pageSize = val; + listApi(); + }; + const handleCurrentChange = (val: number) => { + // console.log(`current page: ${val}`); + ruleForm.pageIndex = val; + listApi(); + }; + const activeNames = ref('1'); + // 打开弹窗 + const Show = ref(); + const openD = (title: String, id: number) => { + Show.value.openDailog(title,ruleForm.searchParams.targetType, id); + }; + // 删除 + const onDelete = (id: number) => { + let arr=[] + arr.push(id) + ElMessageBox.confirm('确定删除所选项吗?', 'Warning', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + goalManagementApi() + .getTargetMngDelete(arr) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + message: res.data.msg, + type: 'success', + }); + listApi(); + } else { + ElMessage.error(res.data.msg); + } + }); + }) + .catch(() => { + // ElMessage({ + // type: 'info', + // message: 'Delete canceled', + // }); + }); + }; + // 批量删除 + const warning = ref(true); + const danger = ref(true); + const deletAll = ref(); + const handleSelectionChange = (val: any) => { + let valId = JSON.parse(JSON.stringify(val)); + let arr = []; + for (let i = 0; i < valId.length; i++) { + arr.push(valId[i].id); + } + deletAll.value = arr + if (val.length == 1) { + warning.value = false; + danger.value = false; + } else if (val.length == 0) { + warning.value = true; + danger.value = true; + } else { + warning.value = true; + danger.value = false; + } + }; + const onDeleteAll = () => { + ElMessageBox.confirm('确定删除所选项吗?', 'Warning', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + goalManagementApi() + .getTargetMngDelete(deletAll.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + message: res.data.msg, + type: 'success', + }); + listApi(); + } else { + ElMessage.error(res.data.msg); + } + }); + }) + .catch(() => { + ElMessage({ + type: 'info', + message: 'Delete canceled', + }); + }); + }; + const add=()=>{ + listApi() + } + return { + timeDate, + listApi, + add, + resetForm, + tableData, + currentPage4, + pageSize4, + total, + ruleForm, + handleSizeChange, + handleCurrentChange, + Show, + openD, + activeNames, + onDelete, + warning, + danger, + deletAll, + handleSelectionChange, + onDeleteAll, + Plus, + Delete, + Upload, + Download, + Refresh, + View, + EditPen, + }; + }, +}); +</script> +<style scoped> +.topTitle { + background-color: #fff; + padding: 20px 0px 20px 0px; +} +.minCenter { + width: 100%; + background-color: #fff; + margin-top: 10px; + padding: 0 20px; +} +.btns { + padding: 0px 0px 10px 0px; + display: flex; + justify-content: space-between; +} +.pages { + padding: 20px 0; + display: flex; + justify-content: right; +} +.tableC { + margin: 0 10%; +} +</style> diff --git a/src/views/goalManagement/targetEscalation/component/Dailog.vue b/src/views/goalManagement/targetEscalation/component/Dailog.vue new file mode 100644 index 0000000..bf223b6 --- /dev/null +++ b/src/views/goalManagement/targetEscalation/component/Dailog.vue @@ -0,0 +1,65 @@ +<template> + <el-dialog v-model="dialogVisible" :fullscreen="full" title="查看审批流程" width="50%" draggable> + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-table :data="tableData" style="width: 100%"> + <el-table-column property="workName" label="审批人" sortable></el-table-column> + <el-table-column property="title" label="审批标题" sortable></el-table-column> + <el-table-column property="approvePersonName" label="编写人" sortable></el-table-column> + <el-table-column property="approveMemo" label="审批意见" sortable></el-table-column> + </el-table> + <template #footer> + <span class="dialog-footer"> + <el-button @click="dialogVisible = false">关闭</el-button> + <!-- <el-button type="primary" @click="dialogVisible = false">确定</el-button> --> + </span> + </template> + </el-dialog> +</template> +<script lang="ts"> +import { defineComponent, reactive, ref } from 'vue'; +import { FullScreen } from '@element-plus/icons-vue'; +import { goalManagementApi } from '/@/api/goalManagement'; +export default defineComponent({ + setup() { + const dialogVisible = ref(false); + const form = ref({ + pageSize: 10, + pageIndex: 1, + searchParams: { + relateId: '', ////检查记录ID + relateType:"", + gmtCreate:[], + }, + }); + const tableData = ref(); + const openDailog = (data: any,type:number) => { + dialogVisible.value = true; + form.value.searchParams.relateId=data + form.value.searchParams.relateType=type + goalManagementApi().getworkApproveListCode(form.value).then(res=>{ + if(res.data.code==200){ + tableData.value=res.data.data + } + }) + }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + return { + dialogVisible, + tableData, + openDailog, + full, + toggleFullscreen, + form, + FullScreen, + }; + }, +}); +</script> diff --git a/src/views/goalManagement/targetEscalation/component/TypeDailog.vue b/src/views/goalManagement/targetEscalation/component/TypeDailog.vue new file mode 100644 index 0000000..02c9afb --- /dev/null +++ b/src/views/goalManagement/targetEscalation/component/TypeDailog.vue @@ -0,0 +1,341 @@ +<template> + <el-dialog :title="titleName" v-model="dialogVisible" @click="resetForm" width="70%" draggable :fullscreen="full" :close-on-click-modal="false"> + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-form ref="ruleFormRef" :model="form" size="default" :disabled="disabled" label-width="120px"> + <div v-if="titleName == '发起审批'"> + <el-row> + <el-col :span="11"> + <el-form-item label="审批名称" prop="workName" size="default"> + <el-input v-model="form.workName" :disabled="disabledT" placeholder="请填写名称"></el-input> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="审批标题" prop="title" size="default"> + <el-input v-model="form.title" :disabled="disabledT" placeholder="请填写标题"></el-input> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="11"> + <el-form-item label="审批人" prop="approvePersonId" size="default"> + <el-input v-model="form.approvePersonName" :disabled="disabledT" placeholder="请选择" class="input-with-select"> + <template #append> + <el-button :icon="Search" @click="openUser" /> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"></el-col> + </el-row> + </div> + <div v-if="titleName != '发起审批'"> + <el-row> + <el-col :span="11"> + <el-form-item label="审批名称" prop="workName" size="default"> + <el-input v-model="formUp.workName" :disabled="disabledT" placeholder="请填写名称"></el-input> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="审批标题" prop="title" size="default"> + <el-input v-model="formUp.title" :disabled="disabledT" placeholder="请填写标题"></el-input> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="11"> + <el-form-item label="审批人" prop="approvePersonId" size="default"> + <el-input v-model="formUp.approvePersonName" :disabled="disabledT" placeholder="请选择" class="input-with-select"> + <template #append> + <el-button :icon="Search" @click="openUser" /> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"></el-col> + </el-row> + </div> + <el-table :data="tableData" style="width: 90%;margin:20px auto"> + <el-table-column align="center" type="index" label="序号" width="80" /> + <el-table-column align="center" prop="makerDepartmentName" label="责任部门" /> + <el-table-column align="center" prop="value" label="考核指标" /> + <el-table-column align="center" prop="dutyDepartmentName" label="制定部门" /> + <el-table-column align="center" prop="makeDate" :formatter="timeDate" label="制定日期" /> + <el-table-column align="center" label="检查值"> + <template #default="scope"> + <el-input v-model="scope.row.commitValue" :disabled="disabledType" /> + </template> + </el-table-column> + <el-table-column align="center" label="检查人"> + <template #default="scope"> + <el-input v-model="scope.row.personName" :disabled="disabledType"> + <template #append> <el-button :icon="Search" @click="openUsers(scope.row)" /> </template + ></el-input> + </template> + </el-table-column> + </el-table> + <div v-if="typeScope"> + <el-row> + <el-col> + <el-form-item label="审批结果" prop="authorUid"> + <el-radio-group :disabled="disabled" v-model="form.approveResult"> + <el-radio :label="0">不通过</el-radio> + <el-radio :label="1">通过</el-radio> + </el-radio-group> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="24"> + <el-form-item label="审批意见" prop="approveMemo"> + <el-input v-model="form.approveMemo" :disabled="disabled" type="textarea" placeholder="请填写审批意见"></el-input> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="24"> + <el-form-item label="是否完成" prop="complete"> + <el-radio-group v-model="form.approveStatus" :disabled="disabled"> + <el-radio :label="3">是</el-radio> + <el-radio :label="2">否</el-radio> + </el-radio-group> + </el-form-item> + </el-col> + </el-row> + <div v-if="form.approveStatus == 2"> + <el-row> + <el-col :span="11"> + <el-form-item label="审批名称" prop="workName" size="default"> + <el-input v-model="form.workName" placeholder="请填写名称"></el-input> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="审批标题" prop="title" size="default"> + <el-input v-model="form.title" placeholder="请填写标题"></el-input> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="11"> + <el-form-item label="审批人" prop="approvePersonId" size="default"> + <el-input v-model="form.approvePersonName" placeholder="请选择" class="input-with-select"> + <template #append> + <el-button :icon="Search" @click="openUser" /> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"></el-col> + </el-row> + </div> + </div> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="resetForm" size="default">关闭</el-button> + <el-button size="default" type="primary" :disabled="disabled" @click="submitForm">确定</el-button> + </span> + </template> + </el-dialog> + <DailogSearchUserManger ref="userRef" @SearchUser="onUser" /> + <DailogSearchUser ref="Show" @SearchUser="onUsers"></DailogSearchUser> +</template> +<script lang="ts"> +import { ref, defineComponent } from 'vue'; +import { timeDate } from '/@/assets/index.ts'; +import DailogSearchUserManger from '/@/components/DailogSearchUserManger/index.vue'; +import { ElMessage } from 'element-plus'; +import DailogSearchUser from '../../../../components/DailogSearchUser/index.vue'; +import { goalManagementApi } from '/@/api/goalManagement'; +import { Search, FullScreen } from '@element-plus/icons-vue'; +export default defineComponent({ + components: { DailogSearchUserManger, DailogSearchUser }, + setup(props, { emit }) { + const dialogVisible = ref(false); + const form = ref({ + workName: '', // 审批名称 + title: '', //审批标题 + approvePersonId: '', + approvePersonName: '', + approveStatus: "", + approveResult: '', + relateType: 1, + relateId: '', + relateDesc: '', + }); + // 提交 + const submitForm = () => { + if (titleName.value == '发起审批') { + let arr = []; + for (let i = 0; i < tableData.value.length; i++) { + arr.push({ + id: tableData.value[i].id, + value: tableData.value[i].commitValue, + personName: tableData.value[i].personName, + personId: tableData.value[i].personId, + }); + } + form.value.approveStatus=2 + form.value.relateDesc = JSON.stringify(arr); + goalManagementApi() + .getworkApproveAdd(form.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'success', + }); + emit('onType'); + } else { + ElMessage.error(res.data.msg); + } + }); + } else if (titleName.value == '审批') { + goalManagementApi() + .getworkApproveUpdata(form.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + showClose: true, + message: res.data.msg, + type: 'success', + }); + emit('onType'); + } else { + ElMessage.error(res.data.msg); + } + }); + } + dialogVisible.value = false; + disabled.value = false; + disabledT.value = false; + form.value = {}; + formUp.value = {}; + }; + // 关闭 + const resetForm = () => { + disabled.value = false; + disabledT.value = false; + form.value = {}; + formUp.value = {}; + tableData.value=[]; + dialogVisible.value = false; + }; + const titleName = ref(); + const typeScope = ref(); + const disabledT = ref(false); + const disabled = ref(false); + const formUp = ref({ + workName: '', + title: '', + approvePersonName: '', + }); + const tableData = ref([]); + const disabledType=ref() + // 打开弹窗 + const openDialog = (title: string, name: any, id: number, type: number,data:any) => { + dialogVisible.value = true; + titleName.value = title; + form.value.relateType = type; + if (title == '发起审批') { + form.value.relateId = id; + typeScope.value = false; + goalManagementApi() + .getTargetMngDetail(id) + .then((res) => { + if (res.data.code == 200) { + tableData.value = res.data.data.targetDivideDetailList; + } else { + ElMessage.error(res.data.msg); + } + }); + disabledType.value=false + } else if (title == '审批' || title == '查看审批') { + goalManagementApi() + .getworkApproveDetail(id) + .then((res) => { + if (res.data.code == 200) { + if (data.approveStatus==2&&data.checkApprove==true){ + disabled.value = false; + } else if(data.approveStatus==2&&data.checkApprove==false) { + disabled.value = true; + } + form.value = res.data.data; + form.value.approveStatus = ''; + formUp.value.workName = form.value.workName; + formUp.value.title = form.value.title; + formUp.value.approvePersonName = form.value.approvePersonName; + form.value.workName="" + form.value.title="" + form.value.approvePersonName="" + tableData.value=res.data.data.targetDivideDetailList + console.log(form.value.approvePersonName) + } + }); + disabledType.value=true + typeScope.value = true; + disabledT.value = true; + } + }; + // 打开用户选择弹窗 + const userRef = ref(); + const openUser = () => { + userRef.value.openDailog(); + }; + const index = ref(); + const Show = ref(); + const openUsers = (id: any) => { + index.value = tableData.value.indexOf(id); + Show.value.openDailog(); + }; + const onUser = (val: any) => { + form.value.approvePersonId = val[0].uid; + form.value.approvePersonName = val[0].realName; + }; + const onUsers = (val: any) => { + tableData.value[index.value].personName = val.realName; + tableData.value[index.value].personId = val.uid; + }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + return { + disabledType, + index, + Show, + onUsers, + openUsers, + formUp, + timeDate, + tableData, + onUser, + dialogVisible, + form, + disabledT, + submitForm, + resetForm, + titleName, + typeScope, + disabled, + openDialog, + userRef, + openUser, + full, + toggleFullscreen, + Search, + FullScreen, + }; + }, +}); +</script> +<style> +.el-row { + padding-bottom: 20px; +} +</style> \ No newline at end of file diff --git a/src/views/goalManagement/targetEscalation/index.vue b/src/views/goalManagement/targetEscalation/index.vue new file mode 100644 index 0000000..22535be --- /dev/null +++ b/src/views/goalManagement/targetEscalation/index.vue @@ -0,0 +1,199 @@ +<template> + <div> + <el-form :model="ruleForm" status-icon label-width="20px" class="topTitle"> + <el-row> + <el-col :span="4"> + <el-form-item> + <el-input v-model="ruleForm.searchParams.qName" size="default" placeholder="安全目标指标" /> + </el-form-item> + </el-col> + <el-col :span="4"> + <el-form-item> + <el-input v-model="ruleForm.searchParams.indexNum" size="default" placeholder="目标指标编号" /> + </el-form-item> + </el-col> + <el-col :span="16"> + <el-form-item> + <el-button type="primary" size="default" @click="listApi">查询</el-button> + <el-button size="default" @click="resetForm">重置</el-button> + </el-form-item> + </el-col> + </el-row> + </el-form> + <div class="minCenter"> + <el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick"> + <el-tab-pane label="检查" name="1"> </el-tab-pane> + <el-tab-pane label="上报" name="2"></el-tab-pane> + </el-tabs> + <el-table ref="multipleTableRef" :data="tableData" style="width: 100%"> + <el-table-column label="安全目标指标" align="center" property="qName" sortable /> + <el-table-column property="indexNum" align="center" label="目标指标编号" sortable /> + <el-table-column property="year" label="年度" align="center" sortable show-overflow-tooltip /> + <el-table-column property="value" label="指标值" align="center" sortable show-overflow-tooltip /> + <el-table-column v-if="activeName == 1" label="操作" align="center" show-overflow-tooltip> + <template #default="scope"> + <el-button link type="primary" size="default" :icon="EditPen" v-if="scope.row.approveStatus==null" @click="TypeDailog('发起审批','检查',scope.row.id,1)">发起审批</el-button> + <el-button link type="primary" size="default" :icon="EditPen" v-if="scope.row.approveStatus==2&&scope.row.checkApprove==true" @click="TypeDailog('审批',scope.row.id,scope.row.approveId,1,scope.row)">审批</el-button> + <el-button link type="primary" size="default" :icon="EditPen" v-if="scope.row.approveStatus==2&&scope.row.checkApprove==false" @click="TypeDailog('查看审批',scope.row.id,scope.row.approveId,1,scope.row)">查看审批</el-button> + <el-button link type="primary" size="default" :icon="EditPen" v-if="scope.row.approveStatus==3" @click="openDai(scope.row.id,1)" >查看审批流程</el-button> + </template> + </el-table-column> + <el-table-column v-if="activeName == 2" label="操作" align="center" show-overflow-tooltip> + <template #default="scope"> + <el-button link type="primary" size="default" :icon="EditPen" v-if="scope.row.approveStatus==null" @click="TypeDailog('发起审批','检查',scope.row.id,2)">发起审批</el-button> + <el-button link type="primary" size="default" :icon="EditPen" v-if="scope.row.approveStatus==2&&scope.row.checkApprove==true" @click="TypeDailog('审批',scope.row.id,scope.row.approveId,2,scope.row)">审批</el-button> + <el-button link type="primary" size="default" :icon="EditPen" v-if="scope.row.approveStatus==2&&scope.row.checkApprove==false" @click="TypeDailog('查看审批',scope.row.id,scope.row.approveId,2,scope.row)">查看审批</el-button> + <el-button link type="primary" size="default" :icon="EditPen" v-if="scope.row.approveStatus==3" @click="openDai(scope.row.id,2)" >查看审批流程</el-button> + </template> + </el-table-column> + </el-table> + <div class="pages"> + <el-pagination + v-model:currentPage="currentPage4" + v-model:page-size="pageSize4" + :page-sizes="[10, 20, 30, 40]" + layout="total, sizes, prev, pager, next, jumper" + :total="total" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + </div> + <Dailog ref="Show"></Dailog> + <TypeDailog ref="TypeD" @onType="typeAlign" /> + </div> +</template> +<script lang="ts"> +import Dailog from './component/Dailog.vue'; +import TypeDailog from './component/TypeDailog.vue'; +import { ref, toRefs, reactive, onMounted, defineComponent } from 'vue'; +import { ElMessageBox, ElMessage, ElButton, ElInput, TabsPaneContext, FormInstance } from 'element-plus'; +import { Plus, Delete, Upload, Download, Refresh, View, EditPen } from '@element-plus/icons-vue'; +import { useRouter } from 'vue-router'; +import { goalManagementApi } from '/@/api/goalManagement'; +export default defineComponent({ + components: { ElButton, ElInput, Dailog,TypeDailog }, + setup() { + // 搜索条件 + const ruleForm = reactive({ + pageSize: 10, + pageIndex: 1, + searchParams: { + qName: '', ////安全目标指标 + indexNum: '', ////目标指标编号 + targetType: 1, ////指标类型 1:年指标 2:月指标 + divideStatus: 1, ////分解状态 1:已分解 2:未分解 + relateType: 1, ////关联业务类型 1:目标检查 2:目标上报 + }, + }); + // 重置 + const resetForm = () => { + ruleForm.searchParams.qName = ''; + ruleForm.searchParams.indexNum = ''; + }; + const listApi = () => { + goalManagementApi() + .getworkApproveList(ruleForm) + .then((res) => { + if (res.data.code == 200) { + tableData.value = res.data.data; + currentPage4.value = res.data.pageIndex; + pageSize4.value = res.data.pageSize; + total.value = res.data.total; + } else { + ElMessage.error(res.data.msg); + } + }); + }; + // + const handleClick = (val: any) => { + // let targetType = JSON.parse(JSON.stringify(val)); + ruleForm.searchParams.relateType = val.paneName; + listApi(); + }; + onMounted(() => { + listApi(); + }); + const onAddorUpdata = () => { + listApi(); + }; + // 表格 + const tableData = ref(); + const currentPage4 = ref(); + const pageSize4 = ref(); + const total = ref(); + const handleSizeChange = (val: number) => { + // console.log(`${val} items per page`); + ruleForm.pageSize = val; + listApi(); + }; + const handleCurrentChange = (val: number) => { + // console.log(`current page: ${val}`); + ruleForm.pageIndex = val; + listApi(); + }; + const activeName = ref<any>('1'); + // 记录弹窗 + const Show = ref(); + const openDai = (data: any,num:number) => { + Show.value.openDailog(data,num); + }; + // 发起审批弹窗 + const TypeD = ref(); + const TypeDailog = (title:string,name:string,id:number,type:number,data:any) => { + TypeD.value.openDialog(title,name,id,type,data); + }; + const typeAlign=()=>{ + listApi(); + } + return { + TypeD, + typeAlign, + TypeDailog, + activeName, + total, + handleClick, + ruleForm, + listApi, + onAddorUpdata, + tableData, + resetForm, + currentPage4, + pageSize4, + handleSizeChange, + handleCurrentChange, + Show, + openDai, + Plus, + Delete, + Upload, + Download, + Refresh, + View, + EditPen, + }; + }, +}); +</script> +<style scoped> +.topTitle { + background-color: #fff; + padding: 20px 0px 20px 0px; +} +.minCenter { + width: 100%; + background-color: #fff; + margin-top: 10px; + padding: 0 20px; +} +.btns { + padding: 0px 0px 10px 0px; + display: flex; + justify-content: space-between; +} +.pages { + padding: 20px 0; + display: flex; + justify-content: right; +} +</style> \ No newline at end of file diff --git a/src/views/goalManagement/targetImprovements/component/Dailogprove.vue b/src/views/goalManagement/targetImprovements/component/Dailogprove.vue new file mode 100644 index 0000000..ee0c885 --- /dev/null +++ b/src/views/goalManagement/targetImprovements/component/Dailogprove.vue @@ -0,0 +1,105 @@ +<template> + <el-dialog v-model="dialogVisible" :fullscreen="full" title="Tips" width="50%" :before-close="handleClose"> + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-form :model="form" label-width="120px"> + <el-row> + <el-col :span="11"> + <el-form-item label="安全目标指标" size="default"> + <el-input v-model="form.name"></el-input> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="目标指标编号" size="default"> + <el-input v-model="form.name" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="11"> + <el-form-item label="年度" size="default"> + <el-input v-model="form.name" /> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="责任部门" size="default"> + <el-input v-model="form.name" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="11"> + <el-form-item label="改进期限" size="default"> + <el-date-picker v-model="form.date1" type="date" placeholder="选择日期时间" style="width: 100%" /> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2" > + <el-form-item label="发起人" size="default"> + <el-input v-model="model"></el-input> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="11"> + <el-form-item label="发起时间" size="default"> + <el-date-picker v-model="form.date1" type="date" placeholder="选择日期时间" style="width: 100%" /> + </el-form-item> + </el-col> + </el-row> + </el-form> + <el-tabs v-model="activeName" class="demo-tabs"> + <el-tab-pane label="目标指标" name="first"></el-tab-pane> + </el-tabs> + <template #footer> + <span class="dialog-footer"> + <el-button @click="dialogVisible = false">关闭</el-button> + </span> + </template> + </el-dialog> +</template> +<script lang="ts"> +import { defineComponent, ref, reactive } from 'vue'; +import { Plus, Delete, Upload, Download, Refresh, View, Search, FullScreen } from '@element-plus/icons-vue'; +export default defineComponent({ + setup() { + const dialogVisible = ref(false); + const form = reactive({ + name: '', + region: '', + date1: '', + date2: '', + delivery: false, + type: [], + resource: '', + desc: '', + }); + const openDailog = () => { + dialogVisible.value = true; + }; + const activeName = ref('first'); + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + return { + dialogVisible, + form, + openDailog, + activeName, + Search, + full, + toggleFullscreen, + FullScreen, + }; + }, +}); +</script> +<style scoped> +.el-row { + padding: 0 0 20px 0; +} +</style> \ No newline at end of file diff --git a/src/views/goalManagement/targetImprovements/index.vue b/src/views/goalManagement/targetImprovements/index.vue new file mode 100644 index 0000000..b273902 --- /dev/null +++ b/src/views/goalManagement/targetImprovements/index.vue @@ -0,0 +1,307 @@ +<template> +<div> + <el-form ref="ruleFormRef" :model="ruleForm" status-icon label-width="20px" class="topTitle"> + <el-row> + <el-col :span="4"> + <el-form-item size="default"> + <el-input v-model="ruleForm.pass" placeholder="安全目标指标" /> + </el-form-item> + </el-col> + <el-col :span="4"> + <el-form-item> + <el-button type="primary" size="default" @click="submitForm(ruleFormRef)">查询</el-button> + <el-button size="default" @click="resetForm(ruleFormRef)">重置</el-button> + </el-form-item> + </el-col> + </el-row> + </el-form> + <div class="minCenter"> + <el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick"> + <el-tab-pane label="发起改进" name="1"> + <el-table ref="multipleTableRef" :data="tableData" style="width: 100%"> + <el-table-column label="序号" align="center" type="index" width="70" /> + <el-table-column label="安全目标指标" align="center" sortable> + <template #default="scope">{{ scope.row.date }}</template> + </el-table-column> + <el-table-column property="name" align="center" label="目标指标编号" sortable /> + <el-table-column property="address" label="年度" align="center" sortable show-overflow-tooltip /> + <el-table-column property="address" label="责任部门" align="center" sortable show-overflow-tooltip /> + <el-table-column property="address" label="考核指标" align="center" sortable show-overflow-tooltip /> + <el-table-column property="address" label="上报值" align="center" sortable show-overflow-tooltip /> + <el-table-column property="address" label="考核时间" align="center" sortable show-overflow-tooltip /> + <el-table-column property="address" label="考核结果" align="center" sortable show-overflow-tooltip /> + <el-table-column label="操作" align="center" width="200" sortable show-overflow-tooltip> + <template #default> + <el-button link type="primary" size="default" :icon="View" @click="handleClick">查看</el-button> + <el-button link type="primary" size="default" :icon="Delete">删除</el-button> + </template> + </el-table-column> + </el-table> + <div class="pages"> + <el-pagination + v-model:currentPage="currentPage4" + v-model:page-size="pageSize4" + :page-sizes="[100, 200, 300, 400]" + :small="small" + :disabled="disabled" + :background="background" + layout="total, sizes, prev, pager, next, jumper" + :total="400" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + </el-tab-pane> + <el-tab-pane label="整改" name="2"> + <el-table ref="multipleTableRef" :data="tableData" style="width: 100%"> + <el-table-column label="序号" align="center" type="index" width="70" /> + <el-table-column label="安全目标指标" align="center" sortable> + <template #default="scope">{{ scope.row.date }}</template> + </el-table-column> + <el-table-column property="name" align="center" label="目标指标编号" sortable /> + <el-table-column property="address" label="年度" align="center" sortable show-overflow-tooltip /> + <el-table-column property="address" label="责任部门" align="center" sortable show-overflow-tooltip /> + <el-table-column property="address" label="考核指标" align="center" sortable show-overflow-tooltip /> + <el-table-column property="address" label="改进期限" align="center" sortable show-overflow-tooltip /> + <el-table-column property="address" label="发起人" align="center" sortable show-overflow-tooltip /> + <el-table-column property="address" label="发起时间" align="center" sortable show-overflow-tooltip /> + <el-table-column label="操作" align="center" width="200" sortable show-overflow-tooltip> + <template #default> + <el-button link type="primary" size="default" :icon="View" @click="openDai">查看</el-button> + <el-button link type="primary" size="default" :icon="Delete" @click="jump">整改上报</el-button> + </template> + </el-table-column> + </el-table> + <div class="pages"> + <el-pagination + v-model:currentPage="currentPage4" + v-model:page-size="pageSize4" + :page-sizes="[100, 200, 300, 400]" + :small="small" + :disabled="disabled" + :background="background" + layout="total, sizes, prev, pager, next, jumper" + :total="400" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + </el-tab-pane> + <el-tab-pane label="验证" name="3"> + <el-table ref="multipleTableRef" :data="tableData" style="width: 100%"> + <el-table-column label="序号" align="center" type="index" width="70" /> + <el-table-column label="安全目标指标" align="center" sortable> + <template #default="scope">{{ scope.row.date }}</template> + </el-table-column> + <el-table-column property="name" align="center" label="目标指标编号" sortable /> + <el-table-column property="address" label="年度" align="center" sortable show-overflow-tooltip /> + <el-table-column property="address" label="责任部门" align="center" sortable show-overflow-tooltip /> + <el-table-column property="address" label="考核指标" align="center" sortable show-overflow-tooltip /> + <el-table-column property="address" label="整改值" align="center" sortable show-overflow-tooltip /> + <el-table-column property="address" label="整改时间" align="center" sortable show-overflow-tooltip /> + <el-table-column label="操作" align="center" width="200" sortable show-overflow-tooltip> + <template #default> + <el-button link type="primary" size="default" :icon="View" @click="handleClick">查看</el-button> + <el-button link type="primary" size="default" :icon="Delete">删除</el-button> + </template> + </el-table-column> + </el-table> + <div class="pages"> + <el-pagination + v-model:currentPage="currentPage4" + v-model:page-size="pageSize4" + :page-sizes="[100, 200, 300, 400]" + :small="small" + :disabled="disabled" + :background="background" + layout="total, sizes, prev, pager, next, jumper" + :total="400" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + </el-tab-pane> + <el-tab-pane label="完成" name="4"> + <el-table ref="multipleTableRef" :data="tableData" style="width: 100%"> + <el-table-column label="序号" align="center" type="index" width="70" /> + <el-table-column label="安全目标指标" align="center" sortable> + <template #default="scope">{{ scope.row.date }}</template> + </el-table-column> + <el-table-column property="name" align="center" label="目标指标编号" sortable /> + <el-table-column property="address" label="年度" align="center" sortable show-overflow-tooltip /> + <el-table-column property="address" label="责任部门" align="center" sortable show-overflow-tooltip /> + <el-table-column property="address" label="考核指标" align="center" sortable show-overflow-tooltip /> + <el-table-column property="address" label="整改值" align="center" sortable show-overflow-tooltip /> + <el-table-column property="address" label="整改时间" align="center" sortable show-overflow-tooltip /> + <el-table-column property="address" label="验证结果" align="center" sortable show-overflow-tooltip /> + <el-table-column property="address" label="验证日期" align="center" sortable show-overflow-tooltip /> + <el-table-column label="操作" align="center" width="200" sortable show-overflow-tooltip> + <template #default> + <el-button link type="primary" size="default" :icon="View" @click="handleClick">查看</el-button> + <el-button link type="primary" size="default" :icon="Delete">审批进度</el-button> + </template> + </el-table-column> + </el-table> + <div class="pages"> + <el-pagination + v-model:currentPage="currentPage4" + v-model:page-size="pageSize4" + :page-sizes="[100, 200, 300, 400]" + :small="small" + :disabled="disabled" + :background="background" + layout="total, sizes, prev, pager, next, jumper" + :total="400" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + </el-tab-pane> + </el-tabs> + </div> + <Dailogprove ref="Show"></Dailogprove> + </div> +</template> +<script lang="ts"> +import { ref, toRefs, reactive, onMounted, defineComponent } from 'vue'; +import { ElMessageBox, ElMessage, ElButton, ElInput, TabsPaneContext, FormInstance } from 'element-plus'; +import { Plus, Delete, Upload, Download, Refresh, View } from '@element-plus/icons-vue'; +interface User { + date: string; + name: string; + address: string; +} +import type { TableColumnCtx } from 'element-plus/es/components/table/src/table-column/defaults'; +import Dailogprove from './component/Dailogprove.vue'; +import { useRouter } from 'vue-router'; +export default defineComponent({ + components: { ElButton, ElInput,Dailogprove}, + setup() { + // 搜索条件 + const ruleForm = reactive({ + pass: '', + checkPass: '', + }); + const resetForm = (formEl: FormInstance | undefined) => { + console.log(!formEl); + if (!formEl) return; + formEl.resetFields(); + }; + // 下方导航与表格 + const activeName = ref('1'); + const handleClick = (tab: TabsPaneContext, event: Event) => { + console.log(tab, event); + }; + const formatter = (row: User, column: TableColumnCtx<User>) => { + return row.address; + }; + + const tableData: User[] = [ + { + date: '2016-05-03', + name: 'Tom', + address: 'No. 189, Grove St, Los Angeles', + }, + { + date: '2016-05-02', + name: 'Tom', + address: 'No. 189, Grove St, Los Angeles', + }, + { + date: '2016-05-04', + name: 'Tom', + address: 'No. 189, Grove St, Los Angeles', + }, + { + date: '2016-05-01', + name: 'Tom', + address: 'No. 189, Grove St, Los Angeles', + }, + { + date: '2016-05-08', + name: 'Tom', + address: 'No. 189, Grove St, Los Angeles', + }, + { + date: '2016-05-06', + name: 'Tom', + address: 'No. 189, Grove St, Los Angeles', + }, + { + date: '2016-05-07', + name: 'Tom', + address: 'No. 189, Grove St, Los Angeles', + }, + ]; + const currentPage4 = ref(4); + const pageSize4 = ref(100); + const small = ref(false); + const disabled = ref(false); + const background = ref(false); + const handleSizeChange = (val: number) => { + console.log(`${val} items per page`); + }; + const handleCurrentChange = (val: number) => { + console.log(`current page: ${val}`); + }; + const Show=ref() + const openDai=()=>{ + Show.value.openDailog() + } + const router=useRouter() + const jump=()=>{ + router.push({ + path:"/processForms" + }) + } + return { + ruleForm, + resetForm, + activeName, + handleClick, + tableData, + formatter, + currentPage4, + pageSize4, + handleSizeChange, + handleCurrentChange, + small, + disabled, + background, + Show, + router, + jump, + openDai, + Plus, + Delete, + Upload, + Download, + Refresh, + View, + }; + }, +}); +</script> +<style scoped> +.topTitle { + background-color: #fff; + padding: 20px 0px 20px 0px; + margin-bottom: 10px; +} +.minCenter { + width: 100%; + background-color: #fff; + margin-top: 10px; + padding: 0 20px; +} +.btns { + padding: 10px 0px 10px 0px; + display: flex; + justify-content: space-between; +} +.pages { + padding: 20px 0; + display: flex; + justify-content: right; +} +</style> \ No newline at end of file diff --git a/src/views/goalManagement/targetSettings/component/dailogAdd.vue b/src/views/goalManagement/targetSettings/component/dailogAdd.vue new file mode 100644 index 0000000..8ab66ca --- /dev/null +++ b/src/views/goalManagement/targetSettings/component/dailogAdd.vue @@ -0,0 +1,284 @@ +<template> + <el-dialog v-model="Shows" @close="handleClose(ruleFormRef)" :fullscreen="full" :title="titles" width="50%" draggable> + <el-button @click="toggleFullscreen" size="small" class="pot" :icon="FullScreen"></el-button> + <el-form :model="form" :disabled="disabled" ref="ruleFormRef" :rules="rules" label-width="120px"> + <el-row> + <el-col :span="11"> + <el-form-item label="安全目标项" prop="qName" size="default"> + <el-input v-model="form.qName" placeholder="请填写安全目标项" /> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="目标编号" prop="indexNum" size="default"> + <el-input v-model="form.indexNum" placeholder="请填写目标编号" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="11"> + <el-form-item label="年度" prop="year" size="default"> + <el-input v-model.number="form.year" maxlength="8" placeholder="请填写年度" /> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="指标值" prop="value" size="default"> + <el-input v-model.number="form.value" placeholder="请填写指标值"> + <template #prepend> + <el-select v-model="form.valueSign " placeholder="请选择" style="width: 115px"> + <el-option label="大于" :value="1" /> + <el-option label="等于" :value="2" /> + <el-option label="小于" :value="3" /> + </el-select> + </template> + </el-input> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="11"> + <el-form-item label="指标级别" size="default" prop="level"> + <el-select v-model="form.level" placeholder="请选择" style="width: 100%"> + <el-option label="公司级" :value="1">公司级</el-option> + <el-option label="部门分厂级" :value="2">部门分厂级</el-option> + <el-option label="工段班组级" :value="3">工段班组级</el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> + <el-form-item label="完成期限" size="default" prop="completeDate"> + <el-date-picker + v-model="form.completeDate" + format="YYYY-MM-DD HH:mm:ss" + value-format="YYYY-MM-DD HH:mm:ss" + type="datetime" + placeholder="请选择" + style="width: 100%" + /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="11"> + <el-form-item label="目标制定部门" size="default" prop=""> + <el-tree-select + v-model="form.makerDepartmentId" + :data="data" + @current-change="makerName" + check-strictly="true" + class="w100" + :props="propse" + placeholder="请选择" + /> + </el-form-item> + </el-col> + <el-col :span="11" :offset="2"> </el-col> + </el-row> + <el-form-item label="备注信息" prop="memo"> + <el-input v-model="form.memo" size="default" type="textarea" /> + </el-form-item> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="resetForm(ruleFormRef)" size="default">关闭</el-button> + <el-button type="primary" v-if="titles == '查看目标设定' ? false : true" @click="submitForm(ruleFormRef)" size="default">确定</el-button> + </span> + </template> + </el-dialog> +</template> +<script lang="ts"> +import { ref, toRefs, reactive, onMounted, watch, defineComponent } from 'vue'; +// import { timeDate } from '/@/assets/index.ts'; +import screenfull from 'screenfull'; +import { ElMessageBox, ElMessage, ElButton, ElInput, TabsPaneContext } from 'element-plus'; +import type { FormInstance, FormRules } from 'element-plus'; +import { Plus, Delete, Upload, Download, Refresh, View, Search, FullScreen } from '@element-plus/icons-vue'; +import { goalManagementApi } from '/@/api/goalManagement'; +export default defineComponent({ + setup(props, { emit }) { + let Shows = ref(false); + const ruleFormRef = ref<FormInstance>(); + const form = ref({ + indexNum: '', //目标指标编号 + qName: '', //安全目标指标 + year: '', //年度 + level: '', ////指标级别 1:公司级 2:部门分厂级 3:工段班组级 + memo: '', ////备注信息 + targetType: '', ////指标类型 1:年指标 2:月指标 + completeDate: '', ////完成期限 + divideStatus: '2', ////分解状态 1:已分解 2:未分解 + value: '', ////指标值 + makerDepartmentId: '', + valueSign:"" + }); + const titles = ref(); + const disabled = ref(false); + const titleT = ref(); + // 打开弹窗 + const openDialog = (title: string, value: any, id: number) => { + department(); + Shows.value = true; + titleT.value = title; + titles.value = `${title}目标设定`; + form.value.targetType = value; + disabled.value = title == '查看' ? true : false; + if (title == '查看' || title == '修改') + goalManagementApi() + .getTargetMngDetail(id) + .then((res) => { + if (res.data.code == 200) { + form.value = res.data.data; + form.value.completeDate = timeC(form.value.completeDate); + } else { + ElMessage.error(res.data.msg); + } + }); + }; + const timeC = (timestamp: any) => { + let a = new Date(timestamp).getTime(); + const date = new Date(a); + const Y = date.getFullYear() + '-'; + const M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-'; + const D = (date.getDate() < 10 ? '0' + date.getDate() : date.getDate()) + ' '; + const h = (date.getHours() < 10 ? '0' + date.getHours() : date.getHours()) + ':'; + const m = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes(); + const s = date.getSeconds(); // 秒 + const dateString = Y + M + D + h + m + `:${s}`; + // console.log('dateString', dateString); // > dateString 2021-07-06 14:23 + return dateString; + }; + //全屏 + const full = ref(false); + const toggleFullscreen = () => { + if (full.value == false) { + full.value = true; + } else { + full.value = false; + } + }; + const rules = reactive<FormRules>({ + qName: [ + { + required: true, + message: '安全目标项不能为空', + trigger: 'change', + }, + ], + indexNum: [ + { + required: true, + message: '目标编号不能为空', + trigger: 'change', + }, + ], + year: [ + { + required: true, + message: '年度不能为空', + trigger: 'change', + }, + ], + value: [ + { + required: true, + message: '指标值不能为空', + trigger: 'change', + }, + { + type: 'number', + message: '指标值只能为数字类型', + trigger: 'change', + }, + ], + level: [], + completeDate: [], + memo: [], + }); + // 提交 + const submitForm = async (formEl: FormInstance | undefined) => { + if (!formEl) return; + await formEl.validate((valid, fields) => { + if (valid) { + if (titleT.value == '新建') { + delete form.value.id; + } + Shows.value = false; + goalManagementApi() + .getTargetMngAddOrupdata(form.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + message: res.data.msg, + type: 'success', + }); + emit('navAddorUpdata'); + } else { + ElMessage.error(res.data.msg); + formEl.resetFields(); + } + }); + formEl.resetFields(); + } else { + console.log('error submit!', fields); + } + }); + }; + // 取消 + const resetForm = (formEl: FormInstance | undefined) => { + if (!formEl) return; + formEl.resetFields(); + Shows.value = false; + }; + const handleClose = (formEl: FormInstance | undefined) => { + formEl.resetFields(); + }; + //部门 + const department = () => { + goalManagementApi() + .getTreedepartment() + .then((res) => { + if (res.data.code == 200) { + data.value = res.data.data; + } else { + ElMessage.error(res.data.msg); + } + }); + }; + const propse = { + label: 'depName', + children: 'children', + value: 'depId', + }; + const data = ref(); + const makerName = (data: any) => { + form.value.makerDepartmentName = data.depName; + }; + return { + department, + propse, + data, + makerName, + timeC, + openDialog, + handleClose, + titles, + titleT, + // timeDate, + Shows, + form, + full, + disabled, + toggleFullscreen, + rules, + ruleFormRef, + submitForm, + resetForm, + FullScreen, + }; + }, +}); +</script> +<style scoped> +.el-row { + padding: 0 0 20px 0; +} +</style> \ No newline at end of file diff --git a/src/views/goalManagement/targetSettings/component/search.vue b/src/views/goalManagement/targetSettings/component/search.vue new file mode 100644 index 0000000..35b1a6a --- /dev/null +++ b/src/views/goalManagement/targetSettings/component/search.vue @@ -0,0 +1,52 @@ +<template> + <el-form ref="ruleFormRef" :model="ruleForm" status-icon label-width="20px" class="topTitle"> + <el-row> + <el-col :span="4"> + <el-form-item> + <el-input v-model="ruleForm.pass" size="default" placeholder="安全目标指标" /> + </el-form-item> + </el-col> + <el-col :span="4"> + <el-form-item> + <el-input v-model="ruleForm.checkPass" size="default" placeholder="目标指标编号" /> + </el-form-item> + </el-col> + <el-col :span="16"> + <el-form-item> + <el-button type="primary" size="default" @click="submitForm(ruleFormRef)">查询</el-button> + <el-button size="default" @click="resetForm(ruleFormRef)">重置</el-button> + </el-form-item> + </el-col> + </el-row> + </el-form> +</template> +<script lang="ts"> +import { ref, reactive, defineComponent } from 'vue'; +import { + FormInstance, +} from "element-plus"; +export default defineComponent({ + setup() { + // 搜索条件 + const ruleForm = reactive({ + pass: '', + checkPass: '', + }); + const resetForm = (formEl: FormInstance | undefined) => { + console.log(!formEl); + if (!formEl) return; + formEl.resetFields(); + }; + return { + ruleForm, + resetForm + }; + }, +}); +</script> +<style scoped> + .topTitle { + background-color: #fff; + padding: 20px 0px 20px 0px; +} +</style> \ No newline at end of file diff --git a/src/views/goalManagement/targetSettings/index.vue b/src/views/goalManagement/targetSettings/index.vue new file mode 100644 index 0000000..0086c8e --- /dev/null +++ b/src/views/goalManagement/targetSettings/index.vue @@ -0,0 +1,300 @@ +<template> + <div> + <el-form :model="ruleForm" status-icon label-width="20px" class="topTitle"> + <el-row> + <el-col :span="4"> + <el-form-item> + <el-input v-model="ruleForm.searchParams.qName" size="default" placeholder="安全目标指标" /> + </el-form-item> + </el-col> + <el-col :span="4"> + <el-form-item> + <el-input v-model="ruleForm.searchParams.indexNum" size="default" placeholder="目标指标编号" /> + </el-form-item> + </el-col> + <el-col :span="16"> + <el-form-item> + <el-button type="primary" size="default" @click="listApi">查询</el-button> + <el-button size="default" @click="resetForm">重置</el-button> + </el-form-item> + </el-col> + </el-row> + </el-form> + <div class="minCenter"> + <el-tabs v-model="ruleForm.searchParams.targetType" class="demo-tabs" @tab-click="handleClick"> + <div class="btns"> + <div> + <el-button type="primary" size="default" :icon="Plus" @click="openD('新建')">新建</el-button> + <el-button type="danger" :disabled="danger" size="default" @click="onDeleteAll" :icon="Delete" plain>删除</el-button> + </div> + <div> + <!-- <el-button size="default" :icon="Upload" @click="upButton"></el-button> + <el-button size="default" :icon="Download"></el-button> + <el-button size="default" :icon="Refresh"></el-button> --> + </div> + </div> + <el-tab-pane label="目标定制(年)" name="1"> </el-tab-pane> + <el-tab-pane label="目标定制(月)" name="2"></el-tab-pane> + <el-tab-pane label="目标定制(半年)" name="3"></el-tab-pane> + <el-tab-pane label="目标定制(季度)" name="4"></el-tab-pane> + </el-tabs> + <el-table ref="multipleTableRef" :data="tableData" @selection-change="handleSelectionChange" style="width: 100%"> + <el-table-column label="序号" align="center" type="index" width="70" /> + <el-table-column type="selection" align="center" width="55" /> + <el-table-column label="安全目标指标" align="center" property="qName" sortable /> + <el-table-column property="indexNum" align="center" label="目标指标编号" sortable /> + <el-table-column property="year" label="年度" align="center" sortable show-overflow-tooltip /> + <el-table-column property="value" label="指标值" align="center" sortable show-overflow-tooltip /> + <el-table-column property="level" label="指标级别" align="center" sortable show-overflow-tooltip /> + <el-table-column property="completeDate" label="完成期限" align="center" :formatter="timeDate" sortable show-overflow-tooltip /> + <el-table-column label="状态" align="center" sortable show-overflow-tooltip> + <template #default="scope"> + <span v-if="scope.row.divideStatus == 1">已分解</span> + <span v-if="scope.row.divideStatus == 2">未分解</span> + </template> + </el-table-column> + <el-table-column property="memo" label="备注信息" align="center" sortable show-overflow-tooltip /> + <el-table-column label="操作" align="center" width="300" sortable show-overflow-tooltip> + <template #default="scope"> + <el-button link type="primary" size="default" :icon="View" @click="openD('查看', scope.row.id)">查看</el-button> + <el-button link type="primary" size="default" :icon="View" @click="openD('修改', scope.row.id)">修改</el-button> + <el-button link type="primary" size="default" :icon="Delete" @click="onDelete(scope.row.id)">删除</el-button> + </template> + </el-table-column> + </el-table> + <div class="pages"> + <el-pagination + v-model:currentPage="currentPage4" + v-model:page-size="pageSize4" + :page-sizes="[10, 20, 30, 40]" + layout="total, sizes, prev, pager, next, jumper" + :total="total" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + <dailogAdd ref="openAdd" @navAddorUpdata="onAddorUpdata"></dailogAdd> + <upData ref="upShow"></upData> + </div> + </div> +</template> +<script lang="ts"> +import dailogAdd from './component/dailogAdd.vue'; +import {timeDate} from '/@/assets/index.ts' +import upData from '../../../components/updata/updata.vue'; +import { ref, toRefs, reactive, onMounted, defineComponent } from 'vue'; +import { ElMessageBox, ElMessage, ElButton, ElInput, TabsPaneContext, FormInstance } from 'element-plus'; +import { Plus, Delete, Upload, Download, Refresh, View } from '@element-plus/icons-vue'; +import { goalManagementApi } from '/@/api/goalManagement'; +export default defineComponent({ + components: { ElButton, ElInput, dailogAdd, upData }, + setup() { + // 搜索条件 + const ruleForm = reactive({ + pageSize: 10, + pageIndex: 1, + searchParams: { + qName: '', ////安全目标指标 + indexNum: '', ////目标指标编号 + targetType: '1', ////指标类型 1:年指标 2:月指标 + divideStatus: '', ////分解状态 1:已分解 2:未分解 + }, + }); + // 重置 + const resetForm = () => { + ruleForm.searchParams.qName = ''; + ruleForm.searchParams.indexNum = ''; + listApi() + }; + const listApi = () => { + goalManagementApi() + .getTargetMngList(ruleForm) + .then((res) => { + if (res.data.code == 200) { + tableData.value = res.data.data; + currentPage4.value = res.data.pageIndex; + pageSize4.value = res.data.pageSize; + total.value = res.data.total; + } else { + ElMessage.error(res.data.msg); + } + }); + }; + // + const handleClick = (val: any) => { + let targetType = JSON.parse(JSON.stringify(val)); + ruleForm.searchParams.targetType = targetType.paneName; + listApi(); + }; + onMounted(() => { + listApi(); + }); + const onAddorUpdata = () => { + listApi(); + }; + // 表格 + const tableData = ref(); + const currentPage4 = ref(); + const pageSize4 = ref(); + const total = ref(); + const small = ref(false); + const disabled = ref(false); + const background = ref(false); + const handleSizeChange = (val: number) => { + // console.log(`${val} items per page`); + ruleForm.pageSize = val; + listApi(); + }; + const handleCurrentChange = (val: number) => { + // console.log(`current page: ${val}`); + ruleForm.pageIndex = val; + listApi(); + }; + // 弹窗 + const openAdd = ref(); + const openD = (title: String, id: number) => { + openAdd.value.openDialog(title, ruleForm.searchParams.targetType, id); + }; + // 删除 + const onDelete = (id: number) => { + let arr=[] + arr.push(id) + ElMessageBox.confirm('确定删除所选项吗?', 'Warning', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + goalManagementApi() + .getTargetMngDelete(arr) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + message: res.data.msg, + type: 'success', + }); + listApi(); + } else { + ElMessage.error(res.data.msg); + } + }); + }) + .catch(() => { + ElMessage({ + type: 'info', + message: 'Delete canceled', + }); + }); + }; + // 批量删除 + // const warning = ref(true); + const danger = ref(true); + const deletAll = ref(); + const handleSelectionChange = (val: any) => { + let valId = JSON.parse(JSON.stringify(val)); + let arr = []; + for (let i = 0; i < valId.length; i++) { + arr.push(valId[i].id); + } + deletAll.value = arr + if (val.length == 1) { + // warning.value = false; + danger.value = false; + } else if (val.length == 0) { + // warning.value = true; + danger.value = true; + } else { + // warning.value = true; + danger.value = false; + } + }; + const onDeleteAll = () => { + ElMessageBox.confirm('确定删除所选项吗?', 'Warning', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(() => { + goalManagementApi() + .getTargetMngDelete(deletAll.value) + .then((res) => { + if (res.data.code == 200) { + ElMessage({ + message: res.data.msg, + type: 'success', + }); + listApi(); + } else { + ElMessage.error(res.data.msg); + } + }); + }) + .catch(() => { + // ElMessage({ + // type: 'info', + // message: 'Delete canceled', + // }); + }); + }; + // 上传 + // const upShow = ref(); + // const upButton = () => { + // upShow.value.openDialog(); + // }; + return { + timeDate, + tableData, + currentPage4, + pageSize4, + total, + handleSizeChange, + handleCurrentChange, + handleClick, + openAdd, + openD, + // upShow, + // upButton, + small, + disabled, + background, + Plus, + Delete, + Upload, + Download, + Refresh, + View, + listApi, + ruleForm, + resetForm, + onAddorUpdata, + onDelete, + handleSelectionChange, + deletAll, + danger, + onDeleteAll, + }; + }, +}); +</script> +<style scoped> +.topTitle { + background-color: #fff; + padding: 20px 0px 20px 0px; +} +.minCenter { + width: 100%; + background-color: #fff; + margin-top: 10px; + padding: 0 20px; +} +.btns { + padding: 0px 0px 10px 0px; + display: flex; + justify-content: space-between; +} +.pages { + padding: 20px 0; + display: flex; + justify-content: right; +} +</style> diff --git a/src/views/goalManagement/targetStatistics/index.vue b/src/views/goalManagement/targetStatistics/index.vue new file mode 100644 index 0000000..bffcc0e --- /dev/null +++ b/src/views/goalManagement/targetStatistics/index.vue @@ -0,0 +1,92 @@ +<template> + <div style="background-color: #fff"> + <h2 style="line-height:40px;text-align: center;padding: 20px 0;">目标完成情况统计</h2> + <el-row style="padding:20px 0"> + <el-col :span="4" :offset="17"> + <el-select v-model="form.targetType" placeholder="" @change="listApi" style="width:100%"> + <el-option label="年指标" :value="1" /> + <el-option label="月指标" :value="2" /> + <el-option label="半年" :value="3" /> + <el-option label="季度" :value="4" /> + </el-select> + </el-col> + </el-row> + <div ref="main" style="width: 100%; height: 450px;"></div> + </div> +</template> +<script lang="ts"> +import { defineComponent, onMounted, ref } from 'vue'; +import * as echarts from 'echarts'; +import { ElMessage } from 'element-plus'; +import { goalManagementApi } from '/@/api/goalManagement'; +export default defineComponent({ + setup() { + const form = ref({ + qName: '', + indexNum: '', + targetType: 1, + divideStatus: '', + }); + onMounted(() => { + listApi(); + }); + const listApi = () => { + goalManagementApi() + .gettargetstatistics(form.value.targetType) + .then((res) => { + let arr = []; + arr.push({ + value: res.data.data.noComplete, + name: `未完成 ${res.data.data.noComplete}`, + }); + arr.push({ + value: res.data.data.complete, + name: `已完成 ${res.data.data.complete}`, + }); + init(arr); + }); + }; + const main = ref(); + const init = (data: any) => { + var myChart = echarts.init(main.value); + var option = { + // title: { + // text: 'Referer of a Website', + // subtext: 'Fake Data', + // left: 'center', + // }, + tooltip: { + trigger: 'item', + }, + legend: { + orient: 'vertical', + left: '30%', + }, + series: [ + { + // name: 'Access From', + type: 'pie', + radius: '90%', + data: data, + emphasis: { + itemStyle: { + shadowBlur: 10, + shadowOffsetX: 0, + shadowColor: 'rgba(0, 0, 0, 0.5)', + }, + }, + }, + ], + }; + + myChart.setOption(option); + }; + return { + form, + main, + init, + listApi, + }; + }, +}); +</script> diff --git a/src/views/intellectInspect/inspectBasic/discriminate/components/RFIDDialog.vue b/src/views/intellectInspect/inspectBasic/discriminate/components/RFIDDialog.vue new file mode 100644 index 0000000..a54d140 --- /dev/null +++ b/src/views/intellectInspect/inspectBasic/discriminate/components/RFIDDialog.vue @@ -0,0 +1,248 @@ +<template> + <div class="system-add-menu-container"> + <el-dialog :title="title" v-model="isShowRFIDDialog" width="600px"> + <el-form :model="RFIDForm" :rules="RFIDFormRules" ref="RFIDFormRef" size="default" label-width="120px"> + <el-row :gutter="35"> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="RFID名称" prop="rfidName"> + <el-input class="input-add" v-model.trim="RFIDForm.rfidName" placeholder="请输入RFID名称" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="RFID编码" prop="rfid"> + <el-input class="input-add" v-model.trim="RFIDForm.rfid" placeholder="请输入RFID编码" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="上传图片" prop="rfidImage"> + <el-upload accept="image/*" :on-preview="handlePictureCardPreview" :limits="1" v-model:file-list="fileList" :http-request="upload" :action="uploadUrl" list-type="picture-card" :on-remove="handleRemove" :before-remove="beforeRemove" :before-upload="getUploadUrl"> + <el-icon><Plus /></el-icon> + <template #tip> + <div class="el-upload__tip">上传 jpg/png 图片尺寸小于500KB</div> + </template> + </el-upload> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="isShowRFIDDialog = !isShowRFIDDialog" size="default">取 消</el-button> + <el-button type="primary" @click="submitRFID" v-throttle size="default">确 定</el-button> + </span> + </template> + </el-dialog> + <el-dialog v-model="dialogVisible"> + <img w-full :src="dialogImageUrl" alt="Preview Image" /> + </el-dialog> + </div> +</template> + +<script lang="ts"> +interface stateType { + isShowRFIDDialog: Boolean; + RFIDForm: { + rfid: string; + rfidName: string; + rfidImage: string | null; + }; + title: string; + dialogVisible: Boolean; + dialogImageUrl: string | null; + RFIDFormRules: {}; + uploadUrl: string; + fileList: Array<file>; +} +interface file { + url: string; +} +import { reactive, toRefs, ref } from 'vue'; +import { RFIDApi } from '/@/api/intellectInspectSystem/RFID'; +import { ElMessage, ElMessageBox } from 'element-plus'; +import type { UploadProps, UploadUserFile } from 'element-plus'; +import axios from 'axios'; +export default { + name: 'RFIDDialog', + setup(props: any, context: any) { + const RFIDFormRef = ref(); + const state = reactive<stateType>({ + title: '', + isShowRFIDDialog: false, + RFIDForm: { + rfid: '', + rfidName: '', + rfidImage: null + }, + uploadUrl: '', + dialogVisible: false, + dialogImageUrl: null, + RFIDFormRules: { + rfid: [{ required: true, message: '请填写RFID编码', trigger: 'blur' }], + rfidName: [{ required: true, message: '请填写RFID名称', trigger: 'change' }], + riskLevel: [{ required: true, message: '请选择风险等级', trigger: 'change' }], + location: [{ required: true, message: '请填写区域位置', trigger: 'blur' }] + }, + + fileList: [] + }); + //打开模态框 + const openRFIDDialog = (type: string, value: object) => { + state.fileList = []; + state.isShowRFIDDialog = true; + setTimeout(() => { + RFIDFormRef.value.clearValidate(); + }); + if (type === '新增') { + state.title = '新增RFID'; + state.RFIDForm = { + rfid: '', + rfidName: '', + rfidImage: '' + }; + } else { + state.title = '修改RFID'; + state.RFIDForm = JSON.parse(JSON.stringify(value)); + if (state.RFIDForm.rfidImage === null) return; + state.fileList = [{ url: state.RFIDForm.rfidImage }]; + } + }; + + // // 图片上传 + // const fileList = ref<UploadUserFile[]>([]); + // + // const handleRemove = () => { + // ElMessageBox.confirm(`此操作将永久删除该图片,是否继续?`, '提示', { + // confirmButtonText: '确认', + // cancelButtonText: '取消', + // type: 'warning' + // }) + // .then(() => { + // state.RFIDForm.rfidImage = null; + // state.fileList = []; + // }) + // .catch(() => {}); + // }; + + const handlePreview: UploadProps['onPreview'] = (uploadFile) => { + console.log(uploadFile); + }; + + const getUploadUrl = async (rawFile: any) => { + const res = await RFIDApi().getUploadUrl(rawFile.name); + state.RFIDForm.rfidImage = res.data.rfidImage; + state.uploadUrl = res.data.uploadUrl; + }; + + const upload = async (params: any) => { + // const formData = new FormData(); + // formData.append('file', state.fileList[0].raw); + let reader = new FileReader(); + reader.readAsArrayBuffer(params.file); + reader.onload = async () => { + axios + .put(state.uploadUrl, reader.result, { + header: { 'Content-Type': 'multipart/form-data' } + }) + .then(() => { + if (state.fileList.length === 2) { + state.fileList.splice(0, 1); + } + }); + // let res = await RFIDApi().uploadFile(state.uploadUrl, reader.result); + // if (res.data.code === '200') { + // } else { + // ElMessage({ + // type: 'warning', + // message: res.data.msg + // }); + // } + }; + }; + + const beforeRemove = (file: {}, fileList: []) => { + const result = new Promise((resolve, reject) => { + ElMessageBox.confirm('此操作将删除该图片, 是否继续?', '提示', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning' + }) + .then(() => { + state.RFIDForm.rfidImage = null; + state.fileList = []; + // 请求删除接口 + }) + .catch(() => { + reject(false); + }); + }); + return result; + }; + + //新增修改提交 + const submitRFID = async () => { + RFIDFormRef.value.validate(async (valid: Boolean) => { + if (valid) { + if (state.title === '新增RFID') { + let res = await RFIDApi().addRFID(state.RFIDForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: 'RFID新增成功', + duration: 2000 + }); + state.isShowRFIDDialog = false; + context.emit('refreshRFID'); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } else { + let res = await RFIDApi().modRFID(state.RFIDForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: 'RFID修改成功', + duration: 2000 + }); + state.isShowRFIDDialog = false; + context.emit('refreshRFID'); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } + } else { + ElMessage({ + type: 'warning', + message: '请完善基本信息' + }); + } + }); + }; + + const handlePictureCardPreview = (uploadFile: { url: string }) => { + state.dialogImageUrl = uploadFile.url!; + state.dialogVisible = true; + }; + + return { + ...toRefs(state), + RFIDFormRef, + // fileList, + upload, + getUploadUrl, + handlePreview, + beforeRemove, + submitRFID, + openRFIDDialog, + handlePictureCardPreview + }; + } +}; +</script> + +<style scoped></style> diff --git a/src/views/intellectInspect/inspectBasic/discriminate/index.vue b/src/views/intellectInspect/inspectBasic/discriminate/index.vue new file mode 100644 index 0000000..d857438 --- /dev/null +++ b/src/views/intellectInspect/inspectBasic/discriminate/index.vue @@ -0,0 +1,190 @@ +<template> + <div class="system-role-container"> + <el-card shadow="hover"> + <div class="system-user-search mb15"> + <div class="basic-line"> + <span>RFID名称:</span> + <el-input class="input-box" v-model="RFIDData.params.rfidName" placeholder="RFID名称" clearable> </el-input> + </div> + <div class="basic-line"> + <span>RFID编码:</span> + <el-input class="input-box" v-model="RFIDData.params.rfid" placeholder="RFID编码" clearable> </el-input> + </div> + <el-button size="default" type="primary" class="ml10" v-throttle @click="handleSearch"> + <el-icon> + <ele-Search /> + </el-icon> + 查询 + </el-button> + <el-button size="default" type="success" class="ml10" @click="onOpenDialogRef('新增', '')"> + <el-icon> + <ele-FolderAdd /> + </el-icon> + 新增RFID + </el-button> + </div> + <el-table :data="RFIDData.data" style="width: 100%"> + <el-table-column type="index" label="序号" width="60" /> + <el-table-column prop="rfidName" label="RFID名称" show-overflow-tooltip></el-table-column> + <el-table-column prop="rfid" label="RFID编码" show-overflow-tooltip></el-table-column> + <el-table-column prop="createUserName" label="创建人" show-overflow-tooltip></el-table-column> + <el-table-column prop="gmtCreate" label="创建时间" show-overflow-tooltip></el-table-column> + <el-table-column prop="lastEditUserName" label="最后修改人" show-overflow-tooltip></el-table-column> + <el-table-column prop="gmtModitify" label="最后修改时间" show-overflow-tooltip></el-table-column> + <el-table-column label="操作" width="150"> + <template #default="scope"> + <el-button size="small" text type="primary" :icon="Edit" @click="onOpenDialogRef('修改', scope.row)">修改</el-button> + <el-button size="small" text type="danger" :icon="Delete" @click="onDelProductionDevice(scope.row)">删除</el-button> + </template> + </el-table-column> + </el-table> + <br /> + <el-pagination @size-change="onHandleSizeChange" @current-change="onHandleCurrentChange" :pager-count="5" :page-sizes="[10, 20, 30]" v-model:current-page="RFIDData.params.pageIndex" background v-model:page-size="RFIDData.params.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="RFIDData.total" class="page-position"> </el-pagination> + <br /> + <br /> + </el-card> + <RFIDDialog ref="RFIDDialogRef" @refreshRFID="initRFIDTableData" /> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, onMounted, ref, defineComponent } from 'vue'; +import { ElMessageBox, ElMessage } from 'element-plus'; +import RFIDDialog from './components/RFIDDialog.vue'; +import { RFIDApi } from '/@/api/intellectInspectSystem/RFID'; +import { Edit, View, Plus, Delete, Refresh, Search, Download } from '@element-plus/icons-vue'; +import type { UploadProps, UploadUserFile } from 'element-plus' +// 定义接口来定义对象的类型 +interface TableData { + quota: string; + quotaUnit: string; + quotaType: string; + createUserName: string; + gmtCreate: string; + lastEditUserName: string; + gmtModitify: string; +} +interface TableDataState { + RFIDData: { + data: Array<TableData>; + total: number; + loading: boolean; + params: { + pageIndex: number; + pageSize: number; + rfid: number | null; + rfidName: string | null; + }; + }; +} + +export default defineComponent({ + name: 'RFID', + components: { RFIDDialog, Edit, Delete }, + setup() { + const RFIDDialogRef = ref(); + const state = reactive<TableDataState>({ + RFIDData: { + data: [], + total: 0, + loading: false, + params: { + pageIndex: 1, + pageSize: 10, + rfid: null, + rfidName: null + } + } + }); + + // 初始化表格数据 + const initRFIDTableData = async () => { + let res = await RFIDApi().getRFIDList(state.RFIDData.params); + if (res.data.code === '200') { + state.RFIDData.data = res.data.data.records; + state.RFIDData.total = res.data.data.total; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 打开弹窗 + const onOpenDialogRef = (type: string, value: any) => { + RFIDDialogRef.value.openRFIDDialog(type, value); + }; + // 删除 + const onDelProductionDevice = (row: any) => { + ElMessageBox.confirm(`此操作将永久删除该RFID:“${row.rfidName}”,是否继续?`, '提示', { + confirmButtonText: '确认', + cancelButtonText: '取消', + type: 'warning' + }) + .then(async () => { + let res = await RFIDApi().deleteRFID({ id: row.id }); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + duration: 2000, + message: '删除成功' + }); + await initRFIDTableData(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }) + .catch(() => {}); + }; + + const handleSearch = () => { + initRFIDTableData(); + }; + // 分页改变 + const onHandleSizeChange = (val: number) => { + state.RFIDData.params.pageSize = val; + initRFIDTableData(); + }; + // 分页改变 + const onHandleCurrentChange = (val: number) => { + state.RFIDData.params.pageIndex = val; + initRFIDTableData(); + }; + // 页面加载时 + onMounted(() => { + initRFIDTableData(); + }); + + return { + Edit, + Delete, + handleSearch, + onOpenDialogRef, + onHandleSizeChange, + onDelProductionDevice, + onHandleCurrentChange, + RFIDDialog, + RFIDDialogRef, + initRFIDTableData, + ...toRefs(state) + }; + } +}); +</script> + +<style scoped> +:deep(.el-textarea.is-disabled .el-textarea__inner) { + background-color: var(--el-card-bg-color); + color: var(--el-input-text-color, var(--el-text-color-regular)); +} +:deep(.el-input.is-disabled .el-input__inner) { + color: var(--el-input-text-color, var(--el-text-color-regular)); +} +:deep(.el-input.is-disabled .el-input__wrapper) { + background-color: var(--el-card-bg-color); +} +</style> diff --git a/src/views/intellectInspect/inspectBasic/facility/components/facilityAreaDialog.vue b/src/views/intellectInspect/inspectBasic/facility/components/facilityAreaDialog.vue new file mode 100644 index 0000000..1e9ede6 --- /dev/null +++ b/src/views/intellectInspect/inspectBasic/facility/components/facilityAreaDialog.vue @@ -0,0 +1,154 @@ +<template> + <div class="system-add-menu-container"> + <el-dialog :title="title" v-model="isShowFacilityAreaDialog" width="600px"> + <el-form :model="facilityAreaForm" :rules="facilityAreaFormRules" ref="facilityAreaFormRef" size="default" label-width="120px"> + <el-row :gutter="35"> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="设备区域名称" prop="region"> + <el-input class="input-length" v-model.trim="facilityAreaForm.region" placeholder="请输入设备区域名称" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="设备区域类型" prop="regionTypeId"> + <el-select class="input-length" v-model="facilityAreaForm.regionTypeId" placeholder="请选择设备区域类型" clearable filterable> + <el-option v-for="item in facilityAreaTypeList" :key="item.id" :label="item.regionType" :value="item.id"></el-option> + </el-select> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="isShowFacilityAreaDialog = !isShowFacilityAreaDialog" size="default">取 消</el-button> + <el-button type="primary" @click="submitFacilityArea" v-throttle size="default">确 定</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script lang="ts"> +interface stateType { + isShowFacilityAreaDialog: Boolean; + facilityAreaForm: { + region: string; + regionTypeId: number | null; + }; + title: string; + facilityAreaTypeList: Array<facilityAreaTypeState>; + facilityAreaFormRules: {}; +} +interface facilityAreaTypeState { + regionType: string; + id: number; +} + +import { reactive, toRefs, ref } from 'vue'; +import { facilityAreaApi } from '/@/api/intellectInspectSystem/facilityAreaManage'; +import { ElMessage } from 'element-plus'; +export default { + name: 'facilityAreaDialog', + setup(props: any, context: any) { + const facilityAreaFormRef = ref(); + const state = reactive<stateType>({ + title: '', + facilityAreaTypeList: [], + isShowFacilityAreaDialog: false, + facilityAreaForm: { + region: '', + regionTypeId: null + }, + facilityAreaFormRules: { + region: [{ required: true, message: '请填写设备区域名称', trigger: 'blur' }], + regionTypeId: [{ required: true, message: '请选择设备区域类型', trigger: 'change' }] + } + }); + + //打开模态框 + const openFacilityAreaDialog = (type: string, value: { id: number; region: string; regionTypeId: number }, facilityAreaTypeList: Array<facilityAreaTypeState>) => { + state.isShowFacilityAreaDialog = true; + state.facilityAreaTypeList = facilityAreaTypeList.filter((item) => item.regionType !== '所有类型'); + setTimeout(() => { + facilityAreaFormRef.value.clearValidate(); + }); + if (type === '新增') { + state.title = '新增设备区域'; + state.facilityAreaForm = { + region: '', + regionTypeId: null + }; + } else { + state.title = '修改设备区域'; + facilityAreaApi() + .getFacilityAreaById({ id: value.id }) + .then((res) => { + if (res.data.code === '200') { + state.facilityAreaForm = JSON.parse(JSON.stringify(res.data.data)); + } else { + } + }) + .catch((error) => {}); + } + }; + + //新增修改提交 + const submitFacilityArea = async () => { + facilityAreaFormRef.value.validate(async (valid: Boolean) => { + if (valid) { + if (state.title === '新增设备区域') { + let res = await facilityAreaApi().addFacilityArea(state.facilityAreaForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '设备区域新增成功', + duration: 2000 + }); + state.isShowFacilityAreaDialog = false; + context.emit('refreshFacilityArea'); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } else { + let res = await facilityAreaApi().modFacilityArea(state.facilityAreaForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '设备区域修改成功', + duration: 2000 + }); + state.isShowFacilityAreaDialog = false; + context.emit('refreshFacilityArea'); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } + } else { + ElMessage({ + type: 'warning', + message: '请完善基本信息' + }); + } + }); + }; + + return { + ...toRefs(state), + facilityAreaFormRef, + submitFacilityArea, + openFacilityAreaDialog + }; + } +}; +</script> + +<style scoped> +.input-length { + width: 85%; +} +</style> diff --git a/src/views/intellectInspect/inspectBasic/facility/index.vue b/src/views/intellectInspect/inspectBasic/facility/index.vue new file mode 100644 index 0000000..76c6efc --- /dev/null +++ b/src/views/intellectInspect/inspectBasic/facility/index.vue @@ -0,0 +1,201 @@ +<template> + <div class="system-role-container"> + <el-card shadow="hover"> + <div class="system-user-search mb15"> + <div class="basic-line"> + <span>设备区域名称:</span> + <el-input class="input-box" v-model="facilityAreaData.params.regionName" placeholder="设备区域名称" clearable> </el-input> + </div> + <div class="basic-line"> + <span>设备区域类型:</span> + <el-select class="input-box" v-model="facilityAreaData.params.regionTypeId" placeholder="设备区域类型" filterable> + <el-option v-for="item in facilityAreaTypeList" :key="item.id" :label="item.regionType" :value="item.id"></el-option> + </el-select> + </div> + <el-button size="default" type="primary" class="ml10" v-throttle @click="handleSearch"> + <el-icon> + <ele-Search /> + </el-icon> + 查询 + </el-button> + <el-button size="default" type="success" class="ml10" @click="onOpenDialogRef('新增', '')"> + <el-icon> + <ele-FolderAdd /> + </el-icon> + 新增设备区域 + </el-button> + </div> + <el-table :data="facilityAreaData.data" style="width: 100%"> + <el-table-column type="index" label="序号" width="60" /> + <el-table-column prop="region" label="设备区域名称" show-overflow-tooltip></el-table-column> + <el-table-column prop="regionType" label="设备区域类型" show-overflow-tooltip></el-table-column> + <el-table-column prop="createByUserName" label="创建人" show-overflow-tooltip></el-table-column> + <el-table-column prop="gmtCreate" label="创建时间" show-overflow-tooltip></el-table-column> + <el-table-column prop="lastEditUserName" label="最后修改人" show-overflow-tooltip></el-table-column> + <el-table-column prop="gmtModitify" label="最后修改时间" show-overflow-tooltip></el-table-column> + <el-table-column label="操作" width="150"> + <template #default="scope"> + <el-button size="small" text type="primary" :icon="Edit" @click="onOpenDialogRef('修改', scope.row)">修改</el-button> + <el-button size="small" text type="danger" :icon="Delete" @click="onDelProductionDevice(scope.row)">删除</el-button> + </template> + </el-table-column> + </el-table> + <br /> + <el-pagination @size-change="onHandleSizeChange" @current-change="onHandleCurrentChange" :pager-count="5" :page-sizes="[10, 20, 30]" v-model:current-page="facilityAreaData.params.pageIndex" background v-model:page-size="facilityAreaData.params.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="facilityAreaData.total" class="page-position"> </el-pagination> + <br /> + <br /> + </el-card> + <facilityAreaDialog ref="facilityAreaDialogRef" @refreshFacilityArea="initFacilityAreaTableData" /> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, onMounted, ref, defineComponent } from 'vue'; +import { ElMessageBox, ElMessage } from 'element-plus'; +import facilityAreaDialog from './components/facilityAreaDialog.vue'; +import { facilityAreaApi } from '/@/api/intellectInspectSystem/facilityAreaManage'; +import { Edit, View, Plus, Delete, Refresh, Search, Download } from '@element-plus/icons-vue'; + +// 定义接口来定义对象的类型 +interface TableData { + quota: string; + quotaUnit: string; + quotaType: string; + createUserName: string; + gmtCreate: string; + lastEditUserName: string; + gmtModitify: string; +} +interface TableDataState { + facilityAreaData: { + data: Array<TableData>; + total: number; + loading: boolean; + params: { + pageIndex: number; + pageSize: number; + regionTypeId: number; + regionName: string | null; + }; + }; + facilityAreaTypeList: Array<facilityAreaTypeState>; +} + +interface facilityAreaTypeState { + regionType: string; + id: number; +} + +export default defineComponent({ + name: 'facilityArea', + components: { facilityAreaDialog, Edit, Delete }, + setup() { + const facilityAreaDialogRef = ref(); + const state = reactive<TableDataState>({ + facilityAreaData: { + data: [], + total: 0, + loading: false, + params: { + pageIndex: 1, + pageSize: 10, + regionTypeId: 1, + regionName: null + } + }, + facilityAreaTypeList: [] + }); + // 初始化表格数据 + const initFacilityAreaTableData = async () => { + let res = await facilityAreaApi().getFacilityAreaList(state.facilityAreaData.params); + if (res.data.code === '200') { + state.facilityAreaData.data = res.data.data.records; + state.facilityAreaData.total = res.data.data.total; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + //获取所有设施区域类型 + const initFacilityAreaType = async () => { + let res = await facilityAreaApi().getFacilityAreaType(); + if (res.data.code === '200') { + state.facilityAreaTypeList = res.data.data; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 打开弹窗 + const onOpenDialogRef = (type: string, value: any) => { + facilityAreaDialogRef.value.openFacilityAreaDialog(type, value, state.facilityAreaTypeList); + }; + // 删除 + const onDelProductionDevice = (row: any) => { + ElMessageBox.confirm(`此操作将永久删除该条设备区域:“${row.region}”,是否继续?`, '提示', { + confirmButtonText: '确认', + cancelButtonText: '取消', + type: 'warning' + }) + .then(async () => { + let res = await facilityAreaApi().deleteFacilityArea({ id: row.id }); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + duration: 2000, + message: '删除成功' + }); + await initFacilityAreaTableData(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }) + .catch(() => {}); + }; + + const handleSearch = () => { + initFacilityAreaTableData(); + }; + // 分页改变 + const onHandleSizeChange = (val: number) => { + state.facilityAreaData.params.pageSize = val; + initFacilityAreaTableData(); + }; + // 分页改变 + const onHandleCurrentChange = (val: number) => { + state.facilityAreaData.params.pageIndex = val; + initFacilityAreaTableData(); + }; + // 页面加载时 + onMounted(() => { + initFacilityAreaTableData(); + initFacilityAreaType(); + }); + + return { + Edit, + Delete, + handleSearch, + onOpenDialogRef, + onHandleSizeChange, + onDelProductionDevice, + onHandleCurrentChange, + facilityAreaDialog, + facilityAreaDialogRef, + initFacilityAreaTableData, + ...toRefs(state) + }; + } +}); +</script> + +<style scoped></style> diff --git a/src/views/intellectInspect/inspectBasic/index.vue b/src/views/intellectInspect/inspectBasic/index.vue new file mode 100644 index 0000000..ea0d797 --- /dev/null +++ b/src/views/intellectInspect/inspectBasic/index.vue @@ -0,0 +1,9 @@ +<template></template> + +<script> +export default { + name: 'index' +}; +</script> + +<style scoped></style> diff --git a/src/views/intellectInspect/inspectBasic/inspectPoint/components/inspectPointDialog.vue b/src/views/intellectInspect/inspectBasic/inspectPoint/components/inspectPointDialog.vue new file mode 100644 index 0000000..1184f3c --- /dev/null +++ b/src/views/intellectInspect/inspectBasic/inspectPoint/components/inspectPointDialog.vue @@ -0,0 +1,166 @@ +<template> + <div class="system-add-menu-container"> + <el-dialog :title="title" v-model="isShowInspectPointDialog" width="600px"> + <el-form :model="inspectPointForm" :rules="inspectPointFormRules" ref="inspectPointFormRef" size="default" label-width="120px"> + <el-row :gutter="35"> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="巡检点名称" prop="code"> + <el-input class="input-length" v-model.trim="inspectPointForm.code" placeholder="请输入巡检点名称" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="所属设备区域" prop="regionId"> + <el-select class="input-length" v-model="inspectPointForm.regionId" placeholder="请选择所属设备区域" clearable filterable> + <el-option v-for="item in regionNameList" :key="item.id" :label="item.region" :value="item.id"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="关联RFID" prop="rfidId"> + <el-select class="input-length" v-model="inspectPointForm.rfidId" placeholder="请选择关联RFID" clearable filterable> + <el-option v-for="item in RFIDList" :key="item.id" :label="item.rfidName" :value="item.id"></el-option> + </el-select> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="isShowInspectPointDialog = !isShowInspectPointDialog" size="default">取 消</el-button> + <el-button type="primary" @click="submitInspectPoint" v-throttle size="default">确 定</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script lang="ts"> +import { facilityAreaApi } from '/@/api/intellectInspectSystem/facilityAreaManage'; + +interface stateType { + isShowInspectPointDialog: Boolean; + inspectPointForm: { + code: string; + regionId: number | null; + rfidId: number | null; + }; + title: string; + regionNameList: []; + RFIDList: Array<levelListState>; + inspectPointFormRules: {}; +} +interface levelListState {} +import { reactive, toRefs, ref } from 'vue'; +import { inspectPointApi } from '/@/api/intellectInspectSystem/inspectPointManage'; +import { ElMessage } from 'element-plus'; +export default { + name: 'inspectPointDialog', + setup(props: any, context: any) { + const inspectPointFormRef = ref(); + const state = reactive<stateType>({ + title: '', + isShowInspectPointDialog: false, + inspectPointForm: { + code: '', + regionId: null, + rfidId: null + }, + regionNameList: [], + RFIDList: [], + inspectPointFormRules: { + code: [{ required: true, message: '请填写巡检点名称', trigger: 'blur' }], + regionId: [{ required: true, message: '请选择所属设施区域', trigger: 'change' }], + rfidId: [{ required: true, message: '请选择关联RFID', trigger: 'change' }] + } + }); + + //打开模态框 + const openInspectPointDialog = (type: string, value: { id: number }, regionNameList: [], RFIDList: []) => { + state.isShowInspectPointDialog = true; + state.regionNameList = regionNameList; + state.RFIDList = RFIDList; + setTimeout(() => { + inspectPointFormRef.value.clearValidate(); + }); + if (type === '新增') { + state.title = '新增巡检点'; + state.inspectPointForm = { + code: '', + regionId: null, + rfidId: null + }; + } else { + state.title = '修改巡检点'; + inspectPointApi() + .getInspectPointById({ id: value.id }) + .then((res) => { + if (res.data.code === '200') { + state.inspectPointForm = JSON.parse(JSON.stringify(res.data.data)); + } else { + } + }) + .catch((error) => {}); + } + }; + + //新增修改提交 + const submitInspectPoint = async () => { + inspectPointFormRef.value.validate(async (valid: Boolean) => { + if (valid) { + if (state.title === '新增巡检点') { + let res = await inspectPointApi().addInspectPoint(state.inspectPointForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '巡检点新增成功', + duration: 2000 + }); + state.isShowInspectPointDialog = false; + context.emit('refreshInspectPoint'); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } else { + let res = await inspectPointApi().modInspectPoint(state.inspectPointForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '巡检点修改成功', + duration: 2000 + }); + state.isShowInspectPointDialog = false; + context.emit('refreshInspectPoint'); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } + } else { + ElMessage({ + type: 'warning', + message: '请完善基本信息' + }); + } + }); + }; + + return { + ...toRefs(state), + inspectPointFormRef, + submitInspectPoint, + openInspectPointDialog + }; + } +}; +</script> + +<style scoped> +.input-length { + width: 85%; +} +</style> diff --git a/src/views/intellectInspect/inspectBasic/inspectPoint/index.vue b/src/views/intellectInspect/inspectBasic/inspectPoint/index.vue new file mode 100644 index 0000000..62064e6 --- /dev/null +++ b/src/views/intellectInspect/inspectBasic/inspectPoint/index.vue @@ -0,0 +1,217 @@ +<template> + <div class="system-role-container"> + <el-card shadow="hover"> + <div class="system-user-search mb15"> + <div class="basic-line"> + <span>巡检点名称:</span> + <el-input class="input-box" v-model="inspectPointData.params.code" placeholder="巡检点名称" clearable> </el-input> + </div> + <div class="basic-line"> + <span>所属区域名称:</span> + <el-select class="input-box" v-model="inspectPointData.params.regionId" placeholder="所属区域名称" filterable> + <el-option v-for="item in regionNameList" :key="item.id" :label="item.region" :value="item.id"></el-option> + </el-select> + </div> + <el-button size="default" type="primary" class="ml10" v-throttle @click="handleSearch"> + <el-icon> + <ele-Search /> + </el-icon> + 查询 + </el-button> + <el-button size="default" type="success" class="ml10" @click="onOpenDialogRef('新增', '')"> + <el-icon> + <ele-FolderAdd /> + </el-icon> + 新增巡检点 + </el-button> + </div> + <el-table :data="inspectPointData.data" style="width: 100%"> + <el-table-column type="index" label="序号" width="60" /> + <el-table-column prop="code" label="巡检点名称" show-overflow-tooltip></el-table-column> + <el-table-column prop="regionName" label="所属设备区域" show-overflow-tooltip></el-table-column> + <el-table-column prop="rfidName" label="关联RFID" show-overflow-tooltip></el-table-column> + <el-table-column prop="createUserName" label="创建人" show-overflow-tooltip></el-table-column> + <el-table-column prop="gmtCreate" label="创建时间" show-overflow-tooltip></el-table-column> + <el-table-column prop="lastEditUserName" label="最后修改人" show-overflow-tooltip></el-table-column> + <el-table-column prop="gmtModitify" label="最后修改时间" show-overflow-tooltip></el-table-column> + <el-table-column label="操作" width="150"> + <template #default="scope"> + <el-button size="small" text type="primary" :icon="Edit" @click="onOpenDialogRef('修改', scope.row)">修改</el-button> + <el-button size="small" text type="danger" :icon="Delete" @click="onDelProductionDevice(scope.row)">删除</el-button> + </template> + </el-table-column> + </el-table> + <br /> + <el-pagination @size-change="onHandleSizeChange" @current-change="onHandleCurrentChange" :pager-count="5" :page-sizes="[10, 20, 30]" v-model:current-page="inspectPointData.params.pageIndex" background v-model:page-size="inspectPointData.params.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="inspectPointData.total" class="page-position"> </el-pagination> + <br /> + <br /> + </el-card> + <inspectPointDialog ref="inspectPointDialogRef" @refreshInspectPoint="initInspectPointTableData" /> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, onMounted, ref, defineComponent } from 'vue'; +import { ElMessageBox, ElMessage } from 'element-plus'; +import inspectPointDialog from './components/inspectPointDialog.vue'; +import { inspectPointApi } from '/@/api/intellectInspectSystem/inspectPointManage'; +import { facilityAreaApi } from '/@/api/intellectInspectSystem/facilityAreaManage'; +import { Edit, View, Plus, Delete, Refresh, Search, Download } from '@element-plus/icons-vue'; +import { RFIDApi } from '/@/api/intellectInspectSystem/RFID'; + +// 定义接口来定义对象的类型 +interface TableData { + quota: string; + quotaUnit: string; + quotaType: string; + createUserName: string; + gmtCreate: string; + lastEditUserName: string; + gmtModitify: string; +} +interface TableDataState { + inspectPointData: { + data: Array<TableData>; + total: number; + loading: boolean; + params: { + pageIndex: number; + pageSize: number; + code: string | null; + regionId: number; + }; + }; + regionNameList: Array<regionNameState>; + RFIDList: []; +} + +interface regionNameState {} + +export default defineComponent({ + name: 'productionDevice', + components: { inspectPointDialog, Edit, Delete }, + setup() { + const inspectPointDialogRef = ref(); + const state = reactive<TableDataState>({ + inspectPointData: { + data: [], + total: 0, + loading: false, + params: { + pageIndex: 1, + pageSize: 10, + code: null, + regionId: 1 + } + }, + regionNameList: [], + RFIDList: [] + }); + // 初始化表格数据 + const initInspectPointTableData = async () => { + let res = await inspectPointApi().getInspectPointList(state.inspectPointData.params); + if (res.data.code === '200') { + state.inspectPointData.data = res.data.data.records; + state.inspectPointData.total = res.data.data.total; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + //获取所有设施区域名称 + const initFacilityAreaType = async () => { + let res = await facilityAreaApi().getAllFacilityAreaList(); + if (res.data.code === '200') { + state.regionNameList = JSON.parse(JSON.stringify(res.data.data)); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + //获取所有RFID名称 + const initRFIDList = async () => { + let res = await RFIDApi().getAllRFIDList(); + if (res.data.code === '200') { + state.RFIDList = JSON.parse(JSON.stringify(res.data.data)); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 打开弹窗 + const onOpenDialogRef = (type: string, value: any) => { + inspectPointDialogRef.value.openInspectPointDialog(type, value, state.regionNameList, state.RFIDList); + }; + // 删除 + const onDelProductionDevice = (row: any) => { + ElMessageBox.confirm(`此操作将永久删除该巡检点:“${row.code}”,是否继续?`, '提示', { + confirmButtonText: '确认', + cancelButtonText: '取消', + type: 'warning' + }) + .then(async () => { + let res = await inspectPointApi().deleteInspectPoint({ id: row.id }); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + duration: 2000, + message: '删除成功' + }); + await initInspectPointTableData(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }) + .catch(() => {}); + }; + + const handleSearch = () => { + initInspectPointTableData(); + }; + // 分页改变 + const onHandleSizeChange = (val: number) => { + state.inspectPointData.params.pageSize = val; + initInspectPointTableData(); + }; + // 分页改变 + const onHandleCurrentChange = (val: number) => { + state.inspectPointData.params.pageIndex = val; + initInspectPointTableData(); + }; + // 页面加载时 + onMounted(() => { + initInspectPointTableData(); + initFacilityAreaType(); + initRFIDList(); + }); + + return { + Edit, + Delete, + handleSearch, + onOpenDialogRef, + onHandleSizeChange, + onDelProductionDevice, + onHandleCurrentChange, + inspectPointDialog, + inspectPointDialogRef, + initInspectPointTableData, + ...toRefs(state) + }; + } +}); +</script> + +<style scoped></style> diff --git a/src/views/intellectInspect/inspectBasic/inspectTarget/components/inspectTargetDialog.vue b/src/views/intellectInspect/inspectBasic/inspectTarget/components/inspectTargetDialog.vue new file mode 100644 index 0000000..a15475d --- /dev/null +++ b/src/views/intellectInspect/inspectBasic/inspectTarget/components/inspectTargetDialog.vue @@ -0,0 +1,164 @@ +<template> + <div class="system-add-menu-container"> + <el-dialog :title="title" v-model="isShowInspectTargetDialog" width="600px"> + <el-form :model="inspectTargetForm" :rules="inspectTargetFormRules" ref="inspectTargetFormRef" size="default" label-width="120px"> + <el-row :gutter="35"> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="指标名称" prop="quota"> + <el-input class="input-add" v-model.trim="inspectTargetForm.quota" placeholder="请输入指标名称" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="指标类型" prop="quotaTypeId"> + <el-select class="input-add" v-model="inspectTargetForm.quotaTypeId" @change="changeQuotaUnit" placeholder="请选择指标类型" clearable filterable> + <el-option v-for="item in quotaTypeList" :key="item.id" :label="item.type" :value="item.id"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="指标单位" prop="quotaUnit"> + <el-input class="input-add" v-model.trim="inspectTargetForm.quotaUnit" type="textarea" placeholder="请输入指标单位" maxlength="150"></el-input> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="isShowInspectTargetDialog = !isShowInspectTargetDialog" size="default">取 消</el-button> + <el-button type="primary" @click="submitInspectTarget" v-throttle size="default">确 定</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script lang="ts"> +interface stateType { + isShowInspectTargetDialog: Boolean; + inspectTargetForm: { + quota: string; + quotaTypeId: number | null; + quotaUnit: string; + }; + title: string; + quotaTypeList: Array<quotaTypeState>; + inspectTargetFormRules: {}; +} +interface quotaTypeState { + id: number; + type: string; + unit: string; +} +import { reactive, toRefs, ref, computed } from 'vue'; +import { inspectTargetApi } from '/@/api/intellectInspectSystem/inspectTargetManage'; +import { ElMessage } from 'element-plus'; +export default { + name: 'inspectTargetDialog', + setup(props: any, context: any) { + const inspectTargetFormRef = ref(); + const state = reactive<stateType>({ + title: '', + quotaTypeList: [], + isShowInspectTargetDialog: false, + inspectTargetForm: { + quota: '', + quotaTypeId: null, + quotaUnit: '' + }, + inspectTargetFormRules: { + quota: [{ required: true, message: '请填写指标名称', trigger: 'blur' }], + quotaTypeId: [{ required: true, message: '请选择指标类型', trigger: 'change' }], + quotaUnit: [{ required: true, message: '请选择指标单位', trigger: 'blur' }] + } + }); + + //打开模态框 + const openInspectTargetDialog = (type: string, value: { id: number }, quotaTypeList: []) => { + state.isShowInspectTargetDialog = true; + state.quotaTypeList = quotaTypeList; + setTimeout(() => { + inspectTargetFormRef.value.clearValidate(); + }); + if (type === '新增') { + state.title = '新增巡检指标'; + state.inspectTargetForm = { + quota: '', + quotaTypeId: null, + quotaUnit: '' + }; + } else { + state.title = '修改巡检指标'; + inspectTargetApi() + .getInspectTargetById(value.id) + .then((res) => { + if (res.data.code === '200') { + state.inspectTargetForm = JSON.parse(JSON.stringify(res.data.data)); + } else { + } + }) + .catch((error) => {}); + } + }; + + const changeQuotaUnit = () => { + state.inspectTargetForm.quotaUnit = JSON.parse(JSON.stringify(state.quotaTypeList)).find((item: any) => item.id === state.inspectTargetForm.quotaTypeId).unit; + }; + + //新增修改提交 + const submitInspectTarget = async () => { + inspectTargetFormRef.value.validate(async (valid: Boolean) => { + if (valid) { + if (state.title === '新增巡检指标') { + let res = await inspectTargetApi().addInspectTarget(state.inspectTargetForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '巡检指标新增成功', + duration: 2000 + }); + state.isShowInspectTargetDialog = false; + context.emit('refreshInspectTarget'); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } else { + let res = await inspectTargetApi().modInspectTarget(state.inspectTargetForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '生巡检指标修改成功', + duration: 2000 + }); + state.isShowInspectTargetDialog = false; + context.emit('refreshInspectTarget'); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } + } else { + ElMessage({ + type: 'warning', + message: '请完善基本信息' + }); + } + }); + }; + + return { + ...toRefs(state), + changeQuotaUnit, + inspectTargetFormRef, + submitInspectTarget, + openInspectTargetDialog + }; + } +}; +</script> + +<style scoped></style> diff --git a/src/views/intellectInspect/inspectBasic/inspectTarget/index.vue b/src/views/intellectInspect/inspectBasic/inspectTarget/index.vue new file mode 100644 index 0000000..4308c50 --- /dev/null +++ b/src/views/intellectInspect/inspectBasic/inspectTarget/index.vue @@ -0,0 +1,191 @@ +<template> + <div class="system-role-container"> + <el-card shadow="hover"> + <div class="system-user-search mb15"> + <div class="basic-line"> + <span>巡检指标名称:</span> + <el-input class="input-box" v-model="inspectTargetData.params.quotaName" placeholder="巡检指标名称"> </el-input> + </div> + <el-button size="default" type="primary" class="ml10" v-throttle @click="handleSearch"> + <el-icon> + <ele-Search /> + </el-icon> + 查询 + </el-button> + <el-button size="default" type="success" class="ml10" @click="onOpenDialogRef('新增', '')"> + <el-icon> + <ele-FolderAdd /> + </el-icon> + 新增巡检指标 + </el-button> + </div> + <el-table :data="inspectTargetData.data" style="width: 100%"> + <el-table-column type="index" label="序号" width="60" /> + <el-table-column prop="quota" label="指标名称" show-overflow-tooltip></el-table-column> + <el-table-column prop="quotaUnit" label="指标单位" show-overflow-tooltip></el-table-column> + <el-table-column prop="quotaType" label="指标类型" show-overflow-tooltip></el-table-column> + <el-table-column prop="createUserName" label="创建人" show-overflow-tooltip></el-table-column> + <el-table-column prop="gmtCreate" label="创建时间" show-overflow-tooltip></el-table-column> + <el-table-column prop="lastEditUserName" label="最后修改人" show-overflow-tooltip></el-table-column> + <el-table-column prop="gmtModitify" label="最后修改时间" show-overflow-tooltip></el-table-column> + <el-table-column label="操作" width="150"> + <template #default="scope"> + <el-button size="small" text type="primary" :icon="Edit" @click="onOpenDialogRef('修改', scope.row)">修改</el-button> + <el-button size="small" text type="danger" :icon="Delete" @click="onDelProductionDevice(scope.row)">删除</el-button> + </template> + </el-table-column> + </el-table> + <br /> + <el-pagination @size-change="onHandleSizeChange" @current-change="onHandleCurrentChange" :pager-count="5" :page-sizes="[10, 20, 30]" v-model:current-page="inspectTargetData.params.pageIndex" background v-model:page-size="inspectTargetData.params.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="inspectTargetData.total" class="page-position"> </el-pagination> + <br /> + <br /> + </el-card> + <inspectTargetDialog ref="inspectTargetDialogRef" @refreshInspectTarget="initInspectTargetTableData" /> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, onMounted, ref, defineComponent, computed } from 'vue'; +import { ElMessageBox, ElMessage } from 'element-plus'; +import inspectTargetDialog from './components/inspectTargetDialog.vue'; +import { inspectTargetApi } from '/@/api/intellectInspectSystem/inspectTargetManage'; +import { Edit, View, Plus, Delete, Refresh, Search, Download } from '@element-plus/icons-vue'; +import { facilityAreaApi } from '/@/api/intellectInspectSystem/facilityAreaManage'; + +// 定义接口来定义对象的类型 +interface TableData { + quota: string; + quotaUnit: string; + quotaType: string; + createUserName: string; + gmtCreate: string; + lastEditUserName: string; + gmtModitify: string; +} +interface TableDataState { + inspectTargetData: { + data: Array<TableData>; + total: number; + loading: boolean; + params: { + pageIndex: number; + pageSize: number; + quotaName: string; + }; + }; + quotaTypeList: []; +} + +export default defineComponent({ + name: 'productionDevice', + components: { inspectTargetDialog, Edit, Delete }, + setup() { + const inspectTargetDialogRef = ref(); + const state = reactive<TableDataState>({ + inspectTargetData: { + data: [], + total: 0, + loading: false, + params: { + pageIndex: 1, + pageSize: 10, + quotaName: '' + } + }, + quotaTypeList: [] + }); + + // 初始化表格数据 + const initInspectTargetTableData = async () => { + let res = await inspectTargetApi().getInspectTargetList(state.inspectTargetData.params); + if (res.data.code === '200') { + state.inspectTargetData.data = res.data.data.records; + state.inspectTargetData.total = res.data.data.total; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + //获取所有指标类型及单位 + const initQuotaType = async () => { + let res = await inspectTargetApi().getQuotaTypeList(); + if (res.data.code === '200') { + state.quotaTypeList = JSON.parse(JSON.stringify(res.data.data)); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 打开生产装置弹窗 + const onOpenDialogRef = (type: string, value: any) => { + inspectTargetDialogRef.value.openInspectTargetDialog(type, value, state.quotaTypeList); + }; + // 删除角色 + const onDelProductionDevice = (row: any) => { + ElMessageBox.confirm(`此操作将永久删除该条巡检指标:“${row.quota}”,是否继续?`, '提示', { + confirmButtonText: '确认', + cancelButtonText: '取消', + type: 'warning' + }) + .then(async () => { + let res = await inspectTargetApi().deleteInspectTarget({ id: row.id }); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + duration: 2000, + message: '删除成功' + }); + await initInspectTargetTableData(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }) + .catch(() => {}); + }; + + const handleSearch = () => { + initInspectTargetTableData(); + }; + // 分页改变 + const onHandleSizeChange = (val: number) => { + state.inspectTargetData.params.pageSize = val; + initInspectTargetTableData(); + }; + // 分页改变 + const onHandleCurrentChange = (val: number) => { + state.inspectTargetData.params.pageIndex = val; + initInspectTargetTableData(); + }; + // 页面加载时 + onMounted(() => { + initInspectTargetTableData(); + initQuotaType(); + }); + + return { + Edit, + Delete, + handleSearch, + onOpenDialogRef, + onHandleSizeChange, + onDelProductionDevice, + onHandleCurrentChange, + inspectTargetDialog, + inspectTargetDialogRef, + initInspectTargetTableData, + ...toRefs(state) + }; + } +}); +</script> + +<style scoped></style> diff --git a/src/views/intellectInspect/inspectIndex/components/inspectRecordDialog.vue b/src/views/intellectInspect/inspectIndex/components/inspectRecordDialog.vue new file mode 100644 index 0000000..02fdd0a --- /dev/null +++ b/src/views/intellectInspect/inspectIndex/components/inspectRecordDialog.vue @@ -0,0 +1,592 @@ +<template> + <div class="system-add-menu-container"> + <el-dialog v-model="ifShowInspectTaskDialog" :title="title" width="60%"> + <el-form :model="inspectTaskForm" label-width="120px" ref="inspectTaskFormRef"> + <el-row> + <el-col :span="12" style="margin-bottom: 20px"> + <el-form-item label="任务名称" prop="unitName"> + <el-input v-model="inspectTaskForm.taskName" :disabled="!inspectPointConfirm" class="input-add" placeholder="请填写任务名称"> </el-input> + </el-form-item> + </el-col> + <el-col :span="12" style="margin-bottom: 20px"> + <el-form-item label="任务类型" prop="taskType"> + <el-select v-model="inspectTaskForm.taskType" :disabled="!inspectPointConfirm" class="input-add" placeholder="请选择任务类型"> + <el-option v-for="item in workTypeList" :key="item.id" :value="item.id" :label="item.name"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :span="12" style="margin-bottom: 20px"> + <el-form-item label="巡检部门" prop="execDepId"> + <el-cascader @change="giveClassGroup" :disabled="!inspectPointConfirm" :options="departmentList" :props="{ emitPath: false, checkStrictly: true, value: 'depId', label: 'depName' }" clearable filterable class="input-add" v-model="inspectTaskForm.execDepId"> </el-cascader> + </el-form-item> + </el-col> + <el-col :span="12" style="margin-bottom: 20px"> + <el-form-item label="巡检班组" prop="execClassgroupId"> + <el-select v-model="inspectTaskForm.execClassgroupId" :disabled="!inspectPointConfirm" class="input-add"> + <el-option v-for="item in classGroup" :key="item.id" :value="item.id" :label="item.groupName"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :span="12" style="margin-bottom: 20px"> + <el-form-item label="巡检人" prop="execUserName"> + <el-input v-model="inspectTaskForm.execUserName" :disabled="!inspectPointConfirm" class="input-add"> </el-input> + </el-form-item> + </el-col> + <el-col :span="12" style="margin-bottom: 20px"> + <el-form-item label="任务开始时间" prop="startTime"> + <el-date-picker v-model="inspectTaskForm.startTime" :disabled="!inspectPointConfirm" placeholder="请选择任务开始时间" type="datetime" format="YYYY/MM/DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss" class="input-add" /> + </el-form-item> + </el-col> + </el-row> + + <div class="checkUnit-point"> + <el-tabs class="active" v-model="activeName"> + <el-tab-pane label="巡检链" name="inspectChain"> + <el-table :data="inspectTaskForm.points" fit style="width: 100%"> + <el-table-column type="index" label="序号" /> + <el-table-column prop="point" label="巡检点" show-overflow-tooltip align="center"></el-table-column> + <el-table-column prop="region" label="所属设备" show-overflow-tooltip align="center"></el-table-column> + <el-table-column prop="rfid" label="RFID" show-overflow-tooltip align="center"></el-table-column> + <el-table-column prop="quotaContent" label="指标作业" show-overflow-tooltip align="center"></el-table-column> + <el-table-column prop="secondReferenceResult" label="记录值" show-overflow-tooltip align="center"> + <template #default="scope"> + <div :style="{ color: scope.row.reportResult == 1 ? '#ff0000' : '#409eff' }"> + {{ scope.row.dataReportType == 1 ? '无' : scope.row.secondReferenceResult }} + </div> + </template> + </el-table-column> + <el-table-column prop="quotaUnit" label="指标单位" show-overflow-tooltip align="center"></el-table-column> + <el-table-column prop="reportResult" label="结果" show-overflow-tooltip align="center"> + <template #default="scope"> + <div :style="{ color: scope.row.reportResult == 1 ? '#ff0000' : '#409eff' }"> + {{ scope.row.reportResult == 0 ? '正常' : scope.row.reportResult == 1 ? '存在异常' : '无' }} + </div> + </template> + </el-table-column> + <!-- <el-table-column label="操作" width="150" align="center">--> + <!-- <template #default="scope">--> + <!-- <el-button size="small" text type="danger" @click="onDelCheckUnit(scope.$index, scope.row)">删除</el-button>--> + <!-- </template>--> + <!-- </el-table-column>--> + </el-table> + </el-tab-pane> + <el-tab-pane label="统计数据" name="allData"> + <sum-data :sumData="taskAndQuotas"></sum-data> + </el-tab-pane> + </el-tabs> + </div> + <div align="right" v-show="inspectPointConfirm"> + <el-button type="warning" @click="inspectPointDialog = false" size="default" plain>取消</el-button> + <el-button type="primary" @click="submitInspectTask()" size="default">确认</el-button> + </div> + </el-form> + </el-dialog> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, defineComponent, ref, onMounted, defineAsyncComponent } from 'vue'; +import { RFIDApi } from '/@/api/intellectInspectSystem/RFID'; +import { ElMessage } from 'element-plus/es'; +import { inspectTaskApi } from '/@/api/intellectInspectSystem/inspectTask'; +import { facilityAreaApi } from '/@/api/intellectInspectSystem/facilityAreaManage'; +import { inspectRecordApi } from '/@/api/intellectInspectSystem/inspectRecord'; +interface dataState { + title: string; + taskAndQuotas: []; + pointTitle: string; + activeName: string; + inspectPointConfirm: boolean; + inspectPointDialog: boolean; + ifShowInspectTaskDialog: boolean; + inspectPointForm: inspectPointForm; + inspectTaskForm: { + execClassgroupId: number | null; + execDepId: number | null; + id: number | null; + execUserName: string; + startTime: string | null; + taskName: string | null; + taskType: number | null; + validTime: string | null; + points: Array<inspectPointForm>; + }; + workTypeList: []; + departmentList: []; + timeList: []; + dataReportTypeList: Array<dataReport>; + firstReferenceValueList: Array<dataReport>; + secondReferenceSignList: Array<dataReport>; + thirdReferenceSignList: Array<dataReport>; + classGroupList: Array<classGroup>; + classGroup: Array<classGroup>; + quotaList: Array<quota>; + inspectPointAllList: Array<inspectPointAllState>; +} +interface inspectPointAllState { + id: number; + code: string; + regionId: number; + rfidId: number; +} +interface classGroup { + depId: number; +} +interface dataReport { + id: number; + name: string; +} +interface quota { + id: number; + type: string; + unit: string; +} +interface inspectPointForm { + id: number | null; + unitId: number | null; + unitUuid: string | null; + pointId: number | null; + pointUuid: string | null; + regionId: number | null; + regionUuid: string | null; + rfidId: number | null; + quotaId: number | null; + quotaUnit: string | null; + reportResult: number | null; + secondReferenceResult: number | null; + execSequence: number | null; + dataReportType: number | null; + firstReferenceValue: number | null; + secondReferenceSign: number | null; + secondReferenceValue: number | null; + thirdReferenceSign: number | null; + thirdReferenceValue: number | null; +} +export default defineComponent({ + name: 'inspectTaskDialog', + components: { + SumData: defineAsyncComponent(() => import('/@/views/intellectInspect/inspectIndex/components/sum.vue')) + }, + setup(props: any, context: any) { + const inspectTaskFormRef = ref(); + const data = reactive<dataState>({ + title: '', + taskAndQuotas: [], + pointTitle: '', + activeName: 'inspectChain', + inspectPointConfirm: false, + inspectPointDialog: false, + ifShowInspectTaskDialog: false, + inspectPointForm: { + id: null, + unitId: null, + unitUuid: null, + pointId: null, + pointUuid: null, + regionId: null, + regionUuid: null, + rfidId: null, + quotaId: null, + quotaUnit: null, + execSequence: null, + secondReferenceResult: null, + reportResult: null, + dataReportType: null, + firstReferenceValue: null, + secondReferenceSign: null, + secondReferenceValue: null, + thirdReferenceSign: null, + thirdReferenceValue: null + }, + inspectTaskForm: { + execClassgroupId: null, + execDepId: null, + id: null, + points: [], + execUserName: '', + startTime: null, + taskName: null, + taskType: null, + validTime: null + }, + workTypeList: [], + departmentList: [], + timeList: [], + classGroupList: [], + classGroup: [], + quotaList: [], + inspectPointAllList: [], + dataReportTypeList: [ + { id: 1, name: '选择' }, + { id: 2, name: '填空' }, + { id: 3, name: '选择并填空' } + ], + firstReferenceValueList: [ + { id: 0, name: '正常' }, + { id: 1, name: '存在异常' } + ], + secondReferenceSignList: [ + { id: 1, name: '>' }, + { id: 2, name: '>=' } + ], + thirdReferenceSignList: [ + { id: 3, name: '<' }, + { id: 4, name: '<=' } + ] + }); + + const openInspectPointDialog = (type: string, item: {}) => { + data.inspectPointDialog = true; + if (type === '新增') { + data.pointTitle = '新增巡检点'; + data.inspectPointForm = { + id: null, + unitId: null, + unitUuid: null, + pointId: null, + pointUuid: null, + regionId: null, + regionUuid: null, + rfidId: null, + quotaId: null, + quotaUnit: null, + reportResult: null, + execSequence: null, + secondReferenceResult: null, + dataReportType: null, + firstReferenceValue: null, + secondReferenceSign: null, + secondReferenceValue: null, + thirdReferenceSign: null, + thirdReferenceValue: null + }; + } else { + data.pointTitle = '修改巡检点'; + data.inspectPointForm = JSON.parse(JSON.stringify(item)); + } + }; + + const showInspectRecordDialog = (type: string, item: { id: number; uuid: string; execUserName: string }, workTypeList: [], department: [], timeType: [], classGroupList: [], quotaList: [], inspectPointAllList: []) => { + data.quotaList = JSON.parse(JSON.stringify(quotaList)); + data.timeList = JSON.parse(JSON.stringify(timeType)); + data.inspectPointAllList = JSON.parse(JSON.stringify(inspectPointAllList)); + data.workTypeList = JSON.parse(JSON.stringify(workTypeList)); + data.departmentList = JSON.parse(JSON.stringify(department)); + data.classGroupList = JSON.parse(JSON.stringify(classGroupList)); + data.ifShowInspectTaskDialog = true; + data.inspectPointConfirm = false; + data.title = '查看巡检记录'; + getSum(item.id); + inspectRecordApi() + .getInspectRecordById({ id: item.id, uuid: item.uuid }) + .then((res) => { + if (res.data.code === '200') { + data.inspectTaskForm.execDepId = res.data.data.execDepId; + giveClassGroup(); + data.inspectTaskForm = JSON.parse(JSON.stringify(res.data.data)); + data.inspectTaskForm.execUserName = item.execUserName; + } else { + } + }) + .catch((error) => {}); + }; + + // 格式化表格数据 + // const toRefer =(row, column, cellValue, index)=>{ + // return row.secondReferenceResult==0?'正常':(row.reportResult==1?'异常':'无') + // } + + const getSum = async (id: number) => { + let res = await inspectRecordApi().getInspectRecordSum({ id: id }); + if (res.data.code === '200') { + data.taskAndQuotas = JSON.parse(JSON.stringify(res.data.data.taskAndQuotas)); + console.log(data.taskAndQuotas, '666666666666'); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + const submitInspectPoint = async () => { + if (data.title === '新增巡检任务' && data.pointTitle === '新增巡检点') { + if (data.inspectTaskForm.points.length === 0) { + data.inspectPointForm.execSequence = 1; + } else { + data.inspectPointForm.execSequence = (data.inspectTaskForm.points[data.inspectTaskForm.points.length - 1].execSequence as number) + 1; + } + data.inspectTaskForm.points.push(data.inspectPointForm); + data.inspectPointDialog = false; + } else if (data.title === '新增巡检任务' && data.pointTitle === '修改巡检点') { + let result = data.inspectTaskForm.points.findIndex((item) => item.id === data.inspectPointForm.id); + data.inspectTaskForm.points[result] = data.inspectPointForm; + data.inspectPointDialog = false; + } else if (data.title === '修改巡检任务' && data.pointTitle === '新增巡检点') { + data.inspectPointForm.unitId = data.inspectTaskForm.id; + if (data.inspectTaskForm.points.length === 0) { + data.inspectPointForm.execSequence = 1; + } else { + data.inspectPointForm.execSequence = (data.inspectTaskForm.points[data.inspectTaskForm.points.length - 1].execSequence as number) + 1; + } + let res = await inspectTaskApi().addChainOfInspectTask(data.inspectPointForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '巡检点新增成功', + duration: 2000 + }); + data.inspectPointDialog = false; + data.inspectTaskForm.points.push(data.inspectPointForm); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } else { + data.inspectPointForm.unitId = data.inspectTaskForm.id; + let res = await inspectTaskApi().modChainOfInspectTask(data.inspectPointForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '巡检点修改成功', + duration: 2000 + }); + let result = data.inspectTaskForm.points.findIndex((item) => item.id === data.inspectPointForm.id); + data.inspectTaskForm.points[result] = data.inspectPointForm; + data.inspectPointDialog = false; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } + }; + const deleteFlow = async (index: number, item: { id: number }) => { + if (data.pointTitle === '新增巡检点') { + data.inspectTaskForm.points.splice(index, 1); + } else { + let res = await inspectTaskApi().deleteChainOfInspectTask({ id: item.id, unitId: data.inspectTaskForm.id }); + if (res.data.code === '200') { + data.inspectTaskForm.points.splice(index, 1); + ElMessage({ + type: 'success', + message: '巡检点删除成功' + }); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } + }; + + const giveRegionAndRFID = () => { + data.inspectPointForm.regionId = data.inspectPointAllList.find((item) => item.id === data.inspectPointForm.pointId)?.regionId as number; + data.inspectPointForm.rfidId = data.inspectPointAllList.find((item) => item.id === data.inspectPointForm.pointId)?.rfidId as number; + }; + + const giveClassGroup = () => { + data.inspectTaskForm.execClassgroupId = null; + data.classGroup = data.classGroupList.filter((item) => item.depId === data.inspectTaskForm.execDepId); + }; + + const giveQuotaUnit = () => { + data.inspectPointForm.quotaUnit = data.quotaList.find((item) => item.id === data.inspectPointForm.quotaId)?.unit as string; + }; + const submitInspectTask = () => { + inspectTaskFormRef.value.validate(async (valid: Boolean) => { + if (valid) { + if (data.title === '新增巡检任务') { + let res = await inspectTaskApi().addInspectTask(data.inspectTaskForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '巡检任务新增成功', + duration: 2000 + }); + data.ifShowInspectTaskDialog = false; + context.emit('refreshInspectTask'); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } else { + let res = await inspectTaskApi().modInspectTask(data.inspectTaskForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '巡检指标修改成功', + duration: 2000 + }); + data.ifShowInspectTaskDialog = false; + context.emit('refreshInspectTask'); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } + } else { + ElMessage({ + type: 'warning', + message: '请完善基本信息' + }); + } + }); + }; + + return { + ...toRefs(data), + inspectTaskFormRef, + deleteFlow, + getSum, + // toRefer, + giveQuotaUnit, + giveClassGroup, + submitInspectTask, + submitInspectPoint, + giveRegionAndRFID, + showInspectRecordDialog, + openInspectPointDialog + }; + } +}); +</script> + +<style scoped lang="scss"> +$homeNavLengh: 8; +.home-container { + height: calc(100vh - 144px); + box-sizing: border-box; + overflow: hidden; + .homeCard { + width: 100%; + padding: 20px; + box-sizing: border-box; + background: #fff; + border-radius: 4px; + + .main-card { + width: 100%; + height: 100%; + .cardTop { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 20px; + .mainCardBtn { + margin: 0; + } + } + .pageBtn { + height: 60px; + display: flex; + align-items: center; + justify-content: right; + + .demo-pagination-block + .demo-pagination-block { + margin-top: 10px; + } + .demo-pagination-block .demonstration { + margin-bottom: 16px; + } + } + } + &:last-of-type { + height: calc(100% - 100px); + } + } + .el-row { + display: flex; + align-items: center; + margin-bottom: 20px; + &:last-child { + margin-bottom: 0; + } + .grid-content { + align-items: center; + min-height: 36px; + } + + .topInfo { + display: flex; + align-items: center; + font-size: 16px; + font-weight: bold; + + & > div { + white-space: nowrap; + margin-right: 20px; + } + } + } +} +.stepItem { + width: 100%; + display: flex; + align-items: flex-start; + margin-bottom: 30px; + margin-left: 30px; + padding-bottom: 30px; + border-left: 2px solid #ccc; + &:first-of-type { + margin-top: 30px; + } + &:last-of-type { + margin-bottom: 0; + border-left: none; + } + .stepNum { + width: 30px; + height: 30px; + border-radius: 15px; + box-sizing: border-box; + color: #333; + border: 1px solid #999; + line-height: 28px; + text-align: center; + margin-right: 10px; + margin-left: -16px; + margin-top: -30px; + } + .stepCard { + width: 100%; + margin-top: -30px; + + .box-card { + width: 100%; + &:deep(.el-card__header) { + padding: 10px 15px; + } + .card-header { + width: 100%; + display: flex; + justify-content: space-between; + align-items: center; + & > div:first-of-type { + margin-right: 80px; + font-size: 18px; + font-weight: bold; + } + } + } + } + &:hover .card-header { + color: #0098f5; + } + &:hover .stepNum { + border: 2px solid #0098f5; + color: #0098f5; + } +} +:deep(.el-date-editor) { + width: 100%; +} +</style> diff --git a/src/views/intellectInspect/inspectIndex/components/sum.vue b/src/views/intellectInspect/inspectIndex/components/sum.vue new file mode 100644 index 0000000..b0071e0 --- /dev/null +++ b/src/views/intellectInspect/inspectIndex/components/sum.vue @@ -0,0 +1,131 @@ +<template> + <div style="height: 100%"> + <div class="sum-info"> + <div v-for="item in sumData" class="region-card"> + <div class="region-tit">{{item[0][0].region}}</div> + <div class="unit-card"> + <div v-for="i in item"> + <div class="unit-tit">{{i[0].quotaContent}}({{i[0].quotaUnit}})</div> + <div class="points"> + <div v-for="t in i" > + <span class="point-tit">{{t.point}}</span> + <span>{{t.dataReportType == 1 ? '无' : t.secondReferenceResult}}</span> + </div> + </div> + </div> + </div> + </div> + </div> + </div> +</template> + +<script lang="ts"> + import { toRefs, reactive, defineComponent, ref, defineAsyncComponent } from 'vue'; + import { storeToRefs } from 'pinia'; + import { initBackEndControlRoutes } from '/@/router/backEnd'; + import {useUserInfo} from "/@/stores/userInfo"; + import { Session } from '/@/utils/storage'; + import { ElMessage } from 'element-plus' + import type { FormInstance, FormRules } from 'element-plus' + import { workApplyApi } from '/@/api/specialWorkSystem/workApply'; + + + interface stateType { + + } + export default defineComponent({ + name: 'SumData', + components: {}, + props:['sumData'], + setup() { + const userInfo = useUserInfo() + const { userInfos } = storeToRefs(userInfo); + return { + + }; + }, + }); +</script> + +<style scoped lang="scss"> + .home-container { + height: 100%; + overflow: hidden; + position: relative; + + .sum-info{ + width: 100%; + border: 1px solid #ccc; + + .region-card{ + width: 100%; + border-bottom: 1px solid #ccc; + display: flex; + font-size: 16px; + align-items: center; + .region-tit{ + width: 25%; + text-align: center; + } + .unit-card{ + width: 75%; + height: 100%; + border-left: 1px solid #ccc; + + &>div{ + width: 100%; + display: flex; + align-items: center; + border-bottom: 1px solid #ccc; + + &:last-of-type{ + border-bottom: none; + } + + .unit-tit{ + width: 40%; + padding-left: 10px; + } + .points{ + width: 60%; + height: 100%; + border-left: 1px solid #ccc; + + &>div{ + width: 100%; + display: flex; + align-items: center; + span{ + text-align: center; + width: 50%; + } + .point-tit{ + border-right: 1px solid #ccc; + padding: 10px; + } + } + } + } + } + } + } + .el-row{ + margin-bottom: 20px; + } + .el-row:last-child { + margin-bottom: 0; + } + .el-input{ + width: 100% !important; + } + .el-date-editor::v-deep{ + width: 100%; + } + .el-select{ + width: 100%; + } + .el-cascader{ + width: 100% !important; + } + } +</style> diff --git a/src/views/intellectInspect/inspectIndex/index.vue b/src/views/intellectInspect/inspectIndex/index.vue new file mode 100644 index 0000000..2e64240 --- /dev/null +++ b/src/views/intellectInspect/inspectIndex/index.vue @@ -0,0 +1,587 @@ +<template> + <div class="home-container"> + <div style="height: 100%"> + <div class="homeCard topCard"> + <div class="title">当前巡检任务</div> + <div class="top-info" v-if="unchecked != 0 || unusual != 0"> + <el-icon :size="18" color="#F3001E" style="margin-right: 4px"><BellFilled /></el-icon> + 预警消息: + <div v-if="unchecked != 0"> + 当日超期未巡检任务<el-tooltip + class="box-item" + effect="light" + content="查看相关记录" + placement="bottom-start" + ><span @click="toOverTime(4)">{{ unchecked }}</span></el-tooltip>个 + </div> + <span v-if="unchecked != 0 && unusual != 0">,</span> + <div v-if="unusual != 0"> + 存在异常任务<el-tooltip + class="box-item" + effect="light" + content="查看相关记录" + placement="bottom-start" + ><span @click="toOverTime(5)">{{ unusual }}</span + ></el-tooltip>个 + </div> + 。 + </div> + </div> + <div class="homeCard"> + <div class="main-card"> + <div class="list"> + <div class="cardTop" v-for="(item, index) in tableData" :key="index"> + <div class="left-info"> + <span class="num">{{ pageSize * (pageIndex - 1) + index + 1 }}、</span> + <span class="place">{{ item.taskName }},</span> + <p v-if="item.execUserName == null">该任务暂无人认领</p> + <p v-else> + <span class="time">{{ item.taskStatus == 2 ? item.startTime : item.endTime }}</span + >由<span class="name">{{ item.execUserName }}</span + >进行的巡检任务 + </p> + </div> + <div class="mid-info"> + 任务状态:<span :class="item.taskStatus == 1 ? 'grey' : item.taskStatus == 2 ? 'green' : item.taskStatus == 3 ? 'blue' : 'red'">{{ item.taskStatus == 1 ? '待巡检' : item.taskStatus == 2 ? '巡检中' : item.taskStatus == 3 ? '已巡检' : '超期未巡检' }}</span> + </div> + <div class="right-info"> + <div v-if="item.taskStatus == 2" @click="toLine(item)" class="checkBtn">查看实时巡检</div> + <div v-else class="reviewBtn" @click="toDetails('查看', item)">[查看巡检记录]</div> + </div> + </div> + </div> + <div class="pageBtn"> + <el-pagination v-model:currentPage="pageIndex" v-model:page-size="pageSize" :page-sizes="[10, 15]" small="false" background layout="total, sizes, prev, pager, next, jumper" :total="totalSize" @size-change="handleSizeChange" @current-change="handleCurrentChange" /> + </div> + </div> + </div> + </div> + <inspect-record-dialog ref="inspectRecordDialogRef" @refreshInspectRecord="getInspectRecord"></inspect-record-dialog> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, ref, onMounted } from 'vue'; +import { storeToRefs } from 'pinia'; +import { initBackEndControlRoutes } from '/@/router/backEnd'; +import { useUserInfo } from '/@/stores/userInfo'; +import { Session } from '/@/utils/storage'; +import { Edit, View, Plus, Delete, Refresh, Search, Download } from '@element-plus/icons-vue'; +import { ElTable } from 'element-plus'; +import { FormInstance, FormRules, ElMessage } from 'element-plus'; +import { inspectRecordApi } from '/@/api/intellectInspectSystem/inspectRecord'; +import { useRouter } from 'vue-router'; +import inspectRecordDialog from './components/inspectRecordDialog.vue'; +import { departmentApi } from '/@/api/systemManage/department'; +// 定义接口来定义对象的类型 +interface stateType { + tableData: Array<string>; + unchecked: null | number; + unusual: null | number; + uncheckedList: []; + abnormalList: []; + pageIndex: number; + pageSize: number; + totalSize: number; + workTypeList: Array<type>; + departmentList: []; + timeType: Array<type>; + classGroupList: Array<classGroup>; + quotaList: []; + inspectPointAllList: []; +} +interface type { + id: number; + name: string; +} +interface classGroup { + id: number; + groupName: string; +} +export default { + name: 'workingHours', + components: { inspectRecordDialog }, + setup() { + const router = useRouter(); + const state = reactive<stateType>({ + pageIndex: 1, + pageSize: 10, + totalSize: 0, + tableData: [], + unchecked: null, + unusual: null, + uncheckedList: [], + abnormalList: [], + workTypeList: [ + { id: 1, name: '日常任务' }, + { id: 2, name: '周期任务' } + ], + departmentList: [], + timeType: [ + { id: 1, name: '分' }, + { id: 2, name: '小时' }, + { id: 3, name: '日' }, + { id: 4, name: '月' }, + { id: 5, name: '年' } + ], + classGroupList: [], + quotaList: [], + inspectPointAllList: [] + }); + const inspectRecordDialogRef = ref(); + interface User { + name: string; + startTime: string; + endTime: string; + info: string; + } + + // 页面载入时执行方法 + onMounted(() => { + getInspectRecord(); + getDayData(); + getDepartmentData(); + }); + + // 分页获取工作时段列表 + const getInspectRecord = async () => { + const data = { pageSize: state.pageSize, pageIndex: state.pageIndex }; + let res = await inspectRecordApi().getInspectRecordByIndex(data); + if (res.data.code === '200') { + state.tableData = res.data.data.records; + state.totalSize = res.data.data.total; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + //获取部门 + const getDepartmentData = async () => { + let res = await departmentApi().getDepartmentList(); + if (res.data.code === '200') { + state.departmentList = res.data.data; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + //获取当日数据 + const getDayData = async () => { + let res = await inspectRecordApi().getDayRecord(); + if (res.data.code === '200') { + state.unchecked = res.data.data.noCheckTaskCount; + state.unusual = res.data.data.abnormalTaskCount; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + const handleSizeChange = (val: number) => { + state.pageSize = val; + getInspectRecord(); + }; + const handleCurrentChange = (val: number) => { + state.pageIndex = val; + getInspectRecord(); + }; + + const toLine = (item) => { + console.log(item,'item') + let id = item.id; + console.log(id,'id') + router.push({ + path: 'intelligentLine', + query: { + id: id + } + }); + }; + + const toOverTime = (id) => { + console.log(state.uncheckedList, 'list'); + router.push({ + path: 'inspectRecord', + query: { + id: id, + } + }); + }; + const toDetails = (type: string, item) => { + inspectRecordDialogRef.value.showInspectRecordDialog(type, item, state.workTypeList, state.departmentList, state.timeType, state.classGroupList, state.quotaList, state.inspectPointAllList); + }; + return { + View, + Edit, + Delete, + Refresh, + Plus, + router, + inspectRecordDialogRef, + toLine, + toOverTime, + toDetails, + handleSizeChange, + handleCurrentChange, + ...toRefs(state) + }; + } +}; +</script> + +<style scoped lang="scss"> +$homeNavLengh: 8; +@media screen and (min-width: 1366px) { + .topCard { + display: flex; + align-items: center; + justify-content: space-between; + font-weight: bolder; + + .top-info { + display: flex; + font-size: 16px; + align-items: center; + padding: 10px 15px; + background: #ffeb87; + border-radius: 8px; + border: 1px solid #ffae00; + + & > div { + vertical-align: middle; + white-space: nowrap; + span { + font-size: 22px; + color: #f3001e; + margin: 0 4px; + cursor: pointer; + + &:hover{ + text-decoration: underline; + } + } + } + } + } + .left-info { + width: 70%; + display: flex; + align-items: center; + justify-content: left; + font-size: 18px; + color: #333; + overflow-x: auto; + & > span { + white-space: nowrap; + } + p { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + & > span { + white-space: nowrap; + } + } + } + .mid-info { + width: 20%; + font-size: 18px; + color: #333; + } + .right-info { + width: 10%; + display: flex; + justify-content: right; + align-items: center; + font-size: 16px; + color: #fff; + + div { + white-space: nowrap; + } + } +} +@media screen and (min-width: 1200px) and (max-width: 1366px) { + .topCard { + display: flex; + align-items: center; + justify-content: space-between; + font-weight: bolder; + + .top-info { + display: flex; + font-size: 14px; + align-items: center; + padding: 6px 10px; + background: #ffeb87; + border-radius: 4px; + border: 1px solid #ffae00; + + & > div { + vertical-align: middle; + white-space: nowrap; + span { + font-size: 18px; + color: #f3001e; + margin: 0 2px; + cursor: pointer; + + &:hover{ + text-decoration: underline; + } + } + } + } + } + .left-info { + width: 70%; + display: flex; + align-items: center; + justify-content: left; + font-size: 15px; + color: #333; + overflow-x: auto; + & > span { + white-space: nowrap; + } + p { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + & > span { + white-space: nowrap; + } + } + } + .mid-info { + width: 20%; + font-size: 15px; + color: #333; + } + .right-info { + width: 10%; + display: flex; + justify-content: right; + align-items: center; + font-size: 13px; + color: #fff; + div { + white-space: nowrap; + } + } +} +@media screen and (max-width: 1200px) { + .topCard { + display: flex; + align-items: center; + justify-content: space-between; + font-weight: bolder; + + .top-info { + display: flex; + font-size: 14px; + align-items: center; + padding: 2px 6px; + background: #ffeb87; + border-radius: 4px; + border: 1px solid #ffae00; + + & > div { + vertical-align: middle; + white-space: nowrap; + span { + font-size: 16px; + color: #f3001e; + margin: 0 1px; + cursor: pointer; + + &:hover{ + text-decoration: underline; + } + } + } + } + } + .left-info { + width: 70%; + display: flex; + align-items: center; + justify-content: left; + font-size: 12px; + color: #333; + overflow-x: auto; + & > span { + white-space: nowrap; + } + p { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + & > span { + white-space: nowrap; + } + } + } + .mid-info { + width: 20%; + font-size: 12px; + color: #333; + } + .right-info { + width: 10%; + display: flex; + justify-content: right; + align-items: center; + font-size: 12px; + color: #fff; + div { + white-space: nowrap; + } + } +} + +.home-container { + height: calc(100vh - 144px); + box-sizing: border-box; + overflow: hidden; + .homeCard { + width: 100%; + padding: 20px; + box-sizing: border-box; + background: #fff; + border-radius: 4px; + + .title { + font-size: 20px; + font-weight: bolder; + } + .main-card { + width: 100%; + height: 100%; + .cardTop { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 10px; + background: #daf3ff; + padding: 10px 15px; + border-radius: 8px; + + .left-info { + .num { + font-weight: bolder; + margin-right: 10px; + } + .place { + font-weight: bolder; + } + .time { + font-weight: bolder; + margin-right: 5px; + } + .name { + font-weight: bolder; + margin: 0 5px; + font-weight: bolder; + } + } + .mid-info { + span { + font-weight: bolder; + } + + .grey { + color: #999; + } + .green { + color: #44b100; + } + .blue { + color: #409eff; + } + .red { + color: red; + } + } + .right-info { + .checkBtn { + padding: 10px 15px; + background: #409eff; + border-radius: 4px; + cursor: pointer; + } + + .reviewBtn { + margin: 10px 15px; + cursor: pointer; + color: #44b100; + } + } + } + .list { + height: calc(100% - 60px); + overflow-y: auto; + } + .pageBtn { + position: absolute; + bottom: 15px; + right: 20px; + height: 60px; + display: flex; + align-items: center; + justify-content: right; + + .demo-pagination-block + .demo-pagination-block { + margin-top: 10px; + } + .demo-pagination-block .demonstration { + margin-bottom: 16px; + } + } + } + &:last-of-type { + position: relative; + padding-top: 0; + height: calc(100% - 60px); + } + } + .el-row { + display: flex; + align-items: center; + margin-bottom: 20px; + &:last-child { + margin-bottom: 0; + } + .grid-content { + align-items: center; + min-height: 36px; + } + } +} +.el-input { + width: 100% !important; +} +.el-date-editor::v-deep { + width: 100%; +} +.el-select { + width: 100%; +} +:deep(.el-textarea.is-disabled .el-textarea__inner) { + background-color: var(--el-card-bg-color); + color: var(--el-input-text-color, var(--el-text-color-regular)); +} +:deep(.el-input.is-disabled .el-input__inner) { + color: var(--el-input-text-color, var(--el-text-color-regular)); +} +:deep(.el-input.is-disabled .el-input__wrapper) { + background-color: var(--el-card-bg-color); +} +</style> diff --git a/src/views/intellectInspect/inspectRecordManage/inspectRecord/components/inspectRecordDialog.vue b/src/views/intellectInspect/inspectRecordManage/inspectRecord/components/inspectRecordDialog.vue new file mode 100644 index 0000000..4aec32f --- /dev/null +++ b/src/views/intellectInspect/inspectRecordManage/inspectRecord/components/inspectRecordDialog.vue @@ -0,0 +1,560 @@ +<template> + <div class="system-add-menu-container"> + <el-dialog v-model="ifShowInspectTaskDialog" :title="title" width="60%"> + <el-form :model="inspectTaskForm" label-width="120px" ref="inspectTaskFormRef"> + <el-row> + <el-col :span="12" style="margin-bottom: 20px"> + <el-form-item label="任务名称" prop="unitName"> + <el-input v-model="inspectTaskForm.taskName" :disabled="!inspectPointConfirm" class="input-add" placeholder="请填写任务名称"> </el-input> + </el-form-item> + </el-col> + <el-col :span="12" style="margin-bottom: 20px"> + <el-form-item label="任务类型" prop="taskType"> + <el-select v-model="inspectTaskForm.taskType" :disabled="!inspectPointConfirm" class="input-add" placeholder="请选择任务类型"> + <el-option v-for="item in workTypeList" :key="item.id" :value="item.id" :label="item.name"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :span="12" style="margin-bottom: 20px"> + <el-form-item label="巡检部门" prop="execDepId"> + <el-cascader @change="giveClassGroup" :disabled="!inspectPointConfirm" placeholder="请选择巡检部门" :options="departmentList" :props="{ emitPath: false, checkStrictly: true, value: 'depId', label: 'depName' }" clearable filterable class="input-add" v-model="inspectTaskForm.execDepId"> </el-cascader> + </el-form-item> + </el-col> + <el-col :span="12" style="margin-bottom: 20px"> + <el-form-item label="巡检班组" prop="execClassgroupId"> + <el-select v-model="inspectTaskForm.execClassgroupId" :disabled="!inspectPointConfirm" placeholder="请选择巡检班组" class="input-add"> + <el-option v-for="item in classGroup" :key="item.id" :value="item.id" :label="item.groupName"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :span="12" style="margin-bottom: 20px"> + <el-form-item label="任务开始时间" prop="startTime"> + <el-date-picker v-model="inspectTaskForm.startTime" :disabled="!inspectPointConfirm" placeholder="请选择任务开始时间" type="datetime" format="YYYY/MM/DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss" class="input-add" /> + </el-form-item> + </el-col> + </el-row> + + <div class="checkUnit-point"> + <el-tabs class="active" v-model="activeName"> + <el-tab-pane label="巡检链" name="inspectChain"> + <el-table :data="inspectTaskForm.points" fit style="width: 100%"> + <el-table-column type="index" label="序号" /> + <el-table-column prop="point" label="巡检点" show-overflow-tooltip align="center"></el-table-column> + <el-table-column prop="region" label="所属设备" show-overflow-tooltip align="center"></el-table-column> + <el-table-column prop="rfid" label="RFID" show-overflow-tooltip align="center"></el-table-column> + <el-table-column prop="quotaContent" label="指标作业" show-overflow-tooltip align="center"></el-table-column> + <el-table-column prop="secondReferenceResult" label="记录值" show-overflow-tooltip align="center"> + <template #default="scope"> + <div :style="{ color: scope.row.reportResult == 1 ? '#ff0000' : '#409eff' }"> + {{ scope.row.dataReportType == 1 ? '无' : scope.row.secondReferenceResult }} + </div> + </template> + </el-table-column> + <el-table-column prop="quotaUnit" label="指标单位" show-overflow-tooltip align="center"></el-table-column> + <el-table-column prop="reportResult" label="结果" show-overflow-tooltip align="center"> + <template #default="scope"> + <div :style="{ color: scope.row.reportResult == 1 ? '#ff0000' : '#409eff' }"> + {{ scope.row.reportResult == 0 ? '正常' : scope.row.reportResult == 1 ? '存在异常' : '无' }} + </div> + </template> + </el-table-column> + <!-- <el-table-column label="操作" width="150" align="center">--> + <!-- <template #default="scope">--> + <!-- <el-button size="small" text type="danger" @click="onDelCheckUnit(scope.$index, scope.row)">删除</el-button>--> + <!-- </template>--> + <!-- </el-table-column>--> + </el-table> + </el-tab-pane> + <el-tab-pane label="统计数据" name="allData"> + <sum-data :sumData="taskAndQuotas"></sum-data> + </el-tab-pane> + </el-tabs> + </div> + <div align="right" v-show="inspectPointConfirm"> + <el-button type="warning" @click="inspectPointDialog = false" size="default" plain>取消</el-button> + <el-button type="primary" @click="submitInspectTask()" size="default">确认</el-button> + </div> + </el-form> + </el-dialog> + </div> +</template> + +<script lang="ts"> +import { reactive, toRefs, ref, defineAsyncComponent } from 'vue'; +import { RFIDApi } from '/@/api/intellectInspectSystem/RFID'; +import { ElMessage } from 'element-plus/es'; +import { inspectTaskApi } from '/@/api/intellectInspectSystem/inspectTask'; +import { facilityAreaApi } from '/@/api/intellectInspectSystem/facilityAreaManage'; +import { inspectRecordApi } from '/@/api/intellectInspectSystem/inspectRecord'; +interface dataState { + title: string; + pointTitle: string; + activeName: string; + inspectPointConfirm: boolean; + inspectPointDialog: boolean; + ifShowInspectTaskDialog: boolean; + inspectPointForm: inspectPointForm; + inspectTaskForm: { + execClassgroupId: number | null; + execDepId: number | null; + id: number | null; + startTime: string | null; + taskName: string | null; + taskType: number | null; + validTime: string | null; + points: Array<inspectPointForm>; + }; + workTypeList: []; + departmentList: []; + timeList: []; + dataReportTypeList: Array<dataReport>; + firstReferenceValueList: Array<dataReport>; + secondReferenceSignList: Array<dataReport>; + thirdReferenceSignList: Array<dataReport>; + classGroupList: Array<classGroup>; + classGroup: Array<classGroup>; + quotaList: Array<quota>; + inspectPointAllList: Array<inspectPointAllState>; +} +interface inspectPointAllState { + id: number; + code: string; + regionId: number; + rfidId: number; +} +interface classGroup { + depId: number; +} +interface dataReport { + id: number; + name: string; +} +interface quota { + id: number; + type: string; + unit: string; +} +interface inspectPointForm { + id: number | null; + unitId: number | null; + unitUuid: string | null; + pointId: number | null; + pointUuid: string | null; + regionId: number | null; + regionUuid: string | null; + rfidId: number | null; + quotaId: number | null; + quotaUnit: string | null; + execSequence: number | null; + dataReportType: number | null; + firstReferenceValue: number | null; + secondReferenceSign: number | null; + secondReferenceValue: number | null; + thirdReferenceSign: number | null; + thirdReferenceValue: number | null; +} +export default { + name: 'inspectTaskDialog', + components: { + SumData: defineAsyncComponent(() => import('/@/views/intellectInspect/inspectIndex/components/sum.vue')) + }, + setup(props: any, context: any) { + const inspectTaskFormRef = ref(); + const data = reactive<dataState>({ + title: '', + pointTitle: '', + activeName: 'inspectChain', + inspectPointConfirm: false, + inspectPointDialog: false, + ifShowInspectTaskDialog: false, + inspectPointForm: { + id: null, + unitId: null, + unitUuid: null, + pointId: null, + pointUuid: null, + regionId: null, + regionUuid: null, + rfidId: null, + quotaId: null, + quotaUnit: null, + execSequence: null, + dataReportType: null, + firstReferenceValue: null, + secondReferenceSign: null, + secondReferenceValue: null, + thirdReferenceSign: null, + thirdReferenceValue: null + }, + inspectTaskForm: { + execClassgroupId: null, + execDepId: null, + id: null, + points: [], + startTime: null, + taskName: null, + taskType: null, + validTime: null + }, + workTypeList: [], + departmentList: [], + timeList: [], + classGroupList: [], + classGroup: [], + quotaList: [], + inspectPointAllList: [], + dataReportTypeList: [ + { id: 1, name: '选择' }, + { id: 2, name: '填空' }, + { id: 3, name: '选择并填空' } + ], + firstReferenceValueList: [ + { id: 0, name: '正常' }, + { id: 1, name: '异常' } + ], + secondReferenceSignList: [ + { id: 1, name: '>' }, + { id: 2, name: '>=' } + ], + thirdReferenceSignList: [ + { id: 3, name: '<' }, + { id: 4, name: '<=' } + ] + }); + + const openInspectPointDialog = (type: string, value: {}) => { + data.inspectPointDialog = true; + if (type === '新增') { + data.pointTitle = '新增巡检点'; + data.inspectPointForm = { + id: null, + unitId: null, + unitUuid: null, + pointId: null, + pointUuid: null, + regionId: null, + regionUuid: null, + rfidId: null, + quotaId: null, + quotaUnit: null, + execSequence: null, + dataReportType: null, + firstReferenceValue: null, + secondReferenceSign: null, + secondReferenceValue: null, + thirdReferenceSign: null, + thirdReferenceValue: null + }; + } else { + data.pointTitle = '修改巡检点'; + data.inspectPointForm = JSON.parse(JSON.stringify(value)); + } + }; + + const showInspectRecordDialog = (type: string, value: { id: number; uuid: string }, workTypeList: [], department: [], timeType: [], classGroupList: [], quotaList: [], inspectPointAllList: []) => { + data.quotaList = JSON.parse(JSON.stringify(quotaList)); + data.timeList = JSON.parse(JSON.stringify(timeType)); + data.inspectPointAllList = JSON.parse(JSON.stringify(inspectPointAllList)); + data.workTypeList = JSON.parse(JSON.stringify(workTypeList)); + data.departmentList = JSON.parse(JSON.stringify(department)); + data.classGroupList = JSON.parse(JSON.stringify(classGroupList)); + data.ifShowInspectTaskDialog = true; + data.inspectPointConfirm = false; + data.title = '查看巡检记录'; + inspectRecordApi() + .getInspectRecordById({ id: value.id, uuid: value.uuid }) + .then((res) => { + if (res.data.code === '200') { + data.inspectTaskForm.execDepId = res.data.data.execDepId; + giveClassGroup(); + data.inspectTaskForm = JSON.parse(JSON.stringify(res.data.data)); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }) + .catch((error) => {}); + }; + + const submitInspectPoint = async () => { + if (data.title === '新增巡检任务' && data.pointTitle === '新增巡检点') { + if (data.inspectTaskForm.points.length === 0) { + data.inspectPointForm.execSequence = 1; + } else { + data.inspectPointForm.execSequence = (data.inspectTaskForm.points[data.inspectTaskForm.points.length - 1].execSequence as number) + 1; + } + data.inspectTaskForm.points.push(data.inspectPointForm); + data.inspectPointDialog = false; + } else if (data.title === '新增巡检任务' && data.pointTitle === '修改巡检点') { + let result = data.inspectTaskForm.points.findIndex((item) => item.id === data.inspectPointForm.id); + data.inspectTaskForm.points[result] = data.inspectPointForm; + data.inspectPointDialog = false; + } else if (data.title === '修改巡检任务' && data.pointTitle === '新增巡检点') { + data.inspectPointForm.unitId = data.inspectTaskForm.id; + if (data.inspectTaskForm.points.length === 0) { + data.inspectPointForm.execSequence = 1; + } else { + data.inspectPointForm.execSequence = (data.inspectTaskForm.points[data.inspectTaskForm.points.length - 1].execSequence as number) + 1; + } + let res = await inspectTaskApi().addChainOfInspectTask(data.inspectPointForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '巡检点新增成功', + duration: 2000 + }); + data.inspectPointDialog = false; + data.inspectTaskForm.points.push(data.inspectPointForm); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } else { + data.inspectPointForm.unitId = data.inspectTaskForm.id; + let res = await inspectTaskApi().modChainOfInspectTask(data.inspectPointForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '巡检点修改成功', + duration: 2000 + }); + let result = data.inspectTaskForm.points.findIndex((item) => item.id === data.inspectPointForm.id); + data.inspectTaskForm.points[result] = data.inspectPointForm; + data.inspectPointDialog = false; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } + }; + const deleteFlow = async (index: number, item: { id: number }) => { + if (data.pointTitle === '新增巡检点') { + data.inspectTaskForm.points.splice(index, 1); + } else { + let res = await inspectTaskApi().deleteChainOfInspectTask({ id: item.id, unitId: data.inspectTaskForm.id }); + if (res.data.code === '200') { + data.inspectTaskForm.points.splice(index, 1); + ElMessage({ + type: 'success', + message: '巡检点删除成功' + }); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } + }; + + const giveRegionAndRFID = () => { + data.inspectPointForm.regionId = data.inspectPointAllList.find((item) => item.id === data.inspectPointForm.pointId)?.regionId as number; + data.inspectPointForm.rfidId = data.inspectPointAllList.find((item) => item.id === data.inspectPointForm.pointId)?.rfidId as number; + }; + + const giveClassGroup = () => { + data.inspectTaskForm.execClassgroupId = null; + data.classGroup = data.classGroupList.filter((item) => item.depId === data.inspectTaskForm.execDepId); + }; + + const giveQuotaUnit = () => { + data.inspectPointForm.quotaUnit = data.quotaList.find((item) => item.id === data.inspectPointForm.quotaId)?.unit as string; + }; + + const submitInspectTask = () => { + inspectTaskFormRef.value.validate(async (valid: Boolean) => { + if (valid) { + if (data.title === '新增巡检任务') { + let res = await inspectTaskApi().addInspectTask(data.inspectTaskForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '巡检任务新增成功', + duration: 2000 + }); + data.ifShowInspectTaskDialog = false; + context.emit('refreshInspectTask'); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } else { + let res = await inspectTaskApi().modInspectTask(data.inspectTaskForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '巡检指标修改成功', + duration: 2000 + }); + data.ifShowInspectTaskDialog = false; + context.emit('refreshInspectTask'); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } + } else { + ElMessage({ + type: 'warning', + message: '请完善基本信息' + }); + } + }); + }; + + return { + ...toRefs(data), + inspectTaskFormRef, + deleteFlow, + giveQuotaUnit, + giveClassGroup, + submitInspectTask, + submitInspectPoint, + giveRegionAndRFID, + showInspectRecordDialog, + openInspectPointDialog + }; + } +}; +</script> + +<style scoped lang="scss"> +$homeNavLengh: 8; +.home-container { + height: calc(100vh - 144px); + box-sizing: border-box; + overflow: hidden; + .homeCard { + width: 100%; + padding: 20px; + box-sizing: border-box; + background: #fff; + border-radius: 4px; + + .main-card { + width: 100%; + height: 100%; + .cardTop { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 20px; + .mainCardBtn { + margin: 0; + } + } + .pageBtn { + height: 60px; + display: flex; + align-items: center; + justify-content: right; + + .demo-pagination-block + .demo-pagination-block { + margin-top: 10px; + } + .demo-pagination-block .demonstration { + margin-bottom: 16px; + } + } + } + &:last-of-type { + height: calc(100% - 100px); + } + } + .el-row { + display: flex; + align-items: center; + margin-bottom: 20px; + &:last-child { + margin-bottom: 0; + } + .grid-content { + align-items: center; + min-height: 36px; + } + + .topInfo { + display: flex; + align-items: center; + font-size: 16px; + font-weight: bold; + + & > div { + white-space: nowrap; + margin-right: 20px; + } + } + } +} +.stepItem { + width: 100%; + display: flex; + align-items: flex-start; + margin-bottom: 30px; + margin-left: 30px; + padding-bottom: 30px; + border-left: 2px solid #ccc; + &:first-of-type { + margin-top: 30px; + } + &:last-of-type { + margin-bottom: 0; + border-left: none; + } + .stepNum { + width: 30px; + height: 30px; + border-radius: 15px; + box-sizing: border-box; + color: #333; + border: 1px solid #999; + line-height: 28px; + text-align: center; + margin-right: 10px; + margin-left: -16px; + margin-top: -30px; + } + .stepCard { + width: 100%; + margin-top: -30px; + + .box-card { + width: 100%; + &:deep(.el-card__header) { + padding: 10px 15px; + } + .card-header { + width: 100%; + display: flex; + justify-content: space-between; + align-items: center; + & > div:first-of-type { + margin-right: 80px; + font-size: 18px; + font-weight: bold; + } + } + } + } + &:hover .card-header { + color: #0098f5; + } + &:hover .stepNum { + border: 2px solid #0098f5; + color: #0098f5; + } +} +:deep(.el-date-editor) { + width: 100%; +} +</style> diff --git a/src/views/intellectInspect/inspectRecordManage/inspectRecord/components/sum.vue b/src/views/intellectInspect/inspectRecordManage/inspectRecord/components/sum.vue new file mode 100644 index 0000000..b0071e0 --- /dev/null +++ b/src/views/intellectInspect/inspectRecordManage/inspectRecord/components/sum.vue @@ -0,0 +1,131 @@ +<template> + <div style="height: 100%"> + <div class="sum-info"> + <div v-for="item in sumData" class="region-card"> + <div class="region-tit">{{item[0][0].region}}</div> + <div class="unit-card"> + <div v-for="i in item"> + <div class="unit-tit">{{i[0].quotaContent}}({{i[0].quotaUnit}})</div> + <div class="points"> + <div v-for="t in i" > + <span class="point-tit">{{t.point}}</span> + <span>{{t.dataReportType == 1 ? '无' : t.secondReferenceResult}}</span> + </div> + </div> + </div> + </div> + </div> + </div> + </div> +</template> + +<script lang="ts"> + import { toRefs, reactive, defineComponent, ref, defineAsyncComponent } from 'vue'; + import { storeToRefs } from 'pinia'; + import { initBackEndControlRoutes } from '/@/router/backEnd'; + import {useUserInfo} from "/@/stores/userInfo"; + import { Session } from '/@/utils/storage'; + import { ElMessage } from 'element-plus' + import type { FormInstance, FormRules } from 'element-plus' + import { workApplyApi } from '/@/api/specialWorkSystem/workApply'; + + + interface stateType { + + } + export default defineComponent({ + name: 'SumData', + components: {}, + props:['sumData'], + setup() { + const userInfo = useUserInfo() + const { userInfos } = storeToRefs(userInfo); + return { + + }; + }, + }); +</script> + +<style scoped lang="scss"> + .home-container { + height: 100%; + overflow: hidden; + position: relative; + + .sum-info{ + width: 100%; + border: 1px solid #ccc; + + .region-card{ + width: 100%; + border-bottom: 1px solid #ccc; + display: flex; + font-size: 16px; + align-items: center; + .region-tit{ + width: 25%; + text-align: center; + } + .unit-card{ + width: 75%; + height: 100%; + border-left: 1px solid #ccc; + + &>div{ + width: 100%; + display: flex; + align-items: center; + border-bottom: 1px solid #ccc; + + &:last-of-type{ + border-bottom: none; + } + + .unit-tit{ + width: 40%; + padding-left: 10px; + } + .points{ + width: 60%; + height: 100%; + border-left: 1px solid #ccc; + + &>div{ + width: 100%; + display: flex; + align-items: center; + span{ + text-align: center; + width: 50%; + } + .point-tit{ + border-right: 1px solid #ccc; + padding: 10px; + } + } + } + } + } + } + } + .el-row{ + margin-bottom: 20px; + } + .el-row:last-child { + margin-bottom: 0; + } + .el-input{ + width: 100% !important; + } + .el-date-editor::v-deep{ + width: 100%; + } + .el-select{ + width: 100%; + } + .el-cascader{ + width: 100% !important; + } + } +</style> diff --git a/src/views/intellectInspect/inspectRecordManage/inspectRecord/index.vue b/src/views/intellectInspect/inspectRecordManage/inspectRecord/index.vue new file mode 100644 index 0000000..3ac0afc --- /dev/null +++ b/src/views/intellectInspect/inspectRecordManage/inspectRecord/index.vue @@ -0,0 +1,546 @@ +<template> + <div class="home-container"> + <div style="height: 100%"> + <el-row class="homeCard"> + <div class="basic-line"> + <span>任务类型:</span> + <el-select v-model="tableData.params.taskType" clearable filterable class="input-box" placeholder="任务类型"> + <el-option v-for="item in workTypeList" :key="item.id" :label="item.name" :value="item.id"></el-option> + </el-select> + </div> + <div class="basic-line"> + <span>执行班组:</span> + <el-select v-model="tableData.params.execClassgroupId" clearable filterable class="input-box" placeholder="执行班组"> + <el-option v-for="item in classGroupList" :key="item.id" :label="item.groupName" :value="item.id"></el-option> + </el-select> + </div> + <div class="basic-line"> + <span>任务状态:</span> + <el-select v-model="tableData.params.taskStatus" clearable filterable class="input-box" placeholder="执行班组"> + <el-option v-for="item in taskStatusList" :key="item.id" :label="item.name" :value="item.id"></el-option> + </el-select> + </div> + <div style="padding-bottom: 10px"> + <el-button type="primary" @click="getInspectRecord">查询</el-button> + <el-button plain @click="reset">重置</el-button> + </div> + </el-row> + <div class="homeCard"> + <div class="main-card"> + <el-row class="cardTop"> + <el-button type="primary" :icon="Refresh" size="default" /> + </el-row> + <el-table ref="multipleTableRef" :data="tableData.inspectRecordData" style="width: 100%" height="calc(100% - 100px)" :header-cell-style="{ background: '#fafafa' }"> + <el-table-column property="taskName" label="任务名称"> + <template #default="scope"> + <div :class="hasJump == true && scope.row.startTime.slice(0, 10) == date && (tableData.params.taskStatus == 4 || tableData.params.taskStatus == 5) ? 'redTit' : ''"> + {{ scope.row.taskName }} + </div> + </template> + </el-table-column> + <el-table-column property="taskType" label="任务类型"> + <template #default="scope"> + <span> + {{ parseNumber(scope.row.taskType, '任务类型') }} + </span> + </template> + </el-table-column> + <el-table-column property="execClassgroupId" label="巡检班组"> + <template #default="scope"> + <span> + {{ parseNumber(scope.row.execClassgroupId, '巡检班组') }} + </span> + </template> + </el-table-column> + <el-table-column property="frequency" label="检查频次"> + <template #default="scope"> + <span> + {{ scope.row.checkCycle }} + </span> + <span> + {{ parseNumber(scope.row.checkCycleUnit, '检查频次') }} + </span> + </template> + </el-table-column> + <el-table-column property="startTime" label="任务开始时间" /> + <el-table-column prop="execUserName" label="执行人" show-overflow-tooltip></el-table-column> + <el-table-column property="taskStatus" label="任务状态" width="180"> + <template #default="scope"> + <el-tag :type="scope.row.resultStatus === 1 ? 'danger' : scope.row.taskStatus === 1 ? 'info' : scope.row.taskStatus === 2 ? '' : scope.row.taskStatus === 3 ? 'success' : 'danger'"> + <span> + {{ scope.row.resultStatus === 1 ? '已巡检存在异常' : parseNumber(scope.row.taskStatus, '任务状态') }} + </span> + </el-tag> + </template> + </el-table-column> + <el-table-column property="resultStatus" label="巡检结果"> + <template #default="scope"> + <span> + {{ parseNumber(scope.row.resultStatus, '巡检状态') }} + </span> + </template> + </el-table-column> + <el-table-column fixed="right" label="操作" align="center" width="300"> + <template #default="scope"> + <el-button link type="primary" size="small" :icon="View" @click="openInspectRecordDialog('查看', scope.row)">查看</el-button> + </template> + </el-table-column> + </el-table> + <div class="pageBtn"> + <el-pagination @size-change="onHandleSizeChange" @current-change="onHandleCurrentChange" :pager-count="5" :page-sizes="[10, 20, 30]" v-model:current-page="tableData.params.pageIndex" background v-model:page-size="tableData.params.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="tableData.total" class="page-position"> </el-pagination> + </div> + </div> + </div> + </div> + <inspect-record-dialog ref="inspectRecordDialogRef" @refreshInspectRecord="getInspectRecord"></inspect-record-dialog> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, ref, onMounted, nextTick } from 'vue'; +import { Edit, View, Plus, Delete, Refresh, Search, Download } from '@element-plus/icons-vue'; +import { ElTable, ElMessage } from 'element-plus'; +import { inspectRecordApi } from '/@/api/intellectInspectSystem/inspectRecord'; +import inspectRecordDialog from '../../inspectIndex/components/inspectRecordDialog.vue'; +import { departmentApi } from '/@/api/systemManage/department'; +import { teamManageApi } from '/@/api/systemManage/personShiftManage/teamManage'; +import { inspectPointApi } from '/@/api/intellectInspectSystem/inspectPointManage'; +import { inspectTaskApi } from '/@/api/intellectInspectSystem/inspectTask'; +import { useRoute } from 'vue-router'; +let global: any = { + homeChartOne: null, + homeChartTwo: null, + homeCharThree: null, + dispose: [null, '', undefined] +}; + +interface stateType { + isRed: boolean; + hasJump: boolean; + date: string; + tableData: { + inspectRecordData: []; + total: number; + loading: boolean; + params: { + pageIndex: number | null; + pageSize: number | null; + taskName: string | null; + taskType: number | null; + taskStatus: number | null; + execUserId: number | null; + execClassgroupId: number | null; + execDepId: number | null; + startTime: string | null; + validTime: string | null; + createUserId: number | null; + reportTime: string | null; + resultStatus: number | null; + }; + }; + workTypeList: Array<type>; + taskStatusList: Array<type>; + quotaList: []; + departmentList: []; + classGroupList: Array<classGroup>; + inspectPointAllList: []; + timeType: Array<type>; + resultStatusList: Array<type>; +} +interface type { + id: number; + name: string; +} +interface classGroup { + id: number; + groupName: string; +} +interface timeType {} +export default { + name: 'index', + components: { inspectRecordDialog }, + setup() { + const inspectRecordDialogRef = ref(); + const route = useRoute(); + const state = reactive<stateType>({ + hasJump: false, + tableData: { + inspectRecordData: [], + total: 0, + loading: false, + params: { + pageIndex: 1, + pageSize: 10, + taskName: null, + taskType: null, + taskStatus: 2, + execUserId: null, + execClassgroupId: null, + execDepId: null, + startTime: null, + validTime: null, + createUserId: null, + reportTime: null, + resultStatus: null + } + }, + isRed: false, + date: '', + workTypeList: [ + { id: 1, name: '周期任务' }, + { id: 2, name: '单次任务' } + ], + resultStatusList: [ + { id: 0, name: '正常' }, + { id: 1, name: '存在异常' } + ], + taskStatusList: [ + { id: 1, name: '待巡检' }, + { id: 2, name: '巡检中' }, + { id: 3, name: '已巡检正常' }, + { id: 5, name: '已巡检存在异常' }, + { id: 4, name: '超时未完成巡检' } + ], + quotaList: [], + departmentList: [], + classGroupList: [], + inspectPointAllList: [], + timeType: [ + { id: 1, name: '分' }, + { id: 2, name: '小时' }, + { id: 3, name: '日' }, + { id: 4, name: '月' }, + { id: 5, name: '年' } + ] + }); + + //获取巡检记录数据 + const getInspectRecord = async () => { + const data = JSON.parse(JSON.stringify(state.tableData.params)); + if (state.tableData.params.taskStatus == 3) { + data.taskStatus = 3; + data.resultStatus = 0; + } + if (state.tableData.params.taskStatus == 5) { + data.taskStatus = 3; + data.resultStatus = 1; + } + console.log(state.tableData.params.taskStatus, data.taskStatus, 'data'); + let res = await inspectRecordApi().getInspectRecordList(data); + if (res.data.code === '200') { + state.tableData.inspectRecordData = JSON.parse(JSON.stringify(res.data.data.records)); + state.tableData.total = res.data.data.total; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + //获取部门 + const getDepartmentData = async () => { + let res = await departmentApi().getDepartmentList(); + if (res.data.code === '200') { + state.departmentList = res.data.data; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + //获取部门 + const getQuotaList = async () => { + let res = await inspectTaskApi().getQuotaList(); + if (res.data.code === '200') { + state.quotaList = res.data.data; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + //获取巡检点 + const getInspectTaskPoint = async () => { + let res = await inspectPointApi().getInspectPointAll(); + if (res.data.code === '200') { + state.inspectPointAllList = res.data.data; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + //获取班组 + const getClassGroupData = async () => { + let res = await teamManageApi().getRecord({ depIp: null, groupName: null, containGroupMemberEnable: null }); + if (res.data.code === '200') { + state.classGroupList = res.data.data; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // const turnRed =()=>{ + // date + // } + + const openInspectRecordDialog = (type: string, value: {}) => { + inspectRecordDialogRef.value.showInspectRecordDialog(type, value, state.workTypeList, state.departmentList, state.timeType, state.classGroupList, state.quotaList, state.inspectPointAllList); + }; + + const parseNumber = (value: number, type: string) => { + if (type === '任务类型') { + return state.workTypeList.find((item) => item.id === value)?.name; + } else if (type === '检查频次') { + return state.timeType.find((item) => item.id == value)?.name; + } else if (type === '巡检状态') { + return state.resultStatusList.find((item) => item.id == value)?.name; + } else if (type === '任务状态') { + return state.taskStatusList.find((item) => item.id == value)?.name; + } else { + return state.classGroupList.find((item) => item.id == value)?.groupName; + } + }; + + // 分页改变 + const onHandleSizeChange = (val: number) => { + state.tableData.params.pageSize = val; + getInspectRecord(); + }; + // 分页改变 + const onHandleCurrentChange = (val: number) => { + state.tableData.params.pageIndex = val; + getInspectRecord(); + state.isRed = false; + }; + // 时间格式化 + const timeForm: timeType = { + hour12: false, + year: 'numeric', + month: '2-digit', + day: '2-digit', + hour: '2-digit', + minute: '2-digit', + second: '2-digit' + }; + const reset = () => { + state.tableData.params = { + pageIndex: 1, + pageSize: 10, + taskName: null, + taskType: null, + taskStatus: null, + execUserId: null, + execClassgroupId: null, + execDepId: null, + startTime: null, + validTime: null, + createUserId: null, + resultStatus: null, + reportTime: null + }; + }; + // 当前时间 + const getDateTime = () => { + const curTime = new Date().toLocaleString('zh', timeForm).replace(/\//g, '-'); + state.date = curTime.slice(0, 10); + }; + // 页面加载时 + onMounted(() => { + getDateTime(); + if (route.query.id) { + state.hasJump = true; + state.tableData.params.taskStatus = Number(route.query.id); + state.isRed = true; + getInspectRecord(); + getQuotaList(); + getDepartmentData(); + getClassGroupData(); + getInspectTaskPoint(); + } else { + getInspectRecord(); + getQuotaList(); + getDepartmentData(); + getClassGroupData(); + getInspectTaskPoint(); + } + }); + + return { + View, + Edit, + Delete, + Refresh, + Plus, + reset, + parseNumber, + getInspectRecord, + onHandleSizeChange, + onHandleCurrentChange, + inspectRecordDialogRef, + openInspectRecordDialog, + ...toRefs(state) + }; + } +}; +</script> + +<style scoped lang="scss"> +$homeNavLengh: 8; +.home-container { + height: calc(100vh - 144px); + box-sizing: border-box; + overflow: hidden; + .homeCard { + width: 100%; + padding: 20px; + box-sizing: border-box; + background: #fff; + border-radius: 4px; + + .main-card { + width: 100%; + height: 100%; + .cardTop { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 20px; + .mainCardBtn { + margin: 0; + } + } + .pageBtn { + height: 60px; + display: flex; + align-items: center; + justify-content: right; + + .demo-pagination-block + .demo-pagination-block { + margin-top: 10px; + } + .demo-pagination-block .demonstration { + margin-bottom: 16px; + } + } + } + &:last-of-type { + height: calc(100% - 100px); + } + } + .el-row { + display: flex; + align-items: center; + margin-bottom: 20px; + &:last-child { + margin-bottom: 0; + } + .grid-content { + align-items: center; + min-height: 36px; + } + + .topInfo { + display: flex; + align-items: center; + font-size: 16px; + font-weight: bold; + + & > div { + white-space: nowrap; + margin-right: 20px; + } + } + } +} +.stepItem { + width: 100%; + display: flex; + align-items: flex-start; + margin-bottom: 30px; + margin-left: 30px; + padding-bottom: 30px; + border-left: 2px solid #ccc; + &:first-of-type { + margin-top: 30px; + } + &:last-of-type { + margin-bottom: 0; + border-left: none; + } + .stepNum { + width: 30px; + height: 30px; + border-radius: 15px; + box-sizing: border-box; + color: #333; + border: 1px solid #999; + line-height: 28px; + text-align: center; + margin-right: 10px; + margin-left: -16px; + margin-top: -30px; + } + .stepCard { + width: 100%; + margin-top: -30px; + + .box-card { + width: 100%; + &:deep(.el-card__header) { + padding: 10px 15px; + } + .card-header { + width: 100%; + display: flex; + justify-content: space-between; + align-items: center; + & > div:first-of-type { + margin-right: 80px; + font-size: 18px; + font-weight: bold; + } + } + } + } + &:hover .card-header { + color: #0098f5; + } + &:hover .stepNum { + border: 2px solid #0098f5; + color: #0098f5; + } +} +.redTit { + color: red; +} +.el-input { + width: 100% !important; +} +:deep(.el-date-editor) { + width: 100%; +} +.el-select { + width: 100%; +} +:deep(.el-textarea.is-disabled .el-textarea__inner) { + background-color: var(--el-card-bg-color); + color: var(--el-input-text-color, var(--el-text-color-regular)); +} +:deep(.el-input.is-disabled .el-input__inner) { + color: var(--el-input-text-color, var(--el-text-color-regular)); +} +:deep(.el-input.is-disabled .el-input__wrapper) { + background-color: var(--el-card-bg-color); +} +</style> diff --git a/src/views/intellectInspect/inspectTaskManage/inspectTask/components/inspectTaskDialog.vue b/src/views/intellectInspect/inspectTaskManage/inspectTask/components/inspectTaskDialog.vue new file mode 100644 index 0000000..642567c --- /dev/null +++ b/src/views/intellectInspect/inspectTaskManage/inspectTask/components/inspectTaskDialog.vue @@ -0,0 +1,782 @@ +<template> + <div class="system-add-menu-container"> + <el-dialog v-model="ifShowInspectTaskDialog" :title="title" :close-on-click-modal="false"> + <el-form :model="inspectTaskForm" label-width="120px" ref="inspectTaskFormRef" :rules="inspectTaskFormRules"> + <el-row> + <el-col :span="12" style="margin-bottom: 20px"> + <el-form-item label="任务名称" prop="unitName"> + <el-input v-model="inspectTaskForm.unitName" :disabled="!inspectPointConfirm" class="input-add" placeholder="请填写任务名称"> </el-input> + </el-form-item> + </el-col> + <el-col :span="12" style="margin-bottom: 20px"> + <el-form-item label="任务类型" prop="workType"> + <el-select v-model="inspectTaskForm.workType" :disabled="!inspectPointConfirm" class="input-add" placeholder="请选择任务类型"> + <el-option v-for="item in workTypeList" :key="item.id" :value="item.id" :label="item.name"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :span="12" style="margin-bottom: 20px"> + <el-form-item label="巡检部门" prop="execDepId"> + <el-cascader @change="giveClassGroup" :disabled="!inspectPointConfirm" v placeholder="请选择巡检部门" :options="departmentList" :props="{ emitPath: false, checkStrictly: true, value: 'depId', label: 'depName' }" clearable filterable class="input-add" v-model="inspectTaskForm.execDepId"> </el-cascader> + </el-form-item> + </el-col> + <el-col :span="12" style="margin-bottom: 20px"> + <el-form-item label="巡检班组" prop="execClassgroupId"> + <el-select v-model="inspectTaskForm.execClassgroupId" :disabled="!inspectPointConfirm" placeholder="请选择巡检班组" class="input-add"> + <el-option v-for="item in classGroup" :key="item.id" :value="item.id" :label="item.groupName"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :span="12" style="margin-bottom: 20px" v-if="inspectTaskForm.workType === 1"> + <el-form-item label="巡检周期" prop="checkCycle"> + <el-input v-model="inspectTaskForm.checkCycle" @input="onVerifiyNumberInteger($event, 'checkCycle')" :disabled="!inspectPointConfirm" placeholder="请输入巡检周期" class="input-add"> + <template #append> + <el-form-item prop="checkCycleUnit"> + <el-select v-model="inspectTaskForm.checkCycleUnit" :disabled="!inspectPointConfirm" placeholder="选择单位"> + <el-option v-for="item in timeList" :key="item.id" :value="item.id" :label="item.name"></el-option> + </el-select> + </el-form-item> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :span="12" style="margin-bottom: 20px"> + <el-form-item label="提前通知时间" prop="noticeTime"> + <el-input @input="onVerifiyNumberInteger($event, 'noticeTime')" v-model="inspectTaskForm.noticeTime" :disabled="!inspectPointConfirm" placeholder="请输入提前通知时间" class="input-add"> + <template #append> + <el-form-item prop="noticeTimeUnit"> + <el-select v-model="inspectTaskForm.noticeTimeUnit" :disabled="!inspectPointConfirm" placeholder="选择单位"> + <el-option v-for="item in timeList" :key="item.id" :value="item.id" :label="item.name"></el-option> + </el-select> + </el-form-item> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :span="12" style="margin-bottom: 20px"> + <el-form-item label="有效时间" prop="validTime"> + <el-input v-model="inspectTaskForm.validTime" @input="onVerifiyNumberInteger($event, 'validTime')" :disabled="!inspectPointConfirm" placeholder="请输入有效时间" class="input-add"> + <template #append> + <el-form-item prop="noticeTimeUnit"> + <el-select v-model="inspectTaskForm.validTimeUnit" :disabled="!inspectPointConfirm" placeholder="选择单位"> + <el-option v-for="item in timeList" :key="item.id" :value="item.id" :label="item.name"></el-option> + </el-select> + </el-form-item> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :span="12" style="margin-bottom: 20px"> + <el-form-item label="任务开始时间" prop="firstStartTime"> + <el-date-picker v-model="inspectTaskForm.firstStartTime" :disabled="!inspectPointConfirm" placeholder="请选择任务开始时间" type="datetime" format="YYYY/MM/DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss" class="input-add" /> + </el-form-item> + </el-col> + + <el-col :span="24"> + <el-form-item label="创建巡检链"> + <div style="width: 100%; margin-bottom: 20px" v-show="inspectPointConfirm"> + <el-button type="primary" :icon="Plus" size="default" @click="openInspectPointDialog('新增', '')">新增巡检点</el-button> + </div> + <div style="width: 100%; margin-left: -30px"> + <div v-for="(item, index) in inspectTaskForm.points" class="stepItem"> + <div class="stepNum">{{ index + 1 }}</div> + <div class="stepCard"> + <el-card class="box-card"> + <template #header> + <div class="card-header" v-for="i in inspectPointAllList"> + <div v-if="i.id == item.pointId"> + <span>{{ i.code }}</span> + </div> + </div> + </template> + <div class="text item" v-for="i in regionNameList"> + <div v-if="i.id == item.regionId"> + 所属设备区域:<span>{{ i.region }}</span> + </div> + </div> + <!-- <div class="text item">--> + <!-- 所属设备区域:<span>{{ item.regionId }}</span>--> + <!-- </div>--> + <div class="text item" v-for="i in RFIDList"> + <div v-if="i.id == item.rfidId"> + 所属设备区域:<span>{{ i.rfidName }}</span> + </div> + </div> + <!-- <div class="text item">--> + <!-- 关联RFID:<span>{{ item.rfidId }}</span>--> + <!-- </div>--> + <div class="text item" v-for="i in quotaList"> + <div v-if="i.id == item.quotaId"> + 所属设备区域:<span>{{ i.type }}</span> + </div> + </div> + <!-- <div class="text item">--> + <!-- 巡检指标:<span>{{ item.quotaId }}</span>--> + <!-- </div>--> + <div class="text item" v-for="i in dataReportTypeList"> + <div v-if="i.id == item.dataReportType"> + 所属设备区域:<span>{{ i.name }}</span> + </div> + </div> + <!-- <div class="text item">--> + <!-- 数据填报类型:<span>{{ item.dataReportType }}</span>--> + <!-- </div>--> + <div class="text item"> + 数据参考值:<span>{{ item.firstReferenceValue ? item.firstReferenceValue : item.secondReferenceValue ? item.secondReferenceValue : item.thirdReferenceValue }}</span> + </div> + </el-card> + </div> + <div v-show="inspectPointConfirm"> + <!-- <el-button type="primary" size="default" @click="addFlow(index)">新增下一区域</el-button>--> + <el-button type="primary" style="margin-left: 12px" size="default" @click="openInspectPointDialog('修改', item)">修改</el-button> + <el-button type="danger" size="default" @click="deleteFlow(index, item)">删除</el-button> + </div> + </div> + </div> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <div v-if="inspectPointConfirm" class="dialog-footer"> + <el-button type="warning" @click="ifShowInspectTaskDialog = false" size="default" plain>取消</el-button> + <el-button type="primary" @click="submitInspectTask()" size="default">确认</el-button> + </div> + </template> + </el-dialog> + <el-dialog v-model="inspectPointDialog" :title="pointTitle" :close-on-click-modal="false"> + <el-form :model="inspectPointForm" label-width="150px" ref="inspectPointFormRef" :rules="inspectPointFormRules"> + <el-form-item label="选择巡检点" prop="pointId"> + <el-select v-model="inspectPointForm.pointId" @change="giveRegionAndRFID" class="input-add"> + <el-option v-for="item in inspectPointAllList" :key="item.id" :value="item.id" :label="item.code"></el-option> + </el-select> + </el-form-item> + <el-form-item label="所属设备区域" prop="regionId"> + <el-input v-model="inspectPointForm.regionId" class="input-add" readonly /> + </el-form-item> + <el-form-item label="关联RFID" prop="rfidId"> + <el-input v-model="inspectPointForm.rfidId" class="input-add" readonly /> + </el-form-item> + <el-form-item label="选择巡检指标" prop="quotaId"> + <el-select v-model="inspectPointForm.quotaId" @change="giveQuotaUnit" placeholder="请选择巡检指标" class="input-add"> + <el-option v-for="item in quotaList" :key="item.id" :value="item.id" :label="item.type"> </el-option> + </el-select> + </el-form-item> + <el-form-item label="选择巡检指标单位" prop="quotaUnit"> + <el-input v-model="inspectPointForm.quotaUnit" placeholder="单位" class="input-add"> </el-input> + </el-form-item> + <el-form-item label="数据填报类型" prop="dataReportType"> + <el-select v-model="inspectPointForm.dataReportType" class="input-add"> + <el-option v-for="item in dataReportTypeList" :key="item.id" :value="item.id" :label="item.name"> </el-option> + </el-select> + </el-form-item> + <el-form-item v-if="inspectPointForm.dataReportType == '1' || inspectPointForm.dataReportType == '3'" label="数据参考值" prop="firstReferenceValue"> + <el-select v-model="inspectPointForm.firstReferenceValue" class="input-add"> + <el-option v-for="item in firstReferenceValueList" :key="item.id" :value="item.id" :label="item.name"> </el-option> + </el-select> + </el-form-item> + <el-form-item v-if="inspectPointForm.dataReportType == '2' || inspectPointForm.dataReportType == '3'" label="数据参考值"> + <el-input v-model="inspectPointForm.secondReferenceValue" type="number" class="input-add" placeholder="请根据需求选择前方符号后再填写参考值,非必填"> + <template #prepend> + <el-select v-model="inspectPointForm.secondReferenceSign" placeholder="Select" style="width: 115px"> + <el-option v-for="item in secondReferenceSignList" :key="item.id" :value="item.id" :label="item.name"> </el-option> + </el-select> + </template> + </el-input> + </el-form-item> + <el-form-item v-if="inspectPointForm.dataReportType == '2' || inspectPointForm.dataReportType == '3'" label=""> + <el-input v-model="inspectPointForm.thirdReferenceValue" type="number" class="input-add" placeholder="请根据需求选择前方符号后再填写参考值,非必填"> + <template #prepend> + <el-select v-model="inspectPointForm.thirdReferenceSign" placeholder="Select" style="width: 115px"> + <el-option v-for="item in thirdReferenceSignList" :key="item.id" :value="item.id" :label="item.name"> </el-option> + </el-select> + </template> + </el-input> + </el-form-item> + <div align="right"> + <el-button type="warning" @click="inspectPointDialog = false" size="default" plain>取消</el-button> + <el-button type="primary" @click="submitInspectPoint()" size="default">确认</el-button> + </div> + </el-form> + </el-dialog> + </div> +</template> + +<script lang="ts"> +import { reactive, toRefs, ref } from 'vue'; +import { ElMessage } from 'element-plus/es'; +import { inspectTaskApi } from '/@/api/intellectInspectSystem/inspectTask'; +import { verifiyNumberInteger } from '/@/utils/toolsValidate'; + +interface dataState { + title: string; + pointTitle: string; + inspectPointConfirm: boolean; + inspectPointDialog: boolean; + ifShowInspectTaskDialog: boolean; + inspectPointForm: inspectPointForm; + inspectTaskForm: { + id: number | null; + uuid: number | null; + unitName: number | null; + taskUnitStatus: number | null; + workType: number | null; + execClassgroupId: number | null; + execDepId: number | null; + checkCycle: number | null; + checkCycleUnit: number | null; + noticeTime: number | null; + noticeTimeUnit: number | null; + validTime: number | null; + validTimeUnit: number | null; + firstStartTime: number | null; + points: Array<inspectPointForm>; + }; + inspectTaskFormRules: {}; + inspectPointFormRules: {}; + workTypeList: []; + departmentList: []; + timeList: []; + dataReportTypeList: Array<dataReport>; + firstReferenceValueList: Array<dataReport>; + secondReferenceSignList: Array<dataReport>; + thirdReferenceSignList: Array<dataReport>; + classGroupList: Array<classGroup>; + classGroup: Array<classGroup>; + quotaList: Array<quota>; + inspectPointAllList: Array<inspectPointAllState>; + regionNameList: Array<inspectPointAllState>; + RFIDList: Array<inspectPointAllState>; +} +interface inspectPointAllState { + id: number; + code: string; + regionId: number; + rfidId: number; + rfidName: string; + region: string; +} +interface classGroup { + depId: number; +} +interface dataReport { + id: number; + name: string; +} +interface quota { + id: number; + type: string; + unit: string; +} +interface inspectPointForm { + id: number | null; + unitId: number | null; + unitUuid: string | null; + pointId: number | null; + pointUuid: string | null; + regionId: number | null; + regionUuid: string | null; + rfidId: number | null; + quotaId: number | null; + quotaUnit: string | null; + execSequence: number | null; + dataReportType: number | null; + firstReferenceValue: number | null; + secondReferenceSign: number | null; + secondReferenceValue: number | null; + thirdReferenceSign: number | null; + thirdReferenceValue: number | null; +} +export default { + name: 'inspectTaskDialog', + setup(props: any, context: any) { + const inspectTaskFormRef = ref(); + const inspectPointFormRef = ref(); + const data = reactive<dataState>({ + title: '', + pointTitle: '', + inspectPointConfirm: false, + inspectPointDialog: false, + ifShowInspectTaskDialog: false, + inspectPointForm: { + id: null, + unitId: null, + unitUuid: null, + pointId: null, + pointUuid: null, + regionId: null, + regionUuid: null, + rfidId: null, + quotaId: null, + quotaUnit: null, + execSequence: null, + dataReportType: null, + firstReferenceValue: null, + secondReferenceSign: null, + secondReferenceValue: null, + thirdReferenceSign: null, + thirdReferenceValue: null + }, + inspectTaskForm: { + id: null, + uuid: null, + unitName: null, + taskUnitStatus: null, + workType: null, + execClassgroupId: null, + execDepId: null, + checkCycle: null, + checkCycleUnit: null, + noticeTime: null, + noticeTimeUnit: null, + validTime: null, + validTimeUnit: null, + firstStartTime: null, + points: [] + }, + inspectTaskFormRules: { + unitName: [{ required: true, message: '请填写巡检任务单元名称', trigger: 'blur' }], + workType: [{ required: true, message: '请选择巡检任务类型', trigger: 'change' }], + execClassgroupId: [{ required: true, message: '请选择巡检班组', trigger: 'change' }], + execDepId: [{ required: true, message: '请选择巡检部门', trigger: 'blur' }], + checkCycle: [{ required: true, message: '请填写巡检周期', trigger: 'blur' }], + checkCycleUnit: [{ required: true, message: '请选择巡检周期单位', trigger: 'change' }], + noticeTime: [{ required: true, message: '请填写提前通知时间', trigger: 'blur' }], + noticeTimeUnit: [{ required: true, message: '请选择提前通知时间单位', trigger: 'change' }], + validTime: [{ required: true, message: '请填写有效时间', trigger: 'blur' }], + validTimeUnit: [{ required: true, message: '请选择有效时间单位', trigger: 'change' }], + firstStartTime: [{ required: true, message: '请选择周期开始时间', trigger: 'change' }] + }, + inspectPointFormRules: { + pointId: [{ required: true, message: '请选择巡检点', trigger: 'change' }], + regionId: [{ required: true, message: '', trigger: 'change' }], + rfidId: [{ required: true, message: '', trigger: 'change' }], + quotaId: [{ required: true, message: '请选择巡检指标', trigger: 'change' }], + quotaUnit: [{ required: true, message: '请填写巡检指标单位', trigger: 'blur' }], + dataReportType: [{ required: true, message: '请选择巡检指标单位', trigger: 'change' }] + }, + workTypeList: [], + departmentList: [], + timeList: [], + classGroupList: [], + classGroup: [], + quotaList: [], + inspectPointAllList: [], + regionNameList: [], + RFIDList: [], + dataReportTypeList: [ + { id: 1, name: '选择' }, + { id: 2, name: '填空' }, + { id: 3, name: '选择并填空' } + ], + firstReferenceValueList: [ + { id: 0, name: '正常' }, + { id: 1, name: '异常' } + ], + secondReferenceSignList: [ + { id: 1, name: '>' }, + { id: 2, name: '>=' } + ], + thirdReferenceSignList: [ + { id: 3, name: '<' }, + { id: 4, name: '<=' } + ] + }); + + const openInspectPointDialog = (type: string, value: {}) => { + data.inspectPointDialog = true; + if (type === '新增') { + data.pointTitle = '新增巡检点'; + data.inspectPointForm = { + id: null, + unitId: null, + unitUuid: null, + pointId: null, + pointUuid: null, + regionId: null, + regionUuid: null, + rfidId: null, + quotaId: null, + quotaUnit: null, + execSequence: null, + dataReportType: null, + firstReferenceValue: null, + secondReferenceSign: null, + secondReferenceValue: null, + thirdReferenceSign: null, + thirdReferenceValue: null + }; + } else { + data.pointTitle = '修改巡检点'; + data.inspectPointForm = JSON.parse(JSON.stringify(value)); + } + }; + + const showInspectTaskDialog = (type: string, value: { id: number; uuid: string }, workTypeList: [], department: [], timeType: [], classGroupList: [], quotaList: [], inspectPointAllList: [], regionNameList: [], RFIDList: []) => { + data.regionNameList = regionNameList; + data.RFIDList = RFIDList; + data.quotaList = JSON.parse(JSON.stringify(quotaList)); + data.timeList = JSON.parse(JSON.stringify(timeType)); + data.inspectPointAllList = JSON.parse(JSON.stringify(inspectPointAllList)); + data.workTypeList = JSON.parse(JSON.stringify(workTypeList)); + data.departmentList = JSON.parse(JSON.stringify(department)); + data.classGroupList = JSON.parse(JSON.stringify(classGroupList)); + data.ifShowInspectTaskDialog = true; + if (type === '新增') { + data.inspectPointConfirm = true; + data.title = '新增巡检任务'; + data.inspectTaskForm = { + id: null, + uuid: null, + unitName: null, + taskUnitStatus: null, + workType: null, + execClassgroupId: null, + execDepId: null, + checkCycle: null, + checkCycleUnit: null, + noticeTime: null, + noticeTimeUnit: null, + validTime: null, + validTimeUnit: null, + firstStartTime: null, + points: [] + }; + } else if (type === '修改') { + data.inspectPointConfirm = true; + data.title = '修改巡检任务'; + inspectTaskApi() + .getInspectTaskById({ id: value.id, uuid: value.uuid }) + .then((res) => { + if (res.data.code === '200') { + data.inspectTaskForm.execDepId = res.data.data.execDepId; + giveClassGroup(); + data.inspectTaskForm = JSON.parse(JSON.stringify(res.data.data)); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }) + .catch((error) => {}); + } else { + data.inspectPointConfirm = false; + data.title = '查看巡检任务'; + inspectTaskApi() + .getInspectTaskById({ id: value.id, uuid: value.uuid }) + .then((res) => { + if (res.data.code === '200') { + data.inspectTaskForm = JSON.parse(JSON.stringify(res.data.data)); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }) + .catch((error) => {}); + } + }; + + const submitInspectPoint = () => { + inspectPointFormRef.value.validate(async (valid: Boolean) => { + if (valid) { + if (data.title === '新增巡检任务' && data.pointTitle === '新增巡检点') { + if (data.inspectTaskForm.points.length === 0) { + data.inspectPointForm.execSequence = 1; + } else { + data.inspectPointForm.execSequence = (data.inspectTaskForm.points[data.inspectTaskForm.points.length - 1].execSequence as number) + 1; + } + data.inspectTaskForm.points.push(data.inspectPointForm); + data.inspectPointDialog = false; + } else if (data.title === '新增巡检任务' && data.pointTitle === '修改巡检点') { + let result = data.inspectTaskForm.points.findIndex((item) => item.execSequence === data.inspectPointForm.execSequence); + data.inspectTaskForm.points[result] = data.inspectPointForm; + data.inspectPointDialog = false; + } else if (data.title === '修改巡检任务' && data.pointTitle === '新增巡检点') { + data.inspectPointForm.unitId = data.inspectTaskForm.id; + if (data.inspectTaskForm.points.length === 0) { + data.inspectPointForm.execSequence = 1; + } else { + data.inspectPointForm.execSequence = (data.inspectTaskForm.points[data.inspectTaskForm.points.length - 1].execSequence as number) + 1; + } + let res = await inspectTaskApi().addChainOfInspectTask(data.inspectPointForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '巡检点新增成功', + duration: 2000 + }); + data.inspectPointDialog = false; + data.inspectTaskForm.points.push(data.inspectPointForm); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } else { + data.inspectPointForm.unitId = data.inspectTaskForm.id; + let res = await inspectTaskApi().modChainOfInspectTask(data.inspectPointForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '巡检点修改成功', + duration: 2000 + }); + let result = data.inspectTaskForm.points.findIndex((item) => item.execSequence === data.inspectPointForm.execSequence); + data.inspectTaskForm.points[result] = data.inspectPointForm; + data.inspectPointDialog = false; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } + } else { + ElMessage({ + type: 'warning', + message: '请完善基本信息' + }); + } + }); + }; + const deleteFlow = async (index: number, item: { id: number }) => { + if (data.pointTitle === '新增巡检点') { + data.inspectTaskForm.points.splice(index, 1); + } else { + let res = await inspectTaskApi().deleteChainOfInspectTask({ id: item.id, unitId: data.inspectTaskForm.id }); + if (res.data.code === '200') { + data.inspectTaskForm.points.splice(index, 1); + ElMessage({ + type: 'success', + message: '巡检点删除成功' + }); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } + }; + + const giveRegionAndRFID = () => { + data.inspectPointForm.regionId = data.inspectPointAllList.find((item) => item.id === data.inspectPointForm.pointId)?.regionId as number; + data.inspectPointForm.rfidId = data.inspectPointAllList.find((item) => item.id === data.inspectPointForm.pointId)?.rfidId as number; + }; + + const giveClassGroup = () => { + data.inspectTaskForm.execClassgroupId = null; + data.classGroup = data.classGroupList.filter((item) => item.depId === data.inspectTaskForm.execDepId); + }; + + const giveQuotaUnit = () => { + data.inspectPointForm.quotaUnit = data.quotaList.find((item) => item.id === data.inspectPointForm.quotaId)?.unit as string; + }; + + const submitInspectTask = () => { + inspectTaskFormRef.value.validate(async (valid: Boolean) => { + if (valid) { + if (data.title === '新增巡检任务') { + let res = await inspectTaskApi().addInspectTask(data.inspectTaskForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '巡检任务新增成功', + duration: 2000 + }); + data.ifShowInspectTaskDialog = false; + context.emit('refreshInspectTask'); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } else { + let res = await inspectTaskApi().modInspectTask(data.inspectTaskForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '巡检指标修改成功', + duration: 2000 + }); + data.ifShowInspectTaskDialog = false; + context.emit('refreshInspectTask'); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } + } else { + ElMessage({ + type: 'warning', + message: '请完善基本信息' + }); + } + }); + }; + + const onVerifiyNumberInteger = (val: number, title: string) => { + if (title === 'noticeTime') { + data.inspectTaskForm.noticeTime = Number(verifiyNumberInteger(val.toString())) === 0 ? null : Number(verifiyNumberInteger(val.toString())); + } else if (title === 'checkCycle') { + data.inspectTaskForm.checkCycle = Number(verifiyNumberInteger(val.toString())) === 0 ? null : Number(verifiyNumberInteger(val.toString())); + } else { + data.inspectTaskForm.validTime = Number(verifiyNumberInteger(val.toString())) === 0 ? null : Number(verifiyNumberInteger(val.toString())); + } + }; + + return { + ...toRefs(data), + inspectTaskFormRef, + deleteFlow, + giveQuotaUnit, + giveClassGroup, + inspectPointFormRef, + onVerifiyNumberInteger, + submitInspectTask, + submitInspectPoint, + giveRegionAndRFID, + showInspectTaskDialog, + openInspectPointDialog + }; + } +}; +</script> + +<style scoped lang="scss"> +$homeNavLengh: 8; +.home-container { + height: calc(100vh - 144px); + box-sizing: border-box; + overflow: hidden; + .homeCard { + width: 100%; + padding: 20px; + box-sizing: border-box; + background: #fff; + border-radius: 4px; + + .main-card { + width: 100%; + height: 100%; + .cardTop { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 20px; + .mainCardBtn { + margin: 0; + } + } + .pageBtn { + height: 60px; + display: flex; + align-items: center; + justify-content: right; + + .demo-pagination-block + .demo-pagination-block { + margin-top: 10px; + } + .demo-pagination-block .demonstration { + margin-bottom: 16px; + } + } + } + &:last-of-type { + height: calc(100% - 100px); + } + } + .el-row { + display: flex; + align-items: center; + margin-bottom: 20px; + &:last-child { + margin-bottom: 0; + } + .grid-content { + align-items: center; + min-height: 36px; + } + + .topInfo { + display: flex; + align-items: center; + font-size: 16px; + font-weight: bold; + + & > div { + white-space: nowrap; + margin-right: 20px; + } + } + } +} +.stepItem { + width: 100%; + display: flex; + align-items: flex-start; + margin-bottom: 30px; + margin-left: 30px; + padding-bottom: 30px; + border-left: 2px solid #ccc; + &:first-of-type { + margin-top: 30px; + } + &:last-of-type { + margin-bottom: 0; + border-left: none; + } + .stepNum { + width: 30px; + height: 30px; + border-radius: 15px; + box-sizing: border-box; + color: #333; + border: 1px solid #999; + line-height: 28px; + text-align: center; + margin-right: 10px; + margin-left: -16px; + margin-top: -30px; + } + .stepCard { + width: 100%; + margin-top: -30px; + + .box-card { + width: 100%; + &:deep(.el-card__header) { + padding: 10px 15px; + } + .card-header { + width: 100%; + display: flex; + justify-content: space-between; + align-items: center; + & > div:first-of-type { + margin-right: 80px; + font-size: 18px; + font-weight: bold; + } + } + } + } + &:hover .card-header { + color: #0098f5; + } + &:hover .stepNum { + border: 2px solid #0098f5; + color: #0098f5; + } +} +:deep(.el-date-editor) { + width: 100%; +} +</style> diff --git a/src/views/intellectInspect/inspectTaskManage/inspectTask/index.vue b/src/views/intellectInspect/inspectTaskManage/inspectTask/index.vue new file mode 100644 index 0000000..d897b89 --- /dev/null +++ b/src/views/intellectInspect/inspectTaskManage/inspectTask/index.vue @@ -0,0 +1,595 @@ +<template> + <div class="home-container"> + <div style="height: 100%"> + <el-row class="homeCard"> + <div class="basic-line"> + <span>任务类型:</span> + <el-select v-model="tableData.params.workType" clearable filterable class="input-box" placeholder="任务类型"> + <el-option v-for="item in workTypeList" :key="item.id" :label="item.name" :value="item.id"></el-option> + </el-select> + </div> + <div class="basic-line"> + <span>执行班组:</span> + <el-select v-model="tableData.params.execClassgroupId" clearable filterable class="input-box" placeholder="执行班组"> + <el-option v-for="item in classGroupList" :key="item.id" :label="item.groupName" :value="item.id"></el-option> + </el-select> + </div> + <div style="padding-bottom: 10px"> + <el-button type="primary" @click="getInspectionTask">查询</el-button> + <el-button plain @click="reset">重置</el-button> + </div> + </el-row> + <div class="homeCard"> + <div class="main-card"> + <el-row class="cardTop"> + <el-col :span="12" class="mainCardBtn"> + <el-button type="primary" :icon="Plus" size="default" @click="openInspectTaskDialog('新增', {})">新增</el-button> + <!-- <el-button type="danger" :icon="Delete" size="default" plain>删除</el-button>--> + </el-col> + <el-button type="primary" :icon="Refresh" size="default" /> + </el-row> + <el-table ref="multipleTableRef" :data="tableData.inspectTaskData" style="width: 100%" height="calc(100% - 100px)" :header-cell-style="{ background: '#fafafa' }" @selection-change="handleSelectionChange"> + <el-table-column type="selection" width="55" /> + <el-table-column property="unitName" label="任务名称" /> + <el-table-column property="workType" label="任务类型"> + <template #default="scope"> + <span> + {{ parseNumber(scope.row.workType, '任务类型') }} + </span> + </template> + </el-table-column> + <el-table-column property="execClassgroupId" label="巡检班组"> + <template #default="scope"> + <span> + {{ parseNumber(scope.row.execClassgroupId, '巡检班组') }} + </span> + </template> + </el-table-column> + <el-table-column property="frequency" label="检查频次"> + <template #default="scope"> + <span> + {{ scope.row.checkCycle }} + </span> + <span> + {{ scope.row.checkCycleUnit }} + </span> + </template> + </el-table-column> + <!-- <el-table-column prop="validTime" label="有效时间" show-overflow-tooltip>--> + <!-- <template #default="scope">--> + <!-- <span>--> + <!-- {{ scope.row.validTime }}--> + <!-- </span>--> + <!-- <span>--> + <!-- {{ parseNumber(scope.row.validTimeUnit, '检查频次') }}--> + <!-- </span>--> + <!-- </template>--> + <!-- </el-table-column>--> + <!-- <el-table-column prop="validTime" label="提醒时间" show-overflow-tooltip>--> + <!-- <template #default="scope">--> + <!-- <span>--> + <!-- {{ scope.row.noticeTime }}--> + <!-- </span>--> + <!-- <span>--> + <!-- {{ parseNumber(scope.row.noticeTimeUnit, '检查频次') }}--> + <!-- </span>--> + <!-- </template>--> + <!-- </el-table-column>--> + <el-table-column property="firstStartTime" label="任务开始时间" /> + <el-table-column prop="createUserName" label="创建人" show-overflow-tooltip></el-table-column> + <el-table-column prop="gmtCreate" label="创建时间" show-overflow-tooltip></el-table-column> + <el-table-column prop="lastEditUserName" label="最后修改人" show-overflow-tooltip></el-table-column> + <el-table-column prop="gmtModitify" label="最后修改时间" show-overflow-tooltip></el-table-column> + <el-table-column property="taskUnitStatus" label="状态" width="60"> + <template #default="scope"> + <div> + <div v-if="scope.row.taskUnitStatus === 1"> + <el-tag :type="''"> + {{ '开启' }} + </el-tag> + </div> + <div v-if="scope.row.taskUnitStatus === 2"> + <el-tag :type="'danger'"> + {{ '关闭' }} + </el-tag> + </div> + </div> + </template> + </el-table-column> + <el-table-column fixed="right" label="操作" align="center" width="300"> + <template #default="scope"> + <el-button link type="primary" size="small" :icon="View" @click="openInspectTaskDialog('查看', scope.row)">查看</el-button> + <el-button link type="primary" size="small" :icon="Edit" @click="openInspectTaskDialog('修改', scope.row)">修改</el-button> + <el-button link type="danger" size="small" :icon="Delete" v-if="scope.row.taskUnitStatus === 2" @click="deleteInspectTask(scope.row)">删除</el-button> + <div @click="changeStatus(scope.row)"> + <el-switch v-model="scope.row.taskUnitStatus" inline-prompt active-text="开" inactive-text="关" :active-value="1" :inactive-value="2" style="margin: 0 10px" /> + </div> + </template> + </el-table-column> + </el-table> + <div class="pageBtn"> + <el-pagination @size-change="onHandleSizeChange" @current-change="onHandleCurrentChange" :pager-count="5" :page-sizes="[10, 20, 30]" v-model:current-page="tableData.params.pageIndex" background v-model:page-size="tableData.params.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="tableData.total" class="page-position"> </el-pagination> + </div> + </div> + </div> + </div> + <inspect-task-dialog ref="inspectTaskDialogRef" @refreshInspectTask="getInspectionTask"></inspect-task-dialog> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, ref, onMounted } from 'vue'; +import { Edit, View, Plus, Delete, Refresh, Search, Download } from '@element-plus/icons-vue'; +import { ElTable, ElMessage, ElMessageBox } from 'element-plus'; +import { inspectTaskApi } from '/@/api/intellectInspectSystem/inspectTask'; +import inspectTaskDialog from './components/inspectTaskDialog.vue'; +import { departmentApi } from '/@/api/systemManage/department'; +import { teamManageApi } from '/@/api/systemManage/personShiftManage/teamManage'; +import { inspectPointApi } from '/@/api/intellectInspectSystem/inspectPointManage'; +import { facilityAreaApi } from '/@/api/intellectInspectSystem/facilityAreaManage'; +import { RFIDApi } from '/@/api/intellectInspectSystem/RFID'; +let global: any = { + homeChartOne: null, + homeChartTwo: null, + homeCharThree: null, + dispose: [null, '', undefined] +}; + +interface stateType { + tableData: { + inspectTaskData: []; + total: number; + loading: boolean; + params: { + pageIndex: number | null; + pageSize: number | null; + unitName: string | null; + workType: number | null; + createUserId: number | null; + execClassgroupId: number | null; + checkCycle: number | null; + checkCycleUnit: number | null; + }; + }; + workTypeList: Array<type>; + quotaList: []; + departmentList: []; + classGroupList: Array<classGroup>; + inspectPointAllList: []; + regionNameList: []; + RFIDList: []; + timeType: Array<type>; +} +interface type { + id: number; + name: string; +} +interface classGroup { + id: number; + groupName: string; +} +export default { + name: 'index', + components: { inspectTaskDialog }, + setup() { + const inspectTaskDialogRef = ref(); + const state = reactive<stateType>({ + tableData: { + inspectTaskData: [], + total: 0, + loading: false, + params: { + pageIndex: 1, + pageSize: 10, + unitName: null, + workType: null, + createUserId: null, + execClassgroupId: null, + checkCycle: null, + checkCycleUnit: null + } + }, + workTypeList: [ + { id: 1, name: '周期任务' }, + { id: 2, name: '单次任务' } + ], + quotaList: [], + departmentList: [], + classGroupList: [], + inspectPointAllList: [], + regionNameList: [], + RFIDList: [], + timeType: [ + { id: 1, name: '分' }, + { id: 2, name: '小时' }, + { id: 3, name: '日' }, + { id: 4, name: '月' }, + { id: 5, name: '年' } + ] + }); + + //获取巡检任务数据 + const getInspectionTask = async () => { + let res = await inspectTaskApi().getInspectTaskList(state.tableData.params); + if (res.data.code === '200') { + state.tableData.inspectTaskData = res.data.data.records; + state.tableData.total = res.data.data.total; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + //获取部门 + const getDepartmentData = async () => { + let res = await departmentApi().getDepartmentList(); + if (res.data.code === '200') { + state.departmentList = res.data.data; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + //获取部门 + const getQuotaList = async () => { + let res = await inspectTaskApi().getQuotaList(); + if (res.data.code === '200') { + state.quotaList = res.data.data; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + //获取巡检点 + const getInspectTaskPoint = async () => { + let res = await inspectPointApi().getInspectPointAll(); + if (res.data.code === '200') { + state.inspectPointAllList = res.data.data; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + //获取所有设施区域名称 + const initFacilityAreaType = async () => { + let res = await facilityAreaApi().getAllFacilityAreaList(); + if (res.data.code === '200') { + state.regionNameList = JSON.parse(JSON.stringify(res.data.data)); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + //获取所有RFID名称 + const initRFIDList = async () => { + let res = await RFIDApi().getAllRFIDList(); + if (res.data.code === '200') { + state.RFIDList = JSON.parse(JSON.stringify(res.data.data)); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + //获取班组 + const getClassGroupData = async () => { + let res = await teamManageApi().getRecord({ depIp: null, groupName: null, containGroupMemberEnable: null }); + if (res.data.code === '200') { + state.classGroupList = res.data.data; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + const changeStatus = async (value: { taskUnitStatus: number; id: number }) => { + if (value.taskUnitStatus === 2) { + ElMessageBox.confirm(`此操作将关闭该巡检任务”,是否继续?`, '提示', { + confirmButtonText: '确认', + cancelButtonText: '取消', + type: 'warning' + }) + .then(async () => { + let res = await inspectTaskApi().openOrCloseInspectTask({ id: value.id, taskUnitStatus: 2 }); + if (res.data.code === '200') { + await getInspectionTask(); + ElMessage({ + type: 'success', + duration: 2000, + message: '关闭成功' + }); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }) + .catch((error) => {}); + } else { + ElMessageBox.confirm(`此操作将开启该巡检任务”,是否继续?`, '提示', { + confirmButtonText: '确认', + cancelButtonText: '取消', + type: 'warning' + }) + .then(async () => { + let res = await inspectTaskApi().openOrCloseInspectTask({ id: value.id, taskUnitStatus: 1 }); + if (res.data.code === '200') { + await getInspectionTask(); + ElMessage({ + type: 'success', + duration: 2000, + message: '开启成功' + }); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }) + .catch((error) => {}); + } + await getInspectionTask(); + }; + + // 删除 + const deleteInspectTask = (row: any) => { + ElMessageBox.confirm(`此操作将永久删除该任务:“${row.unitName}”,是否继续?`, '提示', { + confirmButtonText: '确认', + cancelButtonText: '取消', + type: 'warning' + }) + .then(async () => { + let res = await inspectTaskApi().deleteInspectTask({ id: row.id }); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + duration: 2000, + message: '删除成功' + }); + await getInspectionTask(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }) + .catch(() => {}); + }; + + const openInspectTaskDialog = (type: string, value: {}) => { + inspectTaskDialogRef.value.showInspectTaskDialog(type, value, state.workTypeList, state.departmentList, state.timeType, state.classGroupList, state.quotaList, state.inspectPointAllList, state.regionNameList, state.RFIDList); + }; + + const parseNumber = (value: number, type: string) => { + if (type === '任务类型') { + return state.workTypeList.find((item) => item.id === value)?.name; + } else if (type === '检查频次') { + return state.timeType.find((item) => item.id == value)?.name; + } else { + return state.classGroupList.find((item) => item.id == value)?.groupName; + } + }; + + // 分页改变 + const onHandleSizeChange = (val: number) => { + state.tableData.params.pageSize = val; + getInspectionTask(); + }; + // 分页改变 + const onHandleCurrentChange = (val: number) => { + state.tableData.params.pageIndex = val; + getInspectionTask(); + }; + + const reset = () => { + state.tableData.params = { + pageIndex: 1, + pageSize: 10, + unitName: null, + workType: null, + createUserId: null, + execClassgroupId: null, + checkCycle: null, + checkCycleUnit: null + }; + }; + + // 页面加载时 + onMounted(() => { + getInspectionTask(); + getQuotaList(); + getDepartmentData(); + getClassGroupData(); + getInspectTaskPoint(); + initFacilityAreaType(); + initRFIDList(); + }); + + return { + View, + Edit, + Delete, + Refresh, + Plus, + reset, + changeStatus, + parseNumber, + deleteInspectTask, + getInspectionTask, + onHandleSizeChange, + onHandleCurrentChange, + inspectTaskDialogRef, + openInspectTaskDialog, + ...toRefs(state) + }; + } +}; +</script> + +<style scoped lang="scss"> +$homeNavLengh: 8; +.home-container { + height: calc(100vh - 144px); + box-sizing: border-box; + overflow: hidden; + .homeCard { + width: 100%; + padding: 20px; + box-sizing: border-box; + background: #fff; + border-radius: 4px; + + .main-card { + width: 100%; + height: 100%; + .cardTop { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 20px; + .mainCardBtn { + margin: 0; + } + } + .pageBtn { + height: 60px; + display: flex; + align-items: center; + justify-content: right; + + .demo-pagination-block + .demo-pagination-block { + margin-top: 10px; + } + .demo-pagination-block .demonstration { + margin-bottom: 16px; + } + } + } + &:last-of-type { + height: calc(100% - 100px); + } + } + .el-row { + display: flex; + align-items: center; + margin-bottom: 20px; + &:last-child { + margin-bottom: 0; + } + .grid-content { + align-items: center; + min-height: 36px; + } + + .topInfo { + display: flex; + align-items: center; + font-size: 16px; + font-weight: bold; + + & > div { + white-space: nowrap; + margin-right: 20px; + } + } + } +} +.stepItem { + width: 100%; + display: flex; + align-items: flex-start; + margin-bottom: 30px; + margin-left: 30px; + padding-bottom: 30px; + border-left: 2px solid #ccc; + &:first-of-type { + margin-top: 30px; + } + &:last-of-type { + margin-bottom: 0; + border-left: none; + } + .stepNum { + width: 30px; + height: 30px; + border-radius: 15px; + box-sizing: border-box; + color: #333; + border: 1px solid #999; + line-height: 28px; + text-align: center; + margin-right: 10px; + margin-left: -16px; + margin-top: -30px; + } + .stepCard { + width: 100%; + margin-top: -30px; + + .box-card { + width: 100%; + &:deep(.el-card__header) { + padding: 10px 15px; + } + .card-header { + width: 100%; + display: flex; + justify-content: space-between; + align-items: center; + & > div:first-of-type { + margin-right: 80px; + font-size: 18px; + font-weight: bold; + } + } + } + } + &:hover .card-header { + color: #0098f5; + } + &:hover .stepNum { + border: 2px solid #0098f5; + color: #0098f5; + } +} +.el-input { + width: 100% !important; +} +:deep(.el-date-editor) { + width: 100%; +} +.el-select { + width: 100%; +} +:deep(.el-textarea.is-disabled .el-textarea__inner) { + background-color: var(--el-card-bg-color); + color: var(--el-input-text-color, var(--el-text-color-regular)); +} +:deep(.el-input.is-disabled .el-input__inner) { + color: var(--el-input-text-color, var(--el-text-color-regular)); +} +:deep(.el-input.is-disabled .el-input__wrapper) { + background-color: var(--el-card-bg-color); +} +</style> diff --git a/src/views/intellectInspect/intelligentLine/index.vue b/src/views/intellectInspect/intelligentLine/index.vue new file mode 100644 index 0000000..c20d361 --- /dev/null +++ b/src/views/intellectInspect/intelligentLine/index.vue @@ -0,0 +1,1412 @@ +<template> + <div class="container" id="screenFull"> + <div class="big-title" @click="goBack()">国泰新华智能巡检系统</div> + <div style="height: 20px;font-size: 14px;line-height: 20px; color: #00ffff; margin-top: 4px">{{ present }}</div> + <div class="btns"> +<!-- <div class="fullbtn" @click="onScreenfullClick">--> +<!-- <div class="toFull">--> +<!-- <i class="iconfont" :title="全屏" :class="!isScreenfull ? 'icon-fullscreen' : 'icon-tuichuquanping'"></i>--> +<!-- <el-icon>--> +<!-- <FullScreen v-if="isScreenfull"/>--> +<!-- <Close v-else/>--> +<!-- </el-icon>--> +<!-- </div>--> +<!-- <div>全屏</div>--> +<!-- </div>--> + <div class="backBtn" @click="goBack()"> + <img src="../../../assets/loginPage/back-icon.png"/> + <div>退出</div> + </div> + </div> + <div class="blocks"> + <div> + <div class="star-pic"> + <dv-decoration-12 scanDur="5" haloDur="4" class="scan"/> + <div class="star-bg"><img src="../../../assets/loginPage/star-bg.png" /></div> + <div class="star"><img src="../../../assets/loginPage/device-pic.png" /></div> + </div> + <div class="line-map" v-if="dataList && dataList.length > 0"> + <div class="line-item" v-for="(item, index) in dataList" :key="index"> + <div class="picbox"> + <div class="imgbox"> + <img :src="item.rfidImage==null?defaultImg:item.rfidImage"/> + </div> + <p> + RFID: <span>{{ item.rfid }}</span> + </p> + <p> + 位置: <span>{{ item.region.toString() }}</span> + </p> + </div> + <div class="area-head"> + <div class="indicator" :class="item.points.some((e) => e.reportResult == 1) ? 'somewarning' : (item.points.some((e) => e.reportResult == null) ? 'someUndone' : '')"> + <div class="indi-dot"></div> + <!-- <div class="indi-pulse"></div>--> + <!-- <div class="indi-pulse1"></div>--> + </div> + <div class="arrow" v-if="item.points.some((e) => e.reportResult != null)"></div> + <div class="top-line" :class="item.points.some((e) => e.reportResult !== null) ? '' : 'fadeLine'"></div> + </div> + <div class="more-info"> + <div class="item" v-for="(t, i) in item.points" :key="i" :class="t.reportResult == null ? 'undone' : t.reportResult == 1 ? 'warning' : ''"> + <section> + <div class="dot"></div> + <div class="pulse"></div> + <div class="pulse1"></div> + </section> + <div :class="t.reportResult == null ? 'noBorder' : t.reportResult == 1 ? 'redBorder' : ''"> + <div> + <span>巡检点:</span><span>{{ t.point }}</span> + </div> + <div> + <span>巡检状态:</span><span>{{ t.pointCheckStatus == 1 ? '未完成' : '已完成' }}</span> + </div> + <div v-if="t.reportResult != null"> + <span>巡检指标:</span><span>{{ t.quotaContent }}</span> + </div> + <div v-if="(t.dataReportType == 2 || t.dataReportType == 3) && t.secondReferenceResult"> + <span>参数:</span><span class="target">{{ t.secondReferenceResult + t.quotaUnit }}</span> + </div> + <div> + <span>巡检结果:</span><span class="target">{{ t.reportResult == null ? '--' : t.reportResult == 0 ? '正常' : '异常' }}</span> + </div> + </div> + </div> + </div> + </div> + <div class="line-item finish"> + <div class="picbox"></div> + <div class="area-head"> + <div class="finish-point"> + <div>完成巡检</div> + </div> + </div> + </div> + </div> + <div class="tip" v-else>抱歉,暂时查询不到巡检路线...</div> + </div> + </div> + </div> +</template> + +<script lang="ts"> +import screenfull from 'screenfull'; +import { lineApi } from '/@/api/intelligentLine'; +import {toRefs, reactive, ref, onMounted, onUnmounted, computed, nextTick, onActivated} from 'vue'; +import {useRoute} from 'vue-router'; +import { storeToRefs } from 'pinia'; +import { initBackEndControlRoutes } from '/@/router/backEnd'; +import { Session } from '/@/utils/storage'; +import { Edit, View, Plus, Delete, Refresh, Search, Download } from '@element-plus/icons-vue'; +import { ElTable } from 'element-plus'; +import { FormInstance, FormRules, ElMessage } from 'element-plus'; +import { useUserInfo } from '/@/stores/userInfo'; + +// 定义接口来定义对象的类型 +interface stateType { + present: string; + path: string; + socket: any; + socketData: string; + data: Array<any>; + id: string; + defaultImg: string +} +export default { + name: 'intelligentLine', + components: {}, + setup() { + const userInfo = useUserInfo(); + const { userInfos } = storeToRefs(userInfo); + const route = useRoute(); + const state = reactive<stateType>({ + present: '', + path: '', + socketData: '', + socket: null, + data: [], + id: '', + defaultImg: new URL('../../../assets/default-img.jpg',import.meta.url).href + }); + + onMounted(() => { + setInterval(() => { + state.present = new Date().toLocaleString(); + }, 1000); + let curId = route.query.id + state.id = curId.toString() + getLine(state.id) + getUrl(state.id) + }); + onActivated(()=>{ + onScreenfullClick(); + }) + + const dataList = computed(() => { + return userInfos.value.dataList; + }); + + // 获取url + + const getUrl =async (id:string)=>{ + const res = await lineApi().getUrl(); + if (res.data.code === '200') { + state.path = 'http://' + res.data.data.ip + ':' + res.data.data.port + '/ws/test/' + if (typeof WebSocket === 'undefined') { + alert('您的浏览器不支持socket'); + } else { + // 实例化socket + let uid = userInfos.value.uid.toString() + var url = state.path + uid + '*' + id; + console.log(url,'url',uid,'uid') + url = url.replace('https', 'ws').replace('http', 'ws'); + console.log(url, '获取地址'); + state.socket = new WebSocket(url); + // 监听socket连接 + state.socket.onopen = () => { + console.log('socket连接成功'); + }; + // 监听socket错误信息 + state.socket.onerror = () => { + console.log('socket连接错误'); + }; + // 监听socket消息 + state.socket.onmessage = (msg) => { + if (msg.data === '连接成功') return; + console.log(msg.data,'data') + userInfos.value.dataList = JSON.parse(msg.data); + }; + } + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } + + // const send = () => { + // state.socket.send(params); + // }; + + // 接口获取数据 + const getLine = async (id:string) => { + let res = await lineApi().getLine({ id: id }); + if (res.data.code === '200') { + userInfos.value.dataList = res.data.data + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 全屏 + const onScreenfullClick = () => { + const element = document.getElementById('screenFull') + if (!screenfull.isEnabled) { + ElMessage.warning('暂不不支持全屏'); + return false; + } + screenfull.toggle(element); + }; + + // 返回 + const goBack = () => { + window.history.go(-1); + }; + + // 页面关闭处理 + onUnmounted(() => { + // 销毁监听 + nextTick(()=>{ + state.socket.onclose = () => { + console.log('socket已经关闭'); + }; + }) + }); + return { + dataList, + goBack, + onScreenfullClick, + ...toRefs(state) + }; + } +}; +</script> + +<!-- Add "scoped" attribute to limit CSS to this components only --> +<style scoped lang="scss"> + @media screen and (min-width: 1366px) { + .big-title { + font-size: 28px; + margin: 10px 0 20px; + } + .btns { + position: absolute; + z-index: 99999; + right: 60px; + top: 40px; + div { + font-size: 16px; + color: #00ffff; + } + } + .line-item { + width: calc((100vw - 40px) / 6); + padding-left: 20px; + display: flex; + flex-direction: column; + align-items: flex-start; + margin-right: 20px; + flex-wrap: nowrap; + + .picbox { + width: 100%; + height: 200px; + padding: 10px; + margin-bottom: 20px; + box-sizing: border-box; + .imgbox{ + width: 100%; + height: 120px; + position: relative; + margin-bottom: 10px; + border-radius: 4px; + overflow: hidden; + img { + display: block; + width: 100%; + height: auto; + position: absolute; + top: 0; + left: 0; + bottom: 0; + right: 0; + margin: auto; + } + } + + p { + font-size: 14px; + white-space: nowrap; + color: rgba(255, 255, 255, 0.8); + margin-bottom: 4px; + span { + color: #fff; + } + } + } + } + .item { + width: calc((100vw - 40px) / 6); + height: calc((100vh - 130px) / 5); + padding: 0 40px 20px 50px; + position: relative; + box-sizing: border-box; + border-left: 1px solid #36fcfc; + + &:last-of-type { + border: none; + } + + section { + width: 24px; + height: 24px; + border-radius: 50%; + position: absolute; + border: 1px solid rgba(0, 114, 255, 0.6); + top: -12px; + left: 10px; + + .dot { + position: absolute; + width: 12px; + height: 12px; + left: 5px; + top: 5px; + -webkit-border-radius: 50%; + -moz-border-radius: 50%; + border: 1px solid #0072ff; + border-radius: 50%; + background-color: #0072ff; + z-index: 2; + } + .pulse { + position: absolute; + width: 48px; + height: 48px; + left: -13px; + top: -13px; + border: 1px solid #0072ff; + -webkit-border-radius: 50%; + -moz-border-radius: 50%; + border-radius: 50%; + z-index: 1; + opacity: 0; + -webkit-animation: warn 2s ease-out; + -moz-animation: warn 2s ease-out; + animation: warn 2s ease-out; + -webkit-animation-iteration-count: infinite; + -moz-animation-iteration-count: infinite; + animation-iteration-count: infinite; + box-shadow: 1px 1px 30px #0072ff; + } + .pulse1 { + position: absolute; + width: 48px; + height: 48px; + left: -13px; + top: -13px; + border: 1px solid #0072ff; + -webkit-border-radius: 50%; + -moz-border-radius: 50%; + border-radius: 50%; + z-index: 1; + opacity: 0; + -webkit-animation: warn1 2s ease-out; + -moz-animation: warn1 2s ease-out; + animation: warn1 2s ease-out; + -webkit-animation-iteration-count: infinite; + -moz-animation-iteration-count: infinite; + animation-iteration-count: infinite; + box-shadow: 1px 1px 30px #0072ff; + } + } + & > div { + padding: 10px 0; + transform: translateY(-14px); + border-radius: 8px; + background-image: linear-gradient(to right, rgba(8, 109, 209, 0.4), rgba(11, 255, 255, 0.2)); + border: 1px solid rgba(54, 252, 252, 1); + display: flex; + flex-direction: column; + justify-content: center; + + div { + margin-bottom: 5px; + &:last-of-type { + margin-bottom: 0; + } + span { + display: inline-block; + white-space: nowrap; + width: 50%; + font-size: 13px; + color: #fff; + text-align: left; + + &:first-of-type { + text-align: right; + color: rgba(255, 255, 255, 0.8); + } + } + } + } + .noBorder{ + border: 1px solid rgba(54, 252, 252, 0.1); + } + .redBorder{ + border: 1px solid #ff0000; + } + p { + width: 140px; + height: 50px; + font-size: 18px; + line-height: 48px; + text-align: center; + color: #fff; + border-radius: 8px; + background-image: linear-gradient(to right, rgba(11, 255, 255, 0.2), rgba(8, 109, 209, 0.4)); + border: 1px solid rgba(54, 252, 252, 0.6); + } + } + .finish-point { + position: absolute; + width: 90px; + height: 90px; + border: 2px solid #0072ff; + left: -30px; + top: -45px; + border-radius: 50%; + + & > div { + width: 80px; + height: 80px; + position: absolute; + left: 3px; + top: 3px; + background: #0072ff; + border-radius: 50%; + color: #fff; + font-size: 16px; + line-height: 80px; + text-align: center; + font-weight: bolder; + } + } + } + + @media screen and (min-width: 1200px) and (max-width: 1366px){ + .big-title { + font-size: 28px; + margin: 10px 0 20px; + } + .btns { + position: absolute; + z-index: 99999; + right: 40px; + top: 40px; + div { + font-size: 14px; + color: #00ffff; + } + } + .line-item { + width: calc((100vw - 40px) / 5); + padding-left: 20px; + display: flex; + flex-direction: column; + align-items: flex-start; + margin-right: 20px; + flex-wrap: nowrap; + .picbox { + width: 100%; + height: 180px; + padding: 10px; + margin-bottom: 40px; + box-sizing: border-box; + .imgbox{ + width: 100%; + height: 100px; + position: relative; + margin-bottom: 6px; + border-radius: 4px; + overflow: hidden; + img { + display: block; + width: 100%; + height: auto; + position: absolute; + top: 0; + left: 0; + bottom: 0; + right: 0; + margin: auto; + } + } + p { + font-size: 14px; + white-space: nowrap; + color: rgba(255, 255, 255, 0.8); + margin-top: 10px; + span { + color: #fff; + } + } + } + } + .item { + width: calc((100vw - 40px) / 5); + height: calc((100vh - 130px) / 5); + padding: 0 20px 20px 40px; + position: relative; + box-sizing: border-box; + border-left: 1px solid #36fcfc; + + &:last-of-type { + border: none; + } + + section { + width: 24px; + height: 24px; + border-radius: 50%; + position: absolute; + border: 1px solid rgba(0, 114, 255, 0.6); + top: -12px; + left: 10px; + + .dot { + position: absolute; + width: 12px; + height: 12px; + left: 5px; + top: 5px; + -webkit-border-radius: 50%; + -moz-border-radius: 50%; + border: 1px solid #0072FF; + border-radius: 50%; + background-color: #0072FF; + z-index: 2; + } + .pulse { + position: absolute; + width: 48px; + height: 48px; + left: -13px; + top: -13px; + border: 1px solid #0072FF; + -webkit-border-radius: 50%; + -moz-border-radius: 50%; + border-radius: 50%; + z-index: 1; + opacity: 0; + -webkit-animation: warn 2s ease-out; + -moz-animation: warn 2s ease-out; + animation: warn 2s ease-out; + -webkit-animation-iteration-count: infinite; + -moz-animation-iteration-count: infinite; + animation-iteration-count: infinite; + box-shadow: 1px 1px 30px #0072FF; + } + .pulse1 { + position: absolute; + width: 48px; + height: 48px; + left: -13px; + top: -13px; + border: 1px solid #0072FF; + -webkit-border-radius: 50%; + -moz-border-radius: 50%; + border-radius: 50%; + z-index: 1; + opacity: 0; + -webkit-animation: warn1 2s ease-out; + -moz-animation: warn1 2s ease-out; + animation: warn1 2s ease-out; + -webkit-animation-iteration-count: infinite; + -moz-animation-iteration-count: infinite; + animation-iteration-count: infinite; + box-shadow: 1px 1px 30px #0072FF; + } + } + & > div { + width: 90%; + padding: 10px 0; + transform: translateY(-14px); + border-radius: 8px; + background-image: linear-gradient(to right, rgba(8, 109, 209, 0.4), rgba(11, 255, 255, 0.2)); + border: 1px solid rgba(54, 252, 252, 1); + display: flex; + flex-direction: column; + justify-content: center; + + div { + width: 100%; + margin-bottom: 5px; + &:last-of-type { + margin-bottom: 0; + } + span { + display: inline-block; + white-space: nowrap; + width: 50%; + font-size: 13px; + color: #fff; + text-align: left; + + &:first-of-type { + text-align: right; + color: rgba(255, 255, 255, 0.8); + } + } + } + } + .noBorder{ + border: 1px solid rgba(54, 252, 252, 0.1); + } + .redBorder{ + border: 1px solid #ff0000; + } + p { + width: 140px; + height: 50px; + font-size: 18px; + line-height: 48px; + text-align: center; + color: #fff; + border-radius: 8px; + background-image: linear-gradient(to right, rgba(11, 255, 255, 0.2), rgba(8, 109, 209, 0.4)); + border: 1px solid rgba(54, 252, 252, 0.6); + } + } + .finish-point { + position: absolute; + width: 80px; + height: 80px; + border: 1px solid #0072ff; + left: -20px; + top: -40px; + border-radius: 50%; + + & > div { + width: 70px; + height: 70px; + position: absolute; + left: 4px; + top: 4px; + background: #0072ff; + border-radius: 50%; + color: #fff; + font-size: 14px; + line-height: 70px; + text-align: center; + font-weight: bolder; + } + } + } + + @media screen and (max-width: 1200px){ + .big-title { + font-size: 20px; + margin: 5px 0 10px; + } + .btns { + position: absolute; + z-index: 99999; + right: 20px; + top: 40px; + div { + font-size: 12px; + color: #00ffff; + } + } + .line-item { + width: 20vw; + padding-left: 10px; + display: flex; + flex-direction: column; + align-items: flex-start; + margin-right: 20px; + flex-wrap: nowrap; + .picbox { + width: 100%; + height: 160px; + padding: 10px; + margin-bottom: 30px; + box-sizing: border-box; + .imgbox{ + width: 100%; + height: 80px; + position: relative; + margin-bottom: 10px; + border-radius: 4px; + overflow: hidden; + img { + display: block; + width: 100%; + height: auto; + position: absolute; + top: 0; + left: 0; + bottom: 0; + right: 0; + margin: auto; + } + } + p { + font-size: 12px; + color: rgba(255, 255, 255, 0.8); + margin-top: 6px; + span { + color: #fff; + } + } + } + } + .item { + width: 20vw; + height: calc((100vh - 130px) / 5); + padding: 0 0 20px 30px; + position: relative; + box-sizing: border-box; + border-left: 1px solid #36fcfc; + + &:last-of-type { + border: none; + } + + section { + width: 24px; + height: 24px; + border-radius: 50%; + position: absolute; + border: 1px solid rgba(0, 114, 255, 0.6); + top: -12px; + left: 2px; + + .dot { + position: absolute; + width: 12px; + height: 12px; + left: 5px; + top: 5px; + -webkit-border-radius: 50%; + -moz-border-radius: 50%; + border: 1px solid #0072ff; + border-radius: 50%; + background-color: #0072ff; + z-index: 2; + } + .pulse { + position: absolute; + width: 48px; + height: 48px; + left: -13px; + top: -13px; + border: 1px solid #0072ff; + -webkit-border-radius: 50%; + -moz-border-radius: 50%; + border-radius: 50%; + z-index: 1; + opacity: 0; + -webkit-animation: warn 2s ease-out; + -moz-animation: warn 2s ease-out; + animation: warn 2s ease-out; + -webkit-animation-iteration-count: infinite; + -moz-animation-iteration-count: infinite; + animation-iteration-count: infinite; + box-shadow: 1px 1px 30px #0072ff; + } + .pulse1 { + position: absolute; + width: 48px; + height: 48px; + left: -13px; + top: -13px; + border: 1px solid #0072ff; + -webkit-border-radius: 50%; + -moz-border-radius: 50%; + border-radius: 50%; + z-index: 1; + opacity: 0; + -webkit-animation: warn1 2s ease-out; + -moz-animation: warn1 2s ease-out; + animation: warn1 2s ease-out; + -webkit-animation-iteration-count: infinite; + -moz-animation-iteration-count: infinite; + animation-iteration-count: infinite; + box-shadow: 1px 1px 30px #0072ff; + } + } + & > div { + width: 80%; + padding: 4px 0; + transform: translateY(-14px); + border-radius: 8px; + background-image: linear-gradient(to right, rgba(8, 109, 209, 0.4), rgba(11, 255, 255, 0.2)); + border: 1px solid rgba(54, 252, 252, 1); + display: flex; + flex-direction: column; + justify-content: center; + + div { + width: 100%; + margin-bottom: 2px; + &:last-of-type { + margin-bottom: 0; + } + span { + width: 50%; + display: inline-block; + white-space: nowrap; + font-size: 12px; + color: #fff; + text-align: left; + + &:first-of-type { + text-align: right; + color: rgba(255, 255, 255, 0.8); + } + } + } + } + .noBorder{ + border: 1px solid rgba(54, 252, 252, 0.1); + } + .redBorder{ + border: 1px solid #ff0000; + } + p { + width: 140px; + height: 50px; + font-size: 18px; + line-height: 48px; + text-align: center; + color: #fff; + border-radius: 8px; + background-image: linear-gradient(to right, rgba(11, 255, 255, 0.2), rgba(8, 109, 209, 0.4)); + border: 1px solid rgba(54, 252, 252, 0.6); + } + } + .finish-point { + position: absolute; + width: 70px; + height: 70px; + border: 1px solid #0072ff; + left: -10px; + top: -35px; + border-radius: 50%; + + & > div { + width: 60px; + height: 60px; + position: absolute; + left: 4px; + top: 4px; + background: #0072ff; + border-radius: 50%; + color: #fff; + font-size: 12px; + line-height: 60px; + text-align: center; + font-weight: bolder; + } + } + } + + @keyframes warn { + 0% { + transform: scale(0.3); + -webkit-transform: scale(0.3); + opacity: 0; + } + + 25% { + transform: scale(0.3); + -webkit-transform: scale(0.3); + opacity: 0.1; + } + + 50% { + transform: scale(0.5); + -webkit-transform: scale(0.5); + opacity: 0.3; + } + + 75% { + transform: scale(0.8); + -webkit-transform: scale(0.8); + opacity: 0.6; + } + + 100% { + transform: scale(1); + -webkit-transform: scale(1); + opacity: 0; + } + } + + @keyframes warn1 { + 0% { + transform: scale(0.3); + -webkit-transform: scale(0.3); + opacity: 0; + } + + 25% { + transform: scale(0.3); + -webkit-transform: scale(0.3); + opacity: 0.1; + } + + 50% { + transform: scale(0.3); + -webkit-transform: scale(0.3); + opacity: 0.3; + } + + 75% { + transform: scale(0.5); + -webkit-transform: scale(0.5); + opacity: 0.6; + } + + 100% { + transform: scale(0.8); + -webkit-transform: scale(0.8); + opacity: 0; + } + } + + @keyframes circle { + 0% { + transform: rotate(0); + -webkit-transform: rotate(0); + } + 100% { + transform: rotate(360deg); + -webkit-transform: rotate(360deg); + } + } + @keyframes run { + to { + transform: translateX(calc((100vw - 180px) / 6 - 80px)); + } + } + .container { + width: 100%; + height: 100%; + position: relative; + display: flex; + flex-direction: column; + align-items: center; + background: url('../../../assets/loginPage/map-bg.jpg') no-repeat center; + background-size: 100% 100%; + .big-title { + height: 40px; + line-height: 40px; + font-weight: bold; + text-align: center; + color: #fff; + display: flex; + align-items: center; + justify-content: center; + } + .btns { + display: flex; + align-items: center; + .fullbtn { + cursor: pointer; + display: flex; + align-items: center; + margin-right: 20px; + .toFull { + font-weight: bolder; + color: #00ffff; + margin-right: 10px; + } + } + + .backBtn { + cursor: pointer; + display: flex; + align-items: center; + img { + width: 14px; + height: 14px; + margin-right: 10px; + } + } + } + .blocks { + width: 100%; + height: calc(100% - 90px); + padding: 10px 40px 35px; + box-sizing: border-box; + + &>div{ + width: 100%; + height: 100%; + display: flex; + justify-content: left; + align-items: flex-start; + overflow-y: hidden; + overflow-x: hidden; + overflow: auto; + } + + .line-map { + display: flex; + justify-content: center; + align-items: flex-start; + + .line-item { + + .area-head { + position: relative; + width: 100%; + height: 80px; + padding-left: 38px; + border-left: 1px solid #36fcfc; + + .indicator { + width: 36px; + height: 36px; + border-radius: 50%; + position: absolute; + border: 1px solid #00ff66; + top: -18px; + left: -18px; + + .indi-dot { + position: absolute; + width: 20px; + height: 20px; + left: 7px; + top: 7px; + -webkit-border-radius: 50%; + -moz-border-radius: 50%; + border: 1px solid #00ff66; + border-radius: 50%; + background-color: #00ff66; + z-index: 2; + } + .indi-pulse { + position: absolute; + width: 56px; + height: 56px; + left: -11px; + top: -11px; + border: 1px solid #00ff66; + -webkit-border-radius: 50%; + -moz-border-radius: 50%; + border-radius: 50%; + z-index: 1; + opacity: 0; + -webkit-animation: warn 2s ease-out; + -moz-animation: warn 2s ease-out; + animation: warn 2s ease-out; + -webkit-animation-iteration-count: infinite; + -moz-animation-iteration-count: infinite; + animation-iteration-count: infinite; + box-shadow: 1px 1px 30px #00ff66; + } + .indi-pulse1 { + position: absolute; + width: 56px; + height: 56px; + left: -11px; + top: -11px; + border: 1px solid #3399ff; + -webkit-border-radius: 50%; + -moz-border-radius: 50%; + border-radius: 50%; + z-index: 1; + opacity: 0; + -webkit-animation: warn1 2s ease-out; + -moz-animation: warn1 2s ease-out; + animation: warn1 2s ease-out; + -webkit-animation-iteration-count: infinite; + -moz-animation-iteration-count: infinite; + animation-iteration-count: infinite; + box-shadow: 1px 1px 30px #3399ff; + } + } + .someUndone { + width: 36px; + height: 36px; + border-radius: 50%; + position: absolute; + border: 1px solid #ccc; + top: -18px; + left: -18px; + + .indi-dot { + position: absolute; + width: 20px; + height: 20px; + left: 7px; + top: 7px; + -webkit-border-radius: 50%; + -moz-border-radius: 50%; + border: 1px solid #ccc; + border-radius: 50%; + background-color: #ccc; + z-index: 2; + } + } + .somewarning { + width: 36px; + height: 36px; + border-radius: 50%; + position: absolute; + border: 1px solid #ff0000; + top: -18px; + left: -18px; + + .indi-dot { + position: absolute; + width: 20px; + height: 20px; + left: 7px; + top: 7px; + -webkit-border-radius: 50%; + -moz-border-radius: 50%; + border: 1px solid #ff0000; + border-radius: 50%; + background-color: #ff0000; + z-index: 2; + } + } + .arrow { + position: absolute; + width: 58px; + height: 20px; + left: 38px; + top: -10px; + background: url('../../../assets/loginPage/arrow-r.png') 0 / cover no-repeat; + animation: run 2s steps(4) 0s infinite; + } + .top-line { + width: 100%; + border-top: 2px solid #36fcfc; + } + .fadeLine { + width: 100%; + border-top: 1px solid rgba(54,252,252,.6); + } + } + .fadeBorder { + border-left: 1px solid #ccc; + } + .more-info { + width: 100%; + + .warning { + & > section { + border: 1px solid #ff0000; + + .dot { + border: 1px solid #ff0000; + background: #ff0000; + } + .pulse { + border: 1px solid #ff0000; + box-shadow: 1px 1px 30px #ff0000; + } + .pulse1 { + border: 1px solid #ff0000; + box-shadow: 1px 1px 30px #ff0000; + } + } + + & > div { + div { + span.target { + color: #ff2929; + font-weight: bolder; + } + } + } + } + .undone { + & > section { + border: 1px solid #ccc; + + .dot { + border: 1px solid #ccc; + background: #ccc; + } + .pulse { + display: none; + } + .pulse1 { + display: none; + } + } + } + } + } + .finish { + .area-head { + position: relative; + width: 100%; + height: 80px; + border-left: none; + } + } + .pic-tit { + display: flex; + width: calc((100vw - 120px) / 7); + height: 160px; + padding: 20px; + transform: translate(-20px, -40%); + flex-direction: column; + align-items: flex-start; + + img { + width: calc((100vw - 120px) / 7 - 40px); + height: 90px; + margin-bottom: 10px; + border-radius: 4px; + } + p { + font-size: 16px; + color: #00ffff; + font-weight: bold; + } + } + + .water { + transform: none; + } + .start { + padding: 40px 0; + p { + margin-top: -21px; + margin-left: 20px; + } + span { + width: 1px; + height: 50px; + background: #36fcfc; + position: absolute; + top: -10px; + left: 0; + } + section { + position: absolute; + top: 30px; + left: -14px; + } + } + } + .tip { + width: 100%; + font-size: 30px; + text-align: center; + margin-top: 100px; + color: #fff; + font-weight: bolder; + } + .current-task { + position: absolute; + width: calc((500vw - 600px) / 7); + z-index: 999999; + top: 0; + right: 0; + padding: 0 60px; + display: flex; + align-items: center; + justify-content: space-between; + + .task-des { + padding: 10px 20px; + display: flex; + align-items: center; + border: 1px solid #36fcfc; + + .task-des-l { + display: flex; + flex-direction: column; + align-items: center; + font-size: 20px; + color: #36fcfc; + border-right: 1px solid #36fcfc; + padding-right: 20px; + img { + margin-bottom: 10px; + } + } + .task-des-r { + width: calc((200vw - 240px) / 7); + display: flex; + flex-direction: column; + align-items: center; + font-size: 20px; + line-height: 28px; + color: #fcfc36; + padding-left: 20px; + } + } + .current-data { + width: 267px; + height: 138px; + padding: 20px 30px; + box-sizing: border-box; + background: url('../../../assets/loginPage/xj-bg.png') no-repeat center; + background-size: 100% 100%; + + .data-area { + display: flex; + align-items: center; + border-bottom: 1px solid #040c3b; + font-weight: bold; + padding-bottom: 10px; + box-sizing: border-box; + + img { + width: 30px; + height: 30px; + margin-right: 10px; + animation: circle 1s ease-in-out infinite; + } + + div { + font-size: 15px; + color: rgba(4, 12, 59, 0.8); + + span { + color: #040c3b; + } + } + } + + .data-spot { + display: flex; + align-items: flex-start; + margin-top: 10px; + + & > div { + display: flex; + flex-direction: column; + align-items: center; + width: 50%; + font-size: 14px; + color: rgba(4, 12, 59, 0.8); + + p { + margin-top: 6px; + color: #040c3b; + } + + &:first-of-type { + border-right: 1px solid #040c3b; + } + } + } + } + } + .star-pic { + position: absolute; + width: calc((100vw - 120px) / 7); + height: calc((100vw - 120px) / 7); + z-index: 9999; + bottom: 40px; + right: 40px; + padding: 20px; + + .scan{ + position: inherit; + width: 65%; + height: 65%; + z-index: 99997; + left: 0; + top: 0; + right: 0; + bottom: 0; + margin: auto; + } + + .star-bg { + position: inherit; + width: 100%; + height: 100%; + z-index: 99998; + left: 0; + top: 0; + img { + width: 100%; + height: auto; + animation: circle 30s linear infinite; + } + } + .star { + position: inherit; + width: 100%; + height: 100%; + z-index: 99999; + left: 0; + top: 0; + img { + width: 100%; + height: auto; + } + } + } + } + } +</style> diff --git a/src/views/layoutPage/index.vue b/src/views/layoutPage/index.vue new file mode 100644 index 0000000..549c2a3 --- /dev/null +++ b/src/views/layoutPage/index.vue @@ -0,0 +1,182 @@ +<template> + <div class="home-container"> + <el-row :gutter="15" class="home-card-one mb15"> + <el-col + :xs="24" + :sm="12" + :md="12" + :lg="4" + :xl="4" + v-for="(v, k) in homeOne" + :key="k" + :class="{ 'home-media home-media-lg': k > 1, 'home-media-sm': k === 1 }" + > + <div class="home-card-item flex" > + <el-button @click="renderMenu(v.id)">{{v.name}}</el-button> + </div> + </el-col> + </el-row> + <el-row :gutter="15" class="home-card-two mb15"> + <el-col :xs="24" :sm="14" :md="14" :lg="16" :xl="16"> + <div class="home-card-item"> + <div style="height: 100%"> + <el-button @click="renderMenu('6')">{{'应急管理系统'}}</el-button> + </div> + </div> + </el-col> + <el-col :xs="24" :sm="10" :md="10" :lg="8" :xl="8" class="home-media"> + <div class="home-card-item"> + <div style="height: 100%"> + <el-button @click="renderMenu('7')">{{'目标责任管理系统'}}</el-button> + </div> + </div> + </el-col> + </el-row> + <el-row :gutter="15" class="home-card-three"> + <el-col :xs="24" :sm="10" :md="10" :lg="8" :xl="8"> + <div class="home-card-item"> + <el-button @click="renderMenu('8')">{{'事故管理系统'}}</el-button> + </div> + </el-col> + <el-col :xs="24" :sm="14" :md="14" :lg="16" :xl="16" class="home-media"> + <div class="home-card-item"> + <div style="height: 100%"> + <el-button @click="renderMenu('9')">{{'设备综合管控系统'}}</el-button> + </div> + </div> + </el-col> + </el-row> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, defineComponent, } from 'vue'; +import { storeToRefs } from 'pinia'; +import { initBackEndControlRoutes } from '/@/router/backEnd'; +import {useUserInfo} from "/@/stores/userInfo"; +import { Session } from '/@/utils/storage'; +let global: any = { + homeChartOne: null, + homeChartTwo: null, + homeCharThree: null, + dispose: [null, '', undefined], +}; + +interface stateType { + homeOne: Array <type> +} +interface type { + id:number, + name: string +} +export default defineComponent({ + name: 'layoutPage', + setup() { + const userInfo = useUserInfo() + const { userInfos } = storeToRefs(userInfo); + const state = reactive<stateType>({ + homeOne:[{id:1,name:'安全基础信息系统'},{id:2,name:'双重预防系统'},{id:3,name:'系统2'},{id:4,name:'系统3'},{id:5,name:'系统4'}], + }); + // 折线图 + const renderMenu = async (value: string) => { + Session.set('projectId',value) + userInfos.value.projectId = value + await initBackEndControlRoutes(); + }; + return { + renderMenu, + ...toRefs(state), + }; + }, +}); +</script> + +<style scoped lang="scss"> +$homeNavLengh: 8; +.home-container { + overflow: hidden; + .home-card-one, + .home-card-two, + .home-card-three { + .home-card-item { + width: 100%; + height: 130px; + border-radius: 4px; + transition: all ease 0.3s; + padding: 20px; + overflow: hidden; + background: var(--el-color-white); + color: var(--el-text-color-primary); + border: 1px solid var(--next-border-color-light); + &:hover { + box-shadow: 0 2px 12px var(--next-color-dark-hover); + transition: all ease 0.3s; + } + &-icon { + width: 70px; + height: 70px; + border-radius: 100%; + flex-shrink: 1; + i { + color: var(--el-text-color-placeholder); + } + } + &-title { + font-size: 15px; + font-weight: bold; + height: 30px; + } + } + } + .home-card-one { + @for $i from 0 through 3 { + .home-one-animation#{$i} { + opacity: 0; + animation-name: error-num; + animation-duration: 0.5s; + animation-fill-mode: forwards; + animation-delay: calc($i/10) + s; + } + } + } + .home-card-two, + .home-card-three { + .home-card-item { + height: 400px; + width: 100%; + overflow: hidden; + .home-monitor { + height: 100%; + .flex-warp-item { + width: 25%; + height: 111px; + display: flex; + .flex-warp-item-box { + margin: auto; + text-align: center; + color: var(--el-text-color-primary); + display: flex; + border-radius: 5px; + background: var(--next-bg-color); + cursor: pointer; + transition: all 0.3s ease; + &:hover { + background: var(--el-color-primary-light-9); + transition: all 0.3s ease; + } + } + @for $i from 0 through $homeNavLengh { + .home-animation#{$i} { + opacity: 0; + animation-name: error-num; + animation-duration: 0.5s; + animation-fill-mode: forwards; + animation-delay: calc($i/10) + s; + } + } + } + } + } + } +} +</style> diff --git a/src/views/loginPage/component/accountLogin.vue b/src/views/loginPage/component/accountLogin.vue new file mode 100644 index 0000000..167d6b1 --- /dev/null +++ b/src/views/loginPage/component/accountLogin.vue @@ -0,0 +1,371 @@ +<template> + <el-form size="large" class="login-content-form"> + <el-form-item class="login-animation1"> + <el-input type="text" :placeholder="$t('message.account.accountPlaceholder1')" v-model="ruleForm.username" clearable autocomplete="off" size="large"> + <template #prefix> + <el-icon class="el-input__icon" style="margin-right: 20px"><img src="../../../assets/loginPage/login_icon_user.png" style="width: 24px; height: 24px" /></el-icon> + </template> + </el-input> + </el-form-item> + <el-form-item class="login-animation2"> + <el-input :type="isShowPassword ? 'text' : 'password'" :placeholder="$t('message.account.accountPlaceholder2')" v-model="ruleForm.password" autocomplete="off" size="large" @keyup.enter.native="onSignIn"> + <template #prefix> + <el-icon class="el-input__icon" style="margin-right: 20px"><img src="../../../assets/loginPage/login_icon_password.png" style="width: 24px; height: 24px" /></el-icon> + </template> + <template #suffix> + <i class="iconfont el-input__icon login-content-password" :class="isShowPassword ? 'icon-xianshimima' : 'icon-yincangmima'" @click="isShowPassword = !isShowPassword"> </i> + </template> + </el-input> + </el-form-item> + <el-form-item class="login-animation4 codeDeal"> + <el-checkbox v-model="saveCode" label="记住密码" size="large" /> + <span class="forgetCode" @click="identify">忘记密码?</span> + </el-form-item> + <el-form-item class="login-animation4"> + <el-button type="primary" class="login-content-submit" round @click="onSignIn" :loading="loading.signIn"> + <span>登录系统</span> + </el-button> + </el-form-item> + </el-form> + <el-dialog v-model="identifyDialog" title="重置密码" width="30%" center @close="clearIdentity"> + <el-form :model="identity" label-width="80px" ref="identifyRef" :rules="identityRules"> + <el-divider border-style="dashed">身份验证</el-divider> + <el-form-item label="姓名" prop="realName"> + <el-input v-model="identity.realName"/> + </el-form-item> + <el-form-item label="身份证号" prop="identify"> + <el-input v-model="identity.identify"/> + </el-form-item> + <el-form-item label="手机号" prop="phone"> + <el-input v-model="identity.phone"/> + </el-form-item> + <el-divider border-style="dashed">重设密码</el-divider> + <el-form-item label="密码" prop="password"> + <el-input v-model="identity.password" :type="showPass ? 'text': 'password'" autocomplete="off"> + <template #suffix> + <i class="iconfont el-input__icon login-content-password" :class="showPass ? 'icon-xianshimima' : 'icon-yincangmima'" @click="showPass = !showPass"> </i> + </template> + </el-input> + </el-form-item> + <el-form-item label="确认密码" prop="rePassword"> + <el-input + v-model="identity.rePassword" + :type="showRePass ? 'text': 'password'" + autocomplete="off" + > + <template #suffix> + <i class="iconfont el-input__icon login-content-password" :class="showRePass ? 'icon-xianshimima' : 'icon-yincangmima'" @click="showRePass = !showRePass"> </i> + </template> + </el-input> + </el-form-item> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button type="warning" @click="identifyDialog = false" size="default">取消</el-button> + <el-button type="primary" @click="confirmIdentity(identifyRef)" size="default">确认</el-button> + </span> + </template> + </el-dialog> +</template> + +<script lang="ts"> +import {toRefs, reactive, defineComponent, computed, ref, onMounted} from 'vue'; +import { useRoute, useRouter } from 'vue-router'; +import { ElMessage } from 'element-plus'; +import { useI18n } from 'vue-i18n'; +import Cookies from 'js-cookie'; +import { storeToRefs } from 'pinia'; +import { useThemeConfig } from '/@/stores/themeConfig'; +import { initFrontEndControlRoutes } from '/@/router/frontEnd'; +import { initBackEndControlRoutes } from '/@/router/backEnd'; +import { Session } from '/@/utils/storage'; +import { formatAxis } from '/@/utils/formatTime'; +import { NextLoading } from '/@/utils/loading'; +import { useLoginApi } from '/@/api/login'; +import { useUserInfo } from '/@/stores/userInfo'; +import type { FormInstance, FormRules } from 'element-plus' +import {workApplyApi} from "/@/api/specialWorkSystem/workApply"; +import {verifyPhone,verifyIdCard} from "/@/utils/toolsValidate" +import { Base64 } from 'js-base64' +export default defineComponent({ + name: 'accountLogin', + setup() { + const { t } = useI18n(); + const userInfo = useUserInfo(); + const route = useRoute(); + const router = useRouter(); + const state = reactive({ + isShowPassword: false, + showPass: false, + showRePass: false, + saveCode: false, + ruleForm: { + username: '', + password: '' + }, + loading: { + signIn: false + }, + identity:{ + realName: '', + identify: '', + phone: '', + password: '', + rePassword: '' + }, + identifyDialog: false + }); + const identifyRef = ref<FormInstance>() + + // 页面载入时执行方法 + onMounted(() => { + hasUserCodeOrPassword() + // getAllDepartment(); + }); + + const hasUserCodeOrPassword =()=> { + if (localStorage.getItem('userCode') && localStorage.getItem('userPassword')) { + state.ruleForm.username = localStorage.getItem('userCode') as string + state.ruleForm.password = Base64.decode(localStorage.getItem('userPassword'))//解密 + state.saveCode = true + } + } + const checkCode = (rule: any, value: any, callback: any) => { + if (value == '') { + return callback(new Error('该内容不能为空')) + } + setTimeout(() => { + if (!verifyIdCard(value)) { + callback(new Error('身份证格式不正确')) + }else callback(); + }, 400) + } + const checkPhone = (rule: any, value: any, callback: any) => { + if (value == '') { + return callback(new Error('该内容不能为空')) + } + setTimeout(() => { + if (!verifyPhone(value)) { + callback(new Error('手机号格式不正确')) + }else callback(); + }, 400) + } + // 修改密码 + const validatePass = (rule: any, value: any, callback: any) => { + if (value === '') { + callback(new Error('该内容不能为空')) + } else { + if (state.identity.rePassword !== '') { + if (!identifyRef.value) return + identifyRef.value.validateField('rePassword', () => null) + } + callback() + } + } + const validatePass2 = (rule: any, value: any, callback: any) => { + if (value === '') { + callback(new Error('该内容不能为空')) + } else if (value !== state.identity.password) { + callback(new Error("两次输入的密码不一致!")) + } else { + callback() + } + } + const identityRules = reactive({ + realName: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + identify: [{ required: true, validator: checkCode, trigger: 'blur'}], + phone: [{ required: true, validator: checkPhone, trigger: 'blur' }], + password: [{ required: true, validator: validatePass, trigger: 'blur' }], + rePassword: [{ required: true, validator: validatePass2, trigger: 'blur' }] + }); + + // 时间获取 + const currentTime = computed(() => { + return formatAxis(new Date()); + }); + // 登录 + const onSignIn = async () => { + state.loading.signIn = true; + // 存储 token 到浏览器缓存 + let res = await useLoginApi().signIn(state.ruleForm); + if (res.data.code === '200') { + await userInfo.setUserInfos(res.data.data); + Cookies.set('token', res.data.data.accessToken); + Cookies.set('projectId', ''); + Cookies.set('uid', res.data.data.uid); + Cookies.set('depId', res.data.data.depId); + // Session.set('token', res.data.data.accessToken); + // Session.set('projectId', ''); + // Session.set('uid', res.data.data.uid); + if (state.saveCode) { + localStorage.setItem('userCode', state.ruleForm.username) + localStorage.setItem('userPassword', Base64.encode(state.ruleForm.password),) + } else { + localStorage.removeItem('userCode') + localStorage.removeItem('userPassword') + } + await signInSuccess(); + } else { + state.loading.signIn = false; + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + state.loading.signIn = false; + // Session.set('token', Math.random().toString(36).substr(0)); + // // 模拟数据,对接接口时,记得删除多余代码及对应依赖的引入。用于 `/src/stores/userInfo.ts` 中不同用户登录判断(模拟数据) + // Cookies.set('userName', state.ruleForm.username); + // if (!themeConfig.value.isRequestRoutes) { + // // 前端控制路由,2、请注意执行顺序 + // await initFrontEndControlRoutes(); + // signInSuccess(); + // } else { + // // 模拟后端控制路由,isRequestRoutes 为 true,则开启后端控制路由 + // // 添加完动态路由,再进行 router 跳转,否则可能报错 No match found for location with path "/" + // await initBackEndControlRoutes(); + // // 执行完 initBackEndControlRoutes,再执行 signInSuccess + // signInSuccess(); + // } + }; + // 登录成功后的跳转 + const signInSuccess = async () => { + // 初始化登录成功时间问候语 + let currentTimeInfo = currentTime.value; + // 登录成功,跳到转首页 + // 如果是复制粘贴的路径,非首页/登录页,那么登录成功后重定向到对应的路径中 + // if (route.query?.redirect) { + router.push('/newMenu'); + // router.push({ + // path: <string>route.query?.redirect, + // query: Object.keys(<string>route.query?.params).length > 0 ? JSON.parse(<string>route.query?.params) : '', + // }); + // } else { + // router.push('/loginPage'); + // } + state.loading.signIn = true; + const signInText = t('message.signInText'); + ElMessage.success(`${currentTimeInfo},${signInText}`); + // 登录成功提示 + // 关闭 loading + // 添加 loading,防止第一次进入界面时出现短暂空白 + // NextLoading.start(); + }; + + // 修改密码 + const identify =()=>{ + state.identifyDialog = true + } + + // 提交验证 + const confirmIdentity = (formEl: FormInstance | undefined) => { + if (!formEl) return + formEl.validate(async(valid) => { + if (valid) { + const res = await useLoginApi().changeCode(state.identity); + if(res.data.code == '200'){ + ElMessage({ + type: 'success', + message: '修改成功,请使用新密码登录' + }); + }else{ + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + state.identifyDialog = false + } else { + console.log('error submit!') + return false + } + }) + } + const clearIdentity = ()=>{ + state.identity = { + realName: '', + identify: '', + phone: '', + password: '', + rePassword: '' + } + } + + return { + identifyRef, + identityRules, + clearIdentity, + onSignIn, + identify, + confirmIdentity, + validatePass, + validatePass2, + ...toRefs(state) + }; + } +}); +</script> + +<style scoped lang="scss"> +.login-content-form { + margin-top: 40px; + width: 100%; + + .el-input::v-deep .el-input__wrapper { + height: 56px; + border-radius: 28px; + padding: 0 30px; + background: #f2f2f2; + &:focus-within { + border: 1px solid #2053d7; + } + } + @for $i from 1 through 4 { + .login-animation#{$i} { + opacity: 0; + animation-name: error-num; + animation-duration: 0.5s; + animation-fill-mode: forwards; + animation-delay: calc($i/10) + s; + } + } + .codeDeal::v-deep .el-form-item__content { + display: flex; + justify-content: space-between; + + .forgetCode { + color: #2053d7; + cursor: pointer; + } + } + .login-content-password { + width: 100%; + display: inline-block; + cursor: pointer; + &:hover { + color: #909399; + } + } + .login-content-code { + width: 100%; + padding: 0; + font-weight: bold; + letter-spacing: 5px; + } + .login-content-submit { + width: 100%; + height: 56px; + font-size: 16px; + border-radius: 28px; + letter-spacing: 4px; + font-weight: 300; + margin-top: 15px; + background: #2053d7; + transition: 0.3s; + &:hover { + letter-spacing: 6px; + background: #4e7aec; + } + } +} +</style> diff --git a/src/views/loginPage/loginPage.vue b/src/views/loginPage/loginPage.vue new file mode 100644 index 0000000..14d69e8 --- /dev/null +++ b/src/views/loginPage/loginPage.vue @@ -0,0 +1,196 @@ +<template> + <div class="login-container"> + <div id="particles-js" style="display: flex; align-items: center; justify-content: center"> + <canvas class="particles-js-canvas-el" style="width: 100%; height: 100%" width="472" height="625"></canvas> + </div> + <el-row class="loginContent"> + <el-col :md="12"> + <div class="loginContL"> + <div class="apTitleT">新疆国泰新华</div> + <div class="apTitleB">安全风险预警监测系统(试运行)</div> + <span></span> + </div> + </el-col> + <el-col :md="12" style="display: flex; justify-content: flex-end"> + <div class="loginPanel"> + <div class="welc">WELCOME!</div> + <div class="welcc">欢迎登录</div> + <!-- <div class="loginInfo">--> + <!-- <el-input v-model="input" placeholder="Please input" />--> + <!-- </div>--> + <div> + <el-tabs v-model="tabsActiveName"> + <AccountLogin /> + </el-tabs> + </div> + </div> + </el-col> + </el-row> + <div class="rights">技术支持:苏州国科鸿宇智能科技有限公司<br/><span>GTXH Intelligent Security Management System V1.0.1</span></div> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, computed, defineComponent, onMounted } from 'vue'; +import { storeToRefs } from 'pinia'; +import { useThemeConfig } from '/@/stores/themeConfig'; +import logoMini from '/@/assets/logo-mini.svg'; +import loginIconTwo from '/@/assets/login-icon-two.svg'; +import { NextLoading } from '/@/utils/loading'; +import AccountLogin from '/@/views/loginPage/component/accountLogin.vue'; +import { loginBg } from '../../../static/loginPage.js/login.js'; +import { loginApp } from '../../../static/loginPage.js/loginApp.js'; + +// 定义接口来定义对象的类型 +interface LoginState { + tabsActiveName: string; + isScan: boolean; +} + +export default defineComponent({ + name: 'loginIndex', + components: { AccountLogin }, + setup() { + const storesThemeConfig = useThemeConfig(); + const { themeConfig } = storeToRefs(storesThemeConfig); + const state = reactive<LoginState>({ + tabsActiveName: 'account', + isScan: false + }); + // 获取布局配置信息 + const getThemeConfig = computed(() => { + return themeConfig.value; + }); + // 页面加载时 + onMounted(() => { + NextLoading.done(); + loginBg(); + loginApp(); + }); + return { + logoMini, + loginIconTwo, + getThemeConfig, + ...toRefs(state) + }; + } +}); +</script> + +<style scoped lang="scss"> + @media screen and (min-width: 1200px){ + .loginContent{ + display: flex; + justify-content: space-around; + padding: 0 200px; + } + .loginContL { + font-size: 60px; + font-weight: bold; + margin-bottom: 100px; + } + } + @media screen and (min-width: 960px) and (max-width: 1200px){ + .loginContent{ + display: flex; + justify-content: space-between; + padding: 0 40px; + } + .loginContL { + font-size: 40px; + font-weight: bold; + margin-bottom: 80px; + } + } +.login-container { + width: 100%; + height: 100%; + position: relative; + z-index: 999; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + background: url('../../assets/loginPage/login-bg.jpg') no-repeat center; + /*background-image: radial-gradient(at center, #0075c3, #000b61);*/ + + canvas { + display: block; + vertical-align: bottom; + } + + #particles-js { + width: 100%; + height: 100%; + background-size: cover; + background-position: 50% 50%; + background-repeat: no-repeat; + position: absolute; + top: 0; + left: 0; + } + .rights { + font-size: 1.2rem; + color: #fff; + position: absolute; + bottom: 30px; + text-align: center; + + span{ + font-size: 1rem; + color: #eee; + } + } + .loginContent { + width: 100%; + flex-wrap: wrap; + align-items: center; + margin-bottom: 60px; + + .loginContL { + width: 100%; + + .apTitleT { + color: #fff; + margin-bottom: 20px; + letter-spacing: 4px; + } + .apTitleB { + color: #01d0ff; + margin-bottom: 36px; + letter-spacing: 4px; + } + & > span { + display: block; + width: 120px; + height: 8px; + background: #01d0ff; + } + } + .loginPanel { + width: 65%; + padding: 85px 70px; + background: #fff; + min-width: 450px; + border-radius: 15px; + box-shadow: 0 8px 40px rgba(0, 0, 0, 0.15); + + .welc { + font-size: 36px; + font-family: 'PingFang SC'; + font-weight: normal; + color: #999999; + letter-spacing: 2px; + margin-bottom: 15px; + } + .welcc { + font-size: 32px; + font-family: 'PingFang SC'; + font-weight: lighter; + color: #333; + letter-spacing: 2px; + } + } + } +} +</style> diff --git a/src/views/newHome/index.vue b/src/views/newHome/index.vue new file mode 100644 index 0000000..8450675 --- /dev/null +++ b/src/views/newHome/index.vue @@ -0,0 +1,967 @@ +<template> + <div class="login-container" :key="once"> + <div class="topPanel"></div> + <div class="topPanelBg"></div> + <div class="topPanelCont"> + <div class="topLogo"> + <img src="../../assets/newMenu/toplogo.png" /> + </div> + <div class="userInfo"> + <div @click="onScreenfullClick" style="margin-right: 15px; cursor: pointer"> + <i class="iconfont" :title="isScreenfull ? $t('message.user.title6') : $t('message.user.title5')" :class="!isScreenfull ? 'icon-fullscreen' : 'icon-tuichuquanping'"></i> + </div> + <div class="loginOut" @click="onLoginOut">退出登录</div> + <span></span> + <div class="avator"> + <img src="../../assets/menu/admin.png" /> + <div>{{userName}}</div> + </div> + </div> + </div> + <div class="leftCont"></div> + <div class="topCont"> + <div class="topInfo"> + <div class="topTit">新疆国泰新华<br />安全风险预警监测系统(试运行)</div> + <div class="topTime"> + <div class="time"> + {{ time }} + </div> + <span></span> + <div class="today"> + <div>{{ date }}</div> + <div> + <span>{{ weekDay }}</span + ><span>{{ dayTime }}</span> + </div> + </div> + </div> + </div> + <div class="line"></div> + </div> + <div class="menuGrid"> + <div class="gridCont"> + <div class="grid-content grid-content-1 cont-bg-1" v-throttle @click="toRiskPlatform"> + <div class="toplayer"> + <div> + <img class="iconImg" src="../../assets/newMenu/icon1.png" /> + <div> + <div class="itemTit1">智能安全风险综合预警<br />预报平台</div> + <div class="enTit1">Intelligent Security Risk Comprehensive Forewarning and Forecasting Platform</div> + </div> + </div> + </div> + <img class="bgImg1" src="../../assets/newMenu/card-1.png" /> + </div> + <div class="grid-content cont-bg-1" v-throttle @click="toDoublePrevent"> + <div class="toplayer"> + <img class="iconImg" src="../../assets/newMenu/icon2.png" /> + <div> + <div class="itemTit">智能安全双重预防系统</div> + <div class="enTit">Intelligent Security Dual Prevention System</div> + </div> + </div> + <img class="bgImg" src="../../assets/newMenu/card-4.png" /> + </div> + <div class="grid-content cont-bg-1" v-throttle @click="render('4')"> + <div class="toplayer"> + <img class="iconImg" src="../../assets/newMenu/icon3.png" /> + <div> + <div class="itemTit">智能安全巡检系统</div> + <div class="enTit">Intelligent Security Patrol System</div> + </div> + </div> + <img class="bgImg" src="../../assets/newMenu/card-8.png" /> + </div> + <div class="grid-content cont-bg-1" v-throttle @click="render('3')"> + <div class="toplayer"> + <img class="iconImg" src="../../assets/newMenu/icon4.png" /> + <div> + <div class="itemTit">智能安全特殊作业系统</div> + <div class="enTit">Intelligent Security Special Operating System</div> + </div> + </div> + <img class="bgImg" src="../../assets/newMenu/card-7.png" /> + </div> + <div class="grid-content cont-bg-1" v-throttle @click="render('7')"> + <div class="toplayer"> + <img class="iconImg" src="../../assets/newMenu/icon5.png" /> + <div> + <div class="itemTit">安全目标责任管理系统</div> + <div class="enTit">Security Target Responsibility Management System</div> + </div> + </div> + <img class="bgImg" src="../../assets/newMenu/card-2.png" /> + </div> + <div class="grid-content cont-bg-2" v-throttle @click="render('10')"> + <div class="toplayer"> + <img class="iconImg" src="../../assets/newMenu/icon6.png" /> + <div> + <div class="itemTit">安全知识图谱系统</div> + <div class="enTit">Security Knowledge Graph System</div> + </div> + </div> + <img class="bgImg" src="../../assets/newMenu/card-3.png" /> + </div> + <div class="grid-content cont-bg-2" v-throttle @click="render('9')"> + <div class="toplayer"> + <img class="iconImg" src="../../assets/newMenu/icon7.png" /> + <div> + <div class="itemTit">设备综合管控系统</div> + <div class="enTit">Equipment Integrated Management and Control System</div> + </div> + </div> + <img class="bgImg" src="../../assets/newMenu/card-9.png" /> + </div> + <div class="grid-content cont-bg-2" v-throttle @click="render('6')"> + <div class="toplayer"> + <img class="iconImg" src="../../assets/newMenu/icon8.png" /> + <div> + <div class="itemTit">应急管理系统</div> + <div class="enTit">Emergency Management System</div> + </div> + </div> + <img class="bgImg" src="../../assets/newMenu/card-5.png" /> + </div> + <div class="grid-content cont-bg-2" v-throttle @click="renderToNew('11')"> + <div class="toplayer"> + <img class="iconImg" src="../../assets/newMenu/icon9.png" /> + <div> + <div class="itemTit">智能安全危险化学品全生命周期管控系统</div> + <div class="enTit">Intelligent Security Hazardous Chemicals Life Cycle Safety Management System </div> + </div> + </div> + <img class="bgImg" src="../../assets/newMenu/card-10.png" /> + </div> + <div class="grid-content cont-bg-2" v-throttle @click="render('8')"> + <div class="toplayer"> + <img class="iconImg" src="../../assets/newMenu/icon10.png" /> + <div> + <div class="itemTit">安全事故管理系统</div> + <div class="enTit">Security Incident Management System</div> + </div> + </div> + <img class="bgImg" src="../../assets/newMenu/card-6.png" /> + </div> + <div class="grid-content cont-bg-2" @click="render('1')"> + <div class="toplayer"> + <img class="iconImg" src="../../assets/newMenu/icon11.png" /> + <div> + <div class="itemTit">安全基础信息系统</div> + <div class="enTit">Basic Security Information System</div> + </div> + </div> + <img class="bgImg" src="../../assets/newMenu/card-11.png" /> + </div> + </div> + </div> + <div class="bot-rights"> + <img src="../../assets/newMenu/pic_line1.png" /> + <div>技术支持:苏州国科鸿宇智能科技有限公司</div> + <img src="../../assets/newMenu/pic_line2.png" /> + </div> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, computed, defineComponent, onMounted } from 'vue'; +import { storeToRefs } from 'pinia'; +import { useThemeConfig } from '/@/stores/themeConfig'; +import logoMini from '/@/assets/logo-mini.svg'; +import loginIconTwo from '/@/assets/login-icon-two.svg'; +import { NextLoading } from '/@/utils/loading'; +import { Session } from '/@/utils/storage'; +import { useRoute, useRouter } from 'vue-router'; +import { initBackEndControlRoutes } from '/@/router/backEnd'; +import { useUserInfo } from '/@/stores/userInfo'; +import { useRoutesList } from '/@/stores/routesList'; +import pinia from '/@/stores'; +import { useTagsViewRoutes } from '/@/stores/tagsViewRoutes'; +import { ElMessage } from 'element-plus'; +import { ElMessageBox } from 'element-plus/es'; +import { useLoginApi } from '/@/api/login'; +import { useI18n } from 'vue-i18n'; +import screenfull from 'screenfull'; +import router from '../../router'; +import Cookies from 'js-cookie'; + +// 定义接口来定义对象的类型 +interface LoginState { + tabsActiveName: string; + isScan: boolean; + count: number; + projectId: string; + once: number; + isScreenfull: boolean; + time: string; + date: string; + weekDay: string; + dayTime: string; +} + +export default defineComponent({ + name: 'loginIndex', + components: {}, + setup() { + const { t } = useI18n(); + const router = useRouter(); + const userInfo = useUserInfo(); + const { userInfos } = storeToRefs(userInfo); + const routeToStore = useRoutesList(pinia); + const { routesList } = storeToRefs(routeToStore); + const storesThemeConfig = useThemeConfig(); + const { themeConfig } = storeToRefs(storesThemeConfig); + // 时间格式化 + const timeForm = { + hour12: false, + year: 'numeric', + month: '2-digit', + day: '2-digit', + hour: '2-digit', + minute: '2-digit', + second: '2-digit' + }; + const state = reactive<LoginState>({ + tabsActiveName: 'account', + isScan: false, + count: 0, + projectId: '1', + once: 0, + time: '', + date: '', + weekDay: '', + dayTime: '', + isScreenfull: false + }); + + const userName = computed(() =>{ + return userInfos.value.userName + }) + // 获取布局配置信息 + const getThemeConfig = computed(() => { + return themeConfig.value; + }); + + // 当前时间 + const getDateTime = () => { + const curTime = new Date().toLocaleString('zh', timeForm).replace(/\//g, '-'); + state.time = curTime.slice(10, 16); + state.date = curTime.slice(0, 10); + let week = ['日', '一', '二', '三', '四', '五', '六']; + let day = new Date().getDay(); + state.weekDay = '星期' + week[day]; + let curHour = Number(curTime.slice(10, 13)); + if (curHour >= 5 && curHour <= 10) { + state.dayTime = '上午'; + } + if (curHour > 10 && curHour <= 12) { + state.dayTime = '中午'; + } + if (curHour > 12 && curHour <= 18) { + state.dayTime = '下午'; + } + if (curHour > 18 && curHour <= 22) { + state.dayTime = '晚上'; + } + if (curHour > 22) { + state.dayTime = '午夜'; + } + }; + // 下拉菜单点击时 + const onLoginOut = () => { + ElMessageBox({ + closeOnClickModal: false, + closeOnPressEscape: false, + title: t('message.user.logOutTitle'), + message: t('message.user.logOutMessage'), + showCancelButton: true, + confirmButtonText: t('message.user.logOutConfirm'), + cancelButtonText: t('message.user.logOutCancel'), + buttonSize: 'default', + beforeClose: (action, instance, done) => { + if (action === 'confirm') { + instance.confirmButtonLoading = true; + instance.confirmButtonText = t('message.user.logOutExit'); + setTimeout(() => { + done(); + setTimeout(() => { + instance.confirmButtonLoading = false; + }, 300); + }, 700); + } else { + done(); + } + } + }) + .then(async () => { + let res = await useLoginApi().signOut(); + if (res.data.code === '200') { + Session.clear(); // 清除缓存/token等 + // 使用 reload 时,不需要调用 resetRoute() 重置路由 + window.location.reload(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }) + .catch(() => {}); + }; + //选择菜单 + const render = (value: string) => { + state.projectId = value; + renderMenu(); + }; + + // 全屏点击时 + const onScreenfullClick = () => { + if (!screenfull.isEnabled) { + ElMessage.warning('暂不不支持全屏'); + return false; + } + screenfull.toggle(); + screenfull.on('change', () => { + if (screenfull.isFullscreen) state.isScreenfull = true; + else state.isScreenfull = false; + }); + }; + // 去风险大屏 + const toRiskPlatform = () => { + // router.push({ + // name: "warningScreen" + // }); + window.open('http://39.104.85.193:8585/'); + }; + + const toDoublePrevent = () => { + window.open('http://121.239.169.27:6801'); + }; + const throttle = (renderMenu: any, delay: number) => { + let flag = true; + let count = 0; + return function () { + if (!flag) return; + flag = false; + if (count === 0) { + renderMenu.apply(); + count++; + flag = true; + } else { + setTimeout(() => { + renderMenu.apply(); + flag = true; + }, delay); + } + }; + }; + + //调用菜单方法 + const renderMenu = throttle(() => { + renderFun(); + }, 2000); + + //调后台菜单接口 + const renderFun = async () => { + Cookies.set('projectId', state.projectId); + userInfos.value.projectId = state.projectId; + await initBackEndControlRoutes().then(() => { + let linkToMenu = [...routesList.value]; + if (linkToMenu && linkToMenu.length > 1) { + router.push(linkToFirstMenu(JSON.parse(JSON.stringify(linkToMenu))[1])); + } else { + ElMessage({ type: 'warning', message: '你没有该子系统的权限' }); + } + }); + }; + + const linkToFirstMenu: any = (value: any) => { + let returnMenu = value; + if (returnMenu.children?.length > 0) { + return linkToFirstMenu(returnMenu.children[0]); + } else { + return returnMenu.path; + } + }; + + const renderToNew = () => { + window.open('http://222.92.213.22:18001/smartlab/', '_blank'); + }; + // //点击进入特殊作业 + // const toSpecialWorkSys = () => { + // router.push('/layoutPage'); + // }; + // 页面加载时 + onMounted(() => { + state.once += 1; + NextLoading.done(); + getDateTime(); + setInterval(() => { + getDateTime(); + }, 1000); + // loginBg(); + // loginApp() + }); + return { + render, + userName, + logoMini, + onLoginOut, + getDateTime, + renderToNew, + toRiskPlatform, + toDoublePrevent, + onScreenfullClick, + loginIconTwo, + getThemeConfig, + ...toRefs(state) + }; + } +}); +</script> + +<style scoped lang="scss"> + @keyframes showDown { + 100% { + position: absolute; + top: 60px; + } + } + @keyframes moveDown { + 100% { + position: absolute; + top: 0; + } + } + @keyframes moveRight { + 100% { + position: absolute; + left: 0; + } + } + @keyframes upDown { + 50% { + -webkit-transform: translateY(-8px); + -ms-transform: translateY(-8px); + -o-transform: translateY(-8px); + transform: translateY(-8px); + } + 100% { + -webkit-transform: translateY(0); + -ms-transform: translateY(0); + -o-transform: translateY(0); + transform: translateY(0); + } + } +@media screen and (min-width: 1600px) { + .gridCont { + width: 100%; + height: 100%; + display: grid; + grid-gap: 20px; + grid-template-columns: repeat(3, 1fr); + grid-auto-flow: row; + justify-content: center; + .toplayer { + width: 100%; + height: 100%; + position: absolute; + left: 0; + top: 0; + display: flex; + align-items: center; + padding: 0 20px; + z-index: 99; + + .itemTit { + font-size: 28px; + line-height: 34px; + margin-bottom: 2px; + height: 40%; + color: #072270; + } + .enTit { + font-size: 16px; + line-height: 20px; + color: #072270; + } + + .iconImg { + width: 88px; + height: 88px; + margin-right: 20px; + } + } + .bgImg { + position: absolute; + width: 30%; + height: auto; + right: -10px; + top: 15px; + } + } + + .grid-content-1 { + grid-row-start: 1; + grid-row-end: 3; + + .toplayer { + width: 100%; + height: 100%; + position: absolute; + left: 0; + top: 0; + display: flex; + align-items: center; + z-index: 99; + + & > div { + display: flex; + align-items: flex-start; + } + + .itemTit1 { + font-size: 32px; + line-height: 42px; + height: 40%; + letter-spacing: 1px; + color: #072270; + margin-bottom: 12px; + } + .enTit1 { + font-size: 18px; + line-height: 24px; + color: #072270; + } + } + .bgImg1 { + position: absolute; + width: 45%; + height: auto; + right: -20px; + top: 30%; + } + } + + .bot-rights { + font-size: 18px; + color: #333; + } +} + +@media screen and (min-width: 1200px) and (max-width: 1600px) { + .gridCont { + width: 100%; + height: 100%; + display: grid; + grid-gap: 15px; + grid-template-columns: repeat(3, 1fr); + grid-auto-flow: row; + justify-content: center; + + .toplayer { + width: 100%; + height: 100%; + position: absolute; + left: 0; + top: 0; + display: flex; + align-items: center; + padding: 0 20px; + z-index: 99; + + .itemTit { + font-size: 22px; + line-height: 30px; + height: 40%; + color: #072270; + margin-bottom: 2px; + } + .enTit { + font-size: 12px; + color: #072270; + } + + .iconImg { + width: 44px; + height: 44px; + margin-right: 10px; + } + } + .bgImg { + position: absolute; + width: 30%; + height: auto; + right: -10px; + top: 15px; + } + } + + .grid-content-1 { + grid-row-start: 1; + grid-row-end: 3; + + .toplayer { + width: 100%; + height: 100%; + position: absolute; + left: 0; + top: 0; + display: flex; + align-items: center; + z-index: 99; + + & > div { + display: flex; + align-items: flex-start; + } + + .itemTit1 { + font-size: 24px; + line-height: 36px; + height: 40%; + letter-spacing: 1px; + color: #072270; + margin-bottom: 12px; + } + .enTit1 { + font-size: 14px; + color: #072270; + } + } + .bgImg1 { + position: absolute; + width: 45%; + height: auto; + right: -20px; + top: 30%; + } + } + .bot-rights { + font-size: 15px; + color: #333; + } +} +@media screen and (max-width: 1200px) { + .gridCont { + width: 100%; + height: 100%; + display: grid; + grid-gap: 10px; + grid-template-columns: repeat(3, 1fr); + grid-auto-flow: row; + justify-content: center; + + .toplayer { + width: 100%; + height: 100%; + position: absolute; + left: 0; + top: 0; + display: flex; + align-items: center; + padding: 0 15px; + z-index: 99; + + .itemTit { + font-size: 14px; + line-height: 22px; + color: #072270; + } + .enTit { + font-size: 10px; + line-height: 14px; + color: #072270; + } + + .iconImg { + width: 32px; + height: 32px; + margin-right: 10px; + } + } + .bgImg { + position: absolute; + width: 45%; + height: auto; + right: -10px; + top: 15px; + } + } + + .grid-content-1 { + grid-row-start: 1; + grid-row-end: 3; + + .toplayer { + width: 100%; + height: 100%; + position: absolute; + left: 0; + top: 0; + display: flex; + align-items: center; + z-index: 99; + + & > div { + display: flex; + align-items: flex-start; + } + + .itemTit1 { + font-size: 16px; + line-height: 36px; + height: 40%; + letter-spacing: 1px; + color: #072270; + margin-bottom: 12px; + } + .enTit1 { + font-size: 12px; + color: #072270; + } + } + .bgImg1 { + position: absolute; + width: 45%; + height: auto; + right: -20px; + top: 30%; + } + } + .bot-rights { + font-size: 12px; + color: #333; + } +} +.login-container { + width: 100%; + height: 100%; + position: relative; + background: #fff; + .topPanel { + width: 100%; + height: 260px; + background: url('../../assets/newMenu/topbg.jpg') no-repeat center; + background-size: 100% 100%; + display: flex; + justify-content: center; + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1); + } + .topPanelBg { + position: absolute; + width: 100%; + height: 60px; + top: -60px; + left: 0; + background: rgba(255, 255, 255, 0.8); + z-index: 9; + animation: moveDown 0.6s 1 ease forwards; + } + .topPanelCont { + position: absolute; + width: 100%; + height: 60px; + padding: 0 50px; + top: -60px; + left: 0; + display: flex; + align-items: center; + justify-content: space-between; + z-index: 999; + animation: moveDown 0.6s 1 ease forwards; + + .topLogo { + display: flex; + align-items: center; + + img { + width: 146px; + height: auto; + } + } + + .userInfo { + display: flex; + align-items: center; + + .avator { + display: flex; + justify-content: right; + + img { + width: 20px; + height: 20px; + border-radius: 10px; + } + div { + font-size: 15px; + color: #333333; + line-height: 20px; + margin-left: 6px; + } + } + span { + width: 1px; + height: 20px; + background: #999; + margin: 0 15px; + } + .loginOut { + font-size: 15px; + color: #333; + line-height: 20px; + cursor: pointer; + + &:hover { + color: #006df5; + } + } + } + } + .leftCont { + position: absolute; + left: -100px; + top: 0; + width: 220px; + height: 100%; + z-index: 99; + background: url('../../assets/newMenu/leftbg.png') no-repeat center; + background-size: 100% 100%; + animation: moveRight .8s 1 ease forwards; + } + .topCont { + position: absolute; + width: 100%; + height: 200px; + left: 0; + top: 30px; + padding: 0 40px 0 120px; + z-index: 99999; + display: flex; + flex-direction: column; + justify-content: center; + align-items: flex-start; + animation: showDown 0.6s 1 ease forwards; + + .topInfo { + width: 100%; + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 10px; + + .topTit { + font-size: 44px; + font-weight: bolder; + text-align: left; + color: #fff; + text-shadow: 0 3px 8px rgba(0, 0, 0, 0.2); + } + + .topTime { + padding: 15px 10px; + box-sizing: border-box; + background: rgba(6, 64, 195, 0.8); + border-radius: 8px; + color: #fff; + font-family: 'PingFang SC'; + font-weight: 600; + font-size: 16px; + display: flex; + align-items: center; + + .time { + font-size: 48px; + } + & > span { + width: 1px; + height: 40px; + margin: 0 15px; + background: #fff; + } + .today { + display: flex; + flex-direction: column; + align-items: flex-start; + + span { + font-size: 14px; + } + + span:first-of-type { + margin-right: 10px; + } + } + } + } + .line { + width: 120px; + height: 6px; + background: #00eeff; + } + } + .menuGrid { + width: calc(100vw - 220px); + height: calc(100vh - 320px); + padding: 20px 20px 0; + position: absolute; + top: 260px; + left: 220px; + .gridCont { + .grid-content { + border-radius: 16px; + position: relative; + overflow: hidden; + cursor: pointer; + transition: 0.3s; + border: 2px solid rgba(255,255,255,0); + + &:hover { + border-radius: 16px; + background-image: radial-gradient(ellipse farthest-side at 50% 100%, #48a3ff 0%, #fff 120%); + box-shadow: -8px -8px 24px rgba(20, 97, 234, 0.2), 8px 8px 24px rgba(20, 97, 234, 0.2); + border: 2px solid #fff; + + .iconImg{ + animation: upDown 0.3s 1 ease-in-out forwards; + filter: drop-shadow(0 0 12px rgba(20, 97, 234, 0.4)); + } + } + } + .cont-bg-1 { + background: #d9eaff; + } + .cont-bg-2 { + background: #cdd6ff; + } + + /*.grid-content-2{*/ + /* background-image: linear-gradient(135deg,#0098F5,#1461EA);*/ + /*}*/ + + /*.grid-content-3{*/ + /* background-image: linear-gradient(135deg,#006DF5,#1450EA);*/ + /*}*/ + } + } + .bot-rights { + width: calc(100vw - 240px); + height: 60px; + position: absolute; + bottom: 0; + left: 240px; + z-index: 9999; + display: flex; + align-items: center; + justify-content: center; + + img { + width: 248px; + height: 8px; + } + div { + margin: 0 20px; + } + } +} +</style> diff --git a/src/views/riskWarningSys/warningBigScreen/components/SPI.vue b/src/views/riskWarningSys/warningBigScreen/components/SPI.vue new file mode 100644 index 0000000..a52fdca --- /dev/null +++ b/src/views/riskWarningSys/warningBigScreen/components/SPI.vue @@ -0,0 +1,441 @@ +<template> + <div class="charts-cont"> + <div :class="spiChart"> + <el-cascader + class="spiSe" + :teleported="false" + v-model="spiValue" + :options="departList" + :props="spiProps" + :show-all-levels="false" + @change="handleChange" + /> + </div> + + <div class="spi" :id="spi"> + + </div> + </div> +</template> + +<script lang="ts"> + import {toRefs, reactive, defineComponent, ref, defineAsyncComponent, onMounted, watchEffect} from 'vue'; + import { storeToRefs } from 'pinia'; + import { initBackEndControlRoutes } from '/@/router/backEnd'; + import {useUserInfo} from "/@/stores/userInfo"; + import { Session } from '/@/utils/storage'; + import { Search } from '@element-plus/icons-vue' + import { ElMessage } from 'element-plus' + import type { FormInstance, FormRules } from 'element-plus' + import { workApplyApi } from '/@/api/specialWorkSystem/workApply'; + import * as echarts from 'echarts'; + import '/@/theme/bigScreen.css' + import {useScreenTheme} from "/@/stores/screenTheme"; + import {teamManageApi} from "/@/api/systemManage/basicDateManage/personShiftManage/teamManage"; + + interface stateType { + spiValue: number; + departList: Array<any>; + spiChart: string; + spiProps: object + } + export default defineComponent({ + name: 'SPI', + components: {}, + props:{ + size: Number, + theme: Boolean + }, + setup(props) { + const userInfo = useUserInfo() + const { userInfos } = storeToRefs(userInfo); + const screenThemes = useScreenTheme() + const { screenTheme } = storeToRefs(screenThemes); + const spi = ref("eChartSpi" + Date.now() + Math.random()) + const state = reactive<stateType>({ + spiValue: 1, + departList: [], + spiProps: { + expandTrigger: 'hover', + checkStrictly: true, + value: 'depId', + label: 'depName', + }, + spiChart: 'spi-dark' + }) + + // 获取部门列表 + const getAllDepartment = async () => { + let res = await teamManageApi().getAllDepartment(); + if (res.data.code === '200') { + state.departList = JSON.parse(JSON.stringify(res.data.data)) + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + type EChartsOption = echarts.EChartsOption + // 隐患整改情况 + const initSpi =()=>{ + let dom = document.getElementById(spi.value); + let myChart = echarts.init(dom); + + let option: EChartsOption; + + option = { + legend: { + data: ['注意线', '警告线', '危险线', 'SPI预警指数值'], + top: '2%', + right: '6%', + textStyle:{ + color: '#999', + fontSize: fontSize(14) + } + }, + color: ['rgba(216,55,55)','rgba(235,194,80)','rgba(147,208,81)'], + tooltip: { + trigger: 'axis' + }, + grid: { + left: '8%', + right: '8%', + bottom: '5%', + }, + xAxis: [ + { + type: 'category', + boundaryGap: false, + data: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'], + axisLine:{ + show: true, + lineStyle:{ + color: '#999' + } + }, + splitLine:{ + show: true, + lineStyle:{ + type: 'dashed', + color: '#999' + } + }, + axisLabel:{ + color: '#999', + } + } + ], + yAxis: [ + { + type: 'value', + axisLine:{ + show: true, + lineStyle:{ + type: 'dotted' + } + }, + axisLabel:{ + color: '#ccc' + }, + splitLine:{ + show: true, + lineStyle:{ + type: 'dashed', + color: 'rgba(255,255,255,.4)' + } + } + } + ], + series: [ + { + name: '危险线', + data: [1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000], + type: 'line', + lineStyle:{ + width: 0 + }, + areaStyle: { + color: { + x: 0, + y: 0, + x2: 0, + y2: 1, + colorStops: [ + { + offset: 0.1, + color: "rgba(216,55,55)", // 线处的颜色 + }, + { + offset: 0.9, + color: "rgba(216,55,55,.1)", // 坐标轴处的颜色 + }, + ], + } + }, + showSymbol: false, + // stack: 'Total', + smooth: true + }, + { + name: '警告线', + data: [750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750], + type: 'line', + lineStyle:{ + width: 0 + }, + areaStyle: { + color: { + x: 0, + y: 0, + x2: 0, + y2: 1, + colorStops: [ + { + offset: 0.1, + color: "rgba(235,194,80)", // 线处的颜色 + }, + { + offset: 0.9, + color: "rgba(235,194,80,.1)", // 坐标轴处的颜色 + }, + ], + } + }, + showSymbol: false, + // stack: 'Total', + smooth: true + }, + { + name: '注意线', + data: [500, 500, 500, 500, 500, 500, 500,500, 500, 500, 500, 500], + type: 'line', + lineStyle:{ + width: 0 + }, + areaStyle: { + color: { + x: 0, + y: 0, + x2: 0, + y2: 1, + colorStops: [ + { + offset: 0.1, + color: "rgba(147,208,81)", // 线处的颜色 + }, + { + offset: 0.9, + color: "rgba(147,208,81,.2)", // 坐标轴处的颜色 + }, + ] + }, + }, + showSymbol: false, + // stack: 'Total', + smooth: true + }, + { + name: 'SPI预警指数值', + data: [450, 632, 501, 434, 390, 530, 520,750, 632, 401, 634, 590], + type: 'line', + triggerLineEvent: true, + label:{ + show: true, + color: '#23E5E5', + fontSize: fontSize(12) + }, + lineStyle:{ + width: 2, + color: '#23E5E5' + }, + itemStyle:{ + color: '#23E5E5', + borderColor: '#fff', + borderWidth: 4 + }, + smooth: true + } + ] + }; + + option && myChart.setOption(option); + window.addEventListener("resize",function (){ + myChart.resize(); + }); + } + + const getTheme =()=>{ + if(screenTheme.value.isDark){ + state.spiChart = 'spi-dark' + }else{ + state.spiChart = 'spi-light' + } + } + + watchEffect(() => { + if(props.theme){ + state.spiChart = 'spi-dark' + }else{ + state.spiChart = 'spi-light' + } + }) + + function fontSize(val){ + let nowClientWidth = document.documentElement.clientWidth; + return val * (nowClientWidth/1920) * Number(props.size); + } + + // 页面载入时执行方法 + onMounted(() => { + getAllDepartment(); + initSpi(); + getTheme(); + }); + + return { + spi, + Search, + fontSize, + ...toRefs(state) + }; + }, + }); +</script> + +<style scoped lang="scss"> + .charts-cont{ + width: 100%; + height: 100%; + padding: 2%; + position: relative; + + .spi-dark{ + position: absolute; + width: 25% !important; + top: 0; + left: 2rem; + z-index: 99999; + + ::v-deep(.el-cascader){ + width: 100% !important; + } + ::v-deep(.el-popper){ + background-color: rgba(10,31,92,1); + border: 1px solid rgba(17,254,238,.4); + color: #11FEEE; + .el-cascader-node__label{ + color: #11FEEE; + } + .el-icon{ + color: #11FEEE; + } + .el-cascader-node{ + &:hover{ + background: #0049af; + } + } + } + ::v-deep(.el-popper__arrow){ + &::before{ + background-color: rgba(10,31,92,.6) !important; + border: 1px solid rgba(17,254,238,.4); + } + } + ::v-deep(.el-input__wrapper){ + width: 20%; + box-shadow: none; + border: 1px solid rgba(17,254,238,.2); + background: rgba(10,31,92,.6) !important; + height: 2.5rem; + color: #11FEEE; + + input{ + font-size: 1.25rem; + color: #11FEEE; + } + .el-icon{ + color: #11FEEE; + } + } + } + + .spi-light{ + position: absolute; + width: 25% !important; + top: 0; + left: 2rem; + z-index: 99999; + + ::v-deep(.el-cascader){ + width: 100% !important; + } + ::v-deep(.el-popper){ + background-color: #fff; + border: 1px solid #ccc; + color: #000; + .el-cascader-node__label{ + color: #000; + } + .el-icon{ + color: #000; + } + .el-cascader-node{ + &:hover{ + background: #ccc; + } + } + } + ::v-deep(.el-popper__arrow){ + &::before{ + background-color: #fff !important; + border: 1px solid #ccc; + } + } + ::v-deep(.el-input__wrapper){ + width: 20%; + box-shadow: none; + border: 1px solid #ccc; + background: #fff !important; + height: 2.5rem; + color: #000; + + input{ + font-size: 1.25rem; + color: #000; + } + .el-icon{ + color: #000; + } + } + } + .spi{ + width: 100%; + height: 100%; + } + } + .home-container { + height: 100%; + overflow: hidden; + position: relative; + .el-row{ + margin-bottom: 20px; + } + .el-row:last-child { + margin-bottom: 0; + } + .el-input{ + width: 100% !important; + } + .el-date-editor::v-deep{ + width: 100%; + } + .el-select{ + width: 100%; + } + .el-cascader{ + width: 100% !important; + } + } +</style> diff --git a/src/views/riskWarningSys/warningBigScreen/components/accident.vue b/src/views/riskWarningSys/warningBigScreen/components/accident.vue new file mode 100644 index 0000000..2f15dfe --- /dev/null +++ b/src/views/riskWarningSys/warningBigScreen/components/accident.vue @@ -0,0 +1,328 @@ +<template> + <div class="charts-cont"> + <div :class="choose" > + <div :class="cur===1?'act':''" @click="changeTab(1)">月度</div> + <div :class="cur===2?'act':''" @click="changeTab(2)">年度</div> + </div> + <div v-show="cur===1" class="month" :id="accidentMonth"></div> + <div v-show="cur===2" class="month" :id="accidentYear"></div> + </div> +</template> + +<script lang="ts"> + import {toRefs, reactive, defineComponent, ref, defineAsyncComponent, onMounted, nextTick, onUnmounted, watchEffect} from 'vue'; + import { storeToRefs } from 'pinia'; + import { initBackEndControlRoutes } from '/@/router/backEnd'; + import {useUserInfo} from "/@/stores/userInfo"; + import { Session } from '/@/utils/storage'; + import { Search } from '@element-plus/icons-vue' + import { ElMessage } from 'element-plus' + import type { FormInstance, FormRules } from 'element-plus' + import { workApplyApi } from '/@/api/specialWorkSystem/workApply'; + import * as echarts from "echarts"; + import '/@/theme/bigScreen.css' + import {useScreenTheme} from "/@/stores/screenTheme" + + interface stateType { + cur: number, + curColor: string, + choose: string + } + export default defineComponent({ + name: 'accident', + components: {}, + props:{ + size: Number, + theme: Boolean + }, + setup(props) { + const userInfo = useUserInfo() + const { userInfos } = storeToRefs(userInfo); + const screenThemes = useScreenTheme() + const { screenTheme } = storeToRefs(screenThemes); + const accidentMonth = ref("eChartFix" + Date.now() + Math.random()) + const accidentYear = ref("eChartFix" + Date.now() + Math.random()) + const state = reactive<stateType>({ + cur: 1, + curColor: '#fff', + choose: 'choose-dark' + }) + + const changeTab =(i)=>{ + state.cur = i + nextTick(()=>{ + initAccidentByYear(); + }) + } + type EChartsOption = echarts.EChartsOption + // 隐患整改情况 + const initAccidentByMonth =()=>{ + let dom = document.getElementById(accidentMonth.value); + let myChart = echarts.init(dom); + + let option: EChartsOption; + + option = { + tooltip: { + trigger: 'item' + }, + legend: { + top: '0', + left: 'center', + itemWidth: fontSize(10), + itemHeight: fontSize(8), + textStyle:{ + color: 'auto', + fontSize: fontSize(11) + } + }, + series: [ + { + name: '月度数据', + type: 'pie', + radius: ['50%', '80%'], + avoidLabelOverlap: false, + itemStyle: { + borderRadius: fontSize(2) + }, + label: { + show: false, + position: 'outer', + fontSize: fontSize(10), + textBorderWidth: 0, + width: fontSize(40), + overflow: 'break' + }, + // labelLine: { + // show: true, + // length: fontSize(10), + // length2: fontSize(10) + // }, + emphasis: { + label: { + show: true, + fontSize: fontSize(22), + fontWeight: 'bold' + } + }, + data: [ + { value: 1, name: '特别重大事故' }, + { value: 10, name: '重大事故' }, + { value: 20, name: '较大事故' }, + { value: 33, name: '一般事故' }, + { value: 50, name: '未遂事故' } + ], + center: ['50%','60%'] + } + ] + }; + + option && myChart.setOption(option); + + window.addEventListener("resize",function (){ + myChart.resize(); + }); + } + // 隐患整改情况 + const initAccidentByYear =()=>{ + let dom = document.getElementById(accidentYear.value); + let myChart = echarts.init(dom); + + let option: EChartsOption; + + option = { + tooltip: { + trigger: 'item' + }, + legend: { + top: '0', + left: 'center', + itemWidth: fontSize(10), + itemHeight: fontSize(8), + textStyle:{ + color: 'auto', + fontSize: fontSize(11) + } + }, + series: [ + { + name: '年度数据', + type: 'pie', + radius: ['50%', '80%'], + avoidLabelOverlap: false, + itemStyle: { + borderRadius: fontSize(2) + }, + label: { + show: false, + position: 'outer', + fontSize: fontSize(10), + textBorderWidth: 0, + width: fontSize(40), + overflow: 'break' + }, + // labelLine: { + // show: true, + // length: fontSize(10), + // length2: fontSize(10) + // }, + emphasis: { + label: { + show: true, + fontSize: fontSize(22), + fontWeight: 'bold' + } + }, + data: [ + { value: 10, name: '特别重大事故' }, + { value: 20, name: '重大事故' }, + { value: 100, name: '较大事故' }, + { value: 130, name: '一般事故' }, + { value: 150, name: '未遂事故' } + ], + center: ['50%','60%'] + } + ] + }; + + option && myChart.setOption(option); + + window.addEventListener("resize",function (){ + myChart.resize(); + }); + } + + function fontSize(val){ + let nowClientWidth = document.documentElement.clientWidth; + return val * (nowClientWidth/1920) * Number(props.size); + } + const getTheme =()=>{ + if(screenTheme.value.isDark){ + state.choose = 'choose-dark' + }else{ + state.choose = 'choose-light' + } + } + + watchEffect(() => { + if(props.theme){ + state.choose = 'choose-dark' + }else{ + state.choose = 'choose-light' + } + }) + + + // 页面载入时执行方法 + onMounted(() => { + initAccidentByMonth(); + getTheme() + // initAccidentByYear(); + }); + + onUnmounted(() =>{ + + }) + + return { + accidentMonth, + accidentYear, + Search, + changeTab, + fontSize, + ...toRefs(state) + }; + }, + }); +</script> + +<style scoped lang="scss"> + .charts-cont{ + width: 100%; + height: 100%; + padding: 5%; + position: relative; + + .choose-dark{ + position: absolute; + right: 4%; + bottom: 4%; + z-index: 999; + display: flex; + align-items: center; + font-size: 0.75rem; + justify-content: space-between; + + div{ + padding: 2px 6px; + box-sizing: border-box; + color: rgba(17,254,238,.4); + border: 1px solid rgba(17,254,238,.4); + border-radius: 2px; + cursor: pointer; + } + div:hover{ + color: #11FEEE; + border: 1px solid #11FEEE; + } + .act{ + color: #11FEEE; + border: 1px solid #11FEEE; + } + } + .choose-light{ + position: absolute; + right: 4%; + bottom: 4%; + z-index: 999; + display: flex; + align-items: center; + font-size: 0.75rem; + justify-content: space-between; + + div{ + padding: 2px 6px; + box-sizing: border-box; + color: #ccc; + border: 1px solid #ccc; + border-radius: 2px; + cursor: pointer; + } + div:hover{ + color: #333; + border: 1px solid #333; + } + .act{ + color: #333; + border: 1px solid #333; + } + } + .month{ + width: 100%; + height: 100%; + } + } + .home-container { + height: 100%; + overflow: hidden; + position: relative; + .el-row{ + margin-bottom: 20px; + } + .el-row:last-child { + margin-bottom: 0; + } + .el-input{ + width: 100% !important; + } + .el-date-editor::v-deep{ + width: 100%; + } + .el-select{ + width: 100%; + } + .el-cascader{ + width: 100% !important; + } + } +</style> diff --git a/src/views/riskWarningSys/warningBigScreen/components/danger.vue b/src/views/riskWarningSys/warningBigScreen/components/danger.vue new file mode 100644 index 0000000..ccf8a14 --- /dev/null +++ b/src/views/riskWarningSys/warningBigScreen/components/danger.vue @@ -0,0 +1,330 @@ +<template> + <div class="charts-cont"> +<!-- <el-select v-model="selected" class="choose" size="small">--> +<!-- <el-option label="月度" value="1"/>--> +<!-- <el-option label="年度" value="2"/>--> +<!-- </el-select>--> + <div :class="choose"> + <div :class="cur===1?'act':''" @click="changeTab(1)">企业</div> + <div :class="cur===2?'act':''" @click="changeTab(2)">部门</div> + </div> + <div v-show="cur===1" class="month" :id="dangerMonth"></div> + <div v-show="cur===2" class="year" :id="dangerYear"></div> + </div> +</template> + +<script lang="ts"> + import { + toRefs, + reactive, + defineComponent, + ref, + computed, + defineAsyncComponent, + onMounted, + nextTick, + watchEffect + } from 'vue'; + import { storeToRefs } from 'pinia'; + import { initBackEndControlRoutes } from '/@/router/backEnd'; + import {useUserInfo} from "/@/stores/userInfo"; + import { Session } from '/@/utils/storage'; + import { Search } from '@element-plus/icons-vue' + import { ElMessage } from 'element-plus' + import type { FormInstance, FormRules } from 'element-plus' + import { workApplyApi } from '/@/api/specialWorkSystem/workApply'; + import * as echarts from "echarts"; + import '/@/theme/bigScreen.css' + import {useScreenTheme} from "/@/stores/screenTheme"; + + + interface stateType { + cur: number, + choose: string + } + export default defineComponent({ + name: 'danger', + components: {}, + props:{ + size: Number, + theme: Boolean + }, + setup(props) { + const userInfo = useUserInfo() + const { userInfos } = storeToRefs(userInfo); + const screenThemes = useScreenTheme() + const { screenTheme } = storeToRefs(screenThemes); + const dangerMonth = ref("eChartFix" + Date.now() + Math.random()) + const dangerYear = ref("eChartFix" + Date.now() + Math.random()) + const state = reactive<stateType>({ + cur: 1, + choose: 'choose-dark' + }) + + const changeTab =(i)=>{ + state.cur = i + nextTick(()=>{ + initdangerByYear() + }) + } + type EChartsOption = echarts.EChartsOption + // 隐患整改情况 + const initdangerByMonth =()=>{ + let dom = document.getElementById(dangerMonth.value); + let myChart = echarts.init(dom); + + let option: EChartsOption; + + option = { + tooltip: { + trigger: 'item' + }, + color: ['#FAC858','#EE6666'], + legend: { + top: '8%', + left: 'center', + itemWidth: fontSize(10), + itemHeight: fontSize(8), + textStyle:{ + color: 'auto', + fontSize: fontSize(11) + } + }, + series: [ + { + type: 'pie', + radius: '65%', + avoidLabelOverlap: true, + label: { + show: true, + position: 'inside', + fontSize: fontSize(12), + color: '#ffffff', + textBorderWidth: 0, + width: 30, + overflow: 'break' + }, + labelLine: { + show: true, + length: 10, + length2: 10 + }, + emphasis: { + label: { + show: true, + fontSize: fontSize(22), + fontWeight: 'bold' + } + }, + data: [ + { value: 235, name: '一般隐患' }, + { value: 1048, name: '重大隐患' } + ], + center: ['50%','55%'] + } + ] + }; + + option && myChart.setOption(option); + + window.addEventListener("resize",function (){ + myChart.resize(); + }); + } + // 隐患整改情况 + const initdangerByYear =()=>{ + let dom = document.getElementById(dangerYear.value); + let myChart = echarts.init(dom); + + let option: EChartsOption; + + option = { + tooltip: { + trigger: 'item' + }, + color: ['#FAC858','#EE6666'], + legend: { + top: '8%', + left: 'center', + itemWidth: fontSize(10), + itemHeight: fontSize(8), + textStyle:{ + color: 'auto', + fontSize: fontSize(11) + } + }, + series: [ + { + name: 'Access From', + type: 'pie', + radius: '65%', + avoidLabelOverlap: true, + label: { + show: true, + position: 'inside', + fontSize: fontSize(12), + color: '#ffffff', + textBorderWidth: 0, + width: 30, + overflow: 'break' + }, + labelLine: { + show: true, + length: 10, + length2: 10 + }, + emphasis: { + label: { + show: true, + fontSize: fontSize(22), + fontWeight: 'bold' + } + }, + data: [ + { value: 35, name: '一般隐患' }, + { value: 1048, name: '重大隐患' } + ], + center: ['50%','55%'] + } + ] + }; + + option && myChart.setOption(option); + + window.addEventListener("resize",function (){ + myChart.resize(); + }); + } + function fontSize(val){ + let nowClientWidth = document.documentElement.clientWidth; + return val * (nowClientWidth/1920) * Number(props.size); + } + + const getTheme =()=>{ + if(screenTheme.value.isDark){ + state.choose = 'choose-dark' + }else{ + state.choose = 'choose-light' + } + } + + watchEffect(() => { + if(props.theme){ + state.choose = 'choose-dark' + }else{ + state.choose = 'choose-light' + } + }) + + // 页面载入时执行方法 + onMounted(() => { + initdangerByMonth(); + getTheme() + }); + + return { + dangerMonth, + dangerYear, + Search, + fontSize, + changeTab, + ...toRefs(state) + }; + }, + }); +</script> + +<style scoped lang="scss"> + .charts-cont{ + width: 100%; + height: 100%; + padding: 2% 2% 0; + position: relative; + + .choose-dark{ + position: absolute; + right: 4%; + bottom: 4%; + z-index: 999; + display: flex; + align-items: center; + font-size: 0.75rem; + justify-content: space-between; + + div{ + padding: 2px 6px; + box-sizing: border-box; + color: rgba(17,254,238,.4); + border: 1px solid rgba(17,254,238,.4); + border-radius: 2px; + cursor: pointer; + } + div:hover{ + color: #11FEEE; + border: 1px solid #11FEEE; + } + .act{ + color: #11FEEE; + border: 1px solid #11FEEE; + } + } + .choose-light{ + position: absolute; + right: 4%; + bottom: 4%; + z-index: 999; + display: flex; + align-items: center; + font-size: 0.75rem; + justify-content: space-between; + + div{ + padding: 2px 6px; + box-sizing: border-box; + color: #ccc; + border: 1px solid #ccc; + border-radius: 2px; + cursor: pointer; + } + div:hover{ + color: #333; + border: 1px solid #333; + } + .act{ + color: #333; + border: 1px solid #333; + } + } + .month{ + width: 100%; + height: 100%; + } + .year{ + width: 100%; + height: 100%; + } + } + .home-container { + height: 100%; + overflow: hidden; + position: relative; + .el-row{ + margin-bottom: 20px; + } + .el-row:last-child { + margin-bottom: 0; + } + .el-input{ + width: 100% !important; + } + .el-date-editor::v-deep{ + width: 100%; + } + .el-select{ + width: 100%; + } + .el-cascader{ + width: 100% !important; + } + } +</style> diff --git a/src/views/riskWarningSys/warningBigScreen/components/educate.vue b/src/views/riskWarningSys/warningBigScreen/components/educate.vue new file mode 100644 index 0000000..f327d7e --- /dev/null +++ b/src/views/riskWarningSys/warningBigScreen/components/educate.vue @@ -0,0 +1,180 @@ +<template> + <div class="charts-cont"> + <div class="educate" :id="educate"> + + </div> + </div> +</template> + +<script lang="ts"> + import {toRefs, reactive, defineComponent, ref, defineAsyncComponent, onMounted} from 'vue'; + import { storeToRefs } from 'pinia'; + import { initBackEndControlRoutes } from '/@/router/backEnd'; + import {useUserInfo} from "/@/stores/userInfo"; + import { Session } from '/@/utils/storage'; + import { Search } from '@element-plus/icons-vue' + import { ElMessage } from 'element-plus' + import type { FormInstance, FormRules } from 'element-plus' + import { workApplyApi } from '/@/api/specialWorkSystem/workApply'; + import * as echarts from 'echarts'; + import '/@/theme/bigScreen.css' + + + interface stateType { + } + export default defineComponent({ + name: 'educate', + components: {}, + props:{ + size: Number + }, + setup(props) { + const userInfo = useUserInfo() + const { userInfos } = storeToRefs(userInfo); + const educate = ref("eChartEdu" + Date.now() + Math.random()) + const state = reactive<stateType>({ + + }) + type EChartsOption = echarts.EChartsOption + // 隐患整改情况 + const initEducate =()=>{ + let dom = document.getElementById(educate.value); + let myChart = echarts.init(dom); + + let option: EChartsOption; + + option = { + color: ['#67F9D8', '#FFE434', '#56A3F1', '#FF917C'], + legend: { + top: '8%', + left: 'center', + itemWidth: fontSize(10), + itemHeight: fontSize(8), + textStyle:{ + color: 'auto', + fontSize: fontSize(11) + } + }, + radar: [ + { + indicator: [ + { name: '设计培训次数' }, + { name: '培训时间(小时)' }, + { name: '完成比例(%)' } + ], + center: ['50%', '60%'], + radius: fontSize(65), + startAngle: 90, + splitNumber: 4, + shape: 'circle', + axisName: { + formatter: '{value}', + color: '#428BD4', + fontSize: fontSize(10), + width: 20, + overflow: 'break' + }, + splitArea: { + areaStyle: { + color: ['#77EADF', '#26C3BE', '#64AFE9', '#428BD4'], + shadowColor: 'rgba(0, 0, 0, 0.1)', + shadowBlur: 10 + } + }, + axisLine: { + lineStyle: { + color: 'rgba(211, 253, 250, 0.8)' + } + }, + splitLine: { + lineStyle: { + color: 'rgba(211, 253, 250, 0.8)' + } + } + } + ], + series: [ + { + type: 'radar', + emphasis: { + lineStyle: { + width: 4 + } + }, + data: [ + { + value: [100, 8, 0.4, -80, 2000], + name: '企业汇总' + }, + { + value: [60, 5, 0.3, -100, 1500], + name: '事业部A', + areaStyle: { + color: 'rgba(255, 228, 52, 0.6)' + } + } + ] + }, + ] + }; + + option && myChart.setOption(option); + window.addEventListener("resize",function (){ + myChart.resize(); + }); + } + function fontSize(val){ + let nowClientWidth = document.documentElement.clientWidth; + return val * (nowClientWidth/1920) * Number(props.size); + } + + // 页面载入时执行方法 + onMounted(() => { + initEducate(); + }); + + return { + educate, + Search, + fontSize, + ...toRefs(state) + }; + }, + }); +</script> + +<style scoped lang="scss"> + .charts-cont{ + width: 100%; + height: 100%; + position: relative; + + .educate{ + width: 100%; + height: 100%; + } + } + .home-container { + height: 100%; + overflow: hidden; + position: relative; + .el-row{ + margin-bottom: 20px; + } + .el-row:last-child { + margin-bottom: 0; + } + .el-input{ + width: 100% !important; + } + .el-date-editor::v-deep{ + width: 100%; + } + .el-select{ + width: 100%; + } + .el-cascader{ + width: 100% !important; + } + } +</style> diff --git a/src/views/riskWarningSys/warningBigScreen/components/message.vue b/src/views/riskWarningSys/warningBigScreen/components/message.vue new file mode 100644 index 0000000..5bcbabc --- /dev/null +++ b/src/views/riskWarningSys/warningBigScreen/components/message.vue @@ -0,0 +1,221 @@ +<template> + <div class="charts-cont"> + <div class="message"> + <dv-scroll-board ref="scrollBoard" :config="config" style="width:100%;height:100%;cursor: pointer" @mouseover="mouseoverHandler" @click="clickHandler" /> + </div> + </div> +</template> + +<script lang="ts"> + import {toRefs, reactive, defineComponent, ref, defineAsyncComponent, onMounted, watchEffect} from 'vue'; + import { storeToRefs } from 'pinia'; + import { initBackEndControlRoutes } from '/@/router/backEnd'; + import {useUserInfo} from "/@/stores/userInfo"; + import { Session } from '/@/utils/storage'; + import { Search } from '@element-plus/icons-vue' + import { ElMessage } from 'element-plus' + import { useRouter } from 'vue-router' + import type { FormInstance, FormRules } from 'element-plus' + import { workApplyApi } from '/@/api/specialWorkSystem/workApply'; + import * as echarts from 'echarts'; + import '/@/theme/bigScreen.css' + import {useScreenTheme} from "/@/stores/screenTheme" + + interface stateType { + config: object + } + export default defineComponent({ + name: 'message', + components: {}, + props:{ + size: Number, + theme: Boolean + }, + setup(props) { + const screenThemes = useScreenTheme() + const { screenTheme } = storeToRefs(screenThemes); + const userInfo = useUserInfo() + const { userInfos } = storeToRefs(userInfo); + const router = useRouter(); + const pro = ref("eChartPro" + Date.now() + Math.random()) + const state = reactive<stateType>({ + config:{ + header: ['消息列表', '同比'], + data: [ + ['一月预警消息SPI报告', '<span style="color:#4CF475;">↑ 94%</span>'], + ['二月预警消息SPI报告', '<span style="color:#4CF475;">↑ 94%</span>'], + ['三月预警消息SPI报告', '<span style="color:#4CF475;">↑ 94%</span>'], + ['四月预警消息SPI报告', '<span style="color:red;">↓ 43%</span>'], + ['五月预警消息SPI报告', '<span style="color:#4CF475;">↑ 94%</span>'], + ['六月预警消息SPI报告', '<span style="color:#4CF475;">↑ 94%</span>'], + ['七月预警消息SPI报告', '<span style="color:#4CF475;">↑ 94%</span>'], + ['八月预警消息SPI报告', '<span style="color:red;">↓ 65%</span>'], + ['九月预警消息SPI报告', '<span style="color:#4CF475;">↑ 94%</span>'], + ['十月预警消息SPI报告', '<span style="color:#4CF475;">↑ 94%</span>'], + ['十一月预警消息SPI报告', '<span style="color:#4CF475;">↑ 94%</span>'], + ['十二月预警消息SPI报告', '<span style="color:#4CF475;">↑ 94%</span>'] + ], + index: true, + columnWidth: [60], + align: ['center','center','center'], + headerBGC: '#0049af', + oddRowBGC: 'none', + evenRowBGC: 'rgba(57,122,206,.1)', + indexHeader: '序号', + rowNum: fontSize(5) + } + }) + + const mouseoverHandler = (e: any) => { + + } + + const clickHandler = (e: any) => { + console.log(e.row,'row') + router.push({ + path: 'msgDetail', + query: { + row: e.row + } + }) + } + + function fontSize(val){ + let nowClientWidth = document.documentElement.clientWidth; + return val * (nowClientWidth/1920) * Number(props.size); + } + watchEffect(() => { + if(props.theme){ + state.config.headerBGC = '#0049af' + state.config.oddRowBGC = 'none' + state.config.evenRowBGC = 'rgba(57,122,206,.1)' + }else{ + state.config.headerBGC = '#333' + state.config.oddRowBGC = '#888' + state.config.evenRowBGC = '#999' + } + }) + + const getTheme =()=>{ + if(screenTheme.value.isDark){ + state.config.headerBGC = '#0049af' + state.config.oddRowBGC = 'none' + state.config.evenRowBGC = 'rgba(57,122,206,.1)' + }else{ + state.config.headerBGC = '#333' + state.config.oddRowBGC = '#888' + state.config.evenRowBGC = '#999' + } + } + + // 页面载入时执行方法 + onMounted(() => { + getTheme() + }); + + return { + pro, + Search, + mouseoverHandler, + clickHandler, + fontSize, + ...toRefs(state) + }; + }, + }); +</script> +<style scoped lang="scss"> + + .charts-cont{ + width: 100%; + height: 100%; + padding: 5%; + position: relative; + + .message{ + width: 100%; + height: 100%; + border-radius: 4px; + overflow: hidden; + + .th{ + width: 100%; + display: flex; + height: 36px; + justify-content: space-between; + background: #1882d5; + font-size: 1rem; + line-height: 36px; + color: #ffffff; + .th-num{ + width: 15%; + text-align: center; + } + .th-info{ + width: 70%; + text-align: left; + color: #11FEEE + } + .th-sum{ + width: 15%; + text-align: center; + } + } + + .tm{ + height: calc(100% - 36px); + width: 100%; + overflow: hidden; + scroll-behavior: smooth; + + .ti{ + display: flex; + height: 40px; + line-height: 40px; + justify-content: space-between; + color: #ffffff; + + .num{ + width: 15%; + text-align: center; + } + .info{ + width: 70%; + text-align: left; + color: #11FEEE + } + .sum{ + width: 15%; + text-align: center; + } + } + .darkBg{ + background: rgba(57,122,206,.4); + } + } + } + } + .home-container { + height: 100%; + overflow: hidden; + position: relative; + .el-row{ + margin-bottom: 20px; + } + .el-row:last-child { + margin-bottom: 0; + } + .el-input{ + width: 100% !important; + } + .el-date-editor::v-deep{ + width: 100%; + } + .el-select{ + width: 100%; + } + .el-cascader{ + width: 100% !important; + } + } +</style> diff --git a/src/views/riskWarningSys/warningBigScreen/components/monitor.vue b/src/views/riskWarningSys/warningBigScreen/components/monitor.vue new file mode 100644 index 0000000..a979428 --- /dev/null +++ b/src/views/riskWarningSys/warningBigScreen/components/monitor.vue @@ -0,0 +1,104 @@ +<template> + <div class="charts-cont"> + <div class="monitor" :id="monitor"> + <div> + <img src="../../../../assets/warningScreen/video.png"> + </div> + </div> + </div> +</template> + +<script lang="ts"> + import {toRefs, reactive, defineComponent, ref, defineAsyncComponent, onMounted} from 'vue'; + import { storeToRefs } from 'pinia'; + import { initBackEndControlRoutes } from '/@/router/backEnd'; + import {useUserInfo} from "/@/stores/userInfo"; + import { Session } from '/@/utils/storage'; + import { Search } from '@element-plus/icons-vue' + import { ElMessage } from 'element-plus' + import type { FormInstance, FormRules } from 'element-plus' + import { workApplyApi } from '/@/api/specialWorkSystem/workApply'; + import * as echarts from 'echarts'; + import '/@/theme/bigScreen.css' + + + interface stateType { + } + export default defineComponent({ + name: 'monitor', + components: {}, + props:['allData'], + setup() { + const userInfo = useUserInfo() + const { userInfos } = storeToRefs(userInfo); + const monitor = ref("eChartMon" + Date.now() + Math.random()) + const state = reactive<stateType>({ + + }) + + + + // 页面载入时执行方法 + onMounted(() => { + }); + + return { + monitor, + Search, + ...toRefs(state) + }; + }, + }); +</script> + +<style scoped lang="scss"> + .charts-cont{ + width: 100%; + height: 100%; + padding: 5%; + position: relative; + + .monitor{ + width: 100%; + height: 100%; + position: relative; + border-radius: 8px; + overflow: hidden; + + img{ + display: block; + width: 100%; + height: auto; + position: absolute; + left: 0; + right: 0; + bottom: 0; + top: 0; + margin: auto; + } + } + } + .home-container { + height: 100%; + overflow: hidden; + position: relative; + .el-row{ + margin-bottom: 20px; + } + .el-row:last-child { + margin-bottom: 0; + } + .el-input{ + width: 100% !important; + } + .el-date-editor::v-deep{ + width: 100%; + } + .el-select{ + width: 100%; + } + .el-cascader{ + width: 100% !important; + } + } +</style> diff --git a/src/views/riskWarningSys/warningBigScreen/components/profession.vue b/src/views/riskWarningSys/warningBigScreen/components/profession.vue new file mode 100644 index 0000000..215c675 --- /dev/null +++ b/src/views/riskWarningSys/warningBigScreen/components/profession.vue @@ -0,0 +1,177 @@ +<template> + <div class="charts-cont"> + <div class="pro" :id="pro"> + + </div> +<!-- <dv-active-ring-chart :config="config" style="width:100%;height:100%" />--> + </div> +</template> + +<script lang="ts"> + import {toRefs, reactive, defineComponent, ref, defineAsyncComponent, onMounted} from 'vue'; + import { storeToRefs } from 'pinia'; + import { initBackEndControlRoutes } from '/@/router/backEnd'; + import {useUserInfo} from "/@/stores/userInfo"; + import { Session } from '/@/utils/storage'; + import { Search } from '@element-plus/icons-vue' + import { ElMessage } from 'element-plus' + import type { FormInstance, FormRules } from 'element-plus' + import { workApplyApi } from '/@/api/specialWorkSystem/workApply'; + import * as echarts from 'echarts'; + import '/@/theme/bigScreen.css' + + + interface stateType { + } + export default defineComponent({ + name: 'profession', + components: {}, + props:{ + size: Number + }, + setup(props) { + const userInfo = useUserInfo() + const { userInfos } = storeToRefs(userInfo); + const pro = ref("eChartPro" + Date.now() + Math.random()) + const state = reactive<stateType>({ + config:{ + data: [ + { + name: '持证人员', + value: 55 + }, + { + name: '非持证人员', + value: 120 + } + ], + radius: '65%', + activeRadius: '60%', + color: ['#FAC858','#EE6666'], + lineWidth: fontSize(25), + digitalFlopStyle: { + fontSize: 16, + fill: '#999' + } + } + }) + type EChartsOption = echarts.EChartsOption + // 隐患整改情况 + const initPro =()=>{ + let dom = document.getElementById(pro.value); + let myChart = echarts.init(dom); + + let option: EChartsOption; + + option = { + tooltip: { + trigger: 'item' + }, + legend: { + top: '0', + left: 'center', + textStyle:{ + color: '#999', + fontSize: fontSize(11) + } + }, + series: [ + { + name: 'Access From', + type: 'pie', + radius: ['45%', '70%'], + avoidLabelOverlap: false, + itemStyle: { + borderRadius: 4 + }, + label: { + show: true, + position: 'outer', + fontSize: fontSize(12), + color: '#999', + textBorderWidth: 0, + width: 30, + overflow: 'break' + }, + labelLine: { + show: true, + length: 10, + length2: 10 + }, + emphasis: { + label: { + show: true, + fontSize: fontSize(22), + fontWeight: 'bold' + } + }, + data: [ + { value: 1048, name: '持证人员' }, + { value: 735, name: '非持证人员' } + ], + center: ['50%','55%'] + } + ] + }; + + option && myChart.setOption(option); + window.addEventListener("resize",function (){ + myChart.resize(); + }); + } + function fontSize(val){ + let nowClientWidth = document.documentElement.clientWidth; + return val * (nowClientWidth/1920) * Number(props.size); + } + + // 页面载入时执行方法 + onMounted(() => { + initPro() + }); + + return { + pro, + Search, + fontSize, + ...toRefs(state) + }; + }, + }); +</script> + +<style scoped lang="scss"> + .charts-cont{ + width: 100%; + height: 100%; + padding: 4% 4% 0; + position: relative; + + .pro{ + width: 100%; + height: 100%; + } + } + .home-container { + height: 100%; + overflow: hidden; + position: relative; + .el-row{ + margin-bottom: 20px; + } + .el-row:last-child { + margin-bottom: 0; + } + .el-input{ + width: 100% !important; + } + .el-date-editor::v-deep{ + width: 100%; + } + .el-select{ + width: 100%; + } + .el-cascader{ + width: 100% !important; + } + } +</style> diff --git a/src/views/riskWarningSys/warningBigScreen/components/risk.vue b/src/views/riskWarningSys/warningBigScreen/components/risk.vue new file mode 100644 index 0000000..038699b --- /dev/null +++ b/src/views/riskWarningSys/warningBigScreen/components/risk.vue @@ -0,0 +1,505 @@ +<template> + <div class="charts-cont"> + <el-select :class="selector" v-model="month" placeholder="Select" :teleported="false" size="default"> + <el-option + v-for="item in optionList" + :key="item.value" + :label="item.label" + :value="item.value" + /> + </el-select> + <div v-show="curValue===true" class="risk" :id="risk1"></div> + <div v-show="curValue===false" class="risk" :id="risk2"></div> + </div> +</template> + +<script lang="ts"> + import { toRefs, reactive, defineComponent, ref, defineAsyncComponent, onMounted, nextTick, onBeforeUnmount, watchEffect } from 'vue'; + import { storeToRefs } from 'pinia'; + import { initBackEndControlRoutes } from '/@/router/backEnd'; + import {useUserInfo} from "/@/stores/userInfo"; + import { Session } from '/@/utils/storage'; + import { Search } from '@element-plus/icons-vue' + import { ElMessage } from 'element-plus' + import type { FormInstance, FormRules } from 'element-plus' + import { workApplyApi } from '/@/api/specialWorkSystem/workApply'; + import * as echarts from 'echarts'; + import '/@/theme/bigScreen.css' + import {useScreenTheme} from "/@/stores/screenTheme"; + + + interface stateType { + curValue: boolean, + month: number, + optionList: Array<any>, + selector: string + } + export default defineComponent({ + name: 'risk', + components: {}, + props:{ + size: Number, + theme: Boolean + }, + setup(props) { + const userInfo = useUserInfo() + const { userInfos } = storeToRefs(userInfo); + const screenThemes = useScreenTheme() + const { screenTheme } = storeToRefs(screenThemes); + const risk1 = ref("eChartRisk1" + Date.now() + Math.random()) + const risk2 = ref("eChartRisk2" + Date.now() + Math.random()) + const state = reactive<stateType>({ + curValue: true, + month: 0, + optionList: [ + { + label: '年度', + value: 0 + }, + { + label: '一月', + value: 1 + }, + { + label: '二月', + value: 2 + }, + { + label: '三月', + value: 3 + }, + { + label: '四月', + value: 4 + }, + { + label: '五月', + value: 5 + }, + { + label: '六月', + value: 6 + }, + { + label: '七月', + value: 7 + }, + { + label: '八月', + value: 8 + }, + { + label: '九月', + value: 9 + }, + { + label: '十月', + value: 10 + } + ], + selector: 'select-dark' + }) + + const swi = setInterval(()=>{ + state.curValue = !state.curValue + if(state.curValue == true){ + nextTick(()=>{ + initRisk1() + }) + }else{ + nextTick(()=>{ + initRisk2() + }) + } + + },5000) + + type EChartsOption = echarts.EChartsOption + // 隐患整改情况 + const initRisk1 =()=>{ + let dom = document.getElementById(risk1.value); + let myChart = echarts.init(dom); + + let option: EChartsOption; + + option = { + tooltip: { + trigger: 'axis', + axisPointer: { + // Use axis to trigger tooltip + type: 'shadow' // 'shadow' as default; can also be 'line' or 'shadow' + } + }, + legend: { + top: '1%', + left: 'center', + itemWidth: fontSize(10), + itemHeight: fontSize(8), + textStyle:{ + color: 'auto', + fontSize: fontSize(12) + } + }, + grid: { + left: '2%', + right: '4%', + bottom: '0', + containLabel: true + }, + xAxis: { + type: 'category', + // data: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'], + data: ['企业总', 'A部门', 'B部门', 'C部门', 'D部门', 'E部门'], + axisLine:{ + show: true, + lineStyle:{ + color: '#999' + } + }, + axisLabel:{ + color: '#999' + } + }, + yAxis: { + type: 'value', + axisLine:{ + show: true, + lineStyle:{ + type: 'dotted' + } + }, + axisLabel:{ + color: '#999' + }, + splitLine:{ + show: false + } + }, + series: [ + { + name: '可能造成死亡的', + type: 'bar', + stack: 'total', + label: { + show: false + }, + emphasis: { + focus: 'series' + }, + // data: [320, 302, 301, 334, 390, 330, 320, 301, 334, 390, 330, 320] + data: [320, 302, 301, 334, 390, 330], + barCategoryGap: '50%' + }, + { + name: '可能造成重伤的', + type: 'bar', + stack: 'total', + label: { + show: false + }, + emphasis: { + focus: 'series' + }, + // data: [120, 132, 101, 134, 90, 230, 210, 132, 101, 134, 90, 230] + data: [120, 132, 101, 134, 90, 230], + barCategoryGap: '50%' + }, + { + name: '可能造成轻伤的', + type: 'bar', + stack: 'total', + label: { + show: false + }, + emphasis: { + focus: 'series' + }, + // data: [220, 182, 191, 234, 290, 330, 310, 191, 234, 290, 330, 310] + data: [220, 182, 191, 234, 290, 330], + barCategoryGap: '50%' + } + ] + }; + + option && myChart.setOption(option); + window.addEventListener("resize",function (){ + myChart.resize(); + }); + echarts.init(document.getElementById(risk2.value)).dispose() + } + + const initRisk2 =()=>{ + let dom = document.getElementById(risk2.value); + let myChart = echarts.init(dom); + + let option: EChartsOption; + + option = { + tooltip: { + trigger: 'axis', + axisPointer: { + // Use axis to trigger tooltip + type: 'shadow' // 'shadow' as default; can also be 'line' or 'shadow' + } + }, + legend: { + top: '1%', + left: 'center', + itemWidth: fontSize(10), + itemHeight: fontSize(8), + textStyle:{ + color: 'auto', + fontSize: fontSize(12) + } + }, + grid: { + left: '2%', + right: '4%', + bottom: '0', + containLabel: true + }, + xAxis: { + type: 'category', + // data: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'], + data: ['F部门', 'G部门', 'H部门', 'I部门', 'J部门', 'K部门'], + axisLine:{ + show: true, + lineStyle:{ + color: '#999' + } + }, + axisLabel:{ + color: '#999' + } + }, + yAxis: { + type: 'value', + axisLine:{ + show: true, + lineStyle:{ + type: 'dotted' + } + }, + axisLabel:{ + color: '#999' + }, + splitLine:{ + show: false + } + }, + series: [ + { + name: '可能造成死亡的', + type: 'bar', + stack: 'total', + label: { + show: false + }, + emphasis: { + focus: 'series' + }, + // data: [320, 302, 301, 334, 390, 330, 320, 301, 334, 390, 330, 320] + data: [320, 301, 334, 390, 330, 320], + barCategoryGap: '50%' + }, + { + name: '可能造成重伤的', + type: 'bar', + stack: 'total', + label: { + show: false + }, + emphasis: { + focus: 'series' + }, + // data: [120, 132, 101, 134, 90, 230, 210, 132, 101, 134, 90, 230] + data: [90, 230, 210, 132, 101, 134], + barCategoryGap: '50%' + }, + { + name: '可能造成轻伤的', + type: 'bar', + stack: 'total', + label: { + show: false + }, + emphasis: { + focus: 'series' + }, + // data: [220, 182, 191, 234, 290, 330, 310, 191, 234, 290, 330, 310] + data: [290, 330, 310, 191, 234, 290], + barCategoryGap: '50%' + } + ] + }; + + option && myChart.setOption(option); + window.addEventListener("resize",function (){ + myChart.resize(); + }); + echarts.init(document.getElementById(risk1.value)).dispose() + } + + const getTheme =()=>{ + if(screenTheme.value.isDark){ + state.selector = 'select-dark' + }else{ + state.selector = 'select-light' + } + } + + watchEffect(() => { + if(props.theme){ + state.selector = 'select-dark' + }else{ + state.selector = 'select-light' + } + }) + + function fontSize(val){ + let nowClientWidth = document.documentElement.clientWidth; + return val * (nowClientWidth/1920) * Number(props.size); + } + + // 页面载入时执行方法 + onMounted(() => { + initRisk1(); + getTheme(); + }); + + onBeforeUnmount(() =>{ + clearInterval(swi) + }) + + return { + risk1, + risk2, + Search, + fontSize, + ...toRefs(state) + }; + }, + }); +</script> + +<style scoped lang="scss"> + .charts-cont{ + width: 100%; + height: 100%; + padding: 5% 5% 2%; + position: relative; + .select-dark{ + position: absolute; + z-index: 999; + top: -20px; + right: 1.6rem; + width: 30%; + height: 20px; + margin-right: 0.8rem; + + ::v-deep(.el-popper){ + background-color: rgba(10,31,92,1); + border: 1px solid rgba(17,254,238,.4); + color: #11FEEE; + .el-select-dropdown__item{ + color: #11FEEE; + } + .el-select-dropdown__item.hover{ + background: #0049af; + } + } + ::v-deep(.el-popper__arrow){ + &::before{ + background-color: rgba(10,31,92,.6) !important; + border: 1px solid rgba(17,254,238,.4); + } + } + ::v-deep(.el-input__wrapper){ + box-shadow: none; + border: 1px solid rgba(17,254,238,.2); + background: rgba(10,31,92,.6) !important; + height: 1.5rem; + color: #11FEEE; + + input{ + font-size: 0.8rem; + color: #11FEEE; + } + .el-icon{ + color: #11FEEE; + } + } + } + + .select-light{ + position: absolute; + z-index: 999; + top: -20px; + right: 1.6rem; + width: 30%; + height: 20px; + margin-right: 0.8rem; + + ::v-deep(.el-popper){ + background-color: rgba(255,255,255,1); + border: 1px solid #ccc; + color: #fff; + .el-select-dropdown__item{ + color: #000; + } + .el-select-dropdown__item.hover{ + background: #ccc; + } + } + ::v-deep(.el-popper__arrow){ + &::before{ + background-color: rgba(255,255,255,.6) !important; + border: 1px solid #ccc; + } + } + ::v-deep(.el-input__wrapper){ + box-shadow: none; + border: 1px solid #ccc; + background: #fff !important; + height: 1.5rem; + color: #fff; + + input{ + font-size: 0.8rem; + color: #000; + } + .el-icon{ + color: #000; + } + } + } + + .risk{ + width: 100%; + height: 100%; + } + } + .home-container { + height: 100%; + overflow: hidden; + position: relative; + .el-row{ + margin-bottom: 20px; + } + .el-row:last-child { + margin-bottom: 0; + } + .el-input{ + width: 100% !important; + } + .el-date-editor::v-deep{ + width: 100%; + } + .el-select{ + width: 100%; + } + .el-cascader{ + width: 100% !important; + } + } +</style> diff --git a/src/views/riskWarningSys/warningBigScreen/components/stock.vue b/src/views/riskWarningSys/warningBigScreen/components/stock.vue new file mode 100644 index 0000000..1feb3db --- /dev/null +++ b/src/views/riskWarningSys/warningBigScreen/components/stock.vue @@ -0,0 +1,681 @@ +<template> + <div class="charts-cont"> + <div v-show="curValue===true" class="stock" :id="stock1"> + + </div> + <div v-show="curValue===false" class="stock" :id="stock2"></div> + </div> +</template> + +<script lang="ts"> + import {toRefs, reactive, defineComponent, ref, defineAsyncComponent, onMounted, nextTick, onBeforeUnmount} from 'vue'; + import { storeToRefs } from 'pinia'; + import { initBackEndControlRoutes } from '/@/router/backEnd'; + import {useUserInfo} from "/@/stores/userInfo"; + import { Session } from '/@/utils/storage'; + import { Search } from '@element-plus/icons-vue' + import { ElMessage } from 'element-plus' + import type { FormInstance, FormRules } from 'element-plus' + import { workApplyApi } from '/@/api/specialWorkSystem/workApply'; + import * as echarts from 'echarts'; + import '/@/theme/bigScreen.css' + + interface stateType { + curValue: boolean + } + export default defineComponent({ + name: 'stock', + components: {}, + props:{ + size: Number + }, + setup(props) { + const userInfo = useUserInfo() + const { userInfos } = storeToRefs(userInfo); + const stock1 = ref("eChartStock1" + Date.now() + Math.random()) + const stock2 = ref("eChartStock2" + Date.now() + Math.random()) + const state = reactive<stateType>({ + curValue: true + }) + + const swit = setInterval(()=>{ + state.curValue = !state.curValue + if(state.curValue == true){ + nextTick(()=>{ + initStock1() + }) + }else{ + nextTick(()=>{ + initStock2() + }) + } + },5000) + type EChartsOption = echarts.EChartsOption + // 隐患整改情况 + const initStock1 =()=>{ + let dom = document.getElementById(stock1.value); + let myChart = echarts.init(dom); + + let option: EChartsOption; + + option = { + series: [ + { + name: '消防耗材', + type: 'pie', + radius: [fontSize(40), fontSize(50)], + data: [ + { value: 2103, name: '消防耗材'}, + { value: 2310, name: '消防耗材未使用'} + ], + label: { + show: true, + position: 'center', + formatter: '{total|{a}}' + '\n\r' + '{active|2103}', + rich: { + total:{ + fontSize: fontSize(12), + color:'#999', + lineHeight: fontSize(16) + }, + active: { + fontSize: fontSize(16), + color:'#999', + }, + } + }, + color: [ + { + type: 'linear', + x: 0, + y: 0, + x2: 0, + y2: 1, + colorStops: [{ + offset: 0, color: "#2D74C0" // 0% 处的颜色 + }, { + offset: 1, color: "#21D9DC" // 100% 处的颜色 + }] + }, + { + type: 'linear', + x: 0, + y: 0, + x2: 0, + y2: 1, + colorStops: [{ + offset: 0, color: "#333" // 0% 处的颜色 + }, { + offset: 1, color: "#333" // 100% 处的颜色 + }] + } + ], + center: ['20%','25%'] + }, + { + name: '安全帽', + type: 'pie', + radius: [fontSize(40), fontSize(50)], + data: [ + { value: 23509, name: '安全帽'}, + { value: 34312, name: '安全帽未使用'} + ], + label: { + show: true, + position: 'center', + formatter: '{total|{a}}' + '\n\r' + '{active|23509}', + rich: { + total:{ + fontSize: fontSize(12), + color:'#999', + lineHeight: fontSize(16) + }, + active: { + fontSize: fontSize(16), + color:'#999', + }, + } + }, + color: [ + { + type: 'linear', + x: 0, + y: 0, + x2: 0, + y2: 1, + colorStops: [{ + offset: 0, color: "#0DAA2E" // 0% 处的颜色 + }, { + offset: 1, color: "#4CF475" // 100% 处的颜色 + }] + }, + { + type: 'linear', + x: 0, + y: 0, + x2: 0, + y2: 1, + colorStops: [{ + offset: 0, color: "#333" // 0% 处的颜色 + }, { + offset: 1, color: "#333" // 100% 处的颜色 + }] + } + ], + center: ['50%','25%'] + }, + { + name: '防护服', + type: 'pie', + radius: [fontSize(40), fontSize(50)], + data: [ + { value: 12830, name: '防护服'}, + { value: 22140, name: '防护服未使用'} + ], + label: { + show: true, + position: 'center', + formatter: '{total|{a}}' + '\n\r' + '{active|12830}', + rich: { + total:{ + fontSize: fontSize(12), + color:'#999', + lineHeight: fontSize(16) + }, + active: { + fontSize: fontSize(16), + color:'#999', + }, + } + }, + color: [ + { + type: 'linear', + x: 0, + y: 0, + x2: 0, + y2: 1, + colorStops: [{ + offset: 0, color: "#E8B21D" // 0% 处的颜色 + }, { + offset: 1, color: "#E5DC44" // 100% 处的颜色 + }], + global: false // 缺省为 false + }, + { + type: 'linear', + x: 0, + y: 0, + x2: 0, + y2: 1, + colorStops: [{ + offset: 0, color: "#333" // 0% 处的颜色 + }, { + offset: 1, color: "#333" // 100% 处的颜色 + }], + global: false // 缺省为 false + } + ], + center: ['80%','25%'] + }, + { + name: '劳保鞋', + type: 'pie', + radius: [fontSize(40), fontSize(50)], + data: [ + { value: 5492, name: '劳保鞋'}, + { value: 10842, name: '劳保鞋未使用'} + ], + label: { + show: true, + position: 'center', + formatter: '{total|{a}}' + '\n\r' + '{active|5492}', + rich: { + total:{ + fontSize: fontSize(12), + color:'#999', + lineHeight: fontSize(16) + }, + active: { + fontSize: fontSize(16), + color:'#999', + }, + } + }, + color: [ + { + type: 'linear', + x: 0, + y: 0, + x2: 0, + y2: 1, + colorStops: [{ + offset: 0, color: "#D65146" // 0% 处的颜色 + }, { + offset: 1, color: "#F58C28" // 100% 处的颜色 + }] + }, + { + type: 'linear', + x: 0, + y: 0, + x2: 0, + y2: 1, + colorStops: [{ + offset: 0, color: "#333" // 0% 处的颜色 + }, { + offset: 1, color: "#333" // 100% 处的颜色 + }] + } + ], + center: ['33.33%','75%'] + }, + { + name: '动火护具', + type: 'pie', + radius: [fontSize(40), fontSize(50)], + data: [ + { value: 44043, name: '动火护具'}, + { value: 68102, name: '动火护具未使用' } + ], + label: { + show: true, + position: 'center', + formatter: '{total|{a}}' + '\n\r' + '{active|44043}', + rich: { + total:{ + fontSize: fontSize(12), + color:'#999', + lineHeight: fontSize(16) + }, + active: { + fontSize: fontSize(16), + color:'#999', + }, + } + }, + color: [ + { + type: 'linear', + x: 0, + y: 0, + x2: 0, + y2: 1, + colorStops: [{ + offset: 0, color: "#4449D1" // 0% 处的颜色 + }, { + offset: 1, color: "#A86DE5" // 100% 处的颜色 + }] + }, + { + type: 'linear', + x: 0, + y: 0, + x2: 0, + y2: 1, + colorStops: [{ + offset: 0, color: "#333" // 0% 处的颜色 + }, { + offset: 1, color: "#333" // 100% 处的颜色 + }] + } + ], + center: ['66.66%','75%'] + } + ], + }; + + option && myChart.setOption(option); + window.addEventListener("resize",function (){ + myChart.resize(); + }); + echarts.init(document.getElementById(stock2.value)).dispose() + } + + const initStock2 =()=>{ + let dom = document.getElementById(stock2.value); + let myChart = echarts.init(dom); + + let option: EChartsOption; + + option = { + series: [ + { + name: '急救包', + type: 'pie', + radius: [fontSize(40), fontSize(50)], + data: [ + { value: 8603, name: '急救包'}, + { value: 12032, name: '急救包未使用'} + ], + label: { + show: true, + position: 'center', + formatter: '{total|{a}}' + '\n\r' + '{active|8603}', + rich: { + total:{ + fontSize: fontSize(12), + color:'#999', + lineHeight: fontSize(16) + }, + active: { + fontSize: fontSize(16), + color:'#999', + }, + } + }, + color: [ + { + type: 'linear', + x: 0, + y: 0, + x2: 0, + y2: 1, + colorStops: [{ + offset: 0, color: "#2D74C0" // 0% 处的颜色 + }, { + offset: 1, color: "#21D9DC" // 100% 处的颜色 + }], + global: false // 缺省为 false + }, + { + type: 'linear', + x: 0, + y: 0, + x2: 0, + y2: 1, + colorStops: [{ + offset: 0, color: "#333" // 0% 处的颜色 + }, { + offset: 1, color: "#333" // 100% 处的颜色 + }], + global: false // 缺省为 false + } + ], + center: ['20%','25%'] + }, + { + name: '人员培训资料', + type: 'pie', + radius: [fontSize(40), fontSize(50)], + data: [ + { value: 8960, name: '人员培训资料'}, + { value: 9890, name: '人员培训资料未使用'} + ], + label: { + show: true, + position: 'center', + formatter: '{total|{a}}' + '\n\r' + '{active|8960}', + rich: { + total:{ + fontSize: fontSize(12), + color:'#999', + lineHeight: fontSize(16) + }, + active: { + fontSize: fontSize(16), + color:'#999', + }, + } + }, + color: [ + { + type: 'linear', + x: 0, + y: 0, + x2: 0, + y2: 1, + colorStops: [{ + offset: 0, color: "#0DAA2E" // 0% 处的颜色 + }, { + offset: 1, color: "#4CF475" // 100% 处的颜色 + }], + global: false // 缺省为 false + }, + { + type: 'linear', + x: 0, + y: 0, + x2: 0, + y2: 1, + colorStops: [{ + offset: 0, color: "#333" // 0% 处的颜色 + }, { + offset: 1, color: "#333" // 100% 处的颜色 + }], + global: false // 缺省为 false + } + ], + center: ['50%','25%'] + }, + { + name: '安全护具', + type: 'pie', + radius: [fontSize(40), fontSize(50)], + data: [ + { value: 12302, name: '安全护具'}, + { value: 20130, name: '安全护具未使用'} + ], + label: { + show: true, + position: 'center', + formatter: '{total|{a}}' + '\n\r' + '{active|12302}', + rich: { + total:{ + fontSize: fontSize(12), + color:'#999', + lineHeight: fontSize(16) + }, + active: { + fontSize: fontSize(16), + color:'#999', + }, + } + }, + color: [ + { + type: 'linear', + x: 0, + y: 0, + x2: 0, + y2: 1, + colorStops: [{ + offset: 0, color: "#E8B21D" // 0% 处的颜色 + }, { + offset: 1, color: "#E5DC44" // 100% 处的颜色 + }], + global: false // 缺省为 false + }, + { + type: 'linear', + x: 0, + y: 0, + x2: 0, + y2: 1, + colorStops: [{ + offset: 0, color: "#333" // 0% 处的颜色 + }, { + offset: 1, color: "#333" // 100% 处的颜色 + }], + global: false // 缺省为 false + } + ], + center: ['80%','25%'] + }, + { + name: '高空护具', + type: 'pie', + radius: [fontSize(40), fontSize(50)], + data: [ + { value: 42948, name: '高空护具'}, + { value: 89342, name: '高空护具未使用'} + ], + label: { + show: true, + position: 'center', + formatter: '{total|{a}}' + '\n\r' + '{active|42948}', + rich: { + total:{ + fontSize: fontSize(12), + color:'#999', + lineHeight: fontSize(16) + }, + active: { + fontSize: fontSize(16), + color:'#999', + }, + } + }, + color: [ + { + type: 'linear', + x: 0, + y: 0, + x2: 0, + y2: 1, + colorStops: [{ + offset: 0, color: "#D65146" // 0% 处的颜色 + }, { + offset: 1, color: "#F58C28" // 100% 处的颜色 + }], + global: false // 缺省为 false + }, + { + type: 'linear', + x: 0, + y: 0, + x2: 0, + y2: 1, + colorStops: [{ + offset: 0, color: "#333" // 0% 处的颜色 + }, { + offset: 1, color: "#333" // 100% 处的颜色 + }], + global: false // 缺省为 false + } + ], + center: ['33.33%','75%'] + }, + { + name: '防尘护具', + type: 'pie', + radius: [fontSize(40), fontSize(50)], + data: [ + { value: 1220, name: '防尘护具'}, + { value: 5034, name: '防尘护具未使用' } + ], + label: { + show: true, + position: 'center', + formatter: '{total|{a}}' + '\n\r' + '{active|1220}', + rich: { + total:{ + fontSize: fontSize(12), + color:'#999', + lineHeight: fontSize(16) + }, + active: { + fontSize: fontSize(16), + color:'#999', + }, + } + }, + color: [ + { + type: 'linear', + x: 0, + y: 0, + x2: 0, + y2: 1, + colorStops: [{ + offset: 0, color: "#4449D1" // 0% 处的颜色 + }, { + offset: 1, color: "#A86DE5" // 100% 处的颜色 + }], + global: false // 缺省为 false + }, + { + type: 'linear', + x: 0, + y: 0, + x2: 0, + y2: 1, + colorStops: [{ + offset: 0, color: "#333" // 0% 处的颜色 + }, { + offset: 1, color: "#333" // 100% 处的颜色 + }], + global: false // 缺省为 false + } + ], + center: ['66.66%','75%'] + } + ], + }; + + option && myChart.setOption(option); + window.addEventListener("resize",function (){ + myChart.resize(); + }); + echarts.init(document.getElementById(stock1.value)).dispose() + } + + function fontSize(val){ + let nowClientWidth = document.documentElement.clientWidth; + return val * (nowClientWidth/1920) * Number(props.size); + } + + // 页面载入时执行方法 + onMounted(() => { + initStock1(); + }); + onBeforeUnmount(() =>{ + clearInterval(swit) + }) + return { + stock1, + stock2, + Search, + fontSize, + ...toRefs(state) + }; + }, + }); +</script> + +<style scoped lang="scss"> + .charts-cont{ + width: 100%; + height: 100%; + padding: 2%; + position: relative; + + .stock{ + width: 100%; + height: 100%; + } + } + .home-container { + height: 100%; + overflow: hidden; + position: relative; + .el-row{ + margin-bottom: 20px; + } + .el-row:last-child { + margin-bottom: 0; + } + .el-input{ + width: 100% !important; + } + .el-date-editor::v-deep{ + width: 100%; + } + .el-select{ + width: 100%; + } + .el-cascader{ + width: 100% !important; + } + } +</style> diff --git a/src/views/riskWarningSys/warningBigScreen/components/training.vue b/src/views/riskWarningSys/warningBigScreen/components/training.vue new file mode 100644 index 0000000..68eab0b --- /dev/null +++ b/src/views/riskWarningSys/warningBigScreen/components/training.vue @@ -0,0 +1,423 @@ +<template> + <div class="charts-cont"> + <div v-show="curTab === 1" class="train" :id="train1"></div> + <div v-show="curTab === 2" class="train" :id="train2"></div> + <div v-show="curTab === 3" class="train" :id="train3"></div> + </div> +</template> + +<script lang="ts"> + import {toRefs, reactive, defineComponent, ref, defineAsyncComponent, onMounted, nextTick, onBeforeUnmount} from 'vue'; + import { storeToRefs } from 'pinia'; + import { initBackEndControlRoutes } from '/@/router/backEnd'; + import {useUserInfo} from "/@/stores/userInfo"; + import { Session } from '/@/utils/storage'; + import { Search } from '@element-plus/icons-vue' + import { ElMessage } from 'element-plus' + import type { FormInstance, FormRules } from 'element-plus' + import { workApplyApi } from '/@/api/specialWorkSystem/workApply'; + import * as echarts from 'echarts'; + import '/@/theme/bigScreen.css' + + interface stateType { + curTab: number + } + export default defineComponent({ + name: 'accident', + components: {}, + props:{ + size: Number + }, + setup(props) { + const userInfo = useUserInfo() + const { userInfos } = storeToRefs(userInfo); + const train1 = ref("eChartTrain1" + Date.now() + Math.random()) + const train2 = ref("eChartTrain2" + Date.now() + Math.random()) + const train3 = ref("eChartTrain3" + Date.now() + Math.random()) + const state = reactive<stateType>({ + curTab: 1 + }) + + // const changeTab=()=>{ + // setInterval(()=>{ + // if(state.curTab<3){ + // state.curTab = state.curTab + 1 + // if(state.curTab == 2){ + // nextTick(()=>{ + // initTrain2() + // }) + // }else{ + // nextTick(()=>{ + // initTrain3() + // }) + // } + // + // }else{ + // state.curTab = 1 + // nextTick(()=>{ + // initTrain1() + // }) + // } + // },5000) + // } + const changeTab = setInterval(()=>{ + if(state.curTab<3){ + state.curTab = state.curTab + 1 + if(state.curTab == 2){ + nextTick(()=>{ + initTrain2() + }) + }else{ + nextTick(()=>{ + initTrain3() + }) + } + + }else{ + state.curTab = 1 + nextTick(()=>{ + initTrain1() + }) + } + },5000) + type EChartsOption = echarts.EChartsOption + // 隐患整改情况 + const initTrain1 =()=>{ + let dom = document.getElementById(train1.value); + let myChart = echarts.init(dom); + let option: EChartsOption; + + option = { + tooltip: { + trigger: 'axis', + axisPointer: { + type: 'shadow' + } + }, + grid: { + top: '1%', + left: '2%', + right: '2%', + bottom: '2%', + containLabel: true + }, + xAxis: { + type: 'value', + boundaryGap: [0, 0.01], + axisLine:{ + show: true, + lineStyle:{ + type: 'dotted' + } + }, + axisLabel:{ + color: '#999' + }, + splitLine:{ + show: false + } + }, + yAxis: { + type: 'category', + // data: ['一月', '二月', '三月', '四月', '五月', '六月','七月', '八月', '九月', '十月', '十一月', '十二月'], + data: ['一月', '二月', '三月', '四月'], + axisLine:{ + show: true, + lineStyle:{ + color: '#999' + } + }, + axisLabel:{ + color: '#999' + } + }, + series: [ + { + name: '2011', + type: 'bar', + // data: [18203, 23489, 29034, 104970, 131744, 630230, 18203, 23489, 29034, 104970, 131744, 630230] + data: [18203, 23489, 29034, 104970], + itemStyle:{ + color: { + x: 0, + y: 0, + x2: 1, + y2: 0, + colorStops: [ + { + offset: 0.1, + color: "#2D74C0", // 线处的颜色 + }, + { + offset: 0.9, + color: "#21D9DC", // 坐标轴处的颜色 + }, + ] + }, + borderRadius: [0,99,99,0] + }, + barCategoryGap: '50%', + label:{ + show: true, + position: 'outside', + color: '#999', + fontSize: fontSize(11) + } + } + ] + }; + + option && myChart.setOption(option); + window.addEventListener("resize",function (){ + myChart.resize(); + }); + echarts.init(document.getElementById(train2.value)).dispose() + echarts.init(document.getElementById(train3.value)).dispose() + } + + const initTrain2 =()=>{ + let dom = document.getElementById(train2.value); + let myChart = echarts.init(dom); + let option: EChartsOption; + + option = { + tooltip: { + trigger: 'axis', + axisPointer: { + type: 'shadow' + } + }, + grid: { + top: '1%', + left: '2%', + right: '2%', + bottom: '2%', + containLabel: true + }, + xAxis: { + type: 'value', + boundaryGap: [0, 0.01], + axisLine:{ + show: true, + lineStyle:{ + type: 'dotted' + } + }, + axisLabel:{ + color: '#999' + }, + splitLine:{ + show: false + } + }, + yAxis: { + type: 'category', + // data: ['一月', '二月', '三月', '四月', '五月', '六月','七月', '八月', '九月', '十月', '十一月', '十二月'], + data: ['五月', '六月','七月', '八月'], + axisLine:{ + show: true, + lineStyle:{ + color: '#999' + } + }, + axisLabel:{ + color: '#999' + } + }, + series: [ + { + name: '2011', + type: 'bar', + // data: [18203, 23489, 29034, 104970, 131744, 630230, 18203, 23489, 29034, 104970, 131744, 630230] + data: [131744, 630230, 18203, 23489], + barCategoryGap: '50%', + itemStyle:{ + color: { + x: 0, + y: 0, + x2: 1, + y2: 0, + colorStops: [ + { + offset: 0.1, + color: "#2D74C0", // 线处的颜色 + }, + { + offset: 0.9, + color: "#21D9DC", // 坐标轴处的颜色 + }, + ] + }, + borderRadius: [0,99,99,0] + }, + label:{ + show: true, + position: 'outside', + color: '#999', + fontSize: fontSize(11) + } + } + ] + }; + + option && myChart.setOption(option); + window.addEventListener("resize",function (){ + myChart.resize(); + }); + echarts.init(document.getElementById(train1.value)).dispose() + echarts.init(document.getElementById(train3.value)).dispose() + } + + const initTrain3 =()=>{ + let dom = document.getElementById(train3.value); + let myChart = echarts.init(dom); + let option: EChartsOption; + + option = { + tooltip: { + trigger: 'axis', + axisPointer: { + type: 'shadow' + } + }, + grid: { + top: '1%', + left: '2%', + right: '2%', + bottom: '2%', + containLabel: true + }, + xAxis: { + type: 'value', + boundaryGap: [0, 0.01], + axisLine:{ + show: true, + lineStyle:{ + type: 'dotted' + } + }, + axisLabel:{ + color: '#999' + }, + splitLine:{ + show: false + } + }, + yAxis: { + type: 'category', + // data: ['一月', '二月', '三月', '四月', '五月', '六月','七月', '八月', '九月', '十月', '十一月', '十二月'], + data: ['九月', '十月', '十一月', '十二月'], + axisLine:{ + show: true, + lineStyle:{ + color: '#999' + } + }, + axisLabel:{ + color: '#999' + } + }, + series: [ + { + name: '2011', + type: 'bar', + // data: [18203, 23489, 29034, 104970, 131744, 630230, 18203, 23489, 29034, 104970, 131744, 630230] + data: [29034, 104970, 131744, 630230], + barCategoryGap: '50%', + itemStyle:{ + color: { + x: 0, + y: 0, + x2: 1, + y2: 0, + colorStops: [ + { + offset: 0.1, + color: "#2D74C0", // 线处的颜色 + }, + { + offset: 0.9, + color: "#21D9DC", // 坐标轴处的颜色 + }, + ] + }, + borderRadius: [0,99,99,0] + }, + label:{ + show: true, + position: 'outside', + color: '#999', + fontSize: fontSize(11) + } + } + ] + }; + + option && myChart.setOption(option); + window.addEventListener("resize",function (){ + myChart.resize(); + }); + echarts.init(document.getElementById(train1.value)).dispose() + echarts.init(document.getElementById(train2.value)).dispose() + } + + function fontSize(val){ + let nowClientWidth = document.documentElement.clientWidth; + return val * (nowClientWidth/1920) * Number(props.size); + } + + // 页面载入时执行方法 + onMounted(() => { + initTrain1(); + }); + onBeforeUnmount(() =>{ + clearInterval(changeTab) + }) + return { + train1, + train2, + train3, + Search, + fontSize, + ...toRefs(state) + }; + }, + }); +</script> + +<style scoped lang="scss"> + .charts-cont{ + width: 100%; + height: 100%; + padding: 1% 5% 5%; + position: relative; + + .train{ + width: 100%; + height: 100%; + } + } + .home-container { + height: 100%; + overflow: hidden; + position: relative; + .el-row{ + margin-bottom: 20px; + } + .el-row:last-child { + margin-bottom: 0; + } + .el-input{ + width: 100% !important; + } + .el-date-editor::v-deep{ + width: 100%; + } + .el-select{ + width: 100%; + } + .el-cascader{ + width: 100% !important; + } + } +</style> diff --git a/src/views/riskWarningSys/warningBigScreen/index.vue b/src/views/riskWarningSys/warningBigScreen/index.vue new file mode 100644 index 0000000..25941cb --- /dev/null +++ b/src/views/riskWarningSys/warningBigScreen/index.vue @@ -0,0 +1,1043 @@ +<template> + <div id="container" class="dark"> + <div class="warn-dialog" :class="dialogShow"> + <div>预警消息</div> + <p>企业8月份总体安全生产预警指数SPI风险值高于预警阈值,可能存在未处理隐患,请注意查阅相关风险因素,采取风险防控措施。</p> + <span @click="dialogShow = 'hide'">关闭</span> + </div> + <div class="info-panel" :class="dialogHide" @click="openDialog"> + <div class="info-tit"> + <div> + <el-icon><Bell /></el-icon> + <div style="margin-left: 10px">消息预警</div> + </div> + <div @click.stop="dialogHide = 'hide'">X</div> + </div> + <div class="info-desc"> + 企业8月份总体安全生产预警指数SPI风险值高于预警阈值。 + </div> + <div class="info-num"> + 1 + </div> + </div> + <div class="header-content"> + <div class="logo"> + <img v-if="screenTheme.isDark" src="../../../assets/warningScreen/logo_dark.png" alt="" /> + <img v-else="!screenTheme.isDark" src="../../../assets/warningScreen/logo_light.png" alt="" /> + </div> + <div class="title">风险预警预报平台</div> + <div class="title-right"> +<!-- <img src="themeStyle.skinIcon" class="qiehuan" @click="changeTheme" />--> + <span class="datetime">{{currentTime}}</span> + <div class="btns"> + <div class="themeBtn" @click="changeTheme()"> + <img v-if="screenTheme.isDark" src="../../../assets/warningScreen/skin.png"/> + <img v-else src="../../../assets/warningScreen/skin-light.png"/> + </div> + <div class="fullBtn" @click="onScreenfullClick"> + <div class="toFull"> + <i class="iconfont" :title="isScreenfull ? $t('message.user.title6') : $t('message.user.title5')" :class="!isScreenfull ? 'icon-fullscreen' : 'icon-tuichuquanping'"></i> + </div> + <div>全屏</div> + </div> + <div class="backBtn" @click="goBack()"> +<!-- <img src="../../../assets/loginPage/back-icon.png"/>--> + <el-icon><SwitchButton /></el-icon> + <div>退出</div> + </div> + </div> + </div> + </div> + <div class="main-content"> + <div class="main-left"> + <div class="left-top"> + <dv-border-box-13 :backgroundColor="boxBg" :color="boxColor" class="box-bg"></dv-border-box-13> + <div class="part-tit"> + <span>| 事故等级分布</span> +<!-- <img @click="jumpPage(1)" src="../../../assets/warningScreen/small-full.png">--> + <Switch style="width: 1.2rem;height: 1.2rem;cursor: pointer" @click="jumpPage(1)"/> + </div> + <div class="chart-box"> + <accident :size="1" :theme="screenTheme.isDark"></accident> + </div> + </div> + <div class="left-mid"> + <dv-border-box-13 :backgroundColor="boxBg" :color="boxColor" class="box-bg"></dv-border-box-13> + <div class="part-tit"> + <span>| 应急演练次数</span> +<!-- <img @click="jumpPage(2)" src="../../../assets/warningScreen/small-full.png">--> + <Switch style="width: 1.2rem;height: 1.2rem;cursor: pointer" @click="jumpPage(2)"/> + </div> + <div class="chart-box"> + <span class="train-tip">距上次演练结束 5 天</span> + <training class="train-chart" :size="1"></training> + </div> + </div> + <div class="left-bottom"> + <dv-border-box-13 :backgroundColor="boxBg" :color="boxColor" class="box-bg"></dv-border-box-13> + <div class="part-tit"> + <span>| 隐患等级数量分布</span> + <Switch style="width: 1.2rem;height: 1.2rem;cursor: pointer" @click="jumpPage(3)"/> + </div> + <div class="chart-box"> + <risk :size="1" :theme="screenTheme.isDark"></risk> + </div> + </div> + </div> + <div class="main-middle"> + <div class="mid-top"> + <dv-border-box-11 title="SPI数据分析" :backgroundColor="boxBg" :color="boxBigColor" class="box-bg"></dv-border-box-11> + <div class="part-tit" style="position: absolute;top: 8%;padding: 0 4%"> + <div></div> + <Switch style="width: 1.2rem;height: 1.2rem;cursor: pointer" @click="jumpPage(4)"/> + </div> + <div class="chart-box" style="top: 60px;height: calc(100% - 70px)"> + <spi :size="1" :theme="screenTheme.isDark"></spi> + </div> + </div> + <div class="mid-bottom"> + <div class="mid-bot-l"> + <dv-border-box-13 :backgroundColor="boxBg" :color="boxColor" class="box-bg"></dv-border-box-13> + <div class="part-tit"> + <span>| 教育培训分析</span> +<!-- <img @click="jumpPage(5)" src="../../../assets/warningScreen/small-full.png">--> + <Switch style="width: 1.2rem;height: 1.2rem;cursor: pointer" @click="jumpPage(5)"/> + </div> + <div class="chart-box"> + <educate :size="1"></educate> + </div> + </div> + <div class="mid-bot-m"> + <dv-border-box-13 :backgroundColor="boxBg" :color="boxColor" class="box-bg"></dv-border-box-13> + <div class="part-tit"> + <span>| 隐患等级</span> +<!-- <img @click="jumpPage(6)" src="../../../assets/warningScreen/small-full.png">--> + <Switch style="width: 1.2rem;height: 1.2rem;cursor: pointer" @click="jumpPage(6)"/> + </div> + <div class="chart-box"> + <danger :size="1" :theme="screenTheme.isDark"></danger> + </div> + </div> + <div class="mid-bot-r"> + <dv-border-box-13 :backgroundColor="boxBg" :color="boxColor" class="box-bg"></dv-border-box-13> + <div class="part-tit"> + <span>| 人员专业度分布</span> +<!-- <img @click="jumpPage(7)" src="../../../assets/warningScreen/small-full.png">--> + <Switch style="width: 1.2rem;height: 1.2rem;cursor: pointer" @click="jumpPage(7)"/> + </div> + <div class="chart-box"> + <profession :size="1"></profession> + </div> + </div> + </div> + </div> + <div class="main-right"> + <div class="right-top"> + <dv-border-box-13 :backgroundColor="boxBg" :color="boxColor" class="box-bg"></dv-border-box-13> + <div class="part-tit"> + <span>| 预警消息报告</span> +<!-- <img @click="jumpPage(8)" src="../../../assets/warningScreen/small-full.png">--> + <Switch style="width: 1.2rem;height: 1.2rem;cursor: pointer" @click="jumpPage(8)"/> + </div> + <div class="chart-box"> + <message :size="1" :theme="screenTheme.isDark"></message> + </div> + </div> + <div class="right-mid"> + <dv-border-box-13 :backgroundColor="boxBg" :color="boxColor" class="box-bg"></dv-border-box-13> + <div class="part-tit"> + <span>| 特殊作业实时监控</span> +<!-- <img @click="jumpPage(9)" src="../../../assets/warningScreen/small-full.png">--> + <Switch style="width: 1.2rem;height: 1.2rem;cursor: pointer" @click="jumpPage(9)"/> + </div> + <div class="chart-box"> + <monitor></monitor> + </div> + </div> + <div class="right-bottom"> + <dv-border-box-13 :backgroundColor="boxBg" :color="boxColor" class="box-bg"></dv-border-box-13> + <div class="part-tit"> + <span>| 风险应急物资储备</span> + <Switch style="width: 1.2rem;height: 1.2rem;cursor: pointer" @click="jumpPage(10)"/> + </div> + <div class="chart-box"> + <stock :size="1"></stock> + </div> + </div> + </div> + </div> + </div> +</template> + +<script lang="ts"> + import screenfull from 'screenfull'; + import { toRefs, reactive, ref, onMounted, defineComponent, defineAsyncComponent, nextTick, onUnmounted } from 'vue'; + import { ElTable } from 'element-plus'; + import { FormInstance, FormRules, ElMessage } from 'element-plus'; + import { safetyRiskEventApi } from '/@/api/doublePreventSystem/safetyRiskEvent/index.ts'; + import { useRouter } from 'vue-router'; + import {hiddenReportApi} from "/@/api/doublePreventSystem/report"; + import { productionDeviceApi } from '/@/api/doublePreventSystem/productionDevice/index.ts'; + import '/@/theme/bigScreen.css' + import {useScreenTheme} from "/@/stores/screenTheme" + import {storeToRefs} from "pinia"; + + // 定义接口来定义对象的类型 + interface stateType { + boxBg: string; + boxColor: Array<string>; + boxBigColor: Array<string>; + isScreenfull: boolean; + currentTime: string; + spiValue: number; + spiOptions: Array<any>; + dialogShow: string; + dialogHide: string + } + export default defineComponent({ + name: 'warningScreen', + components: { + accident: defineAsyncComponent(() => import('/@/views/riskWarningSys/warningBigScreen/components/accident.vue')), + training: defineAsyncComponent(() => import('/@/views/riskWarningSys/warningBigScreen/components/training.vue')), + spi: defineAsyncComponent(() => import('/@/views/riskWarningSys/warningBigScreen/components/SPI.vue')), + risk: defineAsyncComponent(() => import('/@/views/riskWarningSys/warningBigScreen/components/risk.vue')), + educate: defineAsyncComponent(() => import('/@/views/riskWarningSys/warningBigScreen/components/educate.vue')), + danger: defineAsyncComponent(() => import('/@/views/riskWarningSys/warningBigScreen/components/danger.vue')), + profession: defineAsyncComponent(() => import('/@/views/riskWarningSys/warningBigScreen/components/profession.vue')), + message: defineAsyncComponent(() => import('/@/views/riskWarningSys/warningBigScreen/components/message.vue')), + monitor: defineAsyncComponent(() => import('/@/views/riskWarningSys/warningBigScreen/components/monitor.vue')), + stock: defineAsyncComponent(() => import('/@/views/riskWarningSys/warningBigScreen/components/stock.vue')) + }, + setup() { + const screenThemes = useScreenTheme() + const { screenTheme } = storeToRefs(screenThemes); + const router = useRouter(); + const props = { + expandTrigger: 'hover', + checkStrictly: true + } + const state = reactive<stateType>({ + boxBg: 'rgba(8, 109, 209, 0.2)', + boxColor: [], + boxBigColor: [], + isScreenfull: false, + currentTime: '', + spiValue: 0, + dialogShow: 'hide', + dialogHide: 'showup', + spiOptions: [ + { + value: 0, + label: '公司级别SPI' + }, + { + value: 1, + label: 'A事业部SPI', + children: [ + { + value: 11, + label: 'A车间SPI' + }, + { + value: 12, + label: 'B车间SPI' + }, + { + value: 13, + label: 'C车间SPI' + } + ] + }, + { + value: 2, + label: 'B事业部SPI', + children: [ + { + value: 21, + label: 'D车间SPI' + }, + { + value: 22, + label: 'E车间SPI' + }, + { + value: 23, + label: 'F车间SPI' + } + ] + } + ] + }); + + // 页面载入时执行方法 + onMounted(() => { + getTime() + getTheme() + }); + + const getTime =()=>{ + setInterval(() => { + state.currentTime = new Date().toLocaleString(); + }, 1000); + } + + const changeTheme = () =>{ + screenTheme.value.isDark = !screenTheme.value.isDark + screenThemes.setScreenTheme(screenTheme.value.isDark) + if(screenTheme.value.isDark){ + document.getElementById('container').setAttribute( "class", 'dark' ) + state.boxBg = 'rgba(8, 109, 209, 0.2)' + state.boxColor = [] + state.boxBigColor = [] + }else{ + document.getElementById('container').setAttribute( "class", 'light' ) + state.boxBg = '#fff' + state.boxColor = ['#fff','#ccc'] + state.boxBigColor = ['#999','#fff'] + } + } + + const getTheme =()=>{ + if(screenTheme.value.isDark){ + window.document.getElementById('container').setAttribute( "class", 'dark' ); + state.boxBg = 'rgba(8, 109, 209, 0.2)' + state.boxColor = [] + state.boxBigColor = [] + }else{ + window.document.getElementById('container').setAttribute( "class", 'light' ); + state.boxBg = '#fff' + state.boxColor = ['#fff','#ccc'] + state.boxBigColor = ['#999','#fff'] + } + } + + // 全屏 + const onScreenfullClick = () => { + if (!screenfull.isEnabled) { + ElMessage.warning('暂不不支持全屏'); + return false; + } + screenfull.toggle(); + screenfull.on('change', () => { + if (screenfull.isFullscreen) { + state.isScreenfull = true; + } else { + state.isScreenfull = false; + } + }); + }; + + const openDialog = () => { + if(state.dialogShow == 'hide'){ + state.dialogShow = 'showup' + }else{ + state.dialogShow = 'hide' + } + }; + + const closeInfo = ()=>{ + state.dialogHide = 'hide' + }; + + const jumpPage = (num) =>{ + router.push({ + path: 'screenPage', + query: { + num: num + } + }); + } + + // 返回上一页 + const goBack = () => { + window.history.go(-1); + }; + + // 隐患状态列表 + // const getDeviceRecord = async () => { + // const data = { pageSize: state.pageSize, pageIndex: state.pageIndex}; + // let res = await productionDeviceApi().getProductionDeviceList(data) + // if (res.data.code === '200'){ + // state.deviceData = res.data.data + // } else { + // ElMessage({ + // type: 'warning', + // message: res.data.msg + // }); + // } + // }; + + return { + router, + props, + screenTheme, + openDialog, + closeInfo, + changeTheme, + onScreenfullClick, + jumpPage, + goBack, + ...toRefs(state) + }; + } + }); +</script> + +<style scoped lang="scss"> + $homeNavLengh: 8; + .hide{ + display: none; + } + + .showup{ + display: block; + } + .dark { + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + align-items: center; + background: url('../../../assets/warningScreen/riskprocast.jpg') no-repeat center; + background-size: 100% 100%; + color: #11FEEE; + + .warn-dialog{ + position: absolute; + z-index: 999999; + top: 25%; + left: 50%; + width: 50%; + height: 50%; + transform: translateX(-50%); + border-radius: 8px; + transition: .3s; + box-shadow: 0 15px 30px rgba(0,0,0,.2); + border: 1px solid rgba(17,254,238,.4); + padding: 1.5rem; + background: rgba(0,16,32,.8); + + div{ + font-size: 1.5rem; + text-align: center; + } + + p{ + margin-top: 20px; + font-size: 1.125rem; + line-height: 28px; + text-align: left + } + + span{ + position: inherit; + right: 20px; + top: 20px; + font-size: 1rem; + cursor: pointer; + } + } + + .info-panel{ + position: absolute; + width: 20%; + right: 50px; + bottom: 50px; + z-index: 9999999; + font-size: 1rem; + padding: 0 10px; + border-radius: 4px; + cursor: pointer; + box-shadow: 0 15px 30px rgba(0,0,0,.2); + border: 1px solid rgba(17,254,238,.4); + background: rgba(0,16,32,.8); + + .info-tit{ + display: flex; + align-items: center; + padding: 10px; + border-bottom: 1px solid rgba(17,254,238,.4); + justify-content: space-between; + + &>div{ + display: flex; + align-items: center; + + img{ + width: 18px; + height: 18px; + margin-right: 10px; + } + } + } + + .info-desc{ + padding: 15px 10px; + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; + } + .info-num{ + position: inherit; + width: 24px; + height: 24px; + line-height: 24px; + text-align: center; + left: -12px; + top: -12px; + color: #fff; + z-index: 999999999; + border-radius: 50%; + border: 1px solid #ff0000; + background: #ff0000; + } + } + + .header-content { + width: 100%; + height: 7.8%; + padding: 0 20px; + font-size: 1.25rem; + display: flex; + align-items: center; + justify-content: space-around; + z-index: 9; + + .logo { + width: 27%; + display: flex; + align-items: center; + justify-content: center; + img { + width: 10rem; + height: auto; + } + } + .title { + width: 46%; + font-size: 2rem; + font-weight: bolder; + line-height: 7.8%; + text-align: center; + letter-spacing: 2px; + } + + .title-right { + width: 27%; + height: 90px; + display: flex; + align-items: center; + justify-content: space-around; + font-size: 1rem; + padding-left: 30px; + + .datetime { + color: #11FEEE; + font-size: 0.9rem; + } + .btns{ + display: flex; + align-items: center; + + &>div{ + display: flex; + align-items: center; + font-size: 1rem; + margin-right: 20px; + + img{ + width: 1rem; + height: 1rem; + } + div{ + margin-left: 0.4rem; + font-size: 0.9rem; + } + } + .themeBtn{ + img{ + width: 1.25rem; + height: 1.25rem; + } + cursor: pointer; + } + .fullBtn{ + cursor: pointer; + } + .backBtn{ + cursor: pointer; + } + } + } + } + .main-content{ + width: 100%; + height: calc(100vh - 7.8%); + padding: 0.4rem 1.5rem 2rem; + display: flex; + align-items: center; + justify-content: space-between; + + &>div{ + height: 100%; + display: flex; + flex-direction: column; + justify-content: space-between; + align-items: flex-start; + &>div{ + padding: 20px 15px 10px; + box-sizing: border-box; + position: relative; + .box-bg{ + position: absolute; + width: 100%; + height: 100%; + left: 0; + top: 0; + right: 0; + bottom: 0; + margin: auto; + color: #11feee; + font-weight: bolder; + } + + .dv-border-box-11{ + ::v-deep(.dv-border-svg-container){ + .dv-border-box-11-title{ + font-size: 1.5rem; + fill: #11feee !important; + } + } + } + .part-tit{ + position: absolute; + top: 20px; + left: 0; + height: 20px; + width: 100%; + padding: 0 15px; + display: flex; + justify-content: space-between; + align-items: center; + z-index: 9999; + + span{ + font-size: 1.25rem; + font-weight: bolder; + color: #11feee; + } + + img{ + width: 1.2rem; + height: 1.2rem; + cursor: pointer; + } + } + .chart-box{ + position: absolute; + top: 40px; + bottom: 0; + left: 0; + right: 0; + width: 100%; + height: calc(100% - 50px); + z-index: 99999; + .train-tip{ + display: block; + font-size: 0.8rem; + margin-top: 2%; + margin-left: 5%; + color: #fff; + height: 1rem; + } + + .train-chart{ + width: 100%; + height: calc(100% - 1rem); + } + } + } + } + + .main-left{ + width: calc(25% - 5px); + &>div{ + width: 100%; + height: calc((100%/3) - (20px/3)); + } + } + .main-middle{ + width: calc(50% - 10px); + + .mid-top{ + width: 100%; + height: calc((200% - 40px)/3 + 10px); + } + + .mid-bottom{ + display: flex; + width: 100%; + height: calc((100%/3) - (20px/3)); + justify-content: space-between; + padding: 0; + background: none; + border-radius: 0; + + &>div { + position: relative; + width: calc((100% - 20px)/3); + border-radius: 8px; + overflow: hidden; + padding: 10px 15px; + box-sizing: border-box; + } + } + } + .main-right{ + width: calc(25% - 5px); + &>div{ + width: 100%; + height: calc((100%/3) - (20px/3)); + } + } + } + } + .light { + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + align-items: center; + background: url('../../../assets/warningScreen/riskprocast-light.jpg') no-repeat center; + background-size: 100% 100%; + color: #000; + + .warn-dialog{ + position: absolute; + z-index: 999999; + top: 25%; + left: 50%; + width: 50%; + height: 50%; + transform: translateX(-50%); + border-radius: 8px; + transition: .3s; + box-shadow: 0 15px 30px rgba(0,0,0,.2); + border: 1px solid #ccc; + padding: 1.5rem; + background: #fff; + + div{ + font-size: 1.5rem; + text-align: center; + } + + p{ + margin-top: 20px; + font-size: 1.125rem; + line-height: 28px; + text-align: left + } + + span{ + position: inherit; + right: 20px; + top: 20px; + font-size: 1rem; + cursor: pointer; + } + } + + .info-panel{ + position: absolute; + width: 20%; + right: 50px; + bottom: 50px; + z-index: 9999999; + font-size: 1rem; + color: #333; + padding: 0 10px; + border-radius: 4px; + cursor: pointer; + box-shadow: 0 15px 30px rgba(0,0,0,.2); + border: 1px solid #ccc; + background: #fff; + + .info-tit{ + display: flex; + align-items: center; + padding: 10px; + border-bottom: 1px solid #ccc; + justify-content: space-between; + + &>div{ + display: flex; + align-items: center; + + img{ + width: 18px; + height: 18px; + margin-right: 10px; + } + } + } + + .info-desc{ + padding: 15px 10px; + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; + } + .info-num{ + position: inherit; + width: 24px; + height: 24px; + line-height: 24px; + text-align: center; + left: -12px; + top: -12px; + color: #fff; + z-index: 999999999; + border-radius: 50%; + border: 1px solid #ff0000; + background: #ff0000; + } + } + + .header-content { + width: 100%; + height: 7.8%; + padding: 0 20px; + font-size: 1.25rem; + display: flex; + align-items: center; + justify-content: space-around; + z-index: 9; + + .logo { + width: 27%; + display: flex; + align-items: center; + justify-content: center; + img { + width: 10rem; + height: auto; + } + } + .title { + width: 46%; + font-size: 2rem; + font-weight: bolder; + line-height: 7.8%; + text-align: center; + letter-spacing: 2px; + } + + .title-right { + width: 27%; + height: 90px; + display: flex; + align-items: center; + justify-content: space-around; + font-size: 1rem; + padding-left: 30px; + + .datetime { + color: #000; + font-size: 0.9rem; + } + .btns{ + display: flex; + align-items: center; + + &>div{ + display: flex; + align-items: center; + font-size: 1rem; + margin-right: 20px; + + img{ + width: 1rem; + height: 1rem; + } + div{ + margin-left: 0.4rem; + font-size: 0.9rem; + } + } + .themeBtn{ + img{ + width: 1.25rem; + height: 1.25rem; + } + cursor: pointer; + } + .fullBtn{ + cursor: pointer; + } + .backBtn{ + cursor: pointer; + } + } + } + } + .main-content{ + width: 100%; + height: calc(100vh - 7.8%); + padding: 0.4rem 1.5rem 2rem; + display: flex; + align-items: center; + justify-content: space-between; + + &>div{ + height: 100%; + display: flex; + flex-direction: column; + justify-content: space-between; + align-items: flex-start; + &>div{ + padding: 20px 15px 10px; + box-sizing: border-box; + position: relative; + .box-bg{ + position: absolute; + width: 100%; + height: 100%; + left: 0; + top: 0; + right: 0; + bottom: 0; + margin: auto; + color: #000; + font-weight: bolder; + } + + .dv-border-box-11{ + :deep(.dv-border-svg-container){ + .dv-border-box-11-title{ + font-size: 1.5rem; + fill: #000 !important; + } + } + } + .part-tit{ + position: absolute; + top: 20px; + left: 0; + height: 20px; + width: 100%; + padding: 0 15px; + display: flex; + justify-content: space-between; + align-items: center; + z-index: 9999; + span{ + font-size: 1.25rem; + font-weight: bolder; + color: #000; + } + + img{ + width: 1.20rem; + height: 1.20rem; + cursor: pointer; + } + } + .chart-box{ + position: absolute; + top: 40px; + bottom: 0; + left: 0; + right: 0; + width: 100%; + height: calc(100% - 50px); + z-index: 99999; + .train-tip{ + display: block; + font-size: 0.8rem; + margin-top: 2%; + margin-left: 5%; + color: #333; + height: 1rem; + } + + .train-chart{ + width: 100%; + height: calc(100% - 1rem); + } + } + } + } + + .main-left{ + width: calc(25% - 5px); + + .left-top{ + width: 100%; + height: calc((100%/3) - (20px/3)); + + } + .left-mid{ + width: 100%; + height: calc((100%/3) - (20px/3)); + } + .left-bottom{ + width: 100%; + height: calc((100%/3) - (20px/3)); + } + } + .main-middle{ + width: calc(50% - 10px); + + .mid-top{ + width: 100%; + height: calc((200% - 40px)/3 + 10px); + } + + .mid-bottom{ + display: flex; + width: 100%; + height: calc((100%/3) - (20px/3)); + justify-content: space-between; + padding: 0; + background: none; + border-radius: 0; + + &>div { + position: relative; + width: calc((100% - 20px)/3); + border-radius: 8px; + overflow: hidden; + padding: 10px 15px; + box-sizing: border-box; + } + } + } + .main-right{ + width: calc(25% - 5px); + + .right-top{ + width: 100%; + height: calc((100%/3) - (20px/3)); + } + .right-mid{ + width: 100%; + height: calc((100%/3) - (20px/3)); + } + .right-bottom{ + width: 100%; + height: calc((100%/3) - (20px/3)); + } + } + } + } + .el-input { + width: 100% !important; + } + .el-date-editor::v-deep { + width: 100%; + } + .el-select { + width: 100%; + } +</style> \ No newline at end of file diff --git a/src/views/riskWarningSys/warningBigScreen/indexs/index.vue b/src/views/riskWarningSys/warningBigScreen/indexs/index.vue new file mode 100644 index 0000000..c037e1c --- /dev/null +++ b/src/views/riskWarningSys/warningBigScreen/indexs/index.vue @@ -0,0 +1,470 @@ +<template> + <div id="pageCont" class="dark-page"> + <div class="btns"> + <dv-decoration-11 :color="lineColor" @click="goBack()"> + <div color-green font-600 bg="~ dark/0"> + 返回 + </div> + </dv-decoration-11> + </div> + + <div class="tit"> + <div class="title">{{curChart===1?'事故等级分布':curChart===2?'应急演练次数':curChart===3?'隐患等级数量分布':curChart===4?'SPI数据分析':curChart===5?'教育培训分析':curChart===6?'隐患等级':curChart===7?'人员专业度分布':curChart===8?'预警消息报告':curChart===9?'特殊作业实时监控':'风险应急物资储备'}}</div> + </div> + <div class="chart-cont"> + <div class="chart"> + <div v-show="curChart===2" class="selector-2">距上次演练结束5天</div> + <accident v-if="curChart===1" :size="2.5"></accident> + <training v-else-if="curChart===2" :size="2.5"></training> + <risk v-else-if="curChart===3" :month="month" :size="2.5"></risk> + <spi v-else-if="curChart===4" :size="2"></spi> + <educate v-else-if="curChart===5" :size="2.5"></educate> + <danger v-else-if="curChart===6" :size="2.5"></danger> + <profession v-else-if="curChart===7" :size="2.5"></profession> + <message v-else-if="curChart===8" :size="2"></message> + <monitor v-else-if="curChart===9" :size="2.5"></monitor> + <stock v-else class="main-chart" :size="2"></stock> + </div> + <div class="chart-right"> + <dv-decoration-10 :color="lineColor" style="width:100%;height:5%;" /> + <div class="charts-des"> + <div class="des-tit"> + <div v-if="curChart===1">2022年度事故等级分布与影响一览</div> + <div v-else-if="curChart===2">应急演练概况</div> + <div v-else-if="curChart===3">隐患影响等级分布详情</div> + <div v-else-if="curChart===4">2022年度事企业SPI趋势</div> + <div v-else-if="curChart===5">教育培训情况汇总</div> + <div v-else-if="curChart===6">隐患等级分布与隐患整改率</div> + <div v-else-if="curChart===7">人员持证上岗情况</div> + <div v-else-if="curChart===8">预警消息SPI报告-2022年8月</div> + <div v-else-if="curChart===9">监控列表</div> + <div v-else>当前应急物资储备情况(总)</div> + <dv-decoration8 :color="lineColor" :reverse="true" style="width:100%;" /> + </div> + <div v-if="curChart===2" class="des-main"> + <div> + <h4>距上次【<span>{{trainDesc.title}}</span>】应急演练结束<span>{{trainDesc.total}}</span>天</h4> + <h4> + 应急演练分月情况汇总: + </h4> + <p v-for="(item,index) in trainDesc.list" :key="index">{{item.month}}应急演练次数:{{item.num}}次</p> + </div> + </div> + <div v-else class="des-main"> + <div v-for="(item,index) in accidentDesc" :key="index"> + <h4><span>{{item.title}}</span>共计:<span>{{item.total}}</span>起</h4> + <h4> + 事故影响 + </h4> + <p>{{item.desc}}</p> + </div> + </div> + </div> + <dv-decoration-10 :color="lineColor" style="width:100%;height:5%;" /> + </div> + </div> + </div> +</template> + +<script lang="ts"> + import screenfull from 'screenfull'; + import { toRefs, reactive, ref, onMounted, defineComponent, defineAsyncComponent, nextTick, onUnmounted } from 'vue'; + import { ElTable } from 'element-plus'; + import { FormInstance, FormRules, ElMessage } from 'element-plus'; + import { safetyRiskEventApi } from '/@/api/doublePreventSystem/safetyRiskEvent/index.ts'; + import { useRoute } from 'vue-router'; + import {hiddenReportApi} from "/@/api/doublePreventSystem/report"; + import { productionDeviceApi } from '/@/api/doublePreventSystem/productionDevice/index.ts'; + import '/@/theme/bigScreen.css' + import {useScreenTheme} from "/@/stores/screenTheme" + import {storeToRefs} from "pinia"; + + // 定义接口来定义对象的类型 + interface stateType { + isScreenfull: boolean; + curChart: number | null; + lineColor: Array<string>; + accidentDesc: Array<any>; + trainDesc: Object; + } + export default defineComponent({ + name: 'warningPage', + components: { + accident: defineAsyncComponent(() => import('/@/views/riskWarningSys/warningBigScreen/components/accident.vue')), + training: defineAsyncComponent(() => import('/@/views/riskWarningSys/warningBigScreen/components/training.vue')), + spi: defineAsyncComponent(() => import('/@/views/riskWarningSys/warningBigScreen/components/SPI.vue')), + risk: defineAsyncComponent(() => import('/@/views/riskWarningSys/warningBigScreen/components/risk.vue')), + educate: defineAsyncComponent(() => import('/@/views/riskWarningSys/warningBigScreen/components/educate.vue')), + danger: defineAsyncComponent(() => import('/@/views/riskWarningSys/warningBigScreen/components/danger.vue')), + profession: defineAsyncComponent(() => import('/@/views/riskWarningSys/warningBigScreen/components/profession.vue')), + message: defineAsyncComponent(() => import('/@/views/riskWarningSys/warningBigScreen/components/message.vue')), + monitor: defineAsyncComponent(() => import('/@/views/riskWarningSys/warningBigScreen/components/monitor.vue')), + stock: defineAsyncComponent(() => import('/@/views/riskWarningSys/warningBigScreen/components/stock.vue')) + }, + setup() { + const screenThemes = useScreenTheme() + const { screenTheme } = storeToRefs(screenThemes); + const route = useRoute(); + const state = reactive<stateType>({ + isScreenfull: false, + curChart: null, + lineColor: ['#11FEEE'], + accidentDesc:[ + { + title: '特别重大事故', + total: 10, + desc: '死亡人数:0人; 重伤人数:2人; 轻伤人数:3人; 直接经济损失:180.61万元' + }, + { + title: '重大事故', + total: 20, + desc: '死亡人数:1人; 重伤人数:6人; 轻伤人数:0人; 直接经济损失:160.61万元' + }, + { + title: '较大事故', + total: 100, + desc: '死亡人数:0人; 重伤人数:0人; 轻伤人数:3人; 直接经济损失:190.61万元' + }, + { + title: '一般事故', + total: 130, + desc: '死亡人数:0人; 重伤人数:0人; 轻伤人数:0人; 直接经济损失:180.61万元' + }, + { + title: '未遂事故', + total: 150, + desc: '死亡人数:0人; 重伤人数:0人; 轻伤人数:0人; 直接经济损失:9万元' + } + ], + trainDesc:{ + title: '公司级', + total: 5, + list: [ + { + month: '一月份', + num: 23 + }, + { + month: '二月份', + num: 76 + }, + { + month: '三月份', + num: 152 + }, + { + month: '四月份', + num: 200 + }, + { + month: '五月份', + num: 49 + }, + { + month: '六月份', + num: 83 + }, + { + month: '七月份', + num: 102 + }, + { + month: '八月份', + num: 99 + } + ] + } + }); + + // 页面载入时执行方法 + onMounted(() => { + if (route.query.num) { + state.curChart = Number(route.query.num) + } + getTheme() + }); + + + // 全屏 + const onScreenfullClick = () => { + if (!screenfull.isEnabled) { + ElMessage.warning('暂不不支持全屏'); + return false; + } + screenfull.toggle(); + screenfull.on('change', () => { + if (screenfull.isFullscreen) { + state.isScreenfull = true; + } else { + state.isScreenfull = false; + } + }); + }; + const getTheme =()=>{ + if(screenTheme.value.isDark){ + window.document.getElementById('pageCont').setAttribute( "class", 'dark-page' ); + state.lineColor = ['#11FEEE'] + }else{ + window.document.getElementById('pageCont').setAttribute( "class", 'light-page' ); + state.lineColor = ['#333','#ccc'] + } + } + // 返回上一页 + const goBack = () => { + window.history.go(-1); + }; + + + return { + route, + onScreenfullClick, + goBack, + ...toRefs(state) + }; + } + }); +</script> + +<style scoped lang="scss"> + .dark-page{ + width: 100%; + height: 100%; + border:1px #5a5959 solid; + background: url('../../../../assets/warningScreen/body-bg.jpg'); + padding: 4%; + .btns{ + position: fixed; + width: 8%; + height: 6%; + right: 5%; + top: 1.25rem; + font-size: 1.125rem; + color: rgb(17, 254, 238); + cursor: pointer; + } + .tit{ + width: 100%; + height: 122px; + background: url("../../../../assets/warningScreen/pagebg-t.png") no-repeat center; + background-size: 100% 100%; + + + .title{ + width: 100%; + height: 122px; + line-height: 112px; + border-radius: 8px; + margin-bottom: 20px; + font-size: 2.8rem; + color: #11feee; + font-weight: bolder; + text-align: center; + letter-spacing: 5px; + } + } + + .chart-cont{ + width: 100%; + padding: 20px; + height: calc(100% - 122px); + display: flex; + align-items: flex-start; + justify-content: space-between; + + .chart{ + width: calc((100% - 20px) * 0.63); + height: 100%; + padding: 3%; + background: url("../../../../assets/warningScreen/pagebg-l.png") no-repeat center; + background-size: 100% 100%; + position: relative; + .selector-2{ + position: absolute; + top: 5%; + right: 10%; + width: 20%; + font-size: 1.25rem; + color: #fff; + } + .main-chart{ + width: 100%; + height: 100%; + } + } + .chart-right{ + width: calc((100% - 20px) * 0.37); + height: 100%; + .charts-des{ + height: 90%; + background: url("../../../../assets/warningScreen/pagebg-r.png") no-repeat center; + background-size: 100% 100%; + padding: 4%; + + .des-tit{ + width: 100%; + &>div{ + font-size: 1.5rem; + height: 2.2rem; + line-height: 2.2rem; + text-align: center; + font-weight: bolder; + color: #11FEEE; + } + } + .des-main{ + width: 100%; + height: calc(96% - 2.2rem); + padding: 0 2%; + overflow: auto; + color: #11FEEE; + + &::-webkit-scrollbar { width: 0; height: 0; color: transparent; } + &::scrollbar { width: 0; height: 0; color: transparent; } + + &>div{ + margin-bottom: 2rem; + &>h4{ + font-size: 1.25rem; + display: flex; + align-items: center; + + span{ + margin-right: 10px; + } + &:first-of-type{ + margin-bottom: 10px; + } + } + + &>p{ + font-size: 1rem; + margin-top: 10px; + } + } + } + } + } + + } + } + .light-page{ + width: 100%; + height: 100%; + border:1px #5a5959 solid; + background: #F0F0F0; + padding: 4%; + .btns{ + position: fixed; + width: 8%; + height: 6%; + right: 5%; + top: 1.25rem; + font-size: 1.125rem; + color: #333; + cursor: pointer; + } + .tit{ + width: 100%; + height: 122px; + background: url("../../../../assets/warningScreen/pagebg-t-light.png") no-repeat center; + background-size: 100% 100%; + + + .title{ + width: 100%; + height: 122px; + line-height: 112px; + border-radius: 8px; + margin-bottom: 20px; + font-size: 2.8rem; + color: #333; + font-weight: bolder; + text-align: center; + letter-spacing: 5px; + } + } + + .chart-cont{ + width: 100%; + padding: 20px; + height: calc(100% - 122px); + display: flex; + align-items: flex-start; + justify-content: space-between; + + .chart{ + width: calc((100% - 20px) * 0.63); + height: 100%; + padding: 3%; + background: url("../../../../assets/warningScreen/pagebg-l-light.png") no-repeat center; + background-size: 100% 100%; + position: relative; + .selector-2{ + position: absolute; + top: 5%; + right: 10%; + width: 20%; + font-size: 1.25rem; + color: #fff; + } + .main-chart{ + width: 100%; + height: 100%; + } + } + .chart-right{ + width: calc((100% - 20px) * 0.37); + height: 100%; + .charts-des{ + height: 90%; + background: url("../../../../assets/warningScreen/pagebg-r-light.png") no-repeat center; + background-size: 100% 100%; + padding: 4%; + + .des-tit{ + width: 100%; + &>div{ + font-size: 1.5rem; + height: 2.2rem; + line-height: 2.2rem; + text-align: center; + font-weight: bolder; + color: #333; + } + } + .des-main{ + width: 100%; + height: calc(96% - 2.2rem); + padding: 0 2%; + overflow: auto; + color: #333; + + &::-webkit-scrollbar { width: 0; height: 0; color: transparent; } + + &>div{ + margin-bottom: 2rem; + &>h4{ + font-size: 1.25rem; + display: flex; + align-items: center; + + span{ + margin-right: 10px; + } + &:first-of-type{ + margin-bottom: 10px; + } + } + + &>p{ + font-size: 1rem; + margin-top: 10px; + } + } + } + } + } + + } + } +</style> \ No newline at end of file diff --git a/src/views/riskWarningSys/warningBigScreen/indexs/msgDetail.vue b/src/views/riskWarningSys/warningBigScreen/indexs/msgDetail.vue new file mode 100644 index 0000000..c30b03e --- /dev/null +++ b/src/views/riskWarningSys/warningBigScreen/indexs/msgDetail.vue @@ -0,0 +1,137 @@ +<template> + <div id="pageCont" class="dark-page"> + <div class="btns"> + <dv-decoration-11 :color="lineColor" @click="goBack()"> + <div color-green font-600 bg="~ dark/0"> + 返回 + </div> + </dv-decoration-11> + </div> + <dv-decoration7 :color="lineColor" style="width:100%;height:6%;margin-bottom: 20px"> + <div class="msgTit"> + {{title}} + </div> + </dv-decoration7> + <dv-border-box1 :color="lineColor" style="width: 100%;height: calc(100% - 20px)"> + + </dv-border-box1> + </div> +</template> + +<script lang="ts"> + import screenfull from 'screenfull'; + import { toRefs, reactive, ref, onMounted, defineComponent, defineAsyncComponent, nextTick, onUnmounted } from 'vue'; + import { ElTable } from 'element-plus'; + import { FormInstance, FormRules, ElMessage } from 'element-plus'; + import { safetyRiskEventApi } from '/@/api/doublePreventSystem/safetyRiskEvent/index.ts'; + import { useRoute } from 'vue-router'; + import {hiddenReportApi} from "/@/api/doublePreventSystem/report"; + import { productionDeviceApi } from '/@/api/doublePreventSystem/productionDevice/index.ts'; + import '/@/theme/bigScreen.css' + import {useScreenTheme} from "/@/stores/screenTheme" + import {storeToRefs} from "pinia"; + + // 定义接口来定义对象的类型 + interface stateType { + lineColor: Array<string>, + title: string | null + } + export default defineComponent({ + name: 'msgDetail', + components: { + + }, + setup() { + const screenThemes = useScreenTheme() + const { screenTheme } = storeToRefs(screenThemes); + const route = useRoute(); + const state = reactive<stateType>({ + lineColor: ['#11FEEE'], + title: '' + }); + + // 页面载入时执行方法 + onMounted(() => { + if (route.query.row) { + state.title = route.query.row[1] + } + getTheme() + }); + + + + const getTheme =()=>{ + if(screenTheme.value.isDark){ + window.document.getElementById('pageCont').setAttribute( "class", 'dark-page' ); + state.lineColor = ['#11FEEE'] + }else{ + window.document.getElementById('pageCont').setAttribute( "class", 'light-page' ); + state.lineColor = ['#333','#ccc'] + } + } + + // 返回上一页 + const goBack = () => { + window.history.go(-1); + }; + + + return { + route, + goBack, + ...toRefs(state) + }; + } + }); +</script> + +<style scoped lang="scss"> + .dark-page{ + width: 100%; + height: 100%; + border:1px #5a5959 solid; + background: url('../../../../assets/warningScreen/body-bg.jpg'); + padding: 1.25rem 4% 4%; + .btns{ + position: fixed; + width: 8%; + height: 6%; + right: 5%; + top: 1.25rem; + display: flex; + align-items: center; + font-size: 1.125rem; + color: rgb(17, 254, 238); + cursor: pointer; + } + .msgTit{ + font-size: 2rem; + color: rgb(17, 254, 238); + margin: 0 4rem; + } + } + .light-page{ + width: 100%; + height: 100%; + border:1px #5a5959 solid; + background: #F0F0F0; + padding: 1.25rem 4% 4%; + .btns{ + position: fixed; + width: 8%; + height: 6%; + right: 5%; + top: 1.25rem; + display: flex; + align-items: center; + font-size: 1.125rem; + color: #333; + cursor: pointer; + } + .msgTit{ + font-size: 2rem; + color: #333; + margin: 0 4rem; + } + } +</style> \ No newline at end of file diff --git a/src/views/safeKnowledge/bmgz/index.vue b/src/views/safeKnowledge/bmgz/index.vue new file mode 100644 index 0000000..39c6175 --- /dev/null +++ b/src/views/safeKnowledge/bmgz/index.vue @@ -0,0 +1,31 @@ +<template> + <div class="home-container"> + <iframe src="http://39.104.85.193/bmgz"></iframe> + </div> +</template> + +<script> +export default { + name: 'safeKnowledgeSys', + props: {}, + data() { + return {}; + }, + created() {}, + methods: {} +}; +</script> + +<!-- Add "scoped" attribute to limit CSS to this components only --> +<style scoped lang="scss"> +.home-container { + height: calc(100vh - 144px); + box-sizing: border-box; + overflow: hidden; + iframe { + width: 100%; + height: 100%; + border: none; + } +} +</style> diff --git a/src/views/safeKnowledge/df/index.vue b/src/views/safeKnowledge/df/index.vue new file mode 100644 index 0000000..3bfefee --- /dev/null +++ b/src/views/safeKnowledge/df/index.vue @@ -0,0 +1,40 @@ +<template> + <div class="home-container"> + <iframe src="http://39.104.85.193/df"></iframe> + </div> +</template> + +<script> +export default { + name: 'safeKnowledgeSys', + props: { + + }, + data(){ + return{ + + } + }, + created() { + + }, + methods:{ + + } +} +</script> + +<!-- Add "scoped" attribute to limit CSS to this components only --> +<style scoped lang="scss"> + .home-container{ + height: calc(100vh - 144px); + box-sizing: border-box; + overflow: hidden; + + iframe{ + width: 100%; + height: 100%; + border: none; + } + } +</style> diff --git a/src/views/safeKnowledge/index.vue b/src/views/safeKnowledge/index.vue new file mode 100644 index 0000000..c90267a --- /dev/null +++ b/src/views/safeKnowledge/index.vue @@ -0,0 +1,40 @@ +<template> + <div class="home-container"> + <iframe src="http://39.104.85.193"></iframe> + </div> +</template> + +<script> +export default { + name: 'safeKnowledgeSys', + props: { + + }, + data(){ + return{ + + } + }, + created() { + + }, + methods:{ + + } +} +</script> + +<!-- Add "scoped" attribute to limit CSS to this components only --> +<style scoped lang="scss"> + .home-container{ + height: calc(100vh - 144px); + box-sizing: border-box; + overflow: hidden; + + iframe{ + width: 100%; + height: 100%; + border: none; + } + } +</style> diff --git a/src/views/safeKnowledge/inner/index.vue b/src/views/safeKnowledge/inner/index.vue new file mode 100644 index 0000000..bef7f39 --- /dev/null +++ b/src/views/safeKnowledge/inner/index.vue @@ -0,0 +1,40 @@ +<template> + <div class="home-container"> + <iframe src="http://39.104.85.193/inner"></iframe> + </div> +</template> + +<script> +export default { + name: 'safeKnowledgeSys', + props: { + + }, + data(){ + return{ + + } + }, + created() { + + }, + methods:{ + + } +} +</script> + +<!-- Add "scoped" attribute to limit CSS to this components only --> +<style scoped lang="scss"> + .home-container{ + height: calc(100vh - 144px); + box-sizing: border-box; + overflow: hidden; + + iframe{ + width: 100%; + height: 100%; + border: none; + } + } +</style> diff --git a/src/views/safeKnowledge/internationalRules/index.vue b/src/views/safeKnowledge/internationalRules/index.vue new file mode 100644 index 0000000..083cfbb --- /dev/null +++ b/src/views/safeKnowledge/internationalRules/index.vue @@ -0,0 +1,40 @@ +<template> + <div class="home-container"> + <iframe src="http://39.104.85.193/law"></iframe> + </div> +</template> + +<script> +export default { + name: 'safeKnowledgeSys', + props: { + + }, + data(){ + return{ + + } + }, + created() { + + }, + methods:{ + + } +} +</script> + +<!-- Add "scoped" attribute to limit CSS to this components only --> +<style scoped lang="scss"> + .home-container{ + height: calc(100vh - 144px); + box-sizing: border-box; + overflow: hidden; + + iframe{ + width: 100%; + height: 100%; + border: none; + } + } +</style> diff --git a/src/views/safeKnowledge/law/index.vue b/src/views/safeKnowledge/law/index.vue new file mode 100644 index 0000000..84b233c --- /dev/null +++ b/src/views/safeKnowledge/law/index.vue @@ -0,0 +1,40 @@ +<template> + <div class="home-container"> + <iframe src="http://39.104.85.193/gong"></iframe> + </div> +</template> + +<script> +export default { + name: 'safeKnowledgeSys', + props: { + + }, + data(){ + return{ + + } + }, + created() { + + }, + methods:{ + + } +} +</script> + +<!-- Add "scoped" attribute to limit CSS to this components only --> +<style scoped lang="scss"> + .home-container{ + height: calc(100vh - 144px); + box-sizing: border-box; + overflow: hidden; + + iframe{ + width: 100%; + height: 100%; + border: none; + } + } +</style> diff --git a/src/views/safeKnowledge/sfjs/index.vue b/src/views/safeKnowledge/sfjs/index.vue new file mode 100644 index 0000000..21348b6 --- /dev/null +++ b/src/views/safeKnowledge/sfjs/index.vue @@ -0,0 +1,40 @@ +<template> + <div class="home-container"> + <iframe src="http://39.104.85.193/laws"></iframe> + </div> +</template> + +<script> +export default { + name: 'safeKnowledgeSys', + props: { + + }, + data(){ + return{ + + } + }, + created() { + + }, + methods:{ + + } +} +</script> + +<!-- Add "scoped" attribute to limit CSS to this components only --> +<style scoped lang="scss"> + .home-container{ + height: calc(100vh - 144px); + box-sizing: border-box; + overflow: hidden; + + iframe{ + width: 100%; + height: 100%; + border: none; + } + } +</style> diff --git a/src/views/safeKnowledge/xzfg/index.vue b/src/views/safeKnowledge/xzfg/index.vue new file mode 100644 index 0000000..263ec2d --- /dev/null +++ b/src/views/safeKnowledge/xzfg/index.vue @@ -0,0 +1,40 @@ +<template> + <div class="home-container"> + <iframe src="http://39.104.85.193/xzfg"></iframe> + </div> +</template> + +<script> +export default { + name: 'safeKnowledgeSys', + props: { + + }, + data(){ + return{ + + } + }, + created() { + + }, + methods:{ + + } +} +</script> + +<!-- Add "scoped" attribute to limit CSS to this components only --> +<style scoped lang="scss"> + .home-container{ + height: calc(100vh - 144px); + box-sizing: border-box; + overflow: hidden; + + iframe{ + width: 100%; + height: 100%; + border: none; + } + } +</style> diff --git a/src/views/specialWorkSystem/alarm/zyyjjl/index.vue b/src/views/specialWorkSystem/alarm/zyyjjl/index.vue new file mode 100644 index 0000000..0505b81 --- /dev/null +++ b/src/views/specialWorkSystem/alarm/zyyjjl/index.vue @@ -0,0 +1,364 @@ +<template> + <div class="home-container"> + <div style="height: 100%"> + <el-row class="homeCard"> + <el-col :span="6" style="display:flex;align-items: center"> + <span style="white-space: nowrap">作业证编号:</span> + <div class="grid-content topInfo"> + <el-input v-model="searchWord"></el-input> + </div> + </el-col> + <el-col :span="6" style="display:flex;align-items: center"> + <span style="white-space: nowrap">作业类型:</span> + <div class="grid-content topInfo"> + <el-select v-model="searchType" placeholder="请选择作业类型"> + <el-option + v-for="item in workTypeList" + :key="item.id" + :label="item.name" + :value="item.id" + /> + </el-select> + </div> + </el-col> + <el-col :span="6" style="display:flex;align-items: center"> + <span style="white-space: nowrap">预警类型:</span> + <div class="grid-content topInfo"> + <el-select v-model="warningType" placeholder="请选择预警类型"> + <el-option + v-for="item in alertTypeList" + :key="item.id" + :label="item.name" + :value="item.id" + /> + </el-select> + </div> + </el-col> + <el-button type="primary" @click="searchRecord">查询</el-button> + <el-button plain @click="clearSearch">重置</el-button> + </el-row> + <div class="homeCard"> + <div class="main-card"> +<!-- <el-row class="cardTop">--> +<!-- <el-col :span="12" class="mainCardBtn">--> +<!-- <el-button type="primary" :icon="Plus" size="default" @click="dialogAddRecord = true">新增</el-button>--> +<!-- </el-col>--> +<!-- <el-button type="primary" :icon="Refresh" size="default" @click="reLoadData"/>--> +<!-- </el-row>--> + <el-table + ref="multipleTableRef" + :data="tableData" + style="width: 100%" + height="calc(100% - 48px)" + :header-cell-style="{background: '#fafafa'}" + > + <el-table-column type="index" label="序号" width="80"/> + <el-table-column property="workPermitNo" label="作业证编号"/> + <el-table-column property="workTypeDesc" label="作业类型"/> + <el-table-column property="warningContent" show-overflow-tooltip label="预警信息"/> + <el-table-column property="warningTypeDesc" label="预警类型"/> + <el-table-column property="warningInfo" show-overflow-tooltip label="描述" width="200"/> + <el-table-column property="operatorUname" label="上报人"/> + <el-table-column property="operationTime" label="上报时间" width="180"/> + <el-table-column fixed="right" label="操作" align="center" width="250"> + <template #default="scope"> + <el-button link type="primary" size="small" :icon="View" @click="viewRecord(scope.row)">查看</el-button> + </template> + </el-table-column> + </el-table> + <div class="pageBtn"> + <el-pagination + v-model:currentPage="currentPage" + v-model:page-size="pageSize" + :page-sizes="[10, 15]" + small=false + background + layout="total, sizes, prev, pager, next, jumper" + :total="totalSize" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + </div> + </div> + </div> + <el-dialog v-model="dialogDetails" title="作业预警记录"> + <el-form :model="details" label-width="120px"> + <el-form-item label="作业证编号"> + <el-input v-model="details.workPermitNo" readonly/> + </el-form-item> + <el-form-item label="作业类型"> + <el-input v-model="details.workTypeDesc" readonly/> + </el-form-item> + <el-form-item label="预警信息"> + <el-input v-model="details.warningContent" readonly/> + </el-form-item> + <el-form-item label="预警类型"> + <el-input v-model="details.warningTypeDesc" readonly/> + </el-form-item> + <el-form-item label="图片" v-if="details.imagePaths && details.imagePaths.length>0"> + <el-image v-for="item in details.imagePaths" :preview-src-list="details.imagePaths" style="width: 150px; height: 150px;margin-right: 50px;margin-bottom: 20px" :src="item" fit="cover" /> + </el-form-item> + <el-form-item label="描述"> + <el-input v-model="details.warningInfo" type="textarea" readonly/> + </el-form-item> + <el-form-item label="上报人"> + <el-input v-model="details.operatorUname" readonly/> + </el-form-item> + <el-form-item label="上报时间"> + <el-input v-model="details.operationTime" readonly/> + </el-form-item> + <el-form-item> + <el-button type="primary" @click="dialogDetails = false" size="default">确认</el-button> + </el-form-item> + </el-form> + </el-dialog> + </div> +</template> + +<script lang="ts"> + import { toRefs, reactive, ref, onMounted } from 'vue'; + import { storeToRefs } from 'pinia'; + import { initBackEndControlRoutes } from '/@/router/backEnd'; + import { useUserInfo } from '/@/stores/userInfo'; + import { Session } from '/@/utils/storage'; + import { Edit, View, Plus, Delete, Refresh, Search, Download } from '@element-plus/icons-vue'; + import { ElTable } from 'element-plus'; + import { FormInstance, FormRules, ElMessage } from 'element-plus'; + import { workProcessApi } from '/@/api/specialWorkSystem/workProcess'; + + // 定义接口来定义对象的类型 + interface stateType { + tableData: Array<any>; + departmentList: Array<any>; + department:string; + workerList: Array<string>; + multipleSelection: Array<any>; + deleteArr: Array<any>; + dialogDetails: boolean; + dialogAddRecord: boolean; + deleteDialog: boolean; + deleteSetDialog: boolean; + pageIndex: number; + pageSize: number; + chosenIndex: null | number; + deleteId: null | number; + searchWord: string; + searchType: string; + warningType: string; + totalSize: number; + details: { + + }; + workTypeList: Array<any>; + alertTypeList: Array<any> + } + + export default { + name: 'alerts', + components: {}, + setup() { + const userInfo = useUserInfo(); + const { userInfos } = storeToRefs(userInfo); + + const state = reactive<stateType>({ + pageIndex: 1, + pageSize: 10, + totalSize: 0, + chosenIndex: null, + searchWord: '', + searchType: '', + warningType: '', + tableData: [], + departmentList: [], + department: '', + workerList: [], + multipleSelection: [], + dialogDetails: false, + dialogAddRecord: false, + deleteDialog: false, + deleteSetDialog: false, + details: {}, + deleteId: null, + deleteArr: [], + workTypeList: [ + { id: '1', name: '动火作业' }, + { id: '2', name: '受限空间作业' }, + { id: '3', name: '吊装作业' }, + { id: '4', name: '动土作业' }, + { id: '5', name: '断路作业' }, + { id: '6', name: '高处作业' }, + { id: '7', name: '临时用电作业' }, + { id: '8', name: '盲板抽堵作业' } + ], + alertTypeList: [ + { id: '1', name: '检查' }, + { id: '2', name: '检测' } + ] + }); + + // 页面载入时执行方法 + onMounted(() => { + getListByPage(); + }); + + // 分页获取班组管理列表 + const getListByPage = async () => { + const data = { pageSize: state.pageSize, pageIndex: state.pageIndex, searchParams: { workType: state.searchType, workPermitNo: state.searchWord,warningType: state.warningType } }; + let res = await workProcessApi().postAlertList(data); + if (res.data.code === '200') { + state.tableData = JSON.parse(JSON.stringify(res.data.data)) + state.totalSize = res.data.total; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 关键词查询记录 + const searchRecord = () => { + if (state.searchWord == ''&& state.searchType == ''&& state.warningType == '') { + ElMessage({ + type: 'warning', + message: '请输入查询关键词' + }); + } else { + getListByPage(); + } + }; + + const clearSearch = () => { + state.searchWord = '' + state.searchType = '' + state.warningType = '' + getListByPage() + }; + + const handleSizeChange = (val: number) => { + state.pageSize = val; + getListByPage(); + }; + + const handleCurrentChange = (val: number) => { + state.pageIndex = val; + getListByPage(); + }; + + // 查看记录 + const viewRecord = (row) => { + state.details = JSON.parse(JSON.stringify(row)); + state.dialogDetails = true; + }; + + // 刷新 + const reLoadData = async () => { + getListByPage(); + }; + + // 折线图 + const renderMenu = async (value: string) => { + Session.set('projectId', value); + userInfos.value.projectId = value; + await initBackEndControlRoutes(); + }; + + return { + View, + Edit, + Delete, + Refresh, + Plus, + searchRecord, + clearSearch, + viewRecord, + getListByPage, + reLoadData, + handleSizeChange, + handleCurrentChange, + ...toRefs(state) + }; + } + }; +</script> + +<style scoped lang="scss"> + $homeNavLengh: 8; + .home-container { + height: calc(100vh - 144px); + box-sizing: border-box; + overflow: hidden; + .homeCard { + width: 100%; + padding: 20px; + box-sizing: border-box; + background: #fff; + border-radius: 4px; + + .main-card { + width: 100%; + height: 100%; + .cardTop { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 20px; + .mainCardBtn { + margin: 0; + } + } + .pageBtn { + height: 60px; + display: flex; + align-items: center; + justify-content: right; + + .demo-pagination-block + .demo-pagination-block { + margin-top: 10px; + } + .demo-pagination-block .demonstration { + margin-bottom: 16px; + } + } + } + &:last-of-type { + height: calc(100% - 100px); + } + } + .el-row { + display: flex; + align-items: center; + margin-bottom: 20px; + &:last-child { + margin-bottom: 0; + } + .grid-content { + align-items: center; + min-height: 36px; + } + + .topInfo { + width: 100%; + display: flex; + align-items: center; + font-size: 16px; + font-weight: bold; + + & > div { + white-space: nowrap; + margin-right: 20px; + } + } + } + } + .el-input{ + width: 100% !important; + } + .el-date-editor::v-deep{ + width: 100%; + } + .el-select{ + width: 100%; + } +</style> diff --git a/src/views/specialWorkSystem/flow/basicApprove/components/approveBasicDialog.vue b/src/views/specialWorkSystem/flow/basicApprove/components/approveBasicDialog.vue new file mode 100644 index 0000000..9cd39ee --- /dev/null +++ b/src/views/specialWorkSystem/flow/basicApprove/components/approveBasicDialog.vue @@ -0,0 +1,254 @@ +<template> + <div class="system-add-menu-container"> + <el-dialog :title="title" v-model="isShowApproveBasicDialog" width="600px" :close-on-click-modal="false"> + <el-form :model="approveBasicForm" :rules="approveBasicFormRules" ref="approveBasicFormRef" size="default" label-width="120px"> + <el-row :gutter="35"> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="标题" prop="title"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="approveBasicForm.title" placeholder="请输入标题名称" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="标准类型" prop="ruleStandType"> + <el-select class="input-add" :disabled="!disabled" v-model="approveBasicForm.ruleStandType" placeholder="请选择标准类型" clearable filterable> + <el-option v-for="item in ruleStandTypeList" :key="item.id" :label="item.name" :value="item.id"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="最大值" prop="maxVal"> + <el-input :disabled="!disabled" v-model="approveBasicForm.maxVal" type="number" class="input-add" placeholder="请根据需求选择"> + <template #prepend> + <el-select :disabled="!disabled" v-model="approveBasicForm.maxValMatchPattern" placeholder="请根据需求选择" style="width: 115px"> + <el-option v-for="item in typeTwoList" :key="item.id" :value="item.id" :label="item.name"> </el-option> + </el-select> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="最小值" prop="minVal"> + <el-input :disabled="!disabled" v-model="approveBasicForm.minVal" type="number" class="input-add" placeholder="请根据需求选择"> + <template #prepend> + <el-select :disabled="!disabled" v-model="approveBasicForm.minValMatchPattern" placeholder="请根据需求选择" style="width: 115px"> + <el-option v-for="item in typeList" :key="item.id" :value="item.id" :label="item.name"> </el-option> + </el-select> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="描述" prop="info"> + <el-input class="input-add" :rows="3" :disabled="!disabled" v-model.trim="approveBasicForm.info" type="textarea" placeholder="请输入描述"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20" v-show="personTime"> + <el-form-item label="创建人" prop="createUname"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="approveBasicForm.createUname"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20" v-show="personTime"> + <el-form-item label="创建时间" prop="gmtCreate"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="approveBasicForm.gmtCreate"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20" v-show="personTime"> + <el-form-item label="最后修改人" prop="modifiedUname"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="approveBasicForm.modifiedUname"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20" v-show="personTime"> + <el-form-item label="最后修改时间" prop="gmtModified"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="approveBasicForm.gmtModified"></el-input> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer" v-show="disabled"> + <el-button @click="isShowApproveBasicDialog = !isShowApproveBasicDialog" size="default">取 消</el-button> + <el-button type="primary" @click="submitApproveBasic" v-throttle size="default">确 定</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script lang="ts"> +interface stateType { + isShowApproveBasicDialog: Boolean; + disabled: Boolean; + personTime: Boolean; + approveBasicForm: { + ruleStandId: null | number; + ruleStandType: null | number; + minVal: null | number; + minValMatchPattern: null; + maxVal: null | number; + maxValMatchPattern: null | number; + title: null | string; + info: null | string; + }; + title: string; + departmentList: []; + ruleStandTypeList: Array<levelListState>; + typeList: Array<levelListState>; + typeTwoList: Array<levelListState>; + approveBasicFormRules: {}; +} +interface levelListState { + id: number; + name: string; +} +interface approveBasicForm { + ruleStandId: null | number; + ruleStandType: null | number; + minVal: null | number; + minValMatchPattern: null; + maxVal: null | number; + maxValMatchPattern: null | number; + title: null | string; + info: null | string; +} + +import { reactive, toRefs, ref } from 'vue'; +import { approveBasicApi } from '/@/api/specialWorkSystem/approveBasic'; +import { ElMessage } from 'element-plus'; +export default { + name: 'approveBasicDialog', + setup(props: any, context: any) { + const approveBasicFormRef = ref(); + const state = reactive<stateType>({ + title: '', + disabled: false, + personTime: false, + departmentList: [], + isShowApproveBasicDialog: false, + ruleStandTypeList: [ + { id: 1, name: '可燃气体' }, + { id: 3, name: '有毒有害气体' }, + { id: 2, name: '氧气' }, + ], + typeList: [ + { id: 1, name: '大于' }, + { id: 2, name: '等于' }, + { id: 4, name: '大于等于' } + ], + typeTwoList: [ + { id: 3, name: '小于' }, + { id: 2, name: '等于' }, + { id: 5, name: '小于等于' } + ], + approveBasicForm: { + ruleStandId: null, + ruleStandType: null, + minVal: null, + minValMatchPattern: null, + maxVal: null, + maxValMatchPattern: null, + title: null, + info: null + }, + approveBasicFormRules: { + ruleStandType: [{ required: true, message: '请选择标准类型', trigger: 'change' }], + minVal: [{ required: true, message: '请填写标最低值', trigger: 'blur' }], + maxVal: [{ required: true, message: '请填写标最高值', trigger: 'blur' }], + title: [{ required: true, message: '请选择风险等级', trigger: 'blur' }], + info: [{ required: true, message: '请填写描述信息', trigger: 'blur' }] + } + }); + + //打开模态框 + const showApproveBasicDialog = (type: string, value: object, department: []) => { + state.isShowApproveBasicDialog = true; + state.departmentList = department; + setTimeout(() => { + approveBasicFormRef.value.clearValidate(); + }); + if (type === '新增') { + state.disabled = true; + state.personTime = false; + state.title = '新增审批标准'; + state.approveBasicForm = { + ruleStandId: null, + ruleStandType: null, + minVal: null, + minValMatchPattern: null, + maxVal: null, + maxValMatchPattern: null, + title: null, + info: null + }; + } else if (type === '查看') { + state.disabled = false; + state.personTime = true; + state.title = '查看审批标准'; + state.approveBasicForm = JSON.parse(JSON.stringify(value)); + } else { + state.disabled = true; + state.personTime = false; + state.title = '修改审批标准'; + state.approveBasicForm = JSON.parse(JSON.stringify(value)); + // for (let i in state.approveBasicForm) { + // state.approveBasicForm[i] = approveBasicForm[i]; + // } + } + }; + + //新增修改提交 + const submitApproveBasic = async () => { + approveBasicFormRef.value.validate(async (valid: Boolean) => { + if (valid) { + if (state.title === '新增审批标准') { + let res = await approveBasicApi().addApproveBasic(state.approveBasicForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '审批标准新增成功', + duration: 2000 + }); + state.isShowApproveBasicDialog = false; + context.emit('refreshApproveBasic'); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } else { + let res = await approveBasicApi().modApproveBasic(state.approveBasicForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '审批标准修改成功', + duration: 2000 + }); + state.isShowApproveBasicDialog = false; + context.emit('refreshApproveBasic'); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } + } else { + ElMessage({ + type: 'warning', + message: '请完善基本信息' + }); + } + }); + }; + + return { + ...toRefs(state), + approveBasicFormRef, + submitApproveBasic, + showApproveBasicDialog + }; + } +}; +</script> + +<style scoped></style> diff --git a/src/views/specialWorkSystem/flow/basicApprove/index.vue b/src/views/specialWorkSystem/flow/basicApprove/index.vue new file mode 100644 index 0000000..87af29a --- /dev/null +++ b/src/views/specialWorkSystem/flow/basicApprove/index.vue @@ -0,0 +1,448 @@ +<template> + <div class="home-container"> + <div style="height: 100%"> + <el-row class="homeCard"> + <div class="basic-line"> + <span>标准类型:</span> + <el-select v-model="tableData.params.searchParams.ruleStandType" clearable filterable class="input-box" placeholder="标准类型"> + <el-option v-for="item in ruleStandTypeList" :key="item.id" :label="item.name" :value="item.id"></el-option> + </el-select> + </div> + <div class="basic-line"> + <span>标题:</span> + <el-input v-model.trim="tableData.params.searchParams.title" clearable filterable class="input-box" placeholder="标题"> </el-input> + </div> + <div style="padding-bottom: 10px"> + <el-button type="primary" @click="getInspectionTask">查询</el-button> + <el-button plain @click="reset">重置</el-button> + </div> + </el-row> + <div class="homeCard"> + <div class="main-card"> + <el-row class="cardTop"> + <el-col :span="12" class="mainCardBtn"> + <el-button type="primary" :icon="Plus" size="default" @click="openApproveBasicDialog('新增', {})">新增</el-button> + <el-button type="danger" :icon="Delete" size="default" @click="deleteMoreApproveBasic" plain>批量删除</el-button> + </el-col> + <el-button type="primary" :icon="Refresh" size="default" /> + </el-row> + <el-table ref="multipleTableRef" :data="tableData.approveBasicData" style="width: 100%" height="calc(100% - 100px)" :header-cell-style="{ background: '#fafafa' }" @selection-change="handleSelectionChange"> + <el-table-column type="selection" width="55" /> + <el-table-column property="title" label="标题" /> + <el-table-column property="ruleStandType" label="标准类型"> + <template #default="scope"> + <span> + {{ parseNumber(scope.row.ruleStandType, '标准类型') }} + </span> + </template> + </el-table-column> + <el-table-column property="minVal" label="最低值"> + <template #default="scope"> + <span> + {{ parseNumber(scope.row.minValMatchPattern, '最低值') }} + </span> + <span> + {{ scope.row.minVal }} + </span> + </template> + </el-table-column> + <el-table-column property="maxVal" label="最高值"> + <template #default="scope"> + <span> + {{ parseNumber(scope.row.maxValMatchPattern, '最高值') }} + </span> + <span> + {{ scope.row.maxVal }} + </span> + </template> + </el-table-column> + <el-table-column property="info" label="描述" /> + <el-table-column prop="createUname" label="创建人" show-overflow-tooltip></el-table-column> + <el-table-column prop="gmtCreate" label="创建时间" show-overflow-tooltip></el-table-column> + <el-table-column prop="modifiedUname" label="最后修改人" show-overflow-tooltip></el-table-column> + <el-table-column prop="gmtModified" label="最后修改时间" show-overflow-tooltip></el-table-column> +<!-- <el-table-column property="status" label="状态" width="60" />--> + <el-table-column fixed="right" label="操作" align="center" width="300"> + <template #default="scope"> + <el-button link type="primary" size="small" :icon="View" @click="openApproveBasicDialog('查看', scope.row)">查看</el-button> + <el-button link type="primary" size="small" :icon="Edit" @click="openApproveBasicDialog('修改', scope.row)">修改</el-button> + <el-button link type="danger" size="small" :icon="Delete" @click="deleteApproveBasic(scope.row)">删除</el-button> + </template> + </el-table-column> + </el-table> + <br /> + <el-pagination @size-change="onHandleSizeChange" @current-change="onHandleCurrentChange" :pager-count="5" :page-sizes="[10, 20, 30]" v-model:current-page="tableData.params.pageIndex" background v-model:page-size="tableData.params.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="tableData.total" class="page-position"> </el-pagination> + </div> + </div> + </div> + <approve-basic-dialog ref="approveBasicDialogRef" @refreshApproveBasic="getInspectionTask"></approve-basic-dialog> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, ref, onMounted } from 'vue'; +import { Edit, View, Plus, Delete, Refresh, Search, Download } from '@element-plus/icons-vue'; +import { ElTable, ElMessage, ElMessageBox } from 'element-plus'; +import { approveBasicApi } from '/@/api/specialWorkSystem/approveBasic'; +import { departmentApi } from '/@/api/systemManage/department'; +import approveBasicDialog from '/@/views/specialWorkSystem/flow/basicApprove/components/approveBasicDialog.vue'; +let global: any = { + homeChartOne: null, + homeChartTwo: null, + homeCharThree: null, + dispose: [null, '', undefined] +}; + +interface stateType { + tableData: { + approveBasicData: []; + total: number; + loading: boolean; + params: { + pageIndex: number | null; + pageSize: number | null; + searchParams: { + ruleStandType: number | null; + title: string | null; + }; + }; + }; + ruleStandTypeList: Array<type>; + typeList: Array<type>; + typeTwoList: Array<type>; + deleteList: { + ids: Array<number>; + }; +} +interface type { + id: number; + name: string; +} +interface ruleType { + ruleStandId: number; +} +export default { + name: 'index', + components: { approveBasicDialog }, + setup() { + const approveBasicDialogRef = ref(); + const state = reactive<stateType>({ + tableData: { + approveBasicData: [], + total: 0, + loading: false, + params: { + pageIndex: 1, + pageSize: 10, + searchParams: { + ruleStandType: null, + title: null + } + } + }, + ruleStandTypeList: [ + { id: 1, name: '可燃气体' }, + { id: 3, name: '有毒有害气体' }, + { id: 2, name: '氧气' }, + ], + typeList: [ + { id: 1, name: '大于' }, + { id: 2, name: '等于' }, + { id: 4, name: '大于等于' } + ], + typeTwoList: [ + { id: 3, name: '小于' }, + { id: 2, name: '等于' }, + { id: 5, name: '小于等于' } + ], + deleteList: { + ids: [] + } + }); + + //获取巡检任务数据 + const getInspectionTask = async () => { + let res = await approveBasicApi().getApproveBasicList(state.tableData.params); + if (res.data.code === '200') { + state.tableData.approveBasicData = res.data.data; + state.tableData.total = res.data.total; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // //获取部门 + // const getDepartmentData = async () => { + // let res = await departmentApi().getDepartmentList(); + // if (res.data.code === '200') { + // state.departmentList = res.data.data; + // } else { + // ElMessage({ + // type: 'warning', + // message: res.data.msg + // }); + // } + // }; + + // 删除 + const deleteApproveBasic = (row: any) => { + ElMessageBox.confirm(`此操作将永久删除该任务:“${row.title}”,是否继续?`, '提示', { + confirmButtonText: '确认', + cancelButtonText: '取消', + type: 'warning' + }) + .then(async () => { + let res = await approveBasicApi().deleteApproveBasic({ ids: [row.ruleStandId] }); + if (res.data.code === '200') { + state.deleteList.ids = []; + ElMessage({ + type: 'success', + duration: 2000, + message: '删除成功' + }); + await getInspectionTask(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }) + .catch(() => {}); + }; + + // 批量删除 + const deleteMoreApproveBasic = (row: any) => { + ElMessageBox.confirm(`此操作将永久删除这些标准项,是否继续?`, '提示', { + confirmButtonText: '确认', + cancelButtonText: '取消', + type: 'warning' + }) + .then(async () => { + let res = await approveBasicApi().deleteApproveBasic(state.deleteList); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + duration: 2000, + message: '删除成功' + }); + await getInspectionTask(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }) + .catch(() => {}); + }; + + const handleSelectionChange = (val: Array<ruleType>) => { + state.deleteList.ids = val.map((item) => { + return item.ruleStandId; + }); + }; + + const openApproveBasicDialog = (type: string, value: {}) => { + approveBasicDialogRef.value.showApproveBasicDialog(type, value); + }; + + const parseNumber = (value: number, type: string) => { + if (type === '标准类型') { + return state.ruleStandTypeList.find((item) => item.id === value)?.name; + } else if (type === '最高值') { + return state.typeTwoList.find((item) => item.id == value)?.name; + } else { + return state.typeList.find((item) => item.id == value)?.name; + } + }; + + // 分页改变 + const onHandleSizeChange = (val: number) => { + state.tableData.params.pageSize = val; + getInspectionTask(); + }; + // 分页改变 + const onHandleCurrentChange = (val: number) => { + state.tableData.params.pageIndex = val; + getInspectionTask(); + }; + + const reset = () => { + state.tableData.params = { + pageIndex: 1, + pageSize: 10, + searchParams: { + ruleStandType: null, + title: null + } + }; + }; + + // 页面加载时 + onMounted(() => { + getInspectionTask(); + }); + + return { + View, + Edit, + Delete, + Refresh, + Plus, + reset, + parseNumber, + handleSelectionChange, + deleteApproveBasic, + deleteMoreApproveBasic, + getInspectionTask, + onHandleSizeChange, + onHandleCurrentChange, + approveBasicDialogRef, + openApproveBasicDialog, + ...toRefs(state) + }; + } +}; +</script> + +<style scoped lang="scss"> +$homeNavLengh: 8; +.home-container { + height: calc(100vh - 144px); + box-sizing: border-box; + overflow: hidden; + .homeCard { + width: 100%; + padding: 20px; + box-sizing: border-box; + background: #fff; + border-radius: 4px; + + .main-card { + width: 100%; + height: 100%; + .cardTop { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 20px; + .mainCardBtn { + margin: 0; + } + } + .pageBtn { + height: 60px; + display: flex; + align-items: center; + justify-content: right; + + .demo-pagination-block + .demo-pagination-block { + margin-top: 10px; + } + .demo-pagination-block .demonstration { + margin-bottom: 16px; + } + } + } + &:last-of-type { + height: calc(100% - 100px); + } + } + .el-row { + display: flex; + align-items: center; + margin-bottom: 20px; + &:last-child { + margin-bottom: 0; + } + .grid-content { + align-items: center; + min-height: 36px; + } + + .topInfo { + display: flex; + align-items: center; + font-size: 16px; + font-weight: bold; + + & > div { + white-space: nowrap; + margin-right: 20px; + } + } + } +} +.stepItem { + width: 100%; + display: flex; + align-items: flex-start; + margin-bottom: 30px; + margin-left: 30px; + padding-bottom: 30px; + border-left: 2px solid #ccc; + &:first-of-type { + margin-top: 30px; + } + &:last-of-type { + margin-bottom: 0; + border-left: none; + } + .stepNum { + width: 30px; + height: 30px; + border-radius: 15px; + box-sizing: border-box; + color: #333; + border: 1px solid #999; + line-height: 28px; + text-align: center; + margin-right: 10px; + margin-left: -16px; + margin-top: -30px; + } + .stepCard { + width: 100%; + margin-top: -30px; + + .box-card { + width: 100%; + &:deep(.el-card__header) { + padding: 10px 15px; + } + .card-header { + width: 100%; + display: flex; + justify-content: space-between; + align-items: center; + & > div:first-of-type { + margin-right: 80px; + font-size: 18px; + font-weight: bold; + } + } + } + } + &:hover .card-header { + color: #0098f5; + } + &:hover .stepNum { + border: 2px solid #0098f5; + color: #0098f5; + } +} +:deep(.el-textarea.is-disabled .el-textarea__inner) { + background-color: var(--el-card-bg-color); + color: var(--el-input-text-color, var(--el-text-color-regular)); +} +:deep(.el-input.is-disabled .el-input__inner) { + color: var(--el-input-text-color, var(--el-text-color-regular)); +} +:deep(.el-input.is-disabled .el-input__wrapper) { + background-color: var(--el-card-bg-color); +} +</style> diff --git a/src/views/specialWorkSystem/flow/ruleofApp/components/approveItemDialog.vue b/src/views/specialWorkSystem/flow/ruleofApp/components/approveItemDialog.vue new file mode 100644 index 0000000..355aef7 --- /dev/null +++ b/src/views/specialWorkSystem/flow/ruleofApp/components/approveItemDialog.vue @@ -0,0 +1,183 @@ +<template> + <el-dialog v-model="approveItemDialog" :title="title" :close-on-click-modal="false"> + <el-form :model="approveItemForm" label-width="150px" ref="approveItemFormRef" :rules="approveItemFormRule"> + <el-col :span="24" style="margin-bottom: 24px"> + <el-form-item label="审批项名称" prop="itemName"> + <el-input v-model="approveItemForm.itemName" class="input-add" placeholder="请填写审批项名称"> </el-input> + </el-form-item> + </el-col> + <el-col :span="24" style="margin-bottom: 24px"> + <el-form-item label="审批项类型" prop="type"> + <el-select v-model="approveItemForm.type" @change="clearValue" placeholder="请选择审批项类型" class="input-add" clearable filterable> + <el-option v-for="item in typeList" :key="item.id" :value="item.id" :label="item.name"></el-option> + </el-select> + </el-form-item> + </el-col> + <!-- <el-col :span="24" style="margin-bottom: 24px">--> + <!-- <el-form-item label="措施或标准" prop="smType">--> + <!-- <el-select v-model="approveItemForm.smType" @change="clearValue" placeholder="请选择措施或标准" class="input-add" clearable filterable>--> + <!-- <el-option v-for="item in smTypeList" :key="item.id" :value="item.id" :label="item.name"></el-option>--> + <!-- </el-select>--> + <!-- </el-form-item>--> + <!-- </el-col>--> + <el-col v-if="(approveItemForm.type === 2 || approveItemForm.type === 3) && personType !== 3" :span="24" style="margin-bottom: 24px"> + <el-form-item label="措施名称" prop="measureId"> + <el-select v-model="approveItemForm.measureId" placeholder="请选择措施" class="input-add" clearable filterable> + <el-option v-for="item in approveTypeList" :key="item.id" :value="item.id" :label="item.context"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col v-if="approveItemForm.type === 1" :span="24" style="margin-bottom: 20px"> + <el-form-item label="标准名称" prop="standId"> + <el-select v-model="approveItemForm.standId" class="input-add" placeholder="选择标准" clearable filterable> + <el-option v-for="item in standardList" :key="item.ruleStandId" :value="item.ruleStandId" :label="item.title"></el-option> + </el-select> + </el-form-item> + </el-col> + + <div align="right"> + <el-button type="warning" @click="approveItemDialog = false" size="default" plain>取消</el-button> + <el-button type="primary" @click="submitApproveItem()" size="default">确认</el-button> + </div> + </el-form> + </el-dialog> +</template> + +<script lang="ts"> +import { reactive, toRefs, ref, nextTick } from 'vue'; +import { ElMessage } from 'element-plus/es'; +interface dataState { + title: string; + activeName: string; + approveItemDialog: boolean; + approveItemForm: step; + approveItemFormRule: {}; + actionList: Array<type>; + typeList: Array<type>; + approveTypeList: Array<type>; + smTypeList: Array<type>; + standardList: []; + order: number | null; + personType: number | null; +} +interface step { + itemName: string | null; + type: null; + measureId: number | null; + standId: number | null; + smType: number | null; +} +interface type { + id: number; + name: string; + type?:number; +} +export default { + name: 'approveItemDialog', + setup(props: any, context: any) { + const approveItemFormRef = ref(); + const data = reactive<dataState>({ + title: '', + activeName: 'ApproveAction', + approveItemDialog: false, + approveItemForm: { + itemName: null, + type: null, + measureId: null, + smType: 1, + standId: null + }, + approveItemFormRule: { + itemName: [{ required: true, message: '请填写审批项名称', trigger: 'blur' }], + type: [{ required: true, message: '请选择审批项类型', trigger: 'change' }], + measureId: [{ required: true, message: '请选择措施', trigger: 'change' }], + smType: [{ required: true, message: '请选择措施或标准', trigger: 'change' }], + standId: [{ required: true, message: '请选择标准', trigger: 'change' }] + }, + actionList: [], + typeList: [], + approveTypeList: [], + smTypeList: [ + { id: 1, name: '标准' }, + { id: 2, name: '措施' } + ], + standardList: [], + order: null, + personType: null, + }); + + const showApproveItemDialog = (type: string, value: {}, index: number, approveLevelForm: { type: number }, standardList: [], actionList: []) => { + data.approveItemDialog = true; + data.standardList = standardList; + data.actionList = actionList; + data.order = index; + if (approveLevelForm.type === 3) { + data.personType = 3 + data.typeList = [ + { id: 1, name: '数值' }, + { id: 3, name: '填空' } + ]; + } else { + data.personType = 2 + data.typeList = [ + { id: 2, name: '选项' }, + { id: 3, name: '填空' } + ]; + } + nextTick(() => { + approveItemFormRef.value.clearValidate(); + }); + if (type === '新增') { + data.title = '新增审批项'; + data.approveItemForm = { + itemName: null, + type: null, + measureId: null, + standId: null, + smType: 1 + }; + } else { + data.title = '修改审批项'; + data.approveItemForm = JSON.parse(JSON.stringify(value)); + } + }; + + const submitApproveItem = async () => { + approveItemFormRef.value.validate((valid: Boolean) => { + if (valid) { + data.approveItemForm.smType = 1; + context.emit('addApprovalItem', data.approveItemForm, data.title, data.order); + data.approveItemDialog = false; + } else { + ElMessage({ + type: 'warning', + message: '请完善审批项基本信息' + }); + } + }); + }; + + const clearValue = () => { + if (data.approveItemForm.type === 1) { + data.approveItemForm.measureId = null; + }else if(data.approveItemForm.type === 2){ + data.approveItemForm.standId = null; + data.approveTypeList = data.actionList.filter(item => item.type === 1) + } else { + data.approveItemForm.standId = null; + data.approveTypeList = data.actionList.filter(item => item.type === 2) + } + }; + + return { + ...toRefs(data), + clearValue, + approveItemFormRef, + submitApproveItem, + showApproveItemDialog + }; + } +}; +</script> + +<style scoped></style> diff --git a/src/views/specialWorkSystem/flow/ruleofApp/components/approveLevelDialog.vue b/src/views/specialWorkSystem/flow/ruleofApp/components/approveLevelDialog.vue new file mode 100644 index 0000000..cf46a25 --- /dev/null +++ b/src/views/specialWorkSystem/flow/ruleofApp/components/approveLevelDialog.vue @@ -0,0 +1,327 @@ +<template> + <div> + <el-dialog v-model="approveLevelDialog" :title="title" :close-on-click-modal="false"> + <el-form :model="approveLevelForm" label-width="150px" ref="approveLevelFormRef" :rules="approveLevelFormRule"> + <el-col :span="24" style="margin-bottom: 24px"> + <el-form-item label="层级名称" prop="stepName"> + <el-input v-model="approveLevelForm.stepName" class="input-add" placeholder="请填写层级名称"> </el-input> + </el-form-item> + </el-col> + <el-col :span="24" style="margin-bottom: 24px"> + <el-form-item label="审批层级" prop="type"> + <el-select v-model="approveLevelForm.type" placeholder="请选择审批层级" class="input-add"> + <el-option v-for="item in typeList" :key="item.id" :value="item.id" :label="item.name"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :span="24" style="margin-bottom: 24px" v-if="approveLevelForm.type === 2"> + <el-form-item label="审批类型" prop="auditType"> + <el-select v-model="approveLevelForm.auditType" placeholder="请选择审批类型" class="input-add"> + <el-option v-for="item in auditTypeList" :key="item.id" :value="item.id" :label="item.name"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :span="24" style="margin-bottom: 24px"> + <el-form-item label="审批人" prop="unitList"> + <el-select v-model="approveLevelForm.unitList" multiple placeholder="请选择审批人" class="input-add"> + <el-option v-for="item in userList" :key="item.uid" :value="item.uid" :label="item.realName"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :span="24" style="margin-bottom: 20px"> + <el-form-item label="审批有效时间" prop="continueTime"> + <el-input type="number" v-model="approveLevelForm.continueTime" placeholder="请输入审批有效时间" class="input-add"> + <template #prepend> + <el-select v-model="approveLevelForm.continueTimeUnit" placeholder="选择单位"> + <el-option v-for="item in timeList" :key="item.id" :value="item.id" :label="item.name"></el-option> + </el-select> + </template> + </el-input> + </el-form-item> + </el-col> + <div class="checkUnit-point"> + <el-tabs class="active" v-model="activeName"> + <el-tab-pane label="审批流程" name="ApproveAction"> + <div class="filter-container"> + <el-button size="default" type="primary" @click="openApproveActionDialog('新增', '', 0)"> + <el-icon> + <ele-FolderAdd /> + </el-icon> + 新增审批项 + </el-button> + </div> + + <el-table ref="table" :data="approveLevelForm.itemList" style="width: 100%"> + <el-table-column property="itemName" label="审批项名称" show-overflow-tooltip> </el-table-column> + <el-table-column property="type" label="审批项类型" show-overflow-tooltip> + <template #default="scope"> + <span> + {{ parseNumber(scope.row.type, '审批项类型') }} + </span> + </template> + </el-table-column> + <el-table-column property="measureId" label="措施名称" show-overflow-tooltip> + <template #default="scope"> + <span> + {{ parseNumber(scope.row.measureId, '措施名称') }} + </span> + </template> + </el-table-column> + <el-table-column property="standId" label="标准名称" show-overflow-tooltip> + <template #default="scope"> + <span> + {{ parseNumber(scope.row.standId, '标准名称') }} + </span> + </template> + </el-table-column> + <el-table-column label="操作" width="150" align="center"> + <template #default="scope"> + <el-button type="text" size="small" @click="openApproveActionDialog('修改', scope.row, scope.$index)">修改</el-button> + <el-button type="text" size="small" style="color: red" @click="deleteApproveItem(scope.$index)">删除</el-button> + </template> + </el-table-column> + </el-table> + </el-tab-pane> + </el-tabs> + </div> + + <div align="right" style="padding-top: 10px"> + <el-button type="warning" @click="approveLevelDialog = false" size="default" plain>取消</el-button> + <el-button type="primary" @click="submitApproveLevel()" size="default">确认</el-button> + </div> + </el-form> + </el-dialog> + <approve-item-dialog ref="approveItemDialogRef" @addApprovalItem="achieveApprovalItem"></approve-item-dialog> + </div> +</template> + +<script lang="ts"> +import { reactive, toRefs, ref, nextTick, onMounted } from 'vue'; +import approveItemDialog from '/@/views/specialWorkSystem/flow/ruleofApp/components/approveItemDialog.vue'; +import { ElMessage } from 'element-plus/es'; +import { safetyActionApi } from '/@/api/specialWorkSystem/safetyAction'; +import { approveBasicApi } from '/@/api/specialWorkSystem/approveBasic'; +interface dataState { + title: string; + activeName: string; + approveLevelDialog: boolean; + approveLevelForm: step; + approveLevelFormRule: {}; + departmentList: []; + userList: []; + timeList: Array<type>; + typeList: Array<type>; + auditTypeList: Array<type>; + approveTypeList: Array<type>; + workLevelList: []; + standardList: Array<stand>; + actionList: Array<action>; +} +interface action { + id: number; + context: string; +} +interface stand { + ruleStandId: number; + title: string; +} +interface step { + id: number | null; + stepName: null; + stepSerial: number | null; + type: number | null; + auditType: number | null; + continueTime: number | null; + continueTimeUnit: number | null; + unitList: Array<personType>; + itemList: Array<item>; +} +interface personType { + bindUid: number | {}; +} +interface item {} +interface type { + id: number; + name: string; +} +export default { + name: 'approveLevelDialog', + components: { approveItemDialog }, + setup(props: any, context: any) { + const approveLevelFormRef = ref(); + const approveItemDialogRef = ref(); + const data = reactive<dataState>({ + title: '', + activeName: 'ApproveAction', + approveLevelDialog: false, + approveLevelForm: { + id: null, + stepName: null, + stepSerial: null, + type: null, + auditType: null, + continueTime: null, + continueTimeUnit: null, + unitList: [], + itemList: [] + }, + approveLevelFormRule: { + stepName: [{ required: true, message: '请填写层次名称', trigger: 'blur' }], + type: [{ required: true, message: '请选择审批层级', trigger: 'change' }], + auditType: [{ required: true, message: '请选择审批类型', trigger: 'change' }], + unitList: [{ required: true, message: '请选择审批人', trigger: 'change' }], + continueTime: [{ required: true, message: '请填写有效时间', trigger: 'blur' }] + }, + departmentList: [], + userList: [], + timeList: [ + { id: 1, name: '日' }, + { id: 2, name: '时' }, + { id: 3, name: '分' } + ], + typeList: [ + { id: 1, name: '单人' }, + { id: 2, name: '多人' }, + { id: 3, name: '分析人' } + ], + auditTypeList: [ + { id: 1, name: '单审' }, + { id: 2, name: '会审' }, + ], + approveTypeList: [ + { id: 1, name: '数值' }, + { id: 2, name: '选项' }, + { id: 3, name: '填空' } + ], + workLevelList: [], + actionList: [], + standardList: [] + }); + + const showApproveLevelDialog = (type: string, value: {}, userList: []) => { + data.approveLevelDialog = true; + data.userList = userList; + nextTick(() => { + approveLevelFormRef.value.clearValidate(); + }); + if (type === '新增') { + data.title = '新增审批层级'; + data.approveLevelForm = { + id: null, + stepName: null, + stepSerial: null, + type: null, + auditType: null, + continueTime: null, + continueTimeUnit: null, + unitList: [], + itemList: [] + }; + } else { + data.title = '修改审批层级'; + data.approveLevelForm = JSON.parse(JSON.stringify(value)); + data.approveLevelForm.unitList = data.approveLevelForm.unitList.map((item) => { + return item.bindUid; + }) as []; + } + }; + + const openApproveActionDialog = (type: string, value: {}, index: number) => { + approveLevelFormRef.value.validate((valid: Boolean) => { + if (valid) { + approveItemDialogRef.value.showApproveItemDialog(type, value, index, data.approveLevelForm, data.standardList, data.actionList); + } else { + ElMessage({ + type: 'warning', + message: '请先完善审批层级信息,才能选择审批项' + }); + } + }); + }; + + const submitApproveLevel = async () => { + approveLevelFormRef.value.validate((valid: Boolean) => { + if (valid) { + data.approveLevelForm.unitList = data.approveLevelForm.unitList.map((item) => { + return { bindUid: item }; + }); + context.emit('addApprovalLevel', data.approveLevelForm, data.title); + data.approveLevelDialog = false; + } else { + ElMessage({ + type: 'warning', + message: '请完善审批层级基本信息' + }); + } + }); + }; + + const achieveApprovalItem = (value: {}, title: string, index: number) => { + if (title === '新增审批项') { + data.approveLevelForm.itemList.push(value); + } else { + data.approveLevelForm.itemList[index] = JSON.parse(JSON.stringify(value)); + } + }; + + const deleteApproveItem = async (index: number) => { + data.approveLevelForm.itemList.splice(index, 1); + }; + + //获取措施项 + const getActionData = async () => { + let res = await safetyActionApi().getAllSafetyActionList({ workType: null, type: null, context: null }); + if (res.data.code === '200') { + data.actionList = res.data.data; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + //获取标准 + const getStandardData = async () => { + let res = await approveBasicApi().getAllApproveBasicList({ ruleStandType: null, title: null }); + if (res.data.code === '200') { + data.standardList = res.data.data; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + const parseNumber = (value: number, type: string) => { + if (type === '审批项类型') { + return data.approveTypeList.find((item) => item.id === value)?.name; + } else if (type === '措施名称') { + return data.actionList.find((item) => item.id === value)?.context; + } else { + return data.standardList.find((item) => item.ruleStandId === value)?.title; + } + }; + + onMounted(() => { + getActionData(); + getStandardData(); + }); + + return { + ...toRefs(data), + parseNumber, + approveLevelFormRef, + approveItemDialogRef, + deleteApproveItem, + submitApproveLevel, + achieveApprovalItem, + showApproveLevelDialog, + openApproveActionDialog + }; + } +}; +</script> + +<style scoped></style> diff --git a/src/views/specialWorkSystem/flow/ruleofApp/components/approveRuleDialog.vue b/src/views/specialWorkSystem/flow/ruleofApp/components/approveRuleDialog.vue new file mode 100644 index 0000000..7880a01 --- /dev/null +++ b/src/views/specialWorkSystem/flow/ruleofApp/components/approveRuleDialog.vue @@ -0,0 +1,526 @@ +<template> + <div class="system-add-menu-container"> + <el-dialog v-model="ifShowApproveRuleDialog" :title="title" :close-on-click-modal="false"> + <el-form :model="approveRuleForm" label-width="120px" ref="approveRuleFormRef" :rules="approveRuleFormRules"> + <el-row> + <el-col :span="12" style="margin-bottom: 20px"> + <el-form-item label="任务名称" prop="ruleName"> + <el-input v-model="approveRuleForm.ruleName" :disabled="!disabled" class="input-add" placeholder="请填写任务名称"> </el-input> + </el-form-item> + </el-col> + <el-col :span="12" style="margin-bottom: 20px"> + <el-form-item label="部门名称" prop="depId"> + <el-cascader :disabled="!disabled" placeholder="请选择部门名称" :options="departmentList" :props="{ emitPath: false, checkStrictly: true, value: 'depId', label: 'depName' }" clearable filterable class="input-add" v-model="approveRuleForm.depId"> </el-cascader> + </el-form-item> + </el-col> + <el-col :span="12" style="margin-bottom: 20px"> + <el-form-item label="作业类型" prop="workType"> + <el-select v-model="approveRuleForm.workType" @change="clearValue" :disabled="!disabled" placeholder="请选择作业类型" class="input-add"> + <el-option v-for="item in workTypeList" :key="item.id" :value="item.id" :label="item.name"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :span="12" style="margin-bottom: 20px" v-if="approveRuleForm.workType === 3 || approveRuleForm.workType === 6 || approveRuleForm.workType === 8 || approveRuleForm.workType === 1"> + <el-form-item label="作业等级" prop="workLevel"> + <el-select v-model="approveRuleForm.workLevel" :disabled="!disabled" placeholder="请选择作业等级" class="input-add"> + <el-option v-for="item in workLevelList" :key="item.id" :value="item.id" :label="item.name"></el-option> + </el-select> + </el-form-item> + </el-col> + + <el-col :span="24"> + <el-form-item label="创建审批链"> + <div style="width: 100%; margin-bottom: 20px" v-show="disabled"> + <el-button type="primary" :icon="Plus" size="default" @click="openApproveLevelDialog('新增', '')">新增审批层级</el-button> + </div> + <div style="width: 100%; margin-left: -30px"> + <div v-for="(item, index) in approveRuleForm.stepList" class="stepItem"> + <div class="stepNum">{{ index + 1 }}</div> + <div class="stepCard"> + <el-card class="box-card"> + <div class="text item"> + 层级名称:<span>{{ item.stepName }}</span> + </div> + <!-- <div class="text item">--> + <!-- 所属设备区域:<span>{{ item.regionId }}</span>--> + <!-- </div>--> + <div class="text item" v-for="i in typeList"> + <div v-if="i.id === item.type"> + 审批层级:<span>{{ i.name }}</span> + </div> + </div> + <!-- <div class="text item">--> + <!-- 关联RFID:<span>{{ item.rfidId }}</span>--> + <!-- </div>--> + <div class="text item"> + 审批人:<span>{{ + item.unitList + .map((item) => { + return userList.find((i) => i.uid === item.bindUid)?.realName; + }) + .join('、') + }}</span> + </div> + <!-- <div class="text item">--> + <!-- 巡检指标:<span>{{ item.quotaId }}</span>--> + <!-- </div>--> + <div class="text item" v-for="i in timeList"> + <div v-if="i.id === item.continueTimeUnit"> + 审批有效时长:<span>{{ item.continueTime }}</span> + <span>{{ i.name }}</span> + </div> + </div> + <!-- <div class="text item">--> + <!-- 数据填报类型:<span>{{ item.dataReportType }}</span>--> + <!-- </div>--> + <div class="text item"> + 审批项:<span>{{ + item.itemList + .map((item) => { + return item.itemName; + }) + .join('、') + }}</span> + </div> + </el-card> + </div> + <div v-show="disabled"> + <el-button type="primary" style="margin-left: 12px" size="default" @click="openApproveLevelDialog('修改', item)">修改</el-button> + <el-button type="danger" size="default" @click="deleteApproveLevel(index, item)">删除</el-button> + </div> + </div> + </div> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <div v-show="disabled" class="dialog-footer"> + <el-button type="warning" @click="ifShowApproveRuleDialog = false" size="default" plain>取消</el-button> + <el-button type="primary" @click="submitApproveRule()" size="default">确认</el-button> + </div> + </template> + </el-dialog> + <approve-level-dialog ref="approveLevelDialogRef" @addApprovalLevel="achieveApprovalLevel"></approve-level-dialog> + </div> +</template> + +<script lang="ts"> +import { reactive, toRefs, ref } from 'vue'; +import { ElMessage } from 'element-plus/es'; +import { approveRuleApi } from '/@/api/specialWorkSystem/approveRule'; +import { Edit, View, Plus, Delete, Refresh, Search, Download } from '@element-plus/icons-vue'; +import approveLevelDialog from '/@/views/specialWorkSystem/flow/ruleofApp/components/approveLevelDialog.vue'; +interface dataState { + title: string; + pointTitle: string; + disabled: boolean; + ifShowApproveRuleDialog: boolean; + inspectPointForm: step; + approveRuleForm: { + id: number | null; + ruleName: number | null; + depId: number | null; + workType: number | null; + workLevel: number | null; + stepList: Array<step>; + }; + approveRuleFormRules: {}; + departmentList: []; + userList: []; + workTypeList: Array<type>; + timeList: Array<type>; + typeList: Array<type>; + workLevelList: Array<type>; +} + +interface type { + id: number; + name: string; +} +interface step { + id: number | null; + stepName: null; + stepSerial: number | null; + type: number | null; + continueTime: number | null; + continueTimeUnit: number | null; + unitList: []; + itemList: []; +} +export default { + name: 'approveRuleDialog', + components: { approveLevelDialog,Plus }, + setup(props: any, context: any) { + const approveRuleFormRef = ref(); + const approveLevelDialogRef = ref(); + const data = reactive<dataState>({ + title: '', + pointTitle: '', + disabled: true, + ifShowApproveRuleDialog: false, + inspectPointForm: { + id: null, + stepName: null, + stepSerial: null, + type: null, + continueTime: null, + continueTimeUnit: null, + unitList: [], + itemList: [] + }, + approveRuleForm: { + id: null, + ruleName: null, + depId: null, + workType: null, + workLevel: null, + stepList: [] + }, + approveRuleFormRules: { + ruleName: [{ required: true, message: '请填写规则名称', trigger: 'blur' }], + depId: [{ required: true, message: '请选择部门', trigger: 'change' }], + workLevel: [{ required: true, message: '请选择作业等级', trigger: 'change' }], + workType: [{ required: true, message: '请选择作业类型', trigger: 'cahnge' }] + }, + departmentList: [], + userList: [], + typeList: [ + { id: 1, name: '单人' }, + { id: 2, name: '多人' }, + { id: 3, name: '分析人' } + ], + timeList: [ + { id: 1, name: '日' }, + { id: 2, name: '时' }, + { id: 3, name: '分' } + ], + workTypeList: [ + { id: 1, name: '动火作业' }, + { id: 2, name: '受限空间作业' }, + { id: 3, name: '吊装作业' }, + { id: 4, name: '动土作业' }, + { id: 5, name: '断路作业' }, + { id: 6, name: '高处作业' }, + { id: 7, name: '临时用电作业' }, + { id: 8, name: '盲板抽堵作业' } + ], + workLevelList: [] + }); + + const openApproveLevelDialog = (type: string, value: {}) => { + approveLevelDialogRef.value.showApproveLevelDialog(type, value, data.userList); + }; + + const achieveApprovalLevel = (value: step, title: string) => { + if (title === '新增审批层级') { + if (data.approveRuleForm.stepList.length === 0) { + value.stepSerial = 1; + data.approveRuleForm.stepList.push(value); + } else { + value.stepSerial = (data.approveRuleForm.stepList[data.approveRuleForm.stepList.length - 1]?.stepSerial as number) + 1; + data.approveRuleForm.stepList.push(value); + } + } else { + let result = data.approveRuleForm.stepList.findIndex((item) => item.stepSerial === value.stepSerial); + data.approveRuleForm.stepList[result] = JSON.parse(JSON.stringify(value)); + } + }; + + const showApproveRuleDialog = (type: string, value: { workType: number }, departmentList: [], userList: [], workTypeList: []) => { + data.ifShowApproveRuleDialog = true; + data.userList = userList; + data.workTypeList = workTypeList; + data.departmentList = departmentList; + if (type === '新增') { + data.disabled = true; + data.title = '新增审批规则'; + data.approveRuleForm = { + id: null, + ruleName: null, + depId: null, + workType: null, + workLevel: null, + stepList: [] + }; + } else if (type === '修改') { + data.disabled = true; + data.title = '修改审批规则'; + data.approveRuleForm = JSON.parse(JSON.stringify(value)); + setValue(value.workType); + } else { + data.disabled = false; + data.title = '查看审批规则'; + setValue(value.workType); + data.approveRuleForm = JSON.parse(JSON.stringify(value)); + } + }; + + const deleteApproveLevel = (index: number, item: any) => { + data.approveRuleForm.stepList.splice(index, 1); + }; + + const clearValue = () => { + if (data.approveRuleForm.workType === 1) { + data.approveRuleForm.workLevel = null; + data.workLevelList = [ + { id: 3, name: '特级动火作业' }, + { id: 1, name: '一级动火作业' }, + { id: 2, name: '二级动火作业' } + ]; + } else if (data.approveRuleForm.workType === 3) { + data.approveRuleForm.workLevel = null; + data.workLevelList = [ + { id: 8, name: '一级吊装作业' }, + { id: 9, name: '二级吊装作业' }, + { id: 10, name: '三级吊装作业' } + ]; + } else if (data.approveRuleForm.workType === 6) { + data.approveRuleForm.workLevel = null; + data.workLevelList = [ + { id: 7, name: '特级高处作业' }, + { id: 4, name: '一级高处作业' }, + { id: 5, name: '二级高处作业' }, + { id: 6, name: '三级高处作业' }, + ]; + } else if (data.approveRuleForm.workType === 8) { + data.approveRuleForm.workLevel = null; + data.workLevelList = [ + { id: 11, name: '抽盲板作业' }, + { id: 12, name: '堵盲板作业' } + ]; + } else { + data.approveRuleForm.workLevel = null; + data.workLevelList = []; + } + }; + + const setValue = (workType: number) => { + if (workType === 1) { + data.workLevelList = [ + { id: 3, name: '特级动火作业' }, + { id: 1, name: '一级动火作业' }, + { id: 2, name: '二级动火作业' }, + ]; + } else if (workType === 3) { + data.workLevelList = [ + { id: 8, name: '一级吊装作业' }, + { id: 9, name: '二级吊装作业' }, + { id: 10, name: '三级吊装作业' } + ]; + } else if (workType === 6) { + data.workLevelList = [ + { id: 7, name: '四级高处作业' }, + { id: 4, name: '一级高处作业' }, + { id: 5, name: '二级高处作业' }, + { id: 6, name: '三级高处作业' } + ]; + } else if (workType === 8) { + data.workLevelList = [ + { id: 11, name: '抽盲板作业' }, + { id: 12, name: '堵盲板作业' } + ]; + } else { + data.workLevelList = []; + } + }; + + const parseNumber = (type: string, value: number) => { + if (type === '时间单位') { + return data.timeList.find((item) => item.id === value)?.name; + } + }; + + const submitApproveRule = () => { + approveRuleFormRef.value.validate(async (valid: Boolean) => { + if (valid) { + if (data.title === '新增审批规则') { + let res = await approveRuleApi().addApproveRule(data.approveRuleForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '审批规则新增成功', + duration: 2000 + }); + data.ifShowApproveRuleDialog = false; + context.emit('refreshApproveRule'); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } else { + let res = await approveRuleApi().modApproveRule(data.approveRuleForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '审批规则修改成功', + duration: 2000 + }); + data.ifShowApproveRuleDialog = false; + context.emit('refreshApproveRule'); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } + } else { + ElMessage({ + type: 'warning', + message: '请完善基本信息' + }); + } + }); + }; + + return { + ...toRefs(data), + Plus, + clearValue, + parseNumber, + approveLevelDialog, + approveRuleFormRef, + approveLevelDialogRef, + submitApproveRule, + achieveApprovalLevel, + openApproveLevelDialog, + showApproveRuleDialog, + deleteApproveLevel + }; + } +}; +</script> + +<style scoped lang="scss"> +$homeNavLengh: 8; +.home-container { + height: calc(100vh - 144px); + box-sizing: border-box; + overflow: hidden; + .homeCard { + width: 100%; + padding: 20px; + box-sizing: border-box; + background: #fff; + border-radius: 4px; + + .main-card { + width: 100%; + height: 100%; + .cardTop { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 20px; + .mainCardBtn { + margin: 0; + } + } + .pageBtn { + height: 60px; + display: flex; + align-items: center; + justify-content: right; + + .demo-pagination-block + .demo-pagination-block { + margin-top: 10px; + } + .demo-pagination-block .demonstration { + margin-bottom: 16px; + } + } + } + &:last-of-type { + height: calc(100% - 100px); + } + } + .el-row { + display: flex; + align-items: center; + margin-bottom: 20px; + &:last-child { + margin-bottom: 0; + } + .grid-content { + align-items: center; + min-height: 36px; + } + + .topInfo { + display: flex; + align-items: center; + font-size: 16px; + font-weight: bold; + + & > div { + white-space: nowrap; + margin-right: 20px; + } + } + } +} +.stepItem { + width: 100%; + display: flex; + align-items: flex-start; + margin-bottom: 30px; + margin-left: 30px; + padding-bottom: 30px; + border-left: 2px solid #ccc; + &:first-of-type { + margin-top: 30px; + } + &:last-of-type { + margin-bottom: 0; + border-left: none; + } + .stepNum { + width: 30px; + height: 30px; + border-radius: 15px; + box-sizing: border-box; + color: #333; + border: 1px solid #999; + line-height: 28px; + text-align: center; + margin-right: 10px; + margin-left: -16px; + margin-top: -30px; + } + .stepCard { + width: 100%; + margin-top: -30px; + + .box-card { + width: 100%; + &:deep(.el-card__header) { + padding: 10px 15px; + } + .card-header { + width: 100%; + display: flex; + justify-content: space-between; + align-items: center; + & > div:first-of-type { + margin-right: 80px; + font-size: 18px; + font-weight: bold; + } + } + } + } + &:hover .card-header { + color: #0098f5; + } + &:hover .stepNum { + border: 2px solid #0098f5; + color: #0098f5; + } +} +:deep(.el-date-editor) { + width: 100%; +} +</style> diff --git a/src/views/specialWorkSystem/flow/ruleofApp/index.vue b/src/views/specialWorkSystem/flow/ruleofApp/index.vue new file mode 100644 index 0000000..09bb87a --- /dev/null +++ b/src/views/specialWorkSystem/flow/ruleofApp/index.vue @@ -0,0 +1,477 @@ +<template> + <div class="home-container"> + <div style="height: 100%"> + <el-row class="homeCard"> + <div class="basic-line"> + <span>规则名称:</span> + <el-input v-model="tableData.params.searchParams.ruleName" class="input-box" placeholder="规则名称"> </el-input> + </div> + <div class="basic-line"> + <span>部门:</span> + <el-cascader placeholder="部门名称" :options="departmentList" :props="{ emitPath: false, checkStrictly: true, value: 'depId', label: 'depName' }" clearable filterable class="input-box" v-model="tableData.params.searchParams.depId"> </el-cascader> + </div> + <div class="basic-line"> + <span>作业类型:</span> + <el-select v-model="tableData.params.searchParams.workType" clearable filterable class="input-box" placeholder="作业类型"> + <el-option v-for="item in workTypeList" :key="item.id" :label="item.name" :value="item.id"></el-option> + </el-select> + </div> + <div class="basic-line"> + <span>作业等级:</span> + <el-select v-model="tableData.params.searchParams.workLevel" clearable filterable class="input-box" placeholder="作业等级"> + <el-option v-for="item in workLevelList" :key="item.id" :label="item.name" :value="item.id"></el-option> + </el-select> + </div> + <div style="padding-bottom: 10px"> + <el-button type="primary" @click="getApproveRule">查询</el-button> + <el-button plain @click="reset">重置</el-button> + </div> + </el-row> + <div class="homeCard"> + <div class="main-card"> + <el-row class="cardTop"> + <el-col :span="12" class="mainCardBtn"> + <el-button type="primary" :icon="Plus" size="default" @click="openApproveRuleDialog('新增', {})">新增</el-button> + <el-button type="danger" :icon="Delete" size="default" @click="deleteMoreApproveRule" plain>批量删除</el-button> + </el-col> + <el-button type="primary" :icon="Refresh" size="default" /> + </el-row> + <el-table ref="multipleTableRef" :data="tableData.approveRuleData" style="width: 100%" height="calc(100% - 100px)" :header-cell-style="{ background: '#fafafa' }" @selection-change="handleSelectionChange"> + <el-table-column type="selection" width="55" /> + <el-table-column property="ruleName" label="任务名称" /> + <el-table-column property="workType" label="作业类型"> + <template #default="scope"> + <span> + {{ parseNumber(scope.row.workType, '作业类型') }} + </span> + </template> + </el-table-column> + <el-table-column property="workLevel" label="作业等级"> + <template #default="scope"> + <span> + {{ parseNumber(scope.row.workLevel, '作业等级') }} + </span> + </template> + </el-table-column> + <el-table-column prop="createUname" label="创建人" show-overflow-tooltip></el-table-column> + <el-table-column prop="gmtCreate" label="创建时间" show-overflow-tooltip></el-table-column> + <el-table-column prop="modifiedUname" label="最后修改人" show-overflow-tooltip></el-table-column> + <el-table-column prop="gmtModified" label="最后修改时间" show-overflow-tooltip></el-table-column> + <el-table-column fixed="right" label="操作" align="center" width="300"> + <template #default="scope"> + <el-button link type="primary" size="small" :icon="View" @click="openApproveRuleDialog('查看', scope.row)">查看</el-button> + <el-button link type="primary" size="small" :icon="Edit" @click="openApproveRuleDialog('修改', scope.row)">修改</el-button> + <el-button link type="primary" style="color: red" size="small" :icon="Delete" @click="deleteApproveRule(scope.row)">删除</el-button> + </template> + </el-table-column> + </el-table> + <div class="pageBtn"> + <el-pagination @size-change="onHandleSizeChange" @current-change="onHandleCurrentChange" :pager-count="5" :page-sizes="[10, 20, 30]" v-model:current-page="tableData.params.pageIndex" background v-model:page-size="tableData.params.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="tableData.total" class="page-position"> </el-pagination> + </div> + </div> + </div> + </div> + <approve-rule-dialog ref="approveRuleDialogRef" @refreshApproveRule="getApproveRule"></approve-rule-dialog> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, ref, onMounted } from 'vue'; +import { Edit, View, Plus, Delete, Refresh, Search, Download } from '@element-plus/icons-vue'; +import { ElTable, ElMessage, ElMessageBox } from 'element-plus'; +import approveRuleDialog from '/@/views/specialWorkSystem/flow/ruleofApp/components/approveRuleDialog.vue'; +import { departmentApi } from '/@/api/systemManage/department'; +import { approveRuleApi } from '/@/api/specialWorkSystem/approveRule/index'; +import { userApi } from '/@/api/systemManage/user'; + +interface stateType { + tableData: { + approveRuleData: []; + total: number; + loading: boolean; + params: { + pageIndex: number | null; + pageSize: number | null; + searchParams: { + ruleName: string | null; + depId: number | null; + workType: number | null; + workLevel: number | null; + }; + }; + }; + workTypeList: Array<type>; + departmentList: []; + userList: []; + workLevelList: Array<type>; + deleteList: { ids: Array<deleteType> }; + timeType: Array<type>; +} +interface deleteType { + ruleId: number; +} + +interface type { + id: number; + name: string; +} + +export default { + name: 'index', + components: { approveRuleDialog }, + setup() { + const approveRuleDialogRef = ref(); + const state = reactive<stateType>({ + tableData: { + approveRuleData: [], + total: 0, + loading: false, + params: { + pageIndex: 1, + pageSize: 10, + searchParams: { + ruleName: null, + depId: null, + workType: null, + workLevel: null + } + } + }, + workTypeList: [ + { id: 1, name: '动火作业' }, + { id: 2, name: '受限空间作业' }, + { id: 3, name: '吊装作业' }, + { id: 4, name: '动土作业' }, + { id: 5, name: '断路作业' }, + { id: 6, name: '高处作业' }, + { id: 7, name: '临时用电作业' }, + { id: 8, name: '盲板抽堵作业' } + ], + workLevelList: [ + { id: 3, name: '特级动火作业' }, + { id: 1, name: '一级动火作业' }, + { id: 2, name: '二级动火作业' }, + { id: 7, name: '特级高处作业' }, + { id: 4, name: '一级高处作业' }, + { id: 5, name: '二级高处作业' }, + { id: 6, name: '三级高处作业' }, + { id: 8, name: '一级吊装作业' }, + { id: 9, name: '二级吊装作业' }, + { id: 10, name: '三级吊装作业' }, + { id: 11, name: '抽盲板作业' }, + { id: 12, name: '堵盲板作业' } + ], + departmentList: [], + userList: [], + deleteList: { ids: [] }, + timeType: [ + { id: 1, name: '分' }, + { id: 2, name: '小时' }, + { id: 3, name: '日' }, + { id: 4, name: '月' }, + { id: 5, name: '年' } + ] + }); + + //获取巡检任务数据 + const getApproveRule = async () => { + let res = await approveRuleApi().getApproveRuleList(state.tableData.params); + if (res.data.code === '200') { + state.tableData.approveRuleData = res.data.data; + state.tableData.total = res.data.total; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + //获取部门 + const getDepartmentData = async () => { + let res = await departmentApi().getDepartmentList(); + if (res.data.code === '200') { + state.departmentList = res.data.data; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + //获取用户列表 + const getUserData = async () => { + let res = await userApi().getAllUser(); + if (res.data.code === '200') { + state.userList = res.data.data; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 删除 + const deleteApproveRule = (row: any) => { + ElMessageBox.confirm(`此操作将永久删除该审批规则,是否继续?`, '提示', { + confirmButtonText: '确认', + cancelButtonText: '取消', + type: 'warning' + }) + .then(async () => { + let res = await approveRuleApi().deleteApproveRule({ ids: [row.id] }); + state.deleteList.ids = []; + if (res.data.code === '200') { + ElMessage({ + type: 'success', + duration: 2000, + message: '删除成功' + }); + await getApproveRule(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }) + .catch(() => {}); + }; + + // 批量删除 + const deleteMoreApproveRule = (row: any) => { + ElMessageBox.confirm(`此操作将永久删除这些审批规则,是否继续?`, '提示', { + confirmButtonText: '确认', + cancelButtonText: '取消', + type: 'warning' + }) + .then(async () => { + let res = await approveRuleApi().deleteApproveRule(state.deleteList); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + duration: 2000, + message: '删除成功' + }); + await getApproveRule(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }) + .catch(() => {}); + }; + + const openApproveRuleDialog = (type: string, value: {}) => { + approveRuleDialogRef.value.showApproveRuleDialog(type, value, state.departmentList, state.userList, state.workTypeList); + }; + + const parseNumber = (value: number, type: string) => { + if (type === '作业类型') { + return state.workTypeList.find((item) => item.id === value)?.name; + } else if (type === '作业等级') { + return state.workLevelList.find((item) => item.id == value)?.name; + } else { + } + }; + + const handleSelectionChange = (val: Array<deleteType>) => { + state.deleteList.ids = val.map((item) => { + return item.ruleId; + }) as []; + }; + + // 分页改变 + const onHandleSizeChange = (val: number) => { + state.tableData.params.pageSize = val; + getApproveRule(); + }; + // 分页改变 + const onHandleCurrentChange = (val: number) => { + state.tableData.params.pageIndex = val; + getApproveRule(); + }; + + const reset = () => { + state.tableData.params = { + pageIndex: 1, + pageSize: 10, + searchParams: { + ruleName: null, + depId: null, + workType: null, + workLevel: null + } + }; + }; + + // 页面加载时 + onMounted(() => { + getApproveRule(); + getDepartmentData(); + getUserData(); + }); + + return { + View, + Edit, + Delete, + Refresh, + Plus, + reset, + parseNumber, + deleteApproveRule, + getApproveRule, + deleteMoreApproveRule, + handleSelectionChange, + onHandleSizeChange, + onHandleCurrentChange, + approveRuleDialogRef, + openApproveRuleDialog, + ...toRefs(state) + }; + } +}; +</script> + +<style scoped lang="scss"> +$homeNavLengh: 8; +.home-container { + height: calc(100vh - 144px); + box-sizing: border-box; + overflow: hidden; + .homeCard { + width: 100%; + padding: 20px; + box-sizing: border-box; + background: #fff; + border-radius: 4px; + + .main-card { + width: 100%; + height: 100%; + .cardTop { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 20px; + .mainCardBtn { + margin: 0; + } + } + .pageBtn { + height: 60px; + display: flex; + align-items: center; + justify-content: right; + + .demo-pagination-block + .demo-pagination-block { + margin-top: 10px; + } + .demo-pagination-block .demonstration { + margin-bottom: 16px; + } + } + } + &:last-of-type { + height: calc(100% - 100px); + } + } + .el-row { + display: flex; + align-items: center; + margin-bottom: 20px; + &:last-child { + margin-bottom: 0; + } + .grid-content { + align-items: center; + min-height: 36px; + } + + .topInfo { + display: flex; + align-items: center; + font-size: 16px; + font-weight: bold; + + & > div { + white-space: nowrap; + margin-right: 20px; + } + } + } +} +.stepItem { + width: 100%; + display: flex; + align-items: flex-start; + margin-bottom: 30px; + margin-left: 30px; + padding-bottom: 30px; + border-left: 2px solid #ccc; + &:first-of-type { + margin-top: 30px; + } + &:last-of-type { + margin-bottom: 0; + border-left: none; + } + .stepNum { + width: 30px; + height: 30px; + border-radius: 15px; + box-sizing: border-box; + color: #333; + border: 1px solid #999; + line-height: 28px; + text-align: center; + margin-right: 10px; + margin-left: -16px; + margin-top: -30px; + } + .stepCard { + width: 100%; + margin-top: -30px; + + .box-card { + width: 100%; + &:deep(.el-card__header) { + padding: 10px 15px; + } + .card-header { + width: 100%; + display: flex; + justify-content: space-between; + align-items: center; + & > div:first-of-type { + margin-right: 80px; + font-size: 18px; + font-weight: bold; + } + } + } + } + &:hover .card-header { + color: #0098f5; + } + &:hover .stepNum { + border: 2px solid #0098f5; + color: #0098f5; + } +} +:deep(.el-textarea.is-disabled .el-textarea__inner) { + background-color: var(--el-card-bg-color); + color: var(--el-input-text-color, var(--el-text-color-regular)); +} +:deep(.el-input.is-disabled .el-input__inner) { + color: var(--el-input-text-color, var(--el-text-color-regular)); +} +:deep(.el-input.is-disabled .el-input__wrapper) { + background-color: var(--el-card-bg-color); +} +</style> diff --git a/src/views/specialWorkSystem/foundationSet/goods/index.vue b/src/views/specialWorkSystem/foundationSet/goods/index.vue new file mode 100644 index 0000000..ee1493b --- /dev/null +++ b/src/views/specialWorkSystem/foundationSet/goods/index.vue @@ -0,0 +1,989 @@ +<template> + <div class="home-container"> + <div style="height: 100%"> + <el-row class="homeCard"> + <el-col :span="5" style="display:flex;align-items: center"> + <span style="white-space: nowrap">作业类型:</span> + <div class="grid-content topInfo"> + <el-select v-model="searchType"> + <el-option + v-for="item in workTypeList" + :key="item.value" + :label="item.label" + :value="item.value" + /> + </el-select> + </div> + </el-col> + <el-col v-if="searchType==1" :span="5" style="display:flex;align-items: center"> + <span style="white-space: nowrap">作业等级:</span> + <div class="grid-content topInfo"> + <el-select v-model="searchLevel"> + <el-option + v-for="item in fireLevel" + :key="item.value" + :label="item.label" + :value="item.value" + /> + </el-select> + </div> + </el-col> + <el-col v-if="searchType==3" :span="5" style="display:flex;align-items: center"> + <span style="white-space: nowrap">作业等级:</span> + <div class="grid-content topInfo"> + <el-select v-model="searchLevel"> + <el-option + v-for="item in hoistLevel" + :key="item.value" + :label="item.label" + :value="item.value" + /> + </el-select> + </div> + </el-col> + <el-col v-if="searchType==6" :span="5" style="display:flex;align-items: center"> + <span style="white-space: nowrap">作业等级:</span> + <div class="grid-content topInfo"> + <el-select v-model="searchLevel"> + <el-option + v-for="item in heightLevel" + :key="item.value" + :label="item.label" + :value="item.value" + /> + </el-select> + </div> + </el-col> + <el-col v-if="searchType==8" :span="5" style="display:flex;align-items: center"> + <span style="white-space: nowrap">作业等级:</span> + <div class="grid-content topInfo"> + <el-select v-model="searchLevel"> + <el-option + v-for="item in plateLevel" + :key="item.value" + :label="item.label" + :value="item.value" + /> + </el-select> + </div> + </el-col> + <el-col :span="5" style="display:flex;align-items: center"> + <span style="white-space: nowrap">物资配置名称:</span> + <div class="grid-content topInfo"> + <el-input v-model="searchName"/> + </div> + </el-col> + <el-button type="primary" @click="searchRecord">查询</el-button> + <el-button plain @click="clearSearch">重置</el-button> + </el-row> + <div class="homeCard"> + <div class="main-card"> + <el-row class="cardTop"> + <el-col :span="12" class="mainCardBtn"> + <el-button type="primary" :icon="Plus" size="default" @click="addRecordBtn">新增</el-button> + <!-- <el-button type="warning" :icon="Edit" size="default" plain>修改</el-button>--> +<!-- <el-button type="danger" :icon="Delete" size="default" plain @click="deleteBatchBtn">删除</el-button>--> + </el-col> + <el-button type="primary" :icon="Refresh" size="default" @click="reLoadData()" /> + </el-row> + <el-table ref="multipleTableRef" :data="tableData" style="width: 100%" height="calc(100% - 100px)" :header-cell-style="{ background: '#fafafa' }" @selection-change="handleSelectionChange"> +<!-- <el-table-column type="selection" width="100" />--> + <el-table-column property="name" label="物资配置名称" align="center" :show-overflow-tooltip="true"/> + <el-table-column property="workType" label="关联作业类型" align="center" :formatter="toType" :show-overflow-tooltip="true"/> + <el-table-column property="workLevel" label="关联作业等级" align="center" :formatter="toLevel" :show-overflow-tooltip="true"/> + <el-table-column property="createUname" label="创建人" align="center"/> + <el-table-column property="gmtCreate" label="创建时间" align="center"/> +<!-- <el-table-column property="gmtModified" label="更新时间" align="center"/>--> + <el-table-column fixed="right" label="操作" align="center" width="250"> + <template #default="scope"> + <el-button link type="primary" size="small" :icon="View" @click="viewRecord(scope.row)">查看</el-button> + <el-button link type="primary" size="small" :icon="Edit" @click="editRecordBtn(scope.$index, scope.row)">修改</el-button> + <el-button link type="danger" size="small" :icon="Delete" @click="deleteRecordBtn(scope.row)">删除</el-button> + </template> + </el-table-column> + </el-table> + <div class="pageBtn"> + <el-pagination v-model:currentPage="pageIndex" v-model:page-size="pageSize" :page-sizes="[10, 15]" small="false" background layout="total, sizes, prev, pager, next, jumper" :total="totalSize" @size-change="handleSizeChange" @current-change="handleCurrentChange" /> + </div> + </div> + </div> + </div> + <el-dialog v-model="dialogDetails" title="作业物资标准" @close="clearList"> + <el-form :model="details" label-width="140px"> + <el-form-item label="作业物资标准名称"> + <el-input v-model="details.name" readonly /> + </el-form-item> + <el-form-item label="关联作业类型"> + <el-input v-model="details.workType" readonly /> + </el-form-item> + <el-form-item label="关联作业等级"> + <el-input v-model="details.workLevel" readonly /> + </el-form-item> + <el-form-item label="作业物资汇总"> + <div class="materials"> + <div class="maList" v-for="item in details.clList"> + <div>{{item.configurationLevelName}}</div> + <div> + <div v-if="item.mdList.length>0" v-for="i in item.mdList"> + {{i.materialName}}({{i.bigClassifyName }}):标准值:{{i.standVal }} + </div> + <div v-else> + 无 + </div> + </div> + </div> + </div> + </el-form-item> + <el-form-item label="描述"> + <el-input v-model="details.info" type="textarea" autosize readonly /> + </el-form-item> + <el-form-item label="创建人"> + <el-input v-model="details.createUname" readonly /> + </el-form-item> + <el-form-item label="创建时间"> + <el-input v-model="details.gmtCreate" readonly /> + </el-form-item> +<!-- <el-form-item label="更新时间">--> +<!-- <el-input v-model="details.gmtModified" readonly />--> +<!-- </el-form-item>--> + <el-form-item> + <el-button type="primary" @click="dialogDetails = false" size="default">确认</el-button> + </el-form-item> + </el-form> + </el-dialog> + <el-dialog v-model="dialogAddRecord" title="作业物资标准编辑" @close="closeAdd" @open="openAdd" center> + <el-form :model="addRecord" label-width="150px" ref="addRef" :rules="addRules"> + <el-form-item label="作业物资标准名称" prop="name"> + <el-input v-model="addRecord.name"> </el-input> + </el-form-item> + <el-form-item label="关联作业类型" prop="workType"> + <el-select v-model="addRecord.workType" clearable filterable class="input-box" placeholder="关联作业类型"> + <el-option v-for="item in workTypeList" :key="item.value" :label="item.label" :value="item.value"></el-option> + </el-select> + </el-form-item> + <el-form-item v-if="addRecord.workType == 1" label="关联作业等级" prop="workLevel"> + <el-select v-model="addRecord.workLevel"> + <el-option + v-for="item in fireLevel" + :key="item.value" + :label="item.label" + :value="item.value" + /> + </el-select> + </el-form-item> + <el-form-item v-if="addRecord.workType == 3" label="关联作业等级" prop="workLevel"> + <el-select v-model="addRecord.workLevel"> + <el-option + v-for="item in hoistLevel" + :key="item.value" + :label="item.label" + :value="item.value" + /> + </el-select> + </el-form-item> + <el-form-item v-if="addRecord.workType == 6" label="关联作业等级" prop="workLevel"> + <el-select v-model="addRecord.workLevel"> + <el-option + v-for="item in heightLevel" + :key="item.value" + :label="item.label" + :value="item.value" + /> + </el-select> + </el-form-item> + <el-form-item v-if="addRecord.workType == 8" label="关联作业等级" prop="workLevel"> + <el-select v-model="addRecord.workLevel"> + <el-option + v-for="item in plateLevel" + :key="item.value" + :label="item.label" + :value="item.value" + /> + </el-select> + </el-form-item> + <el-form-item label="物资标准配置"> + <el-tabs tab-position="left" class="demo-tabs" type="border-card"> + <el-tab-pane v-for="(item,index) in allList" :label="item.materialClassifyName" :key="index"> + <div class="tab-i" v-if="item.childList && item.childList.length>0"> + <div v-for="(i,x) in item.childList" :key="x"> + <el-checkbox :label="i.materialClassifyName" v-model="checkData[index].childList[x].checked"> + </el-checkbox> + <el-form v-if="checkData[index].childList[x].checked" :model="checkData[index].childList[x]" label-width="100px" ref="addListRef" :rules="addListRules"> + <el-form-item label="配置级别" prop="configurationLevel"> + <el-select v-model="checkData[index].childList[x].configurationLevel"> + <el-option key="0" label="必选" :value="0"/> + <el-option key="1" label="可选" :value="1"/> + <el-option key="2" label="高配" :value="2"/> + </el-select> + </el-form-item> + <el-form-item label="标准值" prop="standVal"><el-input type="number" v-model.number="checkData[index].childList[x].standVal"/></el-form-item> + </el-form> + </div> + </div> + <div v-else>暂无物资配置数据</div> + </el-tab-pane> + </el-tabs> + <div v-if="chosenIndex != null" style="color: #79bbff">注:修改配置数据须重新填写配置</div> + </el-form-item> + <el-form-item label="描述" prop="info"> + <el-input v-model="addRecord.info" type="textarea" autosize :rows="2"/> + </el-form-item> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button type="warning" @click="dialogAddRecord = false" size="default" plain>取消</el-button> + <el-button type="primary" @click="confirmAddRecord(addRef)" size="default">确认</el-button> + </span> + </template> + </el-dialog> + <el-dialog v-model="deleteDialog" title="提示" width="30%" center @close="indexClear"> + <span>您确定要删除该条记录吗?</span> + <template #footer> + <span class="dialog-footer"> + <el-button @click="deleteDialog = false" size="default">取消</el-button> + <el-button type="primary" @click="conFirmDelete" size="default">确认</el-button> + </span> + </template> + </el-dialog> +<!-- <el-dialog v-model="deleteSetDialog" title="提示" width="30%" center>--> +<!-- <span>您确定要删除这些记录吗?</span>--> +<!-- <template #footer>--> +<!-- <span class="dialog-footer">--> +<!-- <el-button @click="deleteSetDialog = false" size="default">取消</el-button>--> +<!-- <el-button type="primary" @click="conFirmDeleteBatch" size="default">确认</el-button>--> +<!-- </span>--> +<!-- </template>--> +<!-- </el-dialog>--> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, ref, onMounted } from 'vue'; +import { storeToRefs } from 'pinia'; +import { initBackEndControlRoutes } from '/@/router/backEnd'; +import { useUserInfo } from '/@/stores/userInfo'; +import { Session } from '/@/utils/storage'; +import { Edit, View, Plus, Delete, Refresh, Search, Download } from '@element-plus/icons-vue'; +import { ElMessage, ElTable } from 'element-plus' +import type { FormInstance, FormRules } from 'element-plus' +import { teamManageApi } from '/@/api/systemManage/basicDateManage/personShiftManage/teamManage'; +import { materialApi } from '/@/api/specialWorkSystem/material'; + +// 定义接口来定义对象的类型 +interface stateType { + tableData: Array<any>; + allList: Array<any>; + departmentList: Array<any>; + casProps: {}; + multipleSelection: Array<any>; + deleteArr: Array<any>; + dialogDetails: boolean; + dialogAddRecord: boolean; + deleteDialog: boolean; + deleteSetDialog: boolean; + pageIndex: number; + pageSize: number; + chosenIndex: null | number; + deleteId: null | number; + searchType: null | number; + searchLevel: null | number; + searchName: string; + totalSize: number; + checkData: Array<any>; + workTypeList: Array<any>; + workLevelList: Array<any>; + fireLevel: Array<any>; + hoistLevel: Array<any>; + heightLevel: Array<any>; + plateLevel: Array<any>; + mustList: Array<string>; + chooseList: Array<string>; + highList: Array<string>; + addRecord: { + + }; + details: { + + }; +} + +export default { + name: 'material', + components: {}, + setup() { + const userInfo = useUserInfo(); + const { userInfos } = storeToRefs(userInfo); + + const state = reactive<stateType>({ + pageIndex: 1, + pageSize: 10, + totalSize: 0, + checkData: [], + chosenIndex: null, + searchType: null, + searchLevel: null, + searchName: '', + tableData: [], + allList: [], + departmentList: [], + mustList: [], + chooseList: [], + highList: [], + workTypeList: [ + { + label: "动火作业", + value: 1 + }, + { + label: "受限空间作业", + value: 2 + }, + { + label: "吊装作业", + value: 3 + }, + { + label: "动土作业", + value: 4 + }, + { + label: "断路作业", + value: 5 + }, + { + label: "高处作业", + value: 6 + }, + { + label: "临时用电作业", + value: 7 + }, + { + label: "盲板抽堵作业", + value: 8 + } + ], + workLevelList: [ + { + label: "动火作业", + value: 1 + }, + { + label: "受限空间作业", + value: 2 + }, + { + label: "吊装作业", + value: 3 + }, + { + label: "动土作业", + value: 4 + }, + { + label: "断路作业", + value: 5 + }, + { + label: "高处作业", + value: 6 + }, + { + label: "临时用电作业", + value: 7 + }, + { + label: "盲板抽堵作业", + value: 8 + } + ], + fireLevel: [ + { + label: "一级动火作业", + value: 1 + }, + { + label: "二级动火作业", + value: 2 + }, + { + label: "特级动火作业", + value: 3 + } + ], + hoistLevel: [ + { + label: "一级吊装作业", + value: 8 + }, + { + label: "二级吊装作业", + value: 9 + }, + { + label: "三级吊装作业", + value: 10 + } + ], + heightLevel: [ + { + label: "一级高处作业", + value: 4 + }, + { + label: "二级高处作业", + value: 5 + }, + { + label: "三级高处作业", + value: 6 + }, + { + label: "特级高处作业", + value: 7 + } + ], + plateLevel: [ + { + label: "抽盲板作业", + value: 11 + }, + { + label: "堵盲板作业", + value: 12 + } + ], + casProps: { + expandTrigger: 'hover', + emitPath: false, + value: 'depId', + label: 'depName' + }, + multipleSelection: [], + dialogDetails: false, + dialogAddRecord: false, + deleteDialog: false, + deleteSetDialog: false, + addRecord: { + + }, + details: { + + }, + deleteId: null, + deleteArr: [] + }); + interface User { + groupName: string; + department: number | null; + depId: number; + groupMembers: Array<any>; + groupInfo: string; + } + // const multipleTableRef = ref<InstanceType<typeof ElTable>>(); + // const toggleSelection = (rows?: User[]) => { + // if (rows) { + // rows.forEach((row) => { + // // TODO: improvement typing when refactor table + // // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // // @ts-expect-error + // multipleTableRef.value!.toggleRowSelection(row, undefined); + // }); + // } else { + // multipleTableRef.value!.clearSelection(); + // } + // }; + + // 多选 + // const handleSelectionChange = (val: User[]) => { + // state.multipleSelection = JSON.parse(JSON.stringify(val)); + // state.deleteArr = state.multipleSelection.map((item) => { + // item = item.id; + // return item; + // }); + // }; + + const addRef = ref<FormInstance>(); + const addListRef = ref<FormInstance>(); + const addRules = reactive<FormRules>({ + name: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + workType: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + workLevel: [{ required: true, message: '该内容不能为空', trigger: 'blur' }] + }); + const addListRules = reactive<FormRules>({ + standVal: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + configurationLevel: [{ required: true, message: '该内容不能为空', trigger: 'blur' }] + }); + + // 页面载入时执行方法 + onMounted(() => { + getListByPage() + }); + + const toType = (row, column, cellValue, index) => { + return state.workTypeList.find((item) => item.value === row.workType)?.label; + }; + + const toLevel = (row, column, cellValue, index) => { + if(row.workLevel == null){ + return '无' + }else{ + if(row.workLevel <= 3){ + return state.fireLevel.find((item) => item.value === row.workLevel)?.label; + }else if(row.workLevel>3 && row.workLevel<=7){ + return state.heightLevel.find((item) => item.value === row.workLevel)?.label; + }else if(row.workLevel>8 && row.workLevel<=10){ + return state.hoistLevel.find((item) => item.value === row.workLevel)?.label; + }else{ + return state.plateLevel.find((item) => item.value === row.workLevel)?.label; + } + } + }; + + const getList = async ()=>{ + let res = await materialApi().getRecordList(); + if (res.data.code === '200') { + state.allList = JSON.parse(JSON.stringify(res.data.data)) + for(let i in state.allList){ + state.allList[i].childList = state.allList[i].childList?.map((item:any) => { + const obj = { + checked: false, + materialClassifyName: item.materialClassifyName, + standVal: 0, + configurationLevel: null, + smallClassifyId: item.id + } + return {...obj} + }) + } + state.checkData = JSON.parse(JSON.stringify(state.allList)) + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } + + // 分页获取物资标准列表 + const getListByPage = async () => { + const data = { pageSize: state.pageSize, pageIndex: state.pageIndex, searchParams: { workType: state.searchType, workLevel: state.searchLevel, name: state.searchName } }; + let res = await materialApi().getRecordPage(data); + if (res.data.code === '200') { + // state.tableData = res.data.data.map((item) => { + // if (!item.groupMembers || item.groupMembers == null) { + // item.groupMembers = []; + // } else { + // item.groupMembers = Array.from(item.groupMembers, ({ username }) => username); + // } + // return item; + // }); + state.tableData = res.data.data + state.totalSize = res.data.total; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 获取部门列表 + const getAllDepartment = async () => { + let res = await teamManageApi().getAllDepartment(); + if (res.data.code === '200') { + state.departmentList = res.data.data; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 关键词查询记录 + const searchRecord = async () => { + if (state.searchType == null && state.searchLevel == null && state.searchName == '') { + ElMessage({ + type: 'warning', + message: '请输入查询关键词' + }); + } else { + getListByPage(); + } + }; + + const clearSearch = async () => { + state.searchType = null + state.searchLevel = null + state.searchName = '' + getListByPage(); + }; + + const addRecordBtn = () =>{ + getList() + state.dialogAddRecord = true + } + + // 添加方法 + const addRecord = async (data: any) => { + let res = await materialApi().addRecord(data); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '添加成功!' + }); + getListByPage(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 修改方法 + const editRecordBtn = async (index, row) => { + getList() + state.addRecord = JSON.parse(JSON.stringify(row)); + state.dialogAddRecord = true; + state.chosenIndex = index; + }; + + const editRecord = async (data: any) => { + let res = await materialApi().updateRecord(data); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '修改成功!' + }); + getListByPage(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 新增修改记录 + const confirmAddRecord = async (formEl: FormInstance | undefined) => { + if (!formEl) return; + await formEl.validate(async (valid, fields) => { + if (valid) { + state.addRecord.materialDetailList = [] + for(let i in state.checkData){ + if(state.checkData[i].childList && state.checkData[i].childList.length>0){ + for(let j=0;j<state.checkData[i].childList.length;j++){ + if(state.checkData[i].childList[j].checked){ + // delete state.checkData[i].list[j].checked + // state.checkData[i].list[j].checked + let { checked,materialClassifyName,...checkObj } = state.checkData[i].childList[j] + state.addRecord.materialDetailList.push(checkObj) + } + } + } + } + const data = { + name: state.addRecord.name, + workType: state.addRecord.workType, + workLevel: state.addRecord.workLevel, + info: state.addRecord.info, + materialDetailList: state.addRecord.materialDetailList + }; + if(data.materialDetailList.length==0 || data.materialDetailList.some((e) => e.configurationLevel == null)){ + ElMessage({ + type: 'warning', + message: '请选择物资配置并完善必填数据' + }); + return + } + if(data.materialDetailList.some((e) => e.configurationLevel == 0 && e.standVal <= 0)){ + ElMessage({ + type: 'warning', + message: '必选物资标准值须大于0' + }); + return + } + if (state.chosenIndex == null) { + await addRecord(data); + } else { + data.id = state.addRecord.id; + await editRecord(data); + } + state.dialogAddRecord = false; + } else { + console.log('error submit!', fields); + } + }); + }; + + // 删除方法 + const deleteRecord = async (data: any) => { + let res = await materialApi().deleteRecord(data); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '删除成功!' + }); + getListByPage(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + const deleteRecordBtn = (row) => { + state.deleteId = row.id; + state.deleteDialog = true; + }; + + const conFirmDelete = () => { + deleteRecord({ id: state.deleteId }); + state.deleteDialog = false; + }; + + // 批量删除 + // const deleteBatchBtn = async () => { + // ElMessage({ + // type: 'warning', + // message: '抱歉,本页面暂不支持批量删除' + // }); + // if (state.deleteArr.length > 0) { + // state.deleteSetDialog = true + // } else { + // ElMessage({ + // type: 'warning', + // message: '请先选择要删除的记录' + // }); + // } + // }; + + // const conFirmDeleteBatch = async () => { + // let res = await teamManageApi().deletBatchRecord({ids: state.deleteArr}); + // if (res.data.code === '200') { + // state.deleteSetDialog = false + // ElMessage({ + // type: 'success', + // message: res.data.msg + // }); + // getListByPage() + // } else { + // ElMessage({ + // type: 'warning', + // message: res.data.msg + // }); + // state.deleteSetDialog = false + // } + // } + + const handleSizeChange = (val: number) => { + state.pageSize = val; + getListByPage(); + }; + const handleCurrentChange = (val: number) => { + state.pageIndex = val; + getListByPage(); + }; + + // 查看记录 + const viewRecord = (row) => { + state.details = JSON.parse(JSON.stringify(row)); + state.details.workType = toType(state.details) + state.details.workLevel = toLevel(state.details) + state.dialogDetails = true; + }; + + const clearList = ()=>{ + state.mustList = [] + state.chooseList = [] + state.highList = [] + } + + // 刷新 + const reLoadData = async () => { + getListByPage(); + }; + + const closeAdd = () => { + state.addRecord = {}; + state.chosenIndex = null; + }; + const openAdd = () => { + if (state.chosenIndex == null) { + state.addRecord.info = ''; + } + }; + const indexClear = () => { + state.deleteId = null; + }; + + // 折线图 + const renderMenu = async (value: string) => { + Session.set('projectId', value); + userInfos.value.projectId = value; + await initBackEndControlRoutes(); + }; + return { + addRef, + addListRef, + addRules, + addListRules, + View, + Edit, + Delete, + Refresh, + Plus, + addRecordBtn, + toType, + toLevel, + searchRecord, + clearSearch, + viewRecord, + clearList, + deleteRecordBtn, + conFirmDelete, + getListByPage, + reLoadData, + deleteRecord, + handleSizeChange, + handleCurrentChange, + confirmAddRecord, + closeAdd, + openAdd, + indexClear, + editRecordBtn, + ...toRefs(state) + }; + } +}; +</script> + +<style scoped lang="scss"> +$homeNavLengh: 8; +.home-container { + height: calc(100vh - 144px); + box-sizing: border-box; + overflow: hidden; + .homeCard { + width: 100%; + padding: 20px; + box-sizing: border-box; + background: #fff; + border-radius: 4px; + + .main-card { + width: 100%; + height: 100%; + .cardTop { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 20px; + .mainCardBtn { + margin: 0; + } + } + .pageBtn { + height: 60px; + display: flex; + align-items: center; + justify-content: right; + + .demo-pagination-block + .demo-pagination-block { + margin-top: 10px; + } + .demo-pagination-block .demonstration { + margin-bottom: 16px; + } + } + } + &:last-of-type { + height: calc(100% - 100px); + } + } + .el-row { + display: flex; + align-items: center; + margin-bottom: 20px; + &:last-child { + margin-bottom: 0; + } + .grid-content { + align-items: center; + min-height: 36px; + } + + .topInfo { + width: 100%; + display: flex; + align-items: center; + font-size: 16px; + font-weight: bold; + + & > div { + white-space: nowrap; + margin-right: 20px; + } + } + } +} +.materials{ + width: 100%; + border: 1px solid #ccc; + .maList{ + width: 100%; + display: flex; + align-items: center; + border-bottom: 1px solid #ccc; + &:last-of-type{ + border-bottom: none; + } + + &>div:first-of-type{ + width: 20%; + text-align: center; + margin-right: 20px; + padding: 5px 10px; + border-right: 1px solid #ccc; + } + &>div{ + height: 100%; + div{ + height: 100%; + line-height: 24px; + } + } + } +} + +.el-input { + width: 100% !important; +} +.el-date-editor::v-deep { + width: 100%; +} +.el-select { + width: 100% !important; +} +.el-tabs{ + width: 100%; +} +::v-deep(.el-date-editor){ + width: 100%; +} + +:deep(.el-cascader){ + width: 100% !important; +} + +.tab-i{ + margin-bottom: 20px; + + .el-form-item{ + margin-bottom: 20px; + } +} +</style> diff --git a/src/views/specialWorkSystem/foundationSet/safetyAction/components/safetyActionDialog.vue b/src/views/specialWorkSystem/foundationSet/safetyAction/components/safetyActionDialog.vue new file mode 100644 index 0000000..5f2fde5 --- /dev/null +++ b/src/views/specialWorkSystem/foundationSet/safetyAction/components/safetyActionDialog.vue @@ -0,0 +1,221 @@ +<template> + <div class="system-add-menu-container"> + <el-dialog :title="title" v-model="isShowSafetyActionDialog" width="600px" :close-on-click-modal="false"> + <el-form :model="safetyActionForm" :rules="safetyActionFormRules" ref="safetyActionFormRef" size="default" label-width="120px"> + <el-row :gutter="35"> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="作业类型" prop="workType"> + <el-select class="input-add" :disabled="!disabled" v-model="safetyActionForm.workType" placeholder="请选择作业类型" filterable clearable> + <el-option v-for="item in workTypeList" :key="item.id" :label="item.name" :value="item.id"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="措施类型" prop="type"> + <el-select class="input-add" :disabled="!disabled" v-model="safetyActionForm.type" placeholder="请选择措施类型" clearable filterable> + <el-option v-for="item in typeList" :key="item.id" :label="item.name" :value="item.id"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col v-if="safetyActionForm.type === 1" :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="正确值" prop="correctVal"> + <el-select class="input-add" :disabled="!disabled" v-model="safetyActionForm.correctVal" placeholder="请选择正确值" clearable filterable> + <el-option v-for="item in typeTwoList" :key="item.id" :label="item.name" :value="item.id"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="措施内容" prop="context"> + <el-input class="input-add" :disabled="!disabled" :rows="3" v-model.trim="safetyActionForm.context" type="textarea" placeholder="请输入描述"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20" v-show="personTime"> + <el-form-item label="创建人" prop="location"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="safetyActionForm.createUname"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20" v-show="personTime"> + <el-form-item label="创建时间" prop="location"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="safetyActionForm.gmtCreate"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20" v-show="personTime"> + <el-form-item label="最后修改人" prop="location"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="safetyActionForm.modifiedUname"></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20" v-show="personTime"> + <el-form-item label="最后修改时间" prop="location"> + <el-input class="input-add" :disabled="!disabled" v-model.trim="safetyActionForm.gmtModified"></el-input> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer" v-show="disabled"> + <el-button @click="isShowSafetyActionDialog = !isShowSafetyActionDialog" size="default">取 消</el-button> + <el-button type="primary" @click="submitSafetyAction" v-throttle size="default">确 定</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script lang="ts"> +interface stateType { + isShowSafetyActionDialog: Boolean; + disabled: Boolean; + personTime: Boolean; + safetyActionForm: { + workType: number | null; + type: number | null; + correctVal: number | null; + context: string | null; + }; + title: string; + departmentList: []; + workTypeList: Array<levelListState>; + typeList: Array<levelListState>; + typeTwoList: Array<levelListState>; + safetyActionFormRules: {}; +} +interface levelListState { + id: number; + name: string; +} + +import { reactive, toRefs, ref } from 'vue'; +import { safetyActionApi } from '/@/api/specialWorkSystem/safetyAction'; +import { ElMessage } from 'element-plus'; +export default { + name: 'SafetyActionDialog', + setup(props: any, context: any) { + const safetyActionFormRef = ref(); + const state = reactive<stateType>({ + title: '', + disabled: false, + personTime: false, + departmentList: [], + isShowSafetyActionDialog: false, + workTypeList: [ + { id: 1, name: '动火作业' }, + { id: 2, name: '受限空间作业' }, + { id: 3, name: '吊装作业' }, + { id: 4, name: '动土作业' }, + { id: 5, name: '断路作业' }, + { id: 6, name: '高处作业' }, + { id: 7, name: '临时用电作业' }, + { id: 8, name: '盲板抽堵作业' } + ], + typeList: [ + { id: 1, name: '选择' }, + { id: 2, name: '填空' } + ], + typeTwoList: [ + { id: 1, name: '是' }, + { id: 2, name: '否' } + ], + safetyActionForm: { + workType: null, + type: null, + correctVal: null, + context: null + }, + safetyActionFormRules: { + workType: [{ required: true, message: '请选择作业类型', trigger: 'change' }], + type: [{ required: true, message: '请选择措施类型', trigger: 'change' }], + correctVal: [{ required: true, message: '请选择正确值', trigger: 'change' }], + context: [{ required: true, message: '请填写措施内容', trigger: 'blur' }] + } + }); + + //打开模态框 + const showSafetyActionDialog = (type: string, value: object, department: []) => { + state.isShowSafetyActionDialog = true; + state.departmentList = department; + setTimeout(() => { + safetyActionFormRef.value.clearValidate(); + }); + if (type === '新增') { + state.disabled = true; + state.personTime = false; + state.title = '新增安全措施'; + state.safetyActionForm = { + workType: null, + type: null, + correctVal: null, + context: null + }; + } else if (type === '查看') { + state.disabled = false; + state.personTime = true; + state.title = '查看安全措施'; + state.safetyActionForm = JSON.parse(JSON.stringify(value)); + } else { + state.disabled = true; + state.personTime = false; + state.title = '修改安全措施'; + state.safetyActionForm = JSON.parse(JSON.stringify(value)); + // for (let i in state.SafetyActionForm) { + // state.SafetyActionForm[i] = SafetyActionForm[i]; + // } + } + }; + + //新增修改提交 + const submitSafetyAction = async () => { + safetyActionFormRef.value.validate(async (valid: Boolean) => { + if (valid) { + if (state.title === '新增安全措施') { + let res = await safetyActionApi().addSafetyAction(state.safetyActionForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '安全措施新增成功', + duration: 2000 + }); + state.isShowSafetyActionDialog = false; + context.emit('refreshSafetyAction'); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } else { + let res = await safetyActionApi().modSafetyAction(state.safetyActionForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '安全措施改成功', + duration: 2000 + }); + state.isShowSafetyActionDialog = false; + context.emit('refreshSafetyAction'); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } + } else { + ElMessage({ + type: 'warning', + message: '请完善基本信息' + }); + } + }); + }; + + return { + ...toRefs(state), + safetyActionFormRef, + submitSafetyAction, + showSafetyActionDialog + }; + } +}; +</script> + +<style scoped></style> diff --git a/src/views/specialWorkSystem/foundationSet/safetyAction/index.vue b/src/views/specialWorkSystem/foundationSet/safetyAction/index.vue new file mode 100644 index 0000000..daae169 --- /dev/null +++ b/src/views/specialWorkSystem/foundationSet/safetyAction/index.vue @@ -0,0 +1,453 @@ +<template> + <div class="home-container"> + <div style="height: 100%"> + <el-row class="homeCard"> + <div class="basic-line"> + <span>作业类型:</span> + <el-select v-model="tableData.params.searchParams.workType" clearable filterable class="input-box" placeholder="作业类型"> + <el-option v-for="item in workTypeList" :key="item.id" :label="item.name" :value="item.id"></el-option> + </el-select> + </div> + <div class="basic-line"> + <span>措施类型:</span> + <el-select v-model="tableData.params.searchParams.type" clearable filterable class="input-box" placeholder="措施类型"> + <el-option v-for="item in typeList" :key="item.id" :label="item.name" :value="item.id"></el-option> + </el-select> + </div> + <div class="basic-line"> + <span>措施内容:</span> + <el-input v-model.trim="tableData.params.searchParams.context" class="input-box" placeholder="措施内容"> </el-input> + </div> + <div style="padding-bottom: 10px"> + <el-button type="primary" @click="initSafetyAction">查询</el-button> + <el-button plain @click="reset">重置</el-button> + </div> + </el-row> + <div class="homeCard"> + <div class="main-card"> + <el-row class="cardTop"> + <el-col :span="12" class="mainCardBtn"> + <el-button type="primary" :icon="Plus" size="default" @click="openSafetyActionDialog('新增', {})">新增</el-button> + <el-button type="danger" :icon="Delete" size="default" @click="deleteMoreSafetyAction" plain>批量删除</el-button> + </el-col> + <el-button type="primary" :icon="Refresh" size="default" /> + </el-row> + <el-table ref="multipleTableRef" :data="tableData.safetyActionData" style="width: 100%" height="calc(100% - 100px)" :header-cell-style="{ background: '#fafafa' }" @selection-change="handleSelectionChange"> + <el-table-column type="selection" width="55" /> + <el-table-column property="workType" label="作业类型"> + <template #default="scope"> + <span> + {{ parseNumber(scope.row.workType, '作业类型') }} + </span> + </template> + </el-table-column> + <el-table-column property="type" label="措施类型"> + <template #default="scope"> + <span> + {{ parseNumber(scope.row.type, '措施类型') }} + </span> + </template> + </el-table-column> + <el-table-column property="context" label="措施内容" show-overflow-tooltip></el-table-column> + <el-table-column prop="correctVal" label="正确值" show-overflow-tooltip> + <template #default="scope"> + <span> + {{ parseNumber(scope.row.correctVal, '正确值') }} + </span> + </template> + </el-table-column> + <el-table-column prop="createUname" label="创建人" show-overflow-tooltip></el-table-column> + <el-table-column prop="gmtCreate" label="创建时间" show-overflow-tooltip></el-table-column> + <el-table-column prop="modifiedUname" label="最后修改人" show-overflow-tooltip></el-table-column> + <el-table-column prop="gmtModified" label="最后修改时间" show-overflow-tooltip></el-table-column> +<!-- <el-table-column property="status" label="状态" width="60" />--> + <el-table-column fixed="right" label="操作" align="center" width="300"> + <template #default="scope"> + <el-button link type="primary" size="small" :icon="View" @click="openSafetyActionDialog('查看', scope.row)">查看</el-button> + <el-button link type="primary" size="small" :icon="Edit" @click="openSafetyActionDialog('修改', scope.row)">修改</el-button> + <el-button link type="danger" size="small" :icon="Delete" @click="deleteSafetyAction(scope.row)">删除</el-button> + </template> + </el-table-column> + </el-table> + <br /> + <el-pagination @size-change="onHandleSizeChange" @current-change="onHandleCurrentChange" :pager-count="5" :page-sizes="[10, 20, 30]" v-model:current-page="tableData.params.pageIndex" background v-model:page-size="tableData.params.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="tableData.total" class="page-position"> </el-pagination> + </div> + </div> + </div> + <safety-action-dialog ref="safetyActionDialogRef" @refreshSafetyAction="initSafetyAction"></safety-action-dialog> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, ref, onMounted } from 'vue'; +import { Edit, View, Plus, Delete, Refresh, Search, Download } from '@element-plus/icons-vue'; +import { ElTable, ElMessage, ElMessageBox } from 'element-plus'; +import { safetyActionApi } from '/@/api/specialWorkSystem/safetyAction/index.ts'; +import { departmentApi } from '/@/api/systemManage/department'; +import safetyActionDialog from '/@/views/specialWorkSystem/foundationSet/safetyAction/components/safetyActionDialog.vue'; +let global: any = { + homeChartOne: null, + homeChartTwo: null, + homeCharThree: null, + dispose: [null, '', undefined] +}; + +interface stateType { + tableData: { + safetyActionData: []; + total: number; + loading: boolean; + params: { + pageIndex: number | null; + pageSize: number | null; + searchParams: { + workType: number | null; + type: number | null; + context: string | null; + }; + }; + }; + workTypeList: Array<type>; + typeList: Array<type>; + typeTwoList: Array<type>; + deleteList: { + ids: Array<number>; + }; +} +interface type { + id: number; + name: string; +} +interface ruleType { + id: number; +} +export default { + name: 'index', + components: { safetyActionDialog }, + setup() { + const safetyActionDialogRef = ref(); + const state = reactive<stateType>({ + tableData: { + safetyActionData: [], + total: 0, + loading: false, + params: { + pageIndex: 1, + pageSize: 10, + searchParams: { + workType: null, + type: null, + context: null + } + } + }, + workTypeList: [ + { id: 1, name: '动火作业' }, + { id: 2, name: '受限空间作业' }, + { id: 3, name: '吊装作业' }, + { id: 4, name: '动土作业' }, + { id: 5, name: '断路作业' }, + { id: 6, name: '高处作业' }, + { id: 7, name: '临时用电作业' }, + { id: 8, name: '盲板抽堵作业' } + ], + typeList: [ + { id: 1, name: '选择' }, + { id: 2, name: '填空' } + ], + typeTwoList: [ + { id: 1, name: '是' }, + { id: 2, name: '否' } + ], + deleteList: { + ids: [] + } + }); + + //获取巡检任务数据 + const initSafetyAction = async () => { + let res = await safetyActionApi().getSafetyActionList(state.tableData.params); + if (res.data.code === '200') { + state.tableData.safetyActionData = res.data.data; + state.tableData.total = res.data.total; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // //获取部门 + // const getDepartmentData = async () => { + // let res = await departmentApi().getDepartmentList(); + // if (res.data.code === '200') { + // state.departmentList = res.data.data; + // } else { + // ElMessage({ + // type: 'warning', + // message: res.data.msg + // }); + // } + // }; + + // 删除 + const deleteMoreSafetyAction = () => { + ElMessageBox.confirm(`此操作将永久删除该措施,是否继续?`, '提示', { + confirmButtonText: '确认', + cancelButtonText: '取消', + type: 'warning' + }) + .then(async () => { + let res = await safetyActionApi().deleteSafetyAction(state.deleteList); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + duration: 2000, + message: '删除成功' + }); + await initSafetyAction(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }) + .catch(() => {}); + }; + + // 删除 + const deleteSafetyAction = (row: any) => { + ElMessageBox.confirm(`此操作将永久删除该措施,是否继续?`, '提示', { + confirmButtonText: '确认', + cancelButtonText: '取消', + type: 'warning' + }) + .then(async () => { + let res = await safetyActionApi().deleteSafetyAction({ ids: [row.id] }); + if (res.data.code === '200') { + state.deleteList.ids = []; + ElMessage({ + type: 'success', + duration: 2000, + message: '删除成功' + }); + await initSafetyAction(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }) + .catch(() => {}); + }; + + const handleSelectionChange = (val: Array<ruleType>) => { + state.deleteList.ids = val.map((item) => { + return item.id; + }); + }; + + const openSafetyActionDialog = (type: string, value: {}) => { + safetyActionDialogRef.value.showSafetyActionDialog(type, value); + }; + + const parseNumber = (value: number, type: string) => { + if (type === '作业类型') { + return state.workTypeList.find((item) => item.id === value)?.name; + } else if (type === '正确值') { + return state.typeTwoList.find((item) => item.id == value)?.name; + } else { + return state.typeList.find((item) => item.id == value)?.name; + } + }; + + // 分页改变 + const onHandleSizeChange = (val: number) => { + state.tableData.params.pageSize = val; + initSafetyAction(); + }; + // 分页改变 + const onHandleCurrentChange = (val: number) => { + state.tableData.params.pageIndex = val; + initSafetyAction(); + }; + + const reset = () => { + state.tableData.params = { + pageIndex: 1, + pageSize: 10, + searchParams: { + workType: null, + type: null, + context: null + } + }; + }; + + // 页面加载时 + onMounted(() => { + initSafetyAction(); + }); + + return { + View, + Edit, + Delete, + Refresh, + Plus, + reset, + parseNumber, + handleSelectionChange, + deleteSafetyAction, + deleteMoreSafetyAction, + initSafetyAction, + onHandleSizeChange, + onHandleCurrentChange, + safetyActionDialogRef, + openSafetyActionDialog, + ...toRefs(state) + }; + } +}; +</script> + +<style scoped lang="scss"> +$homeNavLengh: 8; +.home-container { + height: calc(100vh - 144px); + box-sizing: border-box; + overflow: hidden; + .homeCard { + width: 100%; + padding: 20px; + box-sizing: border-box; + background: #fff; + border-radius: 4px; + + .main-card { + width: 100%; + height: 100%; + .cardTop { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 20px; + .mainCardBtn { + margin: 0; + } + } + .pageBtn { + height: 60px; + display: flex; + align-items: center; + justify-content: right; + + .demo-pagination-block + .demo-pagination-block { + margin-top: 10px; + } + .demo-pagination-block .demonstration { + margin-bottom: 16px; + } + } + } + &:last-of-type { + height: calc(100% - 100px); + } + } + .el-row { + display: flex; + align-items: center; + margin-bottom: 20px; + &:last-child { + margin-bottom: 0; + } + .grid-content { + align-items: center; + min-height: 36px; + } + + .topInfo { + display: flex; + align-items: center; + font-size: 16px; + font-weight: bold; + + & > div { + white-space: nowrap; + margin-right: 20px; + } + } + } +} +.stepItem { + width: 100%; + display: flex; + align-items: flex-start; + margin-bottom: 30px; + margin-left: 30px; + padding-bottom: 30px; + border-left: 2px solid #ccc; + &:first-of-type { + margin-top: 30px; + } + &:last-of-type { + margin-bottom: 0; + border-left: none; + } + .stepNum { + width: 30px; + height: 30px; + border-radius: 15px; + box-sizing: border-box; + color: #333; + border: 1px solid #999; + line-height: 28px; + text-align: center; + margin-right: 10px; + margin-left: -16px; + margin-top: -30px; + } + .stepCard { + width: 100%; + margin-top: -30px; + + .box-card { + width: 100%; + &:deep(.el-card__header) { + padding: 10px 15px; + } + .card-header { + width: 100%; + display: flex; + justify-content: space-between; + align-items: center; + & > div:first-of-type { + margin-right: 80px; + font-size: 18px; + font-weight: bold; + } + } + } + } + &:hover .card-header { + color: #0098f5; + } + &:hover .stepNum { + border: 2px solid #0098f5; + color: #0098f5; + } +} +:deep(.el-textarea.is-disabled .el-textarea__inner) { + background-color: var(--el-card-bg-color); + color: var(--el-input-text-color, var(--el-text-color-regular)); +} +:deep(.el-input.is-disabled .el-input__inner) { + color: var(--el-input-text-color, var(--el-text-color-regular)); +} +:deep(.el-input.is-disabled .el-input__wrapper) { + background-color: var(--el-card-bg-color); +} +</style> diff --git a/src/views/specialWorkSystem/plan/appoint/index.vue b/src/views/specialWorkSystem/plan/appoint/index.vue new file mode 100644 index 0000000..809898b --- /dev/null +++ b/src/views/specialWorkSystem/plan/appoint/index.vue @@ -0,0 +1,616 @@ +<template> + <div class="home-container"> + <div style="height: 100%"> + <el-row class="homeCard"> + <el-col :span="6" style="display:flex;align-items: center"> + <span style="white-space: nowrap">申请部门:</span> + <div class="grid-content topInfo"> + <el-cascader v-model="searchDep" :options="departmentList" :props="casProps" :show-all-levels="false"/> + </div> + </el-col> + <el-col :span="6" style="display:flex;align-items: center;"> + <span style="white-space: nowrap;margin-left: 20px">预约日期:</span> + <div class="grid-content topInfo"> + <el-date-picker + v-model="searchDate" + type="date" + format="YYYY-MM-DD" value-format="YYYY-MM-DD" + /> + </div> + </el-col> + <el-button style="margin-left: 20px" type="primary" @click="searchRecord">查询</el-button> + <el-button plain @click="clearSearch">重置</el-button> + </el-row> + <div class="homeCard"> + <div class="main-card"> +<!-- <el-row class="cardTop">--> +<!-- <el-col :span="12" class="mainCardBtn">--> +<!-- <el-button type="primary" :icon="Plus" size="default" @click="dialogAddRecord = true">新增</el-button>--> +<!-- </el-col>--> +<!-- <el-button type="primary" :icon="Refresh" size="default" @click="reLoadData"/>--> +<!-- </el-row>--> + <el-table + :data="tableData" + style="width: 100%" + height="calc(100% - 48px)" + :header-cell-style="{background: '#fafafa'}" + > +<!-- <el-table-column type="selection" width="55" />--> + <el-table-column type="index" label="序号" width="80" /> + <el-table-column prop="applyDepName" align="center" label="申请部门"/> + <el-table-column prop="appointmentTime" align="center" label="预约时间"/> + <el-table-column prop="hotWork" align="center" label="动火作业"/> + <el-table-column prop="confinedSpaceOper" align="center" label="受限空间作业"/> + <el-table-column prop="liftingOper" align="center" label="吊装作业"/> + <el-table-column prop="groundBreakingOper" align="center" label="动土作业"/> + <el-table-column prop="openCircuitOper" align="center" label="断路作业"/> + <el-table-column prop="workAtHeight" align="center" label="高处作业" /> + <el-table-column prop="temporaryPowerOper" align="center" label="临时用电作业"/> + <el-table-column prop="blindPlatePluggingOper" align="center" label="盲板抽堵作业"/> + <el-table-column fixed="right" label="操作" align="center" width="250"> + <template #default="scope"> + <el-button link type="primary" size="small" :icon="View" @click="viewRecord(scope.row)">查看</el-button> +<!-- <el-button link type="primary" size="small" :icon="Edit" @click="editRecordBtn(scope.$index, scope.row)">修改</el-button>--> +<!-- <el-button link type="danger" size="small" :icon="Delete" @click="deleteRecordBtn(scope.row)">删除</el-button>--> + </template> + </el-table-column> + </el-table> + <div class="pageBtn"> + <el-pagination + v-model:currentPage="currentPage" + v-model:page-size="pageSize" + :page-sizes="[10, 15]" + small=false + background + layout="total, sizes, prev, pager, next, jumper" + :total="totalSize" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + </div> + </div> + </div> + <el-dialog v-model="dialogDetails" title="作业预约"> + <el-form :model="details" label-width="120px"> + <el-form-item label="申请部门"> + <el-input + v-model="details.applyDepName" + readonly + /> + </el-form-item> + <el-form-item label="预约时间"> + <el-input + v-model="details.appointmentTime" + readonly + /> + </el-form-item> + <el-form-item label="动火作业"> + <el-input + v-model="details.hotWork" + readonly + /> + </el-form-item> + <el-form-item label="受限空间作业"> + <el-input + v-model="details.confinedSpaceOper" + readonly + /> + </el-form-item> + <el-form-item label="吊装作业"> + <el-input + v-model="details.liftingOper" + readonly + /> + </el-form-item> + <el-form-item label="动土作业"> + <el-input + v-model="details.groundBreakingOper" + readonly + /> + </el-form-item> + <el-form-item label="断路作业"> + <el-input + v-model="details.openCircuitOper" + readonly + /> + </el-form-item> + <el-form-item label="高处作业"> + <el-input + v-model="details.workAtHeight" + readonly + /> + </el-form-item> + <el-form-item label="临时用电作业"> + <el-input + v-model="details.temporaryPowerOper" + readonly + /> + </el-form-item> + <el-form-item label="盲板抽堵作业"> + <el-input + v-model="details.blindPlatePluggingOper" + readonly + /> + </el-form-item> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button type="primary" @click="dialogDetails = false">确认</el-button> + </span> + </template> + </el-dialog> + <el-dialog v-model="dialogAddRecord" title="作业预约编辑" @close="closeAdd"> + <el-form :model="addRecord" label-width="120px" ref="addRef" :rules="addRules"> + <el-form-item label="申请部门" prop="applyDepId"> + <el-cascader :disabled = isDisabled v-model="addRecord.applyDepId" :options="departmentList" :props="casProps" :show-all-levels="false" @change="handleChange" /> + </el-form-item> + <el-form-item label="预约时间" prop="appointmentTime"> + <el-date-picker + v-model="addRecord.appointmentTime" + type="date" + format="YYYY-MM-DD" value-format="YYYY-MM-DD" + :disabled = isDisabled + /> + </el-form-item> + <el-form-item label="动火作业" prop="hotWork"> + <el-input + v-model="addRecord.hotWork" + /> + </el-form-item> + <el-form-item label="受限空间作业" prop="confinedSpaceOper"> + <el-input + v-model="addRecord.confinedSpaceOper" + /> + </el-form-item> + <el-form-item label="吊装作业" prop="liftingOper"> + <el-input + v-model="addRecord.liftingOper" + /> + </el-form-item> + <el-form-item label="动土作业" prop="groundBreakingOper"> + <el-input + v-model="addRecord.groundBreakingOper" + /> + </el-form-item> + <el-form-item label="断路作业" prop="openCircuitOper"> + <el-input + v-model="addRecord.openCircuitOper" + /> + </el-form-item> + <el-form-item label="高处作业" prop="workAtHeight"> + <el-input + v-model="addRecord.workAtHeight" + /> + </el-form-item> + <el-form-item label="临时用电作业" prop="temporaryPowerOper"> + <el-input + v-model="addRecord.temporaryPowerOper" + /> + </el-form-item> + <el-form-item label="盲板抽堵作业" prop="blindPlatePluggingOper"> + <el-input + v-model="addRecord.blindPlatePluggingOper" + /> + </el-form-item> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button type="warning" @click="dialogAddRecord = false" size="default" plain>取消</el-button> + <el-button type="primary" @click="confirmAddRecord(addRef)" size="default">确认</el-button> + </span> + </template> + </el-dialog> + <el-dialog v-model="deleteDialog" title="提示" width="30%" center @close="indexClear"> + <span>您确定要删除该条记录吗?</span> + <template #footer> + <span class="dialog-footer"> + <el-button @click="deleteDialog = false" size="default">取消</el-button> + <el-button type="primary" @click="conFirmDelete" size="default">确认</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script lang="ts"> + import {toRefs, reactive, ref, onMounted, defineAsyncComponent} from 'vue'; + import { storeToRefs } from 'pinia'; + import { initBackEndControlRoutes } from '/@/router/backEnd'; + import { useUserInfo } from '/@/stores/userInfo'; + import { Session } from '/@/utils/storage'; + import { Edit, View, Plus, Delete, Refresh, Search, Download } from '@element-plus/icons-vue'; + import { ElTable, ElMessage, ElMessageBox } from 'element-plus' + import type { FormInstance, FormRules, UploadProps, UploadUserFile } from 'element-plus' + import { workAppointApi } from '/@/api/specialWorkSystem/workPlan/workAppoint'; + import { teamManageApi } from '/@/api/systemManage/basicDateManage/personShiftManage/teamManage'; + + // 定义接口来定义对象的类型 + interface stateType { + tableData: Array<any>; + departmentList: Array<any>; + casProps: {}; + multipleSelection: Array<any>; + deleteArr: Array<any>; + dialogDetails: boolean; + dialogAddRecord: boolean; + deleteDialog: boolean; + deleteSetDialog: boolean; + pageIndex: number; + pageSize: number; + chosenIndex: null | number; + deleteId: null | number; + searchDep: number | null; + searchDate: string; + isDisabled:boolean; + totalSize: number; + addRecord: { + + }; + details: { + + }; + workTypeList: Array<any> + } + + export default { + name: 'workReservation', + components: {}, + setup() { + const userInfo = useUserInfo(); + const { userInfos } = storeToRefs(userInfo); + const state = reactive<stateType>({ + pageIndex: 1, + pageSize: 10, + totalSize: 0, + chosenIndex: null, + searchDep: null, + searchDate: '', + isDisabled: false, + tableData: [], + departmentList: [], + casProps: { + expandTrigger: 'hover', + emitPath: false, + value: 'depId', + label: 'depName', + checkStrictly: true + }, + multipleSelection: [], + dialogDetails: false, + dialogAddRecord: false, + deleteDialog: false, + deleteSetDialog: false, + addRecord: {}, + details: {}, + deleteId: null, + deleteArr: [], + workTypeList: [ + { id: 1, name: '动火作业' }, + { id: 2, name: '受限空间作业' }, + { id: 3, name: '吊装作业' }, + { id: 4, name: '动土作业' }, + { id: 5, name: '断路作业' }, + { id: 6, name: '高处作业' }, + { id: 7, name: '临时用电作业' }, + { id: 8, name: '盲板抽堵作业' } + ] + }); + + const addRef = ref<FormInstance>(); + const addRules = reactive<FormRules>({ + applyDepId: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + appointmentTime: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + hotWork: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + groundBreakingOper: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + blindPlatePluggingOper: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + temporaryPowerOper : [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + workAtHeight: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + openCircuitOper: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + liftingOper: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + confinedSpaceOper: [{ required: true, message: '该内容不能为空', trigger: 'blur' }] + }); + + // 页面载入时执行方法 + onMounted(() => { + getListByPage() + getAllDepartment() + }); + + // 获取部门列表 + const getAllDepartment = async () => { + let res = await teamManageApi().getAllDepartment(); + if (res.data.code === '200') { + state.departmentList = JSON.parse(JSON.stringify(res.data.data)) + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 分页获取气体检测列表 + const getListByPage = async () => { + const data = { pageSize: state.pageSize, pageIndex: state.pageIndex, searchParams: { applyDepId: state.searchDep, appointmentTime: state.searchDate } }; + let res = await workAppointApi().getAppointListPage(data); + if (res.data.code === '200') { + state.tableData = JSON.parse(JSON.stringify(res.data.data)) + state.totalSize = res.data.total; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 关键词查询记录 + const searchRecord = async () => { + if (state.searchDep == null && state.searchDate == '') { + ElMessage({ + type: 'warning', + message: '请输入查询关键词' + }); + } else { + getListByPage(); + } + }; + + const clearSearch = async () => { + state.searchDep = null; + state.searchDate = ''; + getListByPage(); + }; + + // 添加记录方法 + const addRecord = async (data: any) => { + let res = await workAppointApi().addRecord(data); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '添加成功!' + }); + getListByPage(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 修改记录方法 + const editRecord = async (data: any) => { + let res = await workAppointApi().editRecord(data); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '修改成功!' + }); + getListByPage(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 点击修改 + const editRecordBtn = (index, row) => { + state.dialogAddRecord = true; + state.chosenIndex = index; + state.addRecord = JSON.parse(JSON.stringify(row)); + state.isDisabled = true + }; + + // 新增修改记录 + const confirmAddRecord = async (formEl: FormInstance | undefined) => { + if (!formEl) return; + await formEl.validate(async (valid, fields) => { + if (valid) { + const data = { + applyDepId: state.addRecord.applyDepId, + appointmentTime: state.addRecord.appointmentTime, + hotWork: Number(state.addRecord.hotWork), + groundBreakingOper: Number(state.addRecord.groundBreakingOper), + blindPlatePluggingOper: Number(state.addRecord.blindPlatePluggingOper), + temporaryPowerOper: Number(state.addRecord.temporaryPowerOper), + workAtHeight: Number(state.addRecord.workAtHeight), + openCircuitOper: Number(state.addRecord.openCircuitOper), + liftingOper: Number(state.addRecord.liftingOper), + confinedSpaceOper: Number(state.addRecord.confinedSpaceOper), + }; + if (state.chosenIndex == null) { + await addRecord(data); + } else { + data.id = state.addRecord.id + await editRecord(data); + } + state.dialogAddRecord = false; + getListByPage(); + } else { + console.log('error submit!', fields); + } + }); + }; + + const handleSizeChange = (val: number) => { + state.pageSize = val; + getListByPage(); + }; + const handleCurrentChange = (val: number) => { + state.pageIndex = val; + getListByPage(); + }; + + // 查看记录 + const viewRecord = (row) => { + state.details = JSON.parse(JSON.stringify(row)); + state.dialogDetails = true; + }; + + // 刷新 + const reLoadData = async () => { + getListByPage(); + }; + + + // 删除方法 + const deleteRecord = async (data: any) => { + let res = await workAppointApi().deleteRecord(data); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '删除成功!' + }); + getListByPage(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + const deleteRecordBtn = (row) => { + state.deleteId = row.id; + state.deleteDialog = true; + }; + + const conFirmDelete = () => { + deleteRecord({ id: state.deleteId }); + state.deleteDialog = false; + }; + + + const closeAdd = () => { + state.addRecord = {}; + state.chosenIndex = null; + state.isDisabled = false + }; + + const indexClear = () => { + state.deleteId = null; + }; + + // 折线图 + const renderMenu = async (value: string) => { + Session.set('projectId', value); + userInfos.value.projectId = value; + await initBackEndControlRoutes(); + }; + return { + addRef, + addRules, + View, + Edit, + Delete, + Refresh, + Plus, + Search, + searchRecord, + clearSearch, + viewRecord, + editRecordBtn, + deleteRecordBtn, + conFirmDelete, + getListByPage, + reLoadData, + handleSizeChange, + handleCurrentChange, + confirmAddRecord, + closeAdd, + indexClear, + ...toRefs(state) + }; + } + }; +</script> + +<style scoped lang="scss"> + $homeNavLengh: 8; + .red{ + color: red; + } + .home-container { + height: calc(100vh - 144px); + box-sizing: border-box; + overflow: hidden; + .homeCard { + width: 100%; + padding: 20px; + box-sizing: border-box; + background: #fff; + border-radius: 4px; + + .main-card { + width: 100%; + height: 100%; + .cardTop { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 20px; + .mainCardBtn { + margin: 0; + } + } + .pageBtn { + height: 60px; + display: flex; + align-items: center; + justify-content: right; + + .demo-pagination-block + .demo-pagination-block { + margin-top: 10px; + } + .demo-pagination-block .demonstration { + margin-bottom: 16px; + } + } + } + &:last-of-type { + height: calc(100% - 100px); + } + } + .el-row { + display: flex; + align-items: center; + margin-bottom: 20px; + &:last-child { + margin-bottom: 0; + } + .grid-content { + align-items: center; + min-height: 36px; + } + + .topInfo { + width: 100%; + display: flex; + align-items: center; + font-size: 16px; + font-weight: bold; + + & > div { + white-space: nowrap; + margin-right: 20px; + } + } + } + } + .el-input{ + width: 100% !important; + } + ::v-deep(.el-date-editor){ + width: 100%; + } + .el-select{ + width: 100%; + } + :deep(.el-cascader){ + width: 100% !important; + } +</style> diff --git a/src/views/specialWorkSystem/plan/reservation/index.vue b/src/views/specialWorkSystem/plan/reservation/index.vue new file mode 100644 index 0000000..ae30465 --- /dev/null +++ b/src/views/specialWorkSystem/plan/reservation/index.vue @@ -0,0 +1,632 @@ +<template> + <div class="home-container"> + <div style="height: 100%"> + <el-row class="homeCard"> +<!-- <el-col :span="6" style="display:flex;align-items: center">--> +<!-- <span style="white-space: nowrap">申请部门:</span>--> +<!-- <div class="grid-content topInfo">--> +<!-- <el-cascader v-model="searchDep" :options="departmentList" :props="casProps" :show-all-levels="false"/>--> +<!-- </div>--> +<!-- </el-col>--> + <el-col :span="6" style="display:flex;align-items: center;"> + <span style="white-space: nowrap;margin-left: 20px">预约日期:</span> + <div class="grid-content topInfo"> + <el-date-picker + v-model="searchDate" + type="date" + format="YYYY-MM-DD" value-format="YYYY-MM-DD" + /> + </div> + </el-col> + <el-button style="margin-left: 20px" type="primary" @click="searchRecord">查询</el-button> + <el-button plain @click="clearSearch">重置</el-button> + </el-row> + <div class="homeCard"> + <div class="main-card"> + <el-row class="cardTop"> + <el-col :span="12" class="mainCardBtn"> + <el-button type="primary" :icon="Plus" size="default" @click="dialogAddRecord = true">新增</el-button> + </el-col> + <el-button type="primary" :icon="Refresh" size="default" @click="reLoadData"/> + </el-row> + <el-table + :data="tableData" + style="width: 100%" + height="calc(100% - 100px)" + :header-cell-style="{background: '#fafafa'}" + > +<!-- <el-table-column type="selection" width="55" />--> + <el-table-column type="index" label="序号" width="80" /> + <el-table-column prop="applyDepName" align="center" label="申请部门"/> + <el-table-column prop="appointmentTime" align="center" label="预约时间"/> + <el-table-column prop="hotWork" align="center" label="动火作业"/> + <el-table-column prop="confinedSpaceOper" align="center" label="受限空间作业"/> + <el-table-column prop="liftingOper" align="center" label="吊装作业"/> + <el-table-column prop="groundBreakingOper" align="center" label="动土作业"/> + <el-table-column prop="openCircuitOper" align="center" label="断路作业"/> + <el-table-column prop="workAtHeight" align="center" label="高处作业" /> + <el-table-column prop="temporaryPowerOper" align="center" label="临时用电作业"/> + <el-table-column prop="blindPlatePluggingOper" align="center" label="盲板抽堵作业"/> + <el-table-column fixed="right" label="操作" align="center" width="250"> + <template #default="scope"> + <el-button link type="primary" size="small" :icon="View" @click="viewRecord(scope.row)">查看</el-button> + <el-button link type="primary" size="small" :icon="Edit" @click="editRecordBtn(scope.$index, scope.row)">修改</el-button> + <el-button link type="danger" size="small" :icon="Delete" @click="deleteRecordBtn(scope.row)">删除</el-button> + </template> + </el-table-column> + </el-table> + <div class="pageBtn"> + <el-pagination + v-model:currentPage="currentPage" + v-model:page-size="pageSize" + :page-sizes="[10, 15]" + small=false + background + layout="total, sizes, prev, pager, next, jumper" + :total="totalSize" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + </div> + </div> + </div> + <el-dialog v-model="dialogDetails" title="作业预约"> + <el-form :model="details" label-width="120px"> + <el-form-item label="申请部门"> + <el-input + v-model="details.applyDepName" + readonly + /> + </el-form-item> + <el-form-item label="预约时间"> + <el-input + v-model="details.appointmentTime" + readonly + /> + </el-form-item> + <el-form-item label="动火作业"> + <el-input + v-model="details.hotWork" + readonly + /> + </el-form-item> + <el-form-item label="受限空间作业"> + <el-input + v-model="details.confinedSpaceOper" + readonly + /> + </el-form-item> + <el-form-item label="吊装作业"> + <el-input + v-model="details.liftingOper" + readonly + /> + </el-form-item> + <el-form-item label="动土作业"> + <el-input + v-model="details.groundBreakingOper" + readonly + /> + </el-form-item> + <el-form-item label="断路作业"> + <el-input + v-model="details.openCircuitOper" + readonly + /> + </el-form-item> + <el-form-item label="高处作业"> + <el-input + v-model="details.workAtHeight" + readonly + /> + </el-form-item> + <el-form-item label="临时用电作业"> + <el-input + v-model="details.temporaryPowerOper" + readonly + /> + </el-form-item> + <el-form-item label="盲板抽堵作业"> + <el-input + v-model="details.blindPlatePluggingOper" + readonly + /> + </el-form-item> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button type="primary" @click="dialogDetails = false">确认</el-button> + </span> + </template> + </el-dialog> + <el-dialog v-model="dialogAddRecord" title="作业预约编辑" @close="closeAdd"> + <el-form :model="addRecord" label-width="120px" ref="addRef" :rules="addRules"> +<!-- <el-form-item label="申请部门" prop="applyDepId">--> +<!-- <el-cascader placeholder="若选择部门非本人所在部门,则记录不会出现在该页面" :disabled = isDisabled v-model="addRecord.applyDepId" :options="departmentList" :props="casProps" :show-all-levels="false" @change="handleChange" />--> +<!-- </el-form-item>--> + <el-form-item label="预约时间" prop="appointmentTime"> + <el-date-picker + v-model="addRecord.appointmentTime" + type="date" + format="YYYY-MM-DD" value-format="YYYY-MM-DD" + :disabled = isDisabled + placeholder="请选择预约时间段" + /> + </el-form-item> + <el-form-item label="动火作业" prop="hotWork"> + <el-input + v-model="addRecord.hotWork" + type="number" + placeholder="预约数量(没有则为0)" + /> + </el-form-item> + <el-form-item label="受限空间作业" prop="confinedSpaceOper"> + <el-input + v-model="addRecord.confinedSpaceOper" + type="number" + placeholder="预约数量(没有则为0)" + /> + </el-form-item> + <el-form-item label="吊装作业" prop="liftingOper"> + <el-input + v-model="addRecord.liftingOper" + type="number" + placeholder="预约数量(没有则为0)" + /> + </el-form-item> + <el-form-item label="动土作业" prop="groundBreakingOper"> + <el-input + v-model="addRecord.groundBreakingOper" + type="number" + placeholder="预约数量(没有则为0)" + /> + </el-form-item> + <el-form-item label="断路作业" prop="openCircuitOper"> + <el-input + v-model="addRecord.openCircuitOper" + type="number" + placeholder="预约数量(没有则为0)" + /> + </el-form-item> + <el-form-item label="高处作业" prop="workAtHeight"> + <el-input + v-model="addRecord.workAtHeight" + type="number" + placeholder="预约数量(没有则为0)" + /> + </el-form-item> + <el-form-item label="临时用电作业" prop="temporaryPowerOper"> + <el-input + v-model="addRecord.temporaryPowerOper" + type="number" + placeholder="预约数量(没有则为0)" + /> + </el-form-item> + <el-form-item label="盲板抽堵作业" prop="blindPlatePluggingOper"> + <el-input + v-model="addRecord.blindPlatePluggingOper" + type="number" + placeholder="预约数量(没有则为0)" + /> + </el-form-item> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button type="warning" @click="dialogAddRecord = false" size="default" plain>取消</el-button> + <el-button type="primary" @click="confirmAddRecord(addRef)" size="default">确认</el-button> + </span> + </template> + </el-dialog> + <el-dialog v-model="deleteDialog" title="提示" width="30%" center @close="indexClear"> + <span>您确定要删除该条记录吗?</span> + <template #footer> + <span class="dialog-footer"> + <el-button @click="deleteDialog = false" size="default">取消</el-button> + <el-button type="primary" @click="conFirmDelete" size="default">确认</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script lang="ts"> + import {toRefs, reactive, ref, onMounted, defineAsyncComponent} from 'vue'; + import { storeToRefs } from 'pinia'; + import { initBackEndControlRoutes } from '/@/router/backEnd'; + import { useUserInfo } from '/@/stores/userInfo'; + import { Session } from '/@/utils/storage'; + import { Edit, View, Plus, Delete, Refresh, Search, Download } from '@element-plus/icons-vue'; + import { ElTable, ElMessage, ElMessageBox } from 'element-plus' + import type { FormInstance, FormRules, UploadProps, UploadUserFile } from 'element-plus' + import { workReserveApi } from '/@/api/specialWorkSystem/workPlan/workReservation'; + import { teamManageApi } from '/@/api/systemManage/basicDateManage/personShiftManage/teamManage'; + + // 定义接口来定义对象的类型 + interface stateType { + tableData: Array<any>; + departmentList: Array<any>; + casProps: {}; + multipleSelection: Array<any>; + deleteArr: Array<any>; + dialogDetails: boolean; + dialogAddRecord: boolean; + deleteDialog: boolean; + deleteSetDialog: boolean; + pageIndex: number; + pageSize: number; + chosenIndex: null | number; + deleteId: null | number; + searchDep: number | null; + searchDate: string; + isDisabled:boolean; + totalSize: number; + addRecord: { + + }; + details: { + + }; + workTypeList: Array<any> + } + + export default { + name: 'workReservation', + components: {}, + setup() { + const userInfo = useUserInfo(); + const { userInfos } = storeToRefs(userInfo); + const state = reactive<stateType>({ + pageIndex: 1, + pageSize: 10, + totalSize: 0, + chosenIndex: null, + searchDep: null, + searchDate: '', + isDisabled: false, + tableData: [], + departmentList: [], + casProps: { + expandTrigger: 'hover', + emitPath: false, + value: 'depId', + label: 'depName', + checkStrictly: true + }, + multipleSelection: [], + dialogDetails: false, + dialogAddRecord: false, + deleteDialog: false, + deleteSetDialog: false, + addRecord: {}, + details: {}, + deleteId: null, + deleteArr: [], + workTypeList: [ + { id: 1, name: '动火作业' }, + { id: 2, name: '受限空间作业' }, + { id: 3, name: '吊装作业' }, + { id: 4, name: '动土作业' }, + { id: 5, name: '断路作业' }, + { id: 6, name: '高处作业' }, + { id: 7, name: '临时用电作业' }, + { id: 8, name: '盲板抽堵作业' } + ] + }); + + const addRef = ref<FormInstance>(); + const addRules = reactive<FormRules>({ + appointmentTime: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + hotWork: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + groundBreakingOper: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + blindPlatePluggingOper: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + temporaryPowerOper : [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + workAtHeight: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + openCircuitOper: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + liftingOper: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + confinedSpaceOper: [{ required: true, message: '该内容不能为空', trigger: 'blur' }] + }); + + // 页面载入时执行方法 + onMounted(() => { + getListByPage() + getAllDepartment() + }); + + // 获取部门列表 + const getAllDepartment = async () => { + let res = await teamManageApi().getAllDepartment(); + if (res.data.code === '200') { + state.departmentList = JSON.parse(JSON.stringify(res.data.data)) + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 分页获取气体检测列表 + const getListByPage = async () => { + const data = { pageSize: state.pageSize, pageIndex: state.pageIndex, searchParams: { applyDepId: state.searchDep, appointmentTime: state.searchDate } }; + let res = await workReserveApi().getReserveListPage(data); + if (res.data.code === '200') { + state.tableData = JSON.parse(JSON.stringify(res.data.data)) + state.totalSize = res.data.total; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 关键词查询记录 + const searchRecord = async () => { + if (state.searchDep == null && state.searchDate == '') { + ElMessage({ + type: 'warning', + message: '请输入查询关键词' + }); + } else { + getListByPage(); + } + }; + + const clearSearch = async () => { + state.searchDep = null; + state.searchDate = ''; + getListByPage(); + }; + + // 添加记录方法 + const addRecord = async (data: any) => { + let res = await workReserveApi().addRecord(data); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '添加成功!' + }); + getListByPage(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 修改记录方法 + const editRecord = async (data: any) => { + let res = await workReserveApi().editRecord(data); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '修改成功!' + }); + getListByPage(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 点击修改 + const editRecordBtn = (index, row) => { + state.dialogAddRecord = true; + state.chosenIndex = index; + state.addRecord = JSON.parse(JSON.stringify(row)); + state.isDisabled = true + }; + + // 新增修改记录 + const confirmAddRecord = async (formEl: FormInstance | undefined) => { + if (!formEl) return; + await formEl.validate(async (valid, fields) => { + if (valid) { + const data = { + applyDepId: state.addRecord.applyDepId, + appointmentTime: state.addRecord.appointmentTime, + hotWork: Number(state.addRecord.hotWork), + groundBreakingOper: Number(state.addRecord.groundBreakingOper), + blindPlatePluggingOper: Number(state.addRecord.blindPlatePluggingOper), + temporaryPowerOper: Number(state.addRecord.temporaryPowerOper), + workAtHeight: Number(state.addRecord.workAtHeight), + openCircuitOper: Number(state.addRecord.openCircuitOper), + liftingOper: Number(state.addRecord.liftingOper), + confinedSpaceOper: Number(state.addRecord.confinedSpaceOper), + }; + if (state.chosenIndex == null) { + await addRecord(data); + } else { + data.id = state.addRecord.id + await editRecord(data); + } + state.dialogAddRecord = false; + getListByPage(); + } else { + console.log('error submit!', fields); + } + }); + }; + + const handleSizeChange = (val: number) => { + state.pageSize = val; + getListByPage(); + }; + const handleCurrentChange = (val: number) => { + state.pageIndex = val; + getListByPage(); + }; + + // 查看记录 + const viewRecord = (row) => { + state.details = JSON.parse(JSON.stringify(row)); + state.dialogDetails = true; + }; + + // 刷新 + const reLoadData = async () => { + getListByPage(); + }; + + + // 删除方法 + const deleteRecord = async (data: any) => { + let res = await workReserveApi().deleteRecord(data); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '删除成功!' + }); + getListByPage(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + const deleteRecordBtn = (row) => { + state.deleteId = row.id; + state.deleteDialog = true; + }; + + const conFirmDelete = () => { + deleteRecord({ id: state.deleteId }); + state.deleteDialog = false; + }; + + + const closeAdd = () => { + state.addRecord = {}; + state.chosenIndex = null; + state.isDisabled = false + }; + + const indexClear = () => { + state.deleteId = null; + }; + + // 折线图 + const renderMenu = async (value: string) => { + Session.set('projectId', value); + userInfos.value.projectId = value; + await initBackEndControlRoutes(); + }; + return { + addRef, + addRules, + View, + Edit, + Delete, + Refresh, + Plus, + Search, + searchRecord, + clearSearch, + viewRecord, + editRecordBtn, + deleteRecordBtn, + conFirmDelete, + getListByPage, + reLoadData, + handleSizeChange, + handleCurrentChange, + confirmAddRecord, + closeAdd, + indexClear, + ...toRefs(state) + }; + } + }; +</script> + +<style scoped lang="scss"> + $homeNavLengh: 8; + .red{ + color: red; + } + .home-container { + height: calc(100vh - 144px); + box-sizing: border-box; + overflow: hidden; + .homeCard { + width: 100%; + padding: 20px; + box-sizing: border-box; + background: #fff; + border-radius: 4px; + + .main-card { + width: 100%; + height: 100%; + .cardTop { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 20px; + .mainCardBtn { + margin: 0; + } + } + .pageBtn { + height: 60px; + display: flex; + align-items: center; + justify-content: right; + + .demo-pagination-block + .demo-pagination-block { + margin-top: 10px; + } + .demo-pagination-block .demonstration { + margin-bottom: 16px; + } + } + } + &:last-of-type { + height: calc(100% - 100px); + } + } + .el-row { + display: flex; + align-items: center; + margin-bottom: 20px; + &:last-child { + margin-bottom: 0; + } + .grid-content { + align-items: center; + min-height: 36px; + } + + .topInfo { + width: 100%; + display: flex; + align-items: center; + font-size: 16px; + font-weight: bold; + + & > div { + white-space: nowrap; + margin-right: 20px; + } + } + } + } + .el-input{ + width: 100% !important; + } + ::v-deep(.el-date-editor){ + width: 100%; + } + .el-select{ + width: 100%; + } + :deep(.el-cascader){ + width: 100% !important; + } +</style> diff --git a/src/views/specialWorkSystem/plan/sumReserve/index.vue b/src/views/specialWorkSystem/plan/sumReserve/index.vue new file mode 100644 index 0000000..32f8d2b --- /dev/null +++ b/src/views/specialWorkSystem/plan/sumReserve/index.vue @@ -0,0 +1,436 @@ +<template> + <div class="home-container"> + <div style="height: 100%"> + <el-row class="homeCard"> + <el-col :span="8" style="display:flex;align-items: center"> + <span style="white-space: nowrap">选择时间段:</span> + <div class="grid-content topInfo"> + <el-date-picker + v-model="searchDates" + type="daterange" + unlink-panels + range-separator="至" + start-placeholder="开始日期" + end-placeholder="结束日期" + value-format="YYYY-MM-DD" + :shortcuts="shortcuts" + /> + </div> + </el-col> + <el-button style="margin-left: 20px" type="primary" @click="searchRecord">查询</el-button> + <el-button plain @click="clearSearch">重置</el-button> + </el-row> + <div class="homeCard"> + <div :id="chartName" style="width: 100%;height: 100%"></div> + </div> + </div> + </div> +</template> + +<script lang="ts"> + import {toRefs, reactive, ref, onMounted, defineAsyncComponent, nextTick} from 'vue'; + import { storeToRefs } from 'pinia'; + import { initBackEndControlRoutes } from '/@/router/backEnd'; + import { useUserInfo } from '/@/stores/userInfo'; + import { Session } from '/@/utils/storage'; + import { Edit, View, Plus, Delete, Refresh, Search, Download } from '@element-plus/icons-vue'; + import { ElTable, ElMessage, ElMessageBox } from 'element-plus' + import { workAppointApi } from '/@/api/specialWorkSystem/workPlan/workAppoint'; + import { teamManageApi } from '/@/api/systemManage/basicDateManage/personShiftManage/teamManage'; + import * as echarts from "echarts"; + + // 定义接口来定义对象的类型 + interface stateType { + tableData: [], + departmentList: Array<any>, + hotCount: Array<any>, + confinedSpaceCount: Array<any>, + liftingCount: Array<any>, + groundBreakingCount: Array<any>, + openCircuitCout: Array<any>, + heightCount: Array<any>, + temporaryPowerCount: Array<any>, + blindPlatePluggingCount: Array<any>, + searchDates: Array<any>, + startTime: String, + endTime: String + } + + export default { + name: 'workReservation', + components: {}, + setup() { + const userInfo = useUserInfo(); + const { userInfos } = storeToRefs(userInfo); + const state = reactive<stateType>({ + tableData: [], + departmentList: [], + hotCount: [], + confinedSpaceCount: [], + liftingCount: [], + groundBreakingCount: [], + openCircuitCout: [], + heightCount: [], + temporaryPowerCount: [], + blindPlatePluggingCount: [], + searchDates: [], + startTime: '', + endTime: '' + }); + const chartName = ref("eChart" + Date.now() + Math.random()) + const shortcuts = [ + { + text: '上周', + value: () => { + const end = new Date() + const start = new Date() + start.setTime(start.getTime() - 3600 * 1000 * 24 * 7) + return [start, end] + }, + }, + { + text: '上个月', + value: () => { + const end = new Date() + const start = new Date() + start.setTime(start.getTime() - 3600 * 1000 * 24 * 30) + return [start, end] + }, + }, + { + text: '上个季度', + value: () => { + const end = new Date() + const start = new Date() + start.setTime(start.getTime() - 3600 * 1000 * 24 * 90) + return [start, end] + }, + }, + ] + + // 页面载入时执行方法 + onMounted(() => { + getListByPage() + // getAllDepartment() + }); + + // 获取列表 + const getListByPage = async () => { + const data = { startTime: state.searchDates[0], endTime: state.searchDates[1] }; + let res = await workAppointApi().getAllRecords(data); + if (res.data.code === '200') { + if(JSON.parse(JSON.stringify(res.data.data)).length>0){ + state.tableData = JSON.parse(JSON.stringify(res.data.data)) + state.departmentList = Array.from(state.tableData, ({ applyDepName }) => applyDepName); + state.hotCount = Array.from(state.tableData, ({ hotCount }) => hotCount); + state.confinedSpaceCount = Array.from(state.tableData, ({ confinedSpaceCount }) => confinedSpaceCount); + state.liftingCount = Array.from(state.tableData, ({ liftingCount }) => liftingCount); + state.groundBreakingCount = Array.from(state.tableData, ({ groundBreakingCount }) => groundBreakingCount); + state.openCircuitCout = Array.from(state.tableData, ({ openCircuitCout }) => openCircuitCout); + state.heightCount = Array.from(state.tableData, ({ heightCount }) => heightCount); + state.temporaryPowerCount = Array.from(state.tableData, ({ temporaryPowerCount }) => temporaryPowerCount); + state.blindPlatePluggingCount = Array.from(state.tableData, ({ blindPlatePluggingCount }) => blindPlatePluggingCount); + initCharts() + }else{ + ElMessage({ + type: 'warning', + message: '该时段暂无数据' + }); + } + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + const initCharts =()=>{ + let dom = document.getElementById(chartName.value); + let myChart = echarts.init(dom); + + type EChartsOption = echarts.EChartsOption + let option: EChartsOption; + + option = { + tooltip: { + trigger: 'axis', + // axisPointer: { + // type: 'shadow' // 'shadow' as default; can also be 'line' or 'shadow' + // }, + axisPointer: { + type: "cross", + label: { + formatter: function (params) { + if (params.seriesData.length === 0) { + window.mouseCurValue = params.value; + } + } + } + }, + formatter: function (params) { + let res = "", sum = 0; + for (let i = 0; i < params.length; i++) { + let series = params[i]; + sum += Number(series.data); + if (sum >= window.mouseCurValue) { + res = series.axisValue + "<br/>" + series.marker + series.seriesName + ":" + series.data + "<br/>"; + break; + } + } + return res; + }, + }, + legend: {}, + grid: { + left: '3%', + right: '3%', + bottom: '3%', + containLabel: true + }, + xAxis: { + type: 'value' + }, + yAxis: { + type: 'category', + data: state.departmentList + }, + series: [ + { + name: '动火作业', + type: 'bar', + stack: 'total', + label: { + show: true + }, + emphasis: { + focus: 'series' + }, + data: state.hotCount + }, + { + name: '受限空间作业', + type: 'bar', + stack: 'total', + label: { + show: true + }, + emphasis: { + focus: 'series' + }, + data: state.confinedSpaceCount + }, + { + name: '吊装作业', + type: 'bar', + stack: 'total', + label: { + show: true + }, + emphasis: { + focus: 'series' + }, + data: state.liftingCount + }, + { + name: '动土作业', + type: 'bar', + stack: 'total', + label: { + show: true + }, + emphasis: { + focus: 'series' + }, + data: state.groundBreakingCount + }, + { + name: '断路作业', + type: 'bar', + stack: 'total', + label: { + show: true + }, + emphasis: { + focus: 'series' + }, + data: state.openCircuitCout + }, + { + name: '高处作业', + type: 'bar', + stack: 'total', + label: { + show: true + }, + emphasis: { + focus: 'series' + }, + data: state.heightCount + }, + { + name: '临时用电作业', + type: 'bar', + stack: 'total', + label: { + show: true + }, + emphasis: { + focus: 'series' + }, + data: state.temporaryPowerCount + }, + { + name: '盲板抽堵作业', + type: 'bar', + stack: 'total', + label: { + show: true + }, + emphasis: { + focus: 'series' + }, + data: state.blindPlatePluggingCount + } + ] + }; + + option && myChart.setOption(option); + + window.addEventListener("resize",function (){ + myChart.resize(); + }); + } + + // 关键词查询记录 + const searchRecord = async () => { + if (state.searchDates == []) { + ElMessage({ + type: 'warning', + message: '请选择时间段' + }); + } else { + getListByPage(); + } + }; + + const clearSearch = async () => { + state.searchDates = []; + getListByPage(); + }; + + // 刷新 + const reLoadData = async () => { + getListByPage(); + }; + + // 折线图 + const renderMenu = async (value: string) => { + Session.set('projectId', value); + userInfos.value.projectId = value; + await initBackEndControlRoutes(); + }; + return { + View, + Edit, + Delete, + Refresh, + Plus, + Search, + shortcuts, + chartName, + searchRecord, + clearSearch, + getListByPage, + reLoadData, + ...toRefs(state) + }; + } + }; +</script> + +<style scoped lang="scss"> + $homeNavLengh: 8; + .red{ + color: red; + } + .home-container { + height: calc(100vh - 144px); + box-sizing: border-box; + overflow: hidden; + .homeCard { + width: 100%; + padding: 20px; + box-sizing: border-box; + background: #fff; + border-radius: 4px; + + .main-card { + width: 100%; + height: 100%; + .cardTop { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 20px; + .mainCardBtn { + margin: 0; + } + } + .pageBtn { + height: 60px; + display: flex; + align-items: center; + justify-content: right; + + .demo-pagination-block + .demo-pagination-block { + margin-top: 10px; + } + .demo-pagination-block .demonstration { + margin-bottom: 16px; + } + } + } + &:last-of-type { + height: calc(100% - 100px); + } + } + .el-row { + display: flex; + align-items: center; + margin-bottom: 20px; + &:last-child { + margin-bottom: 0; + } + .grid-content { + align-items: center; + min-height: 36px; + } + + .topInfo { + width: 100%; + display: flex; + align-items: center; + font-size: 16px; + font-weight: bold; + + & > div { + white-space: nowrap; + margin-right: 20px; + } + } + } + } + .el-input{ + width: 100% !important; + } + ::v-deep(.el-date-editor){ + width: 100%; + } + .el-select{ + width: 100%; + } + :deep(.el-cascader){ + width: 100% !important; + } +</style> diff --git a/src/views/specialWorkSystem/process/components/dialogPermitNo.vue b/src/views/specialWorkSystem/process/components/dialogPermitNo.vue new file mode 100644 index 0000000..9738408 --- /dev/null +++ b/src/views/specialWorkSystem/process/components/dialogPermitNo.vue @@ -0,0 +1,225 @@ +<template> + <div class="home-container"> + <div style="height: 100%"> + <el-row class="homeCard"> + <el-col :span="8" style="display:flex;align-items: center"> + <div class="grid-content topInfo"> + <el-input v-model="searchNo" placeholder="请输入作业证编号"></el-input> + </div> + </el-col> + <el-col :span="8" style="display:flex;align-items: center"> + <div class="grid-content topInfo"> + <el-select v-model="workType" placeholder="请选择作业类型"> + <el-option + v-for="item in workTypeList" + :key="item.value" + :label="item.label" + :value="item.value" + /> + </el-select> + </div> + </el-col> + <el-button type="primary" @click="searchRecord">查询</el-button> + <el-button plain @click="clearSearch">重置</el-button> + </el-row> + <div class="homeCard"> + <div class="main-card"> + <el-table + :data="tableData" + ref="singleTableRef" + highlight-current-row + style="width: 100%" + @current-change="handleCurrentChange" + :header-cell-style="{background: '#fafafa'}" + > + <el-table-column type="index" label="序号" width="80"/> + <el-table-column property="workPermitNo" label="作业证编号"/> + <el-table-column property="workTypeDesc" label="作业类型"/> + </el-table> +<!-- <div class="pageBtn">--> +<!-- <el-pagination--> +<!-- v-model:currentPage="currentPage"--> +<!-- v-model:page-size="pageSize"--> +<!-- :page-sizes="[10, 15]"--> +<!-- small=false--> +<!-- background--> +<!-- layout="total, sizes, prev, pager, next, jumper"--> +<!-- :total="totalSize"--> +<!-- @size-change="handleSizeChange"--> +<!-- @current-change="handleCurrentChange"--> +<!-- />--> +<!-- </div>--> + </div> + </div> + </div> + </div> +</template> + +<script lang="ts"> + import {toRefs, reactive, defineComponent, ref, defineAsyncComponent, onMounted} from 'vue'; + import { storeToRefs } from 'pinia'; + import { initBackEndControlRoutes } from '/@/router/backEnd'; + import {useUserInfo} from "/@/stores/userInfo"; + import { Session } from '/@/utils/storage'; + import { Search } from '@element-plus/icons-vue' + import { ElMessage,ElTable } from 'element-plus' + import type { FormInstance, FormRules } from 'element-plus' + import { workApplyApi } from '/@/api/specialWorkSystem/workApply'; + import {workProcessApi} from "/@/api/specialWorkSystem/workProcess"; + + + interface stateType { + workPermitNo: string + searchNo: string + workType: number + } + export default defineComponent({ + name: 'permitNo', + components: {}, + props:[], + setup() { + const userInfo = useUserInfo() + const { userInfos } = storeToRefs(userInfo); + const currentRow = ref() + const singleTableRef = ref<InstanceType<typeof ElTable>>() + const state = reactive<stateType>({ + workPermitNo: '', + searchNo: '', + workType: null, + tableData: [], + workTypeList: [ + { + label: "动火作业", + value: 1 + }, + { + label: "受限空间作业", + value: 2 + }, + { + label: "吊装作业", + value: 3 + }, + { + label: "动土作业", + value: 4 + }, + { + label: "断路作业", + value: 5 + }, + { + label: "高处作业", + value: 6 + }, + { + label: "临时用电作业", + value: 7 + }, + { + label: "盲板抽堵作业", + value: 8 + } + ] + }); + const handleCurrentChange = (val: User | undefined) => { + currentRow.value = val + state.workPermitNo = currentRow.value.workPermitNo + } + // 获取作业编号列表 + const getAllReport = async (data)=>{ + const res = await workProcessApi().postReportList({workPermitNo: state.searchNo,workType: state.workType}) + if (res.data.code === '200') { + state.tableData = JSON.parse(JSON.stringify(res.data.data)) + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + // 关键词查询记录 + const searchRecord = async () => { + if (state.searchNo == ''&& state.workType == null) { + ElMessage({ + type: 'warning', + message: '请输入查询关键词' + }); + } else { + getAllReport(); + } + }; + + const clearSearch = async () => { + state.searchNo = ''; + state.workType = null; + getAllReport(); + }; + // 页面载入时执行方法 + onMounted(() => { + getAllReport() + }); + + // 折线图 + const renderMenu = async (value: string) => { + Session.set('projectId',value) + userInfos.value.projectId = value + await initBackEndControlRoutes(); + }; + return { + renderMenu, + currentRow, + singleTableRef, + searchRecord, + clearSearch, + handleCurrentChange, + Search, + ...toRefs(state), + }; + }, + }); +</script> + +<style scoped lang="scss"> + .home-container { + height: 100%; + overflow: hidden; + position: relative; + .homeCard{ + width: 100%; + padding: 20px; + box-sizing: border-box; + background: #fff; + border-radius: 4px; + margin-bottom: 20px; + } + .applyBtn{ + width: 100%; + background: #fff; + padding-top: 15px; + z-index: 5; + box-shadow: 0 -3px 8px rgba(150,150,150,.1); + display: flex; + align-items: center; + justify-content: center; + } + .el-row{ + margin-bottom: 20px; + } + .el-row:last-child { + margin-bottom: 0; + } + .el-input{ + width: 100% !important; + } + .el-date-editor::v-deep{ + width: 100%; + } + .el-select{ + width: 100%; + } + .el-cascader{ + width: 100% !important; + } + } +</style> diff --git a/src/views/specialWorkSystem/process/qtjcfx/index.vue b/src/views/specialWorkSystem/process/qtjcfx/index.vue new file mode 100644 index 0000000..6ef38e0 --- /dev/null +++ b/src/views/specialWorkSystem/process/qtjcfx/index.vue @@ -0,0 +1,511 @@ +<template> + <div class="home-container"> + <div style="height: 100%"> + <el-row class="homeCard"> + <el-col :span="6" style="display:flex;align-items: center"> + <span style="white-space: nowrap">作业证编号:</span> + <div class="grid-content topInfo"> + <el-input v-model="workPermitNo" placeholder="请输入作业证编号"></el-input> + </div> + </el-col> + <el-col :span="6" style="display:flex;align-items: center"> + <span style="white-space: nowrap">作业类型:</span> + <div class="grid-content topInfo"> + <el-select v-model="workType" placeholder="请选择作业类型"> + <el-option + v-for="item in workTypeList" + :key="item.id" + :label="item.name" + :value="item.id" + /> + </el-select> + </div> + </el-col> + <el-button type="primary" @click="searchRecord">查询</el-button> + <el-button plain @click="clearSearch">重置</el-button> + </el-row> + <div class="homeCard"> + <div class="main-card"> + <el-row class="cardTop"> + <el-col :span="12" class="mainCardBtn"> + <el-button type="primary" :icon="Plus" size="default" @click="dialogAddRecord = true">新增</el-button> + </el-col> + <el-button type="primary" :icon="Refresh" size="default" @click="reLoadData"/> + </el-row> + <el-table + :data="tableData" + style="width: 100%" + height="calc(100% - 100px)" + :header-cell-style="{background: '#fafafa'}" + > + <el-table-column type="index" label="序号" width="80"/> + <el-table-column property="workPermitNo" label="作业证编号"/> + <el-table-column property="workTypeDesc" label="作业类型"/> + <el-table-column property="combustible" label="可燃气%"/> +<!-- <el-table-column property="combustible" label="可燃气%">--> +<!-- <template #default="scope">--> +<!-- <span :class="scope.row.combustible > 0 ? 'red': ''">{{ scope.row.combustible }}</span>--> +<!-- </template>--> +<!-- </el-table-column>--> + <el-table-column property="oxygen" label="氧气%"/> + <el-table-column property="carbonMonoxide" label="一氧化碳ppm"/> + <el-table-column property="hydrogenSulfide" label="硫化氢ppm"/> + <el-table-column property="info" label="描述" show-overflow-tooltip width="200"/> + <el-table-column property="operatorUname" label="分析人"/> + <el-table-column property="operationTime" label="分析时间" align="center" width="180"/> + <el-table-column fixed="right" label="操作" align="center" width="250"> + <template #default="scope"> + <el-button link type="primary" size="small" :icon="View" @click="viewRecord(scope.row)">查看</el-button> + </template> + </el-table-column> + </el-table> + <div class="pageBtn"> + <el-pagination + v-model:currentPage="currentPage" + v-model:page-size="pageSize" + :page-sizes="[10, 15]" + small=false + background + layout="total, sizes, prev, pager, next, jumper" + :total="totalSize" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + </div> + </div> + </div> + <el-dialog v-model="dialogDetails" title="检测记录"> + <el-form :model="details" label-width="120px"> + <el-form-item label="作业证编号"> + <el-input v-model="details.workPermitNo" readonly/> + </el-form-item> + <el-form-item label="作业类型"> + <el-input v-model="details.workTypeDesc" readonly/> + </el-form-item> + <el-form-item label="可燃气%"> + <el-input v-model="details.combustible" readonly/> + </el-form-item> + <el-form-item label="氧气%"> + <el-input v-model="details.oxygen" readonly/> + </el-form-item> + <el-form-item label="一氧化碳ppm"> + <el-input v-model="details.carbonMonoxide" readonly/> + </el-form-item> + <el-form-item label="硫化氢ppm"> + <el-input v-model="details.hydrogenSulfide" readonly/> + </el-form-item> + <el-form-item label="描述"> + <el-input v-model="details.info" type="textarea" readonly/> + </el-form-item> + <el-form-item label="分析人"> + <el-input v-model="details.operatorUname" readonly/> + </el-form-item> + <el-form-item label="分析时间"> + <el-input v-model="details.operationTime" readonly/> + </el-form-item> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button type="primary" @click="dialogDetails = false">确认</el-button> + </span> + </template> + </el-dialog> + <el-dialog v-model="dialogAddRecord" title="新增" @close="closeAdd" @open="openAdd"> + <el-form :model="addRecord" label-width="120px" ref="addRef" :rules="addRules"> + <el-form-item label="作业证编号" prop="workPermitNo"> + <el-input v-model="addRecord.workPermitNo" placeholder="作业编号须为已审批作业的编号,可点击右方按钮查询"> + <template #append> + <el-button :icon="Search" @click="dialogPermitNo = true"/> + </template> + </el-input> + </el-form-item> + <el-form-item label="作业类型" prop="workType"> + <el-select v-model="addRecord.workType"> + <el-option + v-for="item in workTypeList" + :key="item.id" + :label="item.name" + :value="item.id" + /> + </el-select> + </el-form-item> + <el-form-item label="可燃气%" prop="combustible"> + <el-input v-model="addRecord.combustible"/> + </el-form-item> + <el-form-item label="氧气%" prop="oxygen"> + <el-input v-model="addRecord.oxygen"/> + </el-form-item> + <el-form-item label="一氧化碳ppm" prop="carbonMonoxide"> + <el-input v-model="addRecord.carbonMonoxide"/> + </el-form-item> + <el-form-item label="硫化氢ppm" prop="hydrogenSulfide"> + <el-input v-model="addRecord.hydrogenSulfide"/> + </el-form-item> + <el-form-item label="描述" prop="info"> + <el-input v-model="addRecord.info" type="textarea"> </el-input> + </el-form-item> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button type="warning" @click="dialogAddRecord = false" size="default" plain>取消</el-button> + <el-button type="primary" @click="confirmAddRecord(addRef)" size="default">确认</el-button> + </span> + </template> + </el-dialog> + <el-dialog v-model="dialogPermitNo" title="选择相应的作业编号"> + <permit-no ref="permitNoInfo"></permit-no> + <template #footer> + <span class="dialog-footer"> + <el-button type="warning" @click="dialogPermitNo = false" size="default" plain>取消</el-button> + <el-button type="primary" @click="confirmPermitNo" size="default">确认</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script lang="ts"> + import {toRefs, reactive, ref, onMounted, defineAsyncComponent} from 'vue'; + import { storeToRefs } from 'pinia'; + import { initBackEndControlRoutes } from '/@/router/backEnd'; + import { useUserInfo } from '/@/stores/userInfo'; + import { Session } from '/@/utils/storage'; + import { Edit, View, Plus, Delete, Refresh, Search, Download } from '@element-plus/icons-vue'; + import { ElTable, ElMessage, ElMessageBox } from 'element-plus' + import type { FormInstance, FormRules, UploadProps, UploadUserFile } from 'element-plus' + import { workProcessApi } from '/@/api/specialWorkSystem/workProcess'; + + // 定义接口来定义对象的类型 + interface stateType { + tableData: Array<any>; + departmentList: Array<any>; + department:string; + workerList: Array<string>; + casProps: {}; + multipleSelection: Array<any>; + deleteArr: Array<any>; + dialogDetails: boolean; + dialogAddRecord: boolean; + dialogPermitNo: boolean; + deleteDialog: boolean; + deleteSetDialog: boolean; + pageIndex: number; + pageSize: number; + chosenIndex: null | number; + deleteId: null | number; + workPermitNo: string; + workType: number | null; + totalSize: number; + addRecord: { + + }; + details: { + + }; + workTypeList: Array<any> + } + + export default { + name: 'gasCheck', + components: { + permitNo: defineAsyncComponent(() => import('/@/views/specialWorkSystem/process/components/dialogPermitNo.vue')) + }, + setup() { + const userInfo = useUserInfo(); + const { userInfos } = storeToRefs(userInfo); + const permitNoInfo = ref() + const state = reactive<stateType>({ + pageIndex: 1, + pageSize: 10, + totalSize: 0, + chosenIndex: null, + workPermitNo: '', + workType: null, + tableData: [], + departmentList: [], + department: '', + workerList: [], + casProps: { + expandTrigger: 'hover', + emitPath: false, + value: 'depId', + label: 'depName' + }, + multipleSelection: [], + dialogDetails: false, + dialogAddRecord: false, + dialogPermitNo: false, + deleteDialog: false, + deleteSetDialog: false, + addRecord: { + + }, + details: { + + }, + deleteId: null, + deleteArr: [], + workTypeList: [ + { id: 1, name: '动火作业' }, + { id: 2, name: '受限空间作业' }, + { id: 3, name: '吊装作业' }, + { id: 4, name: '动土作业' }, + { id: 5, name: '断路作业' }, + { id: 6, name: '高处作业' }, + { id: 7, name: '临时用电作业' }, + { id: 8, name: '盲板抽堵作业' } + ] + }); + + const addRef = ref<FormInstance>(); + const addRules = reactive<FormRules>({ + workPermitNo: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + workType: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + combustible: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + oxygen: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + carbonMonoxide: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + hydrogenSulfide: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + info: [{ required: true, message: '该内容不能为空', trigger: 'blur' }] + }); + + // 页面载入时执行方法 + onMounted(() => { + getListByPage() + }); + + // 分页获取气体检测列表 + const getListByPage = async () => { + const data = { pageSize: state.pageSize, pageIndex: state.pageIndex, searchParams: { workType: state.workType, workPermitNo: state.workPermitNo } }; + let res = await workProcessApi().getDetectionListPage(data); + if (res.data.code === '200') { + state.tableData = JSON.parse(JSON.stringify(res.data.data)) + state.totalSize = res.data.total; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + const confirmPermitNo = ()=>{ + if(permitNoInfo.value.workPermitNo == ''){ + ElMessage({ + type: 'warning', + message: '请选择相应的作业编码' + }); + }else{ + state.addRecord.workPermitNo = permitNoInfo.value.workPermitNo + state.dialogPermitNo = false + } + } + + // 关键词查询记录 + const searchRecord = async () => { + if (state.workPermitNo == ''&& state.workType == null) { + ElMessage({ + type: 'warning', + message: '请输入查询关键词' + }); + } else { + getListByPage(); + } + }; + + const clearSearch = async () => { + state.workPermitNo = ''; + state.workType = null; + getListByPage(); + }; + + // 添加气体检测方法 + const addRecord = async (data: any) => { + let res = await workProcessApi().postDetectionReport(data); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '添加成功!' + }); + getListByPage(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 新增修改记录 + const confirmAddRecord = async (formEl: FormInstance | undefined) => { + if (!formEl) return; + await formEl.validate(async (valid, fields) => { + if (valid) { + const data = { + workPermitNo: state.addRecord.workPermitNo, + info: state.addRecord.info, + combustible: Number(state.addRecord.combustible), + oxygen: Number(state.addRecord.oxygen), + carbonMonoxide: Number(state.addRecord.carbonMonoxide), + hydrogenSulfide: Number(state.addRecord.hydrogenSulfide), + source: 2, + }; + await addRecord(data); + state.dialogAddRecord = false; + getListByPage(); + } else { + console.log('error submit!', fields); + } + }); + }; + + const handleSizeChange = (val: number) => { + state.pageSize = val; + getListByPage(); + }; + const handleCurrentChange = (val: number) => { + state.pageIndex = val; + getListByPage(); + }; + + // 查看记录 + const viewRecord = (row) => { + state.details = JSON.parse(JSON.stringify(row)); + state.dialogDetails = true; + }; + + // 刷新 + const reLoadData = async () => { + getListByPage(); + }; + + const closeAdd = () => { + state.addRecord = {}; + state.chosenIndex = null; + }; + + const openAdd = () => { + if (state.chosenIndex == null) { + state.addRecord.info = ''; + } + }; + const indexClear = () => { + state.deleteId = null; + }; + + // 折线图 + const renderMenu = async (value: string) => { + Session.set('projectId', value); + userInfos.value.projectId = value; + await initBackEndControlRoutes(); + }; + return { + addRef, + addRules, + View, + Edit, + Delete, + Refresh, + Plus, + Search, + permitNoInfo, + confirmPermitNo, + searchRecord, + clearSearch, + viewRecord, + getListByPage, + reLoadData, + handleSizeChange, + handleCurrentChange, + confirmAddRecord, + closeAdd, + openAdd, + indexClear, + ...toRefs(state) + }; + } + }; +</script> + +<style scoped lang="scss"> + $homeNavLengh: 8; + .red{ + color: red; + } + .home-container { + height: calc(100vh - 144px); + box-sizing: border-box; + overflow: hidden; + .homeCard { + width: 100%; + padding: 20px; + box-sizing: border-box; + background: #fff; + border-radius: 4px; + + .main-card { + width: 100%; + height: 100%; + .cardTop { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 20px; + .mainCardBtn { + margin: 0; + } + } + .pageBtn { + height: 60px; + display: flex; + align-items: center; + justify-content: right; + + .demo-pagination-block + .demo-pagination-block { + margin-top: 10px; + } + .demo-pagination-block .demonstration { + margin-bottom: 16px; + } + } + } + &:last-of-type { + height: calc(100% - 100px); + } + } + .el-row { + display: flex; + align-items: center; + margin-bottom: 20px; + &:last-child { + margin-bottom: 0; + } + .grid-content { + align-items: center; + min-height: 36px; + } + + .topInfo { + width: 100%; + display: flex; + align-items: center; + font-size: 16px; + font-weight: bold; + + & > div { + white-space: nowrap; + margin-right: 20px; + } + } + } + } + .el-input{ + width: 100% !important; + } + .el-date-editor::v-deep{ + width: 100%; + } + .el-select{ + width: 100%; + } +</style> diff --git a/src/views/specialWorkSystem/process/zyjcgl/index.vue b/src/views/specialWorkSystem/process/zyjcgl/index.vue new file mode 100644 index 0000000..7398d60 --- /dev/null +++ b/src/views/specialWorkSystem/process/zyjcgl/index.vue @@ -0,0 +1,632 @@ +<template> + <div class="home-container"> + <div style="height: 100%"> + <el-row class="homeCard"> + <el-col :span="6" style="display:flex;align-items: center"> + <span style="white-space: nowrap">作业证编号:</span> + <div class="grid-content topInfo"> + <el-input v-model="workPermitNo" placeholder="请输入作业证编号"></el-input> + </div> + </el-col> + <el-col :span="6" style="display:flex;align-items: center"> + <span style="white-space: nowrap">作业类型:</span> + <div class="grid-content topInfo"> + <el-select v-model="workType" placeholder="请选择作业类型"> + <el-option + v-for="item in workTypeList" + :key="item.id" + :label="item.name" + :value="item.id" + /> + </el-select> + </div> + </el-col> + <el-button type="primary" @click="searchRecord">查询</el-button> + <el-button plain @click="clearSearch">重置</el-button> + </el-row> + <div class="homeCard"> + <div class="main-card"> + <el-row class="cardTop"> + <el-col :span="12" class="mainCardBtn"> + <el-button type="primary" :icon="Plus" size="default" @click="dialogAddRecord = true">新增</el-button> + </el-col> + <el-button type="primary" :icon="Refresh" size="default" @click="reLoadData"/> + </el-row> + <el-table + :data="tableData" + style="width: 100%" + height="calc(100% - 100px)" + :header-cell-style="{background: '#fafafa'}" + > + <el-table-column type="index" label="序号" width="80" align="center"/> + <el-table-column property="workPermitNo" label="作业证编号" align="center"/> + <el-table-column property="workTypeDesc" label="作业类型" align="center"/> + <el-table-column property="checkContent" label="检查内容" align="center"/> + <el-table-column property="checkResultDesc" label="检查结果" align="center"> + <template #default="scope"> + <span :class="scope.row.checkResultDesc == '异常' ? 'red': ''">{{ scope.row.checkResultDesc}}</span> + </template> + </el-table-column> + <el-table-column property="info" label="描述" show-overflow-tooltip width="200" align="center"/> + <el-table-column property="operatorUname" label="分析人" align="center"/> + <el-table-column property="operationTime" label="分析时间" width="180" align="center"/> + <el-table-column property="mcResultName" label="物资检查" width="180" align="center"> + <template #default="scope"> + <span :class="scope.row.mcResultName == '不合格' ? 'red': ''">{{ scope.row.mcResultName== null?'-':scope.row.mcResultName}}</span> + </template> + </el-table-column> + <el-table-column fixed="right" label="操作" align="center" width="100"> + <template #default="scope"> + <el-button link type="primary" size="small" :icon="View" @click="viewRecord(scope.row)">查看</el-button> + </template> + </el-table-column> + </el-table> + <div class="pageBtn"> + <el-pagination + v-model:currentPage="currentPage" + v-model:page-size="pageSize" + :page-sizes="[10, 15]" + small=false + background + layout="total, sizes, prev, pager, next, jumper" + :total="totalSize" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + </div> + </div> + </div> + <el-dialog v-model="dialogDetails" title="检查记录"> + <el-form :model="details" label-width="120px"> + <el-form-item label="作业证编号"> + <el-input v-model="details.workPermitNo" readonly/> + </el-form-item> + <el-form-item label="作业类型"> + <el-input v-model="details.workTypeDesc" readonly/> + </el-form-item> + <el-form-item label="检查内容"> + <el-input v-model="details.checkContent" readonly/> + </el-form-item> + <el-form-item label="检查结果"> + <el-input :class="details.checkResultDesc == '异常' ? 'red': ''" v-model="details.checkResultDesc" readonly/> + </el-form-item> + <el-form-item label="现场图片" v-if="details.imagePaths && details.imagePaths.length>0"> + <el-image v-for="item in details.imagePaths" :preview-src-list="details.imagePaths" style="width: 150px; height: 150px;margin-right: 50px;margin-bottom: 20px" :src="item" fit="cover" /> + </el-form-item> + <el-form-item label="描述"> + <el-input v-model="details.info" type="textarea" readonly/> + </el-form-item> + <el-form-item label="分析人"> + <el-input v-model="details.operatorUname" readonly/> + </el-form-item> + <el-form-item label="分析时间"> + <el-input v-model="details.operationTime" readonly/> + </el-form-item> + <el-form-item label="物资检查"> + <span>{{details.mcResultName== null?'-':details.mcResultName}}</span> + </el-form-item> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button type="primary" @click="dialogDetails = false">确认</el-button> + </span> + </template> + </el-dialog> + <el-dialog v-model="dialogAddRecord" title="新增" @close="closeAdd" @open="openAdd"> + <el-form :model="addRecord" label-width="120px" ref="addRef" :rules="addRules"> + <el-form-item label="作业证编号" prop="workPermitNo"> + <el-input v-model="addRecord.workPermitNo" placeholder="作业编号须为已审批作业的编号,可点击右方按钮查询"> + <template #append> + <el-button :icon="Search" @click="dialogPermitNo = true"/> + </template> + </el-input> + </el-form-item> + <el-form-item label="作业类型" prop="workType"> + <el-select v-model="addRecord.workType"> + <el-option + v-for="item in workTypeList" + :key="item.id" + :label="item.name" + :value="item.id" + /> + </el-select> + </el-form-item> + <el-form-item label="检查内容" prop="checkContent"> + <el-input v-model="addRecord.checkContent"> </el-input> + </el-form-item> + <el-form-item label="检查结果" prop="checkResult"> + <el-select v-model="addRecord.checkResult"> + <el-option label="正常" value="1"/> + <el-option label="异常" value="2"/> + </el-select> + </el-form-item> + <el-form-item label="现场照片" prop="imagePaths"> + <el-upload accept="image/*" :on-exceed="showTip" :on-preview="handlePictureCardPreview" :limit='imgLimit' v-model:file-list="fileList" :http-request="upload" :action="uploadUrl" list-type="picture-card" :on-remove="handleRemove" :before-remove="beforeRemove" :before-upload="getUploadUrl"> + <el-icon><Plus /></el-icon> + <template #tip> + <div class="el-upload__tip">上传jpg/png图片尺寸小于500KB,最多可上传3张</div> + </template> + </el-upload> + </el-form-item> + <el-form-item label="描述" prop="info"> + <el-input v-model="addRecord.info" type="textarea"> </el-input> + </el-form-item> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button type="warning" @click="dialogAddRecord = false" size="default" plain>取消</el-button> + <el-button type="primary" @click="confirmAddRecord(addRef)" size="default">确认</el-button> + </span> + </template> + </el-dialog> + <el-dialog v-model="dialogVisible"> + <img w-full :src="dialogImageUrl" alt="Preview Image" /> + </el-dialog> + <el-dialog v-model="dialogPermitNo" title="选择相应的作业编号"> + <permit-no ref="permitNoInfo"></permit-no> + <template #footer> + <span class="dialog-footer"> + <el-button type="warning" @click="dialogPermitNo = false" size="default" plain>取消</el-button> + <el-button type="primary" @click="confirmPermitNo" size="default">确认</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script lang="ts"> + import {toRefs, reactive, ref, onMounted, defineAsyncComponent} from 'vue'; + import { storeToRefs } from 'pinia'; + import { initBackEndControlRoutes } from '/@/router/backEnd'; + import { useUserInfo } from '/@/stores/userInfo'; + import { Session } from '/@/utils/storage'; + import { Edit, View, Plus, Delete, Refresh, Search, Download } from '@element-plus/icons-vue'; + import { ElTable, ElMessage, ElMessageBox } from 'element-plus' + import type { FormInstance, FormRules, UploadProps, UploadUserFile } from 'element-plus' + import { teamManageApi } from '/@/api/systemManage/basicDateManage/personShiftManage/teamManage'; + import { workProcessApi } from '/@/api/specialWorkSystem/workProcess'; + import { workApplyApi } from '/@/api/specialWorkSystem/workApply'; + import axios from 'axios'; + + // 定义接口来定义对象的类型 + interface stateType { + tableData: Array<any>; + imgLimit: number; + fileList: Array<file>, + uploadUrl: string, + isOverSize: Boolean, + dialogVisible: Boolean, + dialogImageUrl: string | null, + multipleSelection: Array<any>; + deleteArr: Array<any>; + dialogDetails: boolean; + dialogAddRecord: boolean; + dialogPermitNo: boolean; + deleteDialog: boolean; + deleteSetDialog: boolean; + pageIndex: number; + pageSize: number; + chosenIndex: null | number; + deleteId: null | number; + workPermitNo: string; + workType: number | null; + totalSize: number; + addRecord: {}; + details: {}; + workTypeList: Array<any> + } + interface file { + url: string; + } + export default { + name: 'analysis', + components: { + permitNo: defineAsyncComponent(() => import('/@/views/specialWorkSystem/process/components/dialogPermitNo.vue')) + }, + setup() { + const userInfo = useUserInfo(); + const { userInfos } = storeToRefs(userInfo); + const permitNoInfo = ref() + const state = reactive<stateType>({ + pageIndex: 1, + pageSize: 10, + totalSize: 0, + chosenIndex: null, + workPermitNo: '', + workType: null, + isOverSize: false, + fileList: [], + imgLimit: 3, + uploadUrl: '', + dialogVisible: false, + dialogImageUrl: null, + tableData: [], + multipleSelection: [], + dialogDetails: false, + dialogAddRecord: false, + dialogPermitNo: false, + deleteDialog: false, + deleteSetDialog: false, + addRecord: { + workPermitNo: '', + checkContent: '', + checkResult: '', + info: '', + source: 2, + imagePaths: [] + }, + details: {}, + deleteId: null, + deleteArr: [], + workTypeList: [ + { id: 1, name: '动火作业' }, + { id: 2, name: '受限空间作业' }, + { id: 3, name: '吊装作业' }, + { id: 4, name: '动土作业' }, + { id: 5, name: '断路作业' }, + { id: 6, name: '高处作业' }, + { id: 7, name: '临时用电作业' }, + { id: 8, name: '盲板抽堵作业' } + ] + }); + + const addRef = ref<FormInstance>(); + const addRules = reactive<FormRules>({ + workPermitNo: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + workType: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + checkContent: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + checkResult: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + imagePaths: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + info: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + }); + + // 页面载入时执行方法 + onMounted(() => { + getListByPage(); + }); + + // 分页获取作业检查列表 + const getListByPage = async () => { + const data = { pageSize: state.pageSize, pageIndex: state.pageIndex, searchParams: { workType: state.workType, workPermitNo: state.workPermitNo } }; + let res = await workProcessApi().getCheckListPage(data); + if (res.data.code === '200') { + state.tableData = res.data.data + state.totalSize = res.data.total; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 图片上传 + const showTip =()=>{ + ElMessage({ + type: 'warning', + message: '超出文件上传数量' + }); + } + const confirmPermitNo = ()=>{ + if(permitNoInfo.value.workPermitNo == ''){ + ElMessage({ + type: 'warning', + message: '请选择相应的作业编码' + }); + }else{ + state.addRecord.workPermitNo = permitNoInfo.value.workPermitNo + state.dialogPermitNo = false + } + } + const handlePreview: UploadProps['onPreview'] = (uploadFile) => { + console.log(uploadFile); + }; + + const handlePictureCardPreview = (uploadFile: { url: string }) => { + state.dialogImageUrl = uploadFile.url!; + state.dialogVisible = true; + }; + + const getUploadUrl = async (rawFile: any) => { + const fileSize = rawFile.size / 1024 < 500 ? '1' : '0' + if(fileSize === '0'){ + ElMessage({ + type: 'warning', + message: '文件大小不能超过500k。' + }); + state.isOverSize = true + return false + }else{ + const res = await workApplyApi().getUploadUrl(rawFile.name); + state.addRecord.imagePaths.push(res.data.data.fileName) + state.uploadUrl = res.data.data.uploadUrl; + console.log(state.addRecord.imagePaths,state.uploadUrl,6666666666666) + } + }; + + const upload = async (params: any) => { + // const formData = new FormData(); + // formData.append('file', state.fileList[0].raw); + let reader = new FileReader(); + reader.readAsArrayBuffer(params.file); + reader.onload = async () => { + axios + .put(state.uploadUrl, reader.result, { + header: { 'Content-Type': 'multipart/form-data' } + }) + .then(() => { + // if (state.fileList.length === 2) { + // state.fileList.splice(0, 1); + // } + // console.log(state.form.workDetail.photos,'photos') + }); + }; + }; + + const beforeRemove = (file: {}, fileList: []) => { + const result = new Promise((resolve, reject) => { + if(!state.isOverSize){ + ElMessageBox.confirm('此操作将删除该图片, 是否继续?', '提示', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning' + }) + .then(() => { + // console.log(state.workDetail.photos,'path') + const list = JSON.parse(JSON.stringify(state.addRecord.imagePaths)) + fileList.map((item,index)=>{ + if(item.uid === file.uid){ + fileList.splice(index,1) + state.addRecord.photos.splice(index,1) + // 请求删除接口 + deletePic(false,list[index]) + } + }) + }) + .catch(() => { + reject(false); + }); + }else{ + const list = JSON.parse(JSON.stringify(state.addRecord.imagePaths)) + fileList.map((item,index)=>{ + if(item.uid === file.uid){ + fileList.splice(index,1) + state.addRecord.photos.splice(index,1) + deletePic(true,list[index]) + } + }) + state.isOverSize = false + } + }); + return result; + }; + + // 删除图片接口 + const deletePic = async(isOverSize:boolean,fileName:string)=>{ + const res = await workApplyApi().deleteFile({fileName: fileName}) + if (res.data.code === '200') { + ElMessage({ + type: isOverSize ? 'error' : 'success', + message: isOverSize ? '上传失败':'删除成功!' + }); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } + + + // 关键词查询记录 + const searchRecord = async () => { + if (state.workPermitNo == ''&& state.workType == null) { + ElMessage({ + type: 'warning', + message: '请输入查询关键词' + }); + } else { + getListByPage(); + } + }; + + const clearSearch = async () => { + state.workPermitNo = ''; + state.workType = null; + getListByPage(); + }; + + + // 添加气体检测方法 + const addRecord = async (data: any) => { + let res = await workProcessApi().postCheckReport(data); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '添加成功!' + }); + getListByPage(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + + // 新增修改记录 + const confirmAddRecord = async (formEl: FormInstance | undefined) => { + if (!formEl) return; + await formEl.validate(async (valid, fields) => { + if (valid) { + await addRecord(state.addRecord); + state.dialogAddRecord = false; + getListByPage(); + } else { + console.log('error submit!', fields); + } + }); + }; + + const handleSizeChange = (val: number) => { + state.pageSize = val; + getListByPage(); + }; + const handleCurrentChange = (val: number) => { + state.pageIndex = val; + getListByPage(); + }; + + // 查看记录 + const viewRecord = (row) => { + state.details = JSON.parse(JSON.stringify(row)); + state.dialogDetails = true; + }; + + // 刷新 + const reLoadData = async () => { + getListByPage(); + }; + + const closeAdd = () => { + state.addRecord = {}; + state.chosenIndex = null; + }; + + const openAdd = () => { + if (state.chosenIndex == null) { + state.addRecord.info = ''; + } + }; + const indexClear = () => { + state.deleteId = null; + }; + + // 折线图 + const renderMenu = async (value: string) => { + Session.set('projectId', value); + userInfos.value.projectId = value; + await initBackEndControlRoutes(); + }; + return { + addRef, + addRules, + View, + Edit, + Delete, + Refresh, + Plus, + Search, + permitNoInfo, + showTip, + confirmPermitNo, + handlePreview, + handlePictureCardPreview, + getUploadUrl, + upload, + beforeRemove, + searchRecord, + clearSearch, + viewRecord, + getListByPage, + reLoadData, + handleSizeChange, + handleCurrentChange, + confirmAddRecord, + closeAdd, + openAdd, + indexClear, + ...toRefs(state) + }; + } + }; +</script> + +<style scoped lang="scss"> + $homeNavLengh: 8; + .red{ + color: red; + + ::v-deep(input){ + color: red; + } + } + .home-container { + height: calc(100vh - 144px); + box-sizing: border-box; + overflow: hidden; + .homeCard { + width: 100%; + padding: 20px; + box-sizing: border-box; + background: #fff; + border-radius: 4px; + + .main-card { + width: 100%; + height: 100%; + .cardTop { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 20px; + .mainCardBtn { + margin: 0; + } + } + .pageBtn { + height: 60px; + display: flex; + align-items: center; + justify-content: right; + + .demo-pagination-block + .demo-pagination-block { + margin-top: 10px; + } + .demo-pagination-block .demonstration { + margin-bottom: 16px; + } + } + } + &:last-of-type { + height: calc(100% - 100px); + } + } + .el-row { + display: flex; + align-items: center; + margin-bottom: 20px; + &:last-child { + margin-bottom: 0; + } + .grid-content { + align-items: center; + min-height: 36px; + } + + .topInfo { + width: 100%; + display: flex; + align-items: center; + font-size: 16px; + font-weight: bold; + + & > div { + white-space: nowrap; + margin-right: 20px; + } + } + } + } + .el-input{ + width: 100% !important; + } + .el-date-editor::v-deep{ + width: 100%; + } + .el-select{ + width: 100%; + } +</style> diff --git a/src/views/specialWorkSystem/workTicket/wdsp/components/brokenLog.vue b/src/views/specialWorkSystem/workTicket/wdsp/components/brokenLog.vue new file mode 100644 index 0000000..dcb6adc --- /dev/null +++ b/src/views/specialWorkSystem/workTicket/wdsp/components/brokenLog.vue @@ -0,0 +1,152 @@ +<template> + <div style="height: 100%"> + <el-form :model="details" label-width="150px"> + <el-form-item label="作业申请单号"> + <el-input v-model="details.workPermitNo" readonly /> + </el-form-item> + <el-form-item label="申请人"> + <el-input v-model="details.applyUname" readonly /> + </el-form-item> + <el-form-item label="部门名称"> + <el-input v-model="details.depName" readonly /> + </el-form-item> + <el-form-item label="作业人"> + <el-input v-model="details.operators" readonly type="textarea" /> + </el-form-item> + <el-form-item label="作业类型"> + <el-input v-model="details.workTypeDesc" readonly /> + </el-form-item> + <el-form-item label="作业等级"> + <el-input v-model="details.workLevelDesc" readonly /> + </el-form-item> + <el-form-item label="作业内容"> + <el-input v-model="details.workContent" readonly type="textarea" /> + </el-form-item> + <el-form-item label="作业地址"> + <el-input v-model="details.workLocation" readonly type="textarea" /> + </el-form-item> + <el-form-item label="作业单位ID"> + <el-input v-model="details.workDetail.operationDepId" readonly type="textarea" /> + </el-form-item> + <el-form-item label="断路原因"> + <el-input v-model="details.workDetail.bcReason" readonly type="textarea" /> + </el-form-item> + <el-form-item label="断路地段说明"> + <el-input v-model="details.workDetail.bcExplain" readonly type="textarea" /> + </el-form-item> + <el-form-item label="涉及相关部门"> + <el-input v-model="details.workDetail.involvedDepIds" readonly type="textarea"/> + </el-form-item> + <el-form-item label="图片"> + <el-image v-for="item in details.workDetail.bcPath" :preview-src-list="details.workDetail.bcPath" style="width: 150px; height: 150px;margin-right: 50px;margin-bottom: 20px" :src="item" fit="cover" /> + </el-form-item> + <el-form-item label="期望开始时间"> + <el-input v-model="details.expStartTime" readonly /> + </el-form-item> + <el-form-item label="期望结束时间"> + <el-input v-model="details.expEndTime" readonly /> + </el-form-item> + <el-form-item label="申请时间"> + <el-input v-model="details.applyTime" readonly /> + </el-form-item> +<!-- <el-form-item label="当前层级">--> +<!-- <el-input v-model="details.stepId" readonly />--> +<!-- </el-form-item>--> +<!-- <el-form-item label="上一层级">--> +<!-- <el-input v-model="details.preStepId" readonly />--> +<!-- </el-form-item>--> +<!-- <el-form-item label="下一层级">--> +<!-- <el-input v-model="details.nextStepId" readonly />--> +<!-- </el-form-item>--> + <el-form-item label="层级审批类型"> + <el-input v-model="details.stepTypeDesc" readonly /> + </el-form-item> + <el-form-item v-if="details.stepSerial && details.stepSerial!=null" label="层级排序号"> + <el-input v-model="details.stepSerial" readonly /> + </el-form-item> + <el-form-item v-if="details.stepStartApprovalTime && details.stepStartApprovalTime!=null" label="层级预期开始审批时间"> + <el-input v-model="details.stepStartApprovalTime" readonly /> + </el-form-item> + <el-form-item v-if="details.stepFinishApprovalTime && details.stepFinishApprovalTime!=null" label="层级预期结束审批时间"> + <el-input v-model="details.stepFinishApprovalTime" readonly /> + </el-form-item> + <el-form-item label="审批人姓名"> + <el-input v-model="details.unitApprovalUname" readonly /> + </el-form-item> + <el-form-item v-if="details.unitApprovalStartTime && details.unitApprovalStartTime!=null" label="单元审批开始时间"> + <el-input v-model="details.unitApprovalStartTime" readonly /> + </el-form-item> + <el-form-item v-if="details.unitApprovalEndTime && details.unitApprovalEndTime!=null" label="单元审批结束时间"> + <el-input v-model="details.unitApprovalEndTime" readonly /> + </el-form-item> + <el-form-item v-if="details.unitResultDesc && details.unitResultDesc!=null" label="单元审批结果"> + <el-input v-model="details.unitResultDesc" readonly /> + </el-form-item> + <el-form-item v-if="details.statusDesc && details.statusDesc!=null" label="当前状态"> + <el-input v-model="details.statusDesc" readonly /> + </el-form-item> + <el-form-item v-if="details.stepApprovalResultDesc && details.stepApprovalResultDesc!=null" label="审批结果"> + <el-input v-model="details.stepApprovalResultDesc" readonly /> + </el-form-item> + </el-form> + </div> +</template> + +<script lang="ts"> + import { toRefs, reactive, defineComponent, ref, defineAsyncComponent } from 'vue'; + import { storeToRefs } from 'pinia'; + import { initBackEndControlRoutes } from '/@/router/backEnd'; + import {useUserInfo} from "/@/stores/userInfo"; + import { Session } from '/@/utils/storage'; + import { Search } from '@element-plus/icons-vue' + import { ElMessage } from 'element-plus' + import type { FormInstance, FormRules } from 'element-plus' + import { workApplyApi } from '/@/api/specialWorkSystem/workApply'; + + + interface stateType { + form: Object, + workerList: Array<any>, + workTypeList: Array<any>, + workLevelList: Array<any>, + otherWorkList: Array<any> + } + export default defineComponent({ + name: 'space', + components: {}, + props:['details'], + setup() { + const userInfo = useUserInfo() + const { userInfos } = storeToRefs(userInfo); + return { + Search + }; + }, + }); +</script> + +<style scoped lang="scss"> + .home-container { + height: 100%; + overflow: hidden; + position: relative; + .el-row{ + margin-bottom: 20px; + } + .el-row:last-child { + margin-bottom: 0; + } + .el-input{ + width: 100% !important; + } + .el-date-editor::v-deep{ + width: 100%; + } + .el-select{ + width: 100%; + } + .el-cascader{ + width: 100% !important; + } + } +</style> diff --git a/src/views/specialWorkSystem/workTicket/wdsp/components/fireLog.vue b/src/views/specialWorkSystem/workTicket/wdsp/components/fireLog.vue new file mode 100644 index 0000000..ed30241 --- /dev/null +++ b/src/views/specialWorkSystem/workTicket/wdsp/components/fireLog.vue @@ -0,0 +1,137 @@ +<template> + <div style="height: 100%"> + <el-form :model="details" label-width="150px"> + <el-form-item label="作业申请单号"> + <el-input v-model="details.workPermitNo" readonly /> + </el-form-item> + <el-form-item label="申请人"> + <el-input v-model="details.applyUname" readonly /> + </el-form-item> + <el-form-item label="部门名称"> + <el-input v-model="details.depName" readonly /> + </el-form-item> + <el-form-item label="作业人"> + <el-input v-model="details.operators" readonly type="textarea" /> + </el-form-item> + <el-form-item label="作业类型"> + <el-input v-model="details.workTypeDesc" readonly /> + </el-form-item> + <el-form-item label="作业等级"> + <el-input v-model="details.workLevelDesc" readonly /> + </el-form-item> + <el-form-item label="作业内容"> + <el-input v-model="details.workContent" readonly type="textarea" /> + </el-form-item> + <el-form-item label="作业地址"> + <el-input v-model="details.workLocation" readonly type="textarea" /> + </el-form-item> + <el-form-item label="作业方式"> + <el-input v-model="details.workDetail.hotMethod" readonly type="textarea" /> + </el-form-item> + <el-form-item label="关联其他作业"> + <el-input v-model="details.workDetail.otherSpecialWork" readonly type="textarea" /> + </el-form-item> + <el-form-item label="申请时间"> + <el-input v-model="details.applyTime" readonly /> + </el-form-item> +<!-- <el-form-item label="当前层级">--> +<!-- <el-input v-model="details.stepId" readonly />--> +<!-- </el-form-item>--> +<!-- <el-form-item label="上一层级">--> +<!-- <el-input v-model="details.preStepId" readonly />--> +<!-- </el-form-item>--> +<!-- <el-form-item label="下一层级">--> +<!-- <el-input v-model="details.nextStepId" readonly />--> +<!-- </el-form-item>--> + <el-form-item label="层级审批类型"> + <el-input v-model="details.stepTypeDesc" readonly /> + </el-form-item> + <el-form-item v-if="details.stepSerial && details.stepSerial!=null" label="层级排序号"> + <el-input v-model="details.stepSerial" readonly /> + </el-form-item> + <el-form-item v-if="details.stepStartApprovalTime && details.stepStartApprovalTime!=null" label="层级预期开始审批时间"> + <el-input v-model="details.stepStartApprovalTime" readonly /> + </el-form-item> + <el-form-item v-if="details.stepFinishApprovalTime && details.stepFinishApprovalTime!=null" label="层级预期结束审批时间"> + <el-input v-model="details.stepFinishApprovalTime" readonly /> + </el-form-item> + <el-form-item label="审批人姓名"> + <el-input v-model="details.unitApprovalUname" readonly /> + </el-form-item> + <el-form-item v-if="details.unitApprovalStartTime && details.unitApprovalStartTime!=null" label="单元审批开始时间"> + <el-input v-model="details.unitApprovalStartTime" readonly /> + </el-form-item> + <el-form-item v-if="details.unitApprovalEndTime && details.unitApprovalEndTime!=null" label="单元审批结束时间"> + <el-input v-model="details.unitApprovalEndTime" readonly /> + </el-form-item> + <el-form-item v-if="details.unitResultDesc && details.unitResultDesc!=null" label="单元审批结果"> + <el-input v-model="details.unitResultDesc" readonly /> + </el-form-item> + <el-form-item v-if="details.statusDesc && details.statusDesc!=null" label="当前状态"> + <el-input v-model="details.statusDesc" readonly /> + </el-form-item> + <el-form-item v-if="details.stepApprovalResultDesc && details.stepApprovalResultDesc!=null" label="审批结果"> + <el-input v-model="details.stepApprovalResultDesc" readonly /> + </el-form-item> + </el-form> + </div> +</template> + +<script lang="ts"> + import { toRefs, reactive, defineComponent, ref, defineAsyncComponent } from 'vue'; + import { storeToRefs } from 'pinia'; + import { initBackEndControlRoutes } from '/@/router/backEnd'; + import {useUserInfo} from "/@/stores/userInfo"; + import { Session } from '/@/utils/storage'; + import { Search } from '@element-plus/icons-vue' + import { ElMessage } from 'element-plus' + import type { FormInstance, FormRules } from 'element-plus' + import { workApplyApi } from '/@/api/specialWorkSystem/workApply'; + + + interface stateType { + form: Object, + workerList: Array<any>, + workTypeList: Array<any>, + workLevelList: Array<any>, + otherWorkList: Array<any> + } + export default defineComponent({ + name: 'fire', + components: {}, + props:['details'], + setup() { + const userInfo = useUserInfo() + const { userInfos } = storeToRefs(userInfo); + return { + Search + }; + }, + }); +</script> + +<style scoped lang="scss"> + .home-container { + height: 100%; + overflow: hidden; + position: relative; + .el-row{ + margin-bottom: 20px; + } + .el-row:last-child { + margin-bottom: 0; + } + .el-input{ + width: 100% !important; + } + .el-date-editor::v-deep{ + width: 100%; + } + .el-select{ + width: 100%; + } + .el-cascader{ + width: 100% !important; + } + } +</style> diff --git a/src/views/specialWorkSystem/workTicket/wdsp/components/groundLog.vue b/src/views/specialWorkSystem/workTicket/wdsp/components/groundLog.vue new file mode 100644 index 0000000..244330e --- /dev/null +++ b/src/views/specialWorkSystem/workTicket/wdsp/components/groundLog.vue @@ -0,0 +1,152 @@ +<template> + <div style="height: 100%"> + <el-form :model="details" label-width="150px"> + <el-form-item label="作业申请单号"> + <el-input v-model="details.workPermitNo" readonly /> + </el-form-item> + <el-form-item label="申请人"> + <el-input v-model="details.applyUname" readonly /> + </el-form-item> + <el-form-item label="部门名称"> + <el-input v-model="details.depName" readonly /> + </el-form-item> + <el-form-item label="作业人"> + <el-input v-model="details.operators" readonly type="textarea" /> + </el-form-item> + <el-form-item label="作业类型"> + <el-input v-model="details.workTypeDesc" readonly /> + </el-form-item> + <el-form-item label="作业等级"> + <el-input v-model="details.workLevelDesc" readonly /> + </el-form-item> + <el-form-item label="作业内容"> + <el-input v-model="details.workContent" readonly type="textarea" /> + </el-form-item> + <el-form-item label="作业地址"> + <el-input v-model="details.workLocation" readonly type="textarea" /> + </el-form-item> + <el-form-item label="作业单位"> + <el-input v-model="details.workDetail.operationDepId" readonly type="textarea" /> + </el-form-item> + <el-form-item label="范围"> + <el-input v-model="details.workDetail.gbScope" readonly type="textarea" /> + </el-form-item> + <el-form-item label="动土方式"> + <el-input v-model="details.workDetail.gbMethod" readonly type="textarea" /> + </el-form-item> + <el-form-item label="关联其他作业"> + <el-input v-model="details.workDetail.otherSpecialWork" readonly type="textarea"/> + </el-form-item> + <el-form-item label="图片"> + <el-image v-for="item in details.workDetail.gbPath" :preview-src-list="details.workDetail.gbPath" style="width: 150px; height: 150px;margin-right: 50px;margin-bottom: 20px" :src="item" fit="cover" /> + </el-form-item> + <el-form-item label="期望开始时间"> + <el-input v-model="details.expStartTime" readonly /> + </el-form-item> + <el-form-item label="期望结束时间"> + <el-input v-model="details.expEndTime" readonly /> + </el-form-item> + <el-form-item label="申请时间"> + <el-input v-model="details.applyTime" readonly /> + </el-form-item> +<!-- <el-form-item label="当前层级">--> +<!-- <el-input v-model="details.stepId" readonly />--> +<!-- </el-form-item>--> +<!-- <el-form-item label="上一层级">--> +<!-- <el-input v-model="details.preStepId" readonly />--> +<!-- </el-form-item>--> +<!-- <el-form-item label="下一层级">--> +<!-- <el-input v-model="details.nextStepId" readonly />--> +<!-- </el-form-item>--> + <el-form-item label="层级审批类型"> + <el-input v-model="details.stepTypeDesc" readonly /> + </el-form-item> + <el-form-item v-if="details.stepSerial && details.stepSerial!=null" label="层级排序号"> + <el-input v-model="details.stepSerial" readonly /> + </el-form-item> + <el-form-item v-if="details.stepStartApprovalTime && details.stepStartApprovalTime!=null" label="层级预期开始审批时间"> + <el-input v-model="details.stepStartApprovalTime" readonly /> + </el-form-item> + <el-form-item v-if="details.stepFinishApprovalTime && details.stepFinishApprovalTime!=null" label="层级预期结束审批时间"> + <el-input v-model="details.stepFinishApprovalTime" readonly /> + </el-form-item> + <el-form-item label="审批人姓名"> + <el-input v-model="details.unitApprovalUname" readonly /> + </el-form-item> + <el-form-item v-if="details.unitApprovalStartTime && details.unitApprovalStartTime!=null" label="单元审批开始时间"> + <el-input v-model="details.unitApprovalStartTime" readonly /> + </el-form-item> + <el-form-item v-if="details.unitApprovalEndTime && details.unitApprovalEndTime!=null" label="单元审批结束时间"> + <el-input v-model="details.unitApprovalEndTime" readonly /> + </el-form-item> + <el-form-item v-if="details.unitResultDesc && details.unitResultDesc!=null" label="单元审批结果"> + <el-input v-model="details.unitResultDesc" readonly /> + </el-form-item> + <el-form-item v-if="details.statusDesc && details.statusDesc!=null" label="当前状态"> + <el-input v-model="details.statusDesc" readonly /> + </el-form-item> + <el-form-item v-if="details.stepApprovalResultDesc && details.stepApprovalResultDesc!=null" label="审批结果"> + <el-input v-model="details.stepApprovalResultDesc" readonly /> + </el-form-item> + </el-form> + </div> +</template> + +<script lang="ts"> + import { toRefs, reactive, defineComponent, ref, defineAsyncComponent } from 'vue'; + import { storeToRefs } from 'pinia'; + import { initBackEndControlRoutes } from '/@/router/backEnd'; + import {useUserInfo} from "/@/stores/userInfo"; + import { Session } from '/@/utils/storage'; + import { Search } from '@element-plus/icons-vue' + import { ElMessage } from 'element-plus' + import type { FormInstance, FormRules } from 'element-plus' + import { workApplyApi } from '/@/api/specialWorkSystem/workApply'; + + + interface stateType { + form: Object, + workerList: Array<any>, + workTypeList: Array<any>, + workLevelList: Array<any>, + otherWorkList: Array<any> + } + export default defineComponent({ + name: 'space', + components: {}, + props:['details'], + setup() { + const userInfo = useUserInfo() + const { userInfos } = storeToRefs(userInfo); + return { + Search + }; + }, + }); +</script> + +<style scoped lang="scss"> + .home-container { + height: 100%; + overflow: hidden; + position: relative; + .el-row{ + margin-bottom: 20px; + } + .el-row:last-child { + margin-bottom: 0; + } + .el-input{ + width: 100% !important; + } + .el-date-editor::v-deep{ + width: 100%; + } + .el-select{ + width: 100%; + } + .el-cascader{ + width: 100% !important; + } + } +</style> diff --git a/src/views/specialWorkSystem/workTicket/wdsp/components/heightLog.vue b/src/views/specialWorkSystem/workTicket/wdsp/components/heightLog.vue new file mode 100644 index 0000000..0fb8a7a --- /dev/null +++ b/src/views/specialWorkSystem/workTicket/wdsp/components/heightLog.vue @@ -0,0 +1,146 @@ +<template> + <div style="height: 100%"> + <el-form :model="details" label-width="150px"> + <el-form-item label="作业申请单号"> + <el-input v-model="details.workPermitNo" readonly /> + </el-form-item> + <el-form-item label="申请人"> + <el-input v-model="details.applyUname" readonly /> + </el-form-item> + <el-form-item label="部门名称"> + <el-input v-model="details.depName" readonly /> + </el-form-item> + <el-form-item label="作业人"> + <el-input v-model="details.operators" readonly type="textarea" /> + </el-form-item> + <el-form-item label="作业类型"> + <el-input v-model="details.workTypeDesc" readonly /> + </el-form-item> + <el-form-item label="作业等级"> + <el-input v-model="details.workLevelDesc" readonly /> + </el-form-item> + <el-form-item label="作业内容"> + <el-input v-model="details.workContent" readonly type="textarea" /> + </el-form-item> + <el-form-item label="作业地址"> + <el-input v-model="details.workLocation" readonly type="textarea" /> + </el-form-item> + <el-form-item label="作业单位ID"> + <el-input v-model="details.workDetail.operationDepId" readonly type="textarea" /> + </el-form-item> + <el-form-item label="作业高度"> + <el-input v-model="details.workDetail.operationHeight" readonly type="textarea"><template #append>米(m)</template></el-input> + </el-form-item> + <el-form-item label="关联其他作业"> + <el-input v-model="details.workDetail.otherSpecialWork" readonly type="textarea"/> + </el-form-item> + <el-form-item label="期望开始时间"> + <el-input v-model="details.expStartTime" readonly /> + </el-form-item> + <el-form-item label="期望结束时间"> + <el-input v-model="details.expEndTime" readonly /> + </el-form-item> + <el-form-item label="申请时间"> + <el-input v-model="details.applyTime" readonly /> + </el-form-item> +<!-- <el-form-item label="当前层级">--> +<!-- <el-input v-model="details.stepId" readonly />--> +<!-- </el-form-item>--> +<!-- <el-form-item label="上一层级">--> +<!-- <el-input v-model="details.preStepId" readonly />--> +<!-- </el-form-item>--> +<!-- <el-form-item label="下一层级">--> +<!-- <el-input v-model="details.nextStepId" readonly />--> +<!-- </el-form-item>--> + <el-form-item label="层级审批类型"> + <el-input v-model="details.stepTypeDesc" readonly /> + </el-form-item> + <el-form-item v-if="details.stepSerial && details.stepSerial!=null" label="层级排序号"> + <el-input v-model="details.stepSerial" readonly /> + </el-form-item> + <el-form-item v-if="details.stepStartApprovalTime && details.stepStartApprovalTime!=null" label="层级预期开始审批时间"> + <el-input v-model="details.stepStartApprovalTime" readonly /> + </el-form-item> + <el-form-item v-if="details.stepFinishApprovalTime && details.stepFinishApprovalTime!=null" label="层级预期结束审批时间"> + <el-input v-model="details.stepFinishApprovalTime" readonly /> + </el-form-item> + <el-form-item label="审批人姓名"> + <el-input v-model="details.unitApprovalUname" readonly /> + </el-form-item> + <el-form-item v-if="details.unitApprovalStartTime && details.unitApprovalStartTime!=null" label="单元审批开始时间"> + <el-input v-model="details.unitApprovalStartTime" readonly /> + </el-form-item> + <el-form-item v-if="details.unitApprovalEndTime && details.unitApprovalEndTime!=null" label="单元审批结束时间"> + <el-input v-model="details.unitApprovalEndTime" readonly /> + </el-form-item> + <el-form-item v-if="details.unitResultDesc && details.unitResultDesc!=null" label="单元审批结果"> + <el-input v-model="details.unitResultDesc" readonly /> + </el-form-item> + <el-form-item v-if="details.statusDesc && details.statusDesc!=null" label="当前状态"> + <el-input v-model="details.statusDesc" readonly /> + </el-form-item> + <el-form-item v-if="details.stepApprovalResultDesc && details.stepApprovalResultDesc!=null" label="审批结果"> + <el-input v-model="details.stepApprovalResultDesc" readonly /> + </el-form-item> + </el-form> + </div> +</template> + +<script lang="ts"> + import { toRefs, reactive, defineComponent, ref, defineAsyncComponent } from 'vue'; + import { storeToRefs } from 'pinia'; + import { initBackEndControlRoutes } from '/@/router/backEnd'; + import {useUserInfo} from "/@/stores/userInfo"; + import { Session } from '/@/utils/storage'; + import { Search } from '@element-plus/icons-vue' + import { ElMessage } from 'element-plus' + import type { FormInstance, FormRules } from 'element-plus' + import { workApplyApi } from '/@/api/specialWorkSystem/workApply'; + + + interface stateType { + form: Object, + workerList: Array<any>, + workTypeList: Array<any>, + workLevelList: Array<any>, + otherWorkList: Array<any> + } + export default defineComponent({ + name: 'space', + components: {}, + props:['details'], + setup() { + const userInfo = useUserInfo() + const { userInfos } = storeToRefs(userInfo); + return { + Search + }; + }, + }); +</script> + +<style scoped lang="scss"> + .home-container { + height: 100%; + overflow: hidden; + position: relative; + .el-row{ + margin-bottom: 20px; + } + .el-row:last-child { + margin-bottom: 0; + } + .el-input{ + width: 100% !important; + } + .el-date-editor::v-deep{ + width: 100%; + } + .el-select{ + width: 100%; + } + .el-cascader{ + width: 100% !important; + } + } +</style> diff --git a/src/views/specialWorkSystem/workTicket/wdsp/components/hoistLog.vue b/src/views/specialWorkSystem/workTicket/wdsp/components/hoistLog.vue new file mode 100644 index 0000000..3b4dc2a --- /dev/null +++ b/src/views/specialWorkSystem/workTicket/wdsp/components/hoistLog.vue @@ -0,0 +1,146 @@ +<template> + <div style="height: 100%"> + <el-form :model="details" label-width="150px"> + <el-form-item label="作业申请单号"> + <el-input v-model="details.workPermitNo" readonly /> + </el-form-item> + <el-form-item label="申请人"> + <el-input v-model="details.applyUname" readonly /> + </el-form-item> + <el-form-item label="部门名称"> + <el-input v-model="details.depName" readonly /> + </el-form-item> + <el-form-item label="作业人"> + <el-input v-model="details.operators" readonly type="textarea" /> + </el-form-item> + <el-form-item label="作业类型"> + <el-input v-model="details.workTypeDesc" readonly /> + </el-form-item> + <el-form-item label="作业等级"> + <el-input v-model="details.workLevelDesc" readonly /> + </el-form-item> + <el-form-item label="作业内容"> + <el-input v-model="details.workContent" readonly type="textarea" /> + </el-form-item> + <el-form-item label="作业地址"> + <el-input v-model="details.workLocation" readonly type="textarea" /> + </el-form-item> + <el-form-item label="吊装工具名称"> + <el-input v-model="details.workDetail.hoistingToolName" readonly type="textarea" /> + </el-form-item> + <el-form-item label="起吊物体重量"> + <el-input v-model="details.workDetail.weightMass" readonly type="textarea"><template #append>吨(t)</template></el-input> + </el-form-item> + <el-form-item label="关联其他作业"> + <el-input v-model="details.workDetail.otherSpecialWork" readonly type="textarea"/> + </el-form-item> + <el-form-item label="期望开始时间"> + <el-input v-model="details.expStartTime" readonly /> + </el-form-item> + <el-form-item label="期望结束时间"> + <el-input v-model="details.expEndTime" readonly /> + </el-form-item> + <el-form-item label="申请时间"> + <el-input v-model="details.applyTime" readonly /> + </el-form-item> +<!-- <el-form-item label="当前层级">--> +<!-- <el-input v-model="details.stepId" readonly />--> +<!-- </el-form-item>--> +<!-- <el-form-item label="上一层级">--> +<!-- <el-input v-model="details.preStepId" readonly />--> +<!-- </el-form-item>--> +<!-- <el-form-item label="下一层级">--> +<!-- <el-input v-model="details.nextStepId" readonly />--> +<!-- </el-form-item>--> + <el-form-item label="层级审批类型"> + <el-input v-model="details.stepTypeDesc" readonly /> + </el-form-item> + <el-form-item v-if="details.stepSerial && details.stepSerial!=null" label="层级排序号"> + <el-input v-model="details.stepSerial" readonly /> + </el-form-item> + <el-form-item v-if="details.stepStartApprovalTime && details.stepStartApprovalTime!=null" label="层级预期开始审批时间"> + <el-input v-model="details.stepStartApprovalTime" readonly /> + </el-form-item> + <el-form-item v-if="details.stepFinishApprovalTime && details.stepFinishApprovalTime!=null" label="层级预期结束审批时间"> + <el-input v-model="details.stepFinishApprovalTime" readonly /> + </el-form-item> + <el-form-item label="审批人姓名"> + <el-input v-model="details.unitApprovalUname" readonly /> + </el-form-item> + <el-form-item v-if="details.unitApprovalStartTime && details.unitApprovalStartTime!=null" label="单元审批开始时间"> + <el-input v-model="details.unitApprovalStartTime" readonly /> + </el-form-item> + <el-form-item v-if="details.unitApprovalEndTime && details.unitApprovalEndTime!=null" label="单元审批结束时间"> + <el-input v-model="details.unitApprovalEndTime" readonly /> + </el-form-item> + <el-form-item v-if="details.unitResultDesc && details.unitResultDesc!=null" label="单元审批结果"> + <el-input v-model="details.unitResultDesc" readonly /> + </el-form-item> + <el-form-item v-if="details.statusDesc && details.statusDesc!=null" label="当前状态"> + <el-input v-model="details.statusDesc" readonly /> + </el-form-item> + <el-form-item v-if="details.stepApprovalResultDesc && details.stepApprovalResultDesc!=null" label="审批结果"> + <el-input v-model="details.stepApprovalResultDesc" readonly /> + </el-form-item> + </el-form> + </div> +</template> + +<script lang="ts"> + import { toRefs, reactive, defineComponent, ref, defineAsyncComponent } from 'vue'; + import { storeToRefs } from 'pinia'; + import { initBackEndControlRoutes } from '/@/router/backEnd'; + import {useUserInfo} from "/@/stores/userInfo"; + import { Session } from '/@/utils/storage'; + import { Search } from '@element-plus/icons-vue' + import { ElMessage } from 'element-plus' + import type { FormInstance, FormRules } from 'element-plus' + import { workApplyApi } from '/@/api/specialWorkSystem/workApply'; + + + interface stateType { + form: Object, + workerList: Array<any>, + workTypeList: Array<any>, + workLevelList: Array<any>, + otherWorkList: Array<any> + } + export default defineComponent({ + name: 'space', + components: {}, + props:['details'], + setup() { + const userInfo = useUserInfo() + const { userInfos } = storeToRefs(userInfo); + return { + Search + }; + }, + }); +</script> + +<style scoped lang="scss"> + .home-container { + height: 100%; + overflow: hidden; + position: relative; + .el-row{ + margin-bottom: 20px; + } + .el-row:last-child { + margin-bottom: 0; + } + .el-input{ + width: 100% !important; + } + .el-date-editor::v-deep{ + width: 100%; + } + .el-select{ + width: 100%; + } + .el-cascader{ + width: 100% !important; + } + } +</style> diff --git a/src/views/specialWorkSystem/workTicket/wdsp/components/plateLog.vue b/src/views/specialWorkSystem/workTicket/wdsp/components/plateLog.vue new file mode 100644 index 0000000..f307fc0 --- /dev/null +++ b/src/views/specialWorkSystem/workTicket/wdsp/components/plateLog.vue @@ -0,0 +1,170 @@ +<template> + <div style="height: 100%"> + <el-form :model="details" label-width="150px"> + <el-form-item label="作业申请单号"> + <el-input v-model="details.workPermitNo" readonly /> + </el-form-item> + <el-form-item label="申请人"> + <el-input v-model="details.applyUname" readonly /> + </el-form-item> + <el-form-item label="部门名称"> + <el-input v-model="details.depName" readonly /> + </el-form-item> + <el-form-item label="作业人"> + <el-input v-model="details.operators" readonly type="textarea" /> + </el-form-item> + <el-form-item label="作业类型"> + <el-input v-model="details.workTypeDesc" readonly /> + </el-form-item> + <el-form-item label="作业等级"> + <el-input v-model="details.workLevelDesc" readonly /> + </el-form-item> + <el-form-item label="作业内容"> + <el-input v-model="details.workContent" readonly type="textarea" /> + </el-form-item> + <el-form-item label="作业地址"> + <el-input v-model="details.workLocation" readonly type="textarea" /> + </el-form-item> + <el-form-item label="盲板编号"> + <el-input v-model="details.workDetail.bpCode" readonly type="textarea" /> + </el-form-item> + <el-form-item label="主要介质"> + <el-input v-model="details.workDetail.mainMedia" readonly type="textarea" /> + </el-form-item> + <el-form-item label="温度"> + <el-input v-model="details.workDetail.temperature" readonly type="textarea"><template #append>摄氏度(℃)</template></el-input> + </el-form-item> + <el-form-item label="压力"> + <el-input v-model="details.workDetail.pressure" readonly type="textarea"><template #append>千帕(kPa)</template></el-input> + </el-form-item> + <el-form-item label="盲板材质"> + <el-input v-model="details.workDetail.bpMaterialQuality" readonly type="textarea"/> + </el-form-item> + <el-form-item label="盲板规格"> + <el-input v-model="details.workDetail.bpSpecification" readonly type="textarea"/> + </el-form-item> + <el-form-item label="盲板位置"> + <el-input v-model="details.workDetail.bpLocation" readonly type="textarea"/> + </el-form-item> + <el-form-item label="装盲板时间"> + <el-input v-model="details.workDetail.installBpTime" readonly/> + </el-form-item> + <el-form-item label="拆盲板时间"> + <el-input v-model="details.workDetail.uninstallBpTime" readonly/> + </el-form-item> + <el-form-item label="关联其他作业"> + <el-input v-model="details.workDetail.otherSpecialWork" readonly type="textarea"/> + </el-form-item> + <el-form-item label="盲板位置图"> + <el-image v-for="item in details.workDetail.bpLocationMapPath" :preview-src-list="details.workDetail.bpLocationMapPath" style="width: 150px; height: 150px;margin-right: 50px;margin-bottom: 20px" :src="item" fit="cover" /> + </el-form-item> + <el-form-item label="期望开始时间"> + <el-input v-model="details.expStartTime" readonly /> + </el-form-item> + <el-form-item label="期望结束时间"> + <el-input v-model="details.expEndTime" readonly /> + </el-form-item> + <el-form-item label="申请时间"> + <el-input v-model="details.applyTime" readonly /> + </el-form-item> +<!-- <el-form-item label="当前层级">--> +<!-- <el-input v-model="details.stepId" readonly />--> +<!-- </el-form-item>--> +<!-- <el-form-item label="上一层级">--> +<!-- <el-input v-model="details.preStepId" readonly />--> +<!-- </el-form-item>--> +<!-- <el-form-item label="下一层级">--> +<!-- <el-input v-model="details.nextStepId" readonly />--> +<!-- </el-form-item>--> + <el-form-item label="层级审批类型"> + <el-input v-model="details.stepTypeDesc" readonly /> + </el-form-item> + <el-form-item v-if="details.stepSerial && details.stepSerial!=null" label="层级排序号"> + <el-input v-model="details.stepSerial" readonly /> + </el-form-item> + <el-form-item v-if="details.stepStartApprovalTime && details.stepStartApprovalTime!=null" label="层级预期开始审批时间"> + <el-input v-model="details.stepStartApprovalTime" readonly /> + </el-form-item> + <el-form-item v-if="details.stepFinishApprovalTime && details.stepFinishApprovalTime!=null" label="层级预期结束审批时间"> + <el-input v-model="details.stepFinishApprovalTime" readonly /> + </el-form-item> + <el-form-item label="审批人姓名"> + <el-input v-model="details.unitApprovalUname" readonly /> + </el-form-item> + <el-form-item v-if="details.unitApprovalStartTime && details.unitApprovalStartTime!=null" label="单元审批开始时间"> + <el-input v-model="details.unitApprovalStartTime" readonly /> + </el-form-item> + <el-form-item v-if="details.unitApprovalEndTime && details.unitApprovalEndTime!=null" label="单元审批结束时间"> + <el-input v-model="details.unitApprovalEndTime" readonly /> + </el-form-item> + <el-form-item v-if="details.unitResultDesc && details.unitResultDesc!=null" label="单元审批结果"> + <el-input v-model="details.unitResultDesc" readonly /> + </el-form-item> + <el-form-item v-if="details.statusDesc && details.statusDesc!=null" label="当前状态"> + <el-input v-model="details.statusDesc" readonly /> + </el-form-item> + <el-form-item v-if="details.stepApprovalResultDesc && details.stepApprovalResultDesc!=null" label="审批结果"> + <el-input v-model="details.stepApprovalResultDesc" readonly /> + </el-form-item> + </el-form> + </div> +</template> + +<script lang="ts"> + import { toRefs, reactive, defineComponent, ref, defineAsyncComponent } from 'vue'; + import { storeToRefs } from 'pinia'; + import { initBackEndControlRoutes } from '/@/router/backEnd'; + import {useUserInfo} from "/@/stores/userInfo"; + import { Session } from '/@/utils/storage'; + import { Search } from '@element-plus/icons-vue' + import { ElMessage } from 'element-plus' + import type { FormInstance, FormRules } from 'element-plus' + import { workApplyApi } from '/@/api/specialWorkSystem/workApply'; + + + interface stateType { + form: Object, + workerList: Array<any>, + workTypeList: Array<any>, + workLevelList: Array<any>, + otherWorkList: Array<any> + } + export default defineComponent({ + name: 'space', + components: {}, + props:['details'], + setup() { + const userInfo = useUserInfo() + const { userInfos } = storeToRefs(userInfo); + return { + Search + }; + }, + }); +</script> + +<style scoped lang="scss"> + .home-container { + height: 100%; + overflow: hidden; + position: relative; + .el-row{ + margin-bottom: 20px; + } + .el-row:last-child { + margin-bottom: 0; + } + .el-input{ + width: 100% !important; + } + .el-date-editor::v-deep{ + width: 100%; + } + .el-select{ + width: 100%; + } + .el-cascader{ + width: 100% !important; + } + } +</style> diff --git a/src/views/specialWorkSystem/workTicket/wdsp/components/powerLog.vue b/src/views/specialWorkSystem/workTicket/wdsp/components/powerLog.vue new file mode 100644 index 0000000..f3c893c --- /dev/null +++ b/src/views/specialWorkSystem/workTicket/wdsp/components/powerLog.vue @@ -0,0 +1,149 @@ +<template> + <div style="height: 100%"> + <el-form :model="details" label-width="150px"> + <el-form-item label="作业申请单号"> + <el-input v-model="details.workPermitNo" readonly /> + </el-form-item> + <el-form-item label="申请人"> + <el-input v-model="details.applyUname" readonly /> + </el-form-item> + <el-form-item label="部门名称"> + <el-input v-model="details.depName" readonly /> + </el-form-item> + <el-form-item label="作业人"> + <el-input v-model="details.operators" readonly type="textarea" /> + </el-form-item> + <el-form-item label="作业类型"> + <el-input v-model="details.workTypeDesc" readonly /> + </el-form-item> + <el-form-item label="作业等级"> + <el-input v-model="details.workLevelDesc" readonly /> + </el-form-item> + <el-form-item label="作业内容"> + <el-input v-model="details.workContent" readonly type="textarea" /> + </el-form-item> + <el-form-item label="作业地址"> + <el-input v-model="details.workLocation" readonly type="textarea" /> + </el-form-item> + <el-form-item label="电源接入点"> + <el-input v-model="details.workDetail.powerAccessPoint" readonly type="textarea" /> + </el-form-item> + <el-form-item label="工作电压"> + <el-input v-model="details.workDetail.workingVoltage" readonly type="textarea"><template #append>伏特(v)</template></el-input> + </el-form-item> + <el-form-item label="用电设备及功率"> + <el-input v-model="details.workDetail.equipmentAndPower" readonly type="textarea" /> + </el-form-item> + <el-form-item label="关联其他作业"> + <el-input v-model="details.workDetail.otherSpecialWork" readonly type="textarea"/> + </el-form-item> + <el-form-item label="期望开始时间"> + <el-input v-model="details.expStartTime" readonly /> + </el-form-item> + <el-form-item label="期望结束时间"> + <el-input v-model="details.expEndTime" readonly /> + </el-form-item> + <el-form-item label="申请时间"> + <el-input v-model="details.applyTime" readonly /> + </el-form-item> +<!-- <el-form-item label="当前层级">--> +<!-- <el-input v-model="details.stepId" readonly />--> +<!-- </el-form-item>--> +<!-- <el-form-item label="上一层级">--> +<!-- <el-input v-model="details.preStepId" readonly />--> +<!-- </el-form-item>--> +<!-- <el-form-item label="下一层级">--> +<!-- <el-input v-model="details.nextStepId" readonly />--> +<!-- </el-form-item>--> + <el-form-item label="层级审批类型"> + <el-input v-model="details.stepTypeDesc" readonly /> + </el-form-item> + <el-form-item v-if="details.stepSerial && details.stepSerial!=null" label="层级排序号"> + <el-input v-model="details.stepSerial" readonly /> + </el-form-item> + <el-form-item v-if="details.stepStartApprovalTime && details.stepStartApprovalTime!=null" label="层级预期开始审批时间"> + <el-input v-model="details.stepStartApprovalTime" readonly /> + </el-form-item> + <el-form-item v-if="details.stepFinishApprovalTime && details.stepFinishApprovalTime!=null" label="层级预期结束审批时间"> + <el-input v-model="details.stepFinishApprovalTime" readonly /> + </el-form-item> + <el-form-item label="审批人姓名"> + <el-input v-model="details.unitApprovalUname" readonly /> + </el-form-item> + <el-form-item v-if="details.unitApprovalStartTime && details.unitApprovalStartTime!=null" label="单元审批开始时间"> + <el-input v-model="details.unitApprovalStartTime" readonly /> + </el-form-item> + <el-form-item v-if="details.unitApprovalEndTime && details.unitApprovalEndTime!=null" label="单元审批结束时间"> + <el-input v-model="details.unitApprovalEndTime" readonly /> + </el-form-item> + <el-form-item v-if="details.unitResultDesc && details.unitResultDesc!=null" label="单元审批结果"> + <el-input v-model="details.unitResultDesc" readonly /> + </el-form-item> + <el-form-item v-if="details.statusDesc && details.statusDesc!=null" label="当前状态"> + <el-input v-model="details.statusDesc" readonly /> + </el-form-item> + <el-form-item v-if="details.stepApprovalResultDesc && details.stepApprovalResultDesc!=null" label="审批结果"> + <el-input v-model="details.stepApprovalResultDesc" readonly /> + </el-form-item> + </el-form> + </div> +</template> + +<script lang="ts"> + import { toRefs, reactive, defineComponent, ref, defineAsyncComponent } from 'vue'; + import { storeToRefs } from 'pinia'; + import { initBackEndControlRoutes } from '/@/router/backEnd'; + import {useUserInfo} from "/@/stores/userInfo"; + import { Session } from '/@/utils/storage'; + import { Search } from '@element-plus/icons-vue' + import { ElMessage } from 'element-plus' + import type { FormInstance, FormRules } from 'element-plus' + import { workApplyApi } from '/@/api/specialWorkSystem/workApply'; + + + interface stateType { + form: Object, + workerList: Array<any>, + workTypeList: Array<any>, + workLevelList: Array<any>, + otherWorkList: Array<any> + } + export default defineComponent({ + name: 'space', + components: {}, + props:['details'], + setup() { + const userInfo = useUserInfo() + const { userInfos } = storeToRefs(userInfo); + return { + Search + }; + }, + }); +</script> + +<style scoped lang="scss"> + .home-container { + height: 100%; + overflow: hidden; + position: relative; + .el-row{ + margin-bottom: 20px; + } + .el-row:last-child { + margin-bottom: 0; + } + .el-input{ + width: 100% !important; + } + .el-date-editor::v-deep{ + width: 100%; + } + .el-select{ + width: 100%; + } + .el-cascader{ + width: 100% !important; + } + } +</style> diff --git a/src/views/specialWorkSystem/workTicket/wdsp/components/spaceLog.vue b/src/views/specialWorkSystem/workTicket/wdsp/components/spaceLog.vue new file mode 100644 index 0000000..d9feabc --- /dev/null +++ b/src/views/specialWorkSystem/workTicket/wdsp/components/spaceLog.vue @@ -0,0 +1,149 @@ +<template> + <div style="height: 100%"> + <el-form :model="details" label-width="150px"> + <el-form-item label="作业申请单号"> + <el-input v-model="details.workPermitNo" readonly /> + </el-form-item> + <el-form-item label="申请人"> + <el-input v-model="details.applyUname" readonly /> + </el-form-item> + <el-form-item label="部门名称"> + <el-input v-model="details.depName" readonly /> + </el-form-item> + <el-form-item label="作业人"> + <el-input v-model="details.operators" readonly type="textarea" /> + </el-form-item> + <el-form-item label="作业类型"> + <el-input v-model="details.workTypeDesc" readonly /> + </el-form-item> + <el-form-item label="作业等级"> + <el-input v-model="details.workLevelDesc" readonly /> + </el-form-item> + <el-form-item label="作业内容"> + <el-input v-model="details.workContent" readonly type="textarea" /> + </el-form-item> + <el-form-item label="作业地址"> + <el-input v-model="details.workLocation" readonly type="textarea" /> + </el-form-item> + <el-form-item label="受限空间所属单位"> + <el-input v-model="details.workDetail.csDepId" readonly type="textarea" /> + </el-form-item> + <el-form-item label="受限空间名称"> + <el-input v-model="details.workDetail.csName" readonly type="textarea" /> + </el-form-item> + <el-form-item label="空间原有介质名称"> + <el-input v-model="details.workDetail.csOriginalName" readonly type="textarea" /> + </el-form-item> + <el-form-item label="关联其他作业"> + <el-input v-model="details.workDetail.otherSpecialWork" readonly type="textarea" /> + </el-form-item> + <el-form-item label="期望开始时间"> + <el-input v-model="details.expStartTime" readonly /> + </el-form-item> + <el-form-item label="期望结束时间"> + <el-input v-model="details.expEndTime" readonly /> + </el-form-item> + <el-form-item label="申请时间"> + <el-input v-model="details.applyTime" readonly /> + </el-form-item> +<!-- <el-form-item label="当前层级">--> +<!-- <el-input v-model="details.stepId" readonly />--> +<!-- </el-form-item>--> +<!-- <el-form-item label="上一层级">--> +<!-- <el-input v-model="details.preStepId" readonly />--> +<!-- </el-form-item>--> +<!-- <el-form-item label="下一层级">--> +<!-- <el-input v-model="details.nextStepId" readonly />--> +<!-- </el-form-item>--> + <el-form-item label="层级审批类型"> + <el-input v-model="details.stepTypeDesc" readonly /> + </el-form-item> + <el-form-item v-if="details.stepSerial && details.stepSerial!=null" label="层级排序号"> + <el-input v-model="details.stepSerial" readonly /> + </el-form-item> + <el-form-item v-if="details.stepStartApprovalTime && details.stepStartApprovalTime!=null" label="层级预期开始审批时间"> + <el-input v-model="details.stepStartApprovalTime" readonly /> + </el-form-item> + <el-form-item v-if="details.stepFinishApprovalTime && details.stepFinishApprovalTime!=null" label="层级预期结束审批时间"> + <el-input v-model="details.stepFinishApprovalTime" readonly /> + </el-form-item> + <el-form-item label="审批人姓名"> + <el-input v-model="details.unitApprovalUname" readonly /> + </el-form-item> + <el-form-item v-if="details.unitApprovalStartTime && details.unitApprovalStartTime!=null" label="单元审批开始时间"> + <el-input v-model="details.unitApprovalStartTime" readonly /> + </el-form-item> + <el-form-item v-if="details.unitApprovalEndTime && details.unitApprovalEndTime!=null" label="单元审批结束时间"> + <el-input v-model="details.unitApprovalEndTime" readonly /> + </el-form-item> + <el-form-item v-if="details.unitResultDesc && details.unitResultDesc!=null" label="单元审批结果"> + <el-input v-model="details.unitResultDesc" readonly /> + </el-form-item> + <el-form-item v-if="details.statusDesc && details.statusDesc!=null" label="当前状态"> + <el-input v-model="details.statusDesc" readonly /> + </el-form-item> + <el-form-item v-if="details.stepApprovalResultDesc && details.stepApprovalResultDesc!=null" label="审批结果"> + <el-input v-model="details.stepApprovalResultDesc" readonly /> + </el-form-item> + </el-form> + </div> +</template> + +<script lang="ts"> + import { toRefs, reactive, defineComponent, ref, defineAsyncComponent } from 'vue'; + import { storeToRefs } from 'pinia'; + import { initBackEndControlRoutes } from '/@/router/backEnd'; + import {useUserInfo} from "/@/stores/userInfo"; + import { Session } from '/@/utils/storage'; + import { Search } from '@element-plus/icons-vue' + import { ElMessage } from 'element-plus' + import type { FormInstance, FormRules } from 'element-plus' + import { workApplyApi } from '/@/api/specialWorkSystem/workApply'; + + + interface stateType { + form: Object, + workerList: Array<any>, + workTypeList: Array<any>, + workLevelList: Array<any>, + otherWorkList: Array<any> + } + export default defineComponent({ + name: 'space', + components: {}, + props:['details'], + setup() { + const userInfo = useUserInfo() + const { userInfos } = storeToRefs(userInfo); + return { + Search + }; + }, + }); +</script> + +<style scoped lang="scss"> + .home-container { + height: 100%; + overflow: hidden; + position: relative; + .el-row{ + margin-bottom: 20px; + } + .el-row:last-child { + margin-bottom: 0; + } + .el-input{ + width: 100% !important; + } + .el-date-editor::v-deep{ + width: 100%; + } + .el-select{ + width: 100%; + } + .el-cascader{ + width: 100% !important; + } + } +</style> diff --git a/src/views/specialWorkSystem/workTicket/wdsp/index.vue b/src/views/specialWorkSystem/workTicket/wdsp/index.vue new file mode 100644 index 0000000..84dfa62 --- /dev/null +++ b/src/views/specialWorkSystem/workTicket/wdsp/index.vue @@ -0,0 +1,815 @@ +<template> + <div class="home-container"> +<!-- <el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">--> +<!-- <el-tab-pane label="申请中" name="1">--> + <div style="height: 100%"> + <el-row class="homeCard"> + <span>作业类型:</span> + <el-col :span="10"> + <div class="grid-content topInfo"> + <el-select v-model="searchWord"> + <el-option + v-for="item in workType" + :key="item.id" + :label="item.name" + :value="item.id" + /> + </el-select> + <el-button type="primary" @click="searchRecord">查询</el-button> + <el-button plain @click="clearSearch">重置</el-button> + </div> + </el-col> + </el-row> + <div class="homeCard"> + <div class="main-card"> + <el-row class="cardTop"> + <el-col :span="12" class="mainCardBtn"> + <el-button type="primary" :icon="Plus" size="default" @click="toApply()">申请</el-button> + <!-- <el-button type="danger" :icon="Delete" size="default">删除</el-button>--> + <!-- <el-button type="success" size="default">设置分类</el-button>--> + </el-col> + <el-button type="primary" :icon="Refresh" size="default" @click="reLoadData()" /> + </el-row> + <el-table ref="multipleTableRef" :data="applyData" style="width: 100%" height="calc(100% - 100px)" :header-cell-style="{ background: '#fafafa' }"> + <el-table-column property="applyUname" label="申请人" /> + <el-table-column property="depName" label="部门名称" /> + <el-table-column property="operators" label="作业人" /> + <el-table-column property="workTypeDesc" label="作业类型" /> + <el-table-column property="workLevelDesc" label="作业等级" /> + <el-table-column property="applyTime" label="申请时间" width="180" /> + <el-table-column label="审批状态" align="center" width="180"> + <template #default="scope"> + <el-tag :type="scope.row.status==2?'success':(scope.row.status==8||scope.row.status==9)?'warning':'danger'">{{ scope.row.statusDesc }}</el-tag> + </template> + </el-table-column> + <el-table-column fixed="right" label="操作" align="center" width="250"> + <template #default="scope"> + <el-button link type="primary" size="small" :icon="View" @click="viewRecord(scope.row)">查看</el-button> + <el-button link type="success" size="small" :icon="Finished" @click="viewStatus(scope.row)">进度</el-button> +<!-- <el-button link type="warning" size="small" :icon="Delete" @click="deleteRecordBtn(scope.row)">终止</el-button>--> + </template> + </el-table-column> + </el-table> + <div class="pageBtn"> + <el-pagination v-model:currentPage="pageIndex1" v-model:page-size="pageSize1" :page-sizes="[10, 15]" small="false" background layout="total, sizes, prev, pager, next, jumper" :total="totalSize1" @size-change="handleSizeChange1" @current-change="handleCurrentChange1" /> + </div> + </div> + </div> + </div> + <el-dialog v-model="dialogDetails" title="作业审批详情" center> + <fire v-if="dialogType == 1" :details = details></fire> + <space v-else-if="dialogType == 2" :details = details></space> + <hoist v-else-if="dialogType == 3" :details = details></hoist> + <ground v-else-if="dialogType == 4" :details = details></ground> + <broken v-else-if="dialogType == 5" :details = details></broken> + <height v-else-if="dialogType == 6" :details = details></height> + <power v-else-if="dialogType == 7" :details = details></power> + <plate v-else :details = details></plate> + <template #footer> + <span class="dialog-footer"> + <el-button type="primary" @click="dialogDetails = false" + >确认</el-button + > + </span> + </template> + </el-dialog> + <el-dialog v-model="dialogStatus" title="作业审批进度" center width="60%"> + <el-form v-if="approveInfo.operators.length > 0" style="margin-bottom: 40px"> + <el-form-item label="申请作业人"> + <el-input v-model="approveInfo.operators" readonly type="textarea" /> + </el-form-item> + </el-form> + <div style="display: flex; flex-direction: column-reverse"> + <div v-for="(item, index) in approveInfo.approvalSteps" class="stepItem"> + <div class="stepNum">{{ item.stepSerial }}</div> + <div class="stepCard"> + <el-card class="box-card" shadow="always"> + <div class="text"> + 审批结果:<span class="bold-text">{{ item.approvalResultDesc }}</span> + </div> + <div class="text"> + 审批层级:<span class="bold-text">{{ item.typeDesc }}</span> + </div> + <div class="text" v-if="item.auditTypeDesc"> + 审批类型:<span class="bold-text">{{ item.auditTypeDesc }}</span> + </div> + <div class="text" v-show="item.startApprovalTime != null"> + 开始时间:<span>{{ item.startApprovalTime }}</span> + </div> + <div class="approveUnit"> + <div class="item-tit"><span>审批人</span><span>审批状态</span></div> + <div class="item-cont" v-for="i in item.stepUnits"> + <span>{{ i.approvalUname }}</span + ><span>{{ i.resultDesc }}</span> + </div> + </div> + <div class="approveItem"> + <div class="item-tit"> + <span>审批项目</span> +<!-- <span>类型</span>--> + <div>措施标准</div> + </div> + <div class="item-cont" v-for="i in item.stepItems"> + <span>{{ i.itemName }}</span> +<!-- <span>{{ i.typeDesc }}</span>--> + <div v-if="i.measure !== null"> + <div> + <span>作业类型:</span><span>{{ i.measure.workTypeDesc }}</span> + </div> + <div> + <span>措施内容:</span><span>{{ i.measure.context }}</span> + </div> + </div> + <div v-if="i.stand !== null"> + <div> + <span>标题名称:</span><span>{{ i.stand.title }}</span> + </div> + <div> + <span>标准内容:</span><span>{{ i.stand.typeDesc }}</span> + </div> + </div> + </div> + </div> + <div class="text" v-show="item.expFinishApprovalTime != null"> + 期望结束时间:<span>{{ item.expFinishApprovalTime }}</span> + </div> + <div class="text" v-show="item.finishApprovalTime != null"> + 结束时间:<span>{{ item.finishApprovalTime }}</span> + </div> + </el-card> + </div> + </div> + </div> + </el-dialog> + <el-dialog v-model="deleteDialog" title="提示" width="30%" center @close="indexClear"> + <span>您确定要终止该条审批吗?</span> + <template #footer> + <span class="dialog-footer"> + <el-button @click="deleteDialog = false" size="default">取消</el-button> + <el-button type="primary" @click="conFirmDelete" size="default">确认</el-button> + </span> + </template> + </el-dialog> +<!-- </el-tab-pane>--> +<!-- <el-tab-pane label="已通过" name="2">--> +<!-- <div style="height: 100%">--> +<!-- <el-row class="homeCard">--> +<!-- <el-col :span="8">--> +<!-- <div class="grid-content topInfo">--> +<!-- <el-input v-model="searchWord" placeholder="作业证名称"></el-input>--> +<!-- <el-button type="primary">查询</el-button>--> +<!-- <el-button plain>重置</el-button>--> +<!-- </div>--> +<!-- </el-col>--> +<!-- </el-row>--> +<!-- <div class="homeCard">--> +<!-- <div class="main-card">--> +<!-- <el-table ref="multipleTableRef" :data="passedData" style="width: 100%" height="calc(100% - 48px)" :header-cell-style="{ background: '#fafafa' }" @selection-change="handleSelectionChange">--> +<!-- <el-table-column type="selection" width="55" />--> +<!-- <el-table-column type="index" label="编号" width="200" />--> +<!-- <el-table-column property="level" label="作业证等级" width="180" sortable />--> +<!-- <el-table-column property="applyDate" label="申请日期" sortable />--> +<!-- <el-table-column property="name" label="申请人" width="180" />--> +<!-- <el-table-column property="department" label="申请部门" width="180" />--> +<!-- <el-table-column label="申请状态" width="180">--> +<!-- <template #default="scope">--> +<!-- <el-tag type="success">{{ scope.row.status }}</el-tag>--> +<!-- </template>--> +<!-- </el-table-column>--> +<!-- </el-table>--> +<!-- <div class="pageBtn">--> +<!-- <el-pagination v-model:currentPage="pageIndex2" v-model:page-size="pageSize2" :page-sizes="[10, 15]" small="false" background layout="total, sizes, prev, pager, next, jumper" :total="totalSize2" @size-change="handleSizeChange2" @current-change="handleCurrentChange2" />--> +<!-- </div>--> +<!-- </div>--> +<!-- </div>--> +<!-- </div>--> +<!-- </el-tab-pane>--> +<!-- </el-tabs>--> + </div> +</template> + +<script lang="ts"> +import {toRefs, reactive, defineComponent, ref, onMounted, defineAsyncComponent} from 'vue'; +import { storeToRefs } from 'pinia'; +import { initBackEndControlRoutes } from '/@/router/backEnd'; +import { useUserInfo } from '/@/stores/userInfo'; +import { Session } from '/@/utils/storage'; +import { useRouter } from 'vue-router'; +import { Edit, View, Plus, Delete, Refresh, Search, Finished } from '@element-plus/icons-vue'; +import { ElTable } from 'element-plus'; +import { FormInstance, FormRules, ElMessage } from 'element-plus'; +import { workApprovalApi } from '/@/api/specialWorkSystem/workApproval'; +import type { TabsPaneContext } from 'element-plus'; +import {teamManageApi} from "/@/api/systemManage/basicDateManage/personShiftManage/teamManage"; + +// 定义接口来定义对象的类型 +interface stateType { + applyData: Array<string>; + workTimeList: Array<string>; + multipleSelection: Array<any>; + deleteArr: Array<any>; + approveInfo: Object; + dialogDetails: boolean; + dialogStatus: boolean; + deleteDialog: boolean; + pageIndex1: number; + pageSize1: number; + chosenIndex: null | number; + deleteId: null | number; + searchWord: string; + totalSize1: number; + activeName: string; + addRecord: {}; + details: {}; + statusInfo: {}; + workType: Array<type>; + dialogType: number | null; + departmentList: Array<any>; + departmentRecursionList: Array<DepartmentState>; +} +interface type { + id: number; + name: string; +} +interface DepartmentState { + depId: number; + depName: string; +} +export default defineComponent({ + name: 'myApproval', + components: { + fire: defineAsyncComponent(() => import('/@/views/specialWorkSystem/workTicket/wdsp/components/fireLog.vue')), + space: defineAsyncComponent(() => import('/@/views/specialWorkSystem/workTicket/wdsp/components/spaceLog.vue')), + hoist: defineAsyncComponent(() => import('/@/views/specialWorkSystem/workTicket/wdsp/components/hoistLog.vue')), + ground: defineAsyncComponent(() => import('/@/views/specialWorkSystem/workTicket/wdsp/components/groundLog.vue')), + broken: defineAsyncComponent(() => import('/@/views/specialWorkSystem/workTicket/wdsp/components/brokenLog.vue')), + height: defineAsyncComponent(() => import('/@/views/specialWorkSystem/workTicket/wdsp/components/heightLog.vue')), + power: defineAsyncComponent(() => import('/@/views/specialWorkSystem/workTicket/wdsp/components/powerLog.vue')), + plate: defineAsyncComponent(() => import('/@/views/specialWorkSystem/workTicket/wdsp/components/plateLog.vue')) + }, + setup() { + const userInfo = useUserInfo(); + const { userInfos } = storeToRefs(userInfo); + const router = useRouter(); + const state = reactive<stateType>({ + pageIndex1: 1, + pageSize1: 10, + totalSize1: 0, + dialogType: null, + activeName: '1', + departmentList: [], + departmentRecursionList: [], + chosenIndex: null, + searchWord: '', + applyData: [], + workTimeList: [], + multipleSelection: [], + approveInfo: { + approvalSteps: [], + operators: [] + }, + dialogDetails: false, + dialogStatus: false, + deleteDialog: false, + addRecord: {}, + details: {}, + statusInfo: {}, + deleteId: null, + deleteArr: [], + workType: [ + { id: 1, name: '动火作业' }, + { id: 2, name: '受限空间作业' }, + { id: 3, name: '吊装作业' }, + { id: 4, name: '动土作业' }, + { id: 5, name: '断路作业' }, + { id: 6, name: '高处作业' }, + { id: 7, name: '临时用电作业' }, + { id: 8, name: '盲板抽堵作业' } + ] + }); + interface User { + name: string; + list: []; + info: string; + } + + // 刷新 + const reLoadData = async () => { + getListByPage(); + }; + + // 填写表单 + const toApply = () => { + router.push({ + path: 'zysq' + }); + }; + + const handleClick = (tab: TabsPaneContext, event: Event) => { + console.log(tab, event); + }; + + // 获取部门列表 + const getAllDepartment = async () => { + let res = await teamManageApi().getAllDepartment(); + if (res.data.code === '200') { + state.departmentList = JSON.parse(JSON.stringify(res.data.data)) + recursion(state.departmentList); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 获取层级审批数据 + // const getApprovalData = async (id) => { + // let res = await workApprovalApi().getApprovalData({workApplyId: id}); + // if (res.data.code === '200') { + // console.log(res.data.data,'层级数据') + // // state.departmentList = JSON.parse(JSON.stringify(res.data.data)) + // // recursion(state.departmentList); + // } else { + // ElMessage({ + // type: 'warning', + // message: res.data.msg + // }); + // } + // }; + + const recursion = (value: any) => { + for (let i of value) { + if (i.children.length !== 0) { + state.departmentRecursionList.push(i); + recursion(i.children); + } else { + state.departmentRecursionList.push(i); + } + } + }; + + // 分页获取工作时间组列表 + const getListByPage = async () => { + const data = { pageSize: state.pageSize1, pageIndex: state.pageIndex1, searchParams: { workType: state.searchWord } }; + let res = await workApprovalApi().getApprovalListPage(data); + if (res.data.code === '200') { + state.applyData = JSON.parse(JSON.stringify(res.data.data)); + state.applyData = state.applyData.map((item) => { + if (item.operators == null || item.operators == []) { + item.operators = []; + } else { + item.operators = Array.from(item.operators, ({ operatorUname }) => operatorUname); + } + return item; + }); + state.totalSize1 = res.data.total; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 关键词查询记录 + const searchRecord = async () => { + if (state.searchWord == '') { + ElMessage({ + type: 'warning', + message: '请输入查询关键词' + }); + } else { + getListByPage(); + } + }; + // 重置搜索 + const clearSearch = async () => { + state.searchWord = ''; + getListByPage(); + }; + + // 查看进度 + const viewStatus = (row) => { + getStatus({ workApplyId: row.workApplyId }); + state.dialogStatus = true; + }; + + // 查询进度方法 + const getStatus = async (data: any) => { + let res = await workApprovalApi().getApprovalStatus(data); + if (res.data.code === '200') { + state.approveInfo = JSON.parse(JSON.stringify(res.data.data)); + state.approveInfo.operators = Array.from(state.approveInfo.operators, ({ operatorUname }) => operatorUname); + console.log(state.approveInfo, '我的审批'); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + const deleteRecordBtn = (row) => { + state.deleteId = row.workApplyId; + state.deleteDialog = true; + }; + + // 取消申请方法 + const deleteRecord = async (data: any) => { + let res = await workApprovalApi().postAbord(data); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '取消成功!' + }); + getListByPage(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + const conFirmDelete = () => { + deleteRecord({ workApplyId: state.deleteId }); + state.deleteDialog = false; + }; + + const handleSizeChange1 = (val: number) => { + state.pageSize1 = val; + getListByPage(); + }; + const handleCurrentChange1 = (val: number) => { + state.pageIndex1 = val; + getListByPage(); + }; + + // 查看记录 + const viewRecord = (row: any) => { + state.dialogType = row.workType + state.details = JSON.parse(JSON.stringify(row)); + console.log(state.details,'details') + // getApprovalData(state.details.workApplyId) + if(state.details.workDetail.otherSpecialWork == '' || !state.details.workDetail.otherSpecialWork){ + state.details.workDetail.otherSpecialWork=[] + } + else { + console.log(state.details.workDetail.otherSpecialWork,'split') + const a = state.details.workDetail.otherSpecialWork + state.details.workDetail.otherSpecialWork = a.split(',').map((item) => { + return state.workType.find((i: { id: number }) => i.id === Number(item))?.name; + }); + } + if(state.details.workDetail.involvedDepIds == '' || !state.details.workDetail.involvedDepIds){ + state.details.workDetail.involvedDepIds=[] + } + else { + const a = state.details.workDetail.involvedDepIds + state.details.workDetail.involvedDepIds = a.split(',').map((item) => { + return state.departmentRecursionList.find((i: { depId: number }) => i.depId === Number(item))?.depName; + }); + } + if(state.details.workDetail.csDepId){ + state.details.workDetail.csDepId = state.departmentRecursionList.find((i: { depId: number }) => i.depId === Number(state.details.workDetail.csDepId))?.depName; + } + if(state.details.workDetail.operationDepId){ + state.details.workDetail.operationDepId = state.departmentRecursionList.find((i: { depId: number }) => i.depId === Number(state.details.workDetail.operationDepId))?.depName; + } + if(state.details.workDetail.gbPath){ + state.details.workDetail.gbPath = state.details.workDetail.gbPath.split(',') + } + if(state.details.workDetail.bcPath){ + state.details.workDetail.bcPath = state.details.workDetail.bcPath.split(',') + } + if(state.details.workDetail.bpLocationMapPath){ + state.details.workDetail.bpLocationMapPath = state.details.workDetail.bpLocationMapPath.split(',') + } + state.dialogDetails = true; + }; + + // 折线图 + const renderMenu = async (value: string) => { + Session.set('projectId', value); + userInfos.value.projectId = value; + await initBackEndControlRoutes(); + }; + + // 页面载入时执行方法 + onMounted(() => { + getListByPage(); + getAllDepartment() + }); + + return { + View, + Edit, + Delete, + Refresh, + Plus, + Finished, + reLoadData, + toApply, + handleClick, + searchRecord, + clearSearch, + viewRecord, + viewStatus, + deleteRecordBtn, + conFirmDelete, + getListByPage, + handleSizeChange1, + handleCurrentChange1, + ...toRefs(state) + }; + } +}); +</script> + +<style scoped lang="scss"> +$homeNavLengh: 8; +.home-container { + height: calc(100vh - 144px); + box-sizing: border-box; + overflow: hidden; + .demo-tabs { + width: 100%; + height: 100%; + + &::v-deep(.el-tabs__content) { + height: calc(100% - 60px); + } + + .el-tab-pane { + height: 100%; + } + } + .homeCard { + width: 100%; + padding: 20px; + box-sizing: border-box; + background: #fff; + border-radius: 4px; + + .main-card { + width: 100%; + height: 100%; + .cardTop { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 20px; + .mainCardBtn { + margin: 0; + } + } + .pageBtn { + height: 60px; + display: flex; + align-items: center; + justify-content: right; + + .demo-pagination-block + .demo-pagination-block { + margin-top: 10px; + } + .demo-pagination-block .demonstration { + margin-bottom: 16px; + } + } + } + &:last-of-type { + height: calc(100% - 100px); + } + } + .stepItem { + display: flex; + align-items: flex-start; + margin-top: 30px; + margin-left: 30px; + padding-bottom: 30px; + padding-left: 40px; + border-left: 1px solid #a0cfff; + position: relative; + &:first-of-type { + margin-top: 30px; + } + &:first-of-type { + margin-bottom: 0; + border-left: none; + } + .stepNum { + position: absolute; + width: 40px; + height: 40px; + border-radius: 20px; + box-sizing: border-box; + font-size: 18px; + color: #333; + border: 1px solid #a0cfff; + line-height: 38px; + text-align: center; + left: -20px; + top: -30px; + background: #d9ecff; + } + .stepCard { + width: 100%; + margin-top: -30px; + + .box-card { + width: 100%; + + .card-header { + display: flex; + justify-content: space-between; + align-items: center; + + span { + font-weight: bold; + margin-left: 10px; + } + } + + .text { + width: 100%; + font-size: 14px; + margin-bottom: 10px; + padding-left: 10px; + + span { + color: #409eff; + } + + .bold-text{ + font-weight: bolder; + } + + &:last-of-type { + margin-bottom: 0; + } + } + .approveUnit { + width: 100%; + font-size: 14px; + margin-bottom: 20px; + padding: 10px 15px; + border: 1px solid #fff; + background: #ecf8ff; + border-radius: 6px; + .item-tit { + width: 100%; + display: flex; + color: #409eff; + align-items: flex-start; + justify-content: space-between; + padding-bottom: 10px; + border-bottom: 1px solid #a0cfff; + + & > span { + flex: 1; + &:last-of-type{ + text-align: center; + } + } + & > div { + flex: 1; + text-align: center; + } + } + .item-cont { + width: 100%; + display: flex; + align-items: center; + justify-content: space-between; + padding: 10px 0; + border-bottom: 1px solid #c6e2ff; + + & > span { + flex: 1; + &:last-of-type{ + text-align: center; + } + } + & > div { + flex: 1; + text-align: center; + + & > div { + text-align: left; + width: 100%; + display: flex; + justify-content: center; + align-items: center; + span { + width: 45%; + &:first-of-type { + width: 30%; + } + } + } + } + &:last-of-type { + border-bottom: 0; + } + } + } + .approveItem { + width: 100%; + font-size: 14px; + margin-bottom: 20px; + padding: 10px 15px; + background: #ecf8ff; + border: 1px solid #fff; + border-radius: 6px; + .item-tit { + width: 100%; + display: flex; + color: #409eff; + align-items: flex-start; + justify-content: space-between; + padding-bottom: 10px; + border-bottom: 1px solid #a0cfff; + + & > span { + flex: 1; + } + & > div { + flex: 2; + text-align: center; + } + } + .item-cont { + width: 100%; + display: flex; + align-items: center; + justify-content: space-between; + padding: 10px 0; + border-bottom: 1px solid #c6e2ff; + + & > span { + flex: 1; + } + & > div { + flex: 2; + text-align: center; + + & > div { + text-align: left; + width: 100%; + display: flex; + justify-content: center; + align-items: flex-start; + margin-bottom: 10px; + span { + width: 50%; + &:first-of-type { + width: 25%; + } + } + } + } + &:last-of-type { + border-bottom: 0; + } + } + } + } + } + &:hover .card-header { + color: #0098f5; + } + &:hover .stepNum { + border: 2px solid #0098f5; + color: #0098f5; + } + } + .el-row { + display: flex; + align-items: center; + margin-bottom: 20px; + &:last-child { + margin-bottom: 0; + } + .grid-content { + align-items: center; + min-height: 36px; + } + + .topInfo { + display: flex; + align-items: center; + font-size: 16px; + font-weight: bold; + + & > div { + white-space: nowrap; + margin-right: 20px; + } + } + } + .el-card { + border: 0; + } +} +</style> diff --git a/src/views/specialWorkSystem/workTicket/wdsq/components/brokenLog.vue b/src/views/specialWorkSystem/workTicket/wdsq/components/brokenLog.vue new file mode 100644 index 0000000..b32213d --- /dev/null +++ b/src/views/specialWorkSystem/workTicket/wdsq/components/brokenLog.vue @@ -0,0 +1,131 @@ +<template> + <div style="height: 100%"> + <el-form :model="details" label-width="150px"> + <el-form-item label="作业申请单号"> + <el-input v-model="details.workPermitNo" readonly /> + </el-form-item> + <el-form-item label="申请人"> + <el-input v-model="details.applyUname" readonly /> + </el-form-item> + <el-form-item label="部门名称"> + <el-input v-model="details.depName" readonly /> + </el-form-item> + <el-form-item label="作业人"> + <el-input v-model="details.operators" readonly type="textarea" /> + </el-form-item> + <el-form-item label="作业类型"> + <el-input v-model="details.workTypeDesc" readonly /> + </el-form-item> + <el-form-item label="作业等级"> + <el-input v-model="details.workLevelDesc" readonly /> + </el-form-item> + <el-form-item label="作业内容"> + <el-input v-model="details.workContent" readonly type="textarea" /> + </el-form-item> + <el-form-item label="作业地址"> + <el-input v-model="details.workLocation" readonly type="textarea" /> + </el-form-item> + <el-form-item label="作业单位"> + <el-input v-model="details.workDetail.operationDepId" readonly type="textarea" /> + </el-form-item> + <el-form-item label="断路原因"> + <el-input v-model="details.workDetail.bcReason" readonly type="textarea" /> + </el-form-item> + <el-form-item label="断路地段说明"> + <el-input v-model="details.workDetail.bcExplain" readonly type="textarea" /> + </el-form-item> + <el-form-item label="涉及相关部门"> + <el-input v-model="details.workDetail.involvedDepIds" readonly type="textarea"/> + </el-form-item> + <el-form-item label="图片"> + <el-image v-for="item in details.workDetail.bcPath" :preview-src-list="details.workDetail.bcPath" style="width: 150px; height: 150px;margin-right: 50px;margin-bottom: 20px" :src="item" fit="cover" /> + </el-form-item> + <el-form-item label="物资状态"> + <span>{{ details.materialStatus==0?'未关联物资':(details.materialStatus==1?'必选物资配备不足':(details.materialStatus==2?'必选物资配备齐全':(details.materialStatus==3?'物资配置专业':(details.materialStatus==4?'物资配置高端':'-')))) }}</span> + </el-form-item> + <el-form-item label="关联物资" v-if="details.workMaterial.length>0"> + <el-table :data="details.workMaterial" style="width: 100%" border> + <el-table-column prop="bigClassifyName" label="物资类型" align="center"/> + <el-table-column prop="materialName" label="物资名称" align="center"/> + <el-table-column prop="configurationLevel" label="配置级别" align="center"> + <template #default="scope"> + {{scope.row.configurationLevel == 0?'必选':(scope.row.configurationLevel == 1? '可选':'高配')}} + </template> + </el-table-column> + <el-table-column prop="useCount" label="配置数量" align="center"/> + </el-table> + </el-form-item> + <el-form-item label="期望开始时间"> + <el-input v-model="details.expStartTime" readonly /> + </el-form-item> + <el-form-item label="期望结束时间"> + <el-input v-model="details.expEndTime" readonly /> + </el-form-item> + <el-form-item label="申请时间"> + <el-input v-model="details.applyTime" readonly /> + </el-form-item> + <el-form-item label="当前状态"> + <el-input v-model="details.statusDesc" readonly /> + </el-form-item> + </el-form> + </div> +</template> + +<script lang="ts"> + import { toRefs, reactive, defineComponent, ref, defineAsyncComponent } from 'vue'; + import { storeToRefs } from 'pinia'; + import { initBackEndControlRoutes } from '/@/router/backEnd'; + import {useUserInfo} from "/@/stores/userInfo"; + import { Session } from '/@/utils/storage'; + import { Search } from '@element-plus/icons-vue' + import { ElMessage } from 'element-plus' + import type { FormInstance, FormRules } from 'element-plus' + import { workApplyApi } from '/@/api/specialWorkSystem/workApply'; + + + interface stateType { + form: Object, + workerList: Array<any>, + workTypeList: Array<any>, + workLevelList: Array<any>, + otherWorkList: Array<any> + } + export default defineComponent({ + name: 'space', + components: {}, + props:['details'], + setup() { + const userInfo = useUserInfo() + const { userInfos } = storeToRefs(userInfo); + return { + Search + }; + }, + }); +</script> + +<style scoped lang="scss"> + .home-container { + height: 100%; + overflow: hidden; + position: relative; + .el-row{ + margin-bottom: 20px; + } + .el-row:last-child { + margin-bottom: 0; + } + .el-input{ + width: 100% !important; + } + .el-date-editor::v-deep{ + width: 100%; + } + .el-select{ + width: 100%; + } + .el-cascader{ + width: 100% !important; + } + } +</style> diff --git a/src/views/specialWorkSystem/workTicket/wdsq/components/fireLog.vue b/src/views/specialWorkSystem/workTicket/wdsq/components/fireLog.vue new file mode 100644 index 0000000..6386a7e --- /dev/null +++ b/src/views/specialWorkSystem/workTicket/wdsq/components/fireLog.vue @@ -0,0 +1,122 @@ +<template> + <div style="height: 100%"> + <el-form :model="details" label-width="150px"> + <el-form-item label="作业申请单号"> + <el-input v-model="details.workPermitNo" readonly /> + </el-form-item> + <el-form-item label="申请人"> + <el-input v-model="details.applyUname" readonly /> + </el-form-item> + <el-form-item label="部门名称"> + <el-input v-model="details.depName" readonly /> + </el-form-item> + <el-form-item label="作业人"> + <el-input v-model="details.operators" readonly type="textarea" /> + </el-form-item> + <el-form-item label="作业类型"> + <el-input v-model="details.workTypeDesc" readonly /> + </el-form-item> + <el-form-item label="作业等级"> + <el-input v-model="details.workLevelDesc" readonly /> + </el-form-item> + <el-form-item label="作业内容"> + <el-input v-model="details.workContent" readonly type="textarea" /> + </el-form-item> + <el-form-item label="作业地址"> + <el-input v-model="details.workLocation" readonly type="textarea" /> + </el-form-item> + <el-form-item label="作业方式"> + <el-input v-model="details.workDetail.hotMethod" readonly type="textarea" /> + </el-form-item> + <el-form-item label="物资状态"> + <span>{{ details.materialStatus==0?'未关联物资':(details.materialStatus==1?'必选物资配备不足':(details.materialStatus==2?'必选物资配备齐全':(details.materialStatus==3?'物资配置专业':(details.materialStatus==4?'物资配置高端':'-')))) }}</span> + </el-form-item> + <el-form-item label="关联物资" v-if="details.workMaterial&&details.workMaterial.length>0"> + <el-table :data="details.workMaterial" style="width: 100%" border> + <el-table-column prop="bigClassifyName" label="物资类型" align="center"/> + <el-table-column prop="materialName" label="物资名称" align="center"/> + <el-table-column prop="configurationLevel" label="配置级别" align="center"> + <template #default="scope"> + {{scope.row.configurationLevel == 0?'必选':(scope.row.configurationLevel == 1? '可选':'高配')}} + </template> + </el-table-column> + <el-table-column prop="useCount" label="配置数量" align="center"/> + </el-table> + </el-form-item> + <el-form-item label="关联其他作业"> + <el-input v-model="details.workDetail.otherSpecialWork" readonly type="textarea" /> + </el-form-item> + <el-form-item label="期望开始时间"> + <el-input v-model="details.expStartTime" readonly /> + </el-form-item> + <el-form-item label="期望结束时间"> + <el-input v-model="details.expEndTime" readonly /> + </el-form-item> + <el-form-item label="申请时间"> + <el-input v-model="details.applyTime" readonly /> + </el-form-item> + <el-form-item label="当前状态"> + <el-input v-model="details.statusDesc" readonly /> + </el-form-item> + </el-form> + </div> +</template> + +<script lang="ts"> + import { toRefs, reactive, defineComponent, ref, defineAsyncComponent } from 'vue'; + import { storeToRefs } from 'pinia'; + import { initBackEndControlRoutes } from '/@/router/backEnd'; + import {useUserInfo} from "/@/stores/userInfo"; + import { Session } from '/@/utils/storage'; + import { Search } from '@element-plus/icons-vue' + import { ElMessage } from 'element-plus' + import type { FormInstance, FormRules } from 'element-plus' + import { workApplyApi } from '/@/api/specialWorkSystem/workApply'; + + + interface stateType { + form: Object, + workerList: Array<any>, + workTypeList: Array<any>, + workLevelList: Array<any>, + otherWorkList: Array<any> + } + export default defineComponent({ + name: 'fire', + components: {}, + props:['details'], + setup() { + const userInfo = useUserInfo() + const { userInfos } = storeToRefs(userInfo); + return { + Search + }; + }, + }); +</script> + +<style scoped lang="scss"> + .home-container { + height: 100%; + overflow: hidden; + position: relative; + .el-row{ + margin-bottom: 20px; + } + .el-row:last-child { + margin-bottom: 0; + } + .el-input{ + width: 100% !important; + } + .el-date-editor::v-deep{ + width: 100%; + } + .el-select{ + width: 100%; + } + .el-cascader{ + width: 100% !important; + } + } +</style> diff --git a/src/views/specialWorkSystem/workTicket/wdsq/components/groundLog.vue b/src/views/specialWorkSystem/workTicket/wdsq/components/groundLog.vue new file mode 100644 index 0000000..ed728d7 --- /dev/null +++ b/src/views/specialWorkSystem/workTicket/wdsq/components/groundLog.vue @@ -0,0 +1,131 @@ +<template> + <div style="height: 100%"> + <el-form :model="details" label-width="150px"> + <el-form-item label="作业申请单号"> + <el-input v-model="details.workPermitNo" readonly /> + </el-form-item> + <el-form-item label="申请人"> + <el-input v-model="details.applyUname" readonly /> + </el-form-item> + <el-form-item label="部门名称"> + <el-input v-model="details.depName" readonly /> + </el-form-item> + <el-form-item label="作业人"> + <el-input v-model="details.operators" readonly type="textarea" /> + </el-form-item> + <el-form-item label="作业类型"> + <el-input v-model="details.workTypeDesc" readonly /> + </el-form-item> + <el-form-item label="作业等级"> + <el-input v-model="details.workLevelDesc" readonly /> + </el-form-item> + <el-form-item label="作业内容"> + <el-input v-model="details.workContent" readonly type="textarea" /> + </el-form-item> + <el-form-item label="作业地址"> + <el-input v-model="details.workLocation" readonly type="textarea" /> + </el-form-item> + <el-form-item label="作业单位"> + <el-input v-model="details.workDetail.operationDepId" readonly type="textarea" /> + </el-form-item> + <el-form-item label="范围"> + <el-input v-model="details.workDetail.gbScope" readonly type="textarea" /> + </el-form-item> + <el-form-item label="动土方式"> + <el-input v-model="details.workDetail.gbMethod" readonly type="textarea" /> + </el-form-item> + <el-form-item label="物资状态"> + <span>{{ details.materialStatus==0?'未关联物资':(details.materialStatus==1?'必选物资配备不足':(details.materialStatus==2?'必选物资配备齐全':(details.materialStatus==3?'物资配置专业':(details.materialStatus==4?'物资配置高端':'-')))) }}</span> + </el-form-item> + <el-form-item label="关联物资" v-if="details.workMaterial&&details.workMaterial.length>0"> + <el-table :data="details.workMaterial" style="width: 100%" border> + <el-table-column prop="bigClassifyName" label="物资类型" align="center"/> + <el-table-column prop="materialName" label="物资名称" align="center"/> + <el-table-column prop="configurationLevel" label="配置级别" align="center"> + <template #default="scope"> + {{scope.row.configurationLevel == 0?'必选':(scope.row.configurationLevel == 1? '可选':'高配')}} + </template> + </el-table-column> + <el-table-column prop="useCount" label="配置数量" align="center"/> + </el-table> + </el-form-item> + <el-form-item label="关联其他作业"> + <el-input v-model="details.workDetail.otherSpecialWork" readonly type="textarea"/> + </el-form-item> + <el-form-item label="图片"> + <el-image v-for="item in details.workDetail.gbPath" :preview-src-list="details.workDetail.gbPath" style="width: 150px; height: 150px;margin-right: 50px;margin-bottom: 20px" :src="item" fit="cover" /> + </el-form-item> + <el-form-item label="期望开始时间"> + <el-input v-model="details.expStartTime" readonly /> + </el-form-item> + <el-form-item label="期望结束时间"> + <el-input v-model="details.expEndTime" readonly /> + </el-form-item> + <el-form-item label="申请时间"> + <el-input v-model="details.applyTime" readonly /> + </el-form-item> + <el-form-item label="当前状态"> + <el-input v-model="details.statusDesc" readonly /> + </el-form-item> + </el-form> + </div> +</template> + +<script lang="ts"> + import { toRefs, reactive, defineComponent, ref, defineAsyncComponent } from 'vue'; + import { storeToRefs } from 'pinia'; + import { initBackEndControlRoutes } from '/@/router/backEnd'; + import {useUserInfo} from "/@/stores/userInfo"; + import { Session } from '/@/utils/storage'; + import { Search } from '@element-plus/icons-vue' + import { ElMessage } from 'element-plus' + import type { FormInstance, FormRules } from 'element-plus' + import { workApplyApi } from '/@/api/specialWorkSystem/workApply'; + + + interface stateType { + form: Object, + workerList: Array<any>, + workTypeList: Array<any>, + workLevelList: Array<any>, + otherWorkList: Array<any> + } + export default defineComponent({ + name: 'space', + components: {}, + props:['details'], + setup() { + const userInfo = useUserInfo() + const { userInfos } = storeToRefs(userInfo); + return { + Search + }; + }, + }); +</script> + +<style scoped lang="scss"> + .home-container { + height: 100%; + overflow: hidden; + position: relative; + .el-row{ + margin-bottom: 20px; + } + .el-row:last-child { + margin-bottom: 0; + } + .el-input{ + width: 100% !important; + } + .el-date-editor::v-deep{ + width: 100%; + } + .el-select{ + width: 100%; + } + .el-cascader{ + width: 100% !important; + } + } +</style> diff --git a/src/views/specialWorkSystem/workTicket/wdsq/components/heightLog.vue b/src/views/specialWorkSystem/workTicket/wdsq/components/heightLog.vue new file mode 100644 index 0000000..f95c6e9 --- /dev/null +++ b/src/views/specialWorkSystem/workTicket/wdsq/components/heightLog.vue @@ -0,0 +1,125 @@ +<template> + <div style="height: 100%"> + <el-form :model="details" label-width="150px"> + <el-form-item label="作业申请单号"> + <el-input v-model="details.workPermitNo" readonly /> + </el-form-item> + <el-form-item label="申请人"> + <el-input v-model="details.applyUname" readonly /> + </el-form-item> + <el-form-item label="部门名称"> + <el-input v-model="details.depName" readonly /> + </el-form-item> + <el-form-item label="作业人"> + <el-input v-model="details.operators" readonly type="textarea" /> + </el-form-item> + <el-form-item label="作业类型"> + <el-input v-model="details.workTypeDesc" readonly /> + </el-form-item> + <el-form-item label="作业等级"> + <el-input v-model="details.workLevelDesc" readonly /> + </el-form-item> + <el-form-item label="作业内容"> + <el-input v-model="details.workContent" readonly type="textarea" /> + </el-form-item> + <el-form-item label="作业地址"> + <el-input v-model="details.workLocation" readonly type="textarea" /> + </el-form-item> + <el-form-item label="作业单位"> + <el-input v-model="details.workDetail.operationDepId" readonly type="textarea" /> + </el-form-item> + <el-form-item label="作业高度"> + <el-input v-model="details.workDetail.operationHeight" readonly type="textarea"><template #append>米(m)</template></el-input> + </el-form-item> + <el-form-item label="物资状态"> + <span>{{ details.materialStatus==0?'未关联物资':(details.materialStatus==1?'必选物资配备不足':(details.materialStatus==2?'必选物资配备齐全':(details.materialStatus==3?'物资配置专业':(details.materialStatus==4?'物资配置高端':'-')))) }}</span> + </el-form-item> + <el-form-item label="关联物资" v-if="details.workMaterial&&details.workMaterial.length>0"> + <el-table :data="details.workMaterial" style="width: 100%" border> + <el-table-column prop="bigClassifyName" label="物资类型" align="center"/> + <el-table-column prop="materialName" label="物资名称" align="center"/> + <el-table-column prop="configurationLevel" label="配置级别" align="center"> + <template #default="scope"> + {{scope.row.configurationLevel == 0?'必选':(scope.row.configurationLevel == 1? '可选':'高配')}} + </template> + </el-table-column> + <el-table-column prop="useCount" label="配置数量" align="center"/> + </el-table> + </el-form-item> + <el-form-item label="关联其他作业"> + <el-input v-model="details.workDetail.otherSpecialWork" readonly type="textarea"/> + </el-form-item> + <el-form-item label="期望开始时间"> + <el-input v-model="details.expStartTime" readonly /> + </el-form-item> + <el-form-item label="期望结束时间"> + <el-input v-model="details.expEndTime" readonly /> + </el-form-item> + <el-form-item label="申请时间"> + <el-input v-model="details.applyTime" readonly /> + </el-form-item> + <el-form-item label="当前状态"> + <el-input v-model="details.statusDesc" readonly /> + </el-form-item> + </el-form> + </div> +</template> + +<script lang="ts"> + import { toRefs, reactive, defineComponent, ref, defineAsyncComponent } from 'vue'; + import { storeToRefs } from 'pinia'; + import { initBackEndControlRoutes } from '/@/router/backEnd'; + import {useUserInfo} from "/@/stores/userInfo"; + import { Session } from '/@/utils/storage'; + import { Search } from '@element-plus/icons-vue' + import { ElMessage } from 'element-plus' + import type { FormInstance, FormRules } from 'element-plus' + import { workApplyApi } from '/@/api/specialWorkSystem/workApply'; + + + interface stateType { + form: Object, + workerList: Array<any>, + workTypeList: Array<any>, + workLevelList: Array<any>, + otherWorkList: Array<any> + } + export default defineComponent({ + name: 'space', + components: {}, + props:['details'], + setup() { + const userInfo = useUserInfo() + const { userInfos } = storeToRefs(userInfo); + return { + Search + }; + }, + }); +</script> + +<style scoped lang="scss"> + .home-container { + height: 100%; + overflow: hidden; + position: relative; + .el-row{ + margin-bottom: 20px; + } + .el-row:last-child { + margin-bottom: 0; + } + .el-input{ + width: 100% !important; + } + .el-date-editor::v-deep{ + width: 100%; + } + .el-select{ + width: 100%; + } + .el-cascader{ + width: 100% !important; + } + } +</style> diff --git a/src/views/specialWorkSystem/workTicket/wdsq/components/hoistLog.vue b/src/views/specialWorkSystem/workTicket/wdsq/components/hoistLog.vue new file mode 100644 index 0000000..1086537 --- /dev/null +++ b/src/views/specialWorkSystem/workTicket/wdsq/components/hoistLog.vue @@ -0,0 +1,125 @@ +<template> + <div style="height: 100%"> + <el-form :model="details" label-width="150px"> + <el-form-item label="作业申请单号"> + <el-input v-model="details.workPermitNo" readonly /> + </el-form-item> + <el-form-item label="申请人"> + <el-input v-model="details.applyUname" readonly /> + </el-form-item> + <el-form-item label="部门名称"> + <el-input v-model="details.depName" readonly /> + </el-form-item> + <el-form-item label="作业人"> + <el-input v-model="details.operators" readonly type="textarea" /> + </el-form-item> + <el-form-item label="作业类型"> + <el-input v-model="details.workTypeDesc" readonly /> + </el-form-item> + <el-form-item label="作业等级"> + <el-input v-model="details.workLevelDesc" readonly /> + </el-form-item> + <el-form-item label="作业内容"> + <el-input v-model="details.workContent" readonly type="textarea" /> + </el-form-item> + <el-form-item label="作业地址"> + <el-input v-model="details.workLocation" readonly type="textarea" /> + </el-form-item> + <el-form-item label="吊装工具名称"> + <el-input v-model="details.workDetail.hoistingToolName" readonly type="textarea" /> + </el-form-item> + <el-form-item label="起吊物体重量"> + <el-input v-model="details.workDetail.weightMass" readonly type="textarea"><template #append>吨(t)</template></el-input> + </el-form-item> + <el-form-item label="物资状态"> + <span>{{ details.materialStatus==0?'未关联物资':(details.materialStatus==1?'必选物资配备不足':(details.materialStatus==2?'必选物资配备齐全':(details.materialStatus==3?'物资配置专业':(details.materialStatus==4?'物资配置高端':'-')))) }}</span> + </el-form-item> + <el-form-item label="关联物资" v-if="details.workMaterial&&details.workMaterial.length>0"> + <el-table :data="details.workMaterial" style="width: 100%" border> + <el-table-column prop="bigClassifyName" label="物资类型" align="center"/> + <el-table-column prop="materialName" label="物资名称" align="center"/> + <el-table-column prop="configurationLevel" label="配置级别" align="center"> + <template #default="scope"> + {{scope.row.configurationLevel == 0?'必选':(scope.row.configurationLevel == 1? '可选':'高配')}} + </template> + </el-table-column> + <el-table-column prop="useCount" label="配置数量" align="center"/> + </el-table> + </el-form-item> + <el-form-item label="关联其他作业"> + <el-input v-model="details.workDetail.otherSpecialWork" readonly type="textarea"/> + </el-form-item> + <el-form-item label="期望开始时间"> + <el-input v-model="details.expStartTime" readonly /> + </el-form-item> + <el-form-item label="期望结束时间"> + <el-input v-model="details.expEndTime" readonly /> + </el-form-item> + <el-form-item label="申请时间"> + <el-input v-model="details.applyTime" readonly /> + </el-form-item> + <el-form-item label="当前状态"> + <el-input v-model="details.statusDesc" readonly /> + </el-form-item> + </el-form> + </div> +</template> + +<script lang="ts"> + import { toRefs, reactive, defineComponent, ref, defineAsyncComponent } from 'vue'; + import { storeToRefs } from 'pinia'; + import { initBackEndControlRoutes } from '/@/router/backEnd'; + import {useUserInfo} from "/@/stores/userInfo"; + import { Session } from '/@/utils/storage'; + import { Search } from '@element-plus/icons-vue' + import { ElMessage } from 'element-plus' + import type { FormInstance, FormRules } from 'element-plus' + import { workApplyApi } from '/@/api/specialWorkSystem/workApply'; + + + interface stateType { + form: Object, + workerList: Array<any>, + workTypeList: Array<any>, + workLevelList: Array<any>, + otherWorkList: Array<any> + } + export default defineComponent({ + name: 'space', + components: {}, + props:['details'], + setup() { + const userInfo = useUserInfo() + const { userInfos } = storeToRefs(userInfo); + return { + Search + }; + }, + }); +</script> + +<style scoped lang="scss"> + .home-container { + height: 100%; + overflow: hidden; + position: relative; + .el-row{ + margin-bottom: 20px; + } + .el-row:last-child { + margin-bottom: 0; + } + .el-input{ + width: 100% !important; + } + .el-date-editor::v-deep{ + width: 100%; + } + .el-select{ + width: 100%; + } + .el-cascader{ + width: 100% !important; + } + } +</style> diff --git a/src/views/specialWorkSystem/workTicket/wdsq/components/plateLog.vue b/src/views/specialWorkSystem/workTicket/wdsq/components/plateLog.vue new file mode 100644 index 0000000..69620a3 --- /dev/null +++ b/src/views/specialWorkSystem/workTicket/wdsq/components/plateLog.vue @@ -0,0 +1,149 @@ +<template> + <div style="height: 100%"> + <el-form :model="details" label-width="150px"> + <el-form-item label="作业申请单号"> + <el-input v-model="details.workPermitNo" readonly /> + </el-form-item> + <el-form-item label="申请人"> + <el-input v-model="details.applyUname" readonly /> + </el-form-item> + <el-form-item label="部门名称"> + <el-input v-model="details.depName" readonly /> + </el-form-item> + <el-form-item label="作业人"> + <el-input v-model="details.operators" readonly type="textarea" /> + </el-form-item> + <el-form-item label="作业类型"> + <el-input v-model="details.workTypeDesc" readonly /> + </el-form-item> + <el-form-item label="作业等级"> + <el-input v-model="details.workLevelDesc" readonly /> + </el-form-item> + <el-form-item label="作业内容"> + <el-input v-model="details.workContent" readonly type="textarea" /> + </el-form-item> + <el-form-item label="作业地址"> + <el-input v-model="details.workLocation" readonly type="textarea" /> + </el-form-item> + <el-form-item label="盲板编号"> + <el-input v-model="details.workDetail.bpCode" readonly type="textarea" /> + </el-form-item> + <el-form-item label="主要介质"> + <el-input v-model="details.workDetail.mainMedia" readonly type="textarea" /> + </el-form-item> + <el-form-item label="温度"> + <el-input v-model="details.workDetail.temperature" readonly type="textarea"><template #append>摄氏度(℃)</template></el-input> + </el-form-item> + <el-form-item label="压力"> + <el-input v-model="details.workDetail.pressure" readonly type="textarea"><template #append>千帕(kPa)</template></el-input> + </el-form-item> + <el-form-item label="盲板材质"> + <el-input v-model="details.workDetail.bpMaterialQuality" readonly type="textarea"/> + </el-form-item> + <el-form-item label="盲板规格"> + <el-input v-model="details.workDetail.bpSpecification" readonly type="textarea"/> + </el-form-item> + <el-form-item label="盲板位置"> + <el-input v-model="details.workDetail.bpLocation" readonly type="textarea"/> + </el-form-item> + <el-form-item label="装盲板时间"> + <el-input v-model="details.workDetail.installBpTime" readonly/> + </el-form-item> + <el-form-item label="拆盲板时间"> + <el-input v-model="details.workDetail.uninstallBpTime" readonly/> + </el-form-item> + <el-form-item label="物资状态"> + <span>{{ details.materialStatus==0?'未关联物资':(details.materialStatus==1?'必选物资配备不足':(details.materialStatus==2?'必选物资配备齐全':(details.materialStatus==3?'物资配置专业':(details.materialStatus==4?'物资配置高端':'-')))) }}</span> + </el-form-item> + <el-form-item label="关联物资" v-if="details.workMaterial&&details.workMaterial.length>0"> + <el-table :data="details.workMaterial" style="width: 100%" border> + <el-table-column prop="bigClassifyName" label="物资类型" align="center"/> + <el-table-column prop="materialName" label="物资名称" align="center"/> + <el-table-column prop="configurationLevel" label="配置级别" align="center"> + <template #default="scope"> + {{scope.row.configurationLevel == 0?'必选':(scope.row.configurationLevel == 1? '可选':'高配')}} + </template> + </el-table-column> + <el-table-column prop="useCount" label="配置数量" align="center"/> + </el-table> + </el-form-item> + <el-form-item label="关联其他作业"> + <el-input v-model="details.workDetail.otherSpecialWork" readonly type="textarea"/> + </el-form-item> + <el-form-item label="盲板位置图"> + <el-image v-for="item in details.workDetail.bpLocationMapPath" :preview-src-list="details.workDetail.bpLocationMapPath" style="width: 150px; height: 150px;margin-right: 50px;margin-bottom: 20px" :src="item" fit="cover" /> + </el-form-item> + <el-form-item label="期望开始时间"> + <el-input v-model="details.expStartTime" readonly /> + </el-form-item> + <el-form-item label="期望结束时间"> + <el-input v-model="details.expEndTime" readonly /> + </el-form-item> + <el-form-item label="申请时间"> + <el-input v-model="details.applyTime" readonly /> + </el-form-item> + <el-form-item label="当前状态"> + <el-input v-model="details.statusDesc" readonly /> + </el-form-item> + </el-form> + </div> +</template> + +<script lang="ts"> + import { toRefs, reactive, defineComponent, ref, defineAsyncComponent } from 'vue'; + import { storeToRefs } from 'pinia'; + import { initBackEndControlRoutes } from '/@/router/backEnd'; + import {useUserInfo} from "/@/stores/userInfo"; + import { Session } from '/@/utils/storage'; + import { Search } from '@element-plus/icons-vue' + import { ElMessage } from 'element-plus' + import type { FormInstance, FormRules } from 'element-plus' + import { workApplyApi } from '/@/api/specialWorkSystem/workApply'; + + + interface stateType { + form: Object, + workerList: Array<any>, + workTypeList: Array<any>, + workLevelList: Array<any>, + otherWorkList: Array<any> + } + export default defineComponent({ + name: 'space', + components: {}, + props:['details'], + setup() { + const userInfo = useUserInfo() + const { userInfos } = storeToRefs(userInfo); + return { + Search + }; + }, + }); +</script> + +<style scoped lang="scss"> + .home-container { + height: 100%; + overflow: hidden; + position: relative; + .el-row{ + margin-bottom: 20px; + } + .el-row:last-child { + margin-bottom: 0; + } + .el-input{ + width: 100% !important; + } + .el-date-editor::v-deep{ + width: 100%; + } + .el-select{ + width: 100%; + } + .el-cascader{ + width: 100% !important; + } + } +</style> diff --git a/src/views/specialWorkSystem/workTicket/wdsq/components/powerLog.vue b/src/views/specialWorkSystem/workTicket/wdsq/components/powerLog.vue new file mode 100644 index 0000000..cf81c13 --- /dev/null +++ b/src/views/specialWorkSystem/workTicket/wdsq/components/powerLog.vue @@ -0,0 +1,128 @@ +<template> + <div style="height: 100%"> + <el-form :model="details" label-width="150px"> + <el-form-item label="作业申请单号"> + <el-input v-model="details.workPermitNo" readonly /> + </el-form-item> + <el-form-item label="申请人"> + <el-input v-model="details.applyUname" readonly /> + </el-form-item> + <el-form-item label="部门名称"> + <el-input v-model="details.depName" readonly /> + </el-form-item> + <el-form-item label="作业人"> + <el-input v-model="details.operators" readonly type="textarea" /> + </el-form-item> + <el-form-item label="作业类型"> + <el-input v-model="details.workTypeDesc" readonly /> + </el-form-item> + <el-form-item label="作业等级"> + <el-input v-model="details.workLevelDesc" readonly /> + </el-form-item> + <el-form-item label="作业内容"> + <el-input v-model="details.workContent" readonly type="textarea" /> + </el-form-item> + <el-form-item label="作业地址"> + <el-input v-model="details.workLocation" readonly type="textarea" /> + </el-form-item> + <el-form-item label="电源接入点"> + <el-input v-model="details.workDetail.powerAccessPoint" readonly type="textarea" /> + </el-form-item> + <el-form-item label="工作电压"> + <el-input v-model="details.workDetail.workingVoltage" readonly type="textarea"><template #append>伏特(v)</template></el-input> + </el-form-item> + <el-form-item label="用电设备及功率"> + <el-input v-model="details.workDetail.equipmentAndPower" readonly type="textarea" /> + </el-form-item> + <el-form-item label="物资状态"> + <span>{{ details.materialStatus==0?'未关联物资':(details.materialStatus==1?'必选物资配备不足':(details.materialStatus==2?'必选物资配备齐全':(details.materialStatus==3?'物资配置专业':(details.materialStatus==4?'物资配置高端':'-')))) }}</span> + </el-form-item> + <el-form-item label="关联物资" v-if="details.workMaterial&&details.workMaterial.length>0"> + <el-table :data="details.workMaterial" style="width: 100%" border> + <el-table-column prop="bigClassifyName" label="物资类型" align="center"/> + <el-table-column prop="materialName" label="物资名称" align="center"/> + <el-table-column prop="configurationLevel" label="配置级别" align="center"> + <template #default="scope"> + {{scope.row.configurationLevel == 0?'必选':(scope.row.configurationLevel == 1? '可选':'高配')}} + </template> + </el-table-column> + <el-table-column prop="useCount" label="配置数量" align="center"/> + </el-table> + </el-form-item> + <el-form-item label="关联其他作业"> + <el-input v-model="details.workDetail.otherSpecialWork" readonly type="textarea"/> + </el-form-item> + <el-form-item label="期望开始时间"> + <el-input v-model="details.expStartTime" readonly /> + </el-form-item> + <el-form-item label="期望结束时间"> + <el-input v-model="details.expEndTime" readonly /> + </el-form-item> + <el-form-item label="申请时间"> + <el-input v-model="details.applyTime" readonly /> + </el-form-item> + <el-form-item label="当前状态"> + <el-input v-model="details.statusDesc" readonly /> + </el-form-item> + </el-form> + </div> +</template> + +<script lang="ts"> + import { toRefs, reactive, defineComponent, ref, defineAsyncComponent } from 'vue'; + import { storeToRefs } from 'pinia'; + import { initBackEndControlRoutes } from '/@/router/backEnd'; + import {useUserInfo} from "/@/stores/userInfo"; + import { Session } from '/@/utils/storage'; + import { Search } from '@element-plus/icons-vue' + import { ElMessage } from 'element-plus' + import type { FormInstance, FormRules } from 'element-plus' + import { workApplyApi } from '/@/api/specialWorkSystem/workApply'; + + + interface stateType { + form: Object, + workerList: Array<any>, + workTypeList: Array<any>, + workLevelList: Array<any>, + otherWorkList: Array<any> + } + export default defineComponent({ + name: 'space', + components: {}, + props:['details'], + setup() { + const userInfo = useUserInfo() + const { userInfos } = storeToRefs(userInfo); + return { + Search + }; + }, + }); +</script> + +<style scoped lang="scss"> + .home-container { + height: 100%; + overflow: hidden; + position: relative; + .el-row{ + margin-bottom: 20px; + } + .el-row:last-child { + margin-bottom: 0; + } + .el-input{ + width: 100% !important; + } + .el-date-editor::v-deep{ + width: 100%; + } + .el-select{ + width: 100%; + } + .el-cascader{ + width: 100% !important; + } + } +</style> diff --git a/src/views/specialWorkSystem/workTicket/wdsq/components/spaceLog.vue b/src/views/specialWorkSystem/workTicket/wdsq/components/spaceLog.vue new file mode 100644 index 0000000..d6b4606 --- /dev/null +++ b/src/views/specialWorkSystem/workTicket/wdsq/components/spaceLog.vue @@ -0,0 +1,128 @@ +<template> + <div style="height: 100%"> + <el-form :model="details" label-width="150px"> + <el-form-item label="作业申请单号"> + <el-input v-model="details.workPermitNo" readonly /> + </el-form-item> + <el-form-item label="申请人"> + <el-input v-model="details.applyUname" readonly /> + </el-form-item> + <el-form-item label="部门名称"> + <el-input v-model="details.depName" readonly /> + </el-form-item> + <el-form-item label="作业人"> + <el-input v-model="details.operators" readonly type="textarea" /> + </el-form-item> + <el-form-item label="作业类型"> + <el-input v-model="details.workTypeDesc" readonly /> + </el-form-item> + <el-form-item label="作业等级"> + <el-input v-model="details.workLevelDesc" readonly /> + </el-form-item> + <el-form-item label="作业内容"> + <el-input v-model="details.workContent" readonly type="textarea" /> + </el-form-item> + <el-form-item label="作业地址"> + <el-input v-model="details.workLocation" readonly type="textarea"/> + </el-form-item> + <el-form-item label="受限空间所属单位"> + <el-input v-model="details.workDetail.csDepId" readonly type="textarea" /> + </el-form-item> + <el-form-item label="受限空间名称"> + <el-input v-model="details.workDetail.csName" readonly type="textarea" /> + </el-form-item> + <el-form-item label="空间原有介质名称"> + <el-input v-model="details.workDetail.csOriginalName" readonly type="textarea" /> + </el-form-item> + <el-form-item label="物资状态"> + <span>{{ details.materialStatus==0?'未关联物资':(details.materialStatus==1?'必选物资配备不足':(details.materialStatus==2?'必选物资配备齐全':(details.materialStatus==3?'物资配置专业':(details.materialStatus==4?'物资配置高端':'-')))) }}</span> + </el-form-item> + <el-form-item label="关联物资" v-if="details.workMaterial&&details.workMaterial.length>0"> + <el-table :data="details.workMaterial" style="width: 100%" border> + <el-table-column prop="bigClassifyName" label="物资类型" align="center"/> + <el-table-column prop="materialName" label="物资名称" align="center"/> + <el-table-column prop="configurationLevel" label="配置级别" align="center"> + <template #default="scope"> + {{scope.row.configurationLevel == 0?'必选':(scope.row.configurationLevel == 1? '可选':'高配')}} + </template> + </el-table-column> + <el-table-column prop="useCount" label="配置数量" align="center"/> + </el-table> + </el-form-item> + <el-form-item label="关联其他作业"> + <el-input v-model="details.workDetail.otherSpecialWork" readonly type="textarea" /> + </el-form-item> + <el-form-item label="期望开始时间"> + <el-input v-model="details.expStartTime" readonly /> + </el-form-item> + <el-form-item label="期望结束时间"> + <el-input v-model="details.expEndTime" readonly /> + </el-form-item> + <el-form-item label="申请时间"> + <el-input v-model="details.applyTime" readonly /> + </el-form-item> + <el-form-item label="当前状态"> + <el-input v-model="details.statusDesc" readonly /> + </el-form-item> + </el-form> + </div> +</template> + +<script lang="ts"> + import { toRefs, reactive, defineComponent, ref, defineAsyncComponent } from 'vue'; + import { storeToRefs } from 'pinia'; + import { initBackEndControlRoutes } from '/@/router/backEnd'; + import {useUserInfo} from "/@/stores/userInfo"; + import { Session } from '/@/utils/storage'; + import { Search } from '@element-plus/icons-vue' + import { ElMessage } from 'element-plus' + import type { FormInstance, FormRules } from 'element-plus' + import { workApplyApi } from '/@/api/specialWorkSystem/workApply'; + + + interface stateType { + form: Object, + workerList: Array<any>, + workTypeList: Array<any>, + workLevelList: Array<any>, + otherWorkList: Array<any> + } + export default defineComponent({ + name: 'space', + components: {}, + props:['details'], + setup() { + const userInfo = useUserInfo() + const { userInfos } = storeToRefs(userInfo); + return { + Search + }; + }, + }); +</script> + +<style scoped lang="scss"> + .home-container { + height: 100%; + overflow: hidden; + position: relative; + .el-row{ + margin-bottom: 20px; + } + .el-row:last-child { + margin-bottom: 0; + } + .el-input{ + width: 100% !important; + } + .el-date-editor::v-deep{ + width: 100%; + } + .el-select{ + width: 100%; + } + .el-cascader{ + width: 100% !important; + } + } +</style> diff --git a/src/views/specialWorkSystem/workTicket/wdsq/index.vue b/src/views/specialWorkSystem/workTicket/wdsq/index.vue new file mode 100644 index 0000000..340b902 --- /dev/null +++ b/src/views/specialWorkSystem/workTicket/wdsq/index.vue @@ -0,0 +1,877 @@ +<template> + <div class="home-container"> +<!-- <el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">--> +<!-- <el-tab-pane label="申请中" name="1">--> + <div style="height: 100%"> + <el-row class="homeCard"> + <span>作业类型:</span> + <el-col :span="10"> + <div class="grid-content topInfo"> + <el-select v-model="searchWord"> + <el-option + v-for="item in workType" + :key="item.id" + :label="item.name" + :value="item.id" + /> + </el-select> + + <el-button type="primary" @click="searchRecord">查询</el-button> + <el-button plain @click="clearSearch">重置</el-button> + </div> + </el-col> + </el-row> + <div class="homeCard"> + <div class="main-card"> + <el-row class="cardTop"> + <el-col :span="12" class="mainCardBtn"> + <el-button type="primary" :icon="Plus" size="default" @click="toApply()">申请</el-button> + <!-- <el-button type="danger" :icon="Delete" size="default">删除</el-button>--> + <!-- <el-button type="success" size="default">设置分类</el-button>--> + </el-col> + <el-button type="primary" :icon="Refresh" size="default" @click="reLoadData()" /> + </el-row> + <el-table ref="multipleTableRef" :data="applyData" style="width: 100%" height="calc(100% - 100px)" :header-cell-style="{ background: '#fafafa' }"> + <el-table-column property="workPermitNo" label="作业申请单号" width="180" /> + <el-table-column property="applyUname" label="申请人" /> + <el-table-column property="depName" label="部门名称" /> + <el-table-column property="operators" label="作业人" /> + <el-table-column property="workTypeDesc" label="作业类型" /> + <el-table-column property="workLevelDesc" label="作业等级" /> + <el-table-column property="materialStatus" label="物资状态" align="center" width="180"> + <template #default="scope"> + <span>{{ scope.row.materialStatus==0?'未关联物资':(scope.row.materialStatus==1?'必选物资配备不足':(scope.row.materialStatus==2?'必选物资配备齐全':(scope.row.materialStatus==3?'物资配置专业':(scope.row.materialStatus==4?'物资配置高端':'-')))) }}</span> + </template> + </el-table-column> + <el-table-column property="applyTime" label="申请时间" width="180" /> + <el-table-column label="申请状态" align="center" width="180"> + <template #default="scope"> + <el-tag :type="scope.row.status==2?'success':(scope.row.status==8||scope.row.status==9)?'warning':'danger'">{{ scope.row.statusDesc }}</el-tag> + </template> + </el-table-column> + <el-table-column fixed="right" label="操作" align="center" width="300"> + <template #default="scope"> + <el-button link type="primary" size="small" :icon="View" @click="viewRecord(scope.row)">查看</el-button> + <el-button link type="success" size="small" :icon="Finished" @click="viewStatus(scope.row)">进度</el-button> + <el-button link type="warning" size="small" :icon="Delete" @click="deleteRecordBtn(scope.row)">取消</el-button> + <el-button :disabled="scope.row.status == 7 ? false : true" link type="primary" size="small" :icon="Download" @click="downLoadBtn(scope.row)">导出作业票</el-button> + </template> + </el-table-column> + </el-table> + <div class="pageBtn"> + <el-pagination v-model:currentPage="pageIndex1" v-model:page-size="pageSize1" :page-sizes="[10, 15]" small="false" background layout="total, sizes, prev, pager, next, jumper" :total="totalSize1" @size-change="handleSizeChange1" @current-change="handleCurrentChange1" /> + </div> + </div> + </div> + </div> + <el-dialog v-model="dialogDetails" title="作业申请详情" center> + <fire v-if="dialogType == 1" :details = details></fire> + <space v-else-if="dialogType == 2" :details = details></space> + <hoist v-else-if="dialogType == 3" :details = details></hoist> + <ground v-else-if="dialogType == 4" :details = details></ground> + <broken v-else-if="dialogType == 5" :details = details></broken> + <height v-else-if="dialogType == 6" :details = details></height> + <power v-else-if="dialogType == 7" :details = details></power> + <plate v-else :details = details></plate> + <template #footer> + <span class="dialog-footer"> + <el-button type="primary" @click="dialogDetails = false" + >确认</el-button + > + </span> + </template> + </el-dialog> + <el-dialog v-model="dialogStatus" title="作业申请进度" width="60%"> + <el-form v-if="approveInfo.operators.length > 0" style="margin-bottom: 40px"> + <el-form-item label="申请作业人"> + <el-input v-model="approveInfo.operators" readonly type="textarea" /> + </el-form-item> + </el-form> + <div style="display: flex; flex-direction: column-reverse"> + <div v-for="(item, index) in approveInfo.approvalSteps" class="stepItem"> + <div class="stepNum">{{ item.stepSerial }}</div> + <div class="stepCard"> + <el-card class="box-card" shadow="always"> + <div class="text"> + 审批结果:<span class="bold-text">{{ item.approvalResultDesc }}</span> + </div> + <div class="text"> + 审批类型:<span class="bold-text">{{ item.typeDesc }}</span> + </div> + <div class="text" v-if="item.auditTypeDesc"> + 审批类型:<span class="bold-text">{{ item.auditTypeDesc }}</span> + </div> + <div class="text" v-show="item.startApprovalTime != null"> + 开始时间:<span>{{ item.startApprovalTime }}</span> + </div> + <div class="approveUnit"> + <div class="item-tit"><span>审批人</span><span>审批状态</span></div> + <div class="item-cont" v-for="i in item.stepUnits"> + <span>{{ i.approvalUname }}</span + ><span>{{ i.resultDesc }}</span> + </div> + </div> + <div class="approveItem"> + <div class="item-tit"> + <span>审批项目</span> +<!-- <span>类型</span>--> + <div>措施标准</div> + </div> + <div class="item-cont" v-for="i in item.stepItems"> + <span>{{ i.itemName }}</span> +<!-- <span>{{ i.typeDesc }}</span>--> + <div v-if="i.measure !== null"> + <div> + <span>作业类型:</span><span>{{ i.measure.workTypeDesc }}</span> + </div> + <div> + <span>措施内容:</span><span>{{ i.measure.context }}</span> + </div> + </div> + <div v-if="i.stand !== null"> + <div> + <span>标题名称:</span><span>{{ i.stand.title }}</span> + </div> + <div> + <span>标准内容:</span><span>{{ i.stand.typeDesc }}</span> + </div> + </div> + </div> + </div> + <div class="text" v-show="item.expFinishApprovalTime && item.expFinishApprovalTime != null"> + 期望结束时间:<span>{{ item.expFinishApprovalTime }}</span> + </div> + <div class="text" v-show="item.finishApprovalTime != null"> + 结束时间:<span>{{ item.finishApprovalTime }}</span> + </div> + </el-card> + </div> + </div> + </div> + </el-dialog> + <el-dialog v-model="deleteDialog" title="提示" width="30%" center> + <span>您确定要取消该条申请吗?</span> + <template #footer> + <span class="dialog-footer"> + <el-button @click="deleteDialog = false" size="default">取消</el-button> + <el-button type="primary" @click="conFirmDelete" size="default">确认</el-button> + </span> + </template> + </el-dialog> + <el-dialog v-model="downLoadDialog" title="提示" width="30%" center> + <span>您确定要导出该条记录吗?</span> + <template #footer> + <span class="dialog-footer"> + <el-button @click="downLoadDialog = false" size="default">取消</el-button> + <el-button type="primary" @click="conFirmDownLoad" size="default">确认</el-button> + </span> + </template> + </el-dialog> +<!-- </el-tab-pane>--> +<!-- <el-tab-pane label="已通过" name="2">--> +<!-- <div style="height: 100%">--> +<!-- <el-row class="homeCard">--> +<!-- <el-col :span="8">--> +<!-- <div class="grid-content topInfo">--> +<!-- <el-input v-model="searchWord" placeholder="作业证名称"></el-input>--> +<!-- <el-button type="primary">查询</el-button>--> +<!-- <el-button plain>重置</el-button>--> +<!-- </div>--> +<!-- </el-col>--> +<!-- </el-row>--> +<!-- <div class="homeCard">--> +<!-- <div class="main-card">--> +<!-- <el-table ref="multipleTableRef" :data="passedData" style="width: 100%" height="calc(100% - 48px)" :header-cell-style="{ background: '#fafafa' }" @selection-change="handleSelectionChange">--> +<!-- <el-table-column type="selection" width="55" />--> +<!-- <el-table-column type="index" label="编号" width="200" />--> +<!-- <el-table-column property="level" label="作业证等级" width="180" sortable />--> +<!-- <el-table-column property="applyDate" label="申请日期" sortable />--> +<!-- <el-table-column property="name" label="申请人" width="180" />--> +<!-- <el-table-column property="department" label="申请部门" width="180" />--> +<!-- <el-table-column label="申请状态" width="180">--> +<!-- <template #default="scope">--> +<!-- <el-tag type="success">{{ scope.row.status }}</el-tag>--> +<!-- </template>--> +<!-- </el-table-column>--> +<!-- </el-table>--> +<!-- <div class="pageBtn">--> +<!-- <el-pagination v-model:currentPage="pageIndex2" v-model:page-size="pageSize2" :page-sizes="[10, 15]" small="false" background layout="total, sizes, prev, pager, next, jumper" :total="totalSize2" @size-change="handleSizeChange2" @current-change="handleCurrentChange2" />--> +<!-- </div>--> +<!-- </div>--> +<!-- </div>--> +<!-- </div>--> +<!-- </el-tab-pane>--> +<!-- </el-tabs>--> + </div> +</template> + +<script lang="ts"> +import {toRefs, reactive, defineComponent, ref, onMounted, defineAsyncComponent} from 'vue'; +import { storeToRefs } from 'pinia'; +import { initBackEndControlRoutes } from '/@/router/backEnd'; +import { useUserInfo } from '/@/stores/userInfo'; +import { Session } from '/@/utils/storage'; +import { useRouter } from 'vue-router'; +import { Edit, View, Plus, Delete, Refresh, Search, Finished, Download } from '@element-plus/icons-vue'; +import { ElTable } from 'element-plus'; +import { FormInstance, FormRules, ElMessage } from 'element-plus'; +import { workApplyApi } from '/@/api/specialWorkSystem/workApply'; +import type { TabsPaneContext } from 'element-plus'; +import {teamManageApi} from "/@/api/systemManage/basicDateManage/personShiftManage/teamManage"; +import Cookies from 'js-cookie'; +import axios from 'axios'; + +// 定义接口来定义对象的类型 +interface stateType { + applyData: Array<string>; + workTimeList: Array<string>; + multipleSelection: Array<any>; + deleteArr: Array<any>; + approveInfo: Object; + dialogDetails: boolean; + dialogStatus: boolean; + deleteDialog: boolean; + downLoadDialog: boolean; + pageIndex1: number; + pageSize1: number; + chosenIndex: null | number; + deleteId: null | number; + downLoadId: null | number; + downLoadName: string; + searchWord: string; + totalSize1: number; + activeName: string; + addRecord: {}; + details: {}; + statusInfo: {}; + workType: Array<type>; + dialogType: number | null; + departmentList: Array<any>; + departmentRecursionList: Array<DepartmentState>; +} +interface type { + id: number; + name: string; +} +interface DepartmentState { + depId: number; + depName: string; +} +export default defineComponent({ + name: 'myApply', + components: { + fire: defineAsyncComponent(() => import('/@/views/specialWorkSystem/workTicket/wdsq/components/fireLog.vue')), + space: defineAsyncComponent(() => import('/@/views/specialWorkSystem/workTicket/wdsq/components/spaceLog.vue')), + hoist: defineAsyncComponent(() => import('/@/views/specialWorkSystem/workTicket/wdsq/components/hoistLog.vue')), + ground: defineAsyncComponent(() => import('/@/views/specialWorkSystem/workTicket/wdsq/components/groundLog.vue')), + broken: defineAsyncComponent(() => import('/@/views/specialWorkSystem/workTicket/wdsq/components/brokenLog.vue')), + height: defineAsyncComponent(() => import('/@/views/specialWorkSystem/workTicket/wdsq/components/heightLog.vue')), + power: defineAsyncComponent(() => import('/@/views/specialWorkSystem/workTicket/wdsq/components/powerLog.vue')), + plate: defineAsyncComponent(() => import('/@/views/specialWorkSystem/workTicket/wdsq/components/plateLog.vue')) + }, + setup() { + const userInfo = useUserInfo(); + const { userInfos } = storeToRefs(userInfo); + const router = useRouter(); + const state = reactive<stateType>({ + pageIndex1: 1, + pageSize1: 10, + totalSize1: 0, + dialogType: null, + activeName: '1', + departmentList: [], + departmentRecursionList: [], + chosenIndex: null, + searchWord: '', + applyData: [], + workTimeList: [], + multipleSelection: [], + approveInfo: { + approvalSteps: [], + operators: [] + }, + dialogDetails: false, + dialogStatus: false, + deleteDialog: false, + downLoadDialog: false, + addRecord: {}, + details: {}, + statusInfo: {}, + deleteId: null, + downLoadId: null, + downLoadName: '', + deleteArr: [], + workType: [ + { id: 1, name: '动火作业' }, + { id: 2, name: '受限空间作业' }, + { id: 3, name: '吊装作业' }, + { id: 4, name: '动土作业' }, + { id: 5, name: '断路作业' }, + { id: 6, name: '高处作业' }, + { id: 7, name: '临时用电作业' }, + { id: 8, name: '盲板抽堵作业' } + ] + }); + interface User { + name: string; + list: []; + info: string; + } + + // 刷新 + const reLoadData = async () => { + getListByPage(); + }; + + // 填写表单 + const toApply = () => { + router.push({ + path: 'zysq' + }); + }; + + const handleClick = (tab: TabsPaneContext, event: Event) => { + }; + + // 获取部门列表 + const getAllDepartment = async () => { + let res = await teamManageApi().getAllDepartment(); + if (res.data.code === '200') { + state.departmentList = JSON.parse(JSON.stringify(res.data.data)) + recursion(state.departmentList); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + const recursion = (value: any) => { + for (let i of value) { + if (i.children.length !== 0) { + state.departmentRecursionList.push(i); + recursion(i.children); + } else { + state.departmentRecursionList.push(i); + } + } + }; + + // 分页获取 + const getListByPage = async () => { + const data = { pageSize: state.pageSize1, pageIndex: state.pageIndex1, searchParams: { workType: state.searchWord } }; + let res = await workApplyApi().getApplyListPage(data); + if (res.data.code === '200') { + state.applyData = JSON.parse(JSON.stringify(res.data.data)); + console.log(state.applyData,'applyData') + state.applyData = state.applyData.map((item) => { + if (item.operators == null || item.operators == []) { + item.operators = []; + } else { + item.operators = Array.from(item.operators, ({ operatorUname }) => operatorUname); + } + return item; + }); + state.totalSize1 = res.data.total; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 表格数据格式化 + const toNames = (row, column, cellValue, index) => { + if (row.list == []) { + return []; + } else { + const nameList = []; + for (let i = 0; i < row.list.length; i++) { + for (let t = 0; t < state.workTimeList.length; t++) { + if (row.list[i] == state.workTimeList[t].id) { + nameList.push(state.workTimeList[t].name); + } + } + } + return nameList.join(); + } + }; + + // 关键词查询记录 + const searchRecord = async () => { + if (state.searchWord == '') { + ElMessage({ + type: 'warning', + message: '请输入查询关键词' + }); + } else { + getListByPage(); + } + }; + // 重置搜索 + const clearSearch = async () => { + state.searchWord = ''; + getListByPage(); + }; + + // 查看进度 + const viewStatus = (row) => { + getStatus({ workApplyId: row.workApplyId }); + state.dialogStatus = true; + }; + + // 查询进度方法 + const getStatus = async (data: any) => { + let res = await workApplyApi().getStatus(data); + if (res.data.code === '200') { + state.approveInfo = JSON.parse(JSON.stringify(res.data.data)); + state.approveInfo.operators = Array.from(state.approveInfo.operators, ({ operatorUname }) => operatorUname); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + const deleteRecordBtn = (row) => { + state.deleteId = row.workApplyId; + state.deleteDialog = true; + }; + + // 取消申请方法 + const deleteRecord = async (data: any) => { + let res = await workApplyApi().cancelApply(data); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '删除成功!' + }); + getListByPage(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + const conFirmDelete = () => { + deleteRecord({ workApplyId: state.deleteId }); + state.deleteDialog = false; + }; + + // 导出图表 + const downLoadBtn = (row:any) =>{ + state.downLoadId = row.workApplyId; + state.downLoadName = row.workTypeDesc + row.workPermitNo + state.downLoadDialog = true; + } + + // 导出方法 + const downLoadRecord = async (data: any) => { + // let res = await workApplyApi().postPrinting(data); + axios.post(import.meta.env.VITE_API_URL + `/work/apply/printingPdf`,data,{headers:{'Content-Type': 'application/json','Authorization': `${Cookies.get('token')}`,'uid':`${Cookies.get('uid')}`},responseType: 'blob'}).then(res=>{ + if (res) { + const link = document.createElement('a') + let blob = new Blob([res.data],{type: 'application/pdf'}) + link.style.display = "none"; + link.href = URL.createObjectURL(blob); // 创建URL + link.setAttribute("download", state.downLoadName + "作业证.pdf"); + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }) + + }; + + const conFirmDownLoad = () => { + downLoadRecord({ applyWorkId: state.downLoadId }); + state.downLoadDialog = false; + }; + + const handleSizeChange1 = (val: number) => { + state.pageSize1 = val; + getListByPage(); + }; + const handleCurrentChange1 = (val: number) => { + state.pageIndex1 = val; + getListByPage(); + }; + + // 查看记录 + const viewRecord = (row: any) => { + state.dialogType = row.workType + state.details = JSON.parse(JSON.stringify(row)); + if(state.details.workDetail.otherSpecialWork == '' || !state.details.workDetail.otherSpecialWork){ + state.details.workDetail.otherSpecialWork=[] + } + else { + const a = state.details.workDetail.otherSpecialWork + state.details.workDetail.otherSpecialWork = a.split(',').map((item) => { + return state.workType.find((i: { id: number }) => i.id === Number(item))?.name; + }); + } + if(state.details.workDetail.involvedDepIds == '' || !state.details.workDetail.involvedDepIds){ + state.details.workDetail.involvedDepIds=[] + } + else { + const a = state.details.workDetail.involvedDepIds + state.details.workDetail.involvedDepIds = a.split(',').map((item) => { + return state.departmentRecursionList.find((i: { depId: number }) => i.depId === Number(item))?.depName; + }); + } + if(state.details.workDetail.csDepId){ + state.details.workDetail.csDepId = state.departmentRecursionList.find((i: { depId: number }) => i.depId === Number(state.details.workDetail.csDepId))?.depName; + } + if(state.details.workDetail.operationDepId){ + state.details.workDetail.operationDepId = state.departmentRecursionList.find((i: { depId: number }) => i.depId === Number(state.details.workDetail.operationDepId))?.depName; + } + if(state.details.workDetail.gbPath){ + state.details.workDetail.gbPath = state.details.workDetail.gbPath.split(',') + } + if(state.details.workDetail.bcPath){ + state.details.workDetail.bcPath = state.details.workDetail.bcPath.split(',') + } + if(state.details.workDetail.bpLocationMapPath){ + state.details.workDetail.bpLocationMapPath = state.details.workDetail.bpLocationMapPath.split(',') + } + state.dialogDetails = true; + }; + + // 折线图 + const renderMenu = async (value: string) => { + Session.set('projectId', value); + userInfos.value.projectId = value; + await initBackEndControlRoutes(); + }; + + // 页面载入时执行方法 + onMounted(() => { + getListByPage(); + getAllDepartment() + }); + + return { + View, + Edit, + Delete, + Refresh, + Plus, + Finished, + Download, + reLoadData, + toApply, + handleClick, + toNames, + searchRecord, + clearSearch, + viewRecord, + viewStatus, + deleteRecordBtn, + downLoadBtn, + conFirmDelete, + conFirmDownLoad, + getListByPage, + handleSizeChange1, + handleCurrentChange1, + ...toRefs(state) + }; + } +}); +</script> + +<style scoped lang="scss"> +$homeNavLengh: 8; +.home-container { + height: calc(100vh - 144px); + box-sizing: border-box; + overflow: hidden; + .demo-tabs { + width: 100%; + height: 100%; + + &::v-deep(.el-tabs__content) { + height: calc(100% - 60px); + } + + .el-tab-pane { + height: 100%; + } + } + .homeCard { + width: 100%; + padding: 20px; + box-sizing: border-box; + background: #fff; + border-radius: 4px; + + .main-card { + width: 100%; + height: 100%; + .cardTop { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 20px; + .mainCardBtn { + margin: 0; + } + } + .pageBtn { + height: 60px; + display: flex; + align-items: center; + justify-content: right; + + .demo-pagination-block + .demo-pagination-block { + margin-top: 10px; + } + .demo-pagination-block .demonstration { + margin-bottom: 16px; + } + } + } + &:last-of-type { + height: calc(100% - 100px); + } + } + .stepItem { + display: flex; + align-items: flex-start; + margin-top: 30px; + margin-left: 30px; + padding-bottom: 30px; + padding-left: 40px; + border-left: 1px solid #a0cfff; + position: relative; + &:first-of-type { + margin-top: 30px; + } + &:first-of-type { + margin-bottom: 0; + border-left: none; + } + .stepNum { + position: absolute; + width: 40px; + height: 40px; + border-radius: 20px; + box-sizing: border-box; + font-size: 18px; + color: #333; + border: 1px solid #a0cfff; + line-height: 38px; + text-align: center; + left: -20px; + top: -30px; + background: #d9ecff; + } + .stepCard { + width: 100%; + margin-top: -30px; + + .box-card { + width: 100%; + + .card-header { + display: flex; + justify-content: space-between; + align-items: center; + + span { + font-weight: bold; + margin-left: 10px; + } + } + + .text { + width: 100%; + font-size: 14px; + margin-bottom: 10px; + padding-left: 10px; + + span { + color: #409eff; + } + + .bold-text{ + font-weight: bolder; + } + + &:last-of-type { + margin-bottom: 0; + } + } + .approveUnit { + width: 100%; + font-size: 14px; + margin-bottom: 20px; + padding: 10px 15px; + border: 1px solid #fff; + background: #ecf8ff; + border-radius: 6px; + .item-tit { + width: 100%; + display: flex; + color: #409eff; + align-items: flex-start; + justify-content: space-between; + padding-bottom: 10px; + border-bottom: 1px solid #a0cfff; + + & > span { + flex: 1; + &:last-of-type{ + text-align: center; + } + } + & > div { + flex: 1; + text-align: center; + } + } + .item-cont { + width: 100%; + display: flex; + align-items: center; + justify-content: space-between; + padding: 10px 0; + border-bottom: 1px solid #c6e2ff; + + & > span { + flex: 1; + &:last-of-type{ + text-align: center; + } + } + & > div { + flex: 1; + text-align: center; + + & > div { + text-align: left; + width: 100%; + display: flex; + justify-content: center; + align-items: center; + span { + width: 45%; + &:first-of-type { + width: 30%; + } + } + } + } + &:last-of-type { + border-bottom: 0; + } + } + } + .approveItem { + width: 100%; + font-size: 14px; + margin-bottom: 20px; + padding: 10px 15px; + background: #ecf8ff; + border: 1px solid #fff; + border-radius: 6px; + .item-tit { + width: 100%; + display: flex; + color: #409eff; + align-items: flex-start; + justify-content: space-between; + padding-bottom: 10px; + border-bottom: 1px solid #a0cfff; + + & > span { + flex: 1; + } + & > div { + flex: 2; + text-align: center; + } + } + .item-cont { + width: 100%; + display: flex; + align-items: center; + justify-content: space-between; + padding: 10px 0; + border-bottom: 1px solid #c6e2ff; + + & > span { + flex: 1; + } + & > div { + flex: 2; + text-align: center; + + & > div { + text-align: left; + width: 100%; + display: flex; + justify-content: center; + align-items: flex-start; + margin-bottom: 10px; + span { + width: 50%; + &:first-of-type { + width: 25%; + } + } + } + } + &:last-of-type { + border-bottom: 0; + } + } + } + } + } + &:hover .card-header { + color: #0098f5; + } + &:hover .stepNum { + border: 2px solid #0098f5; + color: #0098f5; + } + } + .el-row { + display: flex; + align-items: center; + margin-bottom: 20px; + &:last-child { + margin-bottom: 0; + } + .grid-content { + align-items: center; + min-height: 36px; + } + + .topInfo { + display: flex; + align-items: center; + font-size: 16px; + font-weight: bold; + + & > div { + white-space: nowrap; + margin-right: 20px; + } + } + } + .el-card { + border: 0; + } +} +</style> diff --git a/src/views/specialWorkSystem/workTicket/wdsqjl/index.vue b/src/views/specialWorkSystem/workTicket/wdsqjl/index.vue new file mode 100644 index 0000000..9bf63b3 --- /dev/null +++ b/src/views/specialWorkSystem/workTicket/wdsqjl/index.vue @@ -0,0 +1,888 @@ +<template> + <div class="home-container"> +<!-- <el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">--> +<!-- <el-tab-pane label="申请中" name="1">--> + <div style="height: 100%"> + <el-row class="homeCard"> + <el-col :span="5" style="display:flex;align-items: center"> + <span style="white-space: nowrap">作业类型:</span> + <div class="grid-content topInfo"> + <el-select v-model="searchWord"> + <el-option + v-for="item in workType" + :key="item.id" + :label="item.name" + :value="item.id" + /> + </el-select> + </div> + </el-col> + <el-col :span="5" style="display:flex;align-items: center"> + <span style="white-space: nowrap">申请部门:</span> + <div class="grid-content topInfo"> + <el-cascader v-model="searchDep" :options="departmentList" :props="casProps" :show-all-levels="false"/> + </div> + </el-col> + <el-col :span="8" style="display:flex;align-items: center;"> + <span style="white-space: nowrap;margin-left: 20px">申请时间:</span> + <div class="grid-content topInfo"> + <el-date-picker + v-model="searchDate" + type="daterange" + unlink-panels + range-separator="至" + start-placeholder="开始日期" + end-placeholder="结束日期" + format="YYYY-MM-DD" value-format="YYYY-MM-DD HH:mm:ss" + /> + </div> + </el-col> + <el-button type="primary" style="margin-left: 20px" @click="searchRecord">查询</el-button> + <el-button plain @click="clearSearch">重置</el-button> + </el-row> + <div class="homeCard"> + <div class="main-card"> + <el-row class="cardTop"> + <el-col :span="12" class="mainCardBtn"> + <el-button type="primary" :icon="Plus" size="default" @click="toApply()">申请</el-button> + <!-- <el-button type="danger" :icon="Delete" size="default">删除</el-button>--> + <!-- <el-button type="success" size="default">设置分类</el-button>--> + </el-col> + <el-button type="primary" :icon="Refresh" size="default" @click="reLoadData()" /> + </el-row> + <el-table ref="multipleTableRef" :data="applyData" style="width: 100%" height="calc(100% - 100px)" :header-cell-style="{ background: '#fafafa' }"> + <el-table-column property="workPermitNo" label="作业申请单号" width="180" align="center"/> + <el-table-column property="applyUname" label="申请人" align="center"/> + <el-table-column property="depName" label="部门名称" align="center"/> + <el-table-column property="operators" label="作业人" align="center"/> + <el-table-column property="workTypeDesc" label="作业类型" align="center"/> + <el-table-column property="workLevelDesc" label="作业等级" align="center"/> + <el-table-column property="materialStatus" label="物资状态" align="center" width="180"> + <template #default="scope"> + <span>{{ scope.row.materialStatus==0?'未关联物资':(scope.row.materialStatus==1?'必选物资配备不足':(scope.row.materialStatus==2?'必选物资配备齐全':(scope.row.materialStatus==3?'物资配置专业':(scope.row.materialStatus==4?'物资配置高端':'-')))) }}</span> + </template> + </el-table-column> + <el-table-column property="applyTime" label="申请时间" width="180" align="center"/> + <el-table-column label="申请状态" align="center" width="180"> + <template #default="scope"> + <el-tag :type="scope.row.status==2?'success':(scope.row.status==8||scope.row.status==9)?'warning':'danger'">{{ scope.row.statusDesc }}</el-tag> + </template> + </el-table-column> + <el-table-column fixed="right" label="操作" align="center" width="250"> + <template #default="scope"> + <el-button link type="primary" size="small" :icon="View" @click="viewRecord(scope.row)">查看</el-button> + <el-button link type="success" size="small" :icon="Finished" @click="viewStatus(scope.row)">进度</el-button> + <el-button :disabled="scope.row.status == 7 ? false : true" link type="primary" size="small" :icon="Download" @click="downLoadBtn(scope.row)">导出作业票</el-button> + </template> + </el-table-column> + </el-table> + <div class="pageBtn"> + <el-pagination v-model:currentPage="pageIndex1" v-model:page-size="pageSize1" :page-sizes="[10, 15]" small="false" background layout="total, sizes, prev, pager, next, jumper" :total="totalSize1" @size-change="handleSizeChange1" @current-change="handleCurrentChange1" /> + </div> + </div> + </div> + </div> + <el-dialog v-model="dialogDetails" title="作业申请详情" center> + <fire v-if="dialogType == 1" :details = details></fire> + <space v-else-if="dialogType == 2" :details = details></space> + <hoist v-else-if="dialogType == 3" :details = details></hoist> + <ground v-else-if="dialogType == 4" :details = details></ground> + <broken v-else-if="dialogType == 5" :details = details></broken> + <height v-else-if="dialogType == 6" :details = details></height> + <power v-else-if="dialogType == 7" :details = details></power> + <plate v-else :details = details></plate> + <template #footer> + <span class="dialog-footer"> + <el-button type="primary" @click="dialogDetails = false" + >确认</el-button + > + </span> + </template> + </el-dialog> + <el-dialog v-model="dialogStatus" title="作业申请进度" width="60%"> + <el-form v-if="approveInfo.operators.length > 0" style="margin-bottom: 40px"> + <el-form-item label="申请作业人"> + <el-input v-model="approveInfo.operators" readonly type="textarea" /> + </el-form-item> + </el-form> + <div style="display: flex; flex-direction: column-reverse"> + <div v-for="(item, index) in approveInfo.approvalSteps" class="stepItem"> + <div class="stepNum">{{ item.stepSerial }}</div> + <div class="stepCard"> + <el-card class="box-card" shadow="always"> + <div class="text"> + 审批结果:<span>{{ item.approvalResultDesc }}</span> + </div> + <div class="text"> + 审批层级:<span>{{ item.typeDesc }}</span> + </div> + <div class="text" v-if="item.auditTypeDesc"> + 审批类型:<span>{{ item.auditTypeDesc }}</span> + </div> + <div class="text" v-show="item.startApprovalTime != null"> + 开始时间:<span>{{ item.startApprovalTime }}</span> + </div> + <div class="approveUnit"> + <div class="item-tit"><span>审批人</span><span>审批状态</span></div> + <div class="item-cont" v-for="i in item.stepUnits"> + <span>{{ i.approvalUname }}</span + ><span>{{ i.resultDesc }}</span> + </div> + </div> + <div class="approveItem"> + <div class="item-tit"> + <span>审批项目</span> +<!-- <span>类型</span>--> + <div>措施标准</div> + </div> + <div class="item-cont" v-for="i in item.stepItems"> + <span>{{ i.itemName }}</span> +<!-- <span>{{ i.typeDesc }}</span>--> + <div v-if="i.measure !== null"> + <div> + <span>作业类型:</span><span>{{ i.measure.workTypeDesc }}</span> + </div> + <div> + <span>措施内容:</span><span>{{ i.measure.context }}</span> + </div> + </div> + <div v-if="i.stand !== null"> + <div> + <span>标题名称:</span><span>{{ i.stand.title }}</span> + </div> + <div> + <span>标准内容:</span><span>{{ i.stand.typeDesc }}</span> + </div> + </div> + </div> + </div> + <div class="text" v-show="item.expFinishApprovalTime != null"> + 期望结束时间:<span>{{ item.expFinishApprovalTime }}</span> + </div> + <div class="text" v-show="item.finishApprovalTime != null"> + 结束时间:<span>{{ item.finishApprovalTime }}</span> + </div> + </el-card> + </div> + </div> + </div> + </el-dialog> + <el-dialog v-model="downLoadDialog" title="提示" width="30%" center> + <span>您确定要导出该条记录吗?</span> + <template #footer> + <span class="dialog-footer"> + <el-button @click="downLoadDialog = false" size="default">取消</el-button> + <el-button type="primary" @click="conFirmDownLoad" size="default">确认</el-button> + </span> + </template> + </el-dialog> +<!-- </el-tab-pane>--> +<!-- <el-tab-pane label="已通过" name="2">--> +<!-- <div style="height: 100%">--> +<!-- <el-row class="homeCard">--> +<!-- <el-col :span="8">--> +<!-- <div class="grid-content topInfo">--> +<!-- <el-input v-model="searchWord" placeholder="作业证名称"></el-input>--> +<!-- <el-button type="primary">查询</el-button>--> +<!-- <el-button plain>重置</el-button>--> +<!-- </div>--> +<!-- </el-col>--> +<!-- </el-row>--> +<!-- <div class="homeCard">--> +<!-- <div class="main-card">--> +<!-- <el-table ref="multipleTableRef" :data="passedData" style="width: 100%" height="calc(100% - 48px)" :header-cell-style="{ background: '#fafafa' }" @selection-change="handleSelectionChange">--> +<!-- <el-table-column type="selection" width="55" />--> +<!-- <el-table-column type="index" label="编号" width="200" />--> +<!-- <el-table-column property="level" label="作业证等级" width="180" sortable />--> +<!-- <el-table-column property="applyDate" label="申请日期" sortable />--> +<!-- <el-table-column property="name" label="申请人" width="180" />--> +<!-- <el-table-column property="department" label="申请部门" width="180" />--> +<!-- <el-table-column label="申请状态" width="180">--> +<!-- <template #default="scope">--> +<!-- <el-tag type="success">{{ scope.row.status }}</el-tag>--> +<!-- </template>--> +<!-- </el-table-column>--> +<!-- </el-table>--> +<!-- <div class="pageBtn">--> +<!-- <el-pagination v-model:currentPage="pageIndex2" v-model:page-size="pageSize2" :page-sizes="[10, 15]" small="false" background layout="total, sizes, prev, pager, next, jumper" :total="totalSize2" @size-change="handleSizeChange2" @current-change="handleCurrentChange2" />--> +<!-- </div>--> +<!-- </div>--> +<!-- </div>--> +<!-- </div>--> +<!-- </el-tab-pane>--> +<!-- </el-tabs>--> + </div> +</template> + +<script lang="ts"> +import {toRefs, reactive, defineComponent, ref, onMounted, defineAsyncComponent} from 'vue'; +import { storeToRefs } from 'pinia'; +import { initBackEndControlRoutes } from '/@/router/backEnd'; +import { useUserInfo } from '/@/stores/userInfo'; +import { Session } from '/@/utils/storage'; +import { useRouter } from 'vue-router'; +import { Edit, View, Plus, Delete, Refresh, Search, Finished, Download } from '@element-plus/icons-vue'; +import { ElTable } from 'element-plus'; +import { FormInstance, FormRules, ElMessage } from 'element-plus'; +import { workApplyApi } from '/@/api/specialWorkSystem/workApply'; +import type { TabsPaneContext } from 'element-plus'; +import {teamManageApi} from "/@/api/systemManage/basicDateManage/personShiftManage/teamManage"; +import Cookies from 'js-cookie'; +import axios from 'axios'; + +// 定义接口来定义对象的类型 +interface stateType { + applyData: Array<string>; + workTimeList: Array<string>; + multipleSelection: Array<any>; + deleteArr: Array<any>; + casProps: {}; + approveInfo: Object; + dialogDetails: boolean; + dialogStatus: boolean; + deleteDialog: boolean; + downLoadDialog: boolean; + pageIndex1: number; + pageSize1: number; + chosenIndex: null | number; + deleteId: null | number; + downLoadId: null | number; + downLoadName: string; + searchWord: number | null; + searchDep: number | null; + searchDate: Array<any>, + totalSize1: number; + activeName: string; + addRecord: {}; + details: {}; + statusInfo: {}; + workType: Array<type>; + dialogType: number | null; + departmentList: Array<any>; + departmentRecursionList: Array<DepartmentState>; +} +interface type { + id: number; + name: string; +} +interface DepartmentState { + depId: number; + depName: string; +} +export default defineComponent({ + name: 'myApply', + components: { + fire: defineAsyncComponent(() => import('/@/views/specialWorkSystem/workTicket/wdsq/components/fireLog.vue')), + space: defineAsyncComponent(() => import('/@/views/specialWorkSystem/workTicket/wdsq/components/spaceLog.vue')), + hoist: defineAsyncComponent(() => import('/@/views/specialWorkSystem/workTicket/wdsq/components/hoistLog.vue')), + ground: defineAsyncComponent(() => import('/@/views/specialWorkSystem/workTicket/wdsq/components/groundLog.vue')), + broken: defineAsyncComponent(() => import('/@/views/specialWorkSystem/workTicket/wdsq/components/brokenLog.vue')), + height: defineAsyncComponent(() => import('/@/views/specialWorkSystem/workTicket/wdsq/components/heightLog.vue')), + power: defineAsyncComponent(() => import('/@/views/specialWorkSystem/workTicket/wdsq/components/powerLog.vue')), + plate: defineAsyncComponent(() => import('/@/views/specialWorkSystem/workTicket/wdsq/components/plateLog.vue')) + }, + setup() { + const userInfo = useUserInfo(); + const { userInfos } = storeToRefs(userInfo); + const router = useRouter(); + const state = reactive<stateType>({ + pageIndex1: 1, + pageSize1: 10, + totalSize1: 0, + dialogType: null, + activeName: '1', + departmentList: [], + departmentRecursionList: [], + chosenIndex: null, + searchWord: null, + searchDep: null, + searchDate: [], + applyData: [], + workTimeList: [], + multipleSelection: [], + approveInfo: { + approvalSteps: [], + operators: [] + }, + casProps: { + expandTrigger: 'hover', + emitPath: false, + value: 'depId', + label: 'depName', + checkStrictly: true + }, + dialogDetails: false, + dialogStatus: false, + deleteDialog: false, + downLoadDialog: false, + addRecord: {}, + details: {}, + statusInfo: {}, + deleteId: null, + downLoadId: null, + downLoadName: '', + deleteArr: [], + workType: [ + { id: 1, name: '动火作业' }, + { id: 2, name: '受限空间作业' }, + { id: 3, name: '吊装作业' }, + { id: 4, name: '动土作业' }, + { id: 5, name: '断路作业' }, + { id: 6, name: '高处作业' }, + { id: 7, name: '临时用电作业' }, + { id: 8, name: '盲板抽堵作业' } + ] + }); + interface User { + name: string; + list: []; + info: string; + } + + // 刷新 + const reLoadData = async () => { + getListByPage(); + }; + + // 填写表单 + const toApply = () => { + router.push({ + path: 'zysq' + }); + }; + + const handleClick = (tab: TabsPaneContext, event: Event) => { + }; + + // 获取部门列表 + const getAllDepartment = async () => { + let res = await teamManageApi().getAllDepartment(); + if (res.data.code === '200') { + state.departmentList = JSON.parse(JSON.stringify(res.data.data)) + // recursion(state.departmentList); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // const recursion = (value: any) => { + // for (let i of value) { + // if (i.children.length !== 0) { + // state.departmentRecursionList.push(i); + // recursion(i.children); + // } else { + // state.departmentRecursionList.push(i); + // } + // } + // }; + + // 分页获取列表 + const getListByPage = async () => { + const dateRange = JSON.parse(JSON.stringify(state.searchDate)) + if(dateRange[1]){dateRange[1] = dateRange[1].replace('00:00:00','23:59:59')} + const data = { pageSize: state.pageSize1, pageIndex: state.pageIndex1, searchParams: { workType: state.searchWord, applyDepId: state.searchDep,applyStartTime: dateRange[0],applyEndTime: dateRange[1]} }; + let res = await workApplyApi().getApplyList(data); + if (res.data.code === '200') { + state.applyData = JSON.parse(JSON.stringify(res.data.data)); + state.applyData = state.applyData.map((item) => { + if (item.operators == null || item.operators == []) { + item.operators = []; + } else { + item.operators = Array.from(item.operators, ({ operatorUname }) => operatorUname); + } + return item; + }); + state.totalSize1 = res.data.total; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 表格数据格式化 + const toNames = (row, column, cellValue, index) => { + if (row.list == []) { + return []; + } else { + const nameList = []; + for (let i = 0; i < row.list.length; i++) { + for (let t = 0; t < state.workTimeList.length; t++) { + if (row.list[i] == state.workTimeList[t].id) { + nameList.push(state.workTimeList[t].name); + } + } + } + return nameList.join(); + } + }; + + // 关键词查询记录 + const searchRecord = async () => { + if (state.searchWord == null && state.searchDep == null && state.searchDate == []) { + ElMessage({ + type: 'warning', + message: '请输入查询关键词' + }); + } else { + getListByPage(); + } + }; + // 重置搜索 + const clearSearch = async () => { + state.searchWord = null; + state.searchDep = null; + state.searchDate = [] + getListByPage(); + }; + + // 查看进度 + const viewStatus = (row) => { + getStatus({ workApplyId: row.workApplyId }); + }; + + // 查询进度方法 + const getStatus = async (data: any) => { + let res = await workApplyApi().getAllStatus(data); + if (res.data.code === '200') { + state.approveInfo = JSON.parse(JSON.stringify(res.data.data)); + state.approveInfo.operators = Array.from(state.approveInfo.operators, ({ operatorUname }) => operatorUname); + state.dialogStatus = true; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + const deleteRecordBtn = (row) => { + state.deleteId = row.workApplyId; + state.deleteDialog = true; + }; + + // 导出图表 + const downLoadBtn = (row:any) =>{ + state.downLoadId = row.workApplyId; + state.downLoadName = row.workTypeDesc + row.workPermitNo + state.downLoadDialog = true; + } + + // 导出方法 + const downLoadRecord = async (data: any) => { + // let res = await workApplyApi().postPrinting(data); + axios.post(import.meta.env.VITE_API_URL + `/work/apply/printingPdf`,data,{headers:{'Content-Type': 'application/json','Authorization': `${Cookies.get('token')}`,'uid':`${Cookies.get('uid')}`},responseType: 'blob'}).then(res=>{ + if (res) { + const link = document.createElement('a') + let blob = new Blob([res.data],{type: 'application/pdf'}) + link.style.display = "none"; + link.href = URL.createObjectURL(blob); // 创建URL + link.setAttribute("download", state.downLoadName + "作业证.pdf"); + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + } else { + ElMessage({ + type: 'warning', + message: '导出失败' + }); + } + }) + + }; + + const conFirmDownLoad = () => { + downLoadRecord({ applyWorkId: state.downLoadId }); + state.downLoadDialog = false; + }; + + const handleSizeChange1 = (val: number) => { + state.pageSize1 = val; + getListByPage(); + }; + const handleCurrentChange1 = (val: number) => { + state.pageIndex1 = val; + getListByPage(); + }; + + // 查看记录 + const viewRecord = (row: any) => { + state.dialogType = row.workType + state.details = JSON.parse(JSON.stringify(row)); + if(state.details.workDetail.otherSpecialWork == '' || !state.details.workDetail.otherSpecialWork){ + state.details.workDetail.otherSpecialWork=[] + } + else { + const a = state.details.workDetail.otherSpecialWork + state.details.workDetail.otherSpecialWork = a.split(',').map((item) => { + return state.workType.find((i: { id: number }) => i.id === Number(item))?.name; + }); + } + if(state.details.workDetail.involvedDepIds == '' || !state.details.workDetail.involvedDepIds){ + state.details.workDetail.involvedDepIds=[] + } + else { + const a = state.details.workDetail.involvedDepIds + state.details.workDetail.involvedDepIds = a.split(',').map((item) => { + return state.departmentRecursionList.find((i: { depId: number }) => i.depId === Number(item))?.depName; + }); + } + if(state.details.workDetail.csDepId){ + state.details.workDetail.csDepId = state.departmentRecursionList.find((i: { depId: number }) => i.depId === Number(state.details.workDetail.csDepId))?.depName; + } + if(state.details.workDetail.operationDepId){ + state.details.workDetail.operationDepId = state.departmentRecursionList.find((i: { depId: number }) => i.depId === Number(state.details.workDetail.operationDepId))?.depName; + } + if(state.details.workDetail.gbPath){ + state.details.workDetail.gbPath = state.details.workDetail.gbPath.split(',') + } + if(state.details.workDetail.bcPath){ + state.details.workDetail.bcPath = state.details.workDetail.bcPath.split(',') + } + if(state.details.workDetail.bpLocationMapPath){ + state.details.workDetail.bpLocationMapPath = state.details.workDetail.bpLocationMapPath.split(',') + } + state.dialogDetails = true; + }; + + // 折线图 + const renderMenu = async (value: string) => { + Session.set('projectId', value); + userInfos.value.projectId = value; + await initBackEndControlRoutes(); + }; + + // 页面载入时执行方法 + onMounted(() => { + getListByPage(); + getAllDepartment() + }); + + return { + View, + Edit, + Delete, + Refresh, + Plus, + Finished, + Download, + reLoadData, + toApply, + handleClick, + toNames, + searchRecord, + clearSearch, + viewRecord, + viewStatus, + deleteRecordBtn, + downLoadBtn, + conFirmDownLoad, + getListByPage, + handleSizeChange1, + handleCurrentChange1, + ...toRefs(state) + }; + } +}); +</script> + +<style scoped lang="scss"> +$homeNavLengh: 8; +.home-container { + height: calc(100vh - 144px); + box-sizing: border-box; + overflow: hidden; + .demo-tabs { + width: 100%; + height: 100%; + + &::v-deep(.el-tabs__content) { + height: calc(100% - 60px); + } + + .el-tab-pane { + height: 100%; + } + } + .homeCard { + width: 100%; + padding: 20px; + box-sizing: border-box; + background: #fff; + border-radius: 4px; + + .main-card { + width: 100%; + height: 100%; + .cardTop { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 20px; + .mainCardBtn { + margin: 0; + } + } + .pageBtn { + height: 60px; + display: flex; + align-items: center; + justify-content: right; + + .demo-pagination-block + .demo-pagination-block { + margin-top: 10px; + } + .demo-pagination-block .demonstration { + margin-bottom: 16px; + } + } + } + &:last-of-type { + height: calc(100% - 100px); + } + } + .stepItem { + display: flex; + align-items: flex-start; + margin-top: 30px; + margin-left: 30px; + padding-bottom: 30px; + padding-left: 40px; + border-left: 1px solid #a0cfff; + position: relative; + &:first-of-type { + margin-top: 30px; + } + &:first-of-type { + margin-bottom: 0; + border-left: none; + } + .stepNum { + position: absolute; + width: 40px; + height: 40px; + border-radius: 20px; + box-sizing: border-box; + font-size: 18px; + color: #333; + border: 1px solid #a0cfff; + line-height: 38px; + text-align: center; + left: -20px; + top: -30px; + background: #d9ecff; + } + .stepCard { + width: 100%; + margin-top: -30px; + + .box-card { + width: 100%; + + .card-header { + display: flex; + justify-content: space-between; + align-items: center; + + span { + font-weight: bold; + margin-left: 10px; + } + } + + .text { + width: 100%; + font-size: 14px; + margin-bottom: 10px; + padding-left: 10px; + + span { + font-weight: bolder; + color: #409eff; + } + + &:last-of-type { + margin-bottom: 0; + } + } + .approveUnit { + width: 100%; + font-size: 14px; + margin-bottom: 20px; + padding: 10px 15px; + border: 1px solid #fff; + background: #ecf8ff; + border-radius: 6px; + .item-tit { + width: 100%; + display: flex; + color: #409eff; + align-items: flex-start; + justify-content: space-between; + padding-bottom: 10px; + border-bottom: 1px solid #a0cfff; + + & > span { + flex: 1; + &:last-of-type{ + text-align: center; + } + } + & > div { + flex: 1; + text-align: center; + } + } + .item-cont { + width: 100%; + display: flex; + align-items: center; + justify-content: space-between; + padding: 10px 0; + border-bottom: 1px solid #c6e2ff; + + & > span { + flex: 1; + &:last-of-type{ + text-align: center; + } + } + & > div { + flex: 1; + text-align: center; + + & > div { + text-align: left; + width: 100%; + display: flex; + justify-content: center; + align-items: center; + span { + width: 45%; + &:first-of-type { + width: 30%; + } + } + } + } + &:last-of-type { + border-bottom: 0; + } + } + } + .approveItem { + width: 100%; + font-size: 14px; + margin-bottom: 20px; + padding: 10px 15px; + background: #ecf8ff; + border: 1px solid #fff; + border-radius: 6px; + .item-tit { + width: 100%; + display: flex; + color: #409eff; + align-items: flex-start; + justify-content: space-between; + padding-bottom: 10px; + border-bottom: 1px solid #a0cfff; + + & > span { + flex: 1; + } + & > div { + flex: 2; + text-align: center; + } + } + .item-cont { + width: 100%; + display: flex; + align-items: center; + justify-content: space-between; + padding: 10px 0; + border-bottom: 1px solid #c6e2ff; + + & > span { + flex: 1; + } + & > div { + flex: 2; + text-align: center; + + & > div { + text-align: left; + width: 100%; + display: flex; + justify-content: center; + align-items: flex-start; + margin-bottom: 10px; + span { + width: 50%; + &:first-of-type { + width: 25%; + } + } + } + } + &:last-of-type { + border-bottom: 0; + } + } + } + } + } + &:hover .card-header { + color: #0098f5; + } + &:hover .stepNum { + border: 2px solid #0098f5; + color: #0098f5; + } + } + .el-row { + display: flex; + align-items: center; + margin-bottom: 20px; + &:last-child { + margin-bottom: 0; + } + .grid-content { + align-items: center; + min-height: 36px; + } + + .topInfo { + width: 100%; + display: flex; + align-items: center; + font-size: 16px; + font-weight: bold; + + & > div { + white-space: nowrap; + margin-right: 20px; + } + } + } +} +.el-card { + border: 0; +} +.el-input{ + width: 100% !important; +} +::v-deep(.el-date-editor){ + width: 100%; +} +.el-select{ + width: 100%; +} +:deep(.el-cascader){ + width: 100% !important; +} +</style> diff --git a/src/views/specialWorkSystem/workTicket/zysq/components/broken.vue b/src/views/specialWorkSystem/workTicket/zysq/components/broken.vue new file mode 100644 index 0000000..da141bb --- /dev/null +++ b/src/views/specialWorkSystem/workTicket/zysq/components/broken.vue @@ -0,0 +1,504 @@ +<template> + <div class="home-container"> + <div style="height: 100%"> + <el-form :model="form" label-width="150px" :rules="applyRules" ref="ruleFormRef"> + <div class="homeCard"> + <el-row> + <el-col :span="12"> + <el-form-item label="作业人" prop="operatorUids"> + <el-select v-model="form.operatorUids" multiple> + <el-option + v-for="item in workerList" + :key="item.uid" + :label="item.username" + :value="item.uid" + /> + </el-select> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="作业时间" prop="workTimeLine"> + <el-date-picker + v-model="form.workTimeLine" + format="YYYY-MM-DD HH:mm" + value-format="YYYY-MM-DD HH:mm:00" + type="datetimerange" + range-separator="至" + start-placeholder="开始时间" + end-placeholder="结束时间" + /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="作业内容" prop="workContent"> + <el-input + v-model="form.workContent" + autosize + type="textarea" + placeholder="请输入作业内容" + /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="作业地址" prop="workLocation"> + <el-input + v-model="form.workLocation" + autosize + type="textarea" + placeholder="请输入作业地址" + /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="危害辨识" prop="hazardIdentification"> + <el-input + v-model="form.hazardIdentification" + placeholder="请输入危害辨识" + /> + </el-form-item> + </el-col> + </el-row> + <el-divider border-style="dashed"/> + <el-row> + <el-col :span="12"> + <el-form-item label="作业单位" prop="workDetail.operationDepId"> +<!-- <el-select v-model="form.workDetail.operationDepId">--> +<!-- <el-option--> +<!-- v-for="item in csDepList"--> +<!-- :key="item.value"--> +<!-- :label="item.label"--> +<!-- :value="item.value"--> +<!-- />--> +<!-- </el-select>--> + <el-cascader v-model="form.workDetail.operationDepId" :options="departList" :props="casProps2" :show-all-levels="false" @change="handleChange2" /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="断路原因" prop="workDetail.bcReason"> + <el-input + v-model="form.workDetail.bcReason" + autosize + type="textarea" + placeholder="请输入" + /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="断路地段说明" prop="workDetail.bcExplain"> + <el-input + v-model="form.workDetail.bcExplain" + autosize + type="textarea" + placeholder="请输入" + /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="涉及相关部门" prop="workDetail.involvedDepIds"> + <el-cascader v-model="form.workDetail.involvedDepIds" :options="departList" :props="casProps" :show-all-levels="false" @change="handleChange" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="24"> + <el-form-item label="图片上传" prop="workDetail.bcPath"> + <el-upload accept="image/*" :on-exceed="showTip" :on-preview="handlePictureCardPreview" :limit='imgLimit' v-model:file-list="fileList" :http-request="upload" :action="uploadUrl" list-type="picture-card" :on-remove="handleRemove" :before-remove="beforeRemove" :before-upload="getUploadUrl"> + <el-icon><Plus /></el-icon> + <template #tip> + <div class="el-upload__tip">上传jpg/png图片尺寸小于500KB,最多可上传3张</div> + </template> + </el-upload> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="选择关联物资"> + <el-button type="primary" @click="openMaList">选择物资标准</el-button> + </el-form-item> + </el-col> + </el-row> + </div> + </el-form> + <material-dialog ref="material" @conFirmMaterials="conFirmMaterials"></material-dialog> + <div class="applyBtn"> + <el-button type="primary" size="large" plain @click="submitForm(ruleFormRef)">发起申请</el-button> + </div> + </div> + <el-dialog v-model="dialogVisible"> + <img w-full :src="dialogImageUrl" alt="Preview Image" /> + </el-dialog> + </div> +</template> + +<script lang="ts"> +import {toRefs, reactive, defineComponent, ref, defineAsyncComponent} from 'vue'; + import { storeToRefs } from 'pinia'; + import { initBackEndControlRoutes } from '/@/router/backEnd'; + import {useUserInfo} from "/@/stores/userInfo"; + import { Session } from '/@/utils/storage'; + import { Search } from '@element-plus/icons-vue' + import { ElMessage, ElMessageBox } from 'element-plus' + import type { FormInstance, FormRules, UploadProps, UploadUserFile } from 'element-plus' + import { workApplyApi } from '/@/api/specialWorkSystem/workApply'; + import axios from 'axios'; + + interface stateType { + form: Object, + csDepList: Array<any>, + fileList: Array<file>, + uploadUrl: string, + dialogVisible: Boolean, + dialogImageUrl: string | null, + imgLimit: number, + casProps: {}, + casProps2: {}, + isOverSize: boolean, + } + interface file { + url: string; + } + export default defineComponent({ + name: 'brokenForm', + components: { + materialDialog: defineAsyncComponent(() => import('/@/views/specialWorkSystem/workTicket/zysq/components/materialDialog.vue')), + }, + props:['workerList','departList'], + setup(props: any, context: any) { + const userInfo = useUserInfo() + const { userInfos } = storeToRefs(userInfo); + const state = reactive<stateType>({ + form: { + operatorUids: [], + workType: 5, + workLevel: 0, + workContent: '', + workLocation: '', + hazardIdentification: '', + maBaseId: null, + workDetail:{ + operationDepId: null, + bcReason: '', + bcExplain: '', + bcPath: [], + involvedDepIds: [] + }, + receiveUids: [], + workTimeLine: [], + expStartTime: '', + expEndTime: '' + }, + isOverSize: false, + fileList: [], + imgLimit: 3, + uploadUrl: '', + dialogVisible: false, + dialogImageUrl: null, + csDepList: [ + { + label: "单位一", + value: 1 + }, + { + label: "单位二", + value: 2 + }, + { + label: "单位三", + value: 3 + }, + { + label: "单位四", + value: 4 + }, + { + label: "单位五", + value: 5 + }, + { + label: "单位六", + value: 6 + } + ], + casProps: { + emitPath: false, + value: 'depId', + label: 'depName', + multiple: true, + expandTrigger: 'hover' + }, + casProps2: { + emitPath: false, + value: 'depId', + label: 'depName', + multiple: false, + expandTrigger: 'hover', + checkStrictly: true + } + }); + const material = ref() + const ruleFormRef = ref<FormInstance>() + const applyRules = reactive<FormRules>({ + operatorUids: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + workType: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + workContent: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + workLocation: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + hazardIdentification: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + workTimeLine: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + "workDetail.operationDepId": [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + "workDetail.bcReason": [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + "workDetail.bcExplain": [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + "workDetail.bcPath": [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + "workDetail.involvedDepIds": [{ required: true, message: '该内容不能为空', trigger: 'blur' }] + }); + + // const toZero = (value: string | number,index: number,name: string,x:number) =>{ + // if(!value){ + // state.materialList[index][name][x].value = 0 + // } + // } + + const openMaList = ()=>{ + if(state.form.operatorUids == []){ + ElMessage({ + type: 'warning', + message: '请先选择作业人再获取相应物资配置' + }); + }else{ + if(material.value.receiveUids.length==0){ + material.value.receiveUids = state.form.operatorUids + } + material.value.getMaList(state.form.workType,state.form.workLevel) + material.value.workerList = props.workerList + } + } + const conFirmMaterials = (receiveUids: Array<number>,chosenId: number) =>{ + state.form.maBaseId = null + state.form.receiveUids = [] + state.form.receiveUids = receiveUids + state.form.maBaseId = chosenId + } + + const submitForm = async (formEl: FormInstance | undefined) => { + if (!formEl) return + await formEl.validate(async (valid, fields) => { + if (valid) { + // if (state.form.wmAddReqDTOList == null || state.form.wmAddReqDTOList.length == 0){ + // ElMessage({ + // type: 'warning', + // message: '请确认关联物资的配置' + // }); + // return + // } + state.form.expStartTime = JSON.parse(JSON.stringify(state.form.workTimeLine))[0] + state.form.expEndTime = JSON.parse(JSON.stringify(state.form.workTimeLine))[1] + let { workTimeLine, ...data } = JSON.parse(JSON.stringify(state.form)) + data.workDetail.involvedDepIds = data.workDetail.involvedDepIds.join(',') + data.workDetail.bcPath = data.workDetail.bcPath.join(',') + const res = await workApplyApi().postBrokenApply(data) + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '提交成功!' + }); + formEl.resetFields() + state.form.workDetail.bcPath = [] + state.fileList = [] + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + material.value.maBaseId = null + material.value.receiveUids = [] + } else { + console.log('error submit!', fields) + } + }) + } + + const handlePreview: UploadProps['onPreview'] = (uploadFile) => { + console.log(uploadFile); + }; + + const handlePictureCardPreview = (uploadFile: { url: string }) => { + state.dialogImageUrl = uploadFile.url!; + state.dialogVisible = true; + }; + + const getUploadUrl = async (rawFile: any) => { + const fileSize = rawFile.size / 1024 < 500 ? '1' : '0' + if(fileSize === '0'){ + ElMessage({ + type: 'warning', + message: '文件大小不能超过500k。' + }); + state.isOverSize = true + return false + }else{ + const res = await workApplyApi().getUploadUrl(rawFile.name); + state.form.workDetail.bcPath.push(res.data.data.fileName) + state.uploadUrl = res.data.data.uploadUrl; + console.log(res.data.data.fileName,'name') + } + }; + + const upload = async (params: any) => { + // const formData = new FormData(); + // formData.append('file', state.fileList[0].raw); + let reader = new FileReader(); + reader.readAsArrayBuffer(params.file); + reader.onload = async () => { + axios + .put(state.uploadUrl, reader.result, { + header: { 'Content-Type': 'multipart/form-data' } + }) + .then(() => { + // if (state.fileList.length === 2) { + // state.fileList.splice(0, 1); + // } + // console.log(state.form.workDetail.bcPath,'bcPath') + }); + }; + }; + + const beforeRemove = (file: {}, fileList: []) => { + const result = new Promise((resolve, reject) => { + if(!state.isOverSize){ + ElMessageBox.confirm('此操作将删除该图片, 是否继续?', '提示', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning' + }) + .then(() => { + // console.log(state.workDetail.bcPath,'path') + const list = JSON.parse(JSON.stringify(state.form.workDetail.bcPath)) + fileList.map((item,index)=>{ + if(item.uid === file.uid){ + fileList.splice(index,1) + state.form.workDetail.bcPath.splice(index,1) + deletePic(false,list[index]) + } + }) + // 请求删除接口 + }) + .catch(() => { + reject(false); + }); + }else{ + const list = JSON.parse(JSON.stringify(state.form.workDetail.bcPath)) + fileList.map((item,index)=>{ + if(item.uid === file.uid){ + fileList.splice(index,1) + state.form.workDetail.bcPath.splice(index,1) + deletePic(true,list[index]) + } + }) + state.isOverSize = false + } + }); + return result; + }; + + + // 删除图片接口 + const deletePic = async(isOverSize:boolean,fileName:string)=>{ + console.log(fileName,'fileName') + const res = await workApplyApi().deleteFile({fileName: fileName}) + if (res.data.code === '200') { + ElMessage({ + type: isOverSize ? 'error' : 'success', + message: isOverSize ? '上传失败':'删除成功!' + }); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } + + const showTip =()=>{ + ElMessage({ + type: 'warning', + message: '超出文件上传数量' + }); + } + + // 折线图 + const renderMenu = async (value: string) => { + Session.set('projectId',value) + userInfos.value.projectId = value + await initBackEndControlRoutes(); + }; + return { + renderMenu, + Search, + ruleFormRef, + applyRules, + material, + conFirmMaterials, + openMaList, + handlePreview, + getUploadUrl, + beforeRemove, + upload, + showTip, + submitForm, + handlePictureCardPreview, + ...toRefs(state), + }; + }, + }); +</script> + +<style scoped lang="scss"> + .home-container { + height: 100%; + overflow: hidden; + position: relative; + .homeCard{ + width: 100%; + padding: 20px; + box-sizing: border-box; + background: #fff; + border-radius: 4px; + margin-bottom: 20px; + } + .applyBtn{ + width: 100%; + background: #fff; + padding-top: 15px; + z-index: 5; + box-shadow: 0 -3px 8px rgba(150,150,150,.1); + display: flex; + align-items: center; + justify-content: center; + } + .el-row{ + margin-bottom: 20px; + } + .el-row:last-child { + margin-bottom: 0; + } + .el-input{ + width: 100% !important; + } + .el-date-editor::v-deep{ + width: 100%; + } + .el-select{ + width: 100%; + } + :deep(.el-cascader){ + width: 100% !important; + } + } +</style> diff --git a/src/views/specialWorkSystem/workTicket/zysq/components/fire.vue b/src/views/specialWorkSystem/workTicket/zysq/components/fire.vue new file mode 100644 index 0000000..9af9738 --- /dev/null +++ b/src/views/specialWorkSystem/workTicket/zysq/components/fire.vue @@ -0,0 +1,366 @@ +<template> + <div class="home-container"> + <div style="height: 100%"> + <el-form :model="form" label-width="150px" :rules="applyRules" ref="ruleFormRef"> + <div class="homeCard"> + <el-row> + <el-col :span="12"> + <el-form-item label="作业人" prop="operatorUids"> + <el-select v-model="form.operatorUids" multiple> + <el-option + v-for="item in workerList" + :key="item.uid" + :label="item.username" + :value="item.uid" + /> + </el-select> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="作业时间" prop="workTimeLine"> + <el-date-picker + v-model="form.workTimeLine" + format="YYYY-MM-DD HH:mm" + value-format="YYYY-MM-DD HH:mm:00" + type="datetimerange" + range-separator="至" + start-placeholder="开始时间" + end-placeholder="结束时间" + /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="作业等级" prop="workLevel"> + <el-select v-model="form.workLevel"> + <el-option + v-for="item in workLevelList" + :key="item.value" + :label="item.label" + :value="item.value" + /> + </el-select> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="作业内容" prop="workContent"> + <el-input + v-model="form.workContent" + autosize + type="textarea" + placeholder="请输入作业内容" + /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="作业地址" prop="workLocation"> + <el-input + v-model="form.workLocation" + autosize + type="textarea" + placeholder="请输入作业地址" + /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="危害辨识" prop="hazardIdentification"> + <el-input + v-model="form.hazardIdentification" + placeholder="请输入危害辨识" + /> + </el-form-item> + </el-col> + </el-row> + <el-divider border-style="dashed"/> + <el-row> + <el-col :span="12"> + <el-form-item label="动火方式" prop="workDetail.hotMethod"> + <el-input + v-model="form.workDetail.hotMethod" + autosize + type="textarea" + placeholder="请输入动火方式" + /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="关联作业" prop="workDetail.otherSpecialWork"> + <el-select v-model="form.workDetail.otherSpecialWork" multiple> + <el-option + v-for="item in otherWorkList" + :key="item.value" + :label="item.label" + :value="item.value" + /> + </el-select> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="选择关联物资"> + <el-button type="primary" @click="openMaList">选择物资标准</el-button> + </el-form-item> + </el-col> + </el-row> + </div> + </el-form> + <material-dialog ref="material" @conFirmMaterials="conFirmMaterials"></material-dialog> + <div class="applyBtn"> + <el-button type="primary" size="large" plain @click="submitForm(ruleFormRef)">发起申请</el-button> + </div> + </div> + </div> +</template> + +<script lang="ts"> + import { toRefs, reactive, defineComponent, ref, defineAsyncComponent, onMounted } from 'vue'; + import { storeToRefs } from 'pinia'; + import { initBackEndControlRoutes } from '/@/router/backEnd'; + import {useUserInfo} from "/@/stores/userInfo"; + import { Session } from '/@/utils/storage'; + import { Search } from '@element-plus/icons-vue' + import { ElMessage, ElMessageBox } from 'element-plus' + import type { FormInstance, FormRules } from 'element-plus' + import { workApplyApi } from '/@/api/specialWorkSystem/workApply'; + interface stateType { + form: Object, + workLevelList: Array<any>, + otherWorkList: Array<any>, + equipmentDialog: boolean + } + export default defineComponent({ + name: 'fireForm', + components: { + materialDialog: defineAsyncComponent(() => import('/@/views/specialWorkSystem/workTicket/zysq/components/materialDialog.vue')), + }, + props:['workerList'], + setup(props: any, context: any) { + const userInfo = useUserInfo() + const { userInfos } = storeToRefs(userInfo); + const state = reactive<stateType>({ + equipmentDialog: false, + form: { + operatorUids: [], + workType: 1, + workLevel: null, + workContent: '', + workLocation: '', + maBaseId: null, + hazardIdentification: '', + workDetail:{ + hotMethod: '', + otherSpecialWork: [] + }, + receiveUids: [], + workTimeLine: [], + expStartTime: '', + expEndTime: '' + }, + workLevelList: [ + { + label: "一级动火作业", + value: 1 + }, + { + label: "二级动火作业", + value: 2 + }, + { + label: "特级动火作业", + value: 3 + } + ], + otherWorkList: [ + { + label: "动火作业", + value: 1 + }, + { + label: "受限空间作业", + value: 2 + }, + { + label: "吊装作业", + value: 3 + }, + { + label: "动土作业", + value: 4 + }, + { + label: "断路作业", + value: 5 + }, + { + label: "高处作业", + value: 6 + }, + { + label: "临时用电作业", + value: 7 + }, + { + label: "盲板抽堵作业", + value: 8 + } + ] + }); + const material = ref() + const ruleFormRef = ref<FormInstance>() + const applyRules = reactive<FormRules>({ + operatorUids: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + workType: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + workLevel: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + workContent: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + workLocation: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + hazardIdentification: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + workTimeLine: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + "workDetail.hotMethod": [{ required: true, message: '该内容不能为空', trigger: 'blur' }] + }); + + // 页面载入时执行方法 + onMounted(() => { + + }); + // const toZero = (value: string | number,index: number,name: string,x:number) =>{ + // if(!value){ + // state.materialList[index][name][x].value = 0 + // } + // } + const openMaList = ()=>{ + if(state.form.workLevel == null || state.form.operatorUids == []){ + ElMessage({ + type: 'warning', + message: '请先选择作业人和作业等级再获取相应物资配置' + }); + }else{ + if(material.value.receiveUids.length==0){ + material.value.receiveUids = state.form.operatorUids + } + material.value.getMaList(state.form.workType,state.form.workLevel) + material.value.workerList = props.workerList + } + } + const conFirmMaterials = (receiveUids: Array<number>,chosenId: number) =>{ + state.form.maBaseId = null + state.form.receiveUids = [] + state.form.receiveUids = receiveUids + state.form.maBaseId = chosenId + } + const submitForm = async (formEl: FormInstance | undefined) => { + if (!formEl) return + await formEl.validate(async (valid, fields) => { + if (valid) { + // if (state.form.wmAddReqDTOList == null || state.form.wmAddReqDTOList.length == 0){ + // ElMessage({ + // type: 'warning', + // message: '请确认关联物资的配置' + // }); + // return + // } + state.form.expStartTime = JSON.parse(JSON.stringify(state.form.workTimeLine))[0] + state.form.expEndTime = JSON.parse(JSON.stringify(state.form.workTimeLine))[1] + let { workTimeLine, ...data } = JSON.parse(JSON.stringify(state.form)) + data.workDetail.otherSpecialWork = data.workDetail.otherSpecialWork.join(',') + const res = await workApplyApi().postFireApply(data) + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '提交成功!' + }); + formEl.resetFields() + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + material.value.maBaseId = null + material.value.receiveUids = [] + } else { + console.log('error submit!', fields) + } + }) + } + + // 折线图 + const renderMenu = async (value: string) => { + Session.set('projectId',value) + userInfos.value.projectId = value + await initBackEndControlRoutes(); + }; + return { + renderMenu, + Search, + material, + ruleFormRef, + applyRules, + openMaList, + conFirmMaterials, + submitForm, + ...toRefs(state), + }; + }, + }); +</script> + +<style scoped lang="scss"> + .home-container { + height: 100%; + overflow: hidden; + position: relative; + .homeCard{ + width: 100%; + padding: 20px; + box-sizing: border-box; + background: #fff; + border-radius: 4px; + margin-bottom: 20px; + } + .applyBtn{ + width: 100%; + background: #fff; + padding-top: 15px; + z-index: 5; + box-shadow: 0 -3px 8px rgba(150,150,150,.1); + display: flex; + align-items: center; + justify-content: center; + } + .el-row{ + margin-bottom: 20px; + } + .el-row:last-child { + margin-bottom: 0; + } + .el-input{ + width: 100% !important; + } + .el-date-editor::v-deep{ + width: 100%; + } + .el-select{ + width: 100%; + } + .el-cascader{ + width: 100% !important; + } + } + + .tab-i{ + margin-bottom: 15px; + + &:last-of-type{ + margin-bottom: 0; + } + ::v-deep(.el-form-item){ + .el-form-item__label{ + margin-bottom: 4px; + } + } + } +</style> diff --git a/src/views/specialWorkSystem/workTicket/zysq/components/ground.vue b/src/views/specialWorkSystem/workTicket/zysq/components/ground.vue new file mode 100644 index 0000000..26a089b --- /dev/null +++ b/src/views/specialWorkSystem/workTicket/zysq/components/ground.vue @@ -0,0 +1,563 @@ + <template> + <div class="home-container"> + <div style="height: 100%"> + <el-form :model="form" label-width="150px" :rules="applyRules" ref="ruleFormRef"> + <div class="homeCard"> + <el-row> + <el-col :span="12"> + <el-form-item label="作业人" prop="operatorUids"> + <el-select v-model="form.operatorUids" multiple> + <el-option + v-for="item in workerList" + :key="item.uid" + :label="item.username" + :value="item.uid" + /> + </el-select> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="作业时间" prop="workTimeLine"> + <el-date-picker + v-model="form.workTimeLine" + format="YYYY-MM-DD HH:mm" + value-format="YYYY-MM-DD HH:mm:00" + type="datetimerange" + range-separator="至" + start-placeholder="开始时间" + end-placeholder="结束时间" + /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="作业内容" prop="workContent"> + <el-input + v-model="form.workContent" + autosize + type="textarea" + placeholder="请输入作业内容" + /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="作业地址" prop="workLocation"> + <el-input + v-model="form.workLocation" + autosize + type="textarea" + placeholder="请输入作业地址" + /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="危害辨识" prop="hazardIdentification"> + <el-input + v-model="form.hazardIdentification" + placeholder="请输入危害辨识" + /> + </el-form-item> + </el-col> + </el-row> + <el-divider border-style="dashed"/> + <el-row> + <el-col :span="12"> + <el-form-item label="作业单位" prop="workDetail.operationDepId"> +<!-- <el-select v-model="form.workDetail.operationDepId">--> +<!-- <el-option--> +<!-- v-for="item in csDepList"--> +<!-- :key="item.value"--> +<!-- :label="item.label"--> +<!-- :value="item.value"--> +<!-- />--> +<!-- </el-select>--> + <el-cascader v-model="form.workDetail.operationDepId" :options="departList" :props="casProps" :show-all-levels="false" @change="handleChange" /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="范围" prop="workDetail.gbScope"> + <el-input + v-model="form.workDetail.gbScope" + autosize + type="textarea" + placeholder="请输入" + /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="动土方式" prop="workDetail.gbMethod"> + <el-input + v-model="form.workDetail.gbMethod" + autosize + type="textarea" + placeholder="请输入" + /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="关联作业" prop="workDetail.otherSpecialWork"> + <el-select v-model="form.workDetail.otherSpecialWork" multiple> + <el-option v-for="item in otherWorkList" :key="item.value" :label="item.label" :value="item.value" /> + </el-select> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="24"> + <el-form-item label="图片上传" prop="workDetail.gbPath"> + <el-upload accept="image/*" :on-exceed="showTip" :on-preview="handlePictureCardPreview" :limit='imgLimit' v-model:file-list="fileList" :http-request="upload" :action="uploadUrl" list-type="picture-card" :on-remove="handleRemove" :before-remove="beforeRemove" :before-upload="getUploadUrl"> + <el-icon><Plus /></el-icon> + <template #tip> + <div class="el-upload__tip">上传jpg/png图片尺寸小于500KB,最多可上传3张</div> + </template> + </el-upload> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="选择关联物资"> + <el-button type="primary" @click="openMaList">选择物资标准</el-button> + </el-form-item> + </el-col> + </el-row> + </div> + </el-form> + <material-dialog ref="material" @conFirmMaterials="conFirmMaterials"></material-dialog> + <div class="applyBtn"> + <el-button type="primary" size="large" plain @click="submitForm(ruleFormRef)">发起申请</el-button> + </div> + </div> + <el-dialog v-model="dialogVisible"> + <img w-full :src="dialogImageUrl" alt="Preview Image" /> + </el-dialog> + </div> +</template> + +<script lang="ts"> + import { toRefs, reactive, defineComponent, ref, defineAsyncComponent } from 'vue'; + import { storeToRefs } from 'pinia'; + import { initBackEndControlRoutes } from '/@/router/backEnd'; + import {useUserInfo} from "/@/stores/userInfo"; + import { Session } from '/@/utils/storage'; + import { Search,Plus } from '@element-plus/icons-vue' + import { ElMessage, ElMessageBox } from 'element-plus' + import type { FormInstance, FormRules, UploadProps, UploadUserFile } from 'element-plus' + import { workApplyApi } from '/@/api/specialWorkSystem/workApply'; + import axios from 'axios'; + + interface stateType { + equipmentDialog: boolean, + form: Object, + csDepList: Array<any>, + otherWorkList: Array<any>, + fileList: Array<file>, + uploadUrl: string, + dialogVisible: Boolean, + dialogImageUrl: string | null, + imgLimit: number, + casProps: {}, + isOverSize: Boolean + } + interface file { + url: string; + } + export default { + name: 'groundForm', + components: { + materialDialog: defineAsyncComponent(() => import('/@/views/specialWorkSystem/workTicket/zysq/components/materialDialog.vue')), + }, + props:['workerList','departList'], + setup(props: any, context: any) { + const userInfo = useUserInfo() + const { userInfos } = storeToRefs(userInfo); + const state = reactive<stateType>({ + equipmentDialog: false, + form: { + operatorUids: [], + workType: 4, + workLevel: 0, + workContent: '', + workLocation: '', + hazardIdentification: '', + maBaseId: null, + workDetail:{ + operationDepId: null, + gbScope: '', + gbMethod: '', + gbPath: [], + otherSpecialWork: [] + }, + receiveUids: [], + workTimeLine: [], + expStartTime: '', + expEndTime: '' + }, + isOverSize: false, + fileList: [], + imgLimit: 3, + uploadUrl: '', + dialogVisible: false, + dialogImageUrl: null, + csDepList: [ + { + label: "单位一", + value: 1 + }, + { + label: "单位二", + value: 2 + }, + { + label: "单位三", + value: 3 + }, + { + label: "单位四", + value: 4 + }, + { + label: "单位五", + value: 5 + }, + { + label: "单位六", + value: 6 + } + ], + otherWorkList: [ + { + label: '动火作业', + value: 1 + }, + { + label: '受限空间作业', + value: 2 + }, + { + label: '吊装作业', + value: 3 + }, + { + label: '动土作业', + value: 4 + }, + { + label: '断路作业', + value: 5 + }, + { + label: '高处作业', + value: 6 + }, + { + label: '临时用电作业', + value: 7 + }, + { + label: '盲板抽堵作业', + value: 8 + } + ], + casProps: { + emitPath: false, + value: 'depId', + label: 'depName', + multiple: false, + expandTrigger: 'hover', + checkStrictly: true + } + }); + const material = ref() + const ruleFormRef = ref<FormInstance>() + const applyRules = reactive<FormRules>({ + operatorUids: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + workType: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + workContent: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + workLocation: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + hazardIdentification: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + workTimeLine: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + "workDetail.operationDepId": [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + "workDetail.gbScope": [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + "workDetail.gbMethod": [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + "workDetail.gbPath": [{ required: true, message: '该内容不能为空', trigger: 'blur' }] + }); + // const toZero = (value: string | number,index: number,name: string,x:number) =>{ + // if(!value){ + // state.materialList[index][name][x].value = 0 + // } + // } + + const openMaList = ()=>{ + if(state.form.operatorUids == []){ + ElMessage({ + type: 'warning', + message: '请先选择作业人再获取相应物资配置' + }); + }else{ + if(material.value.receiveUids.length==0){ + material.value.receiveUids = state.form.operatorUids + } + material.value.getMaList(state.form.workType,state.form.workLevel) + material.value.workerList = props.workerList + } + } + const conFirmMaterials = (receiveUids: Array<number>,chosenId: number) =>{ + state.form.maBaseId = null + state.form.receiveUids = [] + state.form.receiveUids = receiveUids + state.form.maBaseId = chosenId + } + + const submitForm = async (formEl: FormInstance | undefined) => { + if (!formEl) return + await formEl.validate(async (valid, fields) => { + if (valid) { + // if (state.form.wmAddReqDTOList == null || state.form.wmAddReqDTOList.length == 0){ + // ElMessage({ + // type: 'warning', + // message: '请确认关联物资的配置' + // }); + // return + // } + state.form.expStartTime = JSON.parse(JSON.stringify(state.form.workTimeLine))[0] + state.form.expEndTime = JSON.parse(JSON.stringify(state.form.workTimeLine))[1] + let { workTimeLine, ...data } = JSON.parse(JSON.stringify(state.form)) + data.workDetail.otherSpecialWork = data.workDetail.otherSpecialWork.join(',') + data.workDetail.gbPath = data.workDetail.gbPath.join(',') + const res = await workApplyApi().postGroundApply(data) + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '提交成功!' + }); + formEl.resetFields() + state.form.workDetail.gbPath = [] + state.fileList = [] + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + material.value.maBaseId = null + material.value.receiveUids = [] + } else { + console.log('error submit!', fields) + } + }) + } + + const handlePreview: UploadProps['onPreview'] = (uploadFile) => { + console.log(uploadFile); + }; + + const handlePictureCardPreview = (uploadFile: { url: string }) => { + state.dialogImageUrl = uploadFile.url!; + state.dialogVisible = true; + }; + + const getUploadUrl = async (rawFile: any) => { + const fileSize = rawFile.size / 1024 < 500 ? '1' : '0' + if(fileSize === '0'){ + ElMessage({ + type: 'warning', + message: '文件大小不能超过500k。' + }); + state.isOverSize = true + return false + }else{ + const res = await workApplyApi().getUploadUrl(rawFile.name); + state.form.workDetail.gbPath.push(res.data.data.fileName) + state.uploadUrl = res.data.data.uploadUrl; + } + }; + + const upload = async (params: any) => { + // const formData = new FormData(); + // formData.append('file', state.fileList[0].raw); + let reader = new FileReader(); + reader.readAsArrayBuffer(params.file); + reader.onload = async () => { + axios + .put(state.uploadUrl, reader.result, { + header: { 'Content-Type': 'multipart/form-data' } + }) + .then(() => { + // if (state.fileList.length === 2) { + // state.fileList.splice(0, 1); + // } + // console.log(state.form.workDetail.gbPath,'gbpath') + }); + }; + }; + + const beforeRemove = (file: {}, fileList: []) => { + const result = new Promise((resolve, reject) => { + if(!state.isOverSize){ + ElMessageBox.confirm('此操作将删除该图片, 是否继续?', '提示', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning' + }) + .then(() => { + // console.log(state.workDetail.gbPath,'path') + const list = JSON.parse(JSON.stringify(state.form.workDetail.gbPath)) + fileList.map((item,index)=>{ + if(item.uid === file.uid){ + fileList.splice(index,1) + state.form.workDetail.gbPath.splice(index,1) + // 请求删除接口 + deletePic(false,list[index]) + } + }) + }) + .catch(() => { + reject(false); + }); + }else{ + const list = JSON.parse(JSON.stringify(state.form.workDetail.gbPath)) + fileList.map((item,index)=>{ + if(item.uid === file.uid){ + fileList.splice(index,1) + state.form.workDetail.gbPath.splice(index,1) + deletePic(true,list[index]) + } + }) + state.isOverSize = false + } + }); + return result; + }; + + + // 删除图片接口 + const deletePic = async(isOverSize:boolean,fileName:string)=>{ + const res = await workApplyApi().deleteFile({fileName: fileName}) + if (res.data.code === '200') { + ElMessage({ + type: isOverSize ? 'error' : 'success', + message: isOverSize ? '上传失败':'删除成功!' + }); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } + + const showTip =()=>{ + ElMessage({ + type: 'warning', + message: '超出文件上传数量' + }); + } + + // const handleRemove: UploadProps['onRemove'] = (uploadFile, uploadFiles) => { + // console.log('2111111111111') + // }; + + // 折线图 + const renderMenu = async (value: string) => { + Session.set('projectId',value) + userInfos.value.projectId = value + await initBackEndControlRoutes(); + }; + return { + renderMenu, + Search, + Plus, + ruleFormRef, + applyRules, + material, + openMaList, + conFirmMaterials, + handlePreview, + getUploadUrl, + beforeRemove, + upload, + showTip, + submitForm, + handlePictureCardPreview, + ...toRefs(state), + }; + }, + }; +</script> + +<style scoped lang="scss"> + .avatar-uploader .avatar { + width: 178px; + height: 178px; + display: block; + } + .home-container { + height: 100%; + overflow: hidden; + position: relative; + .homeCard{ + width: 100%; + padding: 20px; + box-sizing: border-box; + background: #fff; + border-radius: 4px; + margin-bottom: 20px; + } + .applyBtn{ + width: 100%; + background: #fff; + padding-top: 15px; + z-index: 5; + box-shadow: 0 -3px 8px rgba(150,150,150,.1); + display: flex; + align-items: center; + justify-content: center; + } + .el-row{ + margin-bottom: 20px; + } + .el-row:last-child { + margin-bottom: 0; + } + .el-input{ + width: 100% !important; + } + .el-date-editor::v-deep{ + width: 100%; + } + .el-select{ + width: 100%; + } + :deep(.el-cascader){ + width: 100% !important; + } + } +</style> +<style> + .avatar-uploader .el-upload { + border: 1px dashed var(--el-border-color); + border-radius: 6px; + cursor: pointer; + position: relative; + overflow: hidden; + transition: var(--el-transition-duration-fast); + } + + .avatar-uploader .el-upload:hover { + border-color: var(--el-color-primary); + } + + .el-icon.avatar-uploader-icon { + font-size: 28px; + color: #8c939d; + width: 178px; + height: 178px; + text-align: center; + } +</style> diff --git a/src/views/specialWorkSystem/workTicket/zysq/components/height.vue b/src/views/specialWorkSystem/workTicket/zysq/components/height.vue new file mode 100644 index 0000000..0fcee6b --- /dev/null +++ b/src/views/specialWorkSystem/workTicket/zysq/components/height.vue @@ -0,0 +1,413 @@ +<template> + <div class="home-container"> + <div style="height: 100%"> + <el-form :model="form" label-width="150px" :rules="applyRules" ref="ruleFormRef"> + <div class="homeCard"> + <el-row> + <el-col :span="12"> + <el-form-item label="作业人" prop="operatorUids"> + <el-select v-model="form.operatorUids" multiple> + <el-option + v-for="item in workerList" + :key="item.uid" + :label="item.username" + :value="item.uid" + /> + </el-select> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="作业时间" prop="workTimeLine"> + <el-date-picker + v-model="form.workTimeLine" + format="YYYY-MM-DD HH:mm" + value-format="YYYY-MM-DD HH:mm:00" + type="datetimerange" + range-separator="至" + start-placeholder="开始时间" + end-placeholder="结束时间" + /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="作业等级" prop="workLevel"> + <el-select v-model="form.workLevel"> + <el-option + v-for="item in workLevelList" + :key="item.value" + :label="item.label" + :value="item.value" + /> + </el-select> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="作业内容" prop="workContent"> + <el-input + v-model="form.workContent" + autosize + type="textarea" + placeholder="请输入作业内容" + /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="作业地址" prop="workLocation"> + <el-input + v-model="form.workLocation" + autosize + type="textarea" + placeholder="请输入作业地址" + /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="危害辨识" prop="hazardIdentification"> + <el-input + v-model="form.hazardIdentification" + placeholder="请输入危害辨识" + /> + </el-form-item> + </el-col> + </el-row> + <el-divider border-style="dashed"/> + <el-row> + <el-col :span="12"> + <el-form-item label="作业单位" prop="workDetail.operationDepId"> + <!-- <el-select v-model="form.workDetail.operationDepId">--> + <!-- <el-option--> + <!-- v-for="item in heDepList"--> + <!-- :key="item.value"--> + <!-- :label="item.label"--> + <!-- :value="item.value"--> + <!-- />--> + <!-- </el-select>--> + <el-cascader v-model="form.workDetail.operationDepId" :options="departList" :props="casProps" :show-all-levels="false" @change="handleChange" /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="作业高度" prop="workDetail.operationHeight"> + <el-input + v-model="form.workDetail.operationHeight" + type="number" + placeholder="请输入作业高度(大于等于0)" + > + <template #append>米(m)</template> + </el-input> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="关联作业" prop="workDetail.otherSpecialWork"> + <el-select v-model="form.workDetail.otherSpecialWork" multiple> + <el-option + v-for="item in otherWorkList" + :key="item.value" + :label="item.label" + :value="item.value" + /> + </el-select> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="选择关联物资"> + <el-button type="primary" @click="openMaList">选择物资标准</el-button> + </el-form-item> + </el-col> + </el-row> + </div> + </el-form> + <material-dialog ref="material" @conFirmMaterials="conFirmMaterials"></material-dialog> + <div class="applyBtn"> + <el-button type="primary" size="large" plain @click="submitForm(ruleFormRef)">发起申请</el-button> + </div> + </div> + </div> +</template> + +<script lang="ts"> +import {toRefs, reactive, defineComponent, ref, defineAsyncComponent} from 'vue'; + import { storeToRefs } from 'pinia'; + import { initBackEndControlRoutes } from '/@/router/backEnd'; + import {useUserInfo} from "/@/stores/userInfo"; + import { Session } from '/@/utils/storage'; + import { Search } from '@element-plus/icons-vue' + import { ElMessage, ElMessageBox } from 'element-plus' + import type { FormInstance, FormRules } from 'element-plus' + import { workApplyApi } from '/@/api/specialWorkSystem/workApply'; + + + interface stateType { + equipmentDialog: boolean, + form: Object, + workTypeList: Array<any>, + workLevelList: Array<any>, + heDepList: Array<any>, + otherWorkList: Array<any>, + casProps:{} + } + export default defineComponent({ + name: 'heightForm', + components: { + materialDialog: defineAsyncComponent(() => import('/@/views/specialWorkSystem/workTicket/zysq/components/materialDialog.vue')), + }, + props:['workerList','departList'], + setup(props: any, context: any) { + const userInfo = useUserInfo() + const { userInfos } = storeToRefs(userInfo); + const state = reactive<stateType>({ + equipmentDialog: false, + form: { + operatorUids: [], + workType: 6, + workLevel: null, + workContent: '', + workLocation: '', + hazardIdentification: '', + maBaseId: null, + workDetail:{ + operationDepId: '', + operationHeight: null, + otherSpecialWork: [] + }, + receiveUids: [], + workTimeLine: [], + expStartTime: '', + expEndTime: '' + }, + heDepList: [ + { + label: "单位一", + value: 1 + }, + { + label: "单位二", + value: 2 + }, + { + label: "单位三", + value: 3 + }, + { + label: "单位四", + value: 4 + }, + { + label: "单位五", + value: 5 + }, + { + label: "单位六", + value: 6 + } + ], + casProps: { + emitPath: false, + value: 'depId', + label: 'depName', + multiple: false, + expandTrigger: 'hover', + checkStrictly: true + }, + workTypeList: [ + { + label: "类型一", + value: 1 + }, + { + label: "类型二", + value: 2 + } + ], + workLevelList: [ + { + label: "一级高处作业", + value: 4 + }, + { + label: "二级高处作业", + value: 5 + }, + { + label: "三级高处作业", + value: 6 + }, + { + label: "特级高处作业", + value: 7 + } + ], + otherWorkList: [ + { + label: "动火作业", + value: 1 + }, + { + label: "受限空间作业", + value: 2 + }, + { + label: "吊装作业", + value: 3 + }, + { + label: "动土作业", + value: 4 + }, + { + label: "断路作业", + value: 5 + }, + { + label: "高处作业", + value: 6 + }, + { + label: "临时用电作业", + value: 7 + }, + { + label: "盲板抽堵作业", + value: 8 + } + ] + }); + const material = ref() + const ruleFormRef = ref<FormInstance>() + const applyRules = reactive<FormRules>({ + operatorUids: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + workType: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + workLevel: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + workContent: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + workLocation: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + hazardIdentification: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + workTimeLine: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + "workDetail.operationDepId": [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + "workDetail.operationHeight": [{ required: true, message: '该内容不能为空', trigger: 'blur' }] + }); + + // const toZero = (value: string | number,index: number,name: string,x:number) =>{ + // if(!value){ + // state.materialList[index][name][x].value = 0 + // } + // } + const openMaList = ()=>{ + if(state.form.workLevel == null || state.form.operatorUids == []){ + ElMessage({ + type: 'warning', + message: '请先选择作业人和作业等级再获取相应物资配置' + }); + }else{ + if(material.value.receiveUids.length==0){ + material.value.receiveUids = state.form.operatorUids + } + material.value.getMaList(state.form.workType,state.form.workLevel) + material.value.workerList = props.workerList + } + } + const conFirmMaterials = (receiveUids: Array<number>,chosenId: number) =>{ + state.form.maBaseId = null + state.form.receiveUids = [] + state.form.receiveUids = receiveUids + state.form.maBaseId = chosenId + } + + const submitForm = async (formEl: FormInstance | undefined) => { + if (!formEl) return + await formEl.validate(async (valid, fields) => { + if (valid) { + state.form.expStartTime = JSON.parse(JSON.stringify(state.form.workTimeLine))[0] + state.form.expEndTime = JSON.parse(JSON.stringify(state.form.workTimeLine))[1] + let { workTimeLine, ...data } = JSON.parse(JSON.stringify(state.form)) + data.workDetail.otherSpecialWork = data.workDetail.otherSpecialWork.join(',') + const res = await workApplyApi().postHeightApply(data) + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '提交成功!' + }); + formEl.resetFields() + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + material.value.maBaseId = null + material.value.receiveUids = [] + } else { + console.log('error submit!', fields) + } + }) + } + + + // 折线图 + const renderMenu = async (value: string) => { + Session.set('projectId',value) + userInfos.value.projectId = value + await initBackEndControlRoutes(); + }; + return { + renderMenu, + Search, + ruleFormRef, + applyRules, + material, + openMaList, + conFirmMaterials, + submitForm, + ...toRefs(state), + }; + }, + }); +</script> + +<style scoped lang="scss"> + .home-container { + height: 100%; + overflow: hidden; + position: relative; + .homeCard{ + width: 100%; + padding: 20px; + box-sizing: border-box; + background: #fff; + border-radius: 4px; + margin-bottom: 20px; + } + .applyBtn{ + width: 100%; + background: #fff; + padding-top: 15px; + z-index: 5; + box-shadow: 0 -3px 8px rgba(150,150,150,.1); + display: flex; + align-items: center; + justify-content: center; + } + .el-row{ + margin-bottom: 20px; + } + .el-row:last-child { + margin-bottom: 0; + } + .el-input{ + width: 100% !important; + } + .el-date-editor::v-deep{ + width: 100%; + } + .el-select{ + width: 100%; + } + :deep(.el-cascader){ + width: 100% !important; + } + } +</style> diff --git a/src/views/specialWorkSystem/workTicket/zysq/components/hoist.vue b/src/views/specialWorkSystem/workTicket/zysq/components/hoist.vue new file mode 100644 index 0000000..f9ae96f --- /dev/null +++ b/src/views/specialWorkSystem/workTicket/zysq/components/hoist.vue @@ -0,0 +1,308 @@ +<template> + <div class="home-container"> + <div style="height: 100%"> + <el-form :model="form" label-width="150px" :rules="applyRules" ref="ruleFormRef"> + <div class="homeCard"> + <el-row> + <el-col :span="12"> + <el-form-item label="作业人" prop="operatorUids"> + <el-select v-model="form.operatorUids" multiple> + <el-option + v-for="item in workerList" + :key="item.uid" + :label="item.username" + :value="item.uid" + /> + </el-select> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="作业时间" prop="workTimeLine"> + <el-date-picker + v-model="form.workTimeLine" + format="YYYY-MM-DD HH:mm" + value-format="YYYY-MM-DD HH:mm:00" + type="datetimerange" + range-separator="至" + start-placeholder="开始时间" + end-placeholder="结束时间" + /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="作业等级" prop="workLevel"> + <el-select v-model="form.workLevel"> + <el-option + v-for="item in workLevelList" + :key="item.value" + :label="item.label" + :value="item.value" + /> + </el-select> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="作业内容" prop="workContent"> + <el-input + v-model="form.workContent" + autosize + type="textarea" + placeholder="请输入作业内容" + /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="作业地址" prop="workLocation"> + <el-input + v-model="form.workLocation" + autosize + type="textarea" + placeholder="请输入作业地址" + /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="危害辨识" prop="hazardIdentification"> + <el-input + v-model="form.hazardIdentification" + placeholder="请输入危害辨识" + /> + </el-form-item> + </el-col> + </el-row> + <el-divider border-style="dashed"/> + <el-row> + <el-col :span="12"> + <el-form-item label="吊装工具名称" prop="workDetail.hoistingToolName"> + <el-input + v-model="form.workDetail.hoistingToolName" + autosize + type="textarea" + placeholder="请输入" + /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="起吊物体质量" prop="workDetail.weightMass"> + <el-input + v-model="form.workDetail.weightMass" + type="number" + placeholder="请输入起吊物体质量(大于等于0)" + > + <template #append>吨(t)</template> + </el-input> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="选择关联物资"> + <el-button type="primary" @click="openMaList">选择物资标准</el-button> + </el-form-item> + </el-col> + </el-row> + </div> + </el-form> + <material-dialog ref="material" @conFirmMaterials="conFirmMaterials"></material-dialog> + <div class="applyBtn"> + <el-button type="primary" size="large" plain @click="submitForm(ruleFormRef)">发起申请</el-button> + </div> + </div> + </div> +</template> + +<script lang="ts"> +import {toRefs, reactive, defineComponent, ref, defineAsyncComponent} from 'vue'; + import { storeToRefs } from 'pinia'; + import { initBackEndControlRoutes } from '/@/router/backEnd'; + import {useUserInfo} from "/@/stores/userInfo"; + import { Session } from '/@/utils/storage'; + import { Search } from '@element-plus/icons-vue' + import { ElMessage, ElMessageBox } from 'element-plus' + import type { FormInstance, FormRules } from 'element-plus' + import { workApplyApi } from '/@/api/specialWorkSystem/workApply'; + + interface stateType { + equipmentDialog: boolean, + form: Object, + workLevelList: Array<any> + } + export default defineComponent({ + name: 'hoistForm', + components: { + materialDialog: defineAsyncComponent(() => import('/@/views/specialWorkSystem/workTicket/zysq/components/materialDialog.vue')), + }, + props:['workerList'], + setup(props: any, context: any) { + const userInfo = useUserInfo() + const { userInfos } = storeToRefs(userInfo); + const state = reactive<stateType>({ + equipmentDialog: false, + form: { + operatorUids: [], + workType: 3, + workLevel: null, + workContent: '', + workLocation: '', + maBaseId: null, + hazardIdentification: '', + workDetail:{ + hoistingToolName: '', + weightMass: null + }, + receiveUids: [], + workTimeLine: [], + expStartTime: '', + expEndTime: '' + }, + workLevelList: [ + { + label: "一级吊装作业", + value: 8 + }, + { + label: "二级吊装作业", + value: 9 + }, + { + label: "三级吊装作业", + value: 10 + } + ] + }); + const material = ref() + const ruleFormRef = ref<FormInstance>() + const applyRules = reactive<FormRules>({ + operatorUids: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + workType: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + workLevel: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + workContent: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + workLocation: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + hazardIdentification: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + workTimeLine: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + "workDetail.hoistingToolName": [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + "workDetail.weightMass": [{ required: true, message: '该内容不能为空', trigger: 'blur' }] + }); + + // const toZero = (value: string | number,index: number,name: string,x:number) =>{ + // if(!value){ + // state.materialList[index][name][x].value = 0 + // } + // } + const openMaList = ()=>{ + if(state.form.workLevel == null || state.form.operatorUids == []){ + ElMessage({ + type: 'warning', + message: '请先选择作业人和作业等级再获取相应物资配置' + }); + }else{ + if(material.value.receiveUids.length==0){ + material.value.receiveUids = state.form.operatorUids + } + material.value.getMaList(state.form.workType,state.form.workLevel) + material.value.workerList = props.workerList + } + } + const conFirmMaterials = (receiveUids: Array<number>,chosenId: number) =>{ + state.form.maBaseId = null + state.form.receiveUids = [] + state.form.receiveUids = receiveUids + state.form.maBaseId = chosenId + } + const submitForm = async (formEl: FormInstance | undefined) => { + if (!formEl) return + await formEl.validate(async (valid, fields) => { + if (valid) { + state.form.expStartTime = JSON.parse(JSON.stringify(state.form.workTimeLine))[0] + state.form.expEndTime = JSON.parse(JSON.stringify(state.form.workTimeLine))[1] + let { workTimeLine, ...data } = JSON.parse(JSON.stringify(state.form)) + data.workDetail.weightMass = Number(data.workDetail.weightMass) + const res = await workApplyApi().postHoistApply(data) + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '提交成功!' + }); + formEl.resetFields() + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + material.value.maBaseId = null + material.value.receiveUids = [] + } else { + console.log('error submit!', fields) + } + }) + } + + // 折线图 + const renderMenu = async (value: string) => { + Session.set('projectId',value) + userInfos.value.projectId = value + await initBackEndControlRoutes(); + }; + return { + renderMenu, + Search, + ruleFormRef, + applyRules, + material, + openMaList, + conFirmMaterials, + submitForm, + ...toRefs(state), + }; + }, + }); +</script> + +<style scoped lang="scss"> + .home-container { + height: 100%; + overflow: hidden; + position: relative; + .homeCard{ + width: 100%; + padding: 20px; + box-sizing: border-box; + background: #fff; + border-radius: 4px; + margin-bottom: 20px; + } + .applyBtn{ + width: 100%; + background: #fff; + padding-top: 15px; + z-index: 5; + box-shadow: 0 -3px 8px rgba(150,150,150,.1); + display: flex; + align-items: center; + justify-content: center; + } + .el-row{ + margin-bottom: 20px; + } + .el-row:last-child { + margin-bottom: 0; + } + .el-input{ + width: 100% !important; + } + .el-date-editor::v-deep{ + width: 100%; + } + .el-select{ + width: 100%; + } + .el-cascader{ + width: 100% !important; + } + } +</style> diff --git a/src/views/specialWorkSystem/workTicket/zysq/components/materialDialog.vue b/src/views/specialWorkSystem/workTicket/zysq/components/materialDialog.vue new file mode 100644 index 0000000..384515a --- /dev/null +++ b/src/views/specialWorkSystem/workTicket/zysq/components/materialDialog.vue @@ -0,0 +1,293 @@ +<template> + <el-dialog v-model="equipmentDialog" title="关联物资标准" width="40%" center @close="closeMaterial"> + <div class="standard" v-for="item in materialList"> + <div>{{ item.name }}</div> + <el-button @click="openList(item)" type="success">选用</el-button> + </div> + + <el-dialog v-model="equipDetailDialog" title="物资标准详情" width="75%" center @open="openDetail"> + <div class="choose-receiver"> + <span>选择其他作业关联人员</span> + <el-select v-model="receiveUids" multiple @change="changeReceiver"> + <el-option + v-for="item in workerList" + :key="item.uid" + :label="item.username" + :value="item.uid" + /> + </el-select> + </div> + <table class="table"> + <tr> + <th class="w-25">物资名称</th> + <th class="w-15">标准值</th> + <th class="w-15">级别</th> + <th class="w-30">关联人员与个数</th> + <th class="w-15">实际使用</th> + </tr> + <tr v-for="(item,index) in materialDetail"> + <td class="w-25">{{item.materialName}}</td> +<!-- <td class="w-1">--> +<!-- <el-select v-model="addList[index].depId" @change="changeDep($event,index)">--> +<!-- <el-option--> +<!-- v-for="i in item.msList"--> +<!-- :key="i.depId"--> +<!-- :label="i.depName"--> +<!-- :value="i.depId"--> +<!-- />--> +<!-- </el-select>--> +<!-- </td>--> +<!-- <td class="w-15">--> +<!-- {{stockCount[index]}}--> +<!-- </td>--> + <td class="w-15">{{item.standVal}}</td> + <td class="w-15">{{item.configurationLevelName}}</td> + <td class="w-30"> + {{item.receiveUnames}} + </td> +<!-- <td class="w-15">--> +<!-- <el-input type="number" v-model.number="addList[index].useCount"/>--> +<!-- </td>--> + <td class="w-15"> + {{item.receiveCount}} + </td> + </tr> + </table> + <template #footer> + <span class="dialog-footer"> + <el-button @click="closeChoose()" size="default">取消</el-button> + <el-button type="primary" @click="submitMaterials" size="default">确认</el-button> + </span> + </template> + </el-dialog> + </el-dialog> +</template> + +<script lang="ts"> +import {workApplyApi} from "/@/api/specialWorkSystem/workApply"; + +interface stateType { + equipmentDialog:boolean + materialList: Array<any> + equipDetailDialog: boolean + materialDetail: Array<any> + stockCount: Array<number> + chosenId: number | null, + receiveUids: Array<number> +} + + +import { reactive, toRefs, ref } from 'vue'; +import { approveBasicApi } from '/@/api/specialWorkSystem/approveBasic'; +import {ElMessage, ElMessageBox} from 'element-plus'; +import {useUserInfo} from "/@/stores/userInfo"; +import {storeToRefs} from "pinia"; + +export default { + name: 'materialDialog', + setup(props: any, context: any) { + const userInfo = useUserInfo() + const { userInfos } = storeToRefs(userInfo); + const approveBasicFormRef = ref(); + const state = reactive<stateType>({ + chosenId: null, + equipmentDialog: false, + materialList: [], + equipDetailDialog: false, + materialDetail: [], + stockCount: [], + receiveUids: [] + }); + + // 确认物资标准 + const getMaList = async(type:number,level:number) =>{ + const data = {workType: type,workLevel: level} + const res = await workApplyApi().getMaterial(data) + if (res.data.code === '200') { + if(res.data.data && res.data.data.length>0){ + state.materialList = JSON.parse(JSON.stringify(res.data.data)) + state.equipmentDialog = true + }else{ + ElMessage({ + type: 'warning', + message: '暂时查询不到物资标准信息' + }); + } + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } + const openList = async(item:object)=>{ + state.chosenId = item.id + const data = {maBaseId: state.chosenId,receiveUids:state.receiveUids} + const res = await workApplyApi().getMaterialDetail(data) + if (res.data.code === '200') { + if(res.data.data && res.data.data.length>0){ + state.materialDetail = res.data.data + state.equipDetailDialog = true + }else{ + ElMessage({ + type: 'warning', + message: '暂时查询不到物资标准信息' + }); + } + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + // state.stockCount = [] + // if(item.mcList && item.mcList.length>0){ + // for(let j in item.mcList){ + // if(item.mcList[j].msList == null || item.mcList[j].msList.length==0){ + // item.mcList.splice(j,1) + // } + // } + // state.materialDetail = item.mcList + // for(let i in state.materialDetail){ + // state.addList.push( + // { + // materialId: state.materialDetail[i].materialId, + // depId: null, + // depName: '', + // useCount: null + // } + // ) + // for(let x in state.materialDetail[i].msList){ + // if(state.materialDetail[i].msList[x].depId == userInfos.value.depId){ + // state.addList[i].depId = userInfos.value.depId + // state.addList[i].depName = state.materialDetail[i].msList[x].depName + // state.stockCount[i] = state.materialDetail[i].msList.find((e) => e.depId == state.addList[i].depId).stockCount + // } + // } + // } + // } + } + const changeReceiver = async ()=>{ + const data = {maBaseId: state.chosenId,receiveUids:state.receiveUids} + const res = await workApplyApi().getMaterialDetail(data) + if (res.data.code === '200') { + if(res.data.data && res.data.data.length>0){ + state.materialDetail = res.data.data + }else{ + ElMessage({ + type: 'warning', + message: '暂时查询不到物资标准信息' + }); + } + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } + const openDetail = ()=>{ + } + const submitMaterials = ()=>{ + // if(state.addList.length > 0 && (state.addList.some((e) => e.depId == null && e.useCount != null ) || state.addList.some((e) => e.useCount == null && e.depId != null))){ + // ElMessage({ + // type: 'warning', + // message: '出库部门或实际使用值不可为空' + // }); + // return + // } + // for(let i in state.materialDetail){ + // if(state.materialDetail[i].configurationLevelName == '必选' && state.addList[i].depId != null && state.addList[i].useCount <= 0){ + // ElMessage({ + // type: 'warning', + // message: '必选物资数量不能小于等于0' + // }); + // return + // } + // if((state.stockCount[i] !=null && state.addList[i].useCount !=null) && (state.stockCount[i] < state.addList[i].useCount)){ + // ElMessage({ + // type: 'warning', + // message: '物资配置数量超出库存量,请重新配置' + // }); + // return + // } + // } + // if(state.addList.length > 0){ + // for(let n in state.addList){ + // if(state.addList[n].depId == null && state.addList[n].useCount == null){ + // state.addList.splice(n,1) + // } + // } + // } + console.log(state.receiveUids,state.chosenId,'666666666') + context.emit('conFirmMaterials',state.receiveUids,state.chosenId) + state.equipDetailDialog = false + state.equipmentDialog = false + } + + const closeMaterial = ()=>{ + + } + const closeChoose = () =>{ + state.equipDetailDialog = false + } + return { + ...toRefs(state), + getMaList, + openList, + changeReceiver, + openDetail, + closeChoose, + closeMaterial, + submitMaterials + }; + } +}; +</script> + +<style lang="scss" scoped> + .standard{ + width: 100%; + display: flex; + margin-bottom: 20px; + align-items: center; + justify-content: space-between; + } + + .table{ + width: 100%; + border-collapse: collapse; + margin-top: 20px; + tr{ + width: 100%; + border: 1px solid #ccc; + th,td{ + padding: 6px 0; + border-left: 1px solid #ccc; + &:first-of-type{ + border-left: none; + } + } + td{ + font-weight: bolder; + } + + .w-15{ + width: 15%; + text-align: center; + } + .w-20{ + width: 20%; + text-align: center; + } + .w-25{ + width: 25%; + text-align: center; + } + .w-30{ + width: 30%; + text-align: center; + } + } + } +</style> diff --git a/src/views/specialWorkSystem/workTicket/zysq/components/plate.vue b/src/views/specialWorkSystem/workTicket/zysq/components/plate.vue new file mode 100644 index 0000000..f0e9544 --- /dev/null +++ b/src/views/specialWorkSystem/workTicket/zysq/components/plate.vue @@ -0,0 +1,619 @@ +<template> + <div class="home-container"> + <div style="height: 100%"> + <el-form :model="form" label-width="150px" :rules="applyRules" ref="ruleFormRef"> + <div class="homeCard"> + <el-row> + <el-col :span="12"> + <el-form-item label="作业人" prop="operatorUids"> + <el-select v-model="form.operatorUids" multiple> + <el-option + v-for="item in workerList" + :key="item.uid" + :label="item.username" + :value="item.uid" + /> + </el-select> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="作业时间" prop="workTimeLine"> + <el-date-picker + v-model="form.workTimeLine" + format="YYYY-MM-DD HH:mm" + value-format="YYYY-MM-DD HH:mm:00" + type="datetimerange" + range-separator="至" + start-placeholder="开始时间" + end-placeholder="结束时间" + /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="作业等级" prop="workLevel"> + <el-select v-model="form.workLevel"> + <el-option + v-for="item in workLevelList" + :key="item.value" + :label="item.label" + :value="item.value" + /> + </el-select> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="作业内容" prop="workContent"> + <el-input + v-model="form.workContent" + autosize + type="textarea" + placeholder="请输入作业内容" + /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="作业地址" prop="workLocation"> + <el-input + v-model="form.workLocation" + autosize + type="textarea" + placeholder="请输入作业地址" + /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="危害辨识" prop="hazardIdentification"> + <el-input + v-model="form.hazardIdentification" + placeholder="请输入危害辨识" + /> + </el-form-item> + </el-col> + </el-row> + <el-divider border-style="dashed"/> + <el-row> + <el-col :span="12"> + <el-form-item label="盲板编号" prop="workDetail.bpCode"> + <el-input + v-model="form.workDetail.bpCode" + autosize + type="textarea" + placeholder="请输入" + /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="主要介质" prop="workDetail.mainMedia"> + <el-input + v-model="form.workDetail.mainMedia" + autosize + type="textarea" + placeholder="请输入" + /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="温度" prop="workDetail.temperature"> + <el-input + v-model="form.workDetail.temperature" + type="number" + placeholder="请输入温度(大于等于0)" + > + <template #append>摄氏度(℃)</template> + </el-input> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="压力" prop="workDetail.pressure"> + <el-input + v-model="form.workDetail.pressure" + type="number" + placeholder="请输入压力(大于等于0)" + > + <template #append>千帕(kPa)</template> + </el-input> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="盲板材质" prop="workDetail.bpMaterialQuality"> + <el-input + v-model="form.workDetail.bpMaterialQuality" + autosize + type="textarea" + placeholder="请输入" + /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="盲板规格" prop="workDetail.bpSpecification"> + <el-input + v-model="form.workDetail.bpSpecification" + autosize + type="textarea" + placeholder="请输入" + /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="盲板时间" prop="workDetail.installLine"> + <el-date-picker + v-model="form.workDetail.installLine" + format="YYYY-MM-DD HH:mm" + value-format="YYYY-MM-DD HH:mm:00" + type="datetimerange" + range-separator="--" + start-placeholder="装盲板时间" + end-placeholder="拆盲板时间" + /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="盲板位置" prop="workDetail.bpLocation"> + <el-input + v-model="form.workDetail.bpLocation" + autosize + type="textarea" + placeholder="请输入" + /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="关联作业" prop="workDetail.otherSpecialWork"> + <el-select v-model="form.workDetail.otherSpecialWork" multiple> + <el-option + v-for="item in otherWorkList" + :key="item.value" + :label="item.label" + :value="item.value" + /> + </el-select> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="24"> + <el-form-item label="盲板位置图" prop="workDetail.bpLocationMapPath"> + <el-upload accept="image/*" :on-exceed="showTip" :on-preview="handlePictureCardPreview" :limit='imgLimit' v-model:file-list="fileList" :http-request="upload" :action="uploadUrl" list-type="picture-card" :on-remove="handleRemove" :before-remove="beforeRemove" :before-upload="getUploadUrl"> + <el-icon><Plus /></el-icon> + <template #tip> + <div class="el-upload__tip">上传jpg/png图片尺寸小于500KB,最多可上传3张</div> + </template> + </el-upload> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="选择关联物资"> + <el-button type="primary" @click="openMaList">选择物资标准</el-button> + </el-form-item> + </el-col> + </el-row> + </div> + </el-form> + <material-dialog ref="material" @conFirmMaterials="conFirmMaterials"></material-dialog> + <div class="applyBtn"> + <el-button type="primary" size="large" plain @click="submitForm(ruleFormRef)">发起申请</el-button> + </div> + </div> + <el-dialog v-model="dialogVisible"> + <img w-full :src="dialogImageUrl" alt="Preview Image" /> + </el-dialog> + </div> +</template> + +<script lang="ts"> +import {toRefs, reactive, defineComponent, ref, defineAsyncComponent} from 'vue'; + import { storeToRefs } from 'pinia'; + import { initBackEndControlRoutes } from '/@/router/backEnd'; + import {useUserInfo} from "/@/stores/userInfo"; + import { Session } from '/@/utils/storage'; + import { Search } from '@element-plus/icons-vue' + import { ElMessage, ElMessageBox } from 'element-plus' + import type { FormInstance, FormRules, UploadProps, UploadUserFile } from 'element-plus' + import { workApplyApi } from '/@/api/specialWorkSystem/workApply'; + import axios from 'axios'; + + interface stateType { + form: Object, + csDepList: Array<any>, + otherWorkList: Array<any>, + workLevelList: Array<any>, + fileList: Array<file>, + uploadUrl: string, + dialogVisible: Boolean, + dialogImageUrl: string | null, + imgLimit: number, + isOverSize: boolean, + equipmentDialog: boolean + } + interface file { + url: string; + } + export default defineComponent({ + name: 'plateForm', + components: { + materialDialog: defineAsyncComponent(() => import('/@/views/specialWorkSystem/workTicket/zysq/components/materialDialog.vue')), + }, + props:['workerList'], + setup(props: any, context: any) { + const userInfo = useUserInfo() + const { userInfos } = storeToRefs(userInfo); + const state = reactive<stateType>({ + equipmentDialog: false, + form: { + operatorUids: [], + workType: 8, + workLevel: null, + workContent: '', + workLocation: '', + maBaseId: null, + hazardIdentification: '', + workDetail:{ + bpCode: '', + mainMedia: '', + temperature: null, + pressure: null, + bpMaterialQuality: '', + bpSpecification: '', + bpLocation: '', + bpLocationMapPath: [], + installLine: [], + installBpTime: '', + uninstallBpTime: '', + otherSpecialWork: [] + }, + receiveUids: [], + workTimeLine: [], + expStartTime: '', + expEndTime: '' + }, + isOverSize: false, + fileList: [], + imgLimit: 3, + uploadUrl: '', + dialogVisible: false, + dialogImageUrl: null, + workLevelList: [ + { + label: "抽盲板作业", + value: 11 + }, + { + label: "堵盲板作业", + value: 12 + } + ], + csDepList: [ + { + label: "单位一", + value: 1 + }, + { + label: "单位二", + value: 2 + }, + { + label: "单位三", + value: 3 + }, + { + label: "单位四", + value: 4 + }, + { + label: "单位五", + value: 5 + }, + { + label: "单位六", + value: 6 + } + ], + otherWorkList: [ + { + label: "动火作业", + value: 1 + }, + { + label: "受限空间作业", + value: 2 + }, + { + label: "吊装作业", + value: 3 + }, + { + label: "动土作业", + value: 4 + }, + { + label: "断路作业", + value: 5 + }, + { + label: "高处作业", + value: 6 + }, + { + label: "临时用电作业", + value: 7 + }, + { + label: "盲板抽堵作业", + value: 8 + } + ] + }); + const material = ref() + const ruleFormRef = ref<FormInstance>() + const applyRules = reactive<FormRules>({ + operatorUids: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + workType: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + workLevel: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + workContent: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + workLocation: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + hazardIdentification: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + workTimeLine: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + "workDetail.bpCode": [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + "workDetail.mainMedia": [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + "workDetail.temperature": [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + "workDetail.pressure": [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + "workDetail.bpMaterialQuality": [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + "workDetail.bpSpecification": [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + "workDetail.installLine": [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + "workDetail.bpLocation": [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + "workDetail.bpLocationMapPath": [{ required: true, message: '该内容不能为空', trigger: 'blur' }] + }); + + // const toZero = (value: string | number,index: number,name: string,x:number) =>{ + // if(!value){ + // state.materialList[index][name][x].value = 0 + // } + // } + const openMaList = ()=>{ + if(state.form.workLevel == null || state.form.operatorUids == []){ + ElMessage({ + type: 'warning', + message: '请先选择作业人和作业等级再获取相应物资配置' + }); + }else{ + if(material.value.receiveUids.length==0){ + material.value.receiveUids = state.form.operatorUids + } + material.value.getMaList(state.form.workType,state.form.workLevel) + material.value.workerList = props.workerList + } + } + const conFirmMaterials = (receiveUids: Array<number>,chosenId: number) =>{ + state.form.maBaseId = null + state.form.receiveUids = [] + state.form.receiveUids = receiveUids + state.form.maBaseId = chosenId + } + const submitForm = async (formEl: FormInstance | undefined) => { + if (!formEl) return + await formEl.validate(async (valid, fields) => { + if (valid) { + state.form.expStartTime = JSON.parse(JSON.stringify(state.form.workTimeLine))[0] + state.form.expEndTime = JSON.parse(JSON.stringify(state.form.workTimeLine))[1] + state.form.workDetail.installBpTime = JSON.parse(JSON.stringify(state.form.workDetail.installLine))[0] + state.form.workDetail.uninstallBpTime = JSON.parse(JSON.stringify(state.form.workDetail.installLine))[1] + let { workTimeLine, ...data } = JSON.parse(JSON.stringify(state.form)) + let { installLine, ...data2 } = JSON.parse(JSON.stringify(state.form.workDetail)) + data.workDetail = data2 + data.workDetail.otherSpecialWork = data.workDetail.otherSpecialWork.join(',') + data.workDetail.bpLocationMapPath = data.workDetail.bpLocationMapPath.join(',') + data.workDetail.temperature = Number(data.workDetail.temperature) + data.workDetail.pressure = Number(data.workDetail.pressure) + const res = await workApplyApi().postPlateApply(data) + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '提交成功!' + }); + formEl.resetFields() + state.form.workDetail.bpLocationMapPath = [] + state.fileList = [] + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + material.value.maBaseId = null + material.value.receiveUids = [] + } else { + console.log('error submit!', fields) + } + }) + } + const handlePreview: UploadProps['onPreview'] = (uploadFile) => { + console.log(uploadFile); + }; + + const handlePictureCardPreview = (uploadFile: { url: string }) => { + state.dialogImageUrl = uploadFile.url!; + state.dialogVisible = true; + }; + + const getUploadUrl = async (rawFile: any) => { + const fileSize = rawFile.size / 1024 < 500 ? '1' : '0' + if(fileSize === '0'){ + ElMessage({ + type: 'warning', + message: '文件大小不能超过500k。' + }); + state.isOverSize = true + return false + }else{ + const res = await workApplyApi().getUploadUrl(rawFile.name); + state.form.workDetail.bpLocationMapPath.push(res.data.data.fileName) + state.uploadUrl = res.data.data.uploadUrl; + console.log(res.data.data.fileName,'name') + } + }; + + const upload = async (params: any) => { + // const formData = new FormData(); + // formData.append('file', state.fileList[0].raw); + let reader = new FileReader(); + reader.readAsArrayBuffer(params.file); + reader.onload = async () => { + axios + .put(state.uploadUrl, reader.result, { + header: { 'Content-Type': 'multipart/form-data' } + }) + .then(() => { + // if (state.fileList.length === 2) { + // state.fileList.splice(0, 1); + // } + // console.log(state.form.workDetail.bpLocationMapPath,'bpLocationMapPath') + }); + }; + }; + + const beforeRemove = (file: {}, fileList: []) => { + const result = new Promise((resolve, reject) => { + if(!state.isOverSize){ + ElMessageBox.confirm('此操作将删除该图片, 是否继续?', '提示', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning' + }) + .then(() => { + // console.log(state.workDetail.bpLocationMapPath,'path') + const list = JSON.parse(JSON.stringify(state.form.workDetail.bpLocationMapPath)) + fileList.map((item,index)=>{ + if(item.uid === file.uid){ + fileList.splice(index,1) + state.form.workDetail.bpLocationMapPath.splice(index,1) + deletePic(false,list[index]) + } + }) + // 请求删除接口 + }) + .catch(() => { + reject(false); + }); + }else{ + const list = JSON.parse(JSON.stringify(state.form.workDetail.bpLocationMapPath)) + fileList.map((item,index)=>{ + if(item.uid === file.uid){ + fileList.splice(index,1) + state.form.workDetail.bpLocationMapPath.splice(index,1) + deletePic(true,list[index]) + } + }) + state.isOverSize = false + } + }); + return result; + }; + + + // 删除图片接口 + const deletePic = async(isOverSize:boolean,fileName:string)=>{ + console.log(fileName,'fileName') + const res = await workApplyApi().deleteFile({fileName: fileName}) + if (res.data.code === '200') { + ElMessage({ + type: isOverSize ? 'error' : 'success', + message: isOverSize ? '上传失败':'删除成功!' + }); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } + const showTip =()=>{ + ElMessage({ + type: 'warning', + message: '超出文件上传数量' + }); + } + + // 折线图 + const renderMenu = async (value: string) => { + Session.set('projectId',value) + userInfos.value.projectId = value + await initBackEndControlRoutes(); + }; + return { + renderMenu, + Search, + ruleFormRef, + applyRules, + material, + openMaList, + conFirmMaterials, + handlePreview, + getUploadUrl, + beforeRemove, + upload, + showTip, + submitForm, + handlePictureCardPreview, + ...toRefs(state), + }; + }, + }); +</script> + +<style scoped lang="scss"> + .home-container { + height: 100%; + overflow: hidden; + position: relative; + .homeCard{ + width: 100%; + padding: 20px; + box-sizing: border-box; + background: #fff; + border-radius: 4px; + margin-bottom: 20px; + } + .applyBtn{ + width: 100%; + background: #fff; + padding-top: 15px; + z-index: 5; + box-shadow: 0 -3px 8px rgba(150,150,150,.1); + display: flex; + align-items: center; + justify-content: center; + } + .el-row{ + margin-bottom: 20px; + } + .el-row:last-child { + margin-bottom: 0; + } + .el-input{ + width: 100% !important; + } + .el-date-editor::v-deep{ + width: 100%; + } + .el-select{ + width: 100%; + } + .el-cascader{ + width: 100% !important; + } + } +</style> diff --git a/src/views/specialWorkSystem/workTicket/zysq/components/power.vue b/src/views/specialWorkSystem/workTicket/zysq/components/power.vue new file mode 100644 index 0000000..07d84b4 --- /dev/null +++ b/src/views/specialWorkSystem/workTicket/zysq/components/power.vue @@ -0,0 +1,294 @@ +<template> + <div class="home-container"> + <div style="height: 100%"> + <el-form :model="form" label-width="150px" :rules="applyRules" ref="ruleFormRef"> + <div class="homeCard"> + <el-row> + <el-col :span="12"> + <el-form-item label="作业人" prop="operatorUids"> + <el-select v-model="form.operatorUids" multiple> + <el-option + v-for="item in workerList" + :key="item.uid" + :label="item.username" + :value="item.uid" + /> + </el-select> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="作业时间" prop="workTimeLine"> + <el-date-picker + v-model="form.workTimeLine" + format="YYYY-MM-DD HH:mm" + value-format="YYYY-MM-DD HH:mm:00" + type="datetimerange" + range-separator="至" + start-placeholder="开始时间" + end-placeholder="结束时间" + /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="作业内容" prop="workContent"> + <el-input + v-model="form.workContent" + autosize + type="textarea" + placeholder="请输入作业内容" + /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="作业地址" prop="workLocation"> + <el-input + v-model="form.workLocation" + autosize + type="textarea" + placeholder="请输入作业地址" + /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="危害辨识" prop="hazardIdentification"> + <el-input + v-model="form.hazardIdentification" + placeholder="请输入危害辨识" + /> + </el-form-item> + </el-col> + </el-row> + <el-divider border-style="dashed"/> + <el-row> + <el-col :span="12"> + <el-form-item label="电源接入点" prop="workDetail.powerAccessPoint"> + <el-input + v-model="form.workDetail.powerAccessPoint" + autosize + type="textarea" + placeholder="请输入" + /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="工作电压" prop="workDetail.workingVoltage"> + <el-input + v-model="form.workDetail.workingVoltage" + type="number" + placeholder="请输入工作电压(大于等于0)" + > + <template #append>伏特(v)</template> + </el-input> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="用电设备及功率" prop="workDetail.equipmentAndPower"> + <el-input + v-model="form.workDetail.equipmentAndPower" + autosize + type="textarea" + placeholder="请输入" + /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="选择关联物资"> + <el-button type="primary" @click="openMaList">选择物资标准</el-button> + </el-form-item> + </el-col> + </el-row> + </div> + </el-form> + <material-dialog ref="material" @conFirmMaterials="conFirmMaterials"></material-dialog> + <div class="applyBtn"> + <el-button type="primary" size="large" plain @click="submitForm(ruleFormRef)">发起申请</el-button> + </div> + </div> + </div> +</template> + +<script lang="ts"> +import {toRefs, reactive, defineComponent, ref, defineAsyncComponent} from 'vue'; + import { storeToRefs } from 'pinia'; + import { initBackEndControlRoutes } from '/@/router/backEnd'; + import {useUserInfo} from "/@/stores/userInfo"; + import { Session } from '/@/utils/storage'; + import { Search } from '@element-plus/icons-vue' + import { ElMessage, ElMessageBox } from 'element-plus' + import type { FormInstance, FormRules } from 'element-plus' + import { workApplyApi } from '/@/api/specialWorkSystem/workApply'; + + interface stateType { + form: Object, + equipmentDialog: boolean + } + export default defineComponent({ + name: 'powerForm', + components: { + materialDialog: defineAsyncComponent(() => import('/@/views/specialWorkSystem/workTicket/zysq/components/materialDialog.vue')), + }, + props:['workerList'], + setup(props: any, context: any) { + const userInfo = useUserInfo() + const { userInfos } = storeToRefs(userInfo); + const state = reactive<stateType>({ + equipmentDialog: false, + form: { + operatorUids: [], + workType: 7, + workLevel: 0, + workContent: '', + workLocation: '', + maBaseId: null, + hazardIdentification: '', + workDetail:{ + powerAccessPoint: '', + workingVoltage: null, + equipmentAndPower: '' + }, + receiveUids: [], + workTimeLine: [], + expStartTime: '', + expEndTime: '' + } + }); + const material = ref() + const ruleFormRef = ref<FormInstance>() + const applyRules = reactive<FormRules>({ + operatorUids: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + workType: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + workContent: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + workLocation: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + hazardIdentification: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + workTimeLine: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + "workDetail.powerAccessPoint": [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + "workDetail.workingVoltage": [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + "workDetail.equipmentAndPower": [{ required: true, message: '该内容不能为空', trigger: 'blur' }] + }); + + // const toZero = (value: string | number,index: number,name: string,x:number) =>{ + // if(!value){ + // state.materialList[index][name][x].value = 0 + // } + // } + + const openMaList = ()=>{ + if(state.form.operatorUids == []){ + ElMessage({ + type: 'warning', + message: '请先选择作业人再获取相应物资配置' + }); + }else{ + if(material.value.receiveUids.length==0){ + material.value.receiveUids = state.form.operatorUids + } + material.value.getMaList(state.form.workType,state.form.workLevel) + material.value.workerList = props.workerList + } + } + const conFirmMaterials = (receiveUids: Array<number>,chosenId: number) =>{ + state.form.maBaseId = null + state.form.receiveUids = [] + state.form.receiveUids = receiveUids + state.form.maBaseId = chosenId + } + + const submitForm = async (formEl: FormInstance | undefined) => { + if (!formEl) return + await formEl.validate(async (valid, fields) => { + if (valid) { + state.form.expStartTime = JSON.parse(JSON.stringify(state.form.workTimeLine))[0] + state.form.expEndTime = JSON.parse(JSON.stringify(state.form.workTimeLine))[1] + let { workTimeLine, ...data } = JSON.parse(JSON.stringify(state.form)) + // data.workDetail.weightMass = Number(data.workDetail.weightMass) + const res = await workApplyApi().postPowerApply(data) + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '提交成功!' + }); + formEl.resetFields() + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + material.value.maBaseId = null + material.value.receiveUids = [] + } else { + console.log('error submit!', fields) + } + }) + } + + // 折线图 + const renderMenu = async (value: string) => { + Session.set('projectId',value) + userInfos.value.projectId = value + await initBackEndControlRoutes(); + }; + return { + renderMenu, + Search, + ruleFormRef, + applyRules, + material, + openMaList, + conFirmMaterials, + submitForm, + ...toRefs(state), + }; + }, + }); +</script> + +<style scoped lang="scss"> + .home-container { + height: 100%; + overflow: hidden; + position: relative; + .homeCard{ + width: 100%; + padding: 20px; + box-sizing: border-box; + background: #fff; + border-radius: 4px; + margin-bottom: 20px; + } + .applyBtn{ + width: 100%; + background: #fff; + padding-top: 15px; + z-index: 5; + box-shadow: 0 -3px 8px rgba(150,150,150,.1); + display: flex; + align-items: center; + justify-content: center; + } + .el-row{ + margin-bottom: 20px; + } + .el-row:last-child { + margin-bottom: 0; + } + .el-input{ + width: 100% !important; + } + .el-date-editor::v-deep{ + width: 100%; + } + .el-select{ + width: 100%; + } + .el-cascader{ + width: 100% !important; + } + } +</style> diff --git a/src/views/specialWorkSystem/workTicket/zysq/components/space.vue b/src/views/specialWorkSystem/workTicket/zysq/components/space.vue new file mode 100644 index 0000000..a474192 --- /dev/null +++ b/src/views/specialWorkSystem/workTicket/zysq/components/space.vue @@ -0,0 +1,379 @@ +<template> + <div class="home-container"> + <div style="height: 100%"> + <el-form :model="form" label-width="150px" :rules="applyRules" ref="ruleFormRef"> + <div class="homeCard"> + <el-row> + <el-col :span="12"> + <el-form-item label="作业人" prop="operatorUids"> + <el-select v-model="form.operatorUids" multiple> + <el-option + v-for="item in workerList" + :key="item.uid" + :label="item.username" + :value="item.uid" + /> + </el-select> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="作业时间" prop="workTimeLine"> + <el-date-picker + v-model="form.workTimeLine" + format="YYYY-MM-DD HH:mm" + value-format="YYYY-MM-DD HH:mm:00" + type="datetimerange" + range-separator="至" + start-placeholder="开始时间" + end-placeholder="结束时间" + /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="作业内容" prop="workContent"> + <el-input + v-model="form.workContent" + autosize + type="textarea" + placeholder="请输入作业内容" + /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="作业地址" prop="workLocation"> + <el-input + v-model="form.workLocation" + autosize + type="textarea" + placeholder="请输入作业地址" + /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="危害辨识" prop="hazardIdentification"> + <el-input + v-model="form.hazardIdentification" + placeholder="请输入危害辨识" + /> + </el-form-item> + </el-col> + </el-row> + <el-divider border-style="dashed" /> + <el-row> + <el-col :span="12"> + <el-form-item label="受限空间所属单位" prop="workDetail.csDepId"> +<!-- <el-select v-model="form.workDetail.csDepId">--> +<!-- <el-option--> +<!-- v-for="item in csDepList"--> +<!-- :key="item.value"--> +<!-- :label="item.label"--> +<!-- :value="item.value"--> +<!-- />--> +<!-- </el-select>--> + <el-cascader v-model="form.workDetail.csDepId" :options="departList" :props="casProps" :show-all-levels="false" @change="handleChange" /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="受限空间名称" prop="workDetail.csName"> + <el-input + v-model="form.workDetail.csName" + autosize + type="textarea" + placeholder="请输入" + /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="空间内原有介质" prop="workDetail.csOriginalName"> + <el-input + v-model="form.workDetail.csOriginalName" + autosize + type="textarea" + placeholder="请输入" + /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="关联作业" prop="workDetail.otherSpecialWork"> + <el-select v-model="form.workDetail.otherSpecialWork" multiple> + <el-option v-for="item in otherWorkList" :key="item.value" :label="item.label" :value="item.value" /> + </el-select> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="选择关联物资"> + <el-button type="primary" @click="openMaList">选择物资标准</el-button> + </el-form-item> + </el-col> + </el-row> + </div> + </el-form> + <material-dialog ref="material" @conFirmMaterials="conFirmMaterials"></material-dialog> + <div class="applyBtn"> + <el-button type="primary" size="large" plain @click="submitForm(ruleFormRef)">发起申请</el-button> + </div> + </div> + </div> +</template> + +<script lang="ts"> +import {toRefs, reactive, defineComponent, ref, defineAsyncComponent} from 'vue'; + import { storeToRefs } from 'pinia'; + import { initBackEndControlRoutes } from '/@/router/backEnd'; + import {useUserInfo} from "/@/stores/userInfo"; + import { Session } from '/@/utils/storage'; + import { Search } from '@element-plus/icons-vue' + import { ElMessage, ElMessageBox } from 'element-plus' + import type { FormInstance, FormRules } from 'element-plus' + import { workApplyApi } from '/@/api/specialWorkSystem/workApply'; + + interface stateType { + form: Object, + csDepList: Array<any>, + otherWorkList: Array<any>, + casProps: {}, + equipmentDialog: boolean + } + export default defineComponent({ + name: 'spaceForm', + components: { + materialDialog: defineAsyncComponent(() => import('/@/views/specialWorkSystem/workTicket/zysq/components/materialDialog.vue')), + }, + props:['workerList','departList'], + setup(props: any, context: any) { + const userInfo = useUserInfo() + const { userInfos } = storeToRefs(userInfo); + const state = reactive<stateType>({ + equipmentDialog: false, + form: { + operatorUids: [], + workType: 2, + workLevel: 0, + workContent: '', + workLocation: '', + maBaseId: null, + hazardIdentification: '', + workDetail:{ + csDepId: null, + csName: '', + csOriginalName: '', + otherSpecialWork: [] + }, + receiveUids: [], + workTimeLine: [], + expStartTime: '', + expEndTime: '' + }, + csDepList: [ + { + label: "单位一", + value: 1 + }, + { + label: "单位二", + value: 2 + }, + { + label: "单位三", + value: 3 + }, + { + label: "单位四", + value: 4 + }, + { + label: "单位五", + value: 5 + }, + { + label: "单位六", + value: 6 + } + ], + casProps: { + emitPath: false, + value: 'depId', + label: 'depName', + multiple: false, + expandTrigger: 'hover', + checkStrictly: true + }, + otherWorkList: [ + { + label: '动火作业', + value: 1 + }, + { + label: '受限空间作业', + value: 2 + }, + { + label: '吊装作业', + value: 3 + }, + { + label: '动土作业', + value: 4 + }, + { + label: '断路作业', + value: 5 + }, + { + label: '高处作业', + value: 6 + }, + { + label: '临时用电作业', + value: 7 + }, + { + label: '盲板抽堵作业', + value: 8 + } + ] + }); + const material = ref() + const ruleFormRef = ref<FormInstance>() + const applyRules = reactive<FormRules>({ + operatorUids: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + workType: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + workContent: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + workLocation: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + hazardIdentification: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + workTimeLine: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + "workDetail.csDepId": [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + "workDetail.csName": [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + "workDetail.csOriginalName": [{ required: true, message: '该内容不能为空', trigger: 'blur' }] + }); + + // const toZero = (value: string | number,index: number,name: string,x:number) =>{ + // if(!value){ + // state.materialList[index][name][x].value = 0 + // } + // } + + const openMaList = ()=>{ + if(state.form.operatorUids == []){ + ElMessage({ + type: 'warning', + message: '请先选择作业人再获取相应物资配置' + }); + }else{ + if(material.value.receiveUids.length==0){ + material.value.receiveUids = state.form.operatorUids + } + material.value.getMaList(state.form.workType,state.form.workLevel) + material.value.workerList = props.workerList + } + } + const conFirmMaterials = (receiveUids: Array<number>,chosenId: number) =>{ + state.form.maBaseId = null + state.form.receiveUids = [] + state.form.receiveUids = receiveUids + state.form.maBaseId = chosenId + } + + const submitForm = async (formEl: FormInstance | undefined) => { + if (!formEl) return + await formEl.validate(async (valid, fields) => { + if (valid) { + state.form.expStartTime = JSON.parse(JSON.stringify(state.form.workTimeLine))[0] + state.form.expEndTime = JSON.parse(JSON.stringify(state.form.workTimeLine))[1] + let { workTimeLine, ...data } = JSON.parse(JSON.stringify(state.form)) + data.workDetail.otherSpecialWork = data.workDetail.otherSpecialWork.join(',') + console.log(data,'data') + const res = await workApplyApi().postSpaceApply(data) + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '提交成功!' + }); + formEl.resetFields() + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + material.value.maBaseId = null + material.value.receiveUids = [] + } else { + console.log('error submit!', fields) + } + }) + } + + + // 折线图 + const renderMenu = async (value: string) => { + Session.set('projectId',value) + userInfos.value.projectId = value + await initBackEndControlRoutes(); + }; + return { + renderMenu, + Search, + ruleFormRef, + applyRules, + material, + openMaList, + conFirmMaterials, + submitForm, + ...toRefs(state), + }; + }, + }); +</script> + +<style scoped lang="scss"> + .home-container { + height: 100%; + overflow: hidden; + position: relative; + .homeCard{ + width: 100%; + padding: 20px; + box-sizing: border-box; + background: #fff; + border-radius: 4px; + margin-bottom: 20px; + } + .applyBtn{ + width: 100%; + background: #fff; + padding-top: 15px; + z-index: 5; + box-shadow: 0 -3px 8px rgba(150,150,150,.1); + display: flex; + align-items: center; + justify-content: center; + } + .el-row{ + margin-bottom: 20px; + } + .el-row:last-child { + margin-bottom: 0; + } + .el-input{ + width: 100% !important; + } + .el-date-editor::v-deep{ + width: 100%; + } + .el-select{ + width: 100%; + } + :deep(.el-cascader){ + width: 100% !important; + } + } +</style> diff --git a/src/views/specialWorkSystem/workTicket/zysq/index.vue b/src/views/specialWorkSystem/workTicket/zysq/index.vue new file mode 100644 index 0000000..fea4f09 --- /dev/null +++ b/src/views/specialWorkSystem/workTicket/zysq/index.vue @@ -0,0 +1,177 @@ +<template> + <div class="home-container"> + <el-tabs type="border-card" @tab-change="switchTab"> + <el-tab-pane label="动火作业"> + <fire-form ref="fire" :workerList = allWorkers></fire-form> + </el-tab-pane> + <el-tab-pane label="受限空间作业"> + <space-form ref="space" :workerList = allWorkers :departList = departmentList></space-form> + </el-tab-pane> + <el-tab-pane label="吊装作业"> + <hoist-form ref="hoist" :workerList = allWorkers></hoist-form> + </el-tab-pane> + <el-tab-pane label="动土作业"> + <ground-form ref="ground" :workerList = allWorkers :departList = departmentList></ground-form> + </el-tab-pane> + <el-tab-pane label="断路作业"> + <broken-form ref="broken" :workerList = allWorkers :departList = departmentList></broken-form> + </el-tab-pane> + <el-tab-pane label="高处作业"> + <height-form ref="height" :workerList = allWorkers :departList = departmentList></height-form> + </el-tab-pane> + <el-tab-pane label="临时用电作业"> + <power-form ref="power" :workerList = allWorkers></power-form> + </el-tab-pane> + <el-tab-pane label="盲板抽堵作业"> + <plate-form ref="plate" :workerList = allWorkers></plate-form> + </el-tab-pane> + </el-tabs> + <material-dialog ref="material"></material-dialog> + </div> +</template> + +<script lang="ts"> + import {toRefs, reactive, defineComponent, ref, defineAsyncComponent, onMounted} from 'vue'; + import { storeToRefs } from 'pinia'; + import { initBackEndControlRoutes } from '/@/router/backEnd'; + import {useUserInfo} from "/@/stores/userInfo"; + import { Session } from '/@/utils/storage'; + import { Search } from '@element-plus/icons-vue' + import { ElMessage } from 'element-plus' + import type { FormInstance, FormRules } from 'element-plus' + import { workApplyApi } from '/@/api/specialWorkSystem/workApply'; + import {teamManageApi} from "/@/api/systemManage/basicDateManage/personShiftManage/teamManage"; + + interface stateType { + allWorkers: Array<any> + departmentList: Array<any> + } + export default defineComponent({ + name: 'apply', + components: { + fireForm: defineAsyncComponent(() => import('/@/views/specialWorkSystem/workTicket/zysq/components/fire.vue')), + spaceForm: defineAsyncComponent(() => import('/@/views/specialWorkSystem/workTicket/zysq/components/space.vue')), + hoistForm: defineAsyncComponent(() => import('/@/views/specialWorkSystem/workTicket/zysq/components/hoist.vue')), + groundForm: defineAsyncComponent(() => import('/@/views/specialWorkSystem/workTicket/zysq/components/ground.vue')), + brokenForm: defineAsyncComponent(() => import('/@/views/specialWorkSystem/workTicket/zysq/components/broken.vue')), + heightForm: defineAsyncComponent(() => import('/@/views/specialWorkSystem/workTicket/zysq/components/height.vue')), + powerForm: defineAsyncComponent(() => import('/@/views/specialWorkSystem/workTicket/zysq/components/power.vue')), + plateForm: defineAsyncComponent(() => import('/@/views/specialWorkSystem/workTicket/zysq/components/plate.vue')), + materialDialog: defineAsyncComponent(() => import('/@/views/specialWorkSystem/workTicket/zysq/components/materialDialog.vue')) + }, + setup() { + const userInfo = useUserInfo() + const { userInfos } = storeToRefs(userInfo); + const state = reactive<stateType>({ + allWorkers: [], + departmentList: [] + }); + const fire = ref() + const space = ref() + const hoist = ref() + const ground = ref() + const broken = ref() + const height = ref() + const power = ref() + const plate = ref() + const material = ref() + // 获取用户列表 + const getAll = async ()=>{ + const res = await workApplyApi().getAllUsers() + if (res.data.code === '200') { + state.allWorkers = JSON.parse(JSON.stringify(res.data.data)) + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 获取部门列表 + const getAllDepartment = async () => { + let res = await teamManageApi().getAllDepartment(); + if (res.data.code === '200') { + state.departmentList = JSON.parse(JSON.stringify(res.data.data)) + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + const switchTab = (name)=>{ + console.log(name,'name') + fire.value.form.resetFields() + material.value.maBaseId = null + material.value.receiveUids = [] + } + + + // 页面载入时执行方法 + onMounted(() => { + getAll(); + getAllDepartment(); + }); + + return { + ...toRefs(state), + fire, + space, + broken, + ground, + height, + hoist, + plate, + power, + material, + switchTab + }; + }, + }); +</script> + +<style scoped lang="scss"> + .home-container { + height: 100%; + overflow: hidden; + position: relative; + .homeCard{ + width: 100%; + padding: 20px; + box-sizing: border-box; + background: #fff; + border-radius: 4px; + margin-bottom: 20px; + } + .applyBtn{ + width: 100%; + background: #fff; + height: 80px; + z-index: 5; + box-shadow: 0 -3px 8px rgba(150,150,150,.1); + display: flex; + align-items: center; + justify-content: center; + } + .el-row{ + margin-bottom: 20px; + } + .el-row:last-child { + margin-bottom: 0; + } + .el-input{ + width: 100% !important; + } + .el-date-editor::v-deep{ + width: 100%; + } + .el-select{ + width: 100%; + } + .el-cascader{ + width: 100% !important; + } + } +</style> diff --git a/src/views/system/appVersion/index.vue b/src/views/system/appVersion/index.vue new file mode 100644 index 0000000..656c2d7 --- /dev/null +++ b/src/views/system/appVersion/index.vue @@ -0,0 +1,698 @@ +<template> + <div class="home-container"> + <div style="height: 100%"> + <el-row class="homeCard"> + <el-col :span="5" style="display:flex;align-items: center"> + <span style="white-space: nowrap">app类型:</span> + <div class="grid-content topInfo"> + <el-select v-model="searchType"> + <el-option + v-for="item in appTypeList" + :key="item.id" + :label="item.name" + :value="item.id" + /> + </el-select> + </div> + </el-col> + <el-col :span="5" style="display:flex;align-items: center"> + <span style="white-space: nowrap">版本号:</span> + <div class="grid-content topInfo"> + <el-input v-model="searchVersion"/> + </div> + </el-col> + <el-col :span="5" style="display:flex;align-items: center"> + <span style="white-space: nowrap">APP名称:</span> + <div class="grid-content topInfo"> + <el-input v-model="searchName"/> + </div> + </el-col> + <el-button type="primary" @click="searchRecord">查询</el-button> + <el-button plain @click="clearSearch">重置</el-button> + </el-row> + <div class="homeCard"> + <div class="main-card"> + <el-row class="cardTop"> + <el-col :span="12" class="mainCardBtn"> + <el-button type="primary" :icon="Plus" size="default" @click="dialogAddRecord = true">新增</el-button> + </el-col> + <el-button type="primary" :icon="Refresh" size="default" @click="reLoadData()" /> + </el-row> + <el-table ref="multipleTableRef" :data="tableData" style="width: 100%" height="calc(100% - 100px)" :header-cell-style="{ background: '#fafafa' }" @selection-change="handleSelectionChange"> +<!-- <el-table-column type="selection" width="100" />--> + <el-table-column type="index" label="排序" width="80" align="center"/> + <el-table-column property="appTypeDesc" label="文件类型" align="center" :show-overflow-tooltip="true"/> + <el-table-column property="name" label="app名称" align="center" :show-overflow-tooltip="true"/> + <el-table-column property="objectUrl" label="文件链接" align="center" :show-overflow-tooltip="true"/> + <el-table-column property="customVersion" label="版本号" align="center"> + <template #default="scope"> + <el-tag>{{ scope.row.customVersion }}</el-tag> + </template> + </el-table-column> + <el-table-column property="info" label="备注" align="center" :show-overflow-tooltip="true"/> + <el-table-column property="gmtCreate" label="创建时间" align="center"/> + <el-table-column property="gmtModified" label="更新时间" align="center"/> + <el-table-column fixed="right" label="操作" align="center" width="250"> + <template #default="scope"> + <el-button link type="primary" size="small" :icon="View" @click="viewRecord(scope.row)">查看</el-button> + <el-button link type="primary" size="small" :icon="Edit" @click="editRecordBtn(scope.$index, scope.row)">修改</el-button> + <el-button link type="danger" size="small" :icon="Delete" @click="deleteRecordBtn(scope.row)">删除</el-button> + </template> + </el-table-column> + </el-table> + <div class="pageBtn"> + <el-pagination v-model:currentPage="pageIndex" v-model:page-size="pageSize" :page-sizes="[10, 15]" small="false" background layout="total, sizes, prev, pager, next, jumper" :total="totalSize" @size-change="handleSizeChange" @current-change="handleCurrentChange" /> + </div> + </div> + </div> + </div> + <el-dialog v-model="dialogDetails" title="APP版本信息"> + <el-form :model="details" label-width="120px"> + <el-form-item label="类型"> + <el-input v-model="details.appTypeDesc" readonly /> + </el-form-item> + <el-form-item label="app名称"> + <el-input v-model="details.name" readonly/> + </el-form-item> + <el-form-item label="文件链接"> + <el-input v-model="details.objectUrl" type="textarea" autosize readonly /> + </el-form-item> + <el-form-item label="版本号"> + <el-input v-model="details.customVersion" type="textarea" readonly /> + </el-form-item> + <el-form-item label="备注"> + <el-input v-model="details.info" type="textarea" readonly /> + </el-form-item> + <el-form-item label="创建时间"> + <el-input v-model="details.gmtCreate" readonly /> + </el-form-item> + <el-form-item label="更新时间"> + <el-input v-model="details.gmtModified" readonly /> + </el-form-item> + <el-form-item> + <el-button type="primary" @click="dialogDetails = false" size="default">确认</el-button> + </el-form-item> + </el-form> + </el-dialog> + <el-dialog v-model="dialogAddRecord" title="APP版本信息编辑" @close="closeAdd" @open="openAdd"> + <el-form :model="addRecord" label-width="150px" ref="addRef" :rules="addRules"> + <el-form-item label="类型" prop="appType"> + <el-select v-model="addRecord.appType"> + <el-option + v-for="item in appTypeList" + :key="item.id" + :label="item.name" + :value="item.id" + /> + </el-select> + </el-form-item> + <el-form-item label="app名称" prop="name"> + <el-input v-model="addRecord.name"/> + </el-form-item> + <el-form-item v-if="chosenIndex == null" label="上传文件" prop="objectName"> + <el-upload :on-exceed="showTip" :on-preview="handlePictureCardPreview" :limit='fileLimit' v-model:file-list="fileList" :http-request="upload" :action="uploadUrl" :on-remove="handleRemove" :before-remove="beforeRemove" :before-upload="getUploadUrl"> + <el-button type="primary" plain>选择文件</el-button> + <template #tip> + <div class="el-upload__tip">上传APP源文件</div> + </template> + </el-upload> + </el-form-item> + <el-form-item v-else label="上传文件"> + <el-upload :on-exceed="showTip" :on-preview="handlePictureCardPreview" :limit='fileLimit' v-model:file-list="fileList" :http-request="upload" :action="uploadUrl" :on-remove="handleRemove" :before-remove="beforeRemove" :before-upload="getUploadUrl"> + <el-button type="primary" plain>选择文件</el-button> + <template #tip> + <div class="el-upload__tip">上传新版APP源文件(不上传则默认使用原版本)</div> + </template> + </el-upload> + </el-form-item> + <el-form-item label="自定义版本号" prop="customVersion"> + <el-input v-model="addRecord.customVersion"> </el-input> + </el-form-item> + <el-form-item label="备注" prop="info"> + <el-input v-model="addRecord.info" type="textarea" :rows="2" autosize> </el-input> + </el-form-item> + <el-form-item> + <el-button type="warning" @click="dialogAddRecord = false" size="default" plain>取消</el-button> + <el-button type="primary" @click="confirmAddRecord(addRef)" size="default">确认</el-button> + </el-form-item> + </el-form> + </el-dialog> + <el-dialog v-model="deleteDialog" title="提示" width="30%" center @close="indexClear"> + <span>您确定要删除该条记录吗?</span> + <template #footer> + <span class="dialog-footer"> + <el-button @click="deleteDialog = false" size="default">取消</el-button> + <el-button type="primary" @click="conFirmDelete" size="default">确认</el-button> + </span> + </template> + </el-dialog> +<!-- <el-dialog v-model="deleteSetDialog" title="提示" width="30%" center>--> +<!-- <span>您确定要删除这些记录吗?</span>--> +<!-- <template #footer>--> +<!-- <span class="dialog-footer">--> +<!-- <el-button @click="deleteSetDialog = false" size="default">取消</el-button>--> +<!-- <el-button type="primary" @click="conFirmDeleteBatch" size="default">确认</el-button>--> +<!-- </span>--> +<!-- </template>--> +<!-- </el-dialog>--> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, ref, onMounted } from 'vue'; +import { storeToRefs } from 'pinia'; +import { initBackEndControlRoutes } from '/@/router/backEnd'; +import { useUserInfo } from '/@/stores/userInfo'; +import { Session } from '/@/utils/storage'; +import { Edit, View, Plus, Delete, Refresh, Search, Download } from '@element-plus/icons-vue'; +import { ElMessage, ElMessageBox } from 'element-plus'; +import type { FormInstance, FormRules, UploadProps, UploadUserFile } from 'element-plus' +import { appVersionApi } from '/@/api/systemManage/appVersion'; +import {workApplyApi} from "/@/api/specialWorkSystem/workApply"; +import axios from "axios"; + +// 定义接口来定义对象的类型 +interface stateType { + tableData: Array<any>; + multipleSelection: Array<any>; + deleteArr: Array<any>; + dialogDetails: boolean; + dialogAddRecord: boolean; + deleteDialog: boolean; + deleteSetDialog: boolean; + pageIndex: number; + pageSize: number; + chosenIndex: null | number; + deleteId: null | number; + searchType: number; + appTypeList: Array<any>; + searchVersion: string; + searchName: string; + totalSize: number; + addRecord: {}; + details: {}; + fileLimit: number; + uploadUrl: string; + fileList: Array<file> +} +interface file { + url: string; +} +export default { + name: 'appVersion', + components: {}, + setup() { + const userInfo = useUserInfo(); + const { userInfos } = storeToRefs(userInfo); + const state = reactive<stateType>({ + pageIndex: 1, + pageSize: 10, + totalSize: 0, + chosenIndex: null, + searchType: 1, + appTypeList: [ + { + name: '国泰app', + id: 1 + }, + { + name: '其他', + id: 0 + } + ], + searchVersion: '', + searchName: '', + tableData: [], + fileLimit: 1, + uploadUrl: '', + multipleSelection: [], + dialogDetails: false, + dialogAddRecord: false, + deleteDialog: false, + deleteSetDialog: false, + addRecord: { + appType: 1, + name: '', + objectName: '', + info: '', + customVersion: '' + }, + details: {}, + deleteId: null, + deleteArr: [], + fileList: [] + }); + interface User { + + } + // const multipleTableRef = ref<InstanceType<typeof ElTable>>(); + // const toggleSelection = (rows?: User[]) => { + // if (rows) { + // rows.forEach((row) => { + // // TODO: improvement typing when refactor table + // // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // // @ts-expect-error + // multipleTableRef.value!.toggleRowSelection(row, undefined); + // }); + // } else { + // multipleTableRef.value!.clearSelection(); + // } + // }; + + // 多选 + // const handleSelectionChange = (val: User[]) => { + // state.multipleSelection = JSON.parse(JSON.stringify(val)); + // state.deleteArr = state.multipleSelection.map((item) => { + // item = item.id; + // return item; + // }); + // }; + + const addRef = ref<FormInstance>(); + const addRules = reactive<FormRules>({ + appType: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + name: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + objectName: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + customVersion: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + info: [{ required: true, message: '该内容不能为空', trigger: 'blur' }] + }); + + // 页面载入时执行方法 + onMounted(() => { + getListByPage(); + }); + + // 分页获取物资标准列表 + const getListByPage = async () => { + const data = { pageSize: state.pageSize, pageIndex: state.pageIndex, searchParams: { appType: state.searchType, customVersion: state.searchVersion, appName: state.searchName} }; + let res = await appVersionApi().getRecordPage(data); + if (res.data.code === '200') { + state.tableData = JSON.parse(JSON.stringify(res.data.data)) + state.totalSize = res.data.total; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // const handleChange = async (value) => { + // state.addRecord.depId = value; + // console.log(state.addRecord.department, 'de'); + // let res = await appVersionApi().getAllMember(value); + // if (res.data.code === '200') { + // state.workerList = res.data.data; + // } else { + // ElMessage({ + // type: 'warning', + // message: res.data.msg + // }); + // } + // }; + + // 关键词查询记录 + const searchRecord = async () => { + if (state.searchType == null && state.searchVersion == '' && state.searchName == '') { + ElMessage({ + type: 'warning', + message: '请输入查询关键词' + }); + } else { + getListByPage(); + } + }; + + const clearSearch = async () => { + state.searchType = 1 + state.searchVersion = '' + state.searchName = '' + getListByPage(); + }; + + const showTip =()=>{ + ElMessage({ + type: 'warning', + message: '超出文件上传数量' + }); + } + + const getUploadUrl = async (rawFile: any) => { + const res = await appVersionApi().getUploadUrl({ filename: rawFile.name }); + state.addRecord.objectName = res.data.data.objectName + state.uploadUrl = res.data.data.presignedUrl; + }; + + const upload = async (params: any) => { + // const formData = new FormData(); + // formData.append('file', state.fileList[0].raw); + let reader = new FileReader(); + reader.readAsArrayBuffer(params.file); + reader.onload = async () => { + axios + .put(state.uploadUrl, reader.result, { + header: { 'Content-Type': 'multipart/form-data' } + }) + .then(() => { + // if (state.fileList.length === 2) { + // state.fileList.splice(0, 1); + // } + // console.log(state.form.workDetail.gbPath,'gbpath') + }); + }; + }; + + const beforeRemove = (file: {}, fileList: []) => { + const result = new Promise((resolve, reject) => { + ElMessageBox.confirm('此操作将删除该图片, 是否继续?', '提示', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning' + }) + .then(() => { + // console.log(state.workDetail.gbPath,'path') + state.fileList = [] + // 请求删除接口 + deletePic(state.addRecord.objectName) + state.addRecord.objectName = null + }) + .catch(() => { + reject(false); + }); + }); + return result; + }; + // 删除图片接口 + const deletePic = async(fileName:string)=>{ + const res = await workApplyApi().deleteFile({fileName: fileName}) + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '删除成功!' + }); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } + + // 添加班组管理方法 + const addRecord = async (data: any) => { + let res = await appVersionApi().addRecord(data); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '添加成功!' + }); + state.fileList = [] + getListByPage(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 修改工作时段方法 + const editRecordBtn = async (index, row) => { + console.log(row,'row') + state.addRecord = JSON.parse(JSON.stringify(row)); + state.dialogAddRecord = true; + state.chosenIndex = index; + }; + + const editRecord = async (data: any) => { + let res = await appVersionApi().updateRecord(data); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '修改成功!' + }); + getListByPage(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 新增修改记录 + const confirmAddRecord = async (formEl: FormInstance | undefined) => { + if (!formEl) return; + await formEl.validate(async (valid, fields) => { + if (valid) { + const data = { + appType: state.addRecord.appType, + appName: state.addRecord.name, + objectName: state.addRecord.objectName, + info: state.addRecord.info, + customVersion: state.addRecord.customVersion + }; + if (state.chosenIndex == null) { + await addRecord(data); + } else { + data.id = JSON.stringify(state.addRecord.id); + await editRecord(data); + } + state.dialogAddRecord = false; + } else { + console.log('error submit!', fields); + } + }); + }; + + // 删除工作时间组方法 + const deleteRecord = async (data: any) => { + let res = await appVersionApi().deleteRecord(data); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '删除成功!' + }); + getListByPage(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + const deleteRecordBtn = (row) => { + console.log(row, 'row'); + state.deleteId = row.id; + state.deleteDialog = true; + }; + + const conFirmDelete = () => { + deleteRecord({ id: state.deleteId }); + state.deleteDialog = false; + }; + + // 批量删除 + // const deleteBatchBtn = async () => { + // ElMessage({ + // type: 'warning', + // message: '抱歉,本页面暂不支持批量删除' + // }); + // if (state.deleteArr.length > 0) { + // state.deleteSetDialog = true + // } else { + // ElMessage({ + // type: 'warning', + // message: '请先选择要删除的记录' + // }); + // } + // }; + + // const conFirmDeleteBatch = async () => { + // let res = await appVersionApi().deletBatchRecord({ids: state.deleteArr}); + // if (res.data.code === '200') { + // state.deleteSetDialog = false + // ElMessage({ + // type: 'success', + // message: res.data.msg + // }); + // getListByPage() + // } else { + // ElMessage({ + // type: 'warning', + // message: res.data.msg + // }); + // state.deleteSetDialog = false + // } + // } + + const handleSizeChange = (val: number) => { + state.pageSize = val; + getListByPage(); + }; + const handleCurrentChange = (val: number) => { + state.pageIndex = val; + getListByPage(); + }; + + // 查看记录 + const viewRecord = (row) => { + state.details = JSON.parse(JSON.stringify(row)); + state.dialogDetails = true; + }; + + // 刷新 + const reLoadData = async () => { + getListByPage(); + }; + + const closeAdd = () => { + state.addRecord = { + appType: 1, + name: '', + objectName: '', + info: '', + customVersion: '' + } + state.uploadUrl = '' + state.fileList = [] + state.chosenIndex = null; + }; + const openAdd = () => { + if (state.chosenIndex == null) { + state.addRecord.info = ''; + } + }; + const indexClear = () => { + state.deleteId = null; + }; + + // 折线图 + const renderMenu = async (value: string) => { + Session.set('projectId', value); + userInfos.value.projectId = value; + await initBackEndControlRoutes(); + }; + return { + addRef, + addRules, + View, + Edit, + Delete, + Refresh, + Plus, + searchRecord, + clearSearch, + viewRecord, + deleteRecordBtn, + conFirmDelete, + getListByPage, + reLoadData, + deleteRecord, + showTip, + getUploadUrl, + upload, + beforeRemove, + handleSizeChange, + handleCurrentChange, + confirmAddRecord, + closeAdd, + openAdd, + indexClear, + editRecordBtn, + ...toRefs(state) + }; + } +}; +</script> + +<style scoped lang="scss"> +$homeNavLengh: 8; +.home-container { + height: calc(100vh - 144px); + box-sizing: border-box; + overflow: hidden; + .homeCard { + width: 100%; + padding: 20px; + box-sizing: border-box; + background: #fff; + border-radius: 4px; + + .main-card { + width: 100%; + height: 100%; + .cardTop { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 20px; + .mainCardBtn { + margin: 0; + } + } + .pageBtn { + height: 60px; + display: flex; + align-items: center; + justify-content: right; + + .demo-pagination-block + .demo-pagination-block { + margin-top: 10px; + } + .demo-pagination-block .demonstration { + margin-bottom: 16px; + } + } + } + &:last-of-type { + height: calc(100% - 100px); + } + } + .el-row { + display: flex; + align-items: center; + margin-bottom: 20px; + &:last-child { + margin-bottom: 0; + } + .grid-content { + align-items: center; + min-height: 36px; + } + + .topInfo { + width: 100%; + display: flex; + align-items: center; + font-size: 16px; + font-weight: bold; + + & > div { + white-space: nowrap; + margin-right: 20px; + } + } + } +} +.el-input { + width: 100% !important; +} +.el-date-editor::v-deep { + width: 100%; +} +.el-select { + width: 100% !important; +} +.el-tabs{ + width: 100%; +} +::v-deep(.el-date-editor){ + width: 100%; +} + +:deep(.el-cascader){ + width: 100% !important; +} +</style> diff --git a/src/views/system/department/component/deptDialog.vue b/src/views/system/department/component/deptDialog.vue new file mode 100644 index 0000000..f037f1e --- /dev/null +++ b/src/views/system/department/component/deptDialog.vue @@ -0,0 +1,171 @@ +<template> + <div class="system-add-dept-container"> + <el-dialog :title="title" v-model="isShowDialog" width="600px"> + <el-form :model="departmentForm" size="default" label-width="90px"> + <el-row :gutter="35"> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="部门等级"> + <el-select v-model="departmentForm.depLevel" placeholder="请输入部门等级" class="input-add" clearable> + <el-option + v-for="item in depLevelList" + :key="item.id" + :label="item.name" + :value="item.id" + ></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="上级部门"> + <el-cascader :options="deptData" class="input-add" :props="{ emitPath: false, checkStrictly: true, value: 'depId', label: 'depName' }" placeholder="请选择部门" clearable v-model="departmentForm.parentDepId"> </el-cascader> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="部门名称"> + <el-input v-model="departmentForm.depName" class="input-add" placeholder="请输入部门名称" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="部门描述"> + <el-input v-model="departmentForm.depInfo" class="input-add" type="textarea" placeholder="请输入部门描述" maxlength="150"></el-input> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="onCancel" size="default">取 消</el-button> + <el-button type="primary" v-throttle @click="onSubmit" size="default">确 定</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script lang="ts"> +import { ElMessage } from 'element-plus'; +import { reactive, toRefs, onMounted, defineComponent } from 'vue'; +import { departmentApi } from '/@/api/systemManage/department'; + +// 定义接口来定义对象的类型 +interface TableDataRow { + name: string; + info: string; + parentId: string; + id: number; +} +interface DeptSate { + title: string; + isShowDialog: boolean; + departmentForm: { + depName: string; + depInfo: string; + parentDepId: string; + depLevel:null | number + }; + deptData: Array<TableDataRow>; + depLevelList: Array<Type>; +} +interface Type{ + id:number; + name:string +} + +export default defineComponent({ + name: 'systemAddDept', + setup(prop, context) { + const state = reactive<DeptSate>({ + title: '', + isShowDialog: false, + departmentForm: { + depName: '', + parentDepId: '', + depInfo: '', + depLevel:null, + }, + deptData: [], // 部门数据 + depLevelList: [ + {id:1,name:'公司'}, + {id:2,name:'事业部'}, + {id:3,name:'车间'}, + {id:4,name:'班组'} + ] // 部门数据 + }); + + // 打开弹窗 + const openDialog = (type: string, value: any, departmentList: []) => { + state.isShowDialog = true; + state.deptData = JSON.parse(JSON.stringify(departmentList)); + if (type === '新增') { + state.title = '新增部门'; + state.departmentForm = { + depName: '', + parentDepId: '', + depLevel:null, + depInfo: '' + }; + } else { + state.title = '修改部门'; + state.departmentForm = JSON.parse(JSON.stringify(value)); + } + }; + // 关闭弹窗 + const closeDialog = () => { + state.isShowDialog = false; + }; + // 取消 + const onCancel = () => { + closeDialog(); + }; + // 新增 + const onSubmit = async () => { + if (state.title === '新增部门') { + let res = await departmentApi().addDepartment(state.departmentForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '部门新增成功', + duration: 2000 + }); + closeDialog(); + context.emit('getDepartmentList'); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } else { + let res = await departmentApi().modDepartment(state.departmentForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '部门修改成功', + duration: 2000 + }); + closeDialog(); + context.emit('getDepartmentList'); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } + }; + // 初始化部门数据 + const initTableData = () => {}; + // 页面加载时 + onMounted(() => { + initTableData(); + }); + return { + openDialog, + closeDialog, + onCancel, + onSubmit, + ...toRefs(state) + }; + } +}); +</script> diff --git a/src/views/system/department/index.vue b/src/views/system/department/index.vue new file mode 100644 index 0000000..a0d7c18 --- /dev/null +++ b/src/views/system/department/index.vue @@ -0,0 +1,126 @@ +<template> + <div class="system-dept-container"> + <el-card shadow="hover"> + <div class="system-dept-search mb15"> + <!-- <el-input size="default" placeholder="请输入部门名称" style="max-width: 180px"> </el-input>--> + <el-button size="default" type="primary" class="ml10"> + <el-icon> + <ele-Search /> + </el-icon> + 查询 + </el-button> + <el-button size="default" type="success" class="ml10" @click="onOpenDeptDialog('新增', '')"> + <el-icon> + <ele-FolderAdd /> + </el-icon> + 新增部门 + </el-button> + </div> + <el-table :data="tableData.data" style="width: 100%" row-key="depId" :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"> + <el-table-column prop="depName" label="部门名称" show-overflow-tooltip> </el-table-column> + <el-table-column prop="depInfo" label="部门描述" show-overflow-tooltip></el-table-column> + <el-table-column label="操作" show-overflow-tooltip width="140"> + <template #default="scope"> + <el-button size="small" text type="primary" @click="onOpenDeptDialog('新增', '')">新增</el-button> + <el-button size="small" text type="primary" @click="onOpenDeptDialog('修改', scope.row)">修改</el-button> + <el-button size="small" style="color: red" text type="primary" @click="onTabelRowDel(scope.row)">删除</el-button> + </template> + </el-table-column> + </el-table> + </el-card> + <deptDialog ref="deptDialog" @getDepartmentList="initTableData" /> + </div> +</template> + +<script lang="ts"> +import { ref, toRefs, reactive, onMounted, defineComponent } from 'vue'; +import { ElMessageBox, ElMessage } from 'element-plus'; +import deptDialog from '/@/views/system/department/component/deptDialog.vue'; +import { departmentApi } from '/@/api/systemManage/department'; +import { useRoleApi } from '/@/api/systemManage/role'; + +// 定义接口来定义对象的类型 +interface TableDataRow { + name: string; + status: boolean; + parentId: number; + info: string; + depId: number; + children?: TableDataRow[]; +} +interface TableDataState { + tableData: { + data: Array<TableDataRow>; + total: number; + loading: boolean; + }; +} + +export default defineComponent({ + name: 'systemDept', + components: { deptDialog }, + setup() { + const deptDialog = ref(); + const state = reactive<TableDataState>({ + tableData: { + data: [], + total: 0, + loading: false + } + }); + // 初始化表格数据 + const initTableData = async () => { + let res = await departmentApi().getDepartmentList(); + if (res.data.code === '200') { + state.tableData.data = res.data.data; + state.tableData.total = state.tableData.data.length; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + // 打开新增菜单弹窗 + const onOpenDeptDialog = (type: string, value: any) => { + deptDialog.value.openDialog(type, value, state.tableData.data); + }; + // 删除当前行 + const onTabelRowDel = (row: TableDataRow) => { + ElMessageBox.confirm(`此操作将永久删除部门:${row.depId}, 是否继续?`, '提示', { + confirmButtonText: '删除', + cancelButtonText: '取消', + type: 'warning' + }) + .then(async () => { + let res = await departmentApi().deleteDepartment({ depId: row.depId }); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + duration: 2000, + message: '删除成功' + }); + await initTableData(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }) + .catch(() => {}); + }; + // 页面加载时 + onMounted(() => { + initTableData(); + }); + return { + deptDialog, + initTableData, + onOpenDeptDialog, + onTabelRowDel, + ...toRefs(state) + }; + } +}); +</script> diff --git a/src/views/system/dic/component/addDic.vue b/src/views/system/dic/component/addDic.vue new file mode 100644 index 0000000..c964dd9 --- /dev/null +++ b/src/views/system/dic/component/addDic.vue @@ -0,0 +1,129 @@ +<template> + <div class="system-add-dic-container"> + <el-dialog title="新增字典" v-model="isShowDialog" width="769px"> + <el-alert title="半成品,交互过于复杂,请自行扩展!" type="warning" :closable="false" class="mb20"> </el-alert> + <el-form :model="ruleForm" size="default" label-width="90px"> + <el-row :gutter="35"> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="字典名称"> + <el-input v-model="ruleForm.dicName" placeholder="请输入字典名称" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="字段名"> + <el-input v-model="ruleForm.fieldName" placeholder="请输入字段名,拼接 ruleForm.list" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="字典状态"> + <el-switch v-model="ruleForm.status" inline-prompt active-text="启" inactive-text="禁"></el-switch> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-row :gutter="35" v-for="(v, k) in ruleForm.list" :key="k"> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item :prop="`list[${k}].label`"> + <template #label> + <el-button type="primary" circle size="small" @click="onAddRow" v-if="k === 0"> + <el-icon> + <ele-Plus /> + </el-icon> + </el-button> + <el-button type="danger" circle size="small" @click="onDelRow(k)" v-else> + <el-icon> + <ele-Delete /> + </el-icon> + </el-button> + <span class="ml10">字段</span> + </template> + <el-input v-model="v.label" style="width: 100%" placeholder="请输入字段名"> </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="属性" :prop="`list[${k}].value`"> + <el-input v-model="v.value" style="width: 100%" placeholder="请输入属性值"> </el-input> + </el-form-item> + </el-col> + </el-row> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="字典描述"> + <el-input v-model="ruleForm.describe" type="textarea" placeholder="请输入字典描述" maxlength="150"></el-input> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="onCancel" size="default">取 消</el-button> + <el-button type="primary" @click="onSubmit" size="default">新 增</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script lang="ts"> +import { reactive, toRefs, defineComponent } from 'vue'; + +export default defineComponent({ + name: 'systemAddDic', + setup() { + const state = reactive({ + isShowDialog: false, + ruleForm: { + dicName: '', // 字典名称 + fieldName: '', // 字段名 + status: true, // 字典状态 + list: [ + // 子集字段 + 属性值 + { + id: Math.random(), + label: '', + value: '', + }, + ], + describe: '', // 字典描述 + fieldNameList: [], // 字段名: [{子集字段 + 属性值}] + }, + }); + // 打开弹窗 + const openDialog = () => { + state.isShowDialog = true; + }; + // 关闭弹窗 + const closeDialog = () => { + state.isShowDialog = false; + }; + // 取消 + const onCancel = () => { + closeDialog(); + }; + // 新增 + const onSubmit = () => { + closeDialog(); + }; + // 新增行 + const onAddRow = () => { + state.ruleForm.list.push({ + id: Math.random(), + label: '', + value: '', + }); + }; + // 删除行 + const onDelRow = (k: number) => { + state.ruleForm.list.splice(k, 1); + }; + return { + openDialog, + closeDialog, + onCancel, + onSubmit, + onAddRow, + onDelRow, + ...toRefs(state), + }; + }, +}); +</script> diff --git a/src/views/system/dic/component/editDic.vue b/src/views/system/dic/component/editDic.vue new file mode 100644 index 0000000..66b0365 --- /dev/null +++ b/src/views/system/dic/component/editDic.vue @@ -0,0 +1,162 @@ +<template> + <div class="system-edit-dic-container"> + <el-dialog title="修改字典" v-model="isShowDialog" width="769px"> + <el-alert title="半成品,交互过于复杂,请自行扩展!" type="warning" :closable="false" class="mb20"> </el-alert> + <el-form :model="ruleForm" size="default" label-width="90px"> + <el-row :gutter="35"> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="字典名称"> + <el-input v-model="ruleForm.dicName" placeholder="请输入字典名称" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="字段名"> + <el-input v-model="ruleForm.fieldName" placeholder="请输入字段名,拼接 ruleForm.list" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="字典状态"> + <el-switch v-model="ruleForm.status" inline-prompt active-text="启" inactive-text="禁"></el-switch> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-row :gutter="35" v-for="(v, k) in ruleForm.list" :key="k"> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item :prop="`list[${k}].label`"> + <template #label> + <el-button type="primary" circle size="small" @click="onAddRow" v-if="k === 0"> + <el-icon> + <ele-Plus /> + </el-icon> + </el-button> + <el-button type="danger" circle size="small" @click="onDelRow(k)" v-else> + <el-icon> + <ele-Delete /> + </el-icon> + </el-button> + <span class="ml10">字段</span> + </template> + <el-input v-model="v.label" style="width: 100%" placeholder="请输入字段名"> </el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="属性" :prop="`list[${k}].value`"> + <el-input v-model="v.value" style="width: 100%" placeholder="请输入属性值"> </el-input> + </el-form-item> + </el-col> + </el-row> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="字典描述"> + <el-input v-model="ruleForm.describe" type="textarea" placeholder="请输入字典描述" maxlength="150"></el-input> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="onCancel" size="default">取 消</el-button> + <el-button type="primary" @click="onSubmit" size="default">修 改</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script lang="ts"> +import { reactive, toRefs, defineComponent } from 'vue'; + +// 定义接口来定义对象的类型 +interface RuleFormList { + id: number; + label: string; + value: string; +} +interface RuleFormState { + dicName: string; + fieldName: string; + status: boolean; + list: RuleFormList[]; + describe: string; + fieldNameList: Array<any>; +} +interface DicState { + isShowDialog: boolean; + ruleForm: RuleFormState; +} + +export default defineComponent({ + name: 'systemEditDic', + setup() { + const state = reactive<DicState>({ + isShowDialog: false, + ruleForm: { + dicName: '', // 字典名称 + fieldName: '', // 字段名 + status: true, // 字典状态 + list: [ + // 子集字段 + 属性值 + { + id: Math.random(), + label: '', + value: '', + }, + ], + describe: '', // 字典描述 + fieldNameList: [], // 字段名: [{子集字段 + 属性值}] + }, + }); + // 打开弹窗 + const openDialog = (row: RuleFormState) => { + if (row.fieldName === 'SYS_UERINFO') { + row.list = [ + { id: Math.random(), label: 'sex', value: '1' }, + { id: Math.random(), label: 'sex', value: '0' }, + ]; + } else { + row.list = [ + { id: Math.random(), label: 'role', value: 'admin' }, + { id: Math.random(), label: 'role', value: 'common' }, + { id: Math.random(), label: 'roleName', value: '超级管理员' }, + { id: Math.random(), label: 'roleName', value: '普通用户' }, + ]; + } + state.ruleForm = row; + state.isShowDialog = true; + }; + // 关闭弹窗 + const closeDialog = () => { + state.isShowDialog = false; + }; + // 取消 + const onCancel = () => { + closeDialog(); + }; + // 新增 + const onSubmit = () => { + closeDialog(); + }; + // 新增行 + const onAddRow = () => { + state.ruleForm.list.push({ + id: Math.random(), + label: '', + value: '', + }); + }; + // 删除行 + const onDelRow = (k: number) => { + state.ruleForm.list.splice(k, 1); + }; + return { + openDialog, + closeDialog, + onCancel, + onSubmit, + onAddRow, + onDelRow, + ...toRefs(state), + }; + }, +}); +</script> diff --git a/src/views/system/dic/index.vue b/src/views/system/dic/index.vue new file mode 100644 index 0000000..845e64e --- /dev/null +++ b/src/views/system/dic/index.vue @@ -0,0 +1,220 @@ +<template> + <div class="system-dic-container"> + <el-card shadow="hover"> + <el-row :gutter="10"> + <el-col :xs="24" :sm="24" :md="10" :lg="10" :xl="10"> + <el-card class="box-card"> + <div class="box-card-header"> + <span>字典类型</span> + </div> + <div class="box-card-body"> + <div class="box-card-body-filter"> + <el-input class="input-box" placeholder="输入名称" @keyup.enter.native="queryHandle('dictionaryType')" /> + <el-button type="success" @click="showCreateHandle('dictionaryType')">新增</el-button> + <el-button type="primary" @click="showCreateHandle('dictionaryType')">搜索</el-button> + </div> + <div class="table-content"> + <el-table :data="tableData.data" style="width: 100%"> + <el-table-column type="index" label="序号" width="50" /> + <el-table-column prop="dicName" label="字典名称" show-overflow-tooltip></el-table-column> + <el-table-column prop="fieldName" label="字段名" show-overflow-tooltip></el-table-column> + <el-table-column prop="describe" label="字典描述" show-overflow-tooltip></el-table-column> + <el-table-column prop="createTime" label="创建时间" show-overflow-tooltip></el-table-column> + <el-table-column label="操作" width="100"> + <template #default="scope"> + <el-button size="small" text type="primary" @click="onOpenEditDic(scope.row)">修改</el-button> + <el-button size="small" text type="primary" @click="onRowDel(scope.row)">删除</el-button> + </template> + </el-table-column> + </el-table> + <br /> + <el-pagination + @size-change="onHandleSizeChange" + @current-change="onHandleCurrentChange" + class="page-position" + :pager-count="5" + :page-sizes="[10, 20, 30]" + v-model:current-page="tableData.param.pageNum" + background + v-model:page-size="tableData.param.pageSize" + layout="total, sizes, prev, pager, next, jumper" + :total="tableData.total" + > + </el-pagination> + <br /> + <br /> + </div> + </div> + </el-card> + </el-col> + <el-col :xs="24" :sm="24" :md="14" :lg="14" :xl="14"> + <el-card class="box-card"> + <div class="box-card-header"> + <span>字典详情 </span> + </div> + <div class="box-card-body"> + <div class="box-card-body-filter"> + <el-input class="input-box" placeholder="输入名称" @keyup.enter.native="queryHandle('dictionaryType')" /> + <el-button type="success" @click="showCreateHandle('dictionaryType')">新增</el-button> + <el-button type="primary" @click="showCreateHandle('dictionaryType')">搜索</el-button> + </div> + <div class="table-content"> + <el-table :data="tableData.data" style="width: 100%"> + <el-table-column type="index" label="序号" width="50" /> + <el-table-column prop="dicName" label="字典名称" show-overflow-tooltip></el-table-column> + <el-table-column prop="fieldName" label="字段名" show-overflow-tooltip></el-table-column> + <el-table-column prop="describe" label="字典描述" show-overflow-tooltip></el-table-column> + <el-table-column prop="createTime" label="创建时间" show-overflow-tooltip></el-table-column> + <el-table-column label="操作" width="100"> + <template #default="scope"> + <el-button size="small" text type="primary" @click="onOpenEditDic(scope.row)">修改</el-button> + <el-button size="small" text type="primary" @click="onRowDel(scope.row)">删除</el-button> + </template> + </el-table-column> + </el-table> + <br /> + <el-pagination + @size-change="onHandleSizeChange" + @current-change="onHandleCurrentChange" + class="page-position" + :pager-count="5" + :page-sizes="[10, 20, 30]" + v-model:current-page="tableData.param.pageNum" + background + v-model:page-size="tableData.param.pageSize" + layout="total, sizes, prev, pager, next, jumper" + :total="tableData.total" + > + </el-pagination> + <br /> + <br /> + </div> + </div> + </el-card> + </el-col> + </el-row> + </el-card> + <AddDic ref="addDicRef" /> + <EditDic ref="editDicRef" /> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, onMounted, ref, defineComponent } from 'vue'; +import { ElMessageBox, ElMessage } from 'element-plus'; +import AddDic from '/@/views/system/dic/component/addDic.vue'; +import EditDic from '/@/views/system/dic/component/editDic.vue'; + +// 定义接口来定义对象的类型 +interface TableDataRow { + dicName: string; + fieldName: string; + describe: string; + status: boolean; + createTime: string; +} +interface TableDataState { + tableData: { + data: Array<TableDataRow>; + total: number; + loading: boolean; + param: { + pageNum: number; + pageSize: number; + }; + }; +} + +export default defineComponent({ + name: 'systemDic', + components: { AddDic, EditDic }, + setup() { + const addDicRef = ref(); + const editDicRef = ref(); + const state = reactive<TableDataState>({ + tableData: { + data: [], + total: 0, + loading: false, + param: { + pageNum: 1, + pageSize: 10 + } + } + }); + // 初始化表格数据 + const initTableData = () => { + const data: Array<TableDataRow> = []; + for (let i = 0; i < 2; i++) { + data.push({ + dicName: i === 0 ? '角色标识' : '用户性别', + fieldName: i === 0 ? 'SYS_ROLE' : 'SYS_UERINFO', + describe: i === 0 ? '这是角色字典' : '这是用户性别字典', + status: true, + createTime: new Date().toLocaleString() + }); + } + state.tableData.data = data; + state.tableData.total = state.tableData.data.length; + }; + // 打开新增字典弹窗 + const onOpenAddDic = () => { + addDicRef.value.openDialog(); + }; + // 打开修改字典弹窗 + const onOpenEditDic = (row: TableDataRow) => { + editDicRef.value.openDialog(row); + }; + // 删除字典 + const onRowDel = (row: TableDataRow) => { + ElMessageBox.confirm(`此操作将永久删除字典名称:“${row.dicName}”,是否继续?`, '提示', { + confirmButtonText: '确认', + cancelButtonText: '取消', + type: 'warning' + }) + .then(() => { + ElMessage.success('删除成功'); + }) + .catch(() => {}); + }; + // 分页改变 + const onHandleSizeChange = (val: number) => { + state.tableData.param.pageSize = val; + }; + // 分页改变 + const onHandleCurrentChange = (val: number) => { + state.tableData.param.pageNum = val; + }; + // 页面加载时 + onMounted(() => { + initTableData(); + }); + return { + addDicRef, + editDicRef, + onOpenAddDic, + onOpenEditDic, + onRowDel, + onHandleSizeChange, + onHandleCurrentChange, + ...toRefs(state) + }; + } +}); +</script> +<style scoped lang="scss"> +.box-card { + padding: 0 !important; + .box-card-header { + padding-bottom: 18px; + border-bottom: 1px solid #ebeef5; + -webkit-box-sizing: border-box; + box-sizing: border-box; + font-size: 16px; + width: 100%; + } + .box-card-body { + padding-top: 18px; + } +} +</style> diff --git a/src/views/system/menu/component/menuDialog.vue b/src/views/system/menu/component/menuDialog.vue new file mode 100644 index 0000000..ae7afd9 --- /dev/null +++ b/src/views/system/menu/component/menuDialog.vue @@ -0,0 +1,254 @@ +<template> + <div class="system-add-menu-container"> + <el-dialog :title="title" v-model="isShowDialog" width="769px"> + <el-form :model="ruleForm" size="default" label-width="80px"> + <el-row :gutter="35"> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="上级菜单"> + <el-cascader :options="menuData" :props="{ checkStrictly: true, value: 'id', label: 'title' }" placeholder="请选择上级菜单" clearable class="w100" v-model="ruleForm.menuSuperior"> </el-cascader> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="菜单名称"> + <el-input v-model.trim="ruleForm.meta.title" placeholder="格式:message.router.xxx" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="路由名称"> + <el-input v-model.trim="ruleForm.name" placeholder="路由中的 name 值" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="路由路径"> + <el-input v-model.trim="ruleForm.path" placeholder="路由中的 path 值" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="重定向"> + <el-input v-model.trim="ruleForm.redirect" placeholder="请输入路由重定向" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="菜单图标"> + <!-- <el-input placeholder="请输入菜单图标" v-model.trim="ruleForm.meta.icon" type="all" />--> + <IconSelector placeholder="请输入菜单图标" v-model="ruleForm.meta.icon" type="all" /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="组件路径"> + <el-input v-model.trim="ruleForm.component" placeholder="组件路径" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="权限标识"> + <el-select v-model="ruleForm.meta.roles" multiple placeholder="取角色管理" clearable class="w100"> + <el-option v-for="item in roleList" :key="item.roleId" :value="item.roleCode" :label="item.roleName"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="项目名"> + <el-select @change="handelMenu" v-model="ruleForm.projectId" controls-position="right" placeholder="请输入排序" class="w100"> + <el-option v-for="item in projectList" :key="item.key" :value="item.id" :label="item.name"> </el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="菜单排序"> + <el-input-number v-model="ruleForm.priority" controls-position="right" placeholder="请输入排序" class="w100" /> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="是否隐藏"> + <el-radio-group v-model="ruleForm.meta.isHide"> + <el-radio :label="true">隐藏</el-radio> + <el-radio :label="false">不隐藏</el-radio> + </el-radio-group> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="onCancel" size="default">取 消</el-button> + <el-button type="primary" v-throttle @click="onSubmit" size="default">{{ buttonName }}</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script lang="ts"> +import { reactive, toRefs, onMounted, defineComponent } from 'vue'; +import { storeToRefs } from 'pinia'; +import { useRoutesList } from '/@/stores/routesList'; +import { i18n } from '/@/i18n/index'; +import IconSelector from '/@/components/iconSelector/index.vue'; +import { useMenuApi } from '/@/api/systemManage/menu/index'; +import { ElMessageBox, ElMessage } from 'element-plus'; +import { Session } from '/@/utils/storage'; +// import { setBackEndControlRefreshRoutes } from "/@/router/backEnd"; + +export default defineComponent({ + name: 'systemAddMenu', + components: { IconSelector }, + setup(props, context) { + const stores = useRoutesList(); + const { routesList } = storeToRefs(stores); + const state = reactive({ + isShowDialog: false, + title: '', + buttonName: '', + // 参数请参考 `/src/router/route.ts` 中的 `dynamicRoutes` 路由菜单格式 + ruleForm: { + projectId: '', + parentId: 0, + menuSuperior: [], // 上级菜单 + menuType: 'menu', // 菜单类型 + name: '', // 路由名称 + component: '', // 组件路径 + priority: 0, // 菜单排序 + path: '', // 路由路径 + redirect: '', // 路由重定向,有子集 children 时 + meta: { + title: '', // 菜单名称 + icon: '', // 菜单图标 + isHide: false, // 是否隐藏 + isKeepAlive: true, // 是否缓存 + isAffix: false, // 是否固定 + isLink: '', // 外链/内嵌时链接地址(http:xxx.com),开启外链条件,`1、isLink: 链接地址不为空` + isIframe: false, // 是否内嵌,开启条件,`1、isIframe:true 2、isLink:链接地址不为空` + roles: [] // 权限标识,取角色管理 + }, + btnPower: '' // 菜单类型为按钮时,权限标识 + }, + roleList: [], + menuData: [], // 上级菜单数据 + projectList: [] + }); + // 获取 vuex 中的路由 + const getMenuList = (routes: any) => { + const arr: any = []; + routes.map((val: any) => { + val['title'] = val.meta.title; + val['id'] = val.id; + arr.push(val); + if (val.children) getMenuList(val.children); + }); + return arr; + }; + // 打开弹窗 + const openDialog = (type: string, value: any, projectList: any, projectId: string, roleList: []) => { + state.projectList = JSON.parse(JSON.stringify(projectList)); + state.roleList = roleList; + state.isShowDialog = true; + if (type === '新增') { + state.buttonName = '新增'; + state.title = '新增菜单'; + state.ruleForm = { + projectId: projectId, + parentId: 0, + menuSuperior: [], + menuType: 'menu', + name: '', + component: '', + priority: 0, + path: '', + redirect: '', + meta: { + title: '', + icon: '', + isHide: false, + isKeepAlive: true, + isAffix: false, + isLink: '', + isIframe: false, + roles: [] + }, + btnPower: '' + }; + } else { + state.buttonName = '修改'; + state.title = '修改菜单'; + state.ruleForm = JSON.parse(JSON.stringify(value)); + state.ruleForm.projectId = projectId.toString(); + } + handelMenu(); + }; + // 关闭弹窗 + const closeDialog = () => { + state.isShowDialog = false; + }; + // 是否内嵌下拉改变 + // const onSelectIframeChange = () => { + // if (state.ruleForm.meta.isIframe) state.ruleForm.isLink = true; + // else state.ruleForm.isLink = false; + // }; + // 取消 + const onCancel = () => { + closeDialog(); + }; + // 新增 + const onSubmit = async () => { + if (state.ruleForm.menuSuperior && state.ruleForm.menuSuperior !== []) { + let menuId = JSON.parse(JSON.stringify(state.ruleForm.menuSuperior)); + state.ruleForm.parentId = menuId[menuId.length - 1]; + } + if (state.title === '新增菜单') { + let res = await useMenuApi().addMenu(state.ruleForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '菜单新增成功', + duration: 2000 + }); + closeDialog(); + context.emit('getMenuList'); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } else { + let res = await useMenuApi().modMenu(state.ruleForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '菜单修改成功', + duration: 2000 + }); + closeDialog(); + context.emit('getMenuList'); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } + + // closeDialog(); // 关闭弹窗 + // setBackEndControlRefreshRoutes() // 刷新菜单,未进行后端接口测试 + }; + + const handelMenu = async () => { + let res = await useMenuApi().getMenuAdmin(state.ruleForm.projectId); + state.menuData = JSON.parse(JSON.stringify(getMenuList(res.data.data))); + }; + // 页面加载时 + onMounted(async () => { + // let res = await useMenuApi().getMenuAdmin(Session.get('projectId')) + // state.menuData = JSON.parse(JSON.stringify(getMenuList(res.data.data))) + }); + return { + openDialog, + closeDialog, + onCancel, + onSubmit, + handelMenu, + ...toRefs(state) + }; + } +}); +</script> diff --git a/src/views/system/menu/index.vue b/src/views/system/menu/index.vue new file mode 100644 index 0000000..c4a0e9b --- /dev/null +++ b/src/views/system/menu/index.vue @@ -0,0 +1,206 @@ +<template> + <div class="system-menu-container"> + <el-card shadow="hover"> + <div class="system-menu-search mb15"> + <el-select size="default" v-model="projectId" placeholder="请选择项目名称" style="min-width: 350px" @change="getMenuList()"> + <el-option v-for="item in projectList" :key="item.key" :value="item.id" :label="item.name"> </el-option> + </el-select> + <el-button size="default" type="primary" class="ml10" @click="getMenuList"> + <el-icon> + <ele-Search /> + </el-icon> + 查询 + </el-button> + <el-button size="default" type="success" class="ml10" @click="onOpenMenuDialog('新增')"> + <el-icon> + <ele-FolderAdd /> + </el-icon> + 新增菜单 + </el-button> + </div> + <el-table :data="menuTableData" style="width: 100%" row-key="path" :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"> + <el-table-column label="菜单名称" show-overflow-tooltip> + <template #default="scope"> + <SvgIcon :name="scope.row.meta.icon" /> + <span class="ml10">{{ scope.row.meta.title }}</span> + </template> + </el-table-column> + <el-table-column prop="path" label="路由路径" show-overflow-tooltip></el-table-column> + <el-table-column label="组件路径" show-overflow-tooltip> + <template #default="scope"> + <span>{{ scope.row.component }}</span> + </template> + </el-table-column> + <el-table-column label="权限标识" show-overflow-tooltip> + <template #default="scope"> + <span>{{ parseRole(scope.row.meta.roles) }}</span> + </template> + </el-table-column> + <el-table-column label="排序" show-overflow-tooltip width="80"> + <template #default="scope"> + {{ scope.$index }} + </template> + </el-table-column> + <el-table-column label="类型" show-overflow-tooltip width="80"> + <template #default="scope"> + <el-tag type="success" size="small">{{ scope.row.xx }}菜单</el-tag> + </template> + </el-table-column> + <el-table-column label="操作" show-overflow-tooltip width="140"> + <template #default="scope"> + <el-button size="small" text type="primary" @click="onOpenMenuDialog('新增')">新增</el-button> + <el-button size="small" text type="primary" @click="onOpenMenuDialog('修改', scope.row)">修改</el-button> + <el-button size="small" style="color: red" text type="primary" @click="deleteMenu(scope.row)">删除</el-button> + </template> + </el-table-column> + </el-table> + </el-card> + <menuDialog ref="menuDialog" @getMenuList="getMenuList" /> + </div> +</template> + +<script lang="ts"> +import { ref, toRefs, reactive, computed, onMounted, defineComponent } from 'vue'; +import { RouteRecordRaw } from 'vue-router'; +import { ElMessageBox, ElMessage } from 'element-plus'; +import { storeToRefs } from 'pinia'; +import { useRoutesList } from '/@/stores/routesList'; +import menuDialog from '/@/views/system/menu/component/menuDialog.vue'; +import { useMenuApi } from '/@/api/systemManage/menu'; +import { Session } from '/@/utils/storage'; +import pinia from '/@/stores'; +import { dynamicRoutes } from '/@/router/route'; +import { useUserInfo } from '/@/stores/userInfo'; +import { initBackEndControlRoutes } from '/@/router/backEnd'; +import { useRoleApi } from '/@/api/systemManage/role'; + +export default defineComponent({ + name: 'systemMenu', + components: { menuDialog }, + filters: { + parseRole: (roles: Array<string>) => { + return ['1', '2']; + } + }, + setup() { + const menuDialog = ref(); + const storesRoutesList = useRoutesList(); + const state = reactive({ + projectId: '1', + menuData: [], + roleList: [], + menuTableData: [], + projectList: [ + { id: '1', name: '安全基础信息系统', key: 0 }, + { id: '2', name: '智能安全双重预防系统', key: 1 }, + { id: '3', name: '智能安全特殊作业系统', key: 2 }, + { id: '4', name: '智能安全巡检系统', key: 3 }, + { id: '5', name: '智能安全风险综合预警预报平台', key: 4 }, + { id: '6', name: '应急管理系统', key: 5 }, + { id: '7', name: '安全目标责任管理系统', key: 6 }, + { id: '8', name: '安全事故管理系统', key: 7 }, + { id: '9', name: '设备综合管控系统', key: 8 }, + { id: '10', name: '安全知识图谱系统', key: 9 }, + { id: '11', name: '智能安全危险化学品全生命周期管控系统', key: 10 } + ] + }); + // // 获取 vuex 中的路由 + // const menuTableData = computed(() => { + // return routesList.value; + // }); + // 打开新增菜单弹窗 + const onOpenMenuDialog = (type: string, value: any) => { + menuDialog.value.openDialog(type, value, state.projectList, state.projectId, state.roleList); + }; + + // 删除当前行 + const deleteMenu = (row: any) => { + ElMessageBox.confirm(`此操作将永久删除路由:${row.path}, 是否继续?`, '提示', { + confirmButtonText: '删除', + cancelButtonText: '取消', + type: 'warning' + }) + .then(async () => { + let res = await useMenuApi().deleteMenu({ id: row.id }); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + duration: 2000, + message: '删除成功' + }); + await getMenuList(); + if (Session.get('projectId') == state.projectId) await initBackEndControlRoutes(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }) + .catch(() => {}); + }; + const getMenuList = async () => { + let res = await useMenuApi().getMenuAdmin(state.projectId); + if (res.data.code === '200') { + state.menuTableData = res.data.data; + if (Session.get('projectId') == state.projectId) await initBackEndControlRoutes(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + const getRoleList = async () => { + let res = await useRoleApi().getRoleList(); + if (res.data.code === '200') { + state.roleList = res.data.data; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + const getProjectList = async () => { + let res = await useMenuApi().getProjectList(); + if (res.data.code === '200') { + state.menuTableData = res.data.data; + if (Session.get('projectId') == state.projectId) await initBackEndControlRoutes(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + const parseRole = (roles: Array<string>) => { + let role = roles.map((item) => { + for (let i in state.roleList) { + if (state.roleList[i].roleCode === item) { + return state.roleList[i].roleName; + } + } + }); + return role; + }; + + onMounted(() => { + getMenuList(); + getRoleList(); + console.log(1); + }); + return { + parseRole, + getMenuList, + menuDialog, + onOpenMenuDialog, + deleteMenu, + ...toRefs(state) + }; + } +}); +</script> diff --git a/src/views/system/personShiftManage/personTimeManage/durationManage/index.vue b/src/views/system/personShiftManage/personTimeManage/durationManage/index.vue new file mode 100644 index 0000000..725f36c --- /dev/null +++ b/src/views/system/personShiftManage/personTimeManage/durationManage/index.vue @@ -0,0 +1,561 @@ +<template> + <div class="home-container"> + <div style="height: 100%"> + <el-row class="homeCard"> + <el-col :span="8"> + <div class="grid-content topInfo"> + <el-input v-model="searchWord" placeholder="工作时段名称"></el-input> + <el-button type="primary" @click="searchRecord">查询</el-button> + <el-button plain @click="clearSearch">重置</el-button> + </div> + </el-col> + </el-row> + <div class="homeCard"> + <div class="main-card"> + <el-row class="cardTop"> + <el-col :span="12" class="mainCardBtn"> + <el-button type="primary" :icon="Plus" size="default" @click="dialogAddRecord = true">新增</el-button> + <!-- <el-button type="warning" :icon="Edit" size="default" plain>修改</el-button>--> + <el-button type="danger" :icon="Delete" size="default" plain @click="deleteBatchBtn">删除</el-button> + </el-col> + <el-button type="primary" :icon="Refresh" size="default" @click="reLoadData()" /> + </el-row> + <el-table ref="multipleTableRef" :data="tableData" style="width: 100%" height="calc(100% - 100px)" :header-cell-style="{ background: '#fafafa' }" @selection-change="handleSelectionChange"> + <el-table-column type="selection" width="100" /> + <el-table-column property="name" label="工作时段名称" /> + <el-table-column property="startTime" label="开始时间" /> + <el-table-column property="endTime" label="结束时间" /> + <el-table-column property="info" label="描述信息" /> + <el-table-column fixed="right" label="操作" align="center" width="250"> + <template #default="scope"> + <el-button link type="primary" size="small" :icon="View" @click="viewRecord(scope.row)">查看</el-button> + <el-button link type="primary" size="small" :icon="Edit" @click="editRecord(scope.$index, scope.row)">修改</el-button> + <el-button link type="danger" size="small" :icon="Delete" @click="deleteRecord(scope.row)">删除</el-button> + </template> + </el-table-column> + </el-table> + <div class="pageBtn"> + <el-pagination v-model:currentPage="pageIndex" v-model:page-size="pageSize" :page-sizes="[10, 15]" small="false" background layout="total, sizes, prev, pager, next, jumper" :total="totalSize" @size-change="handleSizeChange" @current-change="handleCurrentChange" /> + </div> + </div> + </div> + </div> + <el-dialog v-model="dialogDetails" title="工作时段"> + <el-form :model="details" label-width="120px"> + <el-form-item label="工作时段名称"> + <el-input v-model="details.name" readonly /> + </el-form-item> + <el-form-item label="开始时间"> + <el-input v-model="details.startTime" readonly /> + </el-form-item> + <el-form-item label="结束时间"> + <el-input v-model="details.endTime" readonly /> + </el-form-item> + <el-form-item label="描述信息"> + <el-input v-model="details.info" readonly /> + </el-form-item> + <el-form-item> + <el-button type="primary" @click="dialogDetails = false" size="default">确认</el-button> + </el-form-item> + </el-form> + </el-dialog> + <el-dialog v-model="dialogAddRecord" title="工作时段编辑" @close="closeAdd" @open="openAdd"> + <el-form :model="addRecord" label-width="120px" ref="addRef" :rules="addRules"> + <el-form-item label="工作时段名称" prop="name"> + <el-input v-model="addRecord.name"> </el-input> + </el-form-item> + <el-form-item label="上班开始时间" prop="startTime"> + <el-time-picker v-model="addRecord.startTime" format="HH:mm" value-format="HH:mm" placeholder="Select time" /> + </el-form-item> + <el-form-item label="上班结束时间" prop="endTime"> + <el-time-picker v-model="addRecord.endTime" format="HH:mm" value-format="HH:mm" placeholder="Select time" /> + </el-form-item> + <el-form-item label="描述信息" prop="info"> + <el-input v-model="addRecord.info" type="textarea"> </el-input> + </el-form-item> + <el-form-item> + <el-button type="warning" @click="dialogAddRecord = false" size="default" plain>取消</el-button> + <el-button type="primary" @click="confirmAddRecord(addRef)" size="default">确认</el-button> + </el-form-item> + </el-form> + </el-dialog> + <el-dialog v-model="deleteDialog" title="提示" width="30%" center @close="indexClear"> + <span>您确定要删除该条记录吗?</span> + <template #footer> + <span class="dialog-footer"> + <el-button @click="deleteDialog = false" size="default">取消</el-button> + <el-button type="primary" @click="conFirmDelete" size="default">确认</el-button> + </span> + </template> + </el-dialog> + <el-dialog v-model="deleteSetDialog" title="提示" width="30%" center> + <span>您确定要删除这些记录吗?</span> + <template #footer> + <span class="dialog-footer"> + <el-button @click="deleteSetDialog = false" size="default">取消</el-button> + <el-button type="primary" @click="conFirmDeleteBatch" size="default">确认</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, ref, onMounted } from 'vue'; +import { storeToRefs } from 'pinia'; +import { initBackEndControlRoutes } from '/@/router/backEnd'; +import { useUserInfo } from '/@/stores/userInfo'; +import { Session } from '/@/utils/storage'; +import { Edit, View, Plus, Delete, Refresh, Search, Download } from '@element-plus/icons-vue'; +import { ElTable } from 'element-plus'; +import { FormInstance, FormRules, ElMessage } from 'element-plus'; +import { workingHoursApi } from '/@/api/systemManage/basicDateManage/personShiftManage/workingHours'; +import { workingHoursSetApi } from '/@/api/systemManage/basicDateManage/personShiftManage/workingHoursSet'; + +// 定义接口来定义对象的类型 +interface stateType { + tableData: Array<string>; + multipleSelection: Array<any>; + deleteArr: Array<any>; + dialogDetails: boolean; + dialogAddRecord: boolean; + deleteDialog: boolean; + deleteSetDialog: boolean; + pageIndex: number; + pageSize: number; + searchWord: string; + totalSize: number; + chosenIndex: number | null; + addRecord: { + id: number | null; + name: string; + startTime: string; + endTime: string; + info: string; + }; + details: { + name: string; + startTime: string; + endTime: string; + info: string; + }; + deleteId: number | null; +} + +export default { + name: 'workingHours', + components: {}, + setup() { + const userInfo = useUserInfo(); + const { userInfos } = storeToRefs(userInfo); + + const state = reactive<stateType>({ + pageIndex: 1, + pageSize: 10, + totalSize: 0, + chosenIndex: null, + searchWord: '', + tableData: [], + multipleSelection: [], + dialogDetails: false, + dialogAddRecord: false, + deleteDialog: false, + deleteSetDialog: false, + addRecord: { + id: null, + name: '', + startTime: '', + endTime: '', + info: '' + }, + details: { + name: '', + startTime: '', + endTime: '', + info: '' + }, + deleteId: null, + deleteArr: [] + }); + interface User { + name: string; + startTime: string; + endTime: string; + info: string; + } + const multipleTableRef = ref<InstanceType<typeof ElTable>>(); + const toggleSelection = (rows?: User[]) => { + if (rows) { + rows.forEach((row) => { + // TODO: improvement typing when refactor table + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error + multipleTableRef.value!.toggleRowSelection(row, undefined); + }); + } else { + multipleTableRef.value!.clearSelection(); + } + }; + + // 多选 + const handleSelectionChange = (val: User[]) => { + state.multipleSelection = JSON.parse(JSON.stringify(val)); + state.deleteArr = state.multipleSelection.map((item) => { + item = item.id; + return item; + }); + }; + + const addRef = ref<FormInstance>(); + const addRules = reactive<FormRules>({ + name: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + startTime: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + endTime: [{ required: true, message: '该内容不能为空', trigger: 'blur' }] + }); + + // 页面载入时执行方法 + onMounted(() => { + // getWorkTimePeriod() + getListByPage(); + }); + + // 获取工作时段列表 + const getWorkTimePeriod = async () => { + let res = await workingHoursApi().getWorkTimePeriod({ name: state.searchWord }); + if (res.data.code === '200') { + state.tableData = res.data.data.map((item: any) => { + item.startHour = item.startHour == null ? '00' : item.startHour.toString()[1] ? item.startHour.toString() : '0' + item.startHour.toString(); + item.startMin = item.startMin == null ? '00' : item.startMin.toString()[1] ? item.startMin.toString() : '0' + item.startMin.toString(); + item.endHour = item.endHour == null ? '00' : item.endHour.toString()[1] ? item.endHour.toString() : '0' + item.endHour.toString(); + item.endMin = item.endMin == null ? '00' : item.endMin.toString()[1] ? item.endMin.toString() : '0' + item.endMin.toString(); + item.startTime = item.startHour + ':' + item.startMin; + item.endTime = item.endHour + ':' + item.endMin; + return item; + }); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 分页获取工作时段列表 + const getListByPage = async () => { + const data = { pageSize: state.pageSize, pageIndex: state.pageIndex, searchParams: { name: state.searchWord } }; + let res = await workingHoursApi().postPeriodPage(data); + if (res.data.code === '200') { + state.tableData = res.data.data.map((item: any) => { + item.startHour = item.startHour == null ? '00' : item.startHour.toString()[1] ? item.startHour.toString() : '0' + item.startHour.toString(); + item.startMin = item.startMin == null ? '00' : item.startMin.toString()[1] ? item.startMin.toString() : '0' + item.startMin.toString(); + item.endHour = item.endHour == null ? '00' : item.endHour.toString()[1] ? item.endHour.toString() : '0' + item.endHour.toString(); + item.endMin = item.endMin == null ? '00' : item.endMin.toString()[1] ? item.endMin.toString() : '0' + item.endMin.toString(); + item.startTime = item.startHour + ':' + item.startMin; + item.endTime = item.endHour + ':' + item.endMin; + return item; + }); + state.totalSize = res.data.total; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 关键词查询记录 + const searchRecord = async () => { + if (state.searchWord == '') { + ElMessage({ + type: 'warning', + message: '请输入查询关键词' + }); + } else { + getListByPage(); + } + }; + + const clearSearch = async () => { + state.searchWord = ''; + getListByPage(); + }; + + // 添加工作时段 + const addWorkTimePeriod = async (data: any) => { + let res = await workingHoursApi().postWorkTimePeriod(data); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '添加成功!' + }); + getListByPage(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 修改工作时段 + const editWorkTimePeriod = async (data: any) => { + let res = await workingHoursApi().updateWorkTimePeriod(data); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '修改成功!' + }); + getListByPage(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 删除工作时段 + const deleteWorkTimePeriod = async (data: any) => { + let res = await workingHoursApi().deletWorkTimePeriod(data); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '删除成功!' + }); + getListByPage(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + const deleteRecord = (row: { id: number }) => { + state.deleteId = row.id; + state.deleteDialog = true; + }; + + const conFirmDelete = () => { + deleteWorkTimePeriod({ id: state.deleteId }); + state.deleteDialog = false; + }; + + // 批量删除 + const deleteBatchBtn = async () => { + if (state.deleteArr.length > 0) { + state.deleteSetDialog = true; + } else { + ElMessage({ + type: 'warning', + message: '请先选择要删除的记录' + }); + } + }; + const conFirmDeleteBatch = async () => { + let res = await workingHoursApi().deleteBatchWorkTimePeriod({ ids: state.deleteArr }); + if (res.data.code === '200') { + state.deleteSetDialog = false; + ElMessage({ + type: 'success', + message: '删除成功!' + }); + getListByPage(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + state.deleteSetDialog = false; + } + }; + + const handleSizeChange = (val: number) => { + state.pageSize = val; + getListByPage(); + }; + const handleCurrentChange = (val: number) => { + state.pageIndex = val; + getListByPage(); + }; + + // 查看记录 + const viewRecord = (row: { name: string; startTime: string; endTime: string; info: string }) => { + state.details = row; + state.dialogDetails = true; + }; + + // 刷新 + const reLoadData = async () => { + getListByPage(); + }; + const editRecord = (index: number, row: {}) => { + state.dialogAddRecord = true; + state.chosenIndex = index; + state.addRecord = JSON.parse(JSON.stringify(row)); + }; + + // 新增修改记录 + const confirmAddRecord = async (formEl: FormInstance | undefined) => { + if (!formEl) return; + await formEl.validate(async (valid, fields) => { + if (valid) { + const data: { id: null | number; name: string; info: string; startHour: number; startMin: number; endHour: number; endMin: number } = { + id: null, + name: state.addRecord.name, + info: state.addRecord.info, + startHour: Number(state.addRecord.startTime.substring(0, 2)), + startMin: Number(state.addRecord.startTime.substring(3)), + endHour: Number(state.addRecord.endTime.substring(0, 2)), + endMin: Number(state.addRecord.endTime.substring(3)) + }; + if (state.chosenIndex == null) { + // if (state.addRecord.startTime >= state.addRecord.endTime) { + // state.addRecord.endTime = '次日' + state.addRecord.endTime + // } + // state.tableData.unshift(data) + await addWorkTimePeriod(data); + } else { + // if (state.addRecord.startTime >= state.addRecord.endTime) { + // state.addRecord.endTime = '次日' + state.addRecord.endTime + // } + // state.tableData[state.chosenIndex] = state.addRecord + (data.id = state.addRecord.id), await editWorkTimePeriod(data); + } + state.dialogAddRecord = false; + } else { + console.log('error submit!', fields); + } + }); + }; + const closeAdd = () => { + state.addRecord = { + id: null, + name: '', + startTime: '', + endTime: '', + info: '' + }; + state.chosenIndex = null; + }; + const openAdd = () => { + if (state.chosenIndex == null) { + state.addRecord.info = ''; + } + }; + const indexClear = () => { + state.deleteId = null; + }; + + return { + addRef, + addRules, + View, + Edit, + Delete, + Refresh, + Plus, + toggleSelection, + handleSelectionChange, + conFirmDeleteBatch, + searchRecord, + clearSearch, + viewRecord, + deleteRecord, + deleteBatchBtn, + conFirmDelete, + getWorkTimePeriod, + getListByPage, + reLoadData, + deleteWorkTimePeriod, + handleSizeChange, + handleCurrentChange, + confirmAddRecord, + closeAdd, + openAdd, + indexClear, + editRecord, + ...toRefs(state) + }; + } +}; +</script> + +<style scoped lang="scss"> +$homeNavLengh: 8; +.home-container { + height: calc(100vh - 144px); + box-sizing: border-box; + overflow: hidden; + .homeCard { + width: 100%; + padding: 20px; + box-sizing: border-box; + background: #fff; + border-radius: 4px; + + .main-card { + width: 100%; + height: 100%; + .cardTop { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 20px; + .mainCardBtn { + margin: 0; + } + } + .pageBtn { + height: 60px; + display: flex; + align-items: center; + justify-content: right; + + .demo-pagination-block + .demo-pagination-block { + margin-top: 10px; + } + .demo-pagination-block .demonstration { + margin-bottom: 16px; + } + } + } + &:last-of-type { + height: calc(100% - 100px); + } + } + .el-row { + display: flex; + align-items: center; + margin-bottom: 20px; + &:last-child { + margin-bottom: 0; + } + .grid-content { + align-items: center; + min-height: 36px; + } + + .topInfo { + display: flex; + align-items: center; + font-size: 16px; + font-weight: bold; + + & > div { + white-space: nowrap; + margin-right: 20px; + } + } + } +} +.el-input { + width: 100% !important; +} +.el-date-editor::v-deep { + width: 100%; +} +.el-select { + width: 100%; +} +</style> diff --git a/src/views/system/personShiftManage/personTimeManage/holidayTime/index.vue b/src/views/system/personShiftManage/personTimeManage/holidayTime/index.vue new file mode 100644 index 0000000..76d97f4 --- /dev/null +++ b/src/views/system/personShiftManage/personTimeManage/holidayTime/index.vue @@ -0,0 +1,660 @@ +<template> + <div class="home-container"> + <div style="height: 100%"> + <el-row class="homeCard"> + <el-col :span="8"> + <div class="grid-content topInfo"> + <el-input v-model="searchWord" placeholder="休息日名称"></el-input> + <el-button type="primary" @click="searchRecord">查询</el-button> + <el-button plain @click="clearSearch">重置</el-button> + </div> + </el-col> + </el-row> + <div class="homeCard"> + <div class="main-card"> + <el-row class="cardTop"> + <el-col :span="12" class="mainCardBtn"> + <el-button type="primary" :icon="Plus" size="default" @click="dialogAddRecord = true">新增</el-button> + <!-- <el-button type="warning" :icon="Edit" size="default" plain>修改</el-button>--> + <el-button type="danger" :icon="Delete" size="default" plain @click="deleteBatchBtn">删除</el-button> + </el-col> + <el-button type="primary" :icon="Refresh" size="default" @click="reLoadData()" /> + </el-row> + <el-table ref="multipleTableRef" :data="tableData" style="width: 100%" height="calc(100% - 100px)" :header-cell-style="{ background: '#fafafa' }" @selection-change="handleSelectionChange"> + <el-table-column type="selection" width="100" /> + <el-table-column property="name" label="休息日名称" /> + <el-table-column property="typeName" label="休息日类型" /> + <el-table-column property="ruleName" label="休息日规则" /> + <el-table-column property="ruleNumber" label="休息日" /> + <el-table-column property="info" label="描述信息" /> + <el-table-column fixed="right" label="操作" align="center" width="250"> + <template #default="scope"> + <el-button link type="primary" size="small" :icon="View" @click="viewRecord(scope.row)">查看</el-button> + <el-button link type="primary" size="small" :icon="Edit" @click="editRecordBtn(scope.$index, scope.row)">修改</el-button> + <el-button link type="danger" size="small" :icon="Delete" @click="deleteRecordBtn(scope.row)">删除</el-button> + </template> + </el-table-column> + </el-table> + <div class="pageBtn"> + <el-pagination v-model:currentPage="pageIndex" v-model:page-size="pageSize" :page-sizes="[10, 15]" small="false" background layout="total, sizes, prev, pager, next, jumper" :total="totalSize" @size-change="handleSizeChange" @current-change="handleCurrentChange" /> + </div> + </div> + </div> + </div> + <el-dialog v-model="dialogDetails" title="休息时间"> + <el-form :model="details" label-width="120px"> + <el-form-item label="名称"> + <el-input v-model="details.name" readonly /> + </el-form-item> + <el-form-item label="休假类型"> + <el-input v-model="details.typeName" readonly /> + </el-form-item> + <el-form-item label="休假规则" v-if="details.type == 2"> + <el-input v-model="details.ruleName" readonly /> + </el-form-item> + <el-form-item label="休假时间" v-if="details.type == 2"> + <el-input v-model="details.ruleNumber" readonly /> + </el-form-item> + <el-form-item label="描述信息" v-if="details.info"> + <el-input v-model="details.info" type="textarea" readonly /> + </el-form-item> + <el-form-item> + <el-button type="primary" @click="dialogDetails = false" size="default">确认</el-button> + </el-form-item> + </el-form> + </el-dialog> + <el-dialog v-model="dialogAddRecord" title="休息时间编辑" @close="closeAdd"> + <el-form :model="addRecord" label-width="120px" ref="addRef" :rules="addRules"> + <el-form-item label="休息日名称" prop="name"> + <el-input v-model="addRecord.name"> </el-input> + </el-form-item> + <el-form-item label="休假类型" prop="type"> + <el-select v-model="addRecord.type" placeholder="请选择休假类型" style="width: 100%" @change="typeChange"> + <el-option v-for="(item, index) in typeList" :key="index" :label="item.name" :value="item.value" /> + </el-select> + </el-form-item> + <el-form-item label="休假规则" prop="rule" v-if="addRecord.type == '自定义休息日' || addRecord.type == 2"> + <el-select v-model="addRecord.rule" placeholder="请选择休假规则" style="width: 100%" @change="ruleChange"> + <el-option v-for="(item, index) in ruleList" :key="index" :label="item.name" :value="item.value" /> + </el-select> + </el-form-item> + <el-form-item label="选择休假时间" prop="ruleNumber" v-if="addRecord.rule == '每周' || addRecord.rule == 1"> + <el-checkbox-group v-model="addRecord.ruleNumber"> + <el-checkbox v-for="(item, i) in weekDays" :label="item.value" :key="i">{{ item.name }}</el-checkbox> + </el-checkbox-group> + </el-form-item> + <el-form-item label="选择休假时间" prop="ruleNumber" v-if="addRecord.rule == '每月' || addRecord.rule == 2"> + <el-checkbox-group v-model="addRecord.ruleNumber"> + <el-checkbox v-for="index in 31" :label="index" :key="index" /> + </el-checkbox-group> + </el-form-item> + <el-form-item label="描述信息" prop="info"> + <el-input v-model="addRecord.info" type="textarea"> </el-input> + </el-form-item> + <el-form-item> + <el-button type="warning" @click="dialogAddRecord = false" size="default" plain>取消</el-button> + <el-button type="primary" @click="confirmAddRecord(addRef)" size="default">确认</el-button> + </el-form-item> + </el-form> + </el-dialog> + <el-dialog v-model="deleteDialog" title="提示" width="30%" center @close="indexClear"> + <span>您确定要删除该条记录吗?</span> + <template #footer> + <span class="dialog-footer"> + <el-button @click="deleteDialog = false" size="default">取消</el-button> + <el-button type="primary" @click="conFirmDelete" size="default">确认</el-button> + </span> + </template> + </el-dialog> + <el-dialog v-model="deleteSetDialog" title="提示" width="30%" center> + <span>您确定要删除这些记录吗?</span> + <template #footer> + <span class="dialog-footer"> + <el-button @click="deleteSetDialog = false" size="default">取消</el-button> + <el-button type="primary" @click="conFirmDeleteBatch" size="default">确认</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, ref, onMounted } from 'vue'; +import { storeToRefs } from 'pinia'; +import { initBackEndControlRoutes } from '/@/router/backEnd'; +import { useUserInfo } from '/@/stores/userInfo'; +import { Session } from '/@/utils/storage'; +import { Edit, View, Plus, Delete, Refresh, Search, Download } from '@element-plus/icons-vue'; +import { ElTable } from 'element-plus'; +import { FormInstance, FormRules, ElMessage } from 'element-plus'; +import { holidayTimeApi } from '/@/api/systemManage/basicDateManage/personShiftManage/holidayTime'; +import { workingHoursSetApi } from '/@/api/systemManage/basicDateManage/personShiftManage/workingHoursSet'; + +// 定义接口来定义对象的类型 +interface stateType { + tableData: Array<string>; + multipleSelection: Array<any>; + deleteArr: Array<any>; + weekDays: Array<any>; + typeList: Array<any>; + ruleList: Array<any>; + dialogDetails: boolean; + dialogAddRecord: boolean; + deleteDialog: boolean; + deleteSetDialog: boolean; + pageIndex: number; + pageSize: number; + searchWord: string; + chosenIndex: null | number; + casProps: object; + deleteId: null | number; + totalSize: number; + addRecord: { + name: string; + type: number | string; + rule: number | string; + ruleNumber: Array<number> | string; + info: string; + }; + details: { + name: string; + type: string; + rule: string; + ruleNumber: string; + info: string; + }; +} + +export default { + name: 'holidayTime', + components: {}, + setup() { + const userInfo = useUserInfo(); + const { userInfos } = storeToRefs(userInfo); + + const state = reactive<stateType>({ + pageIndex: 1, + pageSize: 10, + totalSize: 0, + chosenIndex: null, + searchWord: '', + tableData: [], + typeList: [ + { + name: '每周公休假日', + value: 0 + }, + { + name: '国家法定节假日', + value: 1 + }, + { + name: '自定义休息日', + value: 2 + } + ], + ruleList: [ + { + name: '每周', + value: 1 + }, + { + name: '每月', + value: 2 + } + ], + multipleSelection: [], + dialogDetails: false, + dialogAddRecord: false, + deleteDialog: false, + deleteSetDialog: false, + weekDays: [ + { + name: '周一', + value: 1 + }, + { + name: '周二', + value: 2 + }, + { + name: '周三', + value: 3 + }, + { + name: '周四', + value: 4 + }, + { + name: '周五', + value: 5 + }, + { + name: '周六', + value: 6 + }, + { + name: '周日', + value: 7 + } + ], + casProps: { + expandTrigger: 'hover' + }, + addRecord: { + name: '', + type: '', + rule: '', + ruleNumber: [], + info: '' + }, + details: { + name: '', + type: '', + rule: '', + ruleNumber: '', + info: '' + }, + deleteId: null, + deleteArr: [] + }); + interface User { + name: string; + type: number | string; + rule: number | string; + ruleNumber: Array<number> | string; + info: string; + } + + // 排序 + const compare = (x, y) => { + if (x < y) { + return -1; + } else if (x > y) { + return 1; + } else { + return 0; + } + }; + + const handleChange = (value) => { + state.addRecord.content = []; + console.log(JSON.parse(JSON.stringify(value))); + }; + + const multipleTableRef = ref<InstanceType<typeof ElTable>>(); + const toggleSelection = (rows?: User[]) => { + if (rows) { + rows.forEach((row) => { + // TODO: improvement typing when refactor table + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error + multipleTableRef.value!.toggleRowSelection(row, undefined); + }); + } else { + multipleTableRef.value!.clearSelection(); + } + }; + + // 休息类型改变时操作 + const typeChange = () => { + state.addRecord.rule = ''; + state.addRecord.ruleNumber = []; + }; + // 休息规则改变时操作 + const ruleChange = () => { + state.addRecord.ruleNumber = []; + }; + + // 多选 + const handleSelectionChange = (val: User[]) => { + state.multipleSelection = JSON.parse(JSON.stringify(val)); + state.deleteArr = state.multipleSelection.map((item) => { + item = item.id; + return item; + }); + }; + + const addRef = ref<FormInstance>(); + const addRules = reactive<FormRules>({ + name: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + type: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + rule: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + ruleNumber: [{ required: true, message: '该内容不能为空', trigger: 'blur' }] + }); + + // 页面载入时执行方法 + onMounted(() => { + // getWorkTimePeriod() + getListByPage(); + }); + + // 休假类型格式化 + // const typeName =(row, column, cellValue, index) =>{ + // return row.type == 0? '每周公休假日':(row.type == 1? '国家法定节假日': '自定义休息日') + // } + + // 分页获取工作时段列表 + const getListByPage = async () => { + const data = { pageSize: state.pageSize, pageIndex: state.pageIndex, searchParams: { name: state.searchWord } }; + let res = await holidayTimeApi().getAllBreakTimeRuleByPage(data); + if (res.data.code === '200') { + state.tableData = res.data.data.map((item) => { + item.typeName = item.type === 0 ? '每周公休假日' : item.type === 1 ? '国家法定节假日' : item.type === 2 ? '自定义休息日' : ''; + item.ruleName = item.rule === 1 ? '每周' : item.rule === 2 ? '每月' : ''; + return item; + }); + console.log(state.tableData, '列表获取的tableData'); + state.totalSize = res.data.total; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 关键词查询记录 + const searchRecord = async () => { + if (state.searchWord == '') { + ElMessage({ + type: 'warning', + message: '请输入查询关键词' + }); + } else { + getListByPage(); + } + }; + + const clearSearch = async () => { + state.searchWord = ''; + getListByPage(); + }; + + // 添加休息时间 + const addRecord = async (data: any) => { + let res = await holidayTimeApi().addBreakTime(data); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '添加成功!' + }); + getListByPage(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 修改休息时间 + const editRecordBtn = (index, row) => { + state.dialogAddRecord = true; + state.chosenIndex = index; + state.addRecord = JSON.parse(JSON.stringify(row)); + state.addRecord.ruleNumber = row.ruleNumber.split(',').map((i) => { + return Number(i); + }); + console.log(state.addRecord); + }; + + const editRecord = async (data: any) => { + let res = await holidayTimeApi().updateBreakTime(data); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '修改成功!' + }); + getListByPage(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 新增修改记录 + const confirmAddRecord = async (formEl: FormInstance | undefined) => { + if (!formEl) return; + await formEl.validate(async (valid, fields) => { + if (valid) { + const data = { + name: state.addRecord.name, + info: state.addRecord.info, + type: Number(state.addRecord.type), + rule: Number(state.addRecord.rule), + ruleNumber: state.addRecord.ruleNumber.sort(compare).join(',') + }; + if (state.chosenIndex == null) { + if (data.type == 2 && data.ruleNumber == '') { + ElMessage({ + type: 'warning', + message: '请至少选择一个休息时间' + }); + return; + } else { + await addRecord(data); + } + } else { + (data.id = state.addRecord.id), console.log(data, '提交时的参数data'); + await editRecord(data); + } + state.dialogAddRecord = false; + } else { + console.log('error submit!', fields); + } + }); + }; + const closeAdd = () => { + state.addRecord = { + name: '', + type: '', + rule: '', + ruleNumber: [], + info: '' + }; + state.chosenIndex = null; + }; + + // 删除工作时段 + const deleteRecord = async (data: any) => { + let res = await holidayTimeApi().deleteBreakTime(data); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '删除成功!' + }); + getListByPage(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + const deleteRecordBtn = (row) => { + state.deleteId = row.id; + state.deleteDialog = true; + }; + + const conFirmDelete = () => { + deleteRecord({ id: state.deleteId }); + state.deleteDialog = false; + }; + + // 批量删除 + const deleteBatchBtn = async () => { + if (state.deleteArr.length > 0) { + state.deleteSetDialog = true; + } else { + ElMessage({ + type: 'warning', + message: '请先选择要删除的记录' + }); + } + }; + + const conFirmDeleteBatch = async () => { + let res = await holidayTimeApi().deleteBatch({ ids: state.deleteArr }); + if (res.data.code === '200') { + state.deleteSetDialog = false; + ElMessage({ + type: 'success', + message: '删除成功!' + }); + getListByPage(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + state.deleteSetDialog = false; + } + }; + + const handleSizeChange = (val: number) => { + state.pageSize = val; + getListByPage(); + }; + const handleCurrentChange = (val: number) => { + state.pageIndex = val; + getListByPage(); + }; + + // 查看记录 + const viewRecord = (row) => { + state.details = JSON.parse(JSON.stringify(row)); + state.dialogDetails = true; + }; + + // 刷新 + const reLoadData = async () => { + getListByPage(); + }; + + const indexClear = () => { + state.deleteId = null; + }; + + // 折线图 + const renderMenu = async (value: string) => { + Session.set('projectId', value); + userInfos.value.projectId = value; + await initBackEndControlRoutes(); + }; + return { + addRef, + addRules, + View, + Edit, + Delete, + Refresh, + Plus, + typeChange, + ruleChange, + compare, + toggleSelection, + handleSelectionChange, + deleteBatchBtn, + conFirmDeleteBatch, + searchRecord, + clearSearch, + viewRecord, + deleteRecordBtn, + conFirmDelete, + getListByPage, + reLoadData, + deleteRecord, + handleSizeChange, + handleCurrentChange, + confirmAddRecord, + closeAdd, + indexClear, + editRecordBtn, + ...toRefs(state) + }; + } +}; +</script> + +<style scoped lang="scss"> +$homeNavLengh: 8; +.home-container { + height: calc(100vh - 144px); + box-sizing: border-box; + overflow: hidden; + .homeCard { + width: 100%; + padding: 20px; + box-sizing: border-box; + background: #fff; + border-radius: 4px; + + .main-card { + width: 100%; + height: 100%; + .cardTop { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 20px; + .mainCardBtn { + margin: 0; + } + } + .pageBtn { + height: 60px; + display: flex; + align-items: center; + justify-content: right; + + .demo-pagination-block + .demo-pagination-block { + margin-top: 10px; + } + .demo-pagination-block .demonstration { + margin-bottom: 16px; + } + } + } + &:last-of-type { + height: calc(100% - 100px); + } + } + .el-row { + display: flex; + align-items: center; + margin-bottom: 20px; + &:last-child { + margin-bottom: 0; + } + .grid-content { + align-items: center; + min-height: 36px; + } + + .topInfo { + display: flex; + align-items: center; + font-size: 16px; + font-weight: bold; + + & > div { + white-space: nowrap; + margin-right: 20px; + } + } + } +} +.el-input { + width: 100% !important; +} +.el-date-editor::v-deep { + width: 100%; +} +.el-select { + width: 100%; +} +</style> diff --git a/src/views/system/personShiftManage/personTimeManage/holidayTimeGroup/index.vue b/src/views/system/personShiftManage/personTimeManage/holidayTimeGroup/index.vue new file mode 100644 index 0000000..b37119d --- /dev/null +++ b/src/views/system/personShiftManage/personTimeManage/holidayTimeGroup/index.vue @@ -0,0 +1,561 @@ +<template> + <div class="home-container"> + <div style="height: 100%"> + <el-row class="homeCard"> + <el-col :span="8"> + <div class="grid-content topInfo"> + <el-input v-model="searchWord" placeholder="休息时间组名称"></el-input> + <el-button type="primary" @click="searchRecord">查询</el-button> + <el-button plain @click="clearSearch">重置</el-button> + </div> + </el-col> + </el-row> + <div class="homeCard"> + <div class="main-card"> + <el-row class="cardTop"> + <el-col :span="12" class="mainCardBtn"> + <el-button type="primary" :icon="Plus" size="default" @click="dialogAddRecord = true">新增</el-button> + <!-- <el-button type="warning" :icon="Edit" size="default" plain>修改</el-button>--> + <el-button type="danger" :icon="Delete" size="default" plain @click="deleteBatchBtn">删除</el-button> + </el-col> + <el-button type="primary" :icon="Refresh" size="default" @click="reLoadData()" /> + </el-row> + <el-table ref="multipleTableRef" :data="tableData" style="width: 100%" height="calc(100% - 100px)" :header-cell-style="{ background: '#fafafa' }" @selection-change="handleSelectionChange"> + <el-table-column type="selection" width="100" /> + <el-table-column property="name" label="休息时间组名称" /> + <el-table-column property="list" :formatter="toNames" label="关联休息时间" /> + <el-table-column property="info" label="描述信息" /> + <el-table-column fixed="right" label="操作" align="center" width="250"> + <template #default="scope"> + <el-button link type="primary" size="small" :icon="View" @click="viewRecord(scope.row)">查看</el-button> + <el-button link type="primary" size="small" :icon="Edit" @click="editRecordBtn(scope.$index, scope.row)">修改</el-button> + <el-button link type="danger" size="small" :icon="Delete" @click="deleteRecordBtn(scope.row)">删除</el-button> + </template> + </el-table-column> + </el-table> + <div class="pageBtn"> + <el-pagination v-model:currentPage="pageIndex" v-model:page-size="pageSize" :page-sizes="[10, 15]" small="false" background layout="total, sizes, prev, pager, next, jumper" :total="totalSize" @size-change="handleSizeChange" @current-change="handleCurrentChange" /> + </div> + </div> + </div> + </div> + <el-dialog v-model="dialogDetails" title="休息时间组"> + <el-form :model="details" label-width="120px"> + <el-form-item label="时间组名称"> + <el-input v-model="details.name" readonly /> + </el-form-item> + <el-form-item label="关联休息时间" v-if="details.list.length > 0"> + <el-input v-model="details.list" readonly /> + </el-form-item> + <el-form-item label="描述信息" v-if="details.info"> + <el-input v-model="details.info" type="textarea" readonly /> + </el-form-item> + <el-form-item> + <el-button type="primary" @click="dialogDetails = false" size="default">确认</el-button> + </el-form-item> + </el-form> + </el-dialog> + <el-dialog v-model="dialogAddRecord" title="休息时间组编辑" @close="closeAdd" @open="openAdd"> + <el-form :model="addRecord" label-width="120px" ref="addRef" :rules="addRules"> + <el-form-item label="时间组名称" prop="name"> + <el-input v-model="addRecord.name"> </el-input> + </el-form-item> + <el-form-item label="关联休息时间" prop="list"> + <el-select v-model="addRecord.list" multiple> + <el-option v-for="(item, index) in holidayTimeList" :key="index" :label="item.name" :value="item.id" /> + </el-select> + </el-form-item> + <el-form-item label="描述信息" prop="info"> + <el-input v-model="addRecord.info" type="textarea"> </el-input> + </el-form-item> + <el-form-item> + <el-button type="warning" @click="dialogAddRecord = false" size="default" plain>取消</el-button> + <el-button type="primary" @click="confirmAddRecord(addRef)" size="default">确认</el-button> + </el-form-item> + </el-form> + </el-dialog> + <el-dialog v-model="deleteDialog" title="提示" width="30%" center @close="indexClear"> + <span>您确定要删除该条记录吗?</span> + <template #footer> + <span class="dialog-footer"> + <el-button @click="deleteDialog = false" size="default">取消</el-button> + <el-button type="primary" @click="conFirmDelete" size="default">确认</el-button> + </span> + </template> + </el-dialog> + <el-dialog v-model="deleteSetDialog" title="提示" width="30%" center> + <span>您确定要删除这些记录吗?</span> + <template #footer> + <span class="dialog-footer"> + <el-button @click="deleteSetDialog = false" size="default">取消</el-button> + <el-button type="primary" @click="conFirmDeleteBatch" size="default">确认</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, ref, onMounted } from 'vue'; +import { storeToRefs } from 'pinia'; +import { initBackEndControlRoutes } from '/@/router/backEnd'; +import { useUserInfo } from '/@/stores/userInfo'; +import { Session } from '/@/utils/storage'; +import { Edit, View, Plus, Delete, Refresh, Search, Download } from '@element-plus/icons-vue'; +import { ElTable } from 'element-plus'; +import { FormInstance, FormRules, ElMessage } from 'element-plus'; +import { holidayGroupApi } from '/@/api/systemManage/basicDateManage/personShiftManage/holidayTimeGroup'; + +// 定义接口来定义对象的类型 +interface stateType { + tableData: Array<string>; + holidayTimeList: Array<string>; + multipleSelection: Array<any>; + deleteArr: Array<any>; + dialogDetails: boolean; + dialogAddRecord: boolean; + deleteDialog: boolean; + deleteSetDialog: boolean; + pageIndex: number; + pageSize: number; + chosenIndex: null | number; + deleteId: null | number; + searchWord: string; + totalSize: number; + addRecord: { + name: string; + list: Array<any>; + info: string; + }; + details: { + name: string; + list: Array<any>; + info: string; + }; +} + +export default { + name: 'workingHours', + components: {}, + setup() { + const userInfo = useUserInfo(); + const { userInfos } = storeToRefs(userInfo); + + const state = reactive<stateType>({ + pageIndex: 1, + pageSize: 10, + totalSize: 0, + chosenIndex: null, + searchWord: '', + tableData: [], + holidayTimeList: [], + multipleSelection: [], + dialogDetails: false, + dialogAddRecord: false, + deleteDialog: false, + deleteSetDialog: false, + addRecord: { + name: '', + list: [], + info: '' + }, + details: { + name: '', + list: [], + info: '' + }, + deleteId: null, + deleteArr: [] + }); + interface User { + name: string; + list: Array<any>; + info: string; + } + const multipleTableRef = ref<InstanceType<typeof ElTable>>(); + const toggleSelection = (rows?: User[]) => { + if (rows) { + rows.forEach((row) => { + // TODO: improvement typing when refactor table + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error + multipleTableRef.value!.toggleRowSelection(row, undefined); + }); + } else { + multipleTableRef.value!.clearSelection(); + } + }; + + // 多选 + const handleSelectionChange = (val: User[]) => { + state.multipleSelection = JSON.parse(JSON.stringify(val)); + state.deleteArr = state.multipleSelection.map((item) => { + item = item.id; + return item; + }); + }; + + const addRef = ref<FormInstance>(); + const addRules = reactive<FormRules>({ + name: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + list: [{ required: true, message: '该内容不能为空', trigger: 'blur' }] + }); + + // 页面载入时执行方法 + onMounted(() => { + getListByPage(); + getAllBreak(); + }); + + // 分页获取休息时间组列表 + const getListByPage = async () => { + const data = { pageSize: state.pageSize, pageIndex: state.pageIndex, searchParams: { name: state.searchWord } }; + let res = await holidayGroupApi().getRecordPage(data); + if (res.data.code === '200') { + state.tableData = res.data.data.map((item) => { + if (item.list == null) { + item.list = []; + } else { + item.list = Array.from(item.list, ({ breakTimeRuleId }) => breakTimeRuleId); + } + return item; + }); + state.totalSize = res.data.total; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 表格数据格式化 + const toNames = (row, column, cellValue, index) => { + if (row.list == []) { + return []; + } else { + const nameList = []; + for (let i = 0; i < row.list.length; i++) { + for (let t = 0; t < state.holidayTimeList.length; t++) { + if (row.list[i] == state.holidayTimeList[t].id) { + nameList.push(state.holidayTimeList[t].name); + } + } + } + return nameList.join(); + } + }; + + // 获取工作时段列表 + const getAllBreak = async () => { + let res = await holidayGroupApi().getAllBreak(); + if (res.data.code === '200') { + state.holidayTimeList = res.data.data; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 关键词查询记录 + const searchRecord = async () => { + if (state.searchWord == '') { + ElMessage({ + type: 'warning', + message: '请输入查询关键词' + }); + } else { + getListByPage(); + } + }; + + const clearSearch = async () => { + state.searchWord = ''; + getListByPage(); + }; + + // 添加工作时段方法 + const addRecord = async (data: any) => { + let res = await holidayGroupApi().addRecord(data); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '添加成功!' + }); + getListByPage(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 修改工作时段方法 + const editRecord = async (data: any) => { + let res = await holidayGroupApi().updateRecord(data); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '修改成功!' + }); + getListByPage(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 新增修改记录 + const confirmAddRecord = async (formEl: FormInstance | undefined) => { + if (!formEl) return; + await formEl.validate(async (valid, fields) => { + if (valid) { + const data = { + name: state.addRecord.name, + info: state.addRecord.info, + breakTimeRuleIds: state.addRecord.list + }; + if (state.chosenIndex == null) { + await addRecord(data); + } else { + data.id = JSON.stringify(state.addRecord.id) + await editRecord(data); + } + state.dialogAddRecord = false; + } else { + console.log('error submit!', fields); + } + }); + }; + + // 删除工作时间组方法 + const deleteRecord = async (data: any) => { + let res = await holidayGroupApi().deleteRecord(data); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '删除成功!' + }); + getListByPage(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + const deleteRecordBtn = (row) => { + state.deleteId = row.id; + state.deleteDialog = true; + }; + + const conFirmDelete = () => { + deleteRecord({ id: state.deleteId }); + state.deleteDialog = false; + }; + + // 批量删除 + const deleteBatchBtn = async () => { + if (state.deleteArr.length > 0) { + state.deleteSetDialog = true; + } else { + ElMessage({ + type: 'warning', + message: '请先选择要删除的记录' + }); + } + }; + + const conFirmDeleteBatch = async () => { + let res = await holidayGroupApi().deletBatchRecord({ ids: state.deleteArr }); + if (res.data.code === '200') { + state.deleteSetDialog = false; + ElMessage({ + type: 'success', + message: '删除成功!' + }); + getListByPage(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + state.deleteSetDialog = false; + } + }; + + const handleSizeChange = (val: number) => { + state.pageSize = val; + getListByPage(); + }; + const handleCurrentChange = (val: number) => { + state.pageIndex = val; + getListByPage(); + }; + + // 查看记录 + const viewRecord = (row) => { + state.details = JSON.parse(JSON.stringify(row)); + if (row.list == []) { + state.details.list = []; + } else { + state.details.list = []; + for (let i = 0; i < row.list.length; i++) { + for (let t = 0; t < state.holidayTimeList.length; t++) { + if (row.list[i] == state.holidayTimeList[t].id) { + state.details.list.push(state.holidayTimeList[t].name); + } + } + } + } + state.dialogDetails = true; + }; + + // 刷新 + const reLoadData = async () => { + getListByPage(); + }; + // 点击修改 + const editRecordBtn = (index, row) => { + state.dialogAddRecord = true; + state.chosenIndex = index; + state.addRecord = JSON.parse(JSON.stringify(row)); + }; + const closeAdd = () => { + state.addRecord = {}; + state.chosenIndex = null; + }; + const openAdd = () => { + if (state.chosenIndex == null) { + state.addRecord.info = ''; + } + }; + const indexClear = () => { + state.deleteId = null; + }; + + // 折线图 + const renderMenu = async (value: string) => { + Session.set('projectId', value); + userInfos.value.projectId = value; + await initBackEndControlRoutes(); + }; + return { + addRef, + addRules, + View, + Edit, + Delete, + Refresh, + Plus, + toNames, + toggleSelection, + handleSelectionChange, + searchRecord, + clearSearch, + viewRecord, + deleteRecordBtn, + conFirmDelete, + getListByPage, + getAllBreak, + reLoadData, + deleteRecord, + deleteBatchBtn, + conFirmDeleteBatch, + handleSizeChange, + handleCurrentChange, + confirmAddRecord, + closeAdd, + openAdd, + indexClear, + editRecordBtn, + ...toRefs(state) + }; + } +}; +</script> + +<style scoped lang="scss"> +$homeNavLengh: 8; +.home-container { + height: calc(100vh - 144px); + box-sizing: border-box; + overflow: hidden; + .homeCard { + width: 100%; + padding: 20px; + box-sizing: border-box; + background: #fff; + border-radius: 4px; + + .main-card { + width: 100%; + height: 100%; + .cardTop { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 20px; + .mainCardBtn { + margin: 0; + } + } + .pageBtn { + height: 60px; + display: flex; + align-items: center; + justify-content: right; + + .demo-pagination-block + .demo-pagination-block { + margin-top: 10px; + } + .demo-pagination-block .demonstration { + margin-bottom: 16px; + } + } + } + &:last-of-type { + height: calc(100% - 100px); + } + } + .el-row { + display: flex; + align-items: center; + margin-bottom: 20px; + &:last-child { + margin-bottom: 0; + } + .grid-content { + align-items: center; + min-height: 36px; + } + + .topInfo { + display: flex; + align-items: center; + font-size: 16px; + font-weight: bold; + + & > div { + white-space: nowrap; + margin-right: 20px; + } + } + } +} +.el-input { + width: 100% !important; +} +.el-date-editor::v-deep { + width: 100%; +} +.el-select { + width: 100%; +} +</style> diff --git a/src/views/system/personShiftManage/personTimeManage/timeStrategy/index.vue b/src/views/system/personShiftManage/personTimeManage/timeStrategy/index.vue new file mode 100644 index 0000000..1e88df2 --- /dev/null +++ b/src/views/system/personShiftManage/personTimeManage/timeStrategy/index.vue @@ -0,0 +1,587 @@ +<template> + <div class="home-container"> + <div style="height: 100%"> + <el-row class="homeCard"> + <el-col :span="8"> + <div class="grid-content topInfo"> + <el-input v-model="searchWord" placeholder="时间策略名称"></el-input> + <el-button type="primary" @click="searchRecord">查询</el-button> + <el-button plain @click="clearSearch">重置</el-button> + </div> + </el-col> + </el-row> + <div class="homeCard"> + <div class="main-card"> + <el-row class="cardTop"> + <el-col :span="12" class="mainCardBtn"> + <el-button type="primary" :icon="Plus" size="default" @click="dialogAddRecord = true">新增</el-button> + <!-- <el-button type="warning" :icon="Edit" size="default" plain>修改</el-button>--> + <el-button type="danger" :icon="Delete" size="default" plain @click="deleteBatchBtn">删除</el-button> + </el-col> + <el-button type="primary" :icon="Refresh" size="default" @click="reLoadData()" /> + </el-row> + <el-table ref="multipleTableRef" :data="tableData" style="width: 100%" height="calc(100% - 100px)" :header-cell-style="{ background: '#fafafa' }" @selection-change="handleSelectionChange"> + <el-table-column type="selection" width="100" /> + <el-table-column property="name" label="时间策略名称" /> + <el-table-column property="workList" label="关联工作时间组" /> + <el-table-column property="restList" label="关联休息时间组" /> + <el-table-column property="info" label="描述信息" /> + <el-table-column fixed="right" label="操作" align="center" width="250"> + <template #default="scope"> + <el-button link type="primary" size="small" :icon="View" @click="viewRecord(scope.row)">查看</el-button> + <el-button link type="primary" size="small" :icon="Edit" @click="editRecordBtn(scope.$index, scope.row)">修改</el-button> + <el-button link type="danger" size="small" :icon="Delete" @click="deleteRecordBtn(scope.row)">删除</el-button> + </template> + </el-table-column> + </el-table> + <div class="pageBtn"> + <el-pagination v-model:currentPage="pageIndex" v-model:page-size="pageSize" :page-sizes="[10, 15]" small="false" background layout="total, sizes, prev, pager, next, jumper" :total="totalSize" @size-change="handleSizeChange" @current-change="handleCurrentChange" /> + </div> + </div> + </div> + </div> + <el-dialog v-model="dialogDetails" title="时间策略"> + <el-form :model="details" label-width="120px"> + <el-form-item label="策略名称"> + <el-input v-model="details.name" readonly /> + </el-form-item> + <el-form-item label="关联工作时间组"> + <el-input v-model="details.workList" readonly /> + </el-form-item> + <el-form-item label="关联休息时间组"> + <el-input v-model="details.restList" readonly /> + </el-form-item> + <el-form-item label="描述信息" v-if="details.info"> + <el-input v-model="details.info" type="textarea" readonly /> + </el-form-item> + <el-form-item> + <el-button type="primary" @click="dialogDetails = false" size="default">确认</el-button> + </el-form-item> + </el-form> + </el-dialog> + <el-dialog v-model="dialogAddRecord" title="时间策略编辑" @close="closeAdd" @open="openAdd"> + <el-form :model="addRecord" label-width="120px" ref="addRef" :rules="addRules"> + <el-form-item label="策略名称" prop="name"> + <el-input v-model="addRecord.name"> </el-input> + </el-form-item> + <el-form-item label="关联工作时间组" prop="workList"> + <el-select v-model="addRecord.workList"> + <el-option v-for="(item, index) in workTimeList" :key="index" :label="item.name" :value="item.id" /> + </el-select> + </el-form-item> + <el-form-item label="关联休息时间组" prop="restList"> + <el-select v-model="addRecord.restList"> + <el-option v-for="(item, index) in restTimeList" :key="index" :label="item.name" :value="item.id" /> + </el-select> + </el-form-item> + <el-form-item label="描述信息" prop="info"> + <el-input v-model="addRecord.info" type="textarea"> </el-input> + </el-form-item> + <el-form-item> + <el-button type="warning" @click="dialogAddRecord = false" size="default" plain>取消</el-button> + <el-button type="primary" @click="confirmAddRecord(addRef)" size="default">确认</el-button> + </el-form-item> + </el-form> + </el-dialog> + <el-dialog v-model="deleteDialog" title="提示" width="30%" center @close="indexClear"> + <span>您确定要删除该条记录吗?</span> + <template #footer> + <span class="dialog-footer"> + <el-button @click="deleteDialog = false" size="default">取消</el-button> + <el-button type="primary" @click="conFirmDelete" size="default">确认</el-button> + </span> + </template> + </el-dialog> + <el-dialog v-model="deleteSetDialog" title="提示" width="30%" center> + <span>您确定要删除这些记录吗?</span> + <template #footer> + <span class="dialog-footer"> + <el-button @click="deleteSetDialog = false" size="default">取消</el-button> + <el-button type="primary" @click="conFirmDeleteBatch" size="default">确认</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, ref, onMounted } from 'vue'; +import { storeToRefs } from 'pinia'; +import { initBackEndControlRoutes } from '/@/router/backEnd'; +import { useUserInfo } from '/@/stores/userInfo'; +import { Session } from '/@/utils/storage'; +import { Edit, View, Plus, Delete, Refresh, Search, Download } from '@element-plus/icons-vue'; +import { ElTable } from 'element-plus'; +import { FormInstance, FormRules, ElMessage } from 'element-plus'; +import { timeStrategyApi } from '/@/api/systemManage/basicDateManage/personShiftManage/timeStrategy'; + +// 定义接口来定义对象的类型 +interface stateType { + tableData: Array<string>; + workTimeList: Array<string>; + restTimeList: Array<string>; + multipleSelection: Array<any>; + deleteArr: Array<any>; + dialogDetails: boolean; + dialogAddRecord: boolean; + deleteDialog: boolean; + deleteSetDialog: boolean; + pageIndex: number; + pageSize: number; + chosenIndex: null | number; + deleteId: null | number; + searchWord: string; + totalSize: number; + addRecord: { + name: string; + workList: string; + restList: string; + info: string; + }; + details: { + name: string; + workList: string; + restList: string; + info: string; + }; +} + +export default { + name: 'workingHours', + components: {}, + setup() { + const userInfo = useUserInfo(); + const { userInfos } = storeToRefs(userInfo); + + const state = reactive<stateType>({ + pageIndex: 1, + pageSize: 10, + totalSize: 0, + chosenIndex: null, + searchWord: '', + tableData: [], + workTimeList: [], + restTimeList: [], + multipleSelection: [], + dialogDetails: false, + dialogAddRecord: false, + deleteDialog: false, + deleteSetDialog: false, + addRecord: { + name: '', + workList: '', + restList: '', + info: '' + }, + details: { + name: '', + workList: '', + restList: '', + info: '' + }, + deleteId: null, + deleteArr: [] + }); + interface User { + name: string; + workList: string; + restList: string; + info: string; + } + const multipleTableRef = ref<InstanceType<typeof ElTable>>(); + const toggleSelection = (rows?: User[]) => { + if (rows) { + rows.forEach((row) => { + // TODO: improvement typing when refactor table + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error + multipleTableRef.value!.toggleRowSelection(row, undefined); + }); + } else { + multipleTableRef.value!.clearSelection(); + } + }; + + // 多选 + const handleSelectionChange = (val: User[]) => { + state.multipleSelection = JSON.parse(JSON.stringify(val)); + state.deleteArr = state.multipleSelection.map((item) => { + item = item.id; + return item; + }); + }; + + const addRef = ref<FormInstance>(); + const addRules = reactive<FormRules>({ + name: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + workList: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + restList: [{ required: true, message: '该内容不能为空', trigger: 'blur' }] + }); + + // 页面载入时执行方法 + onMounted(() => { + getListByPage(); + getWorkTimeList(); + getRestTimeList(); + }); + + // 分页获取休息时间组列表 + const getListByPage = async () => { + const data = { pageSize: state.pageSize, pageIndex: state.pageIndex, searchParams: { name: state.searchWord } }; + let res = await timeStrategyApi().getRecordPage(data); + if (res.data.code === '200') { + state.tableData = res.data.data.map((item) => { + // if(item.workTimeGroupRespDTO == null || item.workTimeGroupRespDTO.list == []){ + // item.workList = [] + // }else{ + // item.workList= Array.from(item.workTimeGroupRespDTO.list,({workTimeGroupId})=>workTimeGroupId) + // } + // if(item.breakTimeGroupRespDTO == null || item.breakTimeGroupRespDTO.list == []){ + // item.restList = [] + // }else{ + // item.restList= Array.from(item.breakTimeGroupRespDTO.list,({breakTimeGroupId})=>breakTimeGroupId) + // } + if (item.workTimeGroupRespDTO == null) { + item.workList = ''; + } else { + item.workList = item.workTimeGroupRespDTO.name; + } + if (item.breakTimeGroupRespDTO == null) { + item.restList = ''; + } else { + item.restList = item.breakTimeGroupRespDTO.name; + } + return item; + }); + console.log(state.tableData, 'state.tableData'); + state.totalSize = res.data.total; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 获取工作时间组列表 + const getWorkTimeList = async () => { + let res = await timeStrategyApi().getWorkTimeList(); + if (res.data.code === '200') { + state.workTimeList = res.data.data; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 获取休息时间组列表 + const getRestTimeList = async () => { + let res = await timeStrategyApi().getRestTimeList(); + if (res.data.code === '200') { + state.restTimeList = res.data.data; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 关键词查询记录 + const searchRecord = async () => { + if (state.searchWord == '') { + ElMessage({ + type: 'warning', + message: '请输入查询关键词' + }); + } else { + getListByPage(); + } + }; + + const clearSearch = async () => { + state.searchWord = ''; + getListByPage(); + }; + + // 添加工作时段方法 + const addRecord = async (data: any) => { + let res = await timeStrategyApi().addRecord(data); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '添加成功!' + }); + getListByPage(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 修改工作时段方法 + const editRecord = async (data: any) => { + let res = await timeStrategyApi().updateRecord(data); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '修改成功!' + }); + getListByPage(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 新增修改记录 + const confirmAddRecord = async (formEl: FormInstance | undefined) => { + if (!formEl) return; + await formEl.validate(async (valid, fields) => { + if (valid) { + const data = { + name: state.addRecord.name, + info: state.addRecord.info, + workTimeGroupId: state.addRecord.workList, + breakTimeGroupId: state.addRecord.restList + }; + if (state.chosenIndex == null) { + await addRecord(data); + } else { + data.id = JSON.stringify(state.addRecord.id); + if (typeof state.addRecord.workList == 'string') { + data.workTimeGroupId = state.addRecord.workTimeGroupId; + } + if (typeof state.addRecord.restList == 'string') { + data.breakTimeGroupId = state.addRecord.breakTimeGroupId; + } + await editRecord(data); + } + state.dialogAddRecord = false; + } else { + console.log('error submit!', fields); + } + }); + }; + + // 删除工作时间组方法 + const deleteRecord = async (data: any) => { + let res = await timeStrategyApi().deleteRecord(data); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '删除成功!' + }); + getListByPage(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + const deleteRecordBtn = (row) => { + state.deleteId = row.id; + state.deleteDialog = true; + }; + + const conFirmDelete = () => { + deleteRecord({ id: state.deleteId }); + state.deleteDialog = false; + }; + + // 批量删除 + const deleteBatchBtn = async () => { + if (state.deleteArr.length > 0) { + state.deleteSetDialog = true; + } else { + ElMessage({ + type: 'warning', + message: '请先选择要删除的记录' + }); + } + }; + + const conFirmDeleteBatch = async () => { + let res = await timeStrategyApi().deletBatchRecord({ ids: state.deleteArr }); + if (res.data.code === '200') { + state.deleteSetDialog = false; + ElMessage({ + type: 'success', + message: '删除成功!' + }); + getListByPage(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + state.deleteSetDialog = false; + } + }; + + const handleSizeChange = (val: number) => { + state.pageSize = val; + getListByPage(); + }; + const handleCurrentChange = (val: number) => { + state.pageIndex = val; + getListByPage(); + }; + + // 查看记录 + const viewRecord = (row) => { + state.details = JSON.parse(JSON.stringify(row)); + state.dialogDetails = true; + }; + + // 刷新 + const reLoadData = async () => { + getListByPage(); + }; + // 点击修改 + const editRecordBtn = (index, row) => { + state.dialogAddRecord = true; + state.chosenIndex = index; + state.addRecord = JSON.parse(JSON.stringify(row)); + console.log(state.addRecord, 'state.addRecord'); + }; + const closeAdd = () => { + state.addRecord = {}; + state.chosenIndex = null; + }; + const openAdd = () => { + if (state.chosenIndex == null) { + state.addRecord.info = ''; + } + }; + const indexClear = () => { + state.deleteId = null; + }; + + // 折线图 + const renderMenu = async (value: string) => { + Session.set('projectId', value); + userInfos.value.projectId = value; + await initBackEndControlRoutes(); + }; + return { + addRef, + addRules, + View, + Edit, + Delete, + Refresh, + Plus, + toggleSelection, + handleSelectionChange, + searchRecord, + clearSearch, + viewRecord, + deleteRecordBtn, + conFirmDelete, + getListByPage, + getWorkTimeList, + getRestTimeList, + reLoadData, + deleteRecord, + deleteBatchBtn, + conFirmDeleteBatch, + handleSizeChange, + handleCurrentChange, + confirmAddRecord, + closeAdd, + openAdd, + indexClear, + editRecordBtn, + ...toRefs(state) + }; + } +}; +</script> + +<style scoped lang="scss"> +$homeNavLengh: 8; +.home-container { + height: calc(100vh - 144px); + box-sizing: border-box; + overflow: hidden; + .homeCard { + width: 100%; + padding: 20px; + box-sizing: border-box; + background: #fff; + border-radius: 4px; + + .main-card { + width: 100%; + height: 100%; + .cardTop { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 20px; + .mainCardBtn { + margin: 0; + } + } + .pageBtn { + height: 60px; + display: flex; + align-items: center; + justify-content: right; + + .demo-pagination-block + .demo-pagination-block { + margin-top: 10px; + } + .demo-pagination-block .demonstration { + margin-bottom: 16px; + } + } + } + &:last-of-type { + height: calc(100% - 100px); + } + } + .el-row { + display: flex; + align-items: center; + margin-bottom: 20px; + &:last-child { + margin-bottom: 0; + } + .grid-content { + align-items: center; + min-height: 36px; + } + + .topInfo { + display: flex; + align-items: center; + font-size: 16px; + font-weight: bold; + + & > div { + white-space: nowrap; + margin-right: 20px; + } + } + } +} +.el-input { + width: 100% !important; +} +.el-date-editor::v-deep { + width: 100%; +} +.el-select { + width: 100%; +} +</style> diff --git a/src/views/system/personShiftManage/personTimeManage/workingHoursSet/index.vue b/src/views/system/personShiftManage/personTimeManage/workingHoursSet/index.vue new file mode 100644 index 0000000..41487fd --- /dev/null +++ b/src/views/system/personShiftManage/personTimeManage/workingHoursSet/index.vue @@ -0,0 +1,564 @@ +<template> + <div class="home-container"> + <div style="height: 100%"> + <el-row class="homeCard"> + <el-col :span="8"> + <div class="grid-content topInfo"> + <el-input v-model="searchWord" placeholder="休息时间组名称"></el-input> + <el-button type="primary" @click="searchRecord">查询</el-button> + <el-button plain @click="clearSearch">重置</el-button> + </div> + </el-col> + </el-row> + <div class="homeCard"> + <div class="main-card"> + <el-row class="cardTop"> + <el-col :span="12" class="mainCardBtn"> + <el-button type="primary" :icon="Plus" size="default" @click="dialogAddRecord = true">新增</el-button> + <!-- <el-button type="warning" :icon="Edit" size="default" plain>修改</el-button>--> + <el-button type="danger" :icon="Delete" size="default" plain @click="deleteBatchBtn">删除</el-button> + </el-col> + <el-button type="primary" :icon="Refresh" size="default" @click="reLoadData()" /> + </el-row> + <el-table ref="multipleTableRef" :data="tableData" style="width: 100%" height="calc(100% - 100px)" :header-cell-style="{ background: '#fafafa' }" @selection-change="handleSelectionChange"> + <el-table-column type="selection" width="100" /> + <el-table-column property="name" label="工作时间组名称" /> + <el-table-column property="list" :formatter="toNames" label="关联工作时段" /> + <el-table-column property="info" label="描述信息"/> + <el-table-column fixed="right" label="操作" align="center" width="250"> + <template #default="scope"> + <el-button link type="primary" size="small" :icon="View" @click="viewRecord(scope.row)">查看</el-button> + <el-button link type="primary" size="small" :icon="Edit" @click="editRecordBtn(scope.$index, scope.row)">修改</el-button> + <el-button link type="danger" size="small" :icon="Delete" @click="deleteRecordBtn(scope.row)">删除</el-button> + </template> + </el-table-column> + </el-table> + <div class="pageBtn"> + <el-pagination v-model:currentPage="pageIndex" v-model:page-size="pageSize" :page-sizes="[10, 15]" small="false" background layout="total, sizes, prev, pager, next, jumper" :total="totalSize" @size-change="handleSizeChange" @current-change="handleCurrentChange" /> + </div> + </div> + </div> + </div> + <el-dialog v-model="dialogDetails" title="工作时间组"> + <el-form :model="details" label-width="120px"> + <el-form-item label="时间组名称"> + <el-input v-model="details.name" readonly /> + </el-form-item> + <el-form-item label="关联工作时段" v-if="details.list.length > 0"> + <el-input v-model="details.list" readonly /> + </el-form-item> + <el-form-item label="描述信息" v-if="details.info"> + <el-input v-model="details.info" type="textarea" readonly /> + </el-form-item> + <el-form-item> + <el-button type="primary" @click="dialogDetails = false" size="default">确认</el-button> + </el-form-item> + </el-form> + </el-dialog> + <el-dialog v-model="dialogAddRecord" title="工作时间组编辑" @close="closeAdd" @open="openAdd"> + <el-form :model="addRecord" label-width="120px" ref="addRef" :rules="addRules"> + <el-form-item label="时间组名称" prop="name"> + <el-input v-model="addRecord.name"> </el-input> + </el-form-item> + <el-form-item label="关联工作时段" prop="list"> + <el-select v-model="addRecord.list" multiple> + <el-option v-for="(item, index) in workTimeList" :key="index" :label="item.name" :value="item.id" /> + </el-select> + </el-form-item> + <el-form-item label="描述信息" prop="info"> + <el-input v-model="addRecord.info" type="textarea"> </el-input> + </el-form-item> + <el-form-item> + <el-button type="warning" @click="dialogAddRecord = false" size="default" plain>取消</el-button> + <el-button type="primary" @click="confirmAddRecord(addRef)" size="default">确认</el-button> + </el-form-item> + </el-form> + </el-dialog> + <el-dialog v-model="deleteDialog" title="提示" width="30%" center @close="indexClear"> + <span>您确定要删除该条记录吗?</span> + <template #footer> + <span class="dialog-footer"> + <el-button @click="deleteDialog = false" size="default">取消</el-button> + <el-button type="primary" @click="conFirmDelete" size="default">确认</el-button> + </span> + </template> + </el-dialog> + <el-dialog v-model="deleteSetDialog" title="提示" width="30%" center> + <span>您确定要删除这些记录吗?</span> + <template #footer> + <span class="dialog-footer"> + <el-button @click="deleteSetDialog = false" size="default">取消</el-button> + <el-button type="primary" @click="conFirmDeleteBatch" size="default">确认</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, ref, onMounted } from 'vue'; +import { storeToRefs } from 'pinia'; +import { initBackEndControlRoutes } from '/@/router/backEnd'; +import { useUserInfo } from '/@/stores/userInfo'; +import { Session } from '/@/utils/storage'; +import { Edit, View, Plus, Delete, Refresh, Search, Download } from '@element-plus/icons-vue'; +import { ElTable } from 'element-plus'; +import { FormInstance, FormRules, ElMessage } from 'element-plus'; +import { workingHoursSetApi } from '/@/api/systemManage/basicDateManage/personShiftManage/workingHoursSet'; +import { workingHoursApi } from '/@/api/systemManage/basicDateManage/personShiftManage/workingHours'; + +// 定义接口来定义对象的类型 +interface stateType { + tableData: Array<string>; + workTimeList: Array<string>; + multipleSelection: Array<any>; + deleteArr: Array<any>; + dialogDetails: boolean; + dialogAddRecord: boolean; + deleteDialog: boolean; + deleteSetDialog: boolean; + pageIndex: number; + pageSize: number; + chosenIndex: null | number; + deleteId: null | number; + searchWord: string; + totalSize: number; + addRecord: { + name: string; + list: Array<any>; + info: string; + }; + details: { + name: string; + list: Array<any>; + info: string; + }; +} + +export default { + name: 'workingHours', + components: {}, + setup() { + const userInfo = useUserInfo(); + const { userInfos } = storeToRefs(userInfo); + + const state = reactive<stateType>({ + pageIndex: 1, + pageSize: 10, + totalSize: 0, + chosenIndex: null, + searchWord: '', + tableData: [], + workTimeList: [], + multipleSelection: [], + dialogDetails: false, + dialogAddRecord: false, + deleteDialog: false, + deleteSetDialog: false, + addRecord: { + name: '', + list: [], + info: '' + }, + details: { + name: '', + list: [], + info: '' + }, + deleteId: null, + deleteArr: [] + }); + interface User { + name: string; + list: []; + info: string; + } + const multipleTableRef = ref<InstanceType<typeof ElTable>>(); + const toggleSelection = (rows?: User[]) => { + if (rows) { + rows.forEach((row) => { + // TODO: improvement typing when refactor table + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error + multipleTableRef.value!.toggleRowSelection(row, undefined); + }); + } else { + multipleTableRef.value!.clearSelection(); + } + }; + + // 多选 + const handleSelectionChange = (val: User[]) => { + state.multipleSelection = JSON.parse(JSON.stringify(val)); + state.deleteArr = state.multipleSelection.map((item) => { + item = item.id; + return item; + }); + }; + + const addRef = ref<FormInstance>(); + const addRules = reactive<FormRules>({ + name: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + list: [{ required: true, message: '该内容不能为空', trigger: 'blur' }] + }); + + // 页面载入时执行方法 + onMounted(() => { + getListByPage(); + getWorkTimePeriod(); + }); + + // 分页获取工作时间组列表 + const getListByPage = async () => { + const data = { pageSize: state.pageSize, pageIndex: state.pageIndex, searchParams: { name: state.searchWord } }; + let res = await workingHoursSetApi().postWorkTimeGroupPage(data); + if (res.data.code === '200') { + state.tableData = res.data.data.map((item) => { + if (item.list == null) { + item.list = []; + } else { + item.list = Array.from(item.list, ({ workTimePeriodId }) => workTimePeriodId); + } + return item; + }); + state.totalSize = res.data.total; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 表格数据格式化 + const toNames = (row, column, cellValue, index) => { + if (row.list == []) { + return []; + } else { + const nameList = []; + for (let i = 0; i < row.list.length; i++) { + for (let t = 0; t < state.workTimeList.length; t++) { + if (row.list[i] == state.workTimeList[t].id) { + nameList.push(state.workTimeList[t].name); + } + } + } + return nameList.join(); + } + }; + + // 获取工作时段列表 + const getWorkTimePeriod = async () => { + let res = await workingHoursApi().getWorkTimePeriod(); + if (res.data.code === '200') { + state.workTimeList = res.data.data; + console.log(state.workTimeList, 'list'); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 关键词查询记录 + const searchRecord = async () => { + if (state.searchWord == '') { + ElMessage({ + type: 'warning', + message: '请输入查询关键词' + }); + } else { + getListByPage(); + } + }; + + const clearSearch = async () => { + state.searchWord = ''; + getListByPage(); + }; + + // 添加工作时段方法 + const addRecord = async (data: any) => { + let res = await workingHoursSetApi().addWorkTimeGroup(data); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '添加成功!' + }); + getListByPage(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 修改工作时段方法 + const editRecord = async (data: any) => { + let res = await workingHoursSetApi().updateWorkTimeGroup(data); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '修改成功!' + }); + getListByPage(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 新增修改记录 + const confirmAddRecord = async (formEl: FormInstance | undefined) => { + if (!formEl) return; + await formEl.validate(async (valid, fields) => { + if (valid) { + const data = { + name: state.addRecord.name, + info: state.addRecord.info, + workTimePeriodIds: state.addRecord.list + }; + if (state.chosenIndex == null) { + await addRecord(data); + } else { + (data.id = JSON.stringify(state.addRecord.id)), console.log(data, '修改参数'); + await editRecord(data); + } + state.dialogAddRecord = false; + } else { + console.log('error submit!', fields); + } + }); + }; + + // 删除工作时间组方法 + const deleteRecord = async (data: any) => { + let res = await workingHoursSetApi().deleteWorkTimeGroup(data); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '删除成功!' + }); + getListByPage(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + const deleteRecordBtn = (row) => { + state.deleteId = row.id; + state.deleteDialog = true; + }; + + const conFirmDelete = () => { + deleteRecord({ id: state.deleteId }); + state.deleteDialog = false; + }; + + // 批量删除 + const deleteBatchBtn = async () => { + if (state.deleteArr.length > 0) { + state.deleteSetDialog = true; + } else { + ElMessage({ + type: 'warning', + message: '请先选择要删除的记录' + }); + } + }; + + const conFirmDeleteBatch = async () => { + let res = await workingHoursSetApi().deletBatchWorkTimeGroup({ ids: state.deleteArr }); + if (res.data.code === '200') { + state.deleteSetDialog = false; + ElMessage({ + type: 'success', + message: '删除成功!' + }); + getListByPage(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + state.deleteSetDialog = false; + } + }; + + const handleSizeChange = (val: number) => { + state.pageSize = val; + getListByPage(); + }; + const handleCurrentChange = (val: number) => { + state.pageIndex = val; + getListByPage(); + }; + + // 查看记录 + const viewRecord = (row) => { + state.details = JSON.parse(JSON.stringify(row)); + if (row.list == []) { + state.details.list = []; + } else { + state.details.list = []; + for (let i = 0; i < row.list.length; i++) { + for (let t = 0; t < state.workTimeList.length; t++) { + if (row.list[i] == state.workTimeList[t].id) { + state.details.list.push(state.workTimeList[t].name); + } + } + } + } + state.dialogDetails = true; + }; + + // 刷新 + const reLoadData = async () => { + getListByPage(); + }; + // 点击修改 + const editRecordBtn = (index, row) => { + state.dialogAddRecord = true; + state.chosenIndex = index; + state.addRecord = JSON.parse(JSON.stringify(row)); + }; + const closeAdd = () => { + state.addRecord = {}; + state.chosenIndex = null; + }; + const openAdd = () => { + if (state.chosenIndex == null) { + state.addRecord.info = ''; + } + }; + const indexClear = () => { + state.deleteId = null; + }; + + // 折线图 + const renderMenu = async (value: string) => { + Session.set('projectId', value); + userInfos.value.projectId = value; + await initBackEndControlRoutes(); + }; + + return { + addRef, + addRules, + View, + Edit, + Delete, + Refresh, + Plus, + toNames, + toggleSelection, + handleSelectionChange, + searchRecord, + clearSearch, + viewRecord, + deleteRecordBtn, + conFirmDelete, + getListByPage, + getWorkTimePeriod, + reLoadData, + deleteRecord, + deleteBatchBtn, + conFirmDeleteBatch, + handleSizeChange, + handleCurrentChange, + confirmAddRecord, + closeAdd, + openAdd, + indexClear, + editRecordBtn, + ...toRefs(state) + }; + } +}; +</script> + +<style scoped lang="scss"> +$homeNavLengh: 8; +.home-container { + height: calc(100vh - 144px); + box-sizing: border-box; + overflow: hidden; + .homeCard { + width: 100%; + padding: 20px; + box-sizing: border-box; + background: #fff; + border-radius: 4px; + + .main-card { + width: 100%; + height: 100%; + .cardTop { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 20px; + .mainCardBtn { + margin: 0; + } + } + .pageBtn { + height: 60px; + display: flex; + align-items: center; + justify-content: right; + + .demo-pagination-block + .demo-pagination-block { + margin-top: 10px; + } + .demo-pagination-block .demonstration { + margin-bottom: 16px; + } + } + } + &:last-of-type { + height: calc(100% - 100px); + } + } + .el-row { + display: flex; + align-items: center; + margin-bottom: 20px; + &:last-child { + margin-bottom: 0; + } + .grid-content { + align-items: center; + min-height: 36px; + } + + .topInfo { + display: flex; + align-items: center; + font-size: 16px; + font-weight: bold; + + & > div { + white-space: nowrap; + margin-right: 20px; + } + } + } +} +.el-input { + width: 100% !important; +} +.el-date-editor::v-deep { + width: 100%; +} +.el-select { + width: 100%; +} +</style> diff --git a/src/views/system/personShiftManage/scheduleManage/schedule/index.vue b/src/views/system/personShiftManage/scheduleManage/schedule/index.vue new file mode 100644 index 0000000..008fb17 --- /dev/null +++ b/src/views/system/personShiftManage/scheduleManage/schedule/index.vue @@ -0,0 +1,574 @@ +<template> + <div class="home-container"> + <div style="height: 100%"> + <el-row class="homeCard"> + <el-col :span="8"> + <div class="grid-content topInfo"> + <el-input v-model="searchWord" placeholder="时间策略名称"></el-input> + <el-button type="primary" @click="searchRecord">查询</el-button> + <el-button plain @click="clearSearch">重置</el-button> + </div> + </el-col> + </el-row> + <div class="homeCard"> + <div class="main-card"> + <el-row class="cardTop"> + <el-col :span="12" class="mainCardBtn"> + <el-button type="primary" :icon="Plus" size="default" @click="dialogAddRecord = true">新增</el-button> + <!-- <el-button type="warning" :icon="Edit" size="default" plain>修改</el-button>--> +<!-- <el-button type="danger" :icon="Delete" size="default" plain @click="deleteBatchBtn">删除</el-button>--> + </el-col> + <el-button type="primary" :icon="Refresh" size="default" @click="reLoadData()" /> + </el-row> + <el-table ref="multipleTableRef" :data="tableData" style="width: 100%" height="calc(100% - 100px)" :header-cell-style="{ background: '#fafafa' }" @selection-change="handleSelectionChange"> + <el-table-column property="groupName" label="班组名称" /> + <el-table-column property="groupMembers" label="班组人员" :show-overflow-tooltip="true" /> + <el-table-column property="groupInfo" label="描述" /> + <el-table-column fixed="right" label="操作" align="center" width="250"> + <template #default="scope"> + <el-button link type="primary" size="small" :icon="View" @click="viewRecord(scope.row)">查看</el-button> + <el-button link type="primary" size="small" :icon="Edit" @click="editRecordBtn(scope.$index, scope.row)">修改</el-button> + <el-button link type="danger" size="small" :icon="Delete" @click="deleteRecordBtn(scope.row)">删除</el-button> + </template> + </el-table-column> + </el-table> + <div class="pageBtn"> + <el-pagination v-model:currentPage="pageIndex" v-model:page-size="pageSize" :page-sizes="[10, 15]" small="false" background layout="total, sizes, prev, pager, next, jumper" :total="totalSize" @size-change="handleSizeChange" @current-change="handleCurrentChange" /> + </div> + </div> + </div> + </div> + <el-dialog v-model="dialogDetails" title="时间策略"> + <el-form :model="details" label-width="120px"> + <el-form-item label="班组名称"> + <el-input v-model="details.groupName" readonly /> + </el-form-item> + <el-form-item label="班组人员"> + <el-input v-model="details.groupMembers" type="textarea" readonly /> + </el-form-item> + <el-form-item label="描述"> + <el-input v-model="details.groupInfo" type="textarea" readonly /> + </el-form-item> + <el-form-item> + <el-button type="primary" @click="dialogDetails = false" size="default">确认</el-button> + </el-form-item> + </el-form> + </el-dialog> + <el-dialog v-model="dialogAddRecord" title="时间策略编辑" @close="closeAdd" @open="openAdd"> + <el-form :model="addRecord" label-width="120px" ref="addRef" :rules="addRules"> + <el-form-item label="班组名称" prop="groupName"> + <el-input v-model="addRecord.groupName"> </el-input> + </el-form-item> + <el-form-item label="选择部门" prop="department"> + <el-cascader v-model="addRecord.department" :options="departmentList" :props="casProps" :show-all-levels="false" @change="handleChange" /> + </el-form-item> + <el-form-item label="选择人员" prop="groupMembers" v-if="addRecord.department !== ''"> + <el-select v-model="addRecord.groupMembers" multiple> + <el-option v-for="(item, index) in workerList" :label="item.username" :key="index" :value="item.uid">{{ item.username }}</el-option> + </el-select> + </el-form-item> + <el-form-item label="描述" prop="groupInfo"> + <el-input v-model="addRecord.groupInfo" type="textarea"> </el-input> + </el-form-item> + <el-form-item> + <el-button type="warning" @click="dialogAddRecord = false" size="default" plain>取消</el-button> + <el-button type="primary" @click="confirmAddRecord(addRef)" size="default">确认</el-button> + </el-form-item> + </el-form> + </el-dialog> + <el-dialog v-model="deleteDialog" title="提示" width="30%" center @close="indexClear"> + <span>您确定要删除该条记录吗?</span> + <template #footer> + <span class="dialog-footer"> + <el-button @click="deleteDialog = false" size="default">取消</el-button> + <el-button type="primary" @click="conFirmDelete" size="default">确认</el-button> + </span> + </template> + </el-dialog> + <el-dialog v-model="deleteSetDialog" title="提示" width="30%" center> + <span>您确定要删除这些记录吗?</span> + <template #footer> + <span class="dialog-footer"> + <el-button @click="deleteSetDialog = false" size="default">取消</el-button> + <el-button type="primary" @click="conFirmDeleteBatch" size="default">确认</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, ref, onMounted } from 'vue'; +import { storeToRefs } from 'pinia'; +import { initBackEndControlRoutes } from '/@/router/backEnd'; +import { useUserInfo } from '/@/stores/userInfo'; +import { Session } from '/@/utils/storage'; +import { Edit, View, Plus, Delete, Refresh, Search, Download } from '@element-plus/icons-vue'; +import { ElTable } from 'element-plus'; +import { FormInstance, FormRules, ElMessage } from 'element-plus'; +import { teamManageApi } from '/@/api/systemManage/basicDateManage/personShiftManage/teamManage'; + +// 定义接口来定义对象的类型 +interface stateType { + tableData: Array<string>; + departmentList: Array<any>; + workerList: Array<string>; + casProps: {}; + multipleSelection: Array<any>; + deleteArr: Array<any>; + dialogDetails: boolean; + dialogAddRecord: boolean; + deleteDialog: boolean; + deleteSetDialog: boolean; + pageIndex: number; + pageSize: number; + chosenIndex: null | number; + deleteId: null | number; + searchWord: string; + totalSize: number; + addRecord: { + groupName: string; + department: number | null; + depId: number | null; + groupMembers: Array<any>; + groupInfo: string; + }; + details: { + groupName: string; + department: number | null; + groupMembers: Array<any>; + groupInfo: string; + }; +} + +export default { + name: 'workingHours', + components: {}, + setup() { + const userInfo = useUserInfo(); + const { userInfos } = storeToRefs(userInfo); + + const state = reactive<stateType>({ + pageIndex: 1, + pageSize: 10, + totalSize: 0, + chosenIndex: null, + searchWord: '', + tableData: [], + departmentList: [], + department: '', + workerList: [], + casProps: { + expandTrigger: 'hover', + emitPath: false, + value: 'depId', + label: 'depName' + }, + multipleSelection: [], + dialogDetails: false, + dialogAddRecord: false, + deleteDialog: false, + deleteSetDialog: false, + addRecord: { + groupName: '', + department: null, + groupMembers: [], + depId: null, + groupInfo: '' + }, + details: { + groupName: '', + department: null, + groupMembers: [], + depId: null, + groupInfo: '' + }, + deleteId: null, + deleteArr: [] + }); + interface User { + groupName: string; + department: number | null; + depId: number; + groupMembers: Array<any>; + groupInfo: string; + } + const multipleTableRef = ref<InstanceType<typeof ElTable>>(); + const toggleSelection = (rows?: User[]) => { + if (rows) { + rows.forEach((row) => { + // TODO: improvement typing when refactor table + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error + multipleTableRef.value!.toggleRowSelection(row, undefined); + }); + } else { + multipleTableRef.value!.clearSelection(); + } + }; + + // 多选 + const handleSelectionChange = (val: User[]) => { + state.multipleSelection = JSON.parse(JSON.stringify(val)); + state.deleteArr = state.multipleSelection.map((item) => { + item = item.id; + return item; + }); + }; + + const addRef = ref<FormInstance>(); + const addRules = reactive<FormRules>({ + groupName: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + department: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + groupMembers: [{ required: true, message: '该内容不能为空', trigger: 'blur' }] + }); + + // 页面载入时执行方法 + onMounted(() => { + getListByPage(); + getAllDepartment(); + }); + + // 分页获取班组管理列表 + const getListByPage = async () => { + const data = { pageSize: state.pageSize, pageIndex: state.pageIndex, searchParams: { groupName: state.searchWord, containGroupMemberEnable: true } }; + let res = await teamManageApi().getRecordPage(data); + if (res.data.code === '200') { + state.tableData = res.data.data.map((item) => { + if (!item.groupMembers || item.groupMembers == null) { + item.groupMembers = []; + } else { + item.groupMembers = Array.from(item.groupMembers, ({ username }) => username); + } + return item; + }); + state.totalSize = res.data.total; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 获取部门列表 + const getAllDepartment = async () => { + let res = await teamManageApi().getAllDepartment(); + if (res.data.code === '200') { + state.departmentList = res.data.data; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + const handleChange = async (value) => { + state.addRecord.depId = value; + console.log(state.addRecord.department, 'de'); + let res = await teamManageApi().getAllMember(value); + if (res.data.code === '200') { + state.workerList = res.data.data; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 关键词查询记录 + const searchRecord = async () => { + if (state.searchWord == '') { + ElMessage({ + type: 'warning', + message: '请输入查询关键词' + }); + } else { + getListByPage(); + } + }; + + const clearSearch = async () => { + state.searchWord = ''; + getListByPage(); + }; + + // 添加班组管理方法 + const addRecord = async (data: any) => { + let res = await teamManageApi().addRecord(data); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '添加成功!' + }); + getListByPage(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 修改工作时段方法 + const editRecordBtn = async (index, row) => { + state.addRecord = JSON.parse(JSON.stringify(row)); + state.addRecord.department = ''; + state.addRecord.groupMembers = []; + state.dialogAddRecord = true; + state.chosenIndex = index; + }; + + const editRecord = async (data: any) => { + let res = await teamManageApi().updateRecord(data); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '修改成功!' + }); + getListByPage(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 新增修改记录 + const confirmAddRecord = async (formEl: FormInstance | undefined) => { + if (!formEl) return; + await formEl.validate(async (valid, fields) => { + if (valid) { + const data = { + groupName: state.addRecord.groupName, + groupInfo: state.addRecord.groupInfo, + depId: state.addRecord.depId, + groupMemberIds: state.addRecord.groupMembers + }; + if (state.chosenIndex == null) { + await addRecord(data); + } else { + data.groupId = JSON.stringify(state.addRecord.groupId); + await editRecord(data); + } + state.dialogAddRecord = false; + } else { + console.log('error submit!', fields); + } + }); + }; + + // 删除工作时间组方法 + const deleteRecord = async (data: any) => { + let res = await teamManageApi().deleteRecord(data); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '删除成功!' + }); + getListByPage(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + const deleteRecordBtn = (row) => { + console.log(row, 'row'); + state.deleteId = row.groupId; + state.deleteDialog = true; + }; + + const conFirmDelete = () => { + deleteRecord({ groupId: state.deleteId }); + state.deleteDialog = false; + }; + + // 批量删除 + // const deleteBatchBtn = async () => { + // ElMessage({ + // type: 'warning', + // message: '抱歉,本页面暂不支持批量删除' + // }); + // if (state.deleteArr.length > 0) { + // state.deleteSetDialog = true + // } else { + // ElMessage({ + // type: 'warning', + // message: '请先选择要删除的记录' + // }); + // } + // }; + + // const conFirmDeleteBatch = async () => { + // let res = await teamManageApi().deletBatchRecord({ids: state.deleteArr}); + // if (res.data.code === '200') { + // state.deleteSetDialog = false + // ElMessage({ + // type: 'success', + // message: res.data.msg + // }); + // getListByPage() + // } else { + // ElMessage({ + // type: 'warning', + // message: res.data.msg + // }); + // state.deleteSetDialog = false + // } + // } + + const handleSizeChange = (val: number) => { + state.pageSize = val; + getListByPage(); + }; + const handleCurrentChange = (val: number) => { + state.pageIndex = val; + getListByPage(); + }; + + // 查看记录 + const viewRecord = (row) => { + state.details = JSON.parse(JSON.stringify(row)); + state.dialogDetails = true; + }; + + // 刷新 + const reLoadData = async () => { + getListByPage(); + }; + + const closeAdd = () => { + state.addRecord = {}; + state.chosenIndex = null; + }; + const openAdd = () => { + if (state.chosenIndex == null) { + state.addRecord.info = ''; + } + }; + const indexClear = () => { + state.deleteId = null; + }; + + // 折线图 + const renderMenu = async (value: string) => { + Session.set('projectId', value); + userInfos.value.projectId = value; + await initBackEndControlRoutes(); + }; + return { + addRef, + addRules, + View, + Edit, + Delete, + Refresh, + Plus, + handleChange, + toggleSelection, + handleSelectionChange, + searchRecord, + clearSearch, + viewRecord, + deleteRecordBtn, + conFirmDelete, + getListByPage, + reLoadData, + deleteRecord, + handleSizeChange, + handleCurrentChange, + confirmAddRecord, + closeAdd, + openAdd, + indexClear, + editRecordBtn, + ...toRefs(state) + }; + } +}; +</script> + +<style scoped lang="scss"> +$homeNavLengh: 8; +.home-container { + height: calc(100vh - 144px); + box-sizing: border-box; + overflow: hidden; + .homeCard { + width: 100%; + padding: 20px; + box-sizing: border-box; + background: #fff; + border-radius: 4px; + + .main-card { + width: 100%; + height: 100%; + .cardTop { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 20px; + .mainCardBtn { + margin: 0; + } + } + .pageBtn { + height: 60px; + display: flex; + align-items: center; + justify-content: right; + + .demo-pagination-block + .demo-pagination-block { + margin-top: 10px; + } + .demo-pagination-block .demonstration { + margin-bottom: 16px; + } + } + } + &:last-of-type { + height: calc(100% - 100px); + } + } + .el-row { + display: flex; + align-items: center; + margin-bottom: 20px; + &:last-child { + margin-bottom: 0; + } + .grid-content { + align-items: center; + min-height: 36px; + } + + .topInfo { + display: flex; + align-items: center; + font-size: 16px; + font-weight: bold; + + & > div { + white-space: nowrap; + margin-right: 20px; + } + } + } +} +.el-input { + width: 100% !important; +} +.el-date-editor::v-deep { + width: 100%; +} +.el-select { + width: 100%; +} +</style> diff --git a/src/views/system/personShiftManage/scheduleManage/strategy/index.vue b/src/views/system/personShiftManage/scheduleManage/strategy/index.vue new file mode 100644 index 0000000..a781a2f --- /dev/null +++ b/src/views/system/personShiftManage/scheduleManage/strategy/index.vue @@ -0,0 +1,672 @@ +<template> + <div class="home-container"> + <div style="height: 100%"> + <el-row class="homeCard"> + <el-col :span="8"> + <div class="grid-content topInfo"> + <el-input v-model="searchWord" placeholder="时间策略名称"></el-input> + <el-button type="primary" @click="searchRecord">查询</el-button> + <el-button plain @click="clearSearch">重置</el-button> + </div> + </el-col> + </el-row> + <div class="homeCard"> + <div class="main-card"> + <el-row class="cardTop"> + <el-col :span="12" class="mainCardBtn"> + <el-button type="primary" :icon="Plus" size="default" @click="dialogAddRecord = true">新增</el-button> + <!-- <el-button type="warning" :icon="Edit" size="default" plain>修改</el-button>--> +<!-- <el-button type="danger" :icon="Delete" size="default" plain @click="deleteBatchBtn">删除</el-button>--> + </el-col> + <el-button type="primary" :icon="Refresh" size="default" @click="reLoadData()" /> + </el-row> + <el-table ref="multipleTableRef" :data="tableData" style="width: 100%" height="calc(100% - 100px)" :header-cell-style="{ background: '#fafafa' }" @selection-change="handleSelectionChange"> +<!-- <el-table-column type="selection" width="100" />--> + <el-table-column property="groupStrategyName" label="班组策略名称" /> + <el-table-column property="timeStrategy" label="时间策略" width="180" :show-overflow-tooltip="true" /> + <el-table-column property="cycleName" label="循环类型" :show-overflow-tooltip="true" /> + <el-table-column property="groupNames" label="班组" /> + <el-table-column property="cycleStartTime" label="排班开始时间" width="160" /> + <el-table-column property="groupStrategyInfo" label="描述信息" /> + <el-table-column fixed="right" label="操作" align="center" width="250"> + <template #default="scope"> + <el-button link type="primary" size="small" :icon="View" @click="viewRecord(scope.row)">查看</el-button> + <el-button link type="primary" size="small" :icon="Edit" @click="editRecordBtn(scope.$index, scope.row)">修改</el-button> + <el-button link type="danger" size="small" :icon="Delete" @click="deleteRecordBtn(scope.row)">删除</el-button> + </template> + </el-table-column> + </el-table> + <div class="pageBtn"> + <el-pagination v-model:currentPage="pageIndex" v-model:page-size="pageSize" :page-sizes="[10, 15]" small="false" background layout="total, sizes, prev, pager, next, jumper" :total="totalSize" @size-change="handleSizeChange" @current-change="handleCurrentChange" /> + </div> + </div> + </div> + </div> + <el-dialog v-model="dialogDetails" title="班组策略"> + <el-form :model="details" label-width="120px"> + <el-form-item label="策略名称"> + <el-input v-model="details.groupStrategyName" readonly /> + </el-form-item> + <el-form-item label="时间策略"> + <el-input v-model="details.timeStrategy" readonly /> + </el-form-item> + <el-form-item label="循环类型"> + <el-input v-model="details.cycleName" readonly /> + </el-form-item> + <el-form-item label="班组"> + <el-input v-model="details.groupNames" type="textarea" readonly /> + </el-form-item> + <el-form-item label="排班开始时间"> + <el-input v-model="details.cycleStartTime" readonly /> + </el-form-item> + <el-form-item label="描述信息" v-if="details.groupStrategyInfo"> + <el-input v-model="details.groupStrategyInfo" type="textarea" readonly /> + </el-form-item> + <el-form-item> + <el-button type="primary" @click="dialogDetails = false" size="default">确认</el-button> + </el-form-item> + </el-form> + </el-dialog> + <el-dialog v-model="dialogAddRecord" title="班组策略编辑" @close="closeAdd" @open="openAdd"> + <el-form :model="addRecord" label-width="120px" ref="addRef" :rules="addRules"> + <el-form-item label="策略名称" prop="groupStrategyName"> + <el-input v-model="addRecord.groupStrategyName"> </el-input> + </el-form-item> + <el-form-item label="时间策略" prop="timeStrategyId"> + <el-select v-model="addRecord.timeStrategyId"> + <el-option v-for="(item, index) in timeList" :key="index" :label="item.name" :value="item.id" /> + </el-select> + </el-form-item> + <el-form-item label="循环类型" prop="cycle"> + <el-select v-model="addRecord.cycle"> + <el-option v-for="(item, index) in cycleList" :key="index" :label="item.name" :value="item.value" /> + </el-select> + </el-form-item> + <el-form-item label="班组选择" prop="groupIds"> + <el-select v-model="addRecord.groupIds" multiple> + <el-option v-for="(item, index) in teamList" :key="index" :label="item.groupName" :value="item.id" /> + </el-select> + </el-form-item> + <el-form-item label="排班开始时间" prop="cycleStartTime"> + <el-date-picker v-model="addRecord.cycleStartTime" type="date" value-format="YYYY-MM-DD" /> + </el-form-item> + <el-form-item label="描述信息" prop="groupStrategyInfo"> + <el-input v-model="addRecord.groupStrategyInfo" type="textarea"> </el-input> + </el-form-item> + <el-form-item> + <el-button type="warning" @click="dialogAddRecord = false" size="default" plain>取消</el-button> + <el-button type="primary" @click="confirmAddRecord(addRef)" size="default">确认</el-button> + </el-form-item> + </el-form> + </el-dialog> + <el-dialog v-model="deleteDialog" title="提示" width="30%" center @close="indexClear"> + <span>您确定要删除该条记录吗?</span> + <template #footer> + <span class="dialog-footer"> + <el-button @click="deleteDialog = false" size="default">取消</el-button> + <el-button type="primary" @click="conFirmDelete" size="default">确认</el-button> + </span> + </template> + </el-dialog> + <el-dialog v-model="deleteSetDialog" title="提示" width="30%" center> + <span>您确定要删除这些记录吗?</span> + <template #footer> + <span class="dialog-footer"> + <el-button @click="deleteSetDialog = false" size="default">取消</el-button> + <el-button type="primary" @click="conFirmDeleteBatch" size="default">确认</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, ref, onMounted } from 'vue'; +import { storeToRefs } from 'pinia'; +import { initBackEndControlRoutes } from '/@/router/backEnd'; +import { useUserInfo } from '/@/stores/userInfo'; +import { Session } from '/@/utils/storage'; +import { Edit, View, Plus, Delete, Refresh, Search, Download } from '@element-plus/icons-vue'; +import { ElTable } from 'element-plus'; +import { FormInstance, FormRules, ElMessage } from 'element-plus'; +import { teamStrategyApi } from '/@/api/systemManage/basicDateManage/personShiftManage/teamStrategy'; +import { timeStrategyApi } from '/@/api/systemManage/basicDateManage/personShiftManage/timeStrategy'; +import { teamManageApi } from '/@/api/systemManage/basicDateManage/personShiftManage/teamManage'; + +// 定义接口来定义对象的类型 +interface stateType { + tableData: Array<string>; + pageRecord: Array<string>; + timeList: Array<any>; + teamList: Array<any>; + cycleList: Array<any>; + multipleSelection: Array<any>; + deleteArr: Array<any>; + dialogDetails: boolean; + dialogAddRecord: boolean; + deleteDialog: boolean; + deleteSetDialog: boolean; + pageIndex: number; + pageSize: number; + chosenIndex: null | number; + deleteId: null | number; + searchWord: string; + totalSize: number; + addRecord: { + groupStrategyName: string; + timeStrategyId: number | null; + timeStrategy: string; + groupIds: Array<number>; + cycle: number | null; + cycleName: string; + cycleStartTime: string; + groupStrategyInfo: string; + groupStrategyId: number | null; + }; + details: { + groupStrategyName: string; + timeStrategyId: number | null; + timeStrategy: string; + groups: Array<any>; + cycle: number | null; + cycleName: string; + cycleStartTime: string; + groupStrategyInfo: string; + }; +} + +export default { + name: 'teamStrategy', + components: {}, + setup() { + const userInfo = useUserInfo(); + const { userInfos } = storeToRefs(userInfo); + + const state = reactive<stateType>({ + pageIndex: 1, + pageSize: 10, + totalSize: 0, + chosenIndex: null, + searchWord: '', + tableData: [], + pageRecord: [], + timeList: [], + teamList: [], + cycleList: [ + { + name: '周', + value: 3 + }, + { + name: '月', + value: 2 + }, + { + name: '年', + value: 1 + } + ], + multipleSelection: [], + dialogDetails: false, + dialogAddRecord: false, + deleteDialog: false, + deleteSetDialog: false, + addRecord: { + groupStrategyName: '', + timeStrategyId: null, + timeStrategy: '', + groupIds: [], + cycle: null, + cycleName: '', + cycleStartTime: '', + groupStrategyInfo: '', + groupStrategyId: null + }, + details: { + groupStrategyName: '', + timeStrategyId: null, + timeStrategy: '', + groups: [], + cycle: null, + cycleName: '', + cycleStartTime: '', + groupStrategyInfo: '' + }, + deleteId: null, + deleteArr: [] + }); + interface User { + groupStrategyName: string; + timeStrategyId: null | number; + timeStrategy: string; + groups: Array<any>; + cycle: null | number; + cycleName: string; + cycleStartTime: string; + groupStrategyInfo: string; + } + const multipleTableRef = ref<InstanceType<typeof ElTable>>(); + const toggleSelection = (rows?: User[]) => { + if (rows) { + rows.forEach((row) => { + // TODO: improvement typing when refactor table + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error + multipleTableRef.value!.toggleRowSelection(row, undefined); + }); + } else { + multipleTableRef.value!.clearSelection(); + } + }; + + // 多选 + const handleSelectionChange = (val: User[]) => { + state.multipleSelection = JSON.parse(JSON.stringify(val)); + state.deleteArr = state.multipleSelection.map((item) => { + item = item.id; + return item; + }); + }; + + const addRef = ref<FormInstance>(); + const addRules = reactive<FormRules>({ + groupStrategyName: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + timeStrategyId: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + groupIds: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + cycle: [{ required: true, message: '该内容不能为空', trigger: 'blur' }], + cycleStartTime: [{ required: true, message: '该内容不能为空', trigger: 'blur' }] + }); + + // 页面载入时执行方法 + onMounted(() => { + getListByPage(); + getTimeList(); + getTeamList(); + }); + + // 分页获取班组策略列表 + const getListByPage = async () => { + const data = { pageSize: state.pageSize, pageIndex: state.pageIndex, searchParams: { name: state.searchWord, containGroupEnable: true } }; + let res = await teamStrategyApi().getRecordPage(data); + if (res.data.code === '200') { + state.pageRecord = res.data.data; + state.tableData = res.data.data.map((item) => { + item.cycleName = item.cycle == 1 ? '年' : item.cycle == 2 ? '月' : item.cycle == 3 ? '周' : ''; + if (!item.groups || item.groups == null) { + item.groups = []; + } else { + item.groups = item.groups.map((i) => { + return Object.assign({}, { groupId: i.groupId, groupName: i.groupName }); + }); + item.groupIds = Array.from(item.groups, ({ groupId }) => groupId); + item.groupNames = Array.from(item.groups, ({ groupName }) => groupName); + } + return item; + }); + state.tableData.map(async (item) => { + if (!item.timeStrategyId || item.timeStrategyId == null) { + item.timeStrategy = ''; + } else { + let op = await timeStrategyApi().getRecordById({ id: item.timeStrategyId }); + if (op.data.code && op.data.code === '200') { + if (op.data.data) { + item.timeStrategy = op.data.data.name; + } else { + item.timeStrategy = ''; + } + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } + return item; + }); + console.log(state.tableData, 'state.tableData'); + state.totalSize = res.data.total; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 循环类型格式化 + // const toNames =(row, column, cellValue, index) =>{ + // return row.cycle == 1? '年':(row.type == 2? '月': '周') + // } + + // 时间策略格式化 + // const timeName = async (row, column, cellValue, index) =>{ + // let res = await timeStrategyApi().getRecordById({id: row.timeStrategyId}) + // if (res.data.code === '200') { + // return row.timeStrategyId = res.name + // } else { + // ElMessage({ + // type: 'warning', + // message: res.data.msg + // }); + // } + // } + + // 获取时间策略列表 + const getTimeList = async () => { + let res = await timeStrategyApi().getAllRecord(); + if (res.data.code === '200') { + console.log(res.data.data, 'timestrategy'); + state.timeList = res.data.data; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 获取班组列表 + const getTeamList = async () => { + let res = await teamManageApi().getRecord({ name: '' }); + if (res.data.code === '200') { + state.teamList = res.data.data; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 关键词查询记录 + const searchRecord = async () => { + if (state.searchWord == '') { + ElMessage({ + type: 'warning', + message: '请输入查询关键词' + }); + } else { + getListByPage(); + } + }; + + const clearSearch = async () => { + state.searchWord = ''; + getListByPage(); + }; + + // 添加班组策略方法 + const addRecord = async (data: any) => { + let res = await teamStrategyApi().addRecord(data); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '添加成功!' + }); + getListByPage(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 修改工作时段方法 + const editRecord = async (data: any) => { + let res = await teamStrategyApi().updateRecord(data); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '修改成功!' + }); + getListByPage(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 新增修改记录 + const confirmAddRecord = async (formEl: FormInstance | undefined) => { + if (!formEl) return; + await formEl.validate(async (valid, fields) => { + if (valid) { + const data = { + groupStrategyName: state.addRecord.groupStrategyName, + groupStrategyInfo: state.addRecord.groupStrategyInfo, + groupStrategyCycleType: state.addRecord.cycle, + timeStrategyId: state.addRecord.timeStrategyId, + groupIds: state.addRecord.groupIds, + cycleStartTime: state.addRecord.cycleStartTime + }; + if (state.chosenIndex == null) { + await addRecord(data); + } else { + data.groupStrategyId = JSON.stringify(state.addRecord.groupStrategyId); + await editRecord(data); + } + state.dialogAddRecord = false; + } else { + console.log('error submit!', fields); + } + }); + }; + + // 删除班组策略方法 + const deleteRecord = async (data: any) => { + let res = await teamStrategyApi().deleteRecord(data); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '删除成功!' + }); + getListByPage(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + const deleteRecordBtn = (row) => { + state.deleteId = row.groupStrategyId; + state.deleteDialog = true; + }; + + const conFirmDelete = () => { + deleteRecord({ groupStrategyId: state.deleteId }); + state.deleteDialog = false; + }; + + // 批量删除 + // const deleteBatchBtn = async () => { + // ElMessage({ + // type: 'warning', + // message: '抱歉,本页面暂不支持批量删除' + // }); + // if (state.deleteArr.length > 0) { + // state.deleteSetDialog = true + // } else { + // ElMessage({ + // type: 'warning', + // message: '请先选择要删除的记录' + // }); + // } + // }; + + // const conFirmDeleteBatch = async () => { + // let res = await timeStrategyApi().deletBatchRecord({ids: state.deleteArr}); + // if (res.data.code === '200') { + // state.deleteSetDialog = false + // ElMessage({ + // type: 'success', + // message: res.data.msg + // }); + // getListByPage() + // } else { + // ElMessage({ + // type: 'warning', + // message: res.data.msg + // }); + // state.deleteSetDialog = false + // } + // } + + const handleSizeChange = (val: number) => { + state.pageSize = val; + getListByPage(); + }; + const handleCurrentChange = (val: number) => { + state.pageIndex = val; + getListByPage(); + }; + + // 查看记录 + const viewRecord = (row) => { + state.details = JSON.parse(JSON.stringify(row)); + state.dialogDetails = true; + }; + + // 刷新 + const reLoadData = async () => { + getListByPage(); + }; + // 点击修改 + const editRecordBtn = (index, row) => { + state.dialogAddRecord = true; + state.chosenIndex = index; + state.addRecord = JSON.parse(JSON.stringify(row)); + console.log(state.addRecord, 'state.addRecord'); + }; + const closeAdd = () => { + state.addRecord = {}; + state.chosenIndex = null; + }; + const openAdd = () => { + if (state.chosenIndex == null) { + state.addRecord.info = ''; + } + }; + const indexClear = () => { + state.deleteId = null; + }; + + // 折线图 + const renderMenu = async (value: string) => { + Session.set('projectId', value); + userInfos.value.projectId = value; + await initBackEndControlRoutes(); + }; + return { + addRef, + addRules, + View, + Edit, + Delete, + Refresh, + Plus, + toggleSelection, + handleSelectionChange, + searchRecord, + clearSearch, + viewRecord, + deleteRecordBtn, + conFirmDelete, + getListByPage, + reLoadData, + deleteRecord, + handleSizeChange, + handleCurrentChange, + confirmAddRecord, + closeAdd, + openAdd, + indexClear, + editRecordBtn, + ...toRefs(state) + }; + } +}; +</script> + +<style scoped lang="scss"> +$homeNavLengh: 8; +.home-container { + height: calc(100vh - 144px); + box-sizing: border-box; + overflow: hidden; + .homeCard { + width: 100%; + padding: 20px; + box-sizing: border-box; + background: #fff; + border-radius: 4px; + + .main-card { + width: 100%; + height: 100%; + .cardTop { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 20px; + .mainCardBtn { + margin: 0; + } + } + .pageBtn { + height: 60px; + display: flex; + align-items: center; + justify-content: right; + + .demo-pagination-block + .demo-pagination-block { + margin-top: 10px; + } + .demo-pagination-block .demonstration { + margin-bottom: 16px; + } + } + } + &:last-of-type { + height: calc(100% - 100px); + } + } + .el-row { + display: flex; + align-items: center; + margin-bottom: 20px; + &:last-child { + margin-bottom: 0; + } + .grid-content { + align-items: center; + min-height: 36px; + } + + .topInfo { + display: flex; + align-items: center; + font-size: 16px; + font-weight: bold; + + & > div { + white-space: nowrap; + margin-right: 20px; + } + } + } +} +.el-input { + width: 100% !important; +} +.el-date-editor::v-deep { + width: 100%; +} +.el-select { + width: 100%; +} +</style> diff --git a/src/views/system/role/component/roleDialog.vue b/src/views/system/role/component/roleDialog.vue new file mode 100644 index 0000000..9bdaac2 --- /dev/null +++ b/src/views/system/role/component/roleDialog.vue @@ -0,0 +1,150 @@ +<template> + <div class="system-add-role-container"> + <el-dialog :title="title" v-model="isShowRoleDialog" width="769px"> + <el-form :model="roleForm" size="default" label-width="90px"> + <el-row :gutter="35"> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="角色名称"> + <el-input v-model="roleForm.roleName" placeholder="请输入角色名称" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="角色标识"> + <el-input v-model="roleForm.roleCode" placeholder="请输入角色标识" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20"> + <el-form-item label="角色描述"> + <el-input v-model="roleForm.roleInfo" type="textarea" placeholder="请输入角色描述" maxlength="150"></el-input> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="isShowRoleDialog = !isShowRoleDialog" size="default">取 消</el-button> + <el-button type="primary" @click="onSubmit" v-throttle size="default">{{ buttonName }}</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script lang="ts"> +import { ElMessage } from 'element-plus'; +import { reactive, toRefs, defineComponent } from 'vue'; +import { useRoleApi } from '/@/api/systemManage/role'; + +// 定义接口来定义对象的类型 +interface MenuDataTree { + id: number; + label: string; + children?: MenuDataTree[]; +} +interface RoleState { + title: string; + buttonName: string; + isShowRoleDialog: boolean; + roleForm: { + roleName: string; + roleCode: string; + roleInfo: string; + }; + menuData: Array<MenuDataTree>; + menuProps: { + children: string; + label: string; + }; +} + +export default defineComponent({ + name: 'systemAddRole', + setup(prop, context) { + const state = reactive<RoleState>({ + isShowRoleDialog: false, + title: '', + buttonName: '', + roleForm: { + roleName: '', // 角色名称 + roleCode: '', // 角色标识 + roleInfo: '' // 排序 + }, + menuData: [], + menuProps: { + children: 'children', + label: 'label' + } + }); + // 打开弹窗 + const openDialog = (type: string, value: any) => { + state.isShowRoleDialog = true; + if (type === '新增') { + state.title = '新增角色'; + state.buttonName = '新增'; + state.roleForm = { + roleName: '', + roleCode: '', + roleInfo: '' + }; + } else { + state.title = '修改角色'; + state.buttonName = '修改'; + state.roleForm = JSON.parse(JSON.stringify(value)); + } + }; + // 新增 + const onSubmit = async () => { + if (state.title === '新增角色') { + let res = await useRoleApi().addRole(state.roleForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '角色新增成功', + duration: 2000 + }); + state.isShowRoleDialog = false; + context.emit('refreshRoleList'); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } else { + let res = await useRoleApi().modRole(state.roleForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '角色修改成功', + duration: 2000 + }); + state.isShowRoleDialog = false; + context.emit('refreshRoleList'); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } + }; + // 获取菜单结构数据 + return { + onSubmit, + openDialog, + ...toRefs(state) + }; + } +}); +</script> + +<style scoped lang="scss"> +.system-add-role-container { + .menu-data-tree { + width: 100%; + border: 1px solid var(--el-border-color); + border-radius: var(--el-input-border-radius, var(--el-border-radius-base)); + padding: 5px; + } +} +</style> diff --git a/src/views/system/role/index.vue b/src/views/system/role/index.vue new file mode 100644 index 0000000..ca6131f --- /dev/null +++ b/src/views/system/role/index.vue @@ -0,0 +1,153 @@ +<template> + <div class="system-role-container"> + <el-card shadow="hover"> + <div class="system-user-search mb15"> + <!-- <el-input size="default" placeholder="请输入角色名称" style="max-width: 180px"> </el-input>--> + <el-button size="default" type="primary" class="ml10" @click="handleSearch"> + <el-icon> + <ele-Search /> + </el-icon> + 查询 + </el-button> + <el-button size="default" type="success" class="ml10" @click="onOpenDialogRef('新增', '')"> + <el-icon> + <ele-FolderAdd /> + </el-icon> + 新增角色 + </el-button> + </div> + <el-table :data="tableData.data" style="width: 100%"> + <el-table-column type="index" label="序号" width="60" /> + <el-table-column prop="roleName" label="角色名称" show-overflow-tooltip></el-table-column> + <el-table-column prop="roleCode" label="角色标识" show-overflow-tooltip></el-table-column> + <el-table-column prop="roleInfo" label="角色描述" show-overflow-tooltip></el-table-column> + <el-table-column prop="createTime" label="创建时间" show-overflow-tooltip></el-table-column> + <el-table-column label="操作" width="150"> + <template #default="scope"> + <el-button size="small" text type="primary" @click="onOpenDialogRef('新增', '')">新增</el-button> + <el-button size="small" text type="primary" @click="onOpenDialogRef('修改', scope.row)">修改</el-button> + <el-button size="small" style="color: red" text type="primary" @click="onRowDel(scope.row)">删除</el-button> + </template> + </el-table-column> + </el-table> + </el-card> + <roleDialog ref="roleDialogRef" @refreshRoleList="initRoleTableData" /> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, onMounted, ref, defineComponent } from 'vue'; +import { ElMessageBox, ElMessage } from 'element-plus'; +import roleDialog from '/@/views/system/role/component/roleDialog.vue'; +import { useRoleApi } from '/@/api/systemManage/role'; +import { useMenuApi } from '/@/api/systemManage/menu'; +import { Session } from '/@/utils/storage'; +import { initBackEndControlRoutes } from '/@/router/backEnd'; + +// 定义接口来定义对象的类型 +interface TableData { + roleName: string; + roleSign: string; + describe: string; + sort: number; + status: boolean; + createTime: string; +} +interface TableDataState { + tableData: { + data: Array<TableData>; + total: number; + loading: boolean; + param: { + pageNum: number; + pageSize: number; + }; + }; +} + +export default defineComponent({ + name: 'systemRole', + components: { roleDialog }, + setup() { + const roleDialogRef = ref(); + const state = reactive<TableDataState>({ + tableData: { + data: [], + total: 0, + loading: false, + param: { + pageNum: 1, + pageSize: 10 + } + } + }); + // 初始化表格数据 + const initRoleTableData = async () => { + let res = await useRoleApi().getRoleList(); + if (res.data.code === '200') { + state.tableData.data = res.data.data; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + // 打开新增角色弹窗 + const onOpenDialogRef = (type: string, value: any) => { + roleDialogRef.value.openDialog(type, value); + }; + // 删除角色 + const onRowDel = (row: any) => { + ElMessageBox.confirm(`此操作将永久删除角色名称:“${row.roleName}”,是否继续?`, '提示', { + confirmButtonText: '确认', + cancelButtonText: '取消', + type: 'warning' + }) + .then(async () => { + let res = await useRoleApi().deleteRole({ roleId: row.roleId }); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + duration: 2000, + message: '删除成功' + }); + await initRoleTableData(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }) + .catch(() => {}); + }; + const handleSearch = () => { + initRoleTableData(); + }; + // 分页改变 + const onHandleSizeChange = (val: number) => { + state.tableData.param.pageSize = val; + }; + // 分页改变 + const onHandleCurrentChange = (val: number) => { + state.tableData.param.pageNum = val; + }; + // 页面加载时 + onMounted(() => { + initRoleTableData(); + }); + return { + onRowDel, + roleDialog, + handleSearch, + roleDialogRef, + onOpenDialogRef, + initRoleTableData, + onHandleSizeChange, + onHandleCurrentChange, + ...toRefs(state) + }; + } +}); +</script> diff --git a/src/views/system/user/component/userDialog.vue b/src/views/system/user/component/userDialog.vue new file mode 100644 index 0000000..0eb4dd7 --- /dev/null +++ b/src/views/system/user/component/userDialog.vue @@ -0,0 +1,241 @@ +<template> + <div class="system-add-user-container"> + <el-dialog :title="title" v-model="isShowUserDialog" width="769px"> + <el-form :model="userForm" size="default" ref="userRef" :rules="userFormRules" label-width="90px"> + <el-row :gutter="35"> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20" v-if="disabled"> + <el-form-item label="用户名"> + <el-input v-model.trim="userForm.username" :disabled="disabled" placeholder="" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="真实姓名" prop="realName"> + <el-input v-model.trim="userForm.realName" placeholder="请输入真实姓名" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="关联角色" prop="roleId"> + <el-select v-model="userForm.roleId" placeholder="请选择" clearable class="w100"> + <el-option v-for="item in roleData" :key="item.roleId" :label="item.roleName" :value="item.roleId"> </el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="部门" prop="depId"> + <el-cascader :options="departmentData" :props="{ emitPath: false, checkStrictly: true, value: 'depId', label: 'depName' }" placeholder="请选择部门" clearable class="w100" v-model="userForm.depId"> </el-cascader> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="手机号" prop="phone"> + <el-input v-model.trim="userForm.phone" placeholder="请输入手机号" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="身份证" prop="identify"> + <el-input v-model.trim="userForm.identify" placeholder="请输入身份证" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="邮箱" prop="email"> + <el-input v-model.trim="userForm.email" placeholder="请输入" clearable></el-input> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="性别" prop="gender"> + <el-select v-model="userForm.gender" placeholder="请选择" clearable class="w100"> + <el-option v-for="item in sexList" :key="item.id" :value="item.id" :label="item.name"> </el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> + <el-form-item label="账户过期" prop="expireTime"> + <el-date-picker v-model="userForm.expireTime" type="date" placeholder="请选择" class="w100"> </el-date-picker> + </el-form-item> + </el-col> + <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20" v-if="!disabled"> + <el-form-item label="账户密码" prop="password"> + <el-input v-model.trim="userForm.password" placeholder="请输入" type="password" show-password> + </el-input> + </el-form-item> + </el-col> + + <!-- <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">--> + <!-- <el-form-item label="用户状态">--> + <!-- <el-switch v-model="userForm.status" inline-prompt active-value = 1 inactive-value= 0 active-text="启" inactive-text="禁"></el-switch>--> + <!-- </el-form-item>--> + <!-- </el-col>--> + </el-row> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="isShowUserDialog = !isShowUserDialog" size="default">取 消</el-button> + <el-button type="primary" v-throttle @click="onSubmit" size="default">确 定</el-button> + </span> + </template> + </el-dialog> + </div> +</template> + +<script lang="ts"> +import { reactive, toRefs, onMounted, defineComponent, ref } from 'vue'; +import { ElMessageBox, ElMessage } from 'element-plus'; +import { userApi } from '/@/api/systemManage/user'; + +// 定义接口来定义对象的类型 +interface DeptData {} +interface roleData {} +interface sexData {} +interface UserState { + title: string; + disabled: boolean; + isShowUserDialog: boolean; + userForm: { + username: string; + realName: string; + roleId: number | null; + depId: number | null; + phone: string; + email: string; + gender: number | null; + positionId: number | null; + password: string; + expireTime: string; + status: number; + identify: string; + }; + userFormRules:{ + + }, + departmentData: Array<DeptData>; + roleData: Array<roleData>; + sexList: Array<sexData>; +} + +export default defineComponent({ + name: 'user', + setup(props, context) { + const userRef = ref() + const state = reactive<UserState>({ + title: '', + disabled: false, + isShowUserDialog: false, + userForm: { + username: '', // 账户名称 + realName: '', // 用户昵称 + roleId: null, // 关联角色 + depId: null, // 部门 + phone: '', // 手机号 + email: '', // 邮箱 + identify: '', + gender: null, // 性别 + password: '', // 账户密码 + positionId: 1, // 岗位 + expireTime: '', // 账户过期 + status: 1 // 用户状态 + }, + userFormRules:{ + username: [{ required: true, message: '请填写用户名', trigger: 'blur' }], + realName: [{ required: true, message: '请填写真实姓名', trigger: 'blur' }], + roleId: [{ required: true, message: '请选择用户角色', trigger: 'change' }], + depId: [{ required: true, message: '请选择部门', trigger: 'change' }], + phone: [{ required: true, message: '请填写手机号', trigger: 'blur' }], + email: [{ required: true, message: '请填写邮箱地址', trigger: 'blur' }], + identify: [{ required: true, message: '请填写身份证号', trigger: 'blur' }], + gender: [{ required: true, message: '请选择性别', trigger: 'change' }], + expireTime: [{ required: true, message: '请输入账户过期时间', trigger: 'blur' }], + password: [{ required: true, message: '请输入账户密码', trigger: 'blur' }], + }, + departmentData: [], // 部门数据 + roleData: [], //角色数据 + sexList: [ + { id: 1, name: '男' }, + { id: 0, name: '女' } + ] + }); + // 打开弹窗 + const openDialog = (type: string, value: any, departmentList: [], roleList: []) => { + state.isShowUserDialog = true; + state.departmentData = departmentList; + state.roleData = roleList; + if (type === '新增') { + state.disabled = false + state.title = '新增用户'; + state.userForm = { + username: '', + realName: '', + roleId: null, + depId: null, + phone: '', + email: '', + identify: '', + positionId: 1, + gender: null, + password: '', + expireTime: '', + status: 1 + }; + } else { + state.disabled = true + state.title = '修改用户'; + state.userForm = JSON.parse(JSON.stringify(value)); + } + }; + + // 新增修改 + const onSubmit = async () => { + userRef.value.validate(async (valid:Boolean) => { + if(valid){ + if (state.title === '新增用户') { + let res = await userApi().addUser(state.userForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '用户新增成功', + duration: 2000 + }); + state.isShowUserDialog = false; + context.emit('getUserList'); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } else { + let res = await userApi().modUser(state.userForm); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + message: '用户修改成功', + duration: 2000 + }); + state.isShowUserDialog = false; + context.emit('getUserList'); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + } + }else{ + ElMessage({ + type:'warning', + message:'请完善基本信息' + }) + } + }) + + }; + + // 页面加载时 + onMounted(() => {}); + return { + userRef, + openDialog, + onSubmit, + ...toRefs(state) + }; + } +}); +</script> diff --git a/src/views/system/user/index.vue b/src/views/system/user/index.vue new file mode 100644 index 0000000..a892e9c --- /dev/null +++ b/src/views/system/user/index.vue @@ -0,0 +1,227 @@ +<template> + <div class="system-user-container"> + <el-card shadow="hover"> + <div class="system-user-search mb15"> + <el-input size="default" v-model.trim="userTableData.listQuery.searchParams.username" placeholder="请输入用户名" style="max-width: 180px"> </el-input> + <el-input size="default" v-model.trim="userTableData.listQuery.searchParams.realName" placeholder="请输入真实姓名" style="max-width: 180px; margin-left: 10px"> </el-input> + <el-button size="default" type="primary" class="ml10" @click="initUserTableData"> + <el-icon> + <ele-Search /> + </el-icon> + 查询 + </el-button> + <el-button size="default" type="success" class="ml10" @click="onOpenUserDialog('新增', '')"> + <el-icon> + <ele-FolderAdd /> + </el-icon> + 新增用户 + </el-button> + </div> + <el-table :data="userTableData.data" style="width: 100%"> + <el-table-column type="index" label="序号" width="60" /> + <el-table-column prop="username" label="用户名" show-overflow-tooltip></el-table-column> + <el-table-column prop="realName" label="真实姓名" show-overflow-tooltip></el-table-column> + <el-table-column prop="sex" label="性别" show-overflow-tooltip></el-table-column> + <el-table-column prop="role.name" label="关联角色" show-overflow-tooltip></el-table-column> + <el-table-column prop="department.name" label="部门" show-overflow-tooltip></el-table-column> + <el-table-column prop="phone" label="手机号" show-overflow-tooltip></el-table-column> + <el-table-column prop="email" label="邮箱" show-overflow-tooltip></el-table-column> + <el-table-column prop="status" label="用户状态" show-overflow-tooltip> + <template #default="scope"> + <el-tag type="success" v-if="scope.row.status">启用</el-tag> + <el-tag type="info" v-else>禁用</el-tag> + </template> + </el-table-column> + <el-table-column prop="gmtCreate" label="创建时间" show-overflow-tooltip></el-table-column> + <el-table-column label="操作" width="100"> + <template #default="scope"> + <el-button :disabled="scope.row.userName === 'admin'" size="small" text type="primary" @click="onOpenUserDialog('修改', scope.row)">修改</el-button> + <el-button style="color: red" :disabled="scope.row.userName === 'admin'" size="small" text type="primary" @click="onRowDel(scope.row)">删除</el-button> + </template> + </el-table-column> + </el-table> + <br /> + <el-pagination @size-change="onHandleSizeChange" @current-change="onHandleCurrentChange" class="page-position" :pager-count="5" :page-sizes="[10, 20, 30]" v-model:current-page="userTableData.listQuery.pageIndex" background v-model:page-size="userTableData.listQuery.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="userTableData.total"> </el-pagination> + <br /> + <br /> + </el-card> + <userDialog ref="userRef" @getUserList="initUserTableData" /> + </div> +</template> + +<script lang="ts"> +import { toRefs, reactive, onMounted, ref, defineComponent } from 'vue'; +import { ElMessageBox, ElMessage } from 'element-plus'; +import userDialog from '/@/views/system/user/component/userDialog.vue'; +import { userApi } from '/@/api/systemManage/user'; +import { departmentApi } from '/@/api/systemManage/department'; +import { useRoleApi } from '/@/api/systemManage/role'; + +// 定义接口来定义对象的类型 +interface TableDataRow { + userName: string; + userNickname: string; + roleSign: string; + department: string[]; + phone: string; + email: string; + sex: string; + password: string; + overdueTime: Date; + status: boolean; + describe: string; + createTime: string; +} +interface DepartmentDataRow {} +interface TableDataState { + userTableData: { + data: Array<TableDataRow>; + total: number; + loading: boolean; + listQuery: { + searchParams: { + username: string | null; + realName: string | null; + }; + pageIndex: number; + pageSize: number; + }; + }; + departmentList: []; + roleList: []; +} + +export default defineComponent({ + name: 'systemUser', + components: { userDialog }, + setup() { + const userRef = ref(); + const state = reactive<TableDataState>({ + userTableData: { + data: [], + total: 0, + loading: false, + listQuery: { + searchParams: { + username: null, + realName: null + }, + pageIndex: 1, + pageSize: 10 + } + }, + departmentList: [], + roleList: [] + }); + // 初始化表格数据 + const initUserTableData = async () => { + let res = await userApi().getUserList(state.userTableData.listQuery); + if (res.data.code === '200') { + state.userTableData.data = res.data.data; + state.userTableData.total = res.data.total; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + const getDepartmentData = async () => { + let res = await departmentApi().getDepartmentList(); + if (res.data.code === '200') { + state.departmentList = res.data.data; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + const getRoleData = async () => { + let res = await useRoleApi().getRoleList(); + if (res.data.code === '200') { + state.roleList = res.data.data; + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }; + + // 打开新增修改用户弹窗 + const onOpenUserDialog = (type: string, value: any) => { + userRef.value.openDialog(type, value, state.departmentList, state.roleList); + }; + + // 删除用户 + const onRowDel = (row: TableDataRow) => { + ElMessageBox.confirm(`此操作将永久删除账户名称:“${row.realName}”,是否继续?`, '提示', { + confirmButtonText: '确认', + cancelButtonText: '取消', + type: 'warning' + }) + .then(async () => { + let res = await userApi().deleteUser({ uid: row.uid }); + if (res.data.code === '200') { + ElMessage({ + type: 'success', + duration: 2000, + message: '删除成功' + }); + await initUserTableData(); + } else { + ElMessage({ + type: 'warning', + message: res.data.msg + }); + } + }) + .catch(() => {}); + }; + // 分页改变 + const onHandleSizeChange = (val: number) => { + state.userTableData.listQuery.pageSize = val; + initUserTableData(); + }; + // 分页改变 + const onHandleCurrentChange = (val: number) => { + state.userTableData.listQuery.pageIndex = val; + initUserTableData(); + }; + // 页面加载时 + onMounted(() => { + let a = { name: 1, c: { name: 1 } }; + let b = Object.assign({}, a); + b.c.name = 2; + console.log(a.c.name); + initUserTableData(); + getDepartmentData(); + getRoleData(); + }); + return { + userRef, + onOpenUserDialog, + onRowDel, + onHandleSizeChange, + initUserTableData, + onHandleCurrentChange, + ...toRefs(state) + }; + } +}); +</script> +<style scoped> +:deep(.el-textarea.is-disabled .el-textarea__inner) { + background-color: var(--el-card-bg-color); + color: var(--el-input-text-color, var(--el-text-color-regular)); +} +:deep(.el-input.is-disabled .el-input__inner) { + color: var(--el-input-text-color, var(--el-text-color-regular)); +} +:deep(.el-input.is-disabled .el-input__wrapper) { + background-color: var(--el-card-bg-color); +} +</style> diff --git a/static/loginPage.js/login.js b/static/loginPage.js/login.js new file mode 100644 index 0000000..db81ff6 --- /dev/null +++ b/static/loginPage.js/login.js @@ -0,0 +1,1544 @@ +/* ----------------------------------------------- +/* Author : Vincent Garreau - vincentgarreau.com +/* MIT license: http://opensource.org/licenses/MIT +/* Demo / Generator : vincentgarreau.com/particles.js +/* GitHub : github.com/VincentGarreau/particles.js +/* How to use? : Check the GitHub README +/* v2.0.0 +/* ----------------------------------------------- */ +function loginBg() { +var pJS = function(tag_id, params){ + + var canvas_el = document.querySelector('#'+tag_id+' > .particles-js-canvas-el'); + + /* particles.js variables with default values */ + this.pJS = { + canvas: { + el: canvas_el, + w: canvas_el.offsetWidth, + h: canvas_el.offsetHeight + }, + particles: { + number: { + value: 400, + density: { + enable: true, + value_area: 800 + } + }, + color: { + value: '#fff' + }, + shape: { + type: 'circle', + stroke: { + width: 0, + color: '#ff0000' + }, + polygon: { + nb_sides: 5 + }, + image: { + src: '', + width: 100, + height: 100 + } + }, + opacity: { + value: 1, + random: false, + anim: { + enable: false, + speed: 2, + opacity_min: 0, + sync: false + } + }, + size: { + value: 20, + random: false, + anim: { + enable: false, + speed: 20, + size_min: 0, + sync: false + } + }, + line_linked: { + enable: true, + distance: 100, + color: '#fff', + opacity: 1, + width: 1 + }, + move: { + enable: true, + speed: 2, + direction: 'none', + random: false, + straight: false, + out_mode: 'out', + bounce: false, + attract: { + enable: false, + rotateX: 3000, + rotateY: 3000 + } + }, + array: [] + }, + interactivity: { + detect_on: 'canvas', + events: { + onhover: { + enable: true, + mode: 'grab' + }, + onclick: { + enable: true, + mode: 'push' + }, + resize: true + }, + modes: { + grab:{ + distance: 100, + line_linked:{ + opacity: 1 + } + }, + bubble:{ + distance: 200, + size: 80, + duration: 0.7 + }, + repulse:{ + distance: 200, + duration: 0.4 + }, + push:{ + particles_nb: 4 + }, + remove:{ + particles_nb: 2 + } + }, + mouse:{} + }, + retina_detect: false, + fn: { + interact: {}, + modes: {}, + vendors:{} + }, + tmp: {} + }; + + var pJS = this.pJS; + + /* params settings */ + if(params){ + Object.deepExtend(pJS, params); + } + + pJS.tmp.obj = { + size_value: pJS.particles.size.value, + size_anim_speed: pJS.particles.size.anim.speed, + move_speed: pJS.particles.move.speed, + line_linked_distance: pJS.particles.line_linked.distance, + line_linked_width: pJS.particles.line_linked.width, + mode_grab_distance: pJS.interactivity.modes.grab.distance, + mode_bubble_distance: pJS.interactivity.modes.bubble.distance, + mode_bubble_size: pJS.interactivity.modes.bubble.size, + mode_repulse_distance: pJS.interactivity.modes.repulse.distance + }; + + + pJS.fn.retinaInit = function(){ + + if(pJS.retina_detect && window.devicePixelRatio > 1){ + pJS.canvas.pxratio = window.devicePixelRatio; + pJS.tmp.retina = true; + } + else{ + pJS.canvas.pxratio = 1; + pJS.tmp.retina = false; + } + + pJS.canvas.w = pJS.canvas.el.offsetWidth * pJS.canvas.pxratio; + pJS.canvas.h = pJS.canvas.el.offsetHeight * pJS.canvas.pxratio; + + pJS.particles.size.value = pJS.tmp.obj.size_value * pJS.canvas.pxratio; + pJS.particles.size.anim.speed = pJS.tmp.obj.size_anim_speed * pJS.canvas.pxratio; + pJS.particles.move.speed = pJS.tmp.obj.move_speed * pJS.canvas.pxratio; + pJS.particles.line_linked.distance = pJS.tmp.obj.line_linked_distance * pJS.canvas.pxratio; + pJS.interactivity.modes.grab.distance = pJS.tmp.obj.mode_grab_distance * pJS.canvas.pxratio; + pJS.interactivity.modes.bubble.distance = pJS.tmp.obj.mode_bubble_distance * pJS.canvas.pxratio; + pJS.particles.line_linked.width = pJS.tmp.obj.line_linked_width * pJS.canvas.pxratio; + pJS.interactivity.modes.bubble.size = pJS.tmp.obj.mode_bubble_size * pJS.canvas.pxratio; + pJS.interactivity.modes.repulse.distance = pJS.tmp.obj.mode_repulse_distance * pJS.canvas.pxratio; + + }; + + + + /* ---------- pJS functions - canvas ------------ */ + + pJS.fn.canvasInit = function(){ + pJS.canvas.ctx = pJS.canvas.el.getContext('2d'); + }; + + pJS.fn.canvasSize = function(){ + + pJS.canvas.el.width = pJS.canvas.w; + pJS.canvas.el.height = pJS.canvas.h; + + if(pJS && pJS.interactivity.events.resize){ + + window.addEventListener('resize', function(){ + + pJS.canvas.w = pJS.canvas.el.offsetWidth; + pJS.canvas.h = pJS.canvas.el.offsetHeight; + + /* resize canvas */ + if(pJS.tmp.retina){ + pJS.canvas.w *= pJS.canvas.pxratio; + pJS.canvas.h *= pJS.canvas.pxratio; + } + + pJS.canvas.el.width = pJS.canvas.w; + pJS.canvas.el.height = pJS.canvas.h; + + /* repaint canvas on anim disabled */ + if(!pJS.particles.move.enable){ + pJS.fn.particlesEmpty(); + pJS.fn.particlesCreate(); + pJS.fn.particlesDraw(); + pJS.fn.vendors.densityAutoParticles(); + } + + /* density particles enabled */ + pJS.fn.vendors.densityAutoParticles(); + + }); + + } + + }; + + + pJS.fn.canvasPaint = function(){ + pJS.canvas.ctx.fillRect(0, 0, pJS.canvas.w, pJS.canvas.h); + }; + + pJS.fn.canvasClear = function(){ + pJS.canvas.ctx.clearRect(0, 0, pJS.canvas.w, pJS.canvas.h); + }; + + + /* --------- pJS functions - particles ----------- */ + + pJS.fn.particle = function(color, opacity, position){ + + /* size */ + this.radius = (pJS.particles.size.random ? Math.random() : 1) * pJS.particles.size.value; + if(pJS.particles.size.anim.enable){ + this.size_status = false; + this.vs = pJS.particles.size.anim.speed / 100; + if(!pJS.particles.size.anim.sync){ + this.vs = this.vs * Math.random(); + } + } + + /* position */ + this.x = position ? position.x : Math.random() * pJS.canvas.w; + this.y = position ? position.y : Math.random() * pJS.canvas.h; + + /* check position - into the canvas */ + if(this.x > pJS.canvas.w - this.radius*2) this.x = this.x - this.radius; + else if(this.x < this.radius*2) this.x = this.x + this.radius; + if(this.y > pJS.canvas.h - this.radius*2) this.y = this.y - this.radius; + else if(this.y < this.radius*2) this.y = this.y + this.radius; + + /* check position - avoid overlap */ + if(pJS.particles.move.bounce){ + pJS.fn.vendors.checkOverlap(this, position); + } + + /* color */ + this.color = {}; + if(typeof(color.value) == 'object'){ + + if(color.value instanceof Array){ + var color_selected = color.value[Math.floor(Math.random() * pJS.particles.color.value.length)]; + this.color.rgb = hexToRgb(color_selected); + }else{ + if(color.value.r != undefined && color.value.g != undefined && color.value.b != undefined){ + this.color.rgb = { + r: color.value.r, + g: color.value.g, + b: color.value.b + } + } + if(color.value.h != undefined && color.value.s != undefined && color.value.l != undefined){ + this.color.hsl = { + h: color.value.h, + s: color.value.s, + l: color.value.l + } + } + } + + } + else if(color.value == 'random'){ + this.color.rgb = { + r: (Math.floor(Math.random() * (255 - 0 + 1)) + 0), + g: (Math.floor(Math.random() * (255 - 0 + 1)) + 0), + b: (Math.floor(Math.random() * (255 - 0 + 1)) + 0) + } + } + else if(typeof(color.value) == 'string'){ + this.color = color; + this.color.rgb = hexToRgb(this.color.value); + } + + /* opacity */ + this.opacity = (pJS.particles.opacity.random ? Math.random() : 1) * pJS.particles.opacity.value; + if(pJS.particles.opacity.anim.enable){ + this.opacity_status = false; + this.vo = pJS.particles.opacity.anim.speed / 100; + if(!pJS.particles.opacity.anim.sync){ + this.vo = this.vo * Math.random(); + } + } + + /* animation - velocity for speed */ + var velbase = {} + switch(pJS.particles.move.direction){ + case 'top': + velbase = { x:0, y:-1 }; + break; + case 'top-right': + velbase = { x:0.5, y:-0.5 }; + break; + case 'right': + velbase = { x:1, y:-0 }; + break; + case 'bottom-right': + velbase = { x:0.5, y:0.5 }; + break; + case 'bottom': + velbase = { x:0, y:1 }; + break; + case 'bottom-left': + velbase = { x:-0.5, y:1 }; + break; + case 'left': + velbase = { x:-1, y:0 }; + break; + case 'top-left': + velbase = { x:-0.5, y:-0.5 }; + break; + default: + velbase = { x:0, y:0 }; + break; + } + + if(pJS.particles.move.straight){ + this.vx = velbase.x; + this.vy = velbase.y; + if(pJS.particles.move.random){ + this.vx = this.vx * (Math.random()); + this.vy = this.vy * (Math.random()); + } + }else{ + this.vx = velbase.x + Math.random()-0.5; + this.vy = velbase.y + Math.random()-0.5; + } + + // var theta = 2.0 * Math.PI * Math.random(); + // this.vx = Math.cos(theta); + // this.vy = Math.sin(theta); + + this.vx_i = this.vx; + this.vy_i = this.vy; + + + + /* if shape is image */ + + var shape_type = pJS.particles.shape.type; + if(typeof(shape_type) == 'object'){ + if(shape_type instanceof Array){ + var shape_selected = shape_type[Math.floor(Math.random() * shape_type.length)]; + this.shape = shape_selected; + } + }else{ + this.shape = shape_type; + } + + if(this.shape == 'image'){ + var sh = pJS.particles.shape; + this.img = { + src: sh.image.src, + ratio: sh.image.width / sh.image.height + } + if(!this.img.ratio) this.img.ratio = 1; + if(pJS.tmp.img_type == 'svg' && pJS.tmp.source_svg != undefined){ + pJS.fn.vendors.createSvgImg(this); + if(pJS.tmp.pushing){ + this.img.loaded = false; + } + } + } + + + + }; + + + pJS.fn.particle.prototype.draw = function() { + + var p = this; + + if(p.radius_bubble != undefined){ + var radius = p.radius_bubble; + }else{ + var radius = p.radius; + } + + if(p.opacity_bubble != undefined){ + var opacity = p.opacity_bubble; + }else{ + var opacity = p.opacity; + } + + if(p.color.rgb){ + var color_value = 'rgba('+p.color.rgb.r+','+p.color.rgb.g+','+p.color.rgb.b+','+opacity+')'; + }else{ + var color_value = 'hsla('+p.color.hsl.h+','+p.color.hsl.s+'%,'+p.color.hsl.l+'%,'+opacity+')'; + } + + pJS.canvas.ctx.fillStyle = color_value; + pJS.canvas.ctx.beginPath(); + + switch(p.shape){ + + case 'circle': + pJS.canvas.ctx.arc(p.x, p.y, radius, 0, Math.PI * 2, false); + break; + + case 'edge': + pJS.canvas.ctx.rect(p.x-radius, p.y-radius, radius*2, radius*2); + break; + + case 'triangle': + pJS.fn.vendors.drawShape(pJS.canvas.ctx, p.x-radius, p.y+radius / 1.66, radius*2, 3, 2); + break; + + case 'polygon': + pJS.fn.vendors.drawShape( + pJS.canvas.ctx, + p.x - radius / (pJS.particles.shape.polygon.nb_sides/3.5), // startX + p.y - radius / (2.66/3.5), // startY + radius*2.66 / (pJS.particles.shape.polygon.nb_sides/3), // sideLength + pJS.particles.shape.polygon.nb_sides, // sideCountNumerator + 1 // sideCountDenominator + ); + break; + + case 'star': + pJS.fn.vendors.drawShape( + pJS.canvas.ctx, + p.x - radius*2 / (pJS.particles.shape.polygon.nb_sides/4), // startX + p.y - radius / (2*2.66/3.5), // startY + radius*2*2.66 / (pJS.particles.shape.polygon.nb_sides/3), // sideLength + pJS.particles.shape.polygon.nb_sides, // sideCountNumerator + 2 // sideCountDenominator + ); + break; + + case 'image': + + function draw(){ + pJS.canvas.ctx.drawImage( + img_obj, + p.x-radius, + p.y-radius, + radius*2, + radius*2 / p.img.ratio + ); + } + + if(pJS.tmp.img_type == 'svg'){ + var img_obj = p.img.obj; + }else{ + var img_obj = pJS.tmp.img_obj; + } + + if(img_obj){ + draw(); + } + + break; + + } + + pJS.canvas.ctx.closePath(); + + if(pJS.particles.shape.stroke.width > 0){ + pJS.canvas.ctx.strokeStyle = pJS.particles.shape.stroke.color; + pJS.canvas.ctx.lineWidth = pJS.particles.shape.stroke.width; + pJS.canvas.ctx.stroke(); + } + + pJS.canvas.ctx.fill(); + + }; + + + pJS.fn.particlesCreate = function(){ + for(var i = 0; i < pJS.particles.number.value; i++) { + pJS.particles.array.push(new pJS.fn.particle(pJS.particles.color, pJS.particles.opacity.value)); + } + }; + + pJS.fn.particlesUpdate = function(){ + + for(var i = 0; i < pJS.particles.array.length; i++){ + + /* the particle */ + var p = pJS.particles.array[i]; + + // var d = ( dx = pJS.interactivity.mouse.click_pos_x - p.x ) * dx + ( dy = pJS.interactivity.mouse.click_pos_y - p.y ) * dy; + // var f = -BANG_SIZE / d; + // if ( d < BANG_SIZE ) { + // var t = Math.atan2( dy, dx ); + // p.vx = f * Math.cos(t); + // p.vy = f * Math.sin(t); + // } + + /* move the particle */ + if(pJS.particles.move.enable){ + var ms = pJS.particles.move.speed/2; + p.x += p.vx * ms; + p.y += p.vy * ms; + } + + /* change opacity status */ + if(pJS.particles.opacity.anim.enable) { + if(p.opacity_status == true) { + if(p.opacity >= pJS.particles.opacity.value) p.opacity_status = false; + p.opacity += p.vo; + }else { + if(p.opacity <= pJS.particles.opacity.anim.opacity_min) p.opacity_status = true; + p.opacity -= p.vo; + } + if(p.opacity < 0) p.opacity = 0; + } + + /* change size */ + if(pJS.particles.size.anim.enable){ + if(p.size_status == true){ + if(p.radius >= pJS.particles.size.value) p.size_status = false; + p.radius += p.vs; + }else{ + if(p.radius <= pJS.particles.size.anim.size_min) p.size_status = true; + p.radius -= p.vs; + } + if(p.radius < 0) p.radius = 0; + } + + /* change particle position if it is out of canvas */ + if(pJS.particles.move.out_mode == 'bounce'){ + var new_pos = { + x_left: p.radius, + x_right: pJS.canvas.w, + y_top: p.radius, + y_bottom: pJS.canvas.h + } + }else{ + var new_pos = { + x_left: -p.radius, + x_right: pJS.canvas.w + p.radius, + y_top: -p.radius, + y_bottom: pJS.canvas.h + p.radius + } + } + + if(p.x - p.radius > pJS.canvas.w){ + p.x = new_pos.x_left; + p.y = Math.random() * pJS.canvas.h; + } + else if(p.x + p.radius < 0){ + p.x = new_pos.x_right; + p.y = Math.random() * pJS.canvas.h; + } + if(p.y - p.radius > pJS.canvas.h){ + p.y = new_pos.y_top; + p.x = Math.random() * pJS.canvas.w; + } + else if(p.y + p.radius < 0){ + p.y = new_pos.y_bottom; + p.x = Math.random() * pJS.canvas.w; + } + + /* out of canvas modes */ + switch(pJS.particles.move.out_mode){ + case 'bounce': + if (p.x + p.radius > pJS.canvas.w) p.vx = -p.vx; + else if (p.x - p.radius < 0) p.vx = -p.vx; + if (p.y + p.radius > pJS.canvas.h) p.vy = -p.vy; + else if (p.y - p.radius < 0) p.vy = -p.vy; + break; + } + + /* events */ + if(isInArray('grab', pJS.interactivity.events.onhover.mode)){ + pJS.fn.modes.grabParticle(p); + } + + if(isInArray('bubble', pJS.interactivity.events.onhover.mode) || isInArray('bubble', pJS.interactivity.events.onclick.mode)){ + pJS.fn.modes.bubbleParticle(p); + } + + if(isInArray('repulse', pJS.interactivity.events.onhover.mode) || isInArray('repulse', pJS.interactivity.events.onclick.mode)){ + pJS.fn.modes.repulseParticle(p); + } + + /* interaction auto between particles */ + if(pJS.particles.line_linked.enable || pJS.particles.move.attract.enable){ + for(var j = i + 1; j < pJS.particles.array.length; j++){ + var p2 = pJS.particles.array[j]; + + /* link particles */ + if(pJS.particles.line_linked.enable){ + pJS.fn.interact.linkParticles(p,p2); + } + + /* attract particles */ + if(pJS.particles.move.attract.enable){ + pJS.fn.interact.attractParticles(p,p2); + } + + /* bounce particles */ + if(pJS.particles.move.bounce){ + pJS.fn.interact.bounceParticles(p,p2); + } + + } + } + + + } + + }; + + pJS.fn.particlesDraw = function(){ + + /* clear canvas */ + pJS.canvas.ctx.clearRect(0, 0, pJS.canvas.w, pJS.canvas.h); + + /* update each particles param */ + pJS.fn.particlesUpdate(); + + /* draw each particle */ + for(var i = 0; i < pJS.particles.array.length; i++){ + var p = pJS.particles.array[i]; + p.draw(); + } + + }; + + pJS.fn.particlesEmpty = function(){ + pJS.particles.array = []; + }; + + pJS.fn.particlesRefresh = function(){ + + /* init all */ + cancelRequestAnimFrame(pJS.fn.checkAnimFrame); + cancelRequestAnimFrame(pJS.fn.drawAnimFrame); + pJS.tmp.source_svg = undefined; + pJS.tmp.img_obj = undefined; + pJS.tmp.count_svg = 0; + pJS.fn.particlesEmpty(); + pJS.fn.canvasClear(); + + /* restart */ + pJS.fn.vendors.start(); + + }; + + + /* ---------- pJS functions - particles interaction ------------ */ + + pJS.fn.interact.linkParticles = function(p1, p2){ + + var dx = p1.x - p2.x, + dy = p1.y - p2.y, + dist = Math.sqrt(dx*dx + dy*dy); + + /* draw a line between p1 and p2 if the distance between them is under the config distance */ + if(dist <= pJS.particles.line_linked.distance){ + + var opacity_line = pJS.particles.line_linked.opacity - (dist / (1/pJS.particles.line_linked.opacity)) / pJS.particles.line_linked.distance; + + if(opacity_line > 0){ + + /* style */ + var color_line = pJS.particles.line_linked.color_rgb_line; + pJS.canvas.ctx.strokeStyle = 'rgba('+color_line.r+','+color_line.g+','+color_line.b+','+opacity_line+')'; + pJS.canvas.ctx.lineWidth = pJS.particles.line_linked.width; + //pJS.canvas.ctx.lineCap = 'round'; /* performance issue */ + + /* path */ + pJS.canvas.ctx.beginPath(); + pJS.canvas.ctx.moveTo(p1.x, p1.y); + pJS.canvas.ctx.lineTo(p2.x, p2.y); + pJS.canvas.ctx.stroke(); + pJS.canvas.ctx.closePath(); + + } + + } + + }; + + + pJS.fn.interact.attractParticles = function(p1, p2){ + + /* condensed particles */ + var dx = p1.x - p2.x, + dy = p1.y - p2.y, + dist = Math.sqrt(dx*dx + dy*dy); + + if(dist <= pJS.particles.line_linked.distance){ + + var ax = dx/(pJS.particles.move.attract.rotateX*1000), + ay = dy/(pJS.particles.move.attract.rotateY*1000); + + p1.vx -= ax; + p1.vy -= ay; + + p2.vx += ax; + p2.vy += ay; + + } + + + } + + + pJS.fn.interact.bounceParticles = function(p1, p2){ + + var dx = p1.x - p2.x, + dy = p1.y - p2.y, + dist = Math.sqrt(dx*dx + dy*dy), + dist_p = p1.radius+p2.radius; + + if(dist <= dist_p){ + p1.vx = -p1.vx; + p1.vy = -p1.vy; + + p2.vx = -p2.vx; + p2.vy = -p2.vy; + } + + } + + + /* ---------- pJS functions - modes events ------------ */ + + pJS.fn.modes.pushParticles = function(nb, pos){ + + pJS.tmp.pushing = true; + + for(var i = 0; i < nb; i++){ + pJS.particles.array.push( + new pJS.fn.particle( + pJS.particles.color, + pJS.particles.opacity.value, + { + 'x': pos ? pos.pos_x : Math.random() * pJS.canvas.w, + 'y': pos ? pos.pos_y : Math.random() * pJS.canvas.h + } + ) + ) + if(i == nb-1){ + if(!pJS.particles.move.enable){ + pJS.fn.particlesDraw(); + } + pJS.tmp.pushing = false; + } + } + + }; + + + pJS.fn.modes.removeParticles = function(nb){ + + pJS.particles.array.splice(0, nb); + if(!pJS.particles.move.enable){ + pJS.fn.particlesDraw(); + } + + }; + + + pJS.fn.modes.bubbleParticle = function(p){ + + /* on hover event */ + if(pJS.interactivity.events.onhover.enable && isInArray('bubble', pJS.interactivity.events.onhover.mode)){ + + var dx_mouse = p.x - pJS.interactivity.mouse.pos_x, + dy_mouse = p.y - pJS.interactivity.mouse.pos_y, + dist_mouse = Math.sqrt(dx_mouse*dx_mouse + dy_mouse*dy_mouse), + ratio = 1 - dist_mouse / pJS.interactivity.modes.bubble.distance; + + function init(){ + p.opacity_bubble = p.opacity; + p.radius_bubble = p.radius; + } + + /* mousemove - check ratio */ + if(dist_mouse <= pJS.interactivity.modes.bubble.distance){ + + if(ratio >= 0 && pJS.interactivity.status == 'mousemove'){ + + /* size */ + if(pJS.interactivity.modes.bubble.size != pJS.particles.size.value){ + + if(pJS.interactivity.modes.bubble.size > pJS.particles.size.value){ + var size = p.radius + (pJS.interactivity.modes.bubble.size*ratio); + if(size >= 0){ + p.radius_bubble = size; + } + }else{ + var dif = p.radius - pJS.interactivity.modes.bubble.size, + size = p.radius - (dif*ratio); + if(size > 0){ + p.radius_bubble = size; + }else{ + p.radius_bubble = 0; + } + } + + } + + /* opacity */ + if(pJS.interactivity.modes.bubble.opacity != pJS.particles.opacity.value){ + + if(pJS.interactivity.modes.bubble.opacity > pJS.particles.opacity.value){ + var opacity = pJS.interactivity.modes.bubble.opacity*ratio; + if(opacity > p.opacity && opacity <= pJS.interactivity.modes.bubble.opacity){ + p.opacity_bubble = opacity; + } + }else{ + var opacity = p.opacity - (pJS.particles.opacity.value-pJS.interactivity.modes.bubble.opacity)*ratio; + if(opacity < p.opacity && opacity >= pJS.interactivity.modes.bubble.opacity){ + p.opacity_bubble = opacity; + } + } + + } + + } + + }else{ + init(); + } + + + /* mouseleave */ + if(pJS.interactivity.status == 'mouseleave'){ + init(); + } + + } + + /* on click event */ + else if(pJS.interactivity.events.onclick.enable && isInArray('bubble', pJS.interactivity.events.onclick.mode)){ + + + if(pJS.tmp.bubble_clicking){ + var dx_mouse = p.x - pJS.interactivity.mouse.click_pos_x, + dy_mouse = p.y - pJS.interactivity.mouse.click_pos_y, + dist_mouse = Math.sqrt(dx_mouse*dx_mouse + dy_mouse*dy_mouse), + time_spent = (new Date().getTime() - pJS.interactivity.mouse.click_time)/1000; + + if(time_spent > pJS.interactivity.modes.bubble.duration){ + pJS.tmp.bubble_duration_end = true; + } + + if(time_spent > pJS.interactivity.modes.bubble.duration*2){ + pJS.tmp.bubble_clicking = false; + pJS.tmp.bubble_duration_end = false; + } + } + + + function process(bubble_param, particles_param, p_obj_bubble, p_obj, id){ + + if(bubble_param != particles_param){ + + if(!pJS.tmp.bubble_duration_end){ + if(dist_mouse <= pJS.interactivity.modes.bubble.distance){ + if(p_obj_bubble != undefined) var obj = p_obj_bubble; + else var obj = p_obj; + if(obj != bubble_param){ + var value = p_obj - (time_spent * (p_obj - bubble_param) / pJS.interactivity.modes.bubble.duration); + if(id == 'size') p.radius_bubble = value; + if(id == 'opacity') p.opacity_bubble = value; + } + }else{ + if(id == 'size') p.radius_bubble = undefined; + if(id == 'opacity') p.opacity_bubble = undefined; + } + }else{ + if(p_obj_bubble != undefined){ + var value_tmp = p_obj - (time_spent * (p_obj - bubble_param) / pJS.interactivity.modes.bubble.duration), + dif = bubble_param - value_tmp; + value = bubble_param + dif; + if(id == 'size') p.radius_bubble = value; + if(id == 'opacity') p.opacity_bubble = value; + } + } + + } + + } + + if(pJS.tmp.bubble_clicking){ + /* size */ + process(pJS.interactivity.modes.bubble.size, pJS.particles.size.value, p.radius_bubble, p.radius, 'size'); + /* opacity */ + process(pJS.interactivity.modes.bubble.opacity, pJS.particles.opacity.value, p.opacity_bubble, p.opacity, 'opacity'); + } + + } + + }; + + + pJS.fn.modes.repulseParticle = function(p){ + + if(pJS.interactivity.events.onhover.enable && isInArray('repulse', pJS.interactivity.events.onhover.mode) && pJS.interactivity.status == 'mousemove') { + + var dx_mouse = p.x - pJS.interactivity.mouse.pos_x, + dy_mouse = p.y - pJS.interactivity.mouse.pos_y, + dist_mouse = Math.sqrt(dx_mouse*dx_mouse + dy_mouse*dy_mouse); + + var normVec = {x: dx_mouse/dist_mouse, y: dy_mouse/dist_mouse}, + repulseRadius = pJS.interactivity.modes.repulse.distance, + velocity = 100, + repulseFactor = clamp((1/repulseRadius)*(-1*Math.pow(dist_mouse/repulseRadius,2)+1)*repulseRadius*velocity, 0, 50); + + var pos = { + x: p.x + normVec.x * repulseFactor, + y: p.y + normVec.y * repulseFactor + } + + if(pJS.particles.move.out_mode == 'bounce'){ + if(pos.x - p.radius > 0 && pos.x + p.radius < pJS.canvas.w) p.x = pos.x; + if(pos.y - p.radius > 0 && pos.y + p.radius < pJS.canvas.h) p.y = pos.y; + }else{ + p.x = pos.x; + p.y = pos.y; + } + + } + + + else if(pJS.interactivity.events.onclick.enable && isInArray('repulse', pJS.interactivity.events.onclick.mode)) { + + if(!pJS.tmp.repulse_finish){ + pJS.tmp.repulse_count++; + if(pJS.tmp.repulse_count == pJS.particles.array.length){ + pJS.tmp.repulse_finish = true; + } + } + + if(pJS.tmp.repulse_clicking){ + + var repulseRadius = Math.pow(pJS.interactivity.modes.repulse.distance/6, 3); + + var dx = pJS.interactivity.mouse.click_pos_x - p.x, + dy = pJS.interactivity.mouse.click_pos_y - p.y, + d = dx*dx + dy*dy; + + var force = -repulseRadius / d * 1; + + function process(){ + + var f = Math.atan2(dy,dx); + p.vx = force * Math.cos(f); + p.vy = force * Math.sin(f); + + if(pJS.particles.move.out_mode == 'bounce'){ + var pos = { + x: p.x + p.vx, + y: p.y + p.vy + } + if (pos.x + p.radius > pJS.canvas.w) p.vx = -p.vx; + else if (pos.x - p.radius < 0) p.vx = -p.vx; + if (pos.y + p.radius > pJS.canvas.h) p.vy = -p.vy; + else if (pos.y - p.radius < 0) p.vy = -p.vy; + } + + } + + // default + if(d <= repulseRadius){ + process(); + } + + // bang - slow motion mode + // if(!pJS.tmp.repulse_finish){ + // if(d <= repulseRadius){ + // process(); + // } + // }else{ + // process(); + // } + + + }else{ + + if(pJS.tmp.repulse_clicking == false){ + + p.vx = p.vx_i; + p.vy = p.vy_i; + + } + + } + + } + + } + + + pJS.fn.modes.grabParticle = function(p){ + + if(pJS.interactivity.events.onhover.enable && pJS.interactivity.status == 'mousemove'){ + + var dx_mouse = p.x - pJS.interactivity.mouse.pos_x, + dy_mouse = p.y - pJS.interactivity.mouse.pos_y, + dist_mouse = Math.sqrt(dx_mouse*dx_mouse + dy_mouse*dy_mouse); + + /* draw a line between the cursor and the particle if the distance between them is under the config distance */ + if(dist_mouse <= pJS.interactivity.modes.grab.distance){ + + var opacity_line = pJS.interactivity.modes.grab.line_linked.opacity - (dist_mouse / (1/pJS.interactivity.modes.grab.line_linked.opacity)) / pJS.interactivity.modes.grab.distance; + + if(opacity_line > 0){ + + /* style */ + var color_line = pJS.particles.line_linked.color_rgb_line; + pJS.canvas.ctx.strokeStyle = 'rgba('+color_line.r+','+color_line.g+','+color_line.b+','+opacity_line+')'; + pJS.canvas.ctx.lineWidth = pJS.particles.line_linked.width; + //pJS.canvas.ctx.lineCap = 'round'; /* performance issue */ + + /* path */ + pJS.canvas.ctx.beginPath(); + pJS.canvas.ctx.moveTo(p.x, p.y); + pJS.canvas.ctx.lineTo(pJS.interactivity.mouse.pos_x, pJS.interactivity.mouse.pos_y); + pJS.canvas.ctx.stroke(); + pJS.canvas.ctx.closePath(); + + } + + } + + } + + }; + + + + /* ---------- pJS functions - vendors ------------ */ + + pJS.fn.vendors.eventsListeners = function(){ + + /* events target element */ + if(pJS.interactivity.detect_on == 'window'){ + pJS.interactivity.el = window; + }else{ + pJS.interactivity.el = pJS.canvas.el; + } + + + /* detect mouse pos - on hover / click event */ + if(pJS.interactivity.events.onhover.enable || pJS.interactivity.events.onclick.enable){ + + /* el on mousemove */ + pJS.interactivity.el.addEventListener('mousemove', function(e){ + + if(pJS.interactivity.el == window){ + var pos_x = e.clientX, + pos_y = e.clientY; + } + else{ + var pos_x = e.offsetX || e.clientX, + pos_y = e.offsetY || e.clientY; + } + + pJS.interactivity.mouse.pos_x = pos_x; + pJS.interactivity.mouse.pos_y = pos_y; + + if(pJS.tmp.retina){ + pJS.interactivity.mouse.pos_x *= pJS.canvas.pxratio; + pJS.interactivity.mouse.pos_y *= pJS.canvas.pxratio; + } + + pJS.interactivity.status = 'mousemove'; + + }); + + /* el on onmouseleave */ + pJS.interactivity.el.addEventListener('mouseleave', function(e){ + + pJS.interactivity.mouse.pos_x = null; + pJS.interactivity.mouse.pos_y = null; + pJS.interactivity.status = 'mouseleave'; + + }); + + } + + /* on click event */ + if(pJS.interactivity.events.onclick.enable){ + + pJS.interactivity.el.addEventListener('click', function(){ + + pJS.interactivity.mouse.click_pos_x = pJS.interactivity.mouse.pos_x; + pJS.interactivity.mouse.click_pos_y = pJS.interactivity.mouse.pos_y; + pJS.interactivity.mouse.click_time = new Date().getTime(); + + if(pJS.interactivity.events.onclick.enable){ + + switch(pJS.interactivity.events.onclick.mode){ + + case 'push': + if(pJS.particles.move.enable){ + pJS.fn.modes.pushParticles(pJS.interactivity.modes.push.particles_nb, pJS.interactivity.mouse); + }else{ + if(pJS.interactivity.modes.push.particles_nb == 1){ + pJS.fn.modes.pushParticles(pJS.interactivity.modes.push.particles_nb, pJS.interactivity.mouse); + } + else if(pJS.interactivity.modes.push.particles_nb > 1){ + pJS.fn.modes.pushParticles(pJS.interactivity.modes.push.particles_nb); + } + } + break; + + case 'remove': + pJS.fn.modes.removeParticles(pJS.interactivity.modes.remove.particles_nb); + break; + + case 'bubble': + pJS.tmp.bubble_clicking = true; + break; + + case 'repulse': + pJS.tmp.repulse_clicking = true; + pJS.tmp.repulse_count = 0; + pJS.tmp.repulse_finish = false; + setTimeout(function(){ + pJS.tmp.repulse_clicking = false; + }, pJS.interactivity.modes.repulse.duration*1000) + break; + + } + + } + + }); + + } + + + }; + + pJS.fn.vendors.densityAutoParticles = function(){ + + if(pJS.particles.number.density.enable){ + + /* calc area */ + var area = pJS.canvas.el.width * pJS.canvas.el.height / 1000; + if(pJS.tmp.retina){ + area = area/(pJS.canvas.pxratio*2); + } + + /* calc number of particles based on density area */ + var nb_particles = area * pJS.particles.number.value / pJS.particles.number.density.value_area; + + /* add or remove X particles */ + var missing_particles = pJS.particles.array.length - nb_particles; + if(missing_particles < 0) pJS.fn.modes.pushParticles(Math.abs(missing_particles)); + else pJS.fn.modes.removeParticles(missing_particles); + + } + + }; + + + pJS.fn.vendors.checkOverlap = function(p1, position){ + for(var i = 0; i < pJS.particles.array.length; i++){ + var p2 = pJS.particles.array[i]; + + var dx = p1.x - p2.x, + dy = p1.y - p2.y, + dist = Math.sqrt(dx*dx + dy*dy); + + if(dist <= p1.radius + p2.radius){ + p1.x = position ? position.x : Math.random() * pJS.canvas.w; + p1.y = position ? position.y : Math.random() * pJS.canvas.h; + pJS.fn.vendors.checkOverlap(p1); + } + } + }; + + + pJS.fn.vendors.createSvgImg = function(p){ + + /* set color to svg element */ + var svgXml = pJS.tmp.source_svg, + rgbHex = /#([0-9A-F]{3,6})/gi, + coloredSvgXml = svgXml.replace(rgbHex, function (m, r, g, b) { + if(p.color.rgb){ + var color_value = 'rgba('+p.color.rgb.r+','+p.color.rgb.g+','+p.color.rgb.b+','+p.opacity+')'; + }else{ + var color_value = 'hsla('+p.color.hsl.h+','+p.color.hsl.s+'%,'+p.color.hsl.l+'%,'+p.opacity+')'; + } + return color_value; + }); + + /* prepare to create img with colored svg */ + var svg = new Blob([coloredSvgXml], {type: 'image/svg+xml;charset=utf-8'}), + DOMURL = window.URL || window.webkitURL || window, + url = DOMURL.createObjectURL(svg); + + /* create particle img obj */ + var img = new Image(); + img.addEventListener('load', function(){ + p.img.obj = img; + p.img.loaded = true; + DOMURL.revokeObjectURL(url); + pJS.tmp.count_svg++; + }); + img.src = url; + + }; + + + pJS.fn.vendors.destroypJS = function(){ + cancelAnimationFrame(pJS.fn.drawAnimFrame); + canvas_el.remove(); + pJSDom = null; + }; + + + pJS.fn.vendors.drawShape = function(c, startX, startY, sideLength, sideCountNumerator, sideCountDenominator){ + + // By Programming Thomas - https://programmingthomas.wordpress.com/2013/04/03/n-sided-shapes/ + var sideCount = sideCountNumerator * sideCountDenominator; + var decimalSides = sideCountNumerator / sideCountDenominator; + var interiorAngleDegrees = (180 * (decimalSides - 2)) / decimalSides; + var interiorAngle = Math.PI - Math.PI * interiorAngleDegrees / 180; // convert to radians + c.save(); + c.beginPath(); + c.translate(startX, startY); + c.moveTo(0,0); + for (var i = 0; i < sideCount; i++) { + c.lineTo(sideLength,0); + c.translate(sideLength,0); + c.rotate(interiorAngle); + } + //c.stroke(); + c.fill(); + c.restore(); + + }; + + pJS.fn.vendors.exportImg = function(){ + window.open(pJS.canvas.el.toDataURL('image/png'), '_blank'); + }; + + + pJS.fn.vendors.loadImg = function(type){ + + pJS.tmp.img_error = undefined; + + if(pJS.particles.shape.image.src != ''){ + + if(type == 'svg'){ + + var xhr = new XMLHttpRequest(); + xhr.open('GET', pJS.particles.shape.image.src); + xhr.onreadystatechange = function (data) { + if(xhr.readyState == 4){ + if(xhr.status == 200){ + pJS.tmp.source_svg = data.currentTarget.response; + pJS.fn.vendors.checkBeforeDraw(); + }else{ + console.log('Error pJS - Image not found'); + pJS.tmp.img_error = true; + } + } + } + xhr.send(); + + }else{ + + var img = new Image(); + img.addEventListener('load', function(){ + pJS.tmp.img_obj = img; + pJS.fn.vendors.checkBeforeDraw(); + }); + img.src = pJS.particles.shape.image.src; + + } + + }else{ + console.log('Error pJS - No image.src'); + pJS.tmp.img_error = true; + } + + }; + + + pJS.fn.vendors.draw = function(){ + + if(pJS.particles.shape.type == 'image'){ + + if(pJS.tmp.img_type == 'svg'){ + + if(pJS.tmp.count_svg >= pJS.particles.number.value){ + pJS.fn.particlesDraw(); + if(!pJS.particles.move.enable) cancelRequestAnimFrame(pJS.fn.drawAnimFrame); + else pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw); + }else{ + //console.log('still loading...'); + if(!pJS.tmp.img_error) pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw); + } + + }else{ + + if(pJS.tmp.img_obj != undefined){ + pJS.fn.particlesDraw(); + if(!pJS.particles.move.enable) cancelRequestAnimFrame(pJS.fn.drawAnimFrame); + else pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw); + }else{ + if(!pJS.tmp.img_error) pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw); + } + + } + + }else{ + pJS.fn.particlesDraw(); + if(!pJS.particles.move.enable) cancelRequestAnimFrame(pJS.fn.drawAnimFrame); + else pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw); + } + + }; + + + pJS.fn.vendors.checkBeforeDraw = function(){ + + // if shape is image + if(pJS.particles.shape.type == 'image'){ + + if(pJS.tmp.img_type == 'svg' && pJS.tmp.source_svg == undefined){ + pJS.tmp.checkAnimFrame = requestAnimFrame(check); + }else{ + //console.log('images loaded! cancel check'); + cancelRequestAnimFrame(pJS.tmp.checkAnimFrame); + if(!pJS.tmp.img_error){ + pJS.fn.vendors.init(); + pJS.fn.vendors.draw(); + } + + } + + }else{ + pJS.fn.vendors.init(); + pJS.fn.vendors.draw(); + } + + }; + + + pJS.fn.vendors.init = function(){ + + /* init canvas + particles */ + pJS.fn.retinaInit(); + pJS.fn.canvasInit(); + pJS.fn.canvasSize(); + pJS.fn.canvasPaint(); + pJS.fn.particlesCreate(); + pJS.fn.vendors.densityAutoParticles(); + + /* particles.line_linked - convert hex colors to rgb */ + pJS.particles.line_linked.color_rgb_line = hexToRgb(pJS.particles.line_linked.color); + + }; + + + pJS.fn.vendors.start = function(){ + + if(isInArray('image', pJS.particles.shape.type)){ + pJS.tmp.img_type = pJS.particles.shape.image.src.substr(pJS.particles.shape.image.src.length - 3); + pJS.fn.vendors.loadImg(pJS.tmp.img_type); + }else{ + pJS.fn.vendors.checkBeforeDraw(); + } + + }; + + + + + /* ---------- pJS - start ------------ */ + + + pJS.fn.vendors.eventsListeners(); + + pJS.fn.vendors.start(); + + + +}; + +/* ---------- global functions - vendors ------------ */ + +Object.deepExtend = function ED(destination, source) { + for (var property in source) { + if (source[property] && source[property].constructor && + source[property].constructor === Object) { + destination[property] = destination[property] || {}; + ED(destination[property], source[property]); + } else { + destination[property] = source[property]; + } + } + return destination; +}; + +window.requestAnimFrame = (function(){ + return window.requestAnimationFrame || + window.webkitRequestAnimationFrame || + window.mozRequestAnimationFrame || + window.oRequestAnimationFrame || + window.msRequestAnimationFrame || + function(callback){ + window.setTimeout(callback, 1000 / 60); + }; +})(); + +window.cancelRequestAnimFrame = ( function() { + return window.cancelAnimationFrame || + window.webkitCancelRequestAnimationFrame || + window.mozCancelRequestAnimationFrame || + window.oCancelRequestAnimationFrame || + window.msCancelRequestAnimationFrame || + clearTimeout +} )(); + +function hexToRgb(hex){ + // By Tim Down - http://stackoverflow.com/a/5624139/3493650 + // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF") + var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i; + hex = hex.replace(shorthandRegex, function(m, r, g, b) { + return r + r + g + g + b + b; + }); + var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); + return result ? { + r: parseInt(result[1], 16), + g: parseInt(result[2], 16), + b: parseInt(result[3], 16) + } : null; +}; + +function clamp(number, min, max) { + return Math.min(Math.max(number, min), max); +}; + +function isInArray(value, array) { + return array.indexOf(value) > -1; +} + + +/* ---------- particles.js functions - start ------------ */ + +window.pJSDom = []; + +window.particlesJS = function(tag_id, params){ + + //console.log(params); + + /* no string id? so it's object params, and set the id with default id */ + if(typeof(tag_id) != 'string'){ + params = tag_id; + tag_id = 'particles-js'; + } + + /* no id? set the id to default id */ + if(!tag_id){ + tag_id = 'particles-js'; + } + + /* pJS elements */ + var pJS_tag = document.getElementById(tag_id), + pJS_canvas_class = 'particles-js-canvas-el', + exist_canvas = pJS_tag.getElementsByClassName(pJS_canvas_class); + + /* remove canvas if exists into the pJS target tag */ + if(exist_canvas.length){ + while(exist_canvas.length > 0){ + pJS_tag.removeChild(exist_canvas[0]); + } + } + + /* create canvas element */ + var canvas_el = document.createElement('canvas'); + canvas_el.className = pJS_canvas_class; + + /* set size canvas */ + canvas_el.style.width = "100%"; + canvas_el.style.height = "100%"; + + /* append canvas */ + var canvas = document.getElementById(tag_id).appendChild(canvas_el); + + /* launch particle.js */ + if(canvas != null){ + pJSDom.push(new pJS(tag_id, params)); + } + +}; + +window.particlesJS.load = function(tag_id, path_config_json, callback){ + /* load json config */ + var xhr = new XMLHttpRequest(); + xhr.open('GET', path_config_json); + xhr.onreadystatechange = function (data) { + if(xhr.readyState == 4){ + if(xhr.status == 200){ + var params = JSON.parse(data.currentTarget.response); + window.particlesJS(tag_id, params); + if(callback) callback(); + }else{ + console.log('Error pJS - XMLHttpRequest status: '+xhr.status); + console.log('Error pJS - File config not found'); + } + } + }; + xhr.send(); + +}; +} +export { + loginBg +} diff --git a/static/loginPage.js/loginApp.js b/static/loginPage.js/loginApp.js new file mode 100644 index 0000000..c5dd94b --- /dev/null +++ b/static/loginPage.js/loginApp.js @@ -0,0 +1,137 @@ +/* ----------------------------------------------- +/* How to use? : Check the GitHub README +/* ----------------------------------------------- */ + +/* To load a config file (particles.json) you need to host this demo (MAMP/WAMP/local)... */ +/* +particlesJS.load('particles-js', 'particles.json', function() { + console.log('particles.js loaded - callback'); +}); +*/ + +/* Otherwise just put the config content (json): */ +function loginApp(){ +particlesJS('particles-js', + + { + "particles": { + "number": { + "value": 80, + "density": { + "enable": true, + "value_area": 800 + } + }, + "color": { + "value": "#ffffff" + }, + "shape": { + "type": "circle", + "stroke": { + "width": 0, + "color": "#000000" + }, + "polygon": { + "nb_sides": 5 + }, + "image": { + "src": "img/github.svg", + "width": 100, + "height": 100 + } + }, + "opacity": { + "value": 0.5, + "random": false, + "anim": { + "enable": false, + "speed": 1, + "opacity_min": 0.1, + "sync": false + } + }, + "size": { + "value": 5, + "random": true, + "anim": { + "enable": false, + "speed": 40, + "size_min": 0.1, + "sync": false + } + }, + "line_linked": { + "enable": true, + "distance": 150, + "color": "#ffffff", + "opacity": 0.4, + "width": 1 + }, + "move": { + "enable": true, + "speed": 6, + "direction": "none", + "random": false, + "straight": false, + "out_mode": "out", + "attract": { + "enable": false, + "rotateX": 600, + "rotateY": 1200 + } + } + }, + "interactivity": { + "detect_on": "canvas", + "events": { + "onhover": { + "enable": true, + "mode": "repulse" + }, + "onclick": { + "enable": true, + "mode": "push" + }, + "resize": true + }, + "modes": { + "grab": { + "distance": 400, + "line_linked": { + "opacity": 1 + } + }, + "bubble": { + "distance": 400, + "size": 40, + "duration": 2, + "opacity": 8, + "speed": 3 + }, + "repulse": { + "distance": 200 + }, + "push": { + "particles_nb": 4 + }, + "remove": { + "particles_nb": 2 + } + } + }, + "retina_detect": true, + "config_demo": { + "hide_card": false, + "background_color": "#b61924", + "background_image": "", + "background_position": "50% 50%", + "background_repeat": "no-repeat", + "background_size": "cover" + } + } + +); +} +export { + loginApp +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..95c5939 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,71 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig.json to read more about this file */ + + /* Basic Options */ + // "incremental": true, /* Enable incremental compilation */ + "target": "esnext" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */, + "module": "esnext" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */, + "lib": ["esnext", "dom", "dom.iterable", "scripthost"] /* Specify library files to be included in the compilation. */, + // "allowJs": true, /* Allow javascript files to be compiled. */ + // "checkJs": true, /* Report errors in .js files. */ + "jsx": "preserve" /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */, + // "declaration": true /* Generates corresponding '.d.ts' file. */, + // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ + // "sourceMap": true, /* Generates corresponding '.map' file. */ + // "outFile": "./", /* Concatenate and emit output to single file. */ + // "outDir": "./", /* Redirect output structure to the directory. */ + // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + // "composite": true, /* Enable project compilation */ + // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ + // "removeComments": true, /* Do not emit comments to output. */ + // "noEmit": true, /* Do not emit outputs. */ + // "importHelpers": true /* Import emit helpers from 'tslib'. */, + // "downlevelIteration": true /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */, + // "isolatedModules": true /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */, + + /* Strict Type-Checking Options */ + "strict": true /* Enable all strict type-checking options. */, + // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* Enable strict null checks. */ + // "strictFunctionTypes": true, /* Enable strict checking of function types. */ + // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ + // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ + // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ + // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ + + /* Additional Checks */ + // "noUnusedLocals": true, /* Report errors on unused locals. */ + // "noUnusedParameters": true, /* Report errors on unused parameters. */ + // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ + // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ + + /* Module Resolution Options */ + "moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */, + "baseUrl": "." /* Base directory to resolve non-absolute module names. */, + "paths": { + "/@/*": ["src/*"] + } /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */, + // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ + // "typeRoots": [], /* List of folders to include type definitions from. */ + "types": ["vite/client"] /* Type declaration files to be included in compilation. */, + "allowSyntheticDefaultImports": true /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */, + "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */, + // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + + /* Source Map Options */ + // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ + // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ + + /* Experimental Options */ + "experimentalDecorators": true /* Enables experimental support for ES7 decorators. */, + // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ + /* Advanced Options */ + "skipLibCheck": true /* Skip type checking of declaration files. */, + "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ + } +} diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..b761ba2 --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,81 @@ +import vue from '@vitejs/plugin-vue'; +import { resolve } from 'path'; +import { defineConfig, loadEnv, ConfigEnv } from 'vite'; + +const pathResolve = (dir: string): any => { + return resolve(__dirname, '.', dir); +}; + +const alias: Record<string, string> = { + '/@': pathResolve('./src/'), + 'vue-i18n': 'vue-i18n/dist/vue-i18n.cjs.js' +}; + +const viteConfig = defineConfig((mode: ConfigEnv) => { + const env = loadEnv(mode.mode, process.cwd()); + return { + publicPath: './', + plugins: [vue()], + root: process.cwd(), + resolve: { alias }, + assetsInclude: ['**/*.JPG'], + base: mode.command === 'serve' ? './' : env.VITE_PUBLIC_PATH, + hmr: true, + optimizeDeps: { + include: ['element-plus/lib/locale/lang/zh-cn', 'element-plus/lib/locale/lang/en', 'element-plus/lib/locale/lang/zh-tw'] + }, + server: { + host: '0.0.0.0', + port: env.VITE_PORT as unknown as number, + open: env.VITE_OPEN, + proxy: { + '/gitee': { + target: 'https://gitee.com', + ws: true, + changeOrigin: true, + rewrite: (path) => path.replace(/^\/gitee/, '') + } + } + }, + build: { + outDir: 'dist', + sourcemap: false, + chunkSizeWarningLimit: 2000, + rollupOptions: { + output: { + entryFileNames: `assets/[name].${new Date().getTime()}.js`, + chunkFileNames: `assets/[name].${new Date().getTime()}.js`, + assetFileNames: `assets/[name].${new Date().getTime()}.[ext]`, + compact: true, + manualChunks: { + vue: ['vue', 'vue-router', 'pinia'], + echarts: ['echarts'] + } + } + } + }, + css: { + postcss: { + plugins: [ + { + postcssPlugin: 'internal:charset-removal', + AtRule: { + charset: (atRule) => { + if (atRule.name === 'charset') { + atRule.remove(); + } + } + } + } + ] + } + }, + define: { + __VUE_I18N_LEGACY_API__: JSON.stringify(false), + __VUE_I18N_FULL_INSTALL__: JSON.stringify(false), + __INTLIFY_PROD_DEVTOOLS__: JSON.stringify(false) + } + }; +}); + +export default viteConfig; diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..6bacd66 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,2419 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@babel/parser@^7.16.4": + version "7.18.0" + resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.18.0.tgz" + integrity sha512-AqDccGC+m5O/iUStSJy3DGRIUFu7WbY/CppZYwrEUB4N0tZlnI8CSTsgL7v5fHVFmUbRv2sd+yy27o8Ydt4MGg== + +"@babel/runtime-corejs3@^7.11.2": + version "7.18.9" + resolved "https://registry.npmmirror.com/@babel/runtime-corejs3/-/runtime-corejs3-7.18.9.tgz" + integrity sha512-qZEWeccZCrHA2Au4/X05QW5CMdm4VjUDCrGq5gf1ZDcM4hRqreKrtwAn7yci9zfgAS9apvnsFXiGBHBAxZdK9A== + dependencies: + core-js-pure "^3.20.2" + regenerator-runtime "^0.13.4" + +"@babel/runtime@^7.11.2", "@babel/runtime@^7.12.0", "@babel/runtime@^7.5.5": + version "7.18.0" + resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.0.tgz" + integrity sha512-YMQvx/6nKEaucl0MY56mwIG483xk8SDNdlUwb2Ts6FUpr7fm85DxEmsY18LXBNhcTz6tO6JwZV8w1W06v8UKeg== + dependencies: + regenerator-runtime "^0.13.4" + +"@ctrl/tinycolor@^3.4.1": + version "3.4.1" + resolved "https://registry.npmmirror.com/@ctrl/tinycolor/-/tinycolor-3.4.1.tgz" + integrity sha512-ej5oVy6lykXsvieQtqZxCOaLT+xD4+QNarq78cIYISHmZXshCvROLudpQN3lfL8G0NL7plMSSK+zlyvCaIJ4Iw== + +"@element-plus/icons-vue@^2.0.6": + version "2.0.6" + resolved "https://registry.npmmirror.com/@element-plus/icons-vue/-/icons-vue-2.0.6.tgz" + integrity sha512-lPpG8hYkjL/Z97DH5Ei6w6o22Z4YdNglWCNYOPcB33JCF2A4wye6HFgSI7hEt9zdLyxlSpiqtgf9XcYU+m5mew== + +"@eslint/eslintrc@^1.3.0": + version "1.3.0" + resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.0.tgz" + integrity sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw== + dependencies: + ajv "^6.12.4" + debug "^4.3.2" + espree "^9.3.2" + globals "^13.15.0" + ignore "^5.2.0" + import-fresh "^3.2.1" + js-yaml "^4.1.0" + minimatch "^3.1.2" + strip-json-comments "^3.1.1" + +"@floating-ui/core@^0.7.3": + version "0.7.3" + resolved "https://registry.npmmirror.com/@floating-ui/core/-/core-0.7.3.tgz" + integrity sha512-buc8BXHmG9l82+OQXOFU3Kr2XQx9ys01U/Q9HMIrZ300iLc8HLMgh7dcCqgYzAzf4BkoQvDcXf5Y+CuEZ5JBYg== + +"@floating-ui/dom@^0.5.4": + version "0.5.4" + resolved "https://registry.npmmirror.com/@floating-ui/dom/-/dom-0.5.4.tgz" + integrity sha512-419BMceRLq0RrmTSDxn8hf9R3VCJv2K9PUfugh5JyEFmdjzDo+e8U5EdR8nzKq8Yj1htzLm3b6eQEEam3/rrtg== + dependencies: + "@floating-ui/core" "^0.7.3" + +"@humanwhocodes/config-array@^0.9.2": + version "0.9.5" + resolved "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz" + integrity sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw== + dependencies: + "@humanwhocodes/object-schema" "^1.2.1" + debug "^4.1.1" + minimatch "^3.0.4" + +"@humanwhocodes/object-schema@^1.2.1": + version "1.2.1" + resolved "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz" + integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== + +"@interactjs/actions@1.10.11", "@interactjs/actions@^1.10.2": + version "1.10.11" + resolved "https://registry.npmjs.org/@interactjs/actions/-/actions-1.10.11.tgz" + integrity sha512-P39zeefr4hkmKx+5nZ+mrH1s0l2YJ3gIHrthXmE81n6MlMa42m0WtHcTms4C5JTTNBP2EEDY+KGgGxSnmJKvUw== + optionalDependencies: + "@interactjs/interact" "1.10.11" + +"@interactjs/auto-scroll@1.10.11": + version "1.10.11" + resolved "https://registry.npmjs.org/@interactjs/auto-scroll/-/auto-scroll-1.10.11.tgz" + integrity sha512-feHNjhi0EMNLV2nQcEgjYPz2mI54aeSW2RiaoNtFLyBvtXKp0b4DmluwDv6DvuXmUpDwD5g/Hk1gGM2rgl7iqQ== + optionalDependencies: + "@interactjs/interact" "1.10.11" + +"@interactjs/auto-start@1.10.11", "@interactjs/auto-start@^1.10.2": + version "1.10.11" + resolved "https://registry.npmjs.org/@interactjs/auto-start/-/auto-start-1.10.11.tgz" + integrity sha512-cIg5CcalCPtC6AiGq6j/0hKUtL2MweEpvw12FuB19sz2Q9Dye0J4GliHKhOYvtumNinnvfVAZ4FZMqZEuX7YZA== + optionalDependencies: + "@interactjs/interact" "1.10.11" + +"@interactjs/core@1.10.11": + version "1.10.11" + resolved "https://registry.npmjs.org/@interactjs/core/-/core-1.10.11.tgz" + integrity sha512-aJ50ccVeszpJt7wPH7Yfqm7f1aG1SA94qd90P0NaESh5/QUXn4CESO6igobo4DFHQ5z+1Rfdl8aphP4JxlH4gw== + +"@interactjs/dev-tools@1.10.11", "@interactjs/dev-tools@^1.10.2": + version "1.10.11" + resolved "https://registry.npmjs.org/@interactjs/dev-tools/-/dev-tools-1.10.11.tgz" + integrity sha512-BP2FNfMbF7zLuOAUGMkDhCo1e1B0fnqyb9ih/Y8yAIJuoLrZxP/9htbsS1vZOIVZ4UgtrId4cYOwfcAZBMQtmw== + optionalDependencies: + "@interactjs/interact" "1.10.11" + +"@interactjs/inertia@1.10.11": + version "1.10.11" + resolved "https://registry.npmjs.org/@interactjs/inertia/-/inertia-1.10.11.tgz" + integrity sha512-h+sknCzRqBSyHy4ctPNsq56mxkAMMdwHWD6en7rDEw899gdGKYaXVDVdv1jMfiwNRw0eRFBNoCiol8r3a/a3Jw== + dependencies: + "@interactjs/offset" "1.10.11" + optionalDependencies: + "@interactjs/interact" "1.10.11" + +"@interactjs/interact@1.10.11": + version "1.10.11" + resolved "https://registry.npmjs.org/@interactjs/interact/-/interact-1.10.11.tgz" + integrity sha512-0iZJ9l547JuBA/lKxK4ARGYVmMqRSsAdA8gXL1zWe51qEIQq8PyWmMipoi8JbDaL7exC2THKwkXu5uq5ndT+iA== + dependencies: + "@interactjs/core" "1.10.11" + "@interactjs/types" "1.10.11" + "@interactjs/utils" "1.10.11" + +"@interactjs/interactjs@^1.10.2": + version "1.10.11" + resolved "https://registry.npmjs.org/@interactjs/interactjs/-/interactjs-1.10.11.tgz" + integrity sha512-cGOxf6rp3Y8/sk88LhIT0XDn4gCiCzAnUG5Kkj9SAqiUO6BK/9+Wbp1IBkNaPgl/8uG8gNHh/dXBrlBBNcqJAg== + dependencies: + "@interactjs/actions" "1.10.11" + "@interactjs/auto-scroll" "1.10.11" + "@interactjs/auto-start" "1.10.11" + "@interactjs/core" "1.10.11" + "@interactjs/dev-tools" "1.10.11" + "@interactjs/inertia" "1.10.11" + "@interactjs/interact" "1.10.11" + "@interactjs/modifiers" "1.10.11" + "@interactjs/offset" "1.10.11" + "@interactjs/pointer-events" "1.10.11" + "@interactjs/reflow" "1.10.11" + "@interactjs/utils" "1.10.11" + +"@interactjs/modifiers@1.10.11", "@interactjs/modifiers@^1.10.2": + version "1.10.11" + resolved "https://registry.npmjs.org/@interactjs/modifiers/-/modifiers-1.10.11.tgz" + integrity sha512-ltqX1RSqeAIikixlQBlyEUdclT5+rbfIGi3sIdLLYaIZQnltYkWqL9MHKx/w5b+hV+Mc0p5MLUFWJbTdkSCZ9g== + dependencies: + "@interactjs/snappers" "1.10.11" + optionalDependencies: + "@interactjs/interact" "1.10.11" + +"@interactjs/offset@1.10.11": + version "1.10.11" + resolved "https://registry.npmjs.org/@interactjs/offset/-/offset-1.10.11.tgz" + integrity sha512-mBT7eIfy5ivofECiv+VwtEwwIMLV54fT9ujSMWJPduxdSYIHepUWgEf/3zjJknFh6jQc7pqz9dtjvVvyzRCLlQ== + optionalDependencies: + "@interactjs/interact" "1.10.11" + +"@interactjs/pointer-events@1.10.11": + version "1.10.11" + resolved "https://registry.npmjs.org/@interactjs/pointer-events/-/pointer-events-1.10.11.tgz" + integrity sha512-yBT8JJVMZ+MgBay5l1WAHnL8ch/mZsRfaFahti+QFYeQyRloDtsWmEMDSYI/Onyy9+hS3gN/ge77ArGciZZ0Ow== + optionalDependencies: + "@interactjs/interact" "1.10.11" + +"@interactjs/reflow@1.10.11": + version "1.10.11" + resolved "https://registry.npmjs.org/@interactjs/reflow/-/reflow-1.10.11.tgz" + integrity sha512-NSCtcCkjImOYSbxzzv2kFqR9t49J8KlhEr9UoePc7GyLbNXsiv3WQ3n0ehZd7CgZXQDiVXnP2UnmIOv5Zd4HQg== + optionalDependencies: + "@interactjs/interact" "1.10.11" + +"@interactjs/snappers@1.10.11": + version "1.10.11" + resolved "https://registry.npmjs.org/@interactjs/snappers/-/snappers-1.10.11.tgz" + integrity sha512-yYtOMUZ7aFUZ1IYheq9Tj5hZ4J1r5dnaXhLF44WsI/awQ5L0DjZf07GPWof0B+7rZHEVudxyQNbPfFmb+1K94Q== + optionalDependencies: + "@interactjs/interact" "1.10.11" + +"@interactjs/types@1.10.11": + version "1.10.11" + resolved "https://registry.npmjs.org/@interactjs/types/-/types-1.10.11.tgz" + integrity sha512-YRsVFWjL8Gkkvlx3qnjeaxW4fnibSJ9791g8BA7Pv5ANByI64WmtR1vU7A2rXcrOn8XvyCEfY0ss1s8NhZP+MA== + +"@interactjs/utils@1.10.11": + version "1.10.11" + resolved "https://registry.npmjs.org/@interactjs/utils/-/utils-1.10.11.tgz" + integrity sha512-410ZoxKF+r1roeSelL+WHXfdryUMg5iykC1XwQ3l6XqNw43IMACzyvTH6k6Pwxj7w7x42nce0Qdn1GQ3Y8xyCw== + +"@intlify/core-base@9.1.10": + version "9.1.10" + resolved "https://registry.npmjs.org/@intlify/core-base/-/core-base-9.1.10.tgz" + integrity sha512-So9CNUavB/IsZ+zBmk2Cv6McQp6vc2wbGi1S0XQmJ8Vz+UFcNn9MFXAe9gY67PreIHrbLsLxDD0cwo1qsxM1Nw== + dependencies: + "@intlify/devtools-if" "9.1.10" + "@intlify/message-compiler" "9.1.10" + "@intlify/message-resolver" "9.1.10" + "@intlify/runtime" "9.1.10" + "@intlify/shared" "9.1.10" + "@intlify/vue-devtools" "9.1.10" + +"@intlify/devtools-if@9.1.10": + version "9.1.10" + resolved "https://registry.npmjs.org/@intlify/devtools-if/-/devtools-if-9.1.10.tgz" + integrity sha512-SHaKoYu6sog3+Q8js1y3oXLywuogbH1sKuc7NSYkN3GElvXSBaMoCzW+we0ZSFqj/6c7vTNLg9nQ6rxhKqYwnQ== + dependencies: + "@intlify/shared" "9.1.10" + +"@intlify/message-compiler@9.1.10": + version "9.1.10" + resolved "https://registry.npmjs.org/@intlify/message-compiler/-/message-compiler-9.1.10.tgz" + integrity sha512-+JiJpXff/XTb0EadYwdxOyRTB0hXNd4n1HaJ/a4yuV960uRmPXaklJsedW0LNdcptd/hYUZtCkI7Lc9J5C1gxg== + dependencies: + "@intlify/message-resolver" "9.1.10" + "@intlify/shared" "9.1.10" + source-map "0.6.1" + +"@intlify/message-resolver@9.1.10": + version "9.1.10" + resolved "https://registry.npmjs.org/@intlify/message-resolver/-/message-resolver-9.1.10.tgz" + integrity sha512-5YixMG/M05m0cn9+gOzd4EZQTFRUu8RGhzxJbR1DWN21x/Z3bJ8QpDYj6hC4FwBj5uKsRfKpJQ3Xqg98KWoA+w== + +"@intlify/runtime@9.1.10": + version "9.1.10" + resolved "https://registry.npmjs.org/@intlify/runtime/-/runtime-9.1.10.tgz" + integrity sha512-7QsuByNzpe3Gfmhwq6hzgXcMPpxz8Zxb/XFI6s9lQdPLPe5Lgw4U1ovRPZTOs6Y2hwitR3j/HD8BJNGWpJnOFA== + dependencies: + "@intlify/message-compiler" "9.1.10" + "@intlify/message-resolver" "9.1.10" + "@intlify/shared" "9.1.10" + +"@intlify/shared@9.1.10": + version "9.1.10" + resolved "https://registry.npmjs.org/@intlify/shared/-/shared-9.1.10.tgz" + integrity sha512-Om54xJeo1Vw+K1+wHYyXngE8cAbrxZHpWjYzMR9wCkqbhGtRV5VLhVc214Ze2YatPrWlS2WSMOWXR8JktX/IgA== + +"@intlify/vue-devtools@9.1.10": + version "9.1.10" + resolved "https://registry.npmjs.org/@intlify/vue-devtools/-/vue-devtools-9.1.10.tgz" + integrity sha512-5l3qYARVbkWAkagLu1XbDUWRJSL8br1Dj60wgMaKB0+HswVsrR6LloYZTg7ozyvM621V6+zsmwzbQxbVQyrytQ== + dependencies: + "@intlify/message-resolver" "9.1.10" + "@intlify/runtime" "9.1.10" + "@intlify/shared" "9.1.10" + +"@jiaminghi/bezier-curve@*": + version "0.0.9" + resolved "https://registry.npmmirror.com/@jiaminghi/bezier-curve/-/bezier-curve-0.0.9.tgz" + integrity sha512-u9xJPOEl6Dri2E9FfmJoGxYQY7vYJkURNX04Vj64tdi535tPrpkuf9Sm0lNr3QTKdHQh0DdNRsaa62FLQNQEEw== + dependencies: + "@babel/runtime" "^7.5.5" + +"@jiaminghi/c-render@^0.4.3": + version "0.4.3" + resolved "https://registry.npmmirror.com/@jiaminghi/c-render/-/c-render-0.4.3.tgz" + integrity sha512-FJfzj5hGj7MLqqqI2D7vEzHKbQ1Ynnn7PJKgzsjXaZpJzTqs2Yw5OSeZnm6l7Qj7jyPAP53lFvEQNH4o4j6s+Q== + dependencies: + "@babel/runtime" "^7.5.5" + "@jiaminghi/bezier-curve" "*" + "@jiaminghi/color" "*" + "@jiaminghi/transition" "*" + +"@jiaminghi/charts@^0.2.18": + version "0.2.18" + resolved "https://registry.npmmirror.com/@jiaminghi/charts/-/charts-0.2.18.tgz" + integrity sha512-K+HXaOOeWG9OOY1VG6M4mBreeeIAPhb9X+khG651AbnwEwL6G2UtcAQ8GWCq6GzhczcLwwhIhuaHqRygwHC0sA== + dependencies: + "@babel/runtime" "^7.5.5" + "@jiaminghi/c-render" "^0.4.3" + +"@jiaminghi/color@*": + version "0.1.1" + resolved "https://registry.npmmirror.com/@jiaminghi/color/-/color-0.1.1.tgz" + integrity sha512-M09+Sb5HGqVim0zo+nG5gU1v+6gXT8ptr0BZR6dMGt83XmCJgnZtO8s7llTW4hLFFFM5co6geZvTekqLpSPAAQ== + dependencies: + "@babel/runtime" "^7.5.5" + +"@jiaminghi/transition@*": + version "1.1.11" + resolved "https://registry.npmmirror.com/@jiaminghi/transition/-/transition-1.1.11.tgz" + integrity sha512-owBggipoHMikDHHDW5Gc7RZYlVuvxHADiU4bxfjBVkHDAmmck+fCkm46n2JzC3j33hWvP9nSCAeh37t6stgWeg== + dependencies: + "@babel/runtime" "^7.5.5" + +"@kjgl77/datav-vue3@^1.2.1": + version "1.2.2" + resolved "https://registry.npmmirror.com/@kjgl77/datav-vue3/-/datav-vue3-1.2.2.tgz" + integrity sha512-NJEn/n5SOOnVeMzQ7kZ6eaY6ux5SYT9uwfC81LC89s4BtwBRnq8zY7xoNIgai7JR1nW1TKEggOBWMfiLlkc/PA== + dependencies: + "@jiaminghi/c-render" "^0.4.3" + "@jiaminghi/charts" "^0.2.18" + "@vueuse/core" "^9.1.0" + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.8" + resolved "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@popperjs/core@npm:@sxzz/popperjs-es@^2.11.7": + version "2.11.7" + resolved "https://registry.npmmirror.com/@sxzz/popperjs-es/-/popperjs-es-2.11.7.tgz" + integrity sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ== + +"@transloadit/prettier-bytes@0.0.7": + version "0.0.7" + resolved "https://registry.npmjs.org/@transloadit/prettier-bytes/-/prettier-bytes-0.0.7.tgz" + integrity sha512-VeJbUb0wEKbcwaSlj5n+LscBl9IPgLPkHVGBkh00cztv6X4L/TJXK58LzFuBKX7/GAfiGhIwH67YTLTlzvIzBA== + +"@types/event-emitter@^0.3.3": + version "0.3.3" + resolved "https://registry.npmjs.org/@types/event-emitter/-/event-emitter-0.3.3.tgz" + integrity sha512-UfnOK1pIxO7P+EgPRZXD9jMpimd8QEFcEZ5R67R1UhGbv4zghU5+NE7U8M8G9H5Jc8FI51rqDWQs6FtUfq2e/Q== + +"@types/json-bigint@^1.0.1": + version "1.0.1" + resolved "https://registry.npmmirror.com/@types/json-bigint/-/json-bigint-1.0.1.tgz" + integrity sha512-zpchZLNsNuzJHi6v64UBoFWAvQlPhch7XAi36FkH6tL1bbbmimIF+cS7vwkzY4u5RaSWMoflQfu+TshMPPw8uw== + +"@types/json-schema@^7.0.9": + version "7.0.11" + resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz" + integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== + +"@types/lodash-es@^4.17.6": + version "4.17.6" + resolved "https://registry.npmmirror.com/@types/lodash-es/-/lodash-es-4.17.6.tgz" + integrity sha512-R+zTeVUKDdfoRxpAryaQNRKk3105Rrgx2CFRClIgRGaqDTdjsm8h6IYA8ir584W3ePzkZfst5xIgDwYrlh9HLg== + dependencies: + "@types/lodash" "*" + +"@types/lodash@*", "@types/lodash@^4.14.182": + version "4.14.182" + resolved "https://registry.npmmirror.com/@types/lodash/-/lodash-4.14.182.tgz" + integrity sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q== + +"@types/node@^17.0.39": + version "17.0.39" + resolved "https://registry.npmjs.org/@types/node/-/node-17.0.39.tgz" + integrity sha512-JDU3YLlnPK3WDao6/DlXLOgSNpG13ct+CwIO17V8q0/9fWJyeMJJ/VyZ1lv8kDprihvZMydzVwf0tQOqGiY2Nw== + +"@types/nprogress@^0.2.0": + version "0.2.0" + resolved "https://registry.npmjs.org/@types/nprogress/-/nprogress-0.2.0.tgz" + integrity sha512-1cYJrqq9GezNFPsWTZpFut/d4CjpZqA0vhqDUPFWYKF1oIyBz5qnoYMzR+0C/T96t3ebLAC1SSnwrVOm5/j74A== + +"@types/sortablejs@^1.13.0": + version "1.13.0" + resolved "https://registry.npmjs.org/@types/sortablejs/-/sortablejs-1.13.0.tgz" + integrity sha512-C3064MH72iEfeGCYEGCt7FCxXoAXaMPG0QPnstcxvPmbl54erpISu06d++FY37Smja64iWy5L8wOyHHBghWbJQ== + +"@types/web-bluetooth@^0.0.14": + version "0.0.14" + resolved "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.14.tgz" + integrity sha512-5d2RhCard1nQUC3aHcq/gHzWYO6K0WJmAbjO7mQJgCQKtZpgXxv1rOM6O/dBDhDYYVutk1sciOgNSe+5YyfM8A== + +"@types/web-bluetooth@^0.0.15": + version "0.0.15" + resolved "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.15.tgz" + integrity sha512-w7hEHXnPMEZ+4nGKl/KDRVpxkwYxYExuHOYXyzIzCDzEZ9ZCGMAewulr9IqJu2LR4N37fcnb1XVeuZ09qgOxhA== + +"@typescript-eslint/eslint-plugin@^5.27.0": + version "5.27.0" + resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.27.0.tgz" + integrity sha512-DDrIA7GXtmHXr1VCcx9HivA39eprYBIFxbQEHI6NyraRDxCGpxAFiYQAT/1Y0vh1C+o2vfBiy4IuPoXxtTZCAQ== + dependencies: + "@typescript-eslint/scope-manager" "5.27.0" + "@typescript-eslint/type-utils" "5.27.0" + "@typescript-eslint/utils" "5.27.0" + debug "^4.3.4" + functional-red-black-tree "^1.0.1" + ignore "^5.2.0" + regexpp "^3.2.0" + semver "^7.3.7" + tsutils "^3.21.0" + +"@typescript-eslint/parser@^5.27.0": + version "5.27.0" + resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.27.0.tgz" + integrity sha512-8oGjQF46c52l7fMiPPvX4It3u3V3JipssqDfHQ2hcR0AeR8Zge+OYyKUCm5b70X72N1qXt0qgHenwN6Gc2SXZA== + dependencies: + "@typescript-eslint/scope-manager" "5.27.0" + "@typescript-eslint/types" "5.27.0" + "@typescript-eslint/typescript-estree" "5.27.0" + debug "^4.3.4" + +"@typescript-eslint/scope-manager@5.27.0": + version "5.27.0" + resolved "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.27.0.tgz" + integrity sha512-VnykheBQ/sHd1Vt0LJ1JLrMH1GzHO+SzX6VTXuStISIsvRiurue/eRkTqSrG0CexHQgKG8shyJfR4o5VYioB9g== + dependencies: + "@typescript-eslint/types" "5.27.0" + "@typescript-eslint/visitor-keys" "5.27.0" + +"@typescript-eslint/type-utils@5.27.0": + version "5.27.0" + resolved "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.27.0.tgz" + integrity sha512-vpTvRRchaf628Hb/Xzfek+85o//zEUotr1SmexKvTfs7czXfYjXVT/a5yDbpzLBX1rhbqxjDdr1Gyo0x1Fc64g== + dependencies: + "@typescript-eslint/utils" "5.27.0" + debug "^4.3.4" + tsutils "^3.21.0" + +"@typescript-eslint/types@5.27.0": + version "5.27.0" + resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.27.0.tgz" + integrity sha512-lY6C7oGm9a/GWhmUDOs3xAVRz4ty/XKlQ2fOLr8GAIryGn0+UBOoJDWyHer3UgrHkenorwvBnphhP+zPmzmw0A== + +"@typescript-eslint/typescript-estree@5.27.0": + version "5.27.0" + resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.27.0.tgz" + integrity sha512-QywPMFvgZ+MHSLRofLI7BDL+UczFFHyj0vF5ibeChDAJgdTV8k4xgEwF0geFhVlPc1p8r70eYewzpo6ps+9LJQ== + dependencies: + "@typescript-eslint/types" "5.27.0" + "@typescript-eslint/visitor-keys" "5.27.0" + debug "^4.3.4" + globby "^11.1.0" + is-glob "^4.0.3" + semver "^7.3.7" + tsutils "^3.21.0" + +"@typescript-eslint/utils@5.27.0": + version "5.27.0" + resolved "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.27.0.tgz" + integrity sha512-nZvCrkIJppym7cIbP3pOwIkAefXOmfGPnCM0LQfzNaKxJHI6VjI8NC662uoiPlaf5f6ymkTy9C3NQXev2mdXmA== + dependencies: + "@types/json-schema" "^7.0.9" + "@typescript-eslint/scope-manager" "5.27.0" + "@typescript-eslint/types" "5.27.0" + "@typescript-eslint/typescript-estree" "5.27.0" + eslint-scope "^5.1.1" + eslint-utils "^3.0.0" + +"@typescript-eslint/visitor-keys@5.27.0": + version "5.27.0" + resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.27.0.tgz" + integrity sha512-46cYrteA2MrIAjv9ai44OQDUoCZyHeGIc4lsjCUX2WT6r4C+kidz1bNiR4017wHOPUythYeH+Sc7/cFP97KEAA== + dependencies: + "@typescript-eslint/types" "5.27.0" + eslint-visitor-keys "^3.3.0" + +"@uppy/companion-client@^2.1.0": + version "2.1.0" + resolved "https://registry.npmjs.org/@uppy/companion-client/-/companion-client-2.1.0.tgz" + integrity sha512-1Zsag2z9kygXuVbUxqHhkTJUmEHwbejjyf7vmm+P/AiVgK3O37JINYBGOpdTJNgbC9UydLBjleXo8peDVgpg8Q== + dependencies: + "@uppy/utils" "^4.0.7" + namespace-emitter "^2.0.1" + +"@uppy/core@^2.1.1": + version "2.2.0" + resolved "https://registry.npmjs.org/@uppy/core/-/core-2.2.0.tgz" + integrity sha512-qdDoNCjrVjjOmFCFCxc+HEbtbQ9K0k6LKNbZZwWK7d4Cx3xEa6VsxmqVhfFL6ekH2gyboqYV8Z5IbRkJT/0Nqg== + dependencies: + "@transloadit/prettier-bytes" "0.0.7" + "@uppy/store-default" "^2.0.3" + "@uppy/utils" "^4.0.7" + lodash.throttle "^4.1.1" + mime-match "^1.0.2" + namespace-emitter "^2.0.1" + nanoid "^3.1.25" + preact "^10.5.13" + +"@uppy/store-default@^2.0.3": + version "2.0.3" + resolved "https://registry.npmjs.org/@uppy/store-default/-/store-default-2.0.3.tgz" + integrity sha512-2BGlN1sW0cFv4rOqTK8dfSg579S984N1HxCJxLFqeW9nWD6zd/O8Omyd85tbxGQ+FLZLTmLOm/feD0YeCBMahg== + +"@uppy/utils@^4.0.7": + version "4.0.7" + resolved "https://registry.npmjs.org/@uppy/utils/-/utils-4.0.7.tgz" + integrity sha512-nKViMT8XchKy+NWpb3DtVKuzZBmW7au26LrMq89EsvTwIOT6UR9+7bmz/+zr3+lc7UC7vMgNChIC6G+/Ya9wWQ== + dependencies: + lodash.throttle "^4.1.1" + +"@uppy/xhr-upload@^2.0.3": + version "2.1.0" + resolved "https://registry.npmjs.org/@uppy/xhr-upload/-/xhr-upload-2.1.0.tgz" + integrity sha512-io1uNu7lGkhIkMnt13bu3FYSAdRbBRWl8n/6njYi+727Jyr0XhKfmBYV9OiruFSxLz5Bfxkw2gTs6e0qUb63nA== + dependencies: + "@uppy/companion-client" "^2.1.0" + "@uppy/utils" "^4.0.7" + nanoid "^3.1.25" + +"@vitejs/plugin-vue@^2.3.3": + version "2.3.3" + resolved "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-2.3.3.tgz" + integrity sha512-SmQLDyhz+6lGJhPELsBdzXGc+AcaT8stgkbiTFGpXPe8Tl1tJaBw1A6pxDqDuRsVkD8uscrkx3hA7QDOoKYtyw== + +"@vue/compiler-core@3.2.36": + version "3.2.36" + resolved "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.36.tgz" + integrity sha512-bbyZM5hvBicv0PW3KUfVi+x3ylHnfKG7DOn5wM+f2OztTzTjLEyBb/5yrarIYpmnGitVGbjZqDbODyW4iK8hqw== + dependencies: + "@babel/parser" "^7.16.4" + "@vue/shared" "3.2.36" + estree-walker "^2.0.2" + source-map "^0.6.1" + +"@vue/compiler-dom@3.2.36": + version "3.2.36" + resolved "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.36.tgz" + integrity sha512-tcOTAOiW4s24QLnq+ON6J+GRONXJ+A/mqKCORi0LSlIh8XQlNnlm24y8xIL8la+ZDgkdbjarQ9ZqYSvEja6gVA== + dependencies: + "@vue/compiler-core" "3.2.36" + "@vue/shared" "3.2.36" + +"@vue/compiler-sfc@3.2.36", "@vue/compiler-sfc@^3.2.36": + version "3.2.36" + resolved "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.36.tgz" + integrity sha512-AvGb4bTj4W8uQ4BqaSxo7UwTEqX5utdRSMyHy58OragWlt8nEACQ9mIeQh3K4di4/SX+41+pJrLIY01lHAOFOA== + dependencies: + "@babel/parser" "^7.16.4" + "@vue/compiler-core" "3.2.36" + "@vue/compiler-dom" "3.2.36" + "@vue/compiler-ssr" "3.2.36" + "@vue/reactivity-transform" "3.2.36" + "@vue/shared" "3.2.36" + estree-walker "^2.0.2" + magic-string "^0.25.7" + postcss "^8.1.10" + source-map "^0.6.1" + +"@vue/compiler-ssr@3.2.36": + version "3.2.36" + resolved "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.36.tgz" + integrity sha512-+KugInUFRvOxEdLkZwE+W43BqHyhBh0jpYXhmqw1xGq2dmE6J9eZ8UUSOKNhdHtQ/iNLWWeK/wPZkVLUf3YGaw== + dependencies: + "@vue/compiler-dom" "3.2.36" + "@vue/shared" "3.2.36" + +"@vue/devtools-api@^6.0.0", "@vue/devtools-api@^6.0.0-beta.7", "@vue/devtools-api@^6.1.4": + version "6.1.4" + resolved "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.1.4.tgz" + integrity sha512-IiA0SvDrJEgXvVxjNkHPFfDx6SXw0b/TUkqMcDZWNg9fnCAHbTpoo59YfJ9QLFkwa3raau5vSlRVzMSLDnfdtQ== + +"@vue/reactivity-transform@3.2.36": + version "3.2.36" + resolved "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.2.36.tgz" + integrity sha512-Jk5o2BhpODC9XTA7o4EL8hSJ4JyrFWErLtClG3NH8wDS7ri9jBDWxI7/549T7JY9uilKsaNM+4pJASLj5dtRwA== + dependencies: + "@babel/parser" "^7.16.4" + "@vue/compiler-core" "3.2.36" + "@vue/shared" "3.2.36" + estree-walker "^2.0.2" + magic-string "^0.25.7" + +"@vue/reactivity@3.2.36": + version "3.2.36" + resolved "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.36.tgz" + integrity sha512-c2qvopo0crh9A4GXi2/2kfGYMxsJW4tVILrqRPydVGZHhq0fnzy6qmclWOhBFckEhmyxmpHpdJtIRYGeKcuhnA== + dependencies: + "@vue/shared" "3.2.36" + +"@vue/runtime-core@3.2.36": + version "3.2.36" + resolved "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.2.36.tgz" + integrity sha512-PTWBD+Lub+1U3/KhbCExrfxyS14hstLX+cBboxVHaz+kXoiDLNDEYAovPtxeTutbqtClIXtft+wcGdC+FUQ9qQ== + dependencies: + "@vue/reactivity" "3.2.36" + "@vue/shared" "3.2.36" + +"@vue/runtime-dom@3.2.36": + version "3.2.36" + resolved "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.2.36.tgz" + integrity sha512-gYPYblm7QXHVuBohqNRRT7Wez0f2Mx2D40rb4fleehrJU9CnkjG0phhcGEZFfGwCmHZRqBCRgbFWE98bPULqkg== + dependencies: + "@vue/runtime-core" "3.2.36" + "@vue/shared" "3.2.36" + csstype "^2.6.8" + +"@vue/server-renderer@3.2.36": + version "3.2.36" + resolved "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.2.36.tgz" + integrity sha512-uZE0+jfye6yYXWvAQYeHZv+f50sRryvy16uiqzk3jn8hEY8zTjI+rzlmZSGoE915k+W/Ol9XSw6vxOUD8dGkUg== + dependencies: + "@vue/compiler-ssr" "3.2.36" + "@vue/shared" "3.2.36" + +"@vue/shared@3.2.36": + version "3.2.36" + resolved "https://registry.npmjs.org/@vue/shared/-/shared-3.2.36.tgz" + integrity sha512-JtB41wXl7Au3+Nl3gD16Cfpj7k/6aCroZ6BbOiCMFCMvrOpkg/qQUXTso2XowaNqBbnkuGHurLAqkLBxNGc1hQ== + +"@vueuse/core@^8.7.5": + version "8.9.2" + resolved "https://registry.npmmirror.com/@vueuse/core/-/core-8.9.2.tgz" + integrity sha512-dE3/JgwqIHmmtmRBdZAnq87rZCSFbYVps2t3gWy9Jv/+Qp6sHSSKuPFtwguJVZ2OnaGnB/AMRmx4CuFRxFin3A== + dependencies: + "@types/web-bluetooth" "^0.0.14" + "@vueuse/metadata" "8.9.2" + "@vueuse/shared" "8.9.2" + vue-demi "*" + +"@vueuse/core@^9.1.0": + version "9.1.1" + resolved "https://registry.npmmirror.com/@vueuse/core/-/core-9.1.1.tgz" + integrity sha512-QfuaNWRDMQcCUwXylCyYhPC3ScS9Tiiz4J0chdwr3vOemBwRToSywq8MP+ZegKYFnbETzRY8G/5zC+ca30wrRQ== + dependencies: + "@types/web-bluetooth" "^0.0.15" + "@vueuse/metadata" "9.1.1" + "@vueuse/shared" "9.1.1" + vue-demi "*" + +"@vueuse/metadata@8.9.2": + version "8.9.2" + resolved "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-8.9.2.tgz" + integrity sha512-g2s2BeyeEtJElmMFfFPnM+BTvnt0omniyvz8U18/zXDpQIMGozlNQgHoFeratyMfgVBhH/u2VKzmchChtDsgPQ== + +"@vueuse/metadata@9.1.1": + version "9.1.1" + resolved "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-9.1.1.tgz" + integrity sha512-XZ2KtSW+85LLHB/IdGILPAtbIVHasPsAW7aqz3BRMzJdAQWRiM/FGa1OKBwLbXtUw/AmjKYFlZJo7eOFIBXRog== + +"@vueuse/shared@8.9.2": + version "8.9.2" + resolved "https://registry.npmmirror.com/@vueuse/shared/-/shared-8.9.2.tgz" + integrity sha512-s4Nk82oheL5z1GywyGnqjob0MzbAt88olMZa0vgt/p3gcMsT8Ff7+SqmNgEFC6AAs6xiuhOAZpnew9Zs3d90yQ== + dependencies: + vue-demi "*" + +"@vueuse/shared@9.1.1": + version "9.1.1" + resolved "https://registry.npmmirror.com/@vueuse/shared/-/shared-9.1.1.tgz" + integrity sha512-c+IfcOYmHiHqoEa3ED1Tbpue5GHmoUmTp8PtO4YbczthtY155Rt6DmWhjxMLXBF1Bcidagxljmp/7xtAzEHXLw== + dependencies: + vue-demi "*" + +"@wangeditor/basic-modules@^1.1.3": + version "1.1.3" + resolved "https://registry.npmmirror.com/@wangeditor/basic-modules/-/basic-modules-1.1.3.tgz" + integrity sha512-TGJix4UelO46yAgwI946ctx4lSIJbYBwNvjSJ9Tf8mKr0WMCeLVBV+MV85rXPsfcmWtR4wBNwSg648Z+RbqRUg== + dependencies: + is-url "^1.2.4" + +"@wangeditor/code-highlight@^1.0.2": + version "1.0.2" + resolved "https://registry.npmjs.org/@wangeditor/code-highlight/-/code-highlight-1.0.2.tgz" + integrity sha512-SCtOcUxjKqIso/LSxGSOaYr3G6MC2En0gNTyHIMCG928T0fo0ufaqp/vIXKQzVL2Y+X/CSAOB2EbrFlgGvr0AQ== + dependencies: + prismjs "^1.23.0" + +"@wangeditor/core@^1.1.11": + version "1.1.11" + resolved "https://registry.npmmirror.com/@wangeditor/core/-/core-1.1.11.tgz" + integrity sha512-BwHVRJzESnkjKikTc2U2zsbd06l1pSo7qKy5+SpZLudYWrFxmd85VN+5GxM57FodogkNw/k04DFHcFSUfXcaKA== + dependencies: + "@types/event-emitter" "^0.3.3" + event-emitter "^0.3.5" + html-void-elements "^2.0.0" + i18next "^20.4.0" + scroll-into-view-if-needed "^2.2.28" + slate-history "^0.66.0" + +"@wangeditor/editor@^5.1.14": + version "5.1.14" + resolved "https://registry.npmmirror.com/@wangeditor/editor/-/editor-5.1.14.tgz" + integrity sha512-erILPAkpKldyGi4cEwrOW65v12GhZy2qj2A8kPlypU46lE72Y3XowZxWogN1TI/mqMDR84AHr0QWOvygOV1xwQ== + dependencies: + "@uppy/core" "^2.1.1" + "@uppy/xhr-upload" "^2.0.3" + "@wangeditor/basic-modules" "^1.1.3" + "@wangeditor/code-highlight" "^1.0.2" + "@wangeditor/core" "^1.1.11" + "@wangeditor/list-module" "^1.0.2" + "@wangeditor/table-module" "^1.1.1" + "@wangeditor/upload-image-module" "^1.0.1" + "@wangeditor/video-module" "^1.1.1" + dom7 "^3.0.0" + is-hotkey "^0.2.0" + lodash.camelcase "^4.3.0" + lodash.clonedeep "^4.5.0" + lodash.debounce "^4.0.8" + lodash.foreach "^4.5.0" + lodash.isequal "^4.5.0" + lodash.throttle "^4.1.1" + lodash.toarray "^4.4.0" + nanoid "^3.2.0" + slate "^0.72.0" + snabbdom "^3.1.0" + +"@wangeditor/list-module@^1.0.2": + version "1.0.2" + resolved "https://registry.npmjs.org/@wangeditor/list-module/-/list-module-1.0.2.tgz" + integrity sha512-VfENZEFvsLTiLxN/cj8cibFGy9NVV+/cfATTiLiH9ef+8lgKv8apttXYVlqIAfnlJLLuCk0cIm8c/zH+hbtrZg== + +"@wangeditor/table-module@^1.1.1": + version "1.1.1" + resolved "https://registry.npmmirror.com/@wangeditor/table-module/-/table-module-1.1.1.tgz" + integrity sha512-VPjEWQtncS2DsXYXiHUxPSxn2Xhc8GdhG3la7N5YhvxQde1+4N0SZLXeWsYvbGzOq4um5XToq5pktLLbE8G+EA== + +"@wangeditor/upload-image-module@^1.0.1": + version "1.0.1" + resolved "https://registry.npmjs.org/@wangeditor/upload-image-module/-/upload-image-module-1.0.1.tgz" + integrity sha512-vgUV4ENttTITblqtVuzleIq732OmzmzzgrIvX6b3GRGPSw5u8glJ/87tOEhvHjHECc4oFo18B7xzJ1GpBj79/w== + +"@wangeditor/video-module@^1.1.1": + version "1.1.1" + resolved "https://registry.npmmirror.com/@wangeditor/video-module/-/video-module-1.1.1.tgz" + integrity sha512-6gzpS5cnJihW2T0HFjqmbv6v8ouyaeMUjdM2X8BPohwD74p1ov00dCmRt5QekNTyYSmRHK0ASkUMOvRGqaDxMg== + +acorn-jsx@^5.3.2: + version "5.3.2" + resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + +acorn@^8.7.1: + version "8.7.1" + resolved "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz" + integrity sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A== + +adler-32@~1.3.0: + version "1.3.1" + resolved "https://registry.npmmirror.com/adler-32/-/adler-32-1.3.1.tgz" + integrity sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A== + +ajv@^6.10.0, ajv@^6.12.4: + version "6.12.6" + resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +anymatch@~3.1.2: + version "3.1.2" + resolved "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz" + integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + +async-validator@^4.2.5: + version "4.2.5" + resolved "https://registry.npmmirror.com/async-validator/-/async-validator-4.2.5.tgz" + integrity sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg== + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + +axios@^0.27.2: + version "0.27.2" + resolved "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz" + integrity sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ== + dependencies: + follow-redirects "^1.14.9" + form-data "^4.0.0" + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +batch-processor@1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/batch-processor/-/batch-processor-1.0.0.tgz" + integrity sha512-xoLQD8gmmR32MeuBHgH0Tzd5PuSZx71ZsbhVxOCRbgktZEPe4SQy7s9Z50uPp0F/f7iw2XmkHN2xkgbMfckMDA== + +bignumber.js@^9.0.0: + version "9.0.2" + resolved "https://registry.npmmirror.com/bignumber.js/-/bignumber.js-9.0.2.tgz" + integrity sha512-GAcQvbpsM0pUb0zw1EI0KhQEZ+lRwR5fYaAp3vPOYuP7aDvGy6cVN6XHLauvF8SOga2y0dcLcjt3iQDTSEliyw== + +binary-extensions@^2.0.0: + version "2.2.0" + resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + +boolbase@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz" + integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^3.0.2, braces@~3.0.2: + version "3.0.2" + resolved "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +cfb@~1.2.1: + version "1.2.2" + resolved "https://registry.npmmirror.com/cfb/-/cfb-1.2.2.tgz" + integrity sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA== + dependencies: + adler-32 "~1.3.0" + crc-32 "~1.2.0" + +chalk@^4.0.0: + version "4.1.2" + resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +"chokidar@>=3.0.0 <4.0.0": + version "3.5.3" + resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +claygl@^1.2.1: + version "1.3.0" + resolved "https://registry.npmjs.org/claygl/-/claygl-1.3.0.tgz" + integrity sha512-+gGtJjT6SSHD2l2yC3MCubW/sCV40tZuSs5opdtn79vFSGUgp/lH139RNEQ6Jy078/L0aV8odCw8RSrUcMfLaQ== + +clipboard@^2.0.6: + version "2.0.11" + resolved "https://registry.npmjs.org/clipboard/-/clipboard-2.0.11.tgz" + integrity sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw== + dependencies: + good-listener "^1.2.2" + select "^1.1.2" + tiny-emitter "^2.0.0" + +codepage@~1.15.0: + version "1.15.0" + resolved "https://registry.npmmirror.com/codepage/-/codepage-1.15.0.tgz" + integrity sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA== + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +compute-scroll-into-view@^1.0.17: + version "1.0.17" + resolved "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-1.0.17.tgz" + integrity sha512-j4dx+Fb0URmzbwwMUrhqWM2BEWHdFGx+qZ9qqASHRPqvTYdqvWnHg0H1hIbcyLnvgnoNAVMlwkepyqM3DaIFUg== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + +core-js-pure@^3.20.2: + version "3.25.0" + resolved "https://registry.npmmirror.com/core-js-pure/-/core-js-pure-3.25.0.tgz" + integrity sha512-IeHpLwk3uoci37yoI2Laty59+YqH9x5uR65/yiA0ARAJrTrN4YU0rmauLWfvqOuk77SlNJXj2rM6oT/dBD87+A== + +countup.js@^2.2.0: + version "2.2.0" + resolved "https://registry.npmjs.org/countup.js/-/countup.js-2.2.0.tgz" + integrity sha512-m0TvFNXm9/eFqJm+QiKVI8e0wRUHzlQSewz9dqVjlhl2DFoZtceLbomwzxHz0hJ1+r4zBC7wSpR/TpthG49h6g== + +crc-32@~1.2.0, crc-32@~1.2.1: + version "1.2.2" + resolved "https://registry.npmmirror.com/crc-32/-/crc-32-1.2.2.tgz" + integrity sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ== + +cropperjs@^1.5.12: + version "1.5.12" + resolved "https://registry.npmjs.org/cropperjs/-/cropperjs-1.5.12.tgz" + integrity sha512-re7UdjE5UnwdrovyhNzZ6gathI4Rs3KGCBSc8HCIjUo5hO42CtzyblmWLj6QWVw7huHyDMfpKxhiO2II77nhDw== + +cross-spawn@^7.0.2: + version "7.0.3" + resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +cssesc@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz" + integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== + +csstype@^2.6.8: + version "2.6.20" + resolved "https://registry.npmjs.org/csstype/-/csstype-2.6.20.tgz" + integrity sha512-/WwNkdXfckNgw6S5R125rrW8ez139lBHWouiBvX8dfMFtcn6V81REDqnH7+CRpRipfYlyU1CmOnOxrmGcFOjeA== + +d@1, d@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/d/-/d-1.0.1.tgz" + integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA== + dependencies: + es5-ext "^0.10.50" + type "^1.0.1" + +dayjs@^1.11.3: + version "1.11.3" + resolved "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.3.tgz" + integrity sha512-xxwlswWOlGhzgQ4TKzASQkUhqERI3egRNqgV4ScR8wlANA/A9tZ7miXa44vTTKEq5l7vWoL5G57bG3zA+Kow0A== + +debug@^4.1.1, debug@^4.3.2, debug@^4.3.4: + version "4.3.4" + resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +deep-is@^0.1.3: + version "0.1.4" + resolved "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz" + integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= + +delegate@^3.1.2: + version "3.2.0" + resolved "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz" + integrity sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw== + +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + +dom7@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/dom7/-/dom7-3.0.0.tgz" + integrity sha512-oNlcUdHsC4zb7Msx7JN3K0Nro1dzJ48knvBOnDPKJ2GV9wl1i5vydJZUSyOfrkKFDZEud/jBsTk92S/VGSAe/g== + dependencies: + ssr-window "^3.0.0-alpha.1" + +dotenv@^16.0.1: + version "16.0.1" + resolved "https://registry.npmjs.org/dotenv/-/dotenv-16.0.1.tgz" + integrity sha512-1K6hR6wtk2FviQ4kEiSjFiH5rpzEVi8WW0x96aztHVMhEspNpc4DVOUTEHtEva5VThQ8IaBX1Pe4gSzpVVUsKQ== + +echarts-gl@^2.0.9: + version "2.0.9" + resolved "https://registry.npmjs.org/echarts-gl/-/echarts-gl-2.0.9.tgz" + integrity sha512-oKeMdkkkpJGWOzjgZUsF41DOh6cMsyrGGXimbjK2l6Xeq/dBQu4ShG2w2Dzrs/1bD27b2pLTGSaUzouY191gzA== + dependencies: + claygl "^1.2.1" + zrender "^5.1.1" + +echarts-wordcloud@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/echarts-wordcloud/-/echarts-wordcloud-2.0.0.tgz" + integrity sha512-K7l6pTklqdW7ZWzT/1CS0KhBSINr/cd7c5N1fVMzZMwLQHEwT7x+nivK7g5hkVh7WNcAv4Dn6/ZS5zMKRozC1g== + +echarts@^5.3.3: + version "5.3.3" + resolved "https://registry.npmmirror.com/echarts/-/echarts-5.3.3.tgz" + integrity sha512-BRw2serInRwO5SIwRviZ6Xgm5Lb7irgz+sLiFMmy/HOaf4SQ+7oYqxKzRHAKp4xHQ05AuHw1xvoQWJjDQq/FGw== + dependencies: + tslib "2.3.0" + zrender "5.3.2" + +element-plus@^2.2.9: + version "2.2.9" + resolved "https://registry.npmmirror.com/element-plus/-/element-plus-2.2.9.tgz" + integrity sha512-jYbL0JkCdv95rkT6trZJjCAizLPySa0qcd2cgq+57SKQnCZAcNDDq4GbTuFRnNavdoeCJnuM3HIficTIUpsMOQ== + dependencies: + "@ctrl/tinycolor" "^3.4.1" + "@element-plus/icons-vue" "^2.0.6" + "@floating-ui/dom" "^0.5.4" + "@popperjs/core" "npm:@sxzz/popperjs-es@^2.11.7" + "@types/lodash" "^4.14.182" + "@types/lodash-es" "^4.17.6" + "@vueuse/core" "^8.7.5" + async-validator "^4.2.5" + dayjs "^1.11.3" + escape-html "^1.0.3" + lodash "^4.17.21" + lodash-es "^4.17.21" + lodash-unified "^1.0.2" + memoize-one "^6.0.0" + normalize-wheel-es "^1.1.2" + +element-resize-detector@^1.2.1: + version "1.2.4" + resolved "https://registry.npmjs.org/element-resize-detector/-/element-resize-detector-1.2.4.tgz" + integrity sha512-Fl5Ftk6WwXE0wqCgNoseKWndjzZlDCwuPTcoVZfCP9R3EHQF8qUtr3YUPNETegRBOKqQKPW3n4kiIWngGi8tKg== + dependencies: + batch-processor "1.0.0" + +es5-ext@^0.10.35, es5-ext@^0.10.50, es5-ext@~0.10.14: + version "0.10.61" + resolved "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.61.tgz" + integrity sha512-yFhIqQAzu2Ca2I4SE2Au3rxVfmohU9Y7wqGR+s7+H7krk26NXhIRAZDgqd6xqjCEFUomDEA3/Bo/7fKmIkW1kA== + dependencies: + es6-iterator "^2.0.3" + es6-symbol "^3.1.3" + next-tick "^1.1.0" + +es6-iterator@^2.0.3: + version "2.0.3" + resolved "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz" + integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c= + dependencies: + d "1" + es5-ext "^0.10.35" + es6-symbol "^3.1.1" + +es6-symbol@^3.1.1, es6-symbol@^3.1.3: + version "3.1.3" + resolved "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz" + integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA== + dependencies: + d "^1.0.1" + ext "^1.1.2" + +esbuild-android-64@0.14.39: + version "0.14.39" + resolved "https://registry.npmmirror.com/esbuild-android-64/-/esbuild-android-64-0.14.39.tgz#09f12a372eed9743fd77ff6d889ac14f7b340c21" + integrity sha512-EJOu04p9WgZk0UoKTqLId9VnIsotmI/Z98EXrKURGb3LPNunkeffqQIkjS2cAvidh+OK5uVrXaIP229zK6GvhQ== + +esbuild-android-arm64@0.14.39: + version "0.14.39" + resolved "https://registry.npmmirror.com/esbuild-android-arm64/-/esbuild-android-arm64-0.14.39.tgz#f608d00ea03fe26f3b1ab92a30f99220390f3071" + integrity sha512-+twajJqO7n3MrCz9e+2lVOnFplRsaGRwsq1KL/uOy7xK7QdRSprRQcObGDeDZUZsacD5gUkk6OiHiYp6RzU3CA== + +esbuild-darwin-64@0.14.39: + version "0.14.39" + resolved "https://registry.npmmirror.com/esbuild-darwin-64/-/esbuild-darwin-64-0.14.39.tgz#31528daa75b4c9317721ede344195163fae3e041" + integrity sha512-ImT6eUw3kcGcHoUxEcdBpi6LfTRWaV6+qf32iYYAfwOeV+XaQ/Xp5XQIBiijLeo+LpGci9M0FVec09nUw41a5g== + +esbuild-darwin-arm64@0.14.39: + version "0.14.39" + resolved "https://registry.npmmirror.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.39.tgz#247f770d86d90a215fa194f24f90e30a0bd97245" + integrity sha512-/fcQ5UhE05OiT+bW5v7/up1bDsnvaRZPJxXwzXsMRrr7rZqPa85vayrD723oWMT64dhrgWeA3FIneF8yER0XTw== + +esbuild-freebsd-64@0.14.39: + version "0.14.39" + resolved "https://registry.npmmirror.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.39.tgz#479414d294905055eb396ebe455ed42213284ee0" + integrity sha512-oMNH8lJI4wtgN5oxuFP7BQ22vgB/e3Tl5Woehcd6i2r6F3TszpCnNl8wo2d/KvyQ4zvLvCWAlRciumhQg88+kQ== + +esbuild-freebsd-arm64@0.14.39: + version "0.14.39" + resolved "https://registry.npmmirror.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.39.tgz#cedeb10357c88533615921ae767a67dc870a474c" + integrity sha512-1GHK7kwk57ukY2yI4ILWKJXaxfr+8HcM/r/JKCGCPziIVlL+Wi7RbJ2OzMcTKZ1HpvEqCTBT/J6cO4ZEwW4Ypg== + +esbuild-linux-32@0.14.39: + version "0.14.39" + resolved "https://registry.npmmirror.com/esbuild-linux-32/-/esbuild-linux-32-0.14.39.tgz#d9f008c4322d771f3958f59c1eee5a05cdf92485" + integrity sha512-g97Sbb6g4zfRLIxHgW2pc393DjnkTRMeq3N1rmjDUABxpx8SjocK4jLen+/mq55G46eE2TA0MkJ4R3SpKMu7dg== + +esbuild-linux-64@0.14.39: + version "0.14.39" + resolved "https://registry.npmmirror.com/esbuild-linux-64/-/esbuild-linux-64-0.14.39.tgz#ba58d7f66858913aeb1ab5c6bde1bbd824731795" + integrity sha512-4tcgFDYWdI+UbNMGlua9u1Zhu0N5R6u9tl5WOM8aVnNX143JZoBZLpCuUr5lCKhnD0SCO+5gUyMfupGrHtfggQ== + +esbuild-linux-arm64@0.14.39: + version "0.14.39" + resolved "https://registry.npmmirror.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.39.tgz#708785a30072702b5b1c16b65cf9c25c51202529" + integrity sha512-23pc8MlD2D6Px1mV8GMglZlKgwgNKAO8gsgsLLcXWSs9lQsCYkIlMo/2Ycfo5JrDIbLdwgP8D2vpfH2KcBqrDQ== + +esbuild-linux-arm@0.14.39: + version "0.14.39" + resolved "https://registry.npmmirror.com/esbuild-linux-arm/-/esbuild-linux-arm-0.14.39.tgz#4e8b5deaa7ab60d0d28fab131244ef82b40684f4" + integrity sha512-t0Hn1kWVx5UpCzAJkKRfHeYOLyFnXwYynIkK54/h3tbMweGI7dj400D1k0Vvtj2u1P+JTRT9tx3AjtLEMmfVBQ== + +esbuild-linux-mips64le@0.14.39: + version "0.14.39" + resolved "https://registry.npmmirror.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.39.tgz#6f3bf3023f711084e5a1e8190487d2020f39f0f7" + integrity sha512-epwlYgVdbmkuRr5n4es3B+yDI0I2e/nxhKejT9H0OLxFAlMkeQZxSpxATpDc9m8NqRci6Kwyb/SfmD1koG2Zuw== + +esbuild-linux-ppc64le@0.14.39: + version "0.14.39" + resolved "https://registry.npmmirror.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.39.tgz#900e718a4ea3f6aedde8424828eeefdd4b48d4b9" + integrity sha512-W/5ezaq+rQiQBThIjLMNjsuhPHg+ApVAdTz2LvcuesZFMsJoQAW2hutoyg47XxpWi7aEjJGrkS26qCJKhRn3QQ== + +esbuild-linux-riscv64@0.14.39: + version "0.14.39" + resolved "https://registry.npmmirror.com/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.39.tgz#dcbff622fa37047a75d2ff7a1d8d2949d80277e4" + integrity sha512-IS48xeokcCTKeQIOke2O0t9t14HPvwnZcy+5baG13Z1wxs9ZrC5ig5ypEQQh4QMKxURD5TpCLHw2W42CLuVZaA== + +esbuild-linux-s390x@0.14.39: + version "0.14.39" + resolved "https://registry.npmmirror.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.39.tgz#3f725a7945b419406c99d93744b28552561dcdfd" + integrity sha512-zEfunpqR8sMomqXhNTFEKDs+ik7HC01m3M60MsEjZOqaywHu5e5682fMsqOlZbesEAAaO9aAtRBsU7CHnSZWyA== + +esbuild-netbsd-64@0.14.39: + version "0.14.39" + resolved "https://registry.npmmirror.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.39.tgz#e10e40b6a765798b90d4eb85901cc85c8b7ff85e" + integrity sha512-Uo2suJBSIlrZCe4E0k75VDIFJWfZy+bOV6ih3T4MVMRJh1lHJ2UyGoaX4bOxomYN3t+IakHPyEoln1+qJ1qYaA== + +esbuild-openbsd-64@0.14.39: + version "0.14.39" + resolved "https://registry.npmmirror.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.39.tgz#935ec143f75ce10bd9cdb1c87fee00287eb0edbc" + integrity sha512-secQU+EpgUPpYjJe3OecoeGKVvRMLeKUxSMGHnK+aK5uQM3n1FPXNJzyz1LHFOo0WOyw+uoCxBYdM4O10oaCAA== + +esbuild-sunos-64@0.14.39: + version "0.14.39" + resolved "https://registry.npmmirror.com/esbuild-sunos-64/-/esbuild-sunos-64-0.14.39.tgz#0e7aa82b022a2e6d55b0646738b2582c2d72c3c0" + integrity sha512-qHq0t5gePEDm2nqZLb+35p/qkaXVS7oIe32R0ECh2HOdiXXkj/1uQI9IRogGqKkK+QjDG+DhwiUw7QoHur/Rwg== + +esbuild-windows-32@0.14.39: + version "0.14.39" + resolved "https://registry.npmmirror.com/esbuild-windows-32/-/esbuild-windows-32-0.14.39.tgz#3f1538241f31b538545f4b5841b248cac260fa35" + integrity sha512-XPjwp2OgtEX0JnOlTgT6E5txbRp6Uw54Isorm3CwOtloJazeIWXuiwK0ONJBVb/CGbiCpS7iP2UahGgd2p1x+Q== + +esbuild-windows-64@0.14.39: + version "0.14.39" + resolved "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.39.tgz" + integrity sha512-E2wm+5FwCcLpKsBHRw28bSYQw0Ikxb7zIMxw3OPAkiaQhLVr3dnVO8DofmbWhhf6b97bWzg37iSZ45ZDpLw7Ow== + +esbuild-windows-arm64@0.14.39: + version "0.14.39" + resolved "https://registry.npmmirror.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.39.tgz#00268517e665b33c89778d61f144e4256b39f631" + integrity sha512-sBZQz5D+Gd0EQ09tZRnz/PpVdLwvp/ufMtJ1iDFYddDaPpZXKqPyaxfYBLs3ueiaksQ26GGa7sci0OqFzNs7KA== + +esbuild@^0.14.27: + version "0.14.39" + resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.14.39.tgz" + integrity sha512-2kKujuzvRWYtwvNjYDY444LQIA3TyJhJIX3Yo4+qkFlDDtGlSicWgeHVJqMUP/2sSfH10PGwfsj+O2ro1m10xQ== + optionalDependencies: + esbuild-android-64 "0.14.39" + esbuild-android-arm64 "0.14.39" + esbuild-darwin-64 "0.14.39" + esbuild-darwin-arm64 "0.14.39" + esbuild-freebsd-64 "0.14.39" + esbuild-freebsd-arm64 "0.14.39" + esbuild-linux-32 "0.14.39" + esbuild-linux-64 "0.14.39" + esbuild-linux-arm "0.14.39" + esbuild-linux-arm64 "0.14.39" + esbuild-linux-mips64le "0.14.39" + esbuild-linux-ppc64le "0.14.39" + esbuild-linux-riscv64 "0.14.39" + esbuild-linux-s390x "0.14.39" + esbuild-netbsd-64 "0.14.39" + esbuild-openbsd-64 "0.14.39" + esbuild-sunos-64 "0.14.39" + esbuild-windows-32 "0.14.39" + esbuild-windows-64 "0.14.39" + esbuild-windows-arm64 "0.14.39" + +escape-html@^1.0.3: + version "1.0.3" + resolved "https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz" + integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +eslint-plugin-vue@^9.1.0: + version "9.1.0" + resolved "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.1.0.tgz" + integrity sha512-EPCeInPicQ/YyfOWJDr1yfEeSNoFCMzUus107lZyYi37xejdOolNzS5MXGXp8+9bkoKZMdv/1AcZzQebME6r+g== + dependencies: + eslint-utils "^3.0.0" + natural-compare "^1.4.0" + nth-check "^2.0.1" + postcss-selector-parser "^6.0.9" + semver "^7.3.5" + vue-eslint-parser "^9.0.1" + xml-name-validator "^4.0.0" + +eslint-scope@^5.1.1: + version "5.1.1" + resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + dependencies: + esrecurse "^4.3.0" + estraverse "^4.1.1" + +eslint-scope@^7.1.1: + version "7.1.1" + resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz" + integrity sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw== + dependencies: + esrecurse "^4.3.0" + estraverse "^5.2.0" + +eslint-utils@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz" + integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== + dependencies: + eslint-visitor-keys "^2.0.0" + +eslint-visitor-keys@^2.0.0: + version "2.1.0" + resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz" + integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== + +eslint-visitor-keys@^3.3.0: + version "3.3.0" + resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz" + integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== + +eslint@^8.17.0: + version "8.17.0" + resolved "https://registry.npmjs.org/eslint/-/eslint-8.17.0.tgz" + integrity sha512-gq0m0BTJfci60Fz4nczYxNAlED+sMcihltndR8t9t1evnU/azx53x3t2UHXC/uRjcbvRw/XctpaNygSTcQD+Iw== + dependencies: + "@eslint/eslintrc" "^1.3.0" + "@humanwhocodes/config-array" "^0.9.2" + ajv "^6.10.0" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.3.2" + doctrine "^3.0.0" + escape-string-regexp "^4.0.0" + eslint-scope "^7.1.1" + eslint-utils "^3.0.0" + eslint-visitor-keys "^3.3.0" + espree "^9.3.2" + esquery "^1.4.0" + esutils "^2.0.2" + fast-deep-equal "^3.1.3" + file-entry-cache "^6.0.1" + functional-red-black-tree "^1.0.1" + glob-parent "^6.0.1" + globals "^13.15.0" + ignore "^5.2.0" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + js-yaml "^4.1.0" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.4.1" + lodash.merge "^4.6.2" + minimatch "^3.1.2" + natural-compare "^1.4.0" + optionator "^0.9.1" + regexpp "^3.2.0" + strip-ansi "^6.0.1" + strip-json-comments "^3.1.0" + text-table "^0.2.0" + v8-compile-cache "^2.0.3" + +espree@^9.3.1, espree@^9.3.2: + version "9.3.2" + resolved "https://registry.npmjs.org/espree/-/espree-9.3.2.tgz" + integrity sha512-D211tC7ZwouTIuY5x9XnS0E9sWNChB7IYKX/Xp5eQj3nFXhqmiUDB9q27y76oFl8jTg3pXcQx/bpxMfs3CIZbA== + dependencies: + acorn "^8.7.1" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^3.3.0" + +esquery@^1.4.0: + version "1.4.0" + resolved "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz" + integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +estraverse@^5.1.0, estraverse@^5.2.0: + version "5.3.0" + resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +estree-walker@^2.0.2: + version "2.0.2" + resolved "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz" + integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +event-emitter@^0.3.5: + version "0.3.5" + resolved "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz" + integrity sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk= + dependencies: + d "1" + es5-ext "~0.10.14" + +ext@^1.1.2: + version "1.6.0" + resolved "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz" + integrity sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg== + dependencies: + type "^2.5.0" + +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-glob@^3.2.9: + version "3.2.11" + resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz" + integrity sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-levenshtein@^2.0.6: + version "2.0.6" + resolved "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz" + integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= + +fastq@^1.6.0: + version "1.13.0" + resolved "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz" + integrity sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw== + dependencies: + reusify "^1.0.4" + +file-entry-cache@^6.0.1: + version "6.0.1" + resolved "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz" + integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== + dependencies: + flat-cache "^3.0.4" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +flat-cache@^3.0.4: + version "3.0.4" + resolved "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz" + integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== + dependencies: + flatted "^3.1.0" + rimraf "^3.0.2" + +flatted@^3.1.0: + version "3.2.5" + resolved "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz" + integrity sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg== + +follow-redirects@^1.14.9: + version "1.15.0" + resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.0.tgz" + integrity sha512-aExlJShTV4qOUOL7yF1U5tvLCB0xQuudbf6toyYA0E/acBNw71mvjFTnLaRp50aQaYocMR0a/RMMBIHeZnGyjQ== + +form-data@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz" + integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + +frac@~1.1.2: + version "1.1.2" + resolved "https://registry.npmmirror.com/frac/-/frac-1.1.2.tgz" + integrity sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA== + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + +fsevents@~2.3.2: + version "2.3.2" + resolved "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +functional-red-black-tree@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz" + integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= + +glob-parent@^5.1.2, glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob-parent@^6.0.1: + version "6.0.2" + resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + +glob@^7.1.3: + version "7.2.3" + resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + +globals@^13.15.0: + version "13.15.0" + resolved "https://registry.npmjs.org/globals/-/globals-13.15.0.tgz" + integrity sha512-bpzcOlgDhMG070Av0Vy5Owklpv1I6+j96GhUI7Rh7IzDCKLzboflLrrfqMu8NquDbiR4EOQk7XzJwqVJxicxog== + dependencies: + type-fest "^0.20.2" + +globby@^11.1.0: + version "11.1.0" + resolved "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz" + integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.2.9" + ignore "^5.2.0" + merge2 "^1.4.1" + slash "^3.0.0" + +good-listener@^1.2.2: + version "1.2.2" + resolved "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz" + integrity sha1-1TswzfkxPf+33JoNR3CWqm0UXFA= + dependencies: + delegate "^3.1.2" + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/has/-/has-1.0.3.tgz" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +html-void-elements@^2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/html-void-elements/-/html-void-elements-2.0.1.tgz" + integrity sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A== + +i18next@^20.4.0: + version "20.6.1" + resolved "https://registry.npmjs.org/i18next/-/i18next-20.6.1.tgz" + integrity sha512-yCMYTMEJ9ihCwEQQ3phLo7I/Pwycf8uAx+sRHwwk5U9Aui/IZYgQRyMqXafQOw5QQ7DM1Z+WyEXWIqSuJHhG2A== + dependencies: + "@babel/runtime" "^7.12.0" + +ignore@^5.2.0: + version "5.2.0" + resolved "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz" + integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== + +immer@^9.0.6: + version "9.0.14" + resolved "https://registry.npmjs.org/immer/-/immer-9.0.14.tgz" + integrity sha512-ubBeqQutOSLIFCUBN03jGeOS6a3DoYlSYwYJTa+gSKEZKU5redJIqkIdZ3JVv/4RZpfcXdAWH5zCNLWPRv2WDw== + +immutable@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/immutable/-/immutable-4.0.0.tgz" + integrity sha512-zIE9hX70qew5qTUjSS7wi1iwj/l7+m54KWU247nhM3v806UdGj1yDndXj+IOYxxtW9zyLI+xqFNZjTuDaLUqFw== + +import-fresh@^3.0.0, import-fresh@^3.2.1: + version "3.3.0" + resolved "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz" + integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2: + version "2.0.4" + resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-core-module@^2.8.1: + version "2.9.0" + resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz" + integrity sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A== + dependencies: + has "^1.0.3" + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" + integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-hotkey@^0.2.0: + version "0.2.0" + resolved "https://registry.npmjs.org/is-hotkey/-/is-hotkey-0.2.0.tgz" + integrity sha512-UknnZK4RakDmTgz4PI1wIph5yxSs/mvChWs9ifnlXsKuXgWmOkY/hAE0H/k2MIqH0RlRye0i1oC07MCRSD28Mw== + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-plain-object@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz" + integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q== + +is-url@^1.2.4: + version "1.2.4" + resolved "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz" + integrity sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + +js-base64@^3.7.2: + version "3.7.2" + resolved "https://registry.npmmirror.com/js-base64/-/js-base64-3.7.2.tgz#816d11d81a8aff241603d19ce5761e13e41d7745" + integrity sha512-NnRs6dsyqUXejqk/yv2aiXlAvOs56sLkX6nUdeaNezI5LFFLlsZjOThmwnrcwh5ZZRwZlCMnVAY3CvhIhoVEKQ== + +js-cookie@^3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.1.tgz" + integrity sha512-+0rgsUXZu4ncpPxRL+lNEptWMOWl9etvPHc/koSRp6MPwpRYAhmk0dUG00J4bxVV3r9uUzfo24wW0knS07SKSw== + +js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +json-bigint@^1.0.0: + version "1.0.0" + resolved "https://registry.npmmirror.com/json-bigint/-/json-bigint-1.0.0.tgz" + integrity sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ== + dependencies: + bignumber.js "^9.0.0" + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz" + integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= + +jsplumb@^2.15.6: + version "2.15.6" + resolved "https://registry.npmjs.org/jsplumb/-/jsplumb-2.15.6.tgz" + integrity sha512-sIpbpz5eMVM+vV+MQzFCidlaa1RsknrQs6LOTKYDjYUDdTAi2AN2bFi94TxB33TifcIsRNV1jebcaxg0tCoPzg== + +klona@^2.0.4: + version "2.0.5" + resolved "https://registry.npmjs.org/klona/-/klona-2.0.5.tgz" + integrity sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ== + +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +lodash-es@^4.17.21: + version "4.17.21" + resolved "https://registry.npmmirror.com/lodash-es/-/lodash-es-4.17.21.tgz" + integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw== + +lodash-unified@^1.0.2: + version "1.0.2" + resolved "https://registry.npmmirror.com/lodash-unified/-/lodash-unified-1.0.2.tgz" + integrity sha512-OGbEy+1P+UT26CYi4opY4gebD8cWRDxAT6MAObIVQMiqYdxZr1g3QHWCToVsm31x2NkLS4K3+MC2qInaRMa39g== + +lodash.camelcase@^4.3.0: + version "4.3.0" + resolved "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz" + integrity sha1-soqmKIorn8ZRA1x3EfZathkDMaY= + +lodash.clonedeep@^4.5.0: + version "4.5.0" + resolved "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz" + integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8= + +lodash.debounce@^4.0.8: + version "4.0.8" + resolved "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz" + integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= + +lodash.foreach@^4.5.0: + version "4.5.0" + resolved "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz" + integrity sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM= + +lodash.isequal@^4.5.0: + version "4.5.0" + resolved "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz" + integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA= + +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + +lodash.throttle@^4.1.1: + version "4.1.1" + resolved "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz" + integrity sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ= + +lodash.toarray@^4.4.0: + version "4.4.0" + resolved "https://registry.npmjs.org/lodash.toarray/-/lodash.toarray-4.4.0.tgz" + integrity sha1-JMS/zWsvuji/0FlNsRedjptlZWE= + +lodash@^4.17.21: + version "4.17.21" + resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + +magic-string@^0.25.7: + version "0.25.9" + resolved "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz" + integrity sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ== + dependencies: + sourcemap-codec "^1.4.8" + +memoize-one@^6.0.0: + version "6.0.0" + resolved "https://registry.npmmirror.com/memoize-one/-/memoize-one-6.0.0.tgz" + integrity sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw== + +merge2@^1.3.0, merge2@^1.4.1: + version "1.4.1" + resolved "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +micromatch@^4.0.4: + version "4.0.5" + resolved "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + dependencies: + braces "^3.0.2" + picomatch "^2.3.1" + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-match@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/mime-match/-/mime-match-1.0.2.tgz" + integrity sha1-P4fDHprxpf1IX7nbE0Qosju7e6g= + dependencies: + wildcard "^1.1.0" + +mime-types@^2.1.12: + version "2.1.35" + resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2: + version "3.1.2" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +mitt@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/mitt/-/mitt-2.1.0.tgz" + integrity sha512-ILj2TpLiysu2wkBbWjAmww7TkZb65aiQO+DkVdUTBpBXq+MHYiETENkKFMtsJZX1Lf4pe4QOrTSjIfUwN5lRdg== + +mitt@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/mitt/-/mitt-3.0.0.tgz" + integrity sha512-7dX2/10ITVyqh4aOSVI9gdape+t9l2/8QxHrFmUXu4EEUpdlxl6RudZUPZoc+zuY2hk1j7XxVroIVIan/pD/SQ== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +namespace-emitter@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/namespace-emitter/-/namespace-emitter-2.0.1.tgz" + integrity sha512-N/sMKHniSDJBjfrkbS/tpkPj4RAbvW3mr8UAzvlMHyun93XEm83IAvhWtJVHo+RHn/oO8Job5YN4b+wRjSVp5g== + +nanoid@^3.1.25, nanoid@^3.2.0, nanoid@^3.3.4: + version "3.3.4" + resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz" + integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw== + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz" + integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= + +neo-async@^2.6.2: + version "2.6.2" + resolved "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== + +next-tick@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz" + integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ== + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +normalize-wheel-es@^1.1.2: + version "1.1.2" + resolved "https://registry.npmmirror.com/normalize-wheel-es/-/normalize-wheel-es-1.1.2.tgz" + integrity sha512-scX83plWJXYH1J4+BhAuIHadROzxX0UBF3+HuZNY2Ks8BciE7tSTQ+5JhTsvzjaO0/EJdm4JBGrfObKxFf3Png== + +nprogress@^0.2.0: + version "0.2.0" + resolved "https://registry.npmjs.org/nprogress/-/nprogress-0.2.0.tgz" + integrity sha1-y480xTIT2JVyP8urkH6UIq28r7E= + +nth-check@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz" + integrity sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w== + dependencies: + boolbase "^1.0.0" + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + +optionator@^0.9.1: + version "0.9.1" + resolved "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz" + integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== + dependencies: + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + word-wrap "^1.2.3" + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + +picocolors@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz" + integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== + +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +pinia-plugin-persistedstate@^2.1.1: + version "2.1.1" + resolved "https://registry.npmmirror.com/pinia-plugin-persistedstate/-/pinia-plugin-persistedstate-2.1.1.tgz" + integrity sha512-HUgsU5IRtM75eAQiIqzT3p1oPEuYH1/B2ipTMU++yE+FV0LkHaBswdKXs0RMWYCmugO8s62oxLTh/N1dLNp+5A== + +pinia@^2.0.14: + version "2.0.14" + resolved "https://registry.npmjs.org/pinia/-/pinia-2.0.14.tgz" + integrity sha512-0nPuZR4TetT/WcLN+feMSjWJku3SQU7dBbXC6uw+R6FLQJCsg+/0pzXyD82T1FmAYe0lsx+jnEDQ1BLgkRKlxA== + dependencies: + "@vue/devtools-api" "^6.1.4" + vue-demi "*" + +postcss-selector-parser@^6.0.9: + version "6.0.10" + resolved "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz" + integrity sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w== + dependencies: + cssesc "^3.0.0" + util-deprecate "^1.0.2" + +postcss@^8.1.10, postcss@^8.4.13: + version "8.4.14" + resolved "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz" + integrity sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig== + dependencies: + nanoid "^3.3.4" + picocolors "^1.0.0" + source-map-js "^1.0.2" + +preact@^10.5.13: + version "10.7.2" + resolved "https://registry.npmjs.org/preact/-/preact-10.7.2.tgz" + integrity sha512-GLjn0I3r6ka+NvxJUppsVFqb4V0qDTEHT/QxHlidPuClGaxF/4AI2Qti4a0cv3XMh5n1+D3hLScW10LRIm5msQ== + +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + +prettier@^2.6.2: + version "2.6.2" + resolved "https://registry.npmjs.org/prettier/-/prettier-2.6.2.tgz" + integrity sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew== + +print-js@^1.6.0: + version "1.6.0" + resolved "https://registry.npmjs.org/print-js/-/print-js-1.6.0.tgz" + integrity sha512-BfnOIzSKbqGRtO4o0rnj/K3681BSd2QUrsIZy/+WdCIugjIswjmx3lDEZpXB2ruGf9d4b3YNINri81+J0FsBWg== + +prismjs@^1.23.0: + version "1.28.0" + resolved "https://registry.npmjs.org/prismjs/-/prismjs-1.28.0.tgz" + integrity sha512-8aaXdYvl1F7iC7Xm1spqSaY/OJBpYW3v+KJ+F17iYxvdc8sfjW194COK5wVhMZX45tGteiBQgdvD/nhxcRwylw== + +punycode@^2.1.0: + version "2.1.1" + resolved "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + +qrcodejs2-fixes@^0.0.2: + version "0.0.2" + resolved "https://registry.npmjs.org/qrcodejs2-fixes/-/qrcodejs2-fixes-0.0.2.tgz" + integrity sha512-wMUXYMOixAEJlLnjk5MbLiFaz0gQObWYm/TIFWB5+j7sTY5gPyr09Cx1EpcLYbsgfFdN3wHjrKAhZofTuCBGhg== + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +regenerator-runtime@^0.13.4: + version "0.13.9" + resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz" + integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== + +regexpp@^3.2.0: + version "3.2.0" + resolved "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz" + integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +resolve@^1.22.0: + version "1.22.0" + resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz" + integrity sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw== + dependencies: + is-core-module "^2.8.1" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +rollup@^2.59.0: + version "2.74.1" + resolved "https://registry.npmjs.org/rollup/-/rollup-2.74.1.tgz" + integrity sha512-K2zW7kV8Voua5eGkbnBtWYfMIhYhT9Pel2uhBk2WO5eMee161nPze/XRfvEQPFYz7KgrCCnmh2Wy0AMFLGGmMA== + optionalDependencies: + fsevents "~2.3.2" + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +sass-loader@^13.0.0: + version "13.0.0" + resolved "https://registry.npmjs.org/sass-loader/-/sass-loader-13.0.0.tgz" + integrity sha512-IHCFecI+rbPvXE2zO/mqdVFe8MU7ElGrwga9hh2H65Ru4iaBJAMRteum1c4Gsxi9Cq1FOtTEDd6+/AEYuQDM4Q== + dependencies: + klona "^2.0.4" + neo-async "^2.6.2" + +sass@^1.52.2: + version "1.52.2" + resolved "https://registry.npmjs.org/sass/-/sass-1.52.2.tgz" + integrity sha512-mfHB2VSeFS7sZlPv9YohB9GB7yWIgQNTGniQwfQ04EoQN0wsQEv7SwpCwy/x48Af+Z3vDeFXz+iuXM3HK/phZQ== + dependencies: + chokidar ">=3.0.0 <4.0.0" + immutable "^4.0.0" + source-map-js ">=0.6.2 <2.0.0" + +screenfull@^6.0.1: + version "6.0.1" + resolved "https://registry.npmjs.org/screenfull/-/screenfull-6.0.1.tgz" + integrity sha512-yzQW+j4zMUBQC51xxWaoDYjxOtl8Kn+xvue3p6v/fv2pIi1jH4AldgVLU8TBfFVgH2x3VXlf3+YiA/AYIPlaew== + +scroll-into-view-if-needed@^2.2.28: + version "2.2.29" + resolved "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.29.tgz" + integrity sha512-hxpAR6AN+Gh53AdAimHM6C8oTN1ppwVZITihix+WqalywBeFcQ6LdQP5ABNl26nX8GTEL7VT+b8lKpdqq65wXg== + dependencies: + compute-scroll-into-view "^1.0.17" + +select@^1.1.2: + version "1.1.2" + resolved "https://registry.npmjs.org/select/-/select-1.1.2.tgz" + integrity sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0= + +semver@^7.3.5, semver@^7.3.6, semver@^7.3.7: + version "7.3.7" + resolved "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz" + integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g== + dependencies: + lru-cache "^6.0.0" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +slate-history@^0.66.0: + version "0.66.0" + resolved "https://registry.npmjs.org/slate-history/-/slate-history-0.66.0.tgz" + integrity sha512-6MWpxGQZiMvSINlCbMW43E2YBSVMCMCIwQfBzGssjWw4kb0qfvj0pIdblWNRQZD0hR6WHP+dHHgGSeVdMWzfng== + dependencies: + is-plain-object "^5.0.0" + +slate@^0.72.0: + version "0.72.8" + resolved "https://registry.npmjs.org/slate/-/slate-0.72.8.tgz" + integrity sha512-/nJwTswQgnRurpK+bGJFH1oM7naD5qDmHd89JyiKNT2oOKD8marW0QSBtuFnwEbL5aGCS8AmrhXQgNOsn4osAw== + dependencies: + immer "^9.0.6" + is-plain-object "^5.0.0" + tiny-warning "^1.0.3" + +snabbdom@^3.1.0: + version "3.5.0" + resolved "https://registry.npmjs.org/snabbdom/-/snabbdom-3.5.0.tgz" + integrity sha512-Ff5BKG18KrrPuskHJlA9aujPHqEabItaDl96l7ZZndF4zt5AYSczz7ZjjgQAX5IBd5cd25lw9NfgX21yVUJ+9g== + +sortablejs@^1.15.0: + version "1.15.0" + resolved "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.0.tgz" + integrity sha512-bv9qgVMjUMf89wAvM6AxVvS/4MX3sPeN0+agqShejLU5z5GX4C75ow1O2e5k4L6XItUyAK3gH6AxSbXrOM5e8w== + +"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz" + integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== + +source-map@0.6.1, source-map@^0.6.1: + version "0.6.1" + resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +sourcemap-codec@^1.4.8: + version "1.4.8" + resolved "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz" + integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== + +splitpanes@^3.1.1: + version "3.1.1" + resolved "https://registry.npmjs.org/splitpanes/-/splitpanes-3.1.1.tgz" + integrity sha512-VUkxDJfIGSvTM/fm/+OSrx8ha9URwE/9B8FPvfzoBuAxVELIHBWpsfnJXIXv77zVwuex//QQL4kTU9SDBPeHjA== + +ssf@~0.11.2: + version "0.11.2" + resolved "https://registry.npmmirror.com/ssf/-/ssf-0.11.2.tgz" + integrity sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g== + dependencies: + frac "~1.1.2" + +ssr-window@^3.0.0-alpha.1: + version "3.0.0" + resolved "https://registry.npmjs.org/ssr-window/-/ssr-window-3.0.0.tgz" + integrity sha512-q+8UfWDg9Itrg0yWK7oe5p/XRCJpJF9OBtXfOPgSJl+u3Xd5KI328RUEvUqSMVM9CiQUEf1QdBzJMkYGErj9QA== + +strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz" + integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= + +tiny-emitter@^2.0.0: + version "2.1.0" + resolved "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz" + integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q== + +tiny-warning@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz" + integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +tslib@2.3.0, tslib@^2.1.0: + version "2.3.0" + resolved "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz" + integrity sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg== + +tslib@^1.8.1: + version "1.14.1" + resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + +tsutils@^3.21.0: + version "3.21.0" + resolved "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz" + integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== + dependencies: + tslib "^1.8.1" + +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + +type-fest@^0.20.2: + version "0.20.2" + resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz" + integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== + +type@^1.0.1: + version "1.2.0" + resolved "https://registry.npmjs.org/type/-/type-1.2.0.tgz" + integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== + +type@^2.5.0: + version "2.6.0" + resolved "https://registry.npmjs.org/type/-/type-2.6.0.tgz" + integrity sha512-eiDBDOmkih5pMbo9OqsqPRGMljLodLcwd5XD5JbtNB0o89xZAwynY9EdCDsJU7LtcVCClu9DvM7/0Ep1hYX3EQ== + +typescript@^4.7.3: + version "4.7.3" + resolved "https://registry.npmjs.org/typescript/-/typescript-4.7.3.tgz" + integrity sha512-WOkT3XYvrpXx4vMMqlD+8R8R37fZkjyLGlxavMc4iB8lrl8L0DeTcHbYgw/v0N/z9wAFsgBhcsF0ruoySS22mA== + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +util-deprecate@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + +v8-compile-cache@^2.0.3: + version "2.3.0" + resolved "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz" + integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== + +vite@^2.9.9: + version "2.9.9" + resolved "https://registry.npmjs.org/vite/-/vite-2.9.9.tgz" + integrity sha512-ffaam+NgHfbEmfw/Vuh6BHKKlI/XIAhxE5QSS7gFLIngxg171mg1P3a4LSRME0z2ZU1ScxoKzphkipcYwSD5Ew== + dependencies: + esbuild "^0.14.27" + postcss "^8.4.13" + resolve "^1.22.0" + rollup "^2.59.0" + optionalDependencies: + fsevents "~2.3.2" + +vue-clipboard3@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/vue-clipboard3/-/vue-clipboard3-2.0.0.tgz" + integrity sha512-Q9S7dzWGax7LN5iiSPcu/K1GGm2gcBBlYwmMsUc5/16N6w90cbKow3FnPmPs95sungns4yvd9/+JhbAznECS2A== + dependencies: + clipboard "^2.0.6" + +vue-demi@*: + version "0.13.11" + resolved "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.13.11.tgz" + integrity sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A== + +vue-eslint-parser@^9.0.1, vue-eslint-parser@^9.0.2: + version "9.0.2" + resolved "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.0.2.tgz" + integrity sha512-uCPQwTGjOtAYrwnU+76pYxalhjsh7iFBsHwBqDHiOPTxtICDaraO4Szw54WFTNZTAEsgHHzqFOu1mmnBOBRzDA== + dependencies: + debug "^4.3.4" + eslint-scope "^7.1.1" + eslint-visitor-keys "^3.3.0" + espree "^9.3.1" + esquery "^1.4.0" + lodash "^4.17.21" + semver "^7.3.6" + +vue-grid-layout@^3.0.0-beta1: + version "3.0.0-beta1" + resolved "https://registry.npmjs.org/vue-grid-layout/-/vue-grid-layout-3.0.0-beta1.tgz" + integrity sha512-MsW0yfYNtnAO/uDhfZvkP6effxSJxvhAFbIL37x6Rn3vW9xf0WHVefKaSbQMLpSq3mXnR6ut0pg2Cd5lqIIZzg== + dependencies: + "@interactjs/actions" "^1.10.2" + "@interactjs/auto-start" "^1.10.2" + "@interactjs/dev-tools" "^1.10.2" + "@interactjs/interactjs" "^1.10.2" + "@interactjs/modifiers" "^1.10.2" + element-resize-detector "^1.2.1" + mitt "^2.1.0" + +vue-i18n@^9.1.10: + version "9.1.10" + resolved "https://registry.npmjs.org/vue-i18n/-/vue-i18n-9.1.10.tgz" + integrity sha512-jpr7gV5KPk4n+sSPdpZT8Qx3XzTcNDWffRlHV/cT2NUyEf+sEgTTmLvnBAibjOFJ0zsUyZlVTAWH5DDnYep+1g== + dependencies: + "@intlify/core-base" "9.1.10" + "@intlify/shared" "9.1.10" + "@intlify/vue-devtools" "9.1.10" + "@vue/devtools-api" "^6.0.0-beta.7" + +vue-router@^4.0.15: + version "4.0.15" + resolved "https://registry.npmjs.org/vue-router/-/vue-router-4.0.15.tgz" + integrity sha512-xa+pIN9ZqORdIW1MkN2+d9Ui2pCM1b/UMgwYUCZOiFYHAvz/slKKBDha8DLrh5aCG/RibtrpyhKjKOZ85tYyWg== + dependencies: + "@vue/devtools-api" "^6.0.0" + +vue@^3.2.36: + version "3.2.36" + resolved "https://registry.npmjs.org/vue/-/vue-3.2.36.tgz" + integrity sha512-5yTXmrE6gW8IQgttzHW5bfBiFA6mx35ZXHjGLDmKYzW6MMmYvCwuKybANRepwkMYeXw2v1buGg3/lPICY5YlZw== + dependencies: + "@vue/compiler-dom" "3.2.36" + "@vue/compiler-sfc" "3.2.36" + "@vue/runtime-dom" "3.2.36" + "@vue/server-renderer" "3.2.36" + "@vue/shared" "3.2.36" + +wangeditor@^4.7.15: + version "4.7.15" + resolved "https://registry.npmmirror.com/wangeditor/-/wangeditor-4.7.15.tgz" + integrity sha512-aPTdREd8BxXVyJ5MI+LU83FQ7u1EPd341iXIorRNYSOvoimNoZ4nPg+yn3FGbB93/owEa6buLw8wdhYnMCJQLg== + dependencies: + "@babel/runtime" "^7.11.2" + "@babel/runtime-corejs3" "^7.11.2" + tslib "^2.1.0" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.npmjs.org/which/-/which-2.0.2.tgz" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wildcard@^1.1.0: + version "1.1.2" + resolved "https://registry.npmjs.org/wildcard/-/wildcard-1.1.2.tgz" + integrity sha1-pwIEUwhNjNLv5wup02liY94XEKU= + +wmf@~1.0.1: + version "1.0.2" + resolved "https://registry.npmmirror.com/wmf/-/wmf-1.0.2.tgz" + integrity sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw== + +word-wrap@^1.2.3: + version "1.2.3" + resolved "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz" + integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== + +word@~0.3.0: + version "0.3.0" + resolved "https://registry.npmmirror.com/word/-/word-0.3.0.tgz" + integrity sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA== + +wrappy@1: + version "1.0.2" + resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + +xlsx@^0.18.5: + version "0.18.5" + resolved "https://registry.npmmirror.com/xlsx/-/xlsx-0.18.5.tgz" + integrity sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ== + dependencies: + adler-32 "~1.3.0" + cfb "~1.2.1" + codepage "~1.15.0" + crc-32 "~1.2.1" + ssf "~0.11.2" + wmf "~1.0.1" + word "~0.3.0" + +xml-name-validator@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz" + integrity sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +zrender@5.3.2, zrender@^5.1.1: + version "5.3.2" + resolved "https://registry.npmmirror.com/zrender/-/zrender-5.3.2.tgz" + integrity sha512-8IiYdfwHj2rx0UeIGZGGU4WEVSDEdeVCaIg/fomejg1Xu6OifAL1GVzIPHg2D+MyUkbNgPWji90t0a8IDk+39w== + dependencies: + tslib "2.3.0" -- Gitblit v1.9.2