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}&params=${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(&#45;&#45;el-border-color);-->
+<!--  border-radius: 6px;-->
+<!--  cursor: pointer;-->
+<!--  position: relative;-->
+<!--  overflow: hidden;-->
+<!--  transition: var(&#45;&#45;el-transition-duration-fast);-->
+<!--}-->
+
+<!--.avatar-uploader .el-upload:hover {-->
+<!--  border-color: var(&#45;&#45;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