| @ -1,18 +1,25 @@ | |||||
| pipeline { | podTemplate { | ||||
|     agent { |     node('pod-templ-jenkins-slave-common') { | ||||
|         node{ | 		 | ||||
|             label 'jnlp-slave' | 		env.IMAGE_NAME = "${IOT_IMAGES_REGISTRY}/${IOT}/${JOB_NAME}" | ||||
|     } | 		env.IMAGE_NAME_SHORT = "${IOT}/${JOB_NAME}" | ||||
|     } |         env.CODE_ADDR = "${GIT_ADDRESS}/free-sun/Inspection.git" | ||||
|  | 		 | ||||
|  | 	    stage('Run shell') {  | ||||
|  | 		    git branch: 'master', credentialsId: 'gitea-builder', url: "${CODE_ADDR}" | ||||
| 		     | 		     | ||||
|     stages { | 		    container('image-builder') {			     | ||||
|         stage('巡检 api ......') { | 				sh''' | ||||
|             steps { | 					pwd | ||||
|                buildName "#${BUILD_NUMBER} ~/smartcity/${JOB_NAME}:${IMAGE_VERSION}" | 					ls -al | ||||
|                 buildDescription "harbor.anxinyun.cn/smartcity/${JOB_NAME}:${IMAGE_VERSION}" | 					 | ||||
|                 sh 'nerdctl build -t harbor.anxinyun.cn/smartcity/${JOB_NAME}:${IMAGE_VERSION} ./api' | 				    /kaniko/executor --context=${BUILD_WORKSPACE} --dockerfile=./api/Dockerfile --destination=${IMAGE_NAME}:${IMAGE_VERSION} --cache=false --cleanup  | ||||
| 				    sh 'nerdctl push harbor.anxinyun.cn/smartcity/${JOB_NAME}:${IMAGE_VERSION}' | 
 | ||||
|  | 			    '''			     | ||||
| 		    } | 		    } | ||||
|  | 			 | ||||
|  | 		    buildName "${IMAGE_NAME_SHORT}:${IMAGE_VERSION}" | ||||
|  | 		    buildDescription "${IMAGE_NAME}:${IMAGE_VERSION}"			 | ||||
| 		} | 		} | ||||
| 	} | 	} | ||||
| } | } | ||||
| @ -1,18 +1,25 @@ | |||||
| pipeline { | podTemplate { | ||||
|     agent { |     node('pod-templ-jenkins-slave-common') { | ||||
|         node{ | 		 | ||||
|             label 'jnlp-slave' | 		env.IMAGE_NAME = "${IOT_IMAGES_REGISTRY}/${IOT}/${JOB_NAME}" | ||||
|     } | 		env.IMAGE_NAME_SHORT = "${IOT}/${JOB_NAME}" | ||||
|     } |         env.CODE_ADDR = "${GIT_ADDRESS}/free-sun/Inspection.git" | ||||
|  | 		 | ||||
|  | 	    stage('Run shell') {  | ||||
|  | 		    git branch: 'master', credentialsId: 'gitea-builder', url: "${CODE_ADDR}" | ||||
| 		     | 		     | ||||
|     stages { | 		    container('image-builder') {			     | ||||
|         stage('巡检 web ......') { | 				sh''' | ||||
|             steps { | 					pwd | ||||
|                buildName "#${BUILD_NUMBER} ~/smartcity/${JOB_NAME}:${IMAGE_VERSION}" | 					ls -al | ||||
|                 buildDescription "harbor.anxinyun.cn/smartcity/${JOB_NAME}:${IMAGE_VERSION}" | 					 | ||||
|                 sh 'nerdctl build -t harbor.anxinyun.cn/smartcity/${JOB_NAME}:${IMAGE_VERSION} ./web' | 				    /kaniko/executor --context=${BUILD_WORKSPACE} --dockerfile=./web/Dockerfile --destination=${IMAGE_NAME}:${IMAGE_VERSION} --cache=false --cleanup  | ||||
| 				    sh 'nerdctl push harbor.anxinyun.cn/smartcity/${JOB_NAME}:${IMAGE_VERSION}' | 
 | ||||
|  | 			    '''			     | ||||
| 		    } | 		    } | ||||
|  | 			 | ||||
|  | 		    buildName "${IMAGE_NAME_SHORT}:${IMAGE_VERSION}" | ||||
|  | 		    buildDescription "${IMAGE_NAME}:${IMAGE_VERSION}"			 | ||||
| 		} | 		} | ||||
| 	} | 	} | ||||
| } | } | ||||
| After Width: | Height: | Size: 895 B | 
| After Width: | Height: | Size: 1.1 KiB | 
| After Width: | Height: | Size: 808 B | 
| After Width: | Height: | Size: 1.1 KiB | 
| After Width: | Height: | Size: 1.3 KiB | 
| After Width: | Height: | Size: 1.2 KiB | 
| After Width: | Height: | Size: 942 B | 
| After Width: | Height: | Size: 27 KiB | 
| After Width: | Height: | Size: 1.6 KiB | 
| After Width: | Height: | Size: 1.2 KiB | 
| After Width: | Height: | Size: 1.6 KiB | 
| After Width: | Height: | Size: 808 B | 
| After Width: | Height: | Size: 1.6 KiB | 
| @ -0,0 +1,168 @@ | |||||
|  | // package/riskManagement/riskCalendar/riskCalendar.js
 | ||||
|  | import * as echarts from '../components/ec-canvas/echarts'; | ||||
|  | 
 | ||||
|  | Page({ | ||||
|  |     initECharts(option) { | ||||
|  |         this.ecComponent.init((canvas, width, height, dpr) => { | ||||
|  |             const chart = echarts.init(canvas, null, { | ||||
|  |                 width: width, | ||||
|  |                 height: height, | ||||
|  |                 devicePixelRatio: dpr, | ||||
|  |             }); | ||||
|  |             chart.setOption(option); | ||||
|  |             this.chart = chart; | ||||
|  |             return chart; | ||||
|  |         }); | ||||
|  |     }, | ||||
|  |     initDeviceECharts(option) { | ||||
|  |         this.ecDeviceComponent.init((canvas, width, height, dpr) => { | ||||
|  |             const chart = echarts.init(canvas, null, { | ||||
|  |                 width: width, | ||||
|  |                 height: height, | ||||
|  |                 devicePixelRatio: dpr, | ||||
|  |             }); | ||||
|  |             chart.setOption(option); | ||||
|  |             this.chart = chart; | ||||
|  |             return chart; | ||||
|  |         }); | ||||
|  |     }, | ||||
|  |     /** | ||||
|  |      * 页面的初始数据 | ||||
|  |      */ | ||||
|  |     data: { | ||||
|  |         ec:{} | ||||
|  |     }, | ||||
|  |     navigator(e) { | ||||
|  |         wx.navigateTo({ | ||||
|  |           url: '/package/deviceBigdataGraph/statusDetail/statusDetail', | ||||
|  |         }) | ||||
|  |         console.log('xxxxxx',e) | ||||
|  |       }, | ||||
|  |     /** | ||||
|  |      * 生命周期函数--监听页面加载 | ||||
|  |      */ | ||||
|  |     onLoad(options) { | ||||
|  |         const that = this | ||||
|  |         that.ecComponent = that.selectComponent('#mychart-dom-pie'); | ||||
|  |         that.ecDeviceComponent=that.selectComponent('#mychart-device-pie'); | ||||
|  |         var option = { | ||||
|  |             backgroundColor: "#ffffff", | ||||
|  |             legend: { | ||||
|  |                 bottom: 10, | ||||
|  |                 left: 'center', | ||||
|  |             }, | ||||
|  |             series: [{ | ||||
|  |                 label: { | ||||
|  |                     normal: { | ||||
|  |                         fontSize: 14 | ||||
|  |                     } | ||||
|  |                 }, | ||||
|  |                 type: 'pie', | ||||
|  |                 center: ['50%', '50%'], | ||||
|  |                 radius: ['20%', '40%'], | ||||
|  |                 data: [{ | ||||
|  |                         name: '类型一', | ||||
|  |                         value: 1 | ||||
|  |                     }, | ||||
|  |                     { | ||||
|  |                         name: '类型二', | ||||
|  |                         value: 2 | ||||
|  |                     }, | ||||
|  |                     { | ||||
|  |                         name: '类型三', | ||||
|  |                         value: 3 | ||||
|  |                     }, | ||||
|  |                     { | ||||
|  |                         name: '类型四', | ||||
|  |                         value: 4 | ||||
|  |                     } | ||||
|  |                 ] | ||||
|  | 
 | ||||
|  |             }] | ||||
|  |         }; | ||||
|  |         var optionDevice = { | ||||
|  |             backgroundColor: "#ffffff", | ||||
|  |             legend: { | ||||
|  |                 bottom: 10, | ||||
|  |                 left: 'center', | ||||
|  |             }, | ||||
|  |             series: [{ | ||||
|  |                 label: { | ||||
|  |                     normal: { | ||||
|  |                         fontSize: 14 | ||||
|  |                     } | ||||
|  |                 }, | ||||
|  |                 type: 'pie', | ||||
|  |                 center: ['50%', '50%'], | ||||
|  |                 radius: ['20%', '40%'], | ||||
|  |                  | ||||
|  |                 data: [{ | ||||
|  |                         name: '正常', | ||||
|  |                         value: 1 | ||||
|  |                     }, | ||||
|  |                     { | ||||
|  |                         name: '未知', | ||||
|  |                         value: 2 | ||||
|  |                     }, | ||||
|  |                     { | ||||
|  |                         name: '异常', | ||||
|  |                         value: 3 | ||||
|  |                     }, | ||||
|  |                  | ||||
|  |                 ] | ||||
|  | 
 | ||||
|  |             }] | ||||
|  |         }; | ||||
|  |         that.initECharts(option); | ||||
|  |         that.initDeviceECharts(optionDevice); | ||||
|  |     }, | ||||
|  | 
 | ||||
|  |     /** | ||||
|  |      * 生命周期函数--监听页面初次渲染完成 | ||||
|  |      */ | ||||
|  |     onReady() { | ||||
|  | 
 | ||||
|  |     }, | ||||
|  | 
 | ||||
|  |     /** | ||||
|  |      * 生命周期函数--监听页面显示 | ||||
|  |      */ | ||||
|  |     onShow() { | ||||
|  | 
 | ||||
|  |     }, | ||||
|  | 
 | ||||
|  |     /** | ||||
|  |      * 生命周期函数--监听页面隐藏 | ||||
|  |      */ | ||||
|  |     onHide() { | ||||
|  | 
 | ||||
|  |     }, | ||||
|  | 
 | ||||
|  |     /** | ||||
|  |      * 生命周期函数--监听页面卸载 | ||||
|  |      */ | ||||
|  |     onUnload() { | ||||
|  | 
 | ||||
|  |     }, | ||||
|  | 
 | ||||
|  |     /** | ||||
|  |      * 页面相关事件处理函数--监听用户下拉动作 | ||||
|  |      */ | ||||
|  |     onPullDownRefresh() { | ||||
|  | 
 | ||||
|  |     }, | ||||
|  | 
 | ||||
|  |     /** | ||||
|  |      * 页面上拉触底事件的处理函数 | ||||
|  |      */ | ||||
|  |     onReachBottom() { | ||||
|  | 
 | ||||
|  |     }, | ||||
|  | 
 | ||||
|  |     /** | ||||
|  |      * 用户点击右上角分享 | ||||
|  |      */ | ||||
|  |     onShareAppMessage() { | ||||
|  | 
 | ||||
|  |     } | ||||
|  | }) | ||||
| @ -0,0 +1,11 @@ | |||||
|  | { | ||||
|  |     "navigationBarBackgroundColor": "#1979ff", | ||||
|  |     "navigationBarTextStyle": "white", | ||||
|  |     "navigationBarTitleText": "设备大数据图谱", | ||||
|  |     "enablePullDownRefresh": false, | ||||
|  |     "usingComponents": { | ||||
|  |       "ec-canvas": "../components/ec-canvas/ec-canvas", | ||||
|  |       "van-button": "@vant/weapp/button/index", | ||||
|  |       "van-progress": "@vant/weapp/progress/index" | ||||
|  |     } | ||||
|  |   } | ||||
| @ -0,0 +1,63 @@ | |||||
|  | <!--package/riskManagement/riskCalendar/riskCalendar.wxml--> | ||||
|  | <view class="container"> | ||||
|  |     <!--质保图谱--> | ||||
|  |     <view class="card"> | ||||
|  |         <image src="/images/shape3.png" class="imgStyle"></image> | ||||
|  |         <view class="top"> | ||||
|  |             <view style="display: flex; align-items: center;"> | ||||
|  |                 <image style="width: 30px; height: 30px;" src="/images/edit.png" /> | ||||
|  |                 <text class="fontStyle">质保图谱</text> | ||||
|  |             </view> | ||||
|  |             <view class="detailStyle"> | ||||
|  |                 <van-button type="info" round size="small">查看详情</van-button> | ||||
|  |             </view> | ||||
|  |         </view> | ||||
|  |         <view class="progress-container"> | ||||
|  |             <text class="label">过保比率:</text> | ||||
|  |             <view class="progress-wrapper"> | ||||
|  |                 <progress class="progress" percent="50" color="#4E87FF"></progress> | ||||
|  |                 <text>50%</text> | ||||
|  |             </view> | ||||
|  |         </view> | ||||
|  |         <view class="progress-container"> | ||||
|  |             <text class="label">质保期比例:</text> | ||||
|  |             <view class="progress-wrapper"> | ||||
|  |                 <progress class="progress" percent="50"></progress> | ||||
|  |                 <text>50%</text> | ||||
|  |             </view> | ||||
|  |         </view> | ||||
|  | 
 | ||||
|  |     </view> | ||||
|  |     <!--设备状态--> | ||||
|  |     <view class="card"> | ||||
|  |         <image src="/images/shape1.png" class="imgStyle"></image> | ||||
|  |         <view class="top"> | ||||
|  |             <view style="display: flex; align-items: center;"> | ||||
|  |                 <image style="width: 30px; height: 30px;" src="/images/device.png" /> | ||||
|  |                 <text class="fontStyle">设备状态</text> | ||||
|  |             </view> | ||||
|  |             <view class="detailStyle"> | ||||
|  |                 <van-button type="info" round size="small" bindtap="navigator">查看详情</van-button> | ||||
|  |             </view> | ||||
|  |         </view> | ||||
|  |         <view style="height: 250px;"> | ||||
|  |             <ec-canvas id="mychart-device-pie" canvas-id="mychart-device-pie" ec="{{ ec }}"></ec-canvas> | ||||
|  |         </view> | ||||
|  |     </view> | ||||
|  |     <!--设备类型--> | ||||
|  |     <view class="card"> | ||||
|  |         <image src="/images/shape1.png" class="imgStyle"></image> | ||||
|  |         <view class="top"> | ||||
|  |             <view style="display: flex; align-items: center;"> | ||||
|  |                 <image style="width: 30px; height: 30px;" src="/images/device.png" /> | ||||
|  |                 <text class="fontStyle">设备类型</text> | ||||
|  |             </view> | ||||
|  |             <view class="countStyle"> | ||||
|  |                 总数: | ||||
|  |             </view> | ||||
|  |         </view> | ||||
|  |         <view style="height: 250px;"> | ||||
|  |             <ec-canvas id="mychart-dom-pie" canvas-id="mychart-pie" ec="{{ ec }}"></ec-canvas> | ||||
|  |         </view> | ||||
|  |     </view> | ||||
|  | </view> | ||||
| @ -0,0 +1,91 @@ | |||||
|  | /* package/riskManagement/riskCalendar/riskCalendar.wxss */ | ||||
|  | .container { | ||||
|  |     background-image: linear-gradient(179deg, #006BE3 0%, #4E87FF 16%, #4e87ff00 93%); | ||||
|  |     padding: 0 15px; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .card { | ||||
|  |     position: relative; | ||||
|  |     background-color: #fff; | ||||
|  |     border: 1px solid #ddd; | ||||
|  |     border-radius: 8px; | ||||
|  |     /* padding: 10px; */ | ||||
|  |     box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); | ||||
|  |     margin-top: 12px; | ||||
|  |     width: 100%; | ||||
|  |     background-image: linear-gradient(0deg, #F3F7FF 84%, #DBE6FF 100%); | ||||
|  | 
 | ||||
|  | } | ||||
|  | 
 | ||||
|  | .top { | ||||
|  |     display: flex; | ||||
|  |     justify-content: space-between; | ||||
|  |     padding: 10px; | ||||
|  | 
 | ||||
|  |     /* background-position: bottom; */ | ||||
|  | } | ||||
|  | 
 | ||||
|  | .fontStyle { | ||||
|  |     width: 64px; | ||||
|  |     height: 22px; | ||||
|  |     font-family: PingFangSC-Medium; | ||||
|  |     font-weight: 500; | ||||
|  |     font-size: 16px; | ||||
|  |     color: #000000d9; | ||||
|  |     letter-spacing: 0; | ||||
|  |     margin-left: 5px; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .imgStyle { | ||||
|  |     position: absolute; | ||||
|  |     width: 115px; | ||||
|  |     height: 67px; | ||||
|  |     right: 0; | ||||
|  | 
 | ||||
|  | } | ||||
|  | 
 | ||||
|  | .detailStyle { | ||||
|  |     z-index: 1; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .progress-container { | ||||
|  |     display: flex; | ||||
|  |     align-items: center; | ||||
|  |     width: 100%; | ||||
|  |     margin: 0px 0px 10px 10px; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .label { | ||||
|  |     margin-right: 10px; | ||||
|  |     width: 50%; | ||||
|  |     height: 20px; | ||||
|  |     font-family: PingFangSC-Regular; | ||||
|  |     font-weight: 400; | ||||
|  |     font-size: 14px; | ||||
|  |     color: #383A3B; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .progress-wrapper { | ||||
|  |     display: flex; | ||||
|  |     align-items: center; | ||||
|  |     width: 100%; | ||||
|  | 
 | ||||
|  | } | ||||
|  | 
 | ||||
|  | .percentage { | ||||
|  |     margin-right: 10px; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .progress { | ||||
|  |     width: 75%; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .countStyle { | ||||
|  |     width: 89px; | ||||
|  |     height: 24px; | ||||
|  |     font-family: PingFangSC-Medium; | ||||
|  |     font-weight: 500; | ||||
|  |     font-size: 17px; | ||||
|  |     color: #1684FF; | ||||
|  |     letter-spacing: 0; | ||||
|  | } | ||||
| @ -0,0 +1,120 @@ | |||||
|  | // package/deviceBigdataGraph/detail/detail.js
 | ||||
|  | import * as echarts from '../../components/ec-canvas/echarts'; | ||||
|  | function setOption(chart, data) { | ||||
|  |   const option = { | ||||
|  |     grid: { | ||||
|  |       top: '5%', | ||||
|  |       left: '3%', | ||||
|  |       right: '4%', | ||||
|  |       bottom: '3%', | ||||
|  |       containLabel: true | ||||
|  |     }, | ||||
|  |     xAxis: { | ||||
|  |       type: 'category', | ||||
|  |       data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] | ||||
|  |     }, | ||||
|  |     yAxis: { | ||||
|  |       type: 'value' | ||||
|  |     }, | ||||
|  |     series: [ | ||||
|  |       { | ||||
|  |         data: data, | ||||
|  |         type: 'line' | ||||
|  |       } | ||||
|  |     ] | ||||
|  |   }; | ||||
|  |   chart.setOption(option); | ||||
|  | } | ||||
|  | 
 | ||||
|  | Page({ | ||||
|  | 
 | ||||
|  |   /** | ||||
|  |    * 页面的初始数据 | ||||
|  |    */ | ||||
|  |   data: { | ||||
|  |     ec: { | ||||
|  |         // onInit: initChart,
 | ||||
|  |         lazyLoad: true, // 将 lazyLoad 设为 true 后,需要手动初始化图表
 | ||||
|  |       }, | ||||
|  |       isLoaded: false, | ||||
|  |       list: [1,2,3] | ||||
|  |   }, | ||||
|  | 
 | ||||
|  |   /** | ||||
|  |    * 生命周期函数--监听页面加载 | ||||
|  |    */ | ||||
|  |   onLoad(options) { | ||||
|  |     setTimeout(() => { | ||||
|  |         this.initChart([250, 300, 100, 147, 260, 123, 311]) | ||||
|  |       }, 1000) | ||||
|  |   }, | ||||
|  |   initChart: function (data) { | ||||
|  |     this.ecComponent.init((canvas, width, height, dpr) => { | ||||
|  |       const chart = echarts.init(canvas, null, { | ||||
|  |         width: width, | ||||
|  |         height: height, | ||||
|  |         devicePixelRatio: dpr // new
 | ||||
|  |       }); | ||||
|  |       setOption(chart, data); | ||||
|  | 
 | ||||
|  |       // 将图表实例绑定到 this 上,可以在其他成员函数中访问
 | ||||
|  |       this.chart = chart; | ||||
|  | 
 | ||||
|  |       this.setData({ | ||||
|  |         isLoaded: true, | ||||
|  |       }); | ||||
|  | 
 | ||||
|  |       // 注意这里一定要返回 chart 实例,否则会影响事件处理等
 | ||||
|  |       return chart; | ||||
|  |     }); | ||||
|  |   }, | ||||
|  |   /** | ||||
|  |    * 生命周期函数--监听页面初次渲染完成 | ||||
|  |    */ | ||||
|  |   onReady() { | ||||
|  |     this.ecComponent = this.selectComponent('#device-status-chart'); | ||||
|  | 
 | ||||
|  |   }, | ||||
|  | 
 | ||||
|  |   /** | ||||
|  |    * 生命周期函数--监听页面显示 | ||||
|  |    */ | ||||
|  |   onShow() { | ||||
|  | 
 | ||||
|  |   }, | ||||
|  | 
 | ||||
|  |   /** | ||||
|  |    * 生命周期函数--监听页面隐藏 | ||||
|  |    */ | ||||
|  |   onHide() { | ||||
|  | 
 | ||||
|  |   }, | ||||
|  | 
 | ||||
|  |   /** | ||||
|  |    * 生命周期函数--监听页面卸载 | ||||
|  |    */ | ||||
|  |   onUnload() { | ||||
|  | 
 | ||||
|  |   }, | ||||
|  | 
 | ||||
|  |   /** | ||||
|  |    * 页面相关事件处理函数--监听用户下拉动作 | ||||
|  |    */ | ||||
|  |   onPullDownRefresh() { | ||||
|  | 
 | ||||
|  |   }, | ||||
|  | 
 | ||||
|  |   /** | ||||
|  |    * 页面上拉触底事件的处理函数 | ||||
|  |    */ | ||||
|  |   onReachBottom() { | ||||
|  | 
 | ||||
|  |   }, | ||||
|  | 
 | ||||
|  |   /** | ||||
|  |    * 用户点击右上角分享 | ||||
|  |    */ | ||||
|  |   onShareAppMessage() { | ||||
|  | 
 | ||||
|  |   } | ||||
|  | }) | ||||
| @ -0,0 +1,10 @@ | |||||
|  | { | ||||
|  |     "navigationBarBackgroundColor": "#1979ff", | ||||
|  |     "navigationBarTextStyle": "white", | ||||
|  |     "navigationBarTitleText": "设备状态", | ||||
|  |     "enablePullDownRefresh": false, | ||||
|  |   "usingComponents": { | ||||
|  |     "ec-canvas": "../../components/ec-canvas/ec-canvas" | ||||
|  |      | ||||
|  |   } | ||||
|  | } | ||||
| @ -0,0 +1,26 @@ | |||||
|  | <!--package/deviceBigdataGraph/detail/detail.wxml--> | ||||
|  | <view class="status-detail"> | ||||
|  |   <view class="icon"><text class="icon-text">设备总数</text></view> | ||||
|  |   <view>300</view> | ||||
|  |   <view class="flex flex-around"> | ||||
|  |     <view class="title-item flex flex-col"> | ||||
|  |       <view>设备故障率</view> | ||||
|  |       <view><text class="title-num">{{86}}%</text></view> | ||||
|  |     </view> | ||||
|  |     <view class="title-item flex flex-col"> | ||||
|  |       <view>完好率</view> | ||||
|  |       <view><text class="title-num">{{300}}%</text></view> | ||||
|  |     </view> | ||||
|  |   </view> | ||||
|  | 
 | ||||
|  |   <view class="card"> | ||||
|  |     <view class="flex flex-start"> | ||||
|  |       <!-- <image src="" class="card-img" /> --> | ||||
|  |       <view class="card-img" style="background: blue;"></view> | ||||
|  |       <view class="card-title">历史风险趋势</view> | ||||
|  |     </view> | ||||
|  |     <view class="chart"> | ||||
|  |       <ec-canvas id="device-status-chart" canvas-id="device-status-chart" ec="{{ ec }}"></ec-canvas> | ||||
|  |     </view> | ||||
|  |   </view> | ||||
|  | </view> | ||||
| @ -0,0 +1,76 @@ | |||||
|  | /* package/deviceBigdataGraph/detail/detail.wxss */ | ||||
|  | .status-detail { | ||||
|  |     height: 100vh; | ||||
|  |     background-image: linear-gradient(179deg, #006BE3 0%, #4E87FF 16%, #4e87ff00 93%); | ||||
|  |     padding: 0 15px; | ||||
|  |   } | ||||
|  |    | ||||
|  |   .icon { | ||||
|  |     width: 61px; | ||||
|  |     height: 31.86px; | ||||
|  |     background-image: linear-gradient(0deg, #EAF2FF 5%, #2578F0 100%); | ||||
|  |     box-shadow: 0 3px 4px 1px #bfdbfa4f; | ||||
|  |   } | ||||
|  |    | ||||
|  |   .icon-text { | ||||
|  |     width: 48px; | ||||
|  |     height: 17px; | ||||
|  |     font-family: PingFangSC-Medium; | ||||
|  |     font-weight: 500; | ||||
|  |     font-size: 12px; | ||||
|  |     color: #FFFFFF; | ||||
|  |   } | ||||
|  |    | ||||
|  |   .title-item { | ||||
|  |     width: 150px; | ||||
|  |     color: #ffffffd9; | ||||
|  |   } | ||||
|  |    | ||||
|  |   .title-num { | ||||
|  |     font-size: 20px; | ||||
|  |     color: #FFFFFF; | ||||
|  |   } | ||||
|  |    | ||||
|  |   .title-unit { | ||||
|  |     font-size: 10px; | ||||
|  |     color: #FFFFFE; | ||||
|  |     margin-left: 10px; | ||||
|  |   } | ||||
|  |    | ||||
|  |   .card { | ||||
|  |     background: #FFFFFF; | ||||
|  |     box-shadow: 2px 2px 11px 0 #00000008, 0 0 4px 0 #00000012; | ||||
|  |     border-radius: 4px; | ||||
|  |     padding: 12px; | ||||
|  |     margin-top: 12px; | ||||
|  |   } | ||||
|  |    | ||||
|  |   .card-img { | ||||
|  |     width: 18px; | ||||
|  |     height: 18px; | ||||
|  |     margin-right: 13px; | ||||
|  |   } | ||||
|  |    | ||||
|  |   .card-title { | ||||
|  |     font-weight: 500; | ||||
|  |     font-size: 16px; | ||||
|  |     color: #383A3B; | ||||
|  |   } | ||||
|  |    | ||||
|  |   .card-link { | ||||
|  |     font-weight: 500; | ||||
|  |     font-size: 14px; | ||||
|  |     color: #1684FF; | ||||
|  |   } | ||||
|  |    | ||||
|  |   .chart { | ||||
|  |     width: 100%; | ||||
|  |     height: 195px; | ||||
|  |     margin-top: 20px; | ||||
|  |   } | ||||
|  |    | ||||
|  |   .list { | ||||
|  |     margin-top: 10px; | ||||
|  |     padding: 10px 7px; | ||||
|  |     background-color: #F1F7FF; | ||||
|  |   } | ||||
| @ -0,0 +1,543 @@ | |||||
|  | // package/report/report.js
 | ||||
|  | 
 | ||||
|  | import { getPointList,getPatrolTemplate,getTemplates,reportQuest,getPatrolPlan } from "../../utils/getApiUrl"; | ||||
|  | import {Request} from "../../common"; | ||||
|  | const moment = require("../../utils/moment"); | ||||
|  | 
 | ||||
|  | Page({ | ||||
|  |     data: { | ||||
|  |         isPlanState: false, | ||||
|  |         structList: [{ | ||||
|  |                 id: 0, | ||||
|  |                 name: '指挥中心' | ||||
|  |             }, { | ||||
|  |                 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: '安防系统' | ||||
|  |             } | ||||
|  |         ], | ||||
|  |         data:[],//巡检计划的数据(包括点位,设备等等)
 | ||||
|  |         structListIndex: undefined,//结构物id
 | ||||
|  |         pointList:[],//点位列表
 | ||||
|  |         pointIndex:undefined,//点位索引
 | ||||
|  |         devicesList:[],//设备列表
 | ||||
|  |         dataList: '', // 当前巡检计划
 | ||||
|  |         patrolTemplate:[],//巡检模板
 | ||||
|  |         templateData:[],//巡检模板总数居
 | ||||
|  |         // curPlanTemplateId:0,//当前巡检计划的模板id
 | ||||
|  |         patrolTemplateIndex:undefined,//巡检模板索引
 | ||||
|  |         itemData: '', // 点位
 | ||||
|  |         address: '', // 当前位置
 | ||||
|  |         imgUrl: getApp().globalData.imgUrl, | ||||
|  |         checkItems: [], // 检查项
 | ||||
|  |         inspectContentArr: [], // 巡检内容
 | ||||
|  |         isCommitting: false, | ||||
|  |         planList: null, // 巡检计划列表
 | ||||
|  |         structListVisible: true, | ||||
|  |         scenePointId: null, // 当前点位id
 | ||||
|  |     }, | ||||
|  |     //巡检计划
 | ||||
|  |     getPatrolPlan: function (scenePointId) { | ||||
|  |         let that = this; | ||||
|  |         wx.showLoading({ | ||||
|  |             title: '加载中', | ||||
|  |         }) | ||||
|  |         Request.get(getPatrolPlan()).then(res => { | ||||
|  |             wx.hideLoading(); | ||||
|  |             let pointPlan = res.rows.filter(plan => { | ||||
|  |                 for (const point of plan.points) { | ||||
|  |                     if (point.id == scenePointId) { | ||||
|  |                         return true; | ||||
|  |                     } | ||||
|  |                 } | ||||
|  |                 return false; | ||||
|  |             }).map(p => ({ | ||||
|  |                 label: p.name, | ||||
|  |                 value: p.name, | ||||
|  |                 ...p | ||||
|  |             })) | ||||
|  |             that.setData({ | ||||
|  |                 planList: pointPlan | ||||
|  |             }) | ||||
|  |         }) | ||||
|  |     }, | ||||
|  |     //点位改变函数
 | ||||
|  |     pointChange(e){ | ||||
|  |         const that = this | ||||
|  |         that.getPatrolPlan(that.data.data[e.detail.value].id) | ||||
|  |         that.setData({ | ||||
|  |             inspectContentArr:[], | ||||
|  |             pointIndex:e.detail.value, | ||||
|  |             devicesList:that.data.data[e.detail.value].devices, | ||||
|  |             scenePointId:that.data.data[e.detail.value].id | ||||
|  |         }) | ||||
|  |     }, | ||||
|  |      // 预览图片
 | ||||
|  |      previewImg: function (e) { | ||||
|  |         const { deviceidx, itemidx, index } = e.currentTarget.dataset; | ||||
|  |         // 所有图片
 | ||||
|  |         const imgs = this.data.inspectContentArr[deviceidx].checkItems[itemidx].imgs; | ||||
|  |         const newImgs = imgs.map(i => this.data.imgUrl + i); | ||||
|  |         wx.previewImage({ | ||||
|  |             // 当前显示图片
 | ||||
|  |             current: newImgs[index], | ||||
|  |             // 所有图片
 | ||||
|  |             urls: newImgs | ||||
|  |         }) | ||||
|  |     }, | ||||
|  |     //结构物改变函数
 | ||||
|  |    structChange(event) { | ||||
|  |         const that = this | ||||
|  |         that.setData({ | ||||
|  |             structListIndex: event.detail.value, | ||||
|  |             // isPlanState: true,
 | ||||
|  |             pointList:[],//选择结构物后先置空先前的点位列表
 | ||||
|  |         }) | ||||
|  |        | ||||
|  |         const keywords=that.data?.structList[event.detail.value]?.name | ||||
|  |         const query={keywords} | ||||
|  |          | ||||
|  |         Request.get(getTemplates(query)).then(res=>{ | ||||
|  |             if(res){ | ||||
|  |                 const rlst=res.map(item=>item.patrolTemplate) | ||||
|  |                 that.setData({patrolTemplate:rlst,templateData:res}) | ||||
|  |             }else{ | ||||
|  | 
 | ||||
|  |             } | ||||
|  |         }) | ||||
|  |         Request.get(getPointList(query)).then(res => { | ||||
|  |             if(res){ | ||||
|  |                 const pointList=res.map(item=>{ | ||||
|  |                     return { | ||||
|  |                         id:item.id, | ||||
|  |                         name:item.name | ||||
|  |                     } | ||||
|  |                 }) | ||||
|  |                 that.setData({pointList:pointList,data:res}) | ||||
|  |             }else { | ||||
|  |                 wx.hideLoading(); | ||||
|  |             } | ||||
|  |         }) | ||||
|  | 
 | ||||
|  |     }, | ||||
|  |     //整理设备和检查项
 | ||||
|  |     getPatrolTemplate(templateId,pointDevices=[]) { | ||||
|  |         const that=this | ||||
|  |         Request.get(getPatrolTemplate(templateId)).then(res => { | ||||
|  |             const checkItems = res.rows[0].checkItems; | ||||
|  |             let inspectContentArr = []; | ||||
|  |             // 有绑定设备的点位,每个设备都要检查各个检查项
 | ||||
|  |             if (pointDevices.length) { | ||||
|  |                 pointDevices.forEach(device => { | ||||
|  |                     inspectContentArr.push({ | ||||
|  |                         deviceName: device.name, | ||||
|  |                         deviceId: device.id, | ||||
|  |                         checkItems: checkItems.map(c => ({ | ||||
|  |                             id: `${device.id}-${c.id}`, | ||||
|  |                             name: c.name, | ||||
|  |                             isNormal: null, | ||||
|  |                             msgInp: null, | ||||
|  |                             level: null, | ||||
|  |                             imgs: [], | ||||
|  |                         })) | ||||
|  |                     }) | ||||
|  |                 }); | ||||
|  |             } else { | ||||
|  |                 inspectContentArr.push({ | ||||
|  |                     checkItems: checkItems.map(c => ({ | ||||
|  |                         id: c.id, | ||||
|  |                         name: c.name, | ||||
|  |                         isNormal: null, | ||||
|  |                         msgInp: null, | ||||
|  |                         level: null, | ||||
|  |                         imgs: [], | ||||
|  |                     })) | ||||
|  |                 }) | ||||
|  |             } | ||||
|  |             this.setData({ | ||||
|  |                 checkItems, | ||||
|  |                 inspectContentArr: inspectContentArr, | ||||
|  |             }) | ||||
|  |         }) | ||||
|  |     }, | ||||
|  |     //选择异常或者正常
 | ||||
|  |     handleChangeTwo(e) { | ||||
|  |         const isNormal = e.detail === 'normal'; | ||||
|  |         const { deviceidx, itemidx } = e.currentTarget.dataset; | ||||
|  |         let nextInspectContentArr = this.data.inspectContentArr; | ||||
|  | 
 | ||||
|  |         nextInspectContentArr[deviceidx].checkItems[itemidx].isNormal = isNormal; | ||||
|  |         if (isNormal) { // 清除异常数据
 | ||||
|  |             nextInspectContentArr[deviceidx].checkItems[itemidx].msgInp = null; | ||||
|  |             nextInspectContentArr[deviceidx].checkItems[itemidx].level = null; | ||||
|  |             nextInspectContentArr[deviceidx].checkItems[itemidx].imgs = []; | ||||
|  |         } | ||||
|  |         this.setData({ inspectContentArr: nextInspectContentArr }) | ||||
|  |     }, | ||||
|  |     //返回前一页
 | ||||
|  |     bindCancel() { | ||||
|  |             wx.navigateBack(); | ||||
|  |     }, | ||||
|  |      // 开始巡检录入
 | ||||
|  |      addPatrolRecord: function () { | ||||
|  |         const that = this; | ||||
|  |         if (that.data.isCommitting) { return } | ||||
|  |         let { | ||||
|  |             patrolTemplate, | ||||
|  |             patrolTemplateIndex, | ||||
|  |             structListIndex, | ||||
|  |             pointIndex, | ||||
|  |             pointList, | ||||
|  |             inspectContentArr, | ||||
|  |             dataList, | ||||
|  |             address, | ||||
|  |             data, | ||||
|  |             templateData | ||||
|  |         } = that.data; | ||||
|  |         let alarm = false; | ||||
|  |         if (!address) { | ||||
|  |             wx.showToast({ | ||||
|  |                 title: '请获取当前位置', | ||||
|  |                 icon: 'none', | ||||
|  |                 duration: 1500 | ||||
|  |             }) | ||||
|  |             return; | ||||
|  |         } | ||||
|  |         if (!structListIndex) { | ||||
|  |             wx.showToast({ | ||||
|  |                 title: '请选择结构物', | ||||
|  |                 icon: 'none', | ||||
|  |                 duration: 1500 | ||||
|  |             }) | ||||
|  |             return; | ||||
|  |         } | ||||
|  |         if (!patrolTemplateIndex) { | ||||
|  |             wx.showToast({ | ||||
|  |                 title: '请选择模板', | ||||
|  |                 icon: 'none', | ||||
|  |                 duration: 1500 | ||||
|  |             }) | ||||
|  |             return; | ||||
|  |         } | ||||
|  |         if (!pointIndex) { | ||||
|  |             wx.showToast({ | ||||
|  |                 title: '请选择点位', | ||||
|  |                 icon: 'none', | ||||
|  |                 duration: 1500 | ||||
|  |             }) | ||||
|  |             return; | ||||
|  |         } | ||||
|  |         let reportArr = inspectContentArr.map(d => ({ ...d, alarm: false })); | ||||
|  |         for (const [index, device] of inspectContentArr.entries()) { | ||||
|  |             for (const item of device.checkItems) { | ||||
|  |                 if (item.isNormal === null) { | ||||
|  |                     wx.showToast({ | ||||
|  |                         title: '请填写完整', | ||||
|  |                         icon: 'none', | ||||
|  |                         duration: 1500 | ||||
|  |                     }) | ||||
|  |                     return; | ||||
|  |                 } | ||||
|  |                 if ((!item.isNormal) && (!item.level || !item.msgInp)) { | ||||
|  |                     wx.showToast({ | ||||
|  |                         title: '异常项必须输入巡查详情和选择严重等级', | ||||
|  |                         icon: 'none', | ||||
|  |                         duration: 2000 | ||||
|  |                     }) | ||||
|  |                     return; | ||||
|  |                 } | ||||
|  |                 if (item.isNormal === false) { | ||||
|  |                     alarm = true; // 巡检记录异常
 | ||||
|  |                     reportArr[index].alarm = true; // 设备异常
 | ||||
|  |                 } | ||||
|  |             } | ||||
|  |         } | ||||
|  |         const { id, name, departmentId, deptName } = wx.getStorageSync('userInfo'); | ||||
|  |         const curPlan = that.data.planList.find(item=>item.id=patrolTemplate[patrolTemplateIndex].id) | ||||
|  |         const nextItemData = curPlan.points.find(p => p.id == this.data.scenePointId) | ||||
|  |         const aboutSend=templateData.find(item=>item.patrolTemplate.id===patrolTemplate[patrolTemplateIndex].id) | ||||
|  |         let datas = { | ||||
|  |             patrolPlanId: -1, | ||||
|  |             pointId: pointList[pointIndex].id, | ||||
|  |             inspectionTime: moment().format('YYYY-MM-DD HH:mm:ss'), | ||||
|  |             points: { | ||||
|  |                 user: { id, name, department: { id: departmentId, name: deptName } }, | ||||
|  |                 project: aboutSend.project, | ||||
|  |                 frequency: aboutSend.frequency, | ||||
|  |                 itemData:nextItemData, | ||||
|  |                 inspectContent: reportArr, | ||||
|  |                 address: address | ||||
|  |             }, | ||||
|  |             alarm, | ||||
|  |             projectId: aboutSend.project.id | ||||
|  |         } | ||||
|  |         wx.showLoading({ title: '提交中...' }); | ||||
|  |         that.setData({ isCommitting: true }); | ||||
|  |         Request.post(reportQuest(), datas).then(res => { | ||||
|  |             wx.hideLoading(); | ||||
|  |             that.setData({ isCommitting: false }); | ||||
|  |             wx.showToast({ | ||||
|  |                 title: '提交成功', | ||||
|  |                 icon: 'success' | ||||
|  |             }) | ||||
|  |             setTimeout(() => { | ||||
|  |                 that.bindCancel(); | ||||
|  |             }, 1500) | ||||
|  |         }) | ||||
|  |     }, | ||||
|  |      //多张图片上传
 | ||||
|  |      uploadImg: function (data, deviceidx, itemidx) { | ||||
|  |         wx.showLoading({ | ||||
|  |             title: '上传中...', | ||||
|  |             mask: true, | ||||
|  |         }) | ||||
|  |         let that = this, | ||||
|  |             i = data.i ? data.i : 0, | ||||
|  |             success = data.success ? data.success : 0, | ||||
|  |             fail = data.fail ? data.fail : 0; | ||||
|  |         let imgs = that.data.inspectContentArr[deviceidx].checkItems[itemidx].imgs; | ||||
|  |         wx.uploadFile({ | ||||
|  |             url: data.url, | ||||
|  |             filePath: data.path[i], | ||||
|  |             name: 'file', | ||||
|  |             success: (resp) => { | ||||
|  |                 wx.hideLoading(); | ||||
|  |                 success++; | ||||
|  |                 let str = JSON.parse(resp.data) // 返回的结果,可能不同项目结果不一样
 | ||||
|  |                 str = str.uploaded | ||||
|  |                 if (imgs.length >= 20) { | ||||
|  |                     let nextInspectContentArr = that.data.inspectContentArr; | ||||
|  |                     nextInspectContentArr[deviceidx].checkItems[itemidx].imgs = imgs; | ||||
|  |                     that.setData({ inspectContentArr: nextInspectContentArr }); | ||||
|  |                     return false; | ||||
|  |                 } else { | ||||
|  |                     imgs.push(str); | ||||
|  |                     let nextInspectContentArr = that.data.inspectContentArr; | ||||
|  |                     nextInspectContentArr[deviceidx].checkItems[itemidx].imgs = imgs; | ||||
|  |                     that.setData({ inspectContentArr: nextInspectContentArr }); | ||||
|  |                 } | ||||
|  |             }, | ||||
|  |             fail: (res) => { | ||||
|  |                 fail++; | ||||
|  |                 console.log('fail:' + i + "fail:" + fail); | ||||
|  |             }, | ||||
|  |             complete: () => { | ||||
|  |                 i++; | ||||
|  |                 if (i == data.path.length) { // 当图片传完时,停止调用     
 | ||||
|  |                     console.log('执行完毕'); | ||||
|  |                     console.log('成功:' + success + " 失败:" + fail); | ||||
|  |                 } else { // 若图片还没有传完,则继续调用函数
 | ||||
|  |                     data.i = i; | ||||
|  |                     data.success = success; | ||||
|  |                     data.fail = fail; | ||||
|  |                     that.uploadImg(data, deviceidx, itemidx); // 递归,回调自己
 | ||||
|  |                 } | ||||
|  |             } | ||||
|  |         }); | ||||
|  |     }, | ||||
|  |       // 上传图片
 | ||||
|  |       chooseImg: function (e) { // 这里是选取图片的方法
 | ||||
|  |         const { deviceidx, itemidx } = e.currentTarget.dataset; | ||||
|  |         const that = this; | ||||
|  |         let pics = []; | ||||
|  |         const detailPics = that.data.inspectContentArr[deviceidx].checkItems[itemidx].imgs; | ||||
|  |         if (detailPics.length >= 20) { | ||||
|  |             wx.showToast({ | ||||
|  |                 title: '最多选择20张图片上传', | ||||
|  |                 icon: 'none' | ||||
|  |             }); | ||||
|  |             return; | ||||
|  |         } | ||||
|  |         wx.chooseMedia({ | ||||
|  |             count: 20, // 基础库2.25.0前,最多可支持9个文件,2.25.0及以后最多可支持20个文件
 | ||||
|  |             mediaType: ['image'], // 文件类型
 | ||||
|  |             sizeType: ['original', 'compressed'], // original 原图,compressed 压缩图,默认二者都有
 | ||||
|  |             sourceType: ['album', 'camera'], // album 从相册选图,camera 使用相机,默认二者都有
 | ||||
|  |             success: function (res) { | ||||
|  |                 const imgs = res.tempFiles; | ||||
|  |                 for (let i = 0; i < imgs.length; i++) { | ||||
|  |                     if (res.tempFiles[i].size > 15728640) { | ||||
|  |                         wx.showToast({ title: '图片大于15M,不可上传', icon: 'none' }); | ||||
|  |                         return; | ||||
|  |                     } | ||||
|  |                     const fileNameArr = res.tempFiles[i].tempFilePath.split('.'); | ||||
|  |                     const extension = res.tempFiles[i].tempFilePath.split('.')[fileNameArr.length - 1]; | ||||
|  |                     if (extension !== 'jpg' && extension !== 'png' && extension !== 'jpeg') { | ||||
|  |                         wx.showToast({ title: '只能上传jpg、jpeg、png格式的图片', icon: 'none' }); | ||||
|  |                         return; | ||||
|  |                     } | ||||
|  |                     pics.push(imgs[i].tempFilePath) | ||||
|  |                 } | ||||
|  |                 that.uploadImg({ | ||||
|  |                     url: getApp().globalData.webUrl + '_upload/attachments/project', // 图片上传的接口
 | ||||
|  |                     path: pics, // 选取的图片的地址数组
 | ||||
|  |                 }, deviceidx, itemidx); | ||||
|  |             }, | ||||
|  |         }) | ||||
|  |     }, | ||||
|  |      // 巡查详情
 | ||||
|  |      bindInput: function (e) { | ||||
|  |         const { deviceidx, itemidx } = e.currentTarget.dataset; | ||||
|  |         let nextInspectContentArr = this.data.inspectContentArr; | ||||
|  | 
 | ||||
|  |         nextInspectContentArr[deviceidx].checkItems[itemidx].msgInp = e.detail.value; | ||||
|  |         this.setData({ inspectContentArr: nextInspectContentArr }) | ||||
|  |     }, | ||||
|  | 
 | ||||
|  |     handleChangeThree(e) { | ||||
|  |         const { deviceidx, itemidx } = e.currentTarget.dataset; | ||||
|  |         let nextInspectContentArr = this.data.inspectContentArr; | ||||
|  |         nextInspectContentArr[deviceidx].checkItems[itemidx].level = e.detail; | ||||
|  |         this.setData({ inspectContentArr: nextInspectContentArr }) | ||||
|  |     }, | ||||
|  | 
 | ||||
|  | 
 | ||||
|  |     //巡检模板改变
 | ||||
|  |     patrolTemplateChange(e){ | ||||
|  |         const that=this | ||||
|  |         that.getPatrolTemplate(that.data.patrolTemplate[e.detail.value].id,that.data.devicesList) | ||||
|  |         that.setData({ | ||||
|  |             patrolTemplateIndex:e.detail.value | ||||
|  |         }) | ||||
|  |     }, | ||||
|  |     bindShowMsg() { | ||||
|  |         this.setData({ | ||||
|  |             select: !this.data.select | ||||
|  |         }) | ||||
|  |     }, | ||||
|  | 
 | ||||
|  |     mySelect(e) { | ||||
|  |         var name = e.currentTarget.dataset.name | ||||
|  |         this.setData({ | ||||
|  |             tihuoWay: name, | ||||
|  |             select: false | ||||
|  |         }) | ||||
|  |     }, | ||||
|  |     /** | ||||
|  |      * 页面的初始数据 | ||||
|  |      */ | ||||
|  |     //   data: {
 | ||||
|  | 
 | ||||
|  |     //   },
 | ||||
|  | 
 | ||||
|  |     /** | ||||
|  |      * 生命周期函数--监听页面加载 | ||||
|  |      */ | ||||
|  |     onLoad(options) { | ||||
|  |         const that=this | ||||
|  |         wx.setNavigationBarTitle({ | ||||
|  |             title: options.key, | ||||
|  |         }); | ||||
|  | 
 | ||||
|  |     }, | ||||
|  |     onStructListPicker() { | ||||
|  |         this.setData({ | ||||
|  |             structListVisible: true | ||||
|  |         }); | ||||
|  |     }, | ||||
|  |     // 获取当前位置
 | ||||
|  |     selfLocation() { | ||||
|  |         const that = this | ||||
|  |         wx.showLoading({ | ||||
|  |             title: '定位中', | ||||
|  |             mask: true, | ||||
|  |         }); | ||||
|  |         wx.getLocation({ | ||||
|  |             type: 'wgs84', | ||||
|  |             success: (res) => { | ||||
|  |                 wx.request({ | ||||
|  |                     url: `https://apis.map.qq.com/ws/geocoder/v1/?location=${res.latitude},${res.longitude}&key=${getApp().globalData.key}`, | ||||
|  |                     success: function (res) { | ||||
|  |                         wx.hideLoading(); | ||||
|  |                         // 根据自己项目需求获取res内容
 | ||||
|  |                         that.setData({ | ||||
|  |                             address: res.data.result.address | ||||
|  |                         }) | ||||
|  |                     } | ||||
|  |                 }) | ||||
|  |             }, | ||||
|  |             fail: (res) => { | ||||
|  |                 wx.hideLoading(); | ||||
|  |                 wx.showToast({ | ||||
|  |                     title: res.errMsg, | ||||
|  |                     icon: 'none', | ||||
|  |                     duration: 1000 | ||||
|  |                 }); | ||||
|  |             } | ||||
|  |         }); | ||||
|  |     }, | ||||
|  |     /** | ||||
|  |      * 生命周期函数--监听页面初次渲染完成 | ||||
|  |      */ | ||||
|  |     onReady() { | ||||
|  | 
 | ||||
|  |     }, | ||||
|  | 
 | ||||
|  |     /** | ||||
|  |      * 生命周期函数--监听页面显示 | ||||
|  |      */ | ||||
|  |     onShow() { | ||||
|  | 
 | ||||
|  |     }, | ||||
|  | 
 | ||||
|  |     /** | ||||
|  |      * 生命周期函数--监听页面隐藏 | ||||
|  |      */ | ||||
|  |     onHide() { | ||||
|  | 
 | ||||
|  |     }, | ||||
|  | 
 | ||||
|  |     /** | ||||
|  |      * 生命周期函数--监听页面卸载 | ||||
|  |      */ | ||||
|  |     onUnload() { | ||||
|  | 
 | ||||
|  |     }, | ||||
|  | 
 | ||||
|  |     /** | ||||
|  |      * 页面相关事件处理函数--监听用户下拉动作 | ||||
|  |      */ | ||||
|  |     onPullDownRefresh() { | ||||
|  | 
 | ||||
|  |     }, | ||||
|  | 
 | ||||
|  |     /** | ||||
|  |      * 页面上拉触底事件的处理函数 | ||||
|  |      */ | ||||
|  |     onReachBottom() { | ||||
|  | 
 | ||||
|  |     }, | ||||
|  | 
 | ||||
|  |     /** | ||||
|  |      * 用户点击右上角分享 | ||||
|  |      */ | ||||
|  |     onShareAppMessage() { | ||||
|  | 
 | ||||
|  |     } | ||||
|  | }) | ||||
| @ -0,0 +1,25 @@ | |||||
|  | { | ||||
|  |     "navigationBarBackgroundColor": "#1979ff", | ||||
|  |     "navigationBarTextStyle": "white", | ||||
|  |     "navigationBarTitleText": "发现问题", | ||||
|  |     "enablePullDownRefresh": false, | ||||
|  |     "componentFramework": "glass-easel", | ||||
|  |     "usingComponents": { | ||||
|  |         "van-button": "@vant/weapp/button/index", | ||||
|  |         "van-field": "@vant/weapp/field/index", | ||||
|  |         "van-cell": "@vant/weapp/cell/index", | ||||
|  |         "van-cell-group": "@vant/weapp/cell-group/index", | ||||
|  |         "van-picker": "@vant/weapp/picker/index", | ||||
|  |         "van-popup": "@vant/weapp/popup/index", | ||||
|  |         "van-icon": "@vant/weapp/icon/index", | ||||
|  |         "van-collapse": "@vant/weapp/collapse/index", | ||||
|  |         "van-collapse-item": "@vant/weapp/collapse-item/index", | ||||
|  |         "van-divider": "@vant/weapp/divider/index", | ||||
|  |         "t-cell-group": "tdesign-miniprogram/cell-group/cell-group", | ||||
|  |         "t-cell": "tdesign-miniprogram/cell/cell", | ||||
|  |         "t-picker": "tdesign-miniprogram/picker/picker", | ||||
|  |         "t-picker-item": "tdesign-miniprogram/picker-item/picker-item", | ||||
|  |         "van-radio": "@vant/weapp/radio/index", | ||||
|  |         "van-radio-group": "@vant/weapp/radio-group/index" | ||||
|  |     } | ||||
|  | } | ||||
| @ -0,0 +1,96 @@ | |||||
|  | <view class="popBox"> | ||||
|  |     <view> | ||||
|  |         <van-cell-group class="mission-card"> | ||||
|  |             <van-cell> | ||||
|  |                 <view style="display:flex"> | ||||
|  |                     <view class="fs-cell-title" style="">结构物:</view> | ||||
|  |                     <picker style="width:100%;text-align:left" bindchange="structChange" data-type='jiegouwu' value="{{0}}" range="{{structList}}" range-key="name"> | ||||
|  |                         <view class="fs-cell-content" style="width:100%"> | ||||
|  |                             {{structListIndex||structListIndex==0?structList[structListIndex].name:'请选择'}} | ||||
|  |                             <van-icon   name="arrow" style="float:right;position:relative; top:4px" /> | ||||
|  |                         </view> | ||||
|  |                     </picker> | ||||
|  |                 </view> | ||||
|  |             </van-cell> | ||||
|  |             <van-cell> | ||||
|  |                 <view style="display:flex"> | ||||
|  |                     <view class="fs-cell-title" style="">当前点位:</view> | ||||
|  |                     <picker style="width:100%;text-align:left" bindchange="pointChange" data-type='point'  range="{{pointList}}" range-key="name"> | ||||
|  |                         <view class="fs-cell-content" style="width:100%"> | ||||
|  |                             {{pointIndex||pointIndex==0?pointList[pointIndex].name:'请选择'}} | ||||
|  |                             <van-icon name="arrow" style="float:right;position:relative; top:4px" /> | ||||
|  |                         </view> | ||||
|  |                     </picker> | ||||
|  |                 </view> | ||||
|  |             </van-cell> | ||||
|  |             <van-cell> | ||||
|  |                 <view style="overflow: hidden;"> | ||||
|  |                     <view style="float: left;" class="fs-cell-title">当前位置:</view> | ||||
|  |                     <view style="float:right;" class="fs-cell-content" wx:if="{{address}}"> | ||||
|  |                         {{address}} | ||||
|  |                     </view> | ||||
|  |                     <view style="float:right;"> | ||||
|  |                         <image wx:if="{{!address}}" class="icon" src="../../images/landmark.svg" /> | ||||
|  |                         <view style="display: inline-block;" bindtap="selfLocation" wx:if="{{!address}}"> | ||||
|  |                             点击获取 | ||||
|  |                         </view> | ||||
|  |                     </view> | ||||
|  |                 </view> | ||||
|  |             </van-cell> | ||||
|  |             <van-cell> | ||||
|  |                 <view style="display:flex"> | ||||
|  |                     <view class="fs-cell-title">巡检模板:</view> | ||||
|  |                     <picker style="width:100%;text-align:left"  bindchange="patrolTemplateChange" data-type='template' value="{{0}}" range="{{patrolTemplate}}" range-key="name"> | ||||
|  |                         <view class="fs-cell-content" style="width:100%"> | ||||
|  |                             {{patrolTemplateIndex||patrolTemplateIndex==0?patrolTemplate[patrolTemplateIndex].name:'请选择'}} | ||||
|  |                             <van-icon name="arrow" style="float:right;position:relative; top:4px" /> | ||||
|  |                         </view> | ||||
|  |                     </picker> | ||||
|  |                 </view> | ||||
|  |             </van-cell> | ||||
|  | 
 | ||||
|  | 
 | ||||
|  | 
 | ||||
|  |         </van-cell-group> | ||||
|  |     </view> | ||||
|  | 
 | ||||
|  |     <!-- 渲染巡检内容 --> | ||||
|  |     <view wx:for="{{inspectContentArr}}" wx:key="id" wx:for-item="device" wx:for-index="deviceidx" > | ||||
|  |         <view wx:if="{{device.deviceName}}" class="flex flex-start" style="height: 40px">{{device.deviceName}}</view> | ||||
|  |         <view wx:for="{{device.checkItems}}" wx:key="id" wx:for-index="itemidx"> | ||||
|  |             <view class="flex-between"> | ||||
|  |                 <view class="item-name">{{item.name}}:</view> | ||||
|  |                 <van-radio-group style="padding:10px 15px;" data-deviceidx="{{deviceidx}}" data-itemidx="{{itemidx}}" bindchange="handleChangeTwo"> | ||||
|  |                     <van-radio style="margin-right: 20px;" class="radio-text" color="#1979ff" name="normal">正常</van-radio> | ||||
|  |                     <van-radio class="radio-text" checked-color="#CC0000" name="abnormal">异常</van-radio> | ||||
|  |                 </van-radio-group> | ||||
|  |             </view> | ||||
|  |             <view class="divider" /> | ||||
|  |             <van-radio-group class="flex-end" style="padding:10px 15px;" data-deviceidx="{{deviceidx}}" data-itemidx="{{itemidx}}" bindchange="handleChangeThree" wx:if="{{item.isNormal === false}}"> | ||||
|  |                 <van-radio style="margin-right: 20px;" class="radio-text" checked-color="#FF9900" name="轻微">轻微</van-radio> | ||||
|  |                 <van-radio style="margin-right: 20px;" class="radio-text" checked-color="#FF3300" name="中度">中度</van-radio> | ||||
|  |                 <van-radio class="radio-text" checked-color="#990000" name="严重">严重</van-radio> | ||||
|  |             </van-radio-group> | ||||
|  |             <textarea class="textarea" placeholder="请输入巡查详情" maxlength="-1" wx:if="{{item.isNormal === false}}" data-deviceidx="{{deviceidx}}" data-itemidx="{{itemidx}}" bindinput="bindInput" /> | ||||
|  |             <view class="weui-uploader" style="padding: 20rpx 30rpx;overflow-y:scroll;" wx:if="{{item.isNormal === false}}"> | ||||
|  |                 <view class="img-v weui-uploader__bd" style="overflow:hidden;"> | ||||
|  |                     <view class="pic" wx:for="{{item.imgs}}" wx:for-item="img" wx:key="*this"> | ||||
|  |                         <image class="weui-uploader__img showImg" src="{{imgUrl + img}}" data-index="{{index}}" data-deviceidx="{{deviceidx}}" data-itemidx="{{itemidx}}" mode="aspectFill" bindtap="bindInput"> | ||||
|  |                             <icon type="cancel" class="delete-btn" data-index="{{index}}" data-deviceidx="{{deviceidx}}" data-itemidx="{{itemidx}}" catchtap="deleteImg" /> | ||||
|  |                         </image> | ||||
|  |                     </view> | ||||
|  |                     <!-- 用来提示用户上传图片 --> | ||||
|  |                     <view class="weui-uploader__input-box pic" data-item="{{item.name}}" data-deviceidx="{{deviceidx}}" data-itemidx="{{itemidx}}" bindtap="chooseImg"> | ||||
|  |                         <image class="upload" src="/images/upload.png" /> | ||||
|  |                     </view> | ||||
|  |                 </view> | ||||
|  |             </view> | ||||
|  |             <view class="divider" /> | ||||
|  |         </view> | ||||
|  |     </view> | ||||
|  | 
 | ||||
|  |     <view class="btnBox"> | ||||
|  |         <view class="cancel" bindtap="bindCancel">取消</view> | ||||
|  |         <view class="submit" bindtap="addPatrolRecord">提交</view> | ||||
|  |     </view> | ||||
|  | </view> | ||||
| @ -0,0 +1,131 @@ | |||||
|  | .divider { | ||||
|  |     width: 100%; | ||||
|  |     height: 0px; | ||||
|  |     border-top: 1px solid #F5F5F5; | ||||
|  |   } | ||||
|  |    | ||||
|  |   .flex-between { | ||||
|  |     display: flex; | ||||
|  |     justify-content: space-between; | ||||
|  |   } | ||||
|  |    | ||||
|  |   .flex-end { | ||||
|  |     display: flex; | ||||
|  |     justify-content: flex-end; | ||||
|  |   } | ||||
|  |    | ||||
|  |   .popBox { | ||||
|  |     position: absolute; | ||||
|  |     left: 50%; | ||||
|  |     z-index: 1000; | ||||
|  |     background: #fff; | ||||
|  |     width: 95%; | ||||
|  |     margin-left: -356rpx; | ||||
|  |     padding: 20rpx 0; | ||||
|  |   } | ||||
|  |    | ||||
|  |   .item-name { | ||||
|  |     margin: 20rpx 0 0 30rpx; | ||||
|  |   } | ||||
|  |    | ||||
|  |   .btnBox { | ||||
|  |     padding: 50px 30rpx; | ||||
|  |     overflow: hidden; | ||||
|  |     font-size: 30rpx; | ||||
|  |     display: flex; | ||||
|  |     justify-content: space-between; | ||||
|  |   } | ||||
|  |    | ||||
|  |   .cancel { | ||||
|  |     width: 38vw; | ||||
|  |     height: 42px; | ||||
|  |     line-height: 42px; | ||||
|  |     text-align: center; | ||||
|  |     background: #fff; | ||||
|  |     border: 1px solid #006BE3; | ||||
|  |     border-radius: 24px; | ||||
|  |     font-weight: 600; | ||||
|  |     font-size: 16px; | ||||
|  |     color: #1684FF; | ||||
|  |   } | ||||
|  |    | ||||
|  |   .submit { | ||||
|  |     width: 38vw; | ||||
|  |     height: 42px; | ||||
|  |     line-height: 42px; | ||||
|  |     text-align: center; | ||||
|  |     background: #1684FF; | ||||
|  |     border: 1px solid #006BE3; | ||||
|  |     border-radius: 24px; | ||||
|  |     font-weight: 600; | ||||
|  |     font-size: 16px; | ||||
|  |     color: #FFFFFF; | ||||
|  |   } | ||||
|  |    | ||||
|  |   .pic { | ||||
|  |     float: left; | ||||
|  |     position: relative; | ||||
|  |     margin-right: 8px; | ||||
|  |     margin-bottom: 8px; | ||||
|  |   } | ||||
|  |    | ||||
|  |   .showImg { | ||||
|  |     width: 160rpx; | ||||
|  |     height: 160rpx; | ||||
|  |   } | ||||
|  |    | ||||
|  |   .delete-btn { | ||||
|  |     position: absolute; | ||||
|  |     top: 0; | ||||
|  |     right: 0; | ||||
|  |   } | ||||
|  |    | ||||
|  |   .upload { | ||||
|  |     width: 63px; | ||||
|  |     height: 63px; | ||||
|  |   } | ||||
|  |    | ||||
|  |   .block { | ||||
|  |     display: block; | ||||
|  |   } | ||||
|  |    | ||||
|  |   .icon { | ||||
|  |     width: 18px; | ||||
|  |     height: 18px; | ||||
|  |     margin-right: 5px; | ||||
|  |   } | ||||
|  |    | ||||
|  |   .radio-text { | ||||
|  |     font-size: 14px; | ||||
|  |     color: #323233; | ||||
|  |   } | ||||
|  |    | ||||
|  |   .van-radio-group { | ||||
|  |     display: flex; | ||||
|  |   } | ||||
|  |    | ||||
|  |   .textarea { | ||||
|  |     width: 84%; | ||||
|  |     margin: 0 auto; | ||||
|  |     padding: 20rpx; | ||||
|  |     height: 120rpx; | ||||
|  |     border: 1px solid #61616166; | ||||
|  |   } | ||||
|  |   .mission-card-title { | ||||
|  |     background-color: #fff; | ||||
|  |     overflow: auto; | ||||
|  |     padding: 24rpx 16px; | ||||
|  |     display: flex; | ||||
|  |     align-items: center | ||||
|  | } | ||||
|  | .fs-cell-title { | ||||
|  |     max-width: 6.2em; | ||||
|  |     min-width: 6.2em; | ||||
|  |     margin-right: 12px; | ||||
|  |     text-align: left; | ||||
|  |     color: var(--field-label-color, #646566) | ||||
|  | } | ||||
|  | 
 | ||||
|  | .fs-cell-content { | ||||
|  |     color: var(--field-input-text-color, #323233) | ||||
|  | } | ||||
| @ -1,9 +1,11 @@ | |||||
| { | { | ||||
|   "navigationBarBackgroundColor": "#1979ff", |   "navigationBarBackgroundColor": "#006BE3", | ||||
|   "navigationBarTextStyle": "white", |   "navigationBarTextStyle": "white", | ||||
|   "navigationBarTitleText": "故障日历", |   "navigationBarTitleText": "故障风险管理", | ||||
|   "enablePullDownRefresh": false, |   "enablePullDownRefresh": false, | ||||
|   "usingComponents": { |   "usingComponents": { | ||||
|     "ec-canvas": "../../components/ec-canvas/ec-canvas" |     "van-calendar": "@vant/weapp/calendar/index", | ||||
|  |     "van-picker": "@vant/weapp/picker/index", | ||||
|  |     "van-popup": "@vant/weapp/popup/index" | ||||
|   } |   } | ||||
| } | } | ||||
| @ -1,2 +1,78 @@ | |||||
| <!--package/riskManagement/riskCalendar/riskCalendar.wxml--> | <!--package/riskManagement/riskCalendar/riskCalendar.wxml--> | ||||
| <text>package/riskManagement/riskCalendar/riskCalendar.wxml</text> | <view class="risk-calendar"> | ||||
|  |   <view class="card"> | ||||
|  |     <view class="card-top flex flex-between"> | ||||
|  |       <view class="card-left flex"> | ||||
|  |         <image class="card-icon" src="/images/calendar_icon.png" /> | ||||
|  |         <view class="title">巡检日历</view> | ||||
|  |       </view> | ||||
|  |       <view class="card-right">{{curDate}}</view> | ||||
|  |       <image src="/images/calendar_card_bg.png" class="card-bg" /> | ||||
|  |     </view> | ||||
|  |     <view class="calendar-box"> | ||||
|  |       <van-calendar | ||||
|  |         show-mark="{{ false }}" | ||||
|  |         show-title="{{ false }}" | ||||
|  |         show-subtitle="{{ false }}" | ||||
|  |         poppable="{{ false }}" | ||||
|  |         show-confirm="{{ false }}" | ||||
|  |         min-date="{{ minDate }}" | ||||
|  |         max-date="{{ maxDate }}" | ||||
|  |         formatter="{{ formatter }}" | ||||
|  |         bind:select="onDateSelect" | ||||
|  |         row-height="48" | ||||
|  |         color="#1684FF" | ||||
|  |         class="calendar" | ||||
|  |       /> | ||||
|  |     </view> | ||||
|  |   </view> | ||||
|  | 
 | ||||
|  |   <view class="title-box flex flex-between "> | ||||
|  |     <view class="title">异常等级</view> | ||||
|  |     <view class="flex" bind:tap="showPopup"> | ||||
|  |       <view class="picker-text">{{curLevel}}</view> | ||||
|  |       <image class="arrow" src="/images/arrow_right_blue.svg" /> | ||||
|  |     </view> | ||||
|  |   </view> | ||||
|  |   <van-popup show="{{ show }}" round position="bottom" close-on-click-overlay="{{false}}"> | ||||
|  |     <van-picker | ||||
|  |       show-toolbar | ||||
|  |       columns="{{ level }}" | ||||
|  |       bind:cancel="onCancel" | ||||
|  |       bind:confirm="onConfirm" | ||||
|  |     /> | ||||
|  |   </van-popup> | ||||
|  | 
 | ||||
|  |   <view wx:for="{{showList}}" class="card" style="margin-bottom: 10px"> | ||||
|  |     <view class="card-top flex flex-between"> | ||||
|  |       <view class="card-left flex"> | ||||
|  |         <image class="card-icon" src="/images/right_icon.png" /> | ||||
|  |         <view class="title">{{item.points.project.name}}</view> | ||||
|  |       </view> | ||||
|  |       <view class="card-right-btn flex" data-item="{{item}}" bindtap="toDetail">查看详情</view> | ||||
|  |       <image src="/images/right_card_bg.png" class="card-bg" /> | ||||
|  |     </view> | ||||
|  |     <view class="card-content"> | ||||
|  |       <view class="row flex flex-between"> | ||||
|  |         <view class="content-left">本次巡检日期</view> | ||||
|  |         <view class="content-right">{{item.inspectionTime}}</view> | ||||
|  |       </view> | ||||
|  |       <view class="row flex flex-between"> | ||||
|  |         <view class="content-left">点位</view> | ||||
|  |         <view class="content-right">{{item.points.itemData.name}}</view> | ||||
|  |       </view> | ||||
|  |       <view class="row flex flex-between"> | ||||
|  |         <view class="content-left">巡检人</view> | ||||
|  |         <view class="content-right">{{item.points.user.name}}</view> | ||||
|  |       </view> | ||||
|  |       <view class="row flex flex-between"> | ||||
|  |         <view class="content-left">巡检结果</view> | ||||
|  |         <view class="content-right" style="color: red;">异常</view> | ||||
|  |       </view> | ||||
|  |       <view class="row flex flex-between"> | ||||
|  |         <view class="content-left">异常等级</view> | ||||
|  |         <view class="content-right" style="color: red;">{{item.level}}</view> | ||||
|  |       </view> | ||||
|  |     </view> | ||||
|  |   </view> | ||||
|  | </view> | ||||
|  | |||||
| @ -1 +1,105 @@ | |||||
| /* package/riskManagement/riskCalendar/riskCalendar.wxss */ | /* package/riskManagement/riskCalendar/riskCalendar.wxss */ | ||||
|  | .risk-calendar { | ||||
|  |   height: 100%; | ||||
|  |   background-image: linear-gradient(179deg, #006BE3 0%, #4E87FF 16%, #4e87ff00 93%); | ||||
|  |   padding: 0 15px; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .card { | ||||
|  |   box-sizing: border-box; | ||||
|  |   background: #FFFFFF; | ||||
|  |   box-shadow: 2px 2px 11px 0 #00000008, 0 0 4px 0 #00000012; | ||||
|  |   border-radius: 4px; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .card-top { | ||||
|  |   height: 68px; | ||||
|  |   background-image: linear-gradient(0deg, #F3F7FF 84%, #DBE6FF 100%); | ||||
|  |   border-radius: 4px; | ||||
|  |   position: relative; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .card-bg { | ||||
|  |   position: absolute; | ||||
|  |   top: 0; | ||||
|  |   right: 11px; | ||||
|  |   width: 115px; | ||||
|  |   height: 67px; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .card-left { | ||||
|  |   margin-left: 23px; | ||||
|  |   font-weight: 500; | ||||
|  |   font-size: 16px; | ||||
|  |   color: #000000d9; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .card-right { | ||||
|  |   margin-right: 18px; | ||||
|  |   color: #1684FF; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .card-right-btn { | ||||
|  |   width: 76px; | ||||
|  |   height: 26px; | ||||
|  |   margin-right: 18px; | ||||
|  |   background: #1684FF; | ||||
|  |   border-radius: 16px; | ||||
|  |   color: #fff; | ||||
|  |   font-size: 13px; | ||||
|  |   z-index: 99; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .card-icon { | ||||
|  |   width: 30px; | ||||
|  |   height: 30px; | ||||
|  |   margin-right: 8px; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .calendar-box { | ||||
|  |   padding-bottom: 12px; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .calendar { | ||||
|  |   --calendar-height: 300px; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .title-box { | ||||
|  |   margin: 10px 0; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .title { | ||||
|  |   font-weight: 600; | ||||
|  |   font-size: 16px; | ||||
|  |   color: #383A3B; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .picker-text { | ||||
|  |   font-weight: 600; | ||||
|  |   color: #1684FF; | ||||
|  |   text-align: right; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .arrow { | ||||
|  |   width: 12px; | ||||
|  |   height: 12px; | ||||
|  |   transform: rotate(90deg); | ||||
|  |   margin-left: 9px; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .card-content { | ||||
|  |   padding-bottom: 10px; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .row { | ||||
|  |   margin: 4px 26px; | ||||
|  |   color: #31373E; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .content-left { | ||||
|  |   font-size: 12px; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .content-right { | ||||
|  |   font-size: 14px; | ||||
|  | } | ||||
| After Width: | Height: | Size: 577 B | 
| @ -0,0 +1,56 @@ | |||||
|  | 'use strict'; | ||||
|  | 
 | ||||
|  | import { basicAction } from '@peace/utils' | ||||
|  | import { ApiTable } from '$utils' | ||||
|  | 
 | ||||
|  | export function getDeviceList(query) { | ||||
|  |     return dispatch => basicAction({ | ||||
|  |         type: 'get', | ||||
|  |         dispatch: dispatch, | ||||
|  |         query: query || {}, | ||||
|  |         actionType: 'GET_Device_REPORT', | ||||
|  |         url: `${ApiTable.getDeviceList}`, | ||||
|  |         msg: { error: '获取设备列表失败' }, | ||||
|  |         reducer: { name: 'device' } | ||||
|  |     }); | ||||
|  | } | ||||
|  | 
 | ||||
|  | 
 | ||||
|  | export function addDevice(params) { | ||||
|  |     return (dispatch) => basicAction({ | ||||
|  |         type: 'post', | ||||
|  |         data: params, | ||||
|  |         dispatch, | ||||
|  |         actionType: 'ADD_Device_REPORT', | ||||
|  |         url: ApiTable.addDevice, | ||||
|  |         msg: { | ||||
|  |             option: '设备新增', | ||||
|  |         }, | ||||
|  |     }); | ||||
|  | } | ||||
|  | 
 | ||||
|  | export function deleteDevice(id) { | ||||
|  |     return (dispatch) => basicAction({ | ||||
|  |         type: 'del', | ||||
|  |         dispatch, | ||||
|  |         actionType: 'DELETE_Device_REPORT', | ||||
|  |         url: ApiTable.modifyDevice.replace('{id}', id), | ||||
|  |         msg: { | ||||
|  |             option: '设备删除', | ||||
|  |         }, | ||||
|  |     }); | ||||
|  | } | ||||
|  | 
 | ||||
|  | export function modifyDevice(id, params, msg) { | ||||
|  |     return (dispatch) => basicAction({ | ||||
|  |         type: 'put', | ||||
|  |         data: params, | ||||
|  |         dispatch, | ||||
|  |         actionType: 'MODIFY_Device_REPORT', | ||||
|  |         url: ApiTable.modifyDevice.replace('{id}', id), | ||||
|  |         msg: { | ||||
|  |             option: msg || '设备编辑', | ||||
|  |         }, | ||||
|  |     }); | ||||
|  | } | ||||
|  | 
 | ||||
| @ -0,0 +1,7 @@ | |||||
|  | 'use strict'; | ||||
|  | 
 | ||||
|  | import * as device from './device' | ||||
|  | 
 | ||||
|  | export default { | ||||
|  |     ...device | ||||
|  | } | ||||
| @ -0,0 +1,213 @@ | |||||
|  | 'use strict'; | ||||
|  | import React, { useState, useEffect } from 'react'; | ||||
|  | import { connect } from 'react-redux'; | ||||
|  | import moment from 'moment'; | ||||
|  | import { Modal, Form, Button, Upload, message } from 'antd'; | ||||
|  | import { DownloadOutlined } from '@ant-design/icons'; | ||||
|  | import XLSX from 'xlsx'; | ||||
|  | import { DEVICE_TYPES } from './modelModal'; | ||||
|  | // import porvince from './province.json'
 | ||||
|  | const workerKeys = { | ||||
|  |     name: '设备名称', | ||||
|  |     type: '设备类型', | ||||
|  |     specification: '规格型号', | ||||
|  |     dateProduced: '生产日期', | ||||
|  |     dateInstall: '安装时间', | ||||
|  |     dateGuarantee: '质保期', | ||||
|  |     dateMainten: '维保期', | ||||
|  | } | ||||
|  | //下载模板和上传文件读取
 | ||||
|  | const ImportDeviceModal = props => { | ||||
|  |     const { dispatch, actions, onCancel, onOk, devices } = props; | ||||
|  |     const { deviceManage } = actions; | ||||
|  |     const [msg, setMsg] = useState(''); | ||||
|  |     const [loading, setLoading] = useState(false); | ||||
|  |     const [postData, setPostData] = useState([]); | ||||
|  | 
 | ||||
|  |     //初始化
 | ||||
|  |     useEffect(() => { | ||||
|  | 
 | ||||
|  |     }, []); | ||||
|  | 
 | ||||
|  |     const confirm = () => { | ||||
|  |         if (postData.length) { | ||||
|  |             setLoading(true) | ||||
|  |             //导入明细接口通用
 | ||||
|  |             dispatch(deviceManage?.addDevice(postData)).then(res => { | ||||
|  |                 if (res.success) { | ||||
|  |                     onOk() | ||||
|  |                 } | ||||
|  |                 setLoading(false) | ||||
|  |             }) | ||||
|  |         } else { | ||||
|  |             message.warning({ content: '没有数据可以提交,请上传数据文件', duration: 2 }) | ||||
|  |         } | ||||
|  |     } | ||||
|  | 
 | ||||
|  |     const dldCsvMb = () => { | ||||
|  |         //表头
 | ||||
|  |         let head = []; | ||||
|  |         Object.keys(workerKeys).map(key => { | ||||
|  |             head.push(workerKeys[key]); | ||||
|  |         }) | ||||
|  |         head = head.join(',') + "\n"; | ||||
|  |         //数据
 | ||||
|  |         //let data = 1 + ',' + 2 + ',' + 3 + ',' + 4 + ',' + 5
 | ||||
|  |         let templateCsv = "data:text/xls;charset=utf-8,\ufeff" + head; | ||||
|  |         //创建一个a标签
 | ||||
|  |         let link = document.createElement("a"); | ||||
|  |         //为a标签设置属性
 | ||||
|  |         link.setAttribute("href", templateCsv); | ||||
|  |         link.setAttribute("download", `设备导入模板.xls`); | ||||
|  |         //点击a标签
 | ||||
|  |         link.click(); | ||||
|  |     } | ||||
|  |     const download = () => { | ||||
|  |         dldCsvMb(); | ||||
|  |     } | ||||
|  | 
 | ||||
|  |     const judgeTimeValid = (v) => { | ||||
|  |         let valid = true; | ||||
|  |         if (v.split('/').length !== 3) { | ||||
|  |             valid = false; | ||||
|  |         } else { | ||||
|  |             let time = new Date(v); | ||||
|  |             // if (!time) {
 | ||||
|  |             //     return valid;//可以不填
 | ||||
|  |             // }
 | ||||
|  |             const ymd = /^((19|20)[0-9]{2})[\/\-]((0[1-9])|(1[0-2]))[\/\-]((0[1-9])|((1|2)[0-9])|(3[0-1]))$/;//年月日
 | ||||
|  |             if (time instanceof Date) { | ||||
|  |                 let timeStr = moment(time).format('YYYY/MM/DD'); | ||||
|  |                 if (!ymd.test(timeStr)) { | ||||
|  |                     valid = false; | ||||
|  |                 } | ||||
|  |             } else { | ||||
|  |                 valid = false; | ||||
|  |             } | ||||
|  |         } | ||||
|  |         return valid; | ||||
|  |     } | ||||
|  | 
 | ||||
|  |     return (<Modal | ||||
|  |         title={"导入设备信息"} visible={true} | ||||
|  |         onOk={confirm} width={520} | ||||
|  |         confirmLoading={loading} | ||||
|  |         onCancel={() => { | ||||
|  |             setMsg('') | ||||
|  |             setLoading(false) | ||||
|  |             setPostData([]) | ||||
|  |             onCancel() | ||||
|  |         }} | ||||
|  |     > | ||||
|  |         <Form> | ||||
|  |             <Upload | ||||
|  |                 action={'/'} accept={'.xls,.xlsx'} | ||||
|  |                 maxCount={1} | ||||
|  |                 onRemove={(currentFile, fileList, fileItem) => { | ||||
|  |                     setMsg(''); | ||||
|  |                     setPostData([]); | ||||
|  |                 }} | ||||
|  |                 customRequest={async (data) => { | ||||
|  |                     const { file, onSuccess, onError } = data | ||||
|  |                     const error = (msg) => { | ||||
|  |                         setMsg(msg) | ||||
|  |                         onError({ message: msg }) | ||||
|  |                     } | ||||
|  |                     let isLt = file.size / 1024 / 1024 < 200 | ||||
|  |                     if (!isLt) { | ||||
|  |                         error(`文件最大不超过200M`); | ||||
|  |                         return; | ||||
|  |                     } | ||||
|  |                     const reader = new FileReader(); | ||||
|  |                     reader.onload = function (e) { | ||||
|  |                         const data = e.target.result; | ||||
|  |                         const workbook = XLSX.read(data, { type: 'binary', codepage: 936 }); | ||||
|  |                         const firstSheetName = workbook.SheetNames[0]; | ||||
|  |                         const worksheet = workbook.Sheets[firstSheetName]; | ||||
|  | 
 | ||||
|  |                         //XLSX.utils.sheet_to_json解析 ------把身份证号和手机号变成 字符串------
 | ||||
|  |                         Object.keys(worksheet).forEach(k => { | ||||
|  |                             worksheet[k].w ? worksheet[k].v = worksheet[k].w : '' | ||||
|  |                         }) | ||||
|  |                         //------------------end------------------
 | ||||
|  | 
 | ||||
|  |                         const res = XLSX.utils.sheet_to_json(worksheet); | ||||
|  | 
 | ||||
|  |                         if (res.length > 1000) { | ||||
|  |                             error('一次性上传数据行数应小于1000行,请分批上传') | ||||
|  |                             return | ||||
|  |                         } | ||||
|  |                         if (!res.length) { | ||||
|  |                             error('请填写至少一行数据') | ||||
|  |                             return | ||||
|  |                         } | ||||
|  |                         let postData = [] | ||||
|  | 
 | ||||
|  |                         for (let i = 0; i < res.length; i++) { | ||||
|  |                             let d = res[i] | ||||
|  |                             let obj = {}; | ||||
|  |                             Object.keys(workerKeys).map(key => { | ||||
|  |                                 obj[key] = d[workerKeys[key]] || null; | ||||
|  |                             }) | ||||
|  |                             //必填项
 | ||||
|  |                             let notNullKeys = ['name', 'type', 'specification', 'dateProduced', 'dateGuarantee', 'dateMainten', 'dateInstall'] | ||||
|  |                             for (let k = 0; k < notNullKeys.length; k++) { | ||||
|  |                                 let key = notNullKeys[k]; | ||||
|  |                                 if (!obj[key]) { | ||||
|  |                                     error(`第${i + 2}行【${workerKeys[key]}】不能为空`) | ||||
|  |                                     return | ||||
|  |                                 } | ||||
|  |                             } | ||||
|  |                             | ||||
|  |                             //判断设备类型
 | ||||
|  |                             let ext = DEVICE_TYPES.find(m => m == obj.type); | ||||
|  |                             if (!ext) { | ||||
|  |                                 error(`第${i + 2}行的【设备类型】错误,请填写【${DEVICE_TYPES.toString()}】中的一种`) | ||||
|  |                                 return | ||||
|  |                             } | ||||
|  | 
 | ||||
|  |                             let tValid = judgeTimeValid(obj.dateProduced) && judgeTimeValid(obj.dateGuarantee) | ||||
|  |                                 && judgeTimeValid(obj.dateMainten) && judgeTimeValid(obj.dateInstall); | ||||
|  |                             if (!tValid) { | ||||
|  |                                 error(`第${i + 2}行【日期格式】错误,请填写yyyy/mm/dd格式`) | ||||
|  |                                 return; | ||||
|  |                             } | ||||
|  | 
 | ||||
|  |                             let dateInstallValid = moment(obj.dateInstall).valueOf() > moment().startOf('d').add(1, 'd').valueOf(); | ||||
|  |                             if (dateInstallValid) { | ||||
|  |                                 error(`第${i + 2}行【安装日期】不能填写今天之后的时间`) | ||||
|  |                                 return; | ||||
|  |                             } | ||||
|  | 
 | ||||
|  | 
 | ||||
|  | 
 | ||||
|  |                             postData.push(obj) | ||||
|  |                         } | ||||
|  |                         setPostData(postData) | ||||
|  |                         let msg = '文件解析完成,点击确定按钮上传保存!' | ||||
|  |                         setMsg(msg) | ||||
|  |                         onSuccess({ message: msg }) | ||||
|  |                     } | ||||
|  |                     reader.readAsBinaryString(file); | ||||
|  |                 }}> | ||||
|  |                 <Button icon={<DownloadOutlined />} theme="light"> | ||||
|  |                     请选择文件 | ||||
|  |                 </Button> | ||||
|  |             </Upload> | ||||
|  |             <span>{msg}</span> | ||||
|  |             <div style={{ color: '#ccc', marginTop: 20 }}>最大不超过200M,导入文件需与 | ||||
|  |                 <span onClick={() => download()} style={{ cursor: 'pointer', color: '#0066FF' }}>导入模板</span> | ||||
|  |                 一致</div> | ||||
|  |         </Form> | ||||
|  |     </Modal>) | ||||
|  | } | ||||
|  | 
 | ||||
|  | function mapStateToProps(state) { | ||||
|  |     const { auth, global } = state; | ||||
|  |     return { | ||||
|  |         user: auth.user, | ||||
|  |         actions: global.actions, | ||||
|  |     } | ||||
|  | } | ||||
|  | 
 | ||||
|  | export default connect(mapStateToProps)(ImportDeviceModal); | ||||
| @ -0,0 +1,111 @@ | |||||
|  | import React, { useRef } from 'react'; | ||||
|  | import { Button, Form } from 'antd'; | ||||
|  | import { InfoCircleOutlined } from '@ant-design/icons'; | ||||
|  | import { | ||||
|  |     ModalForm, | ||||
|  |     ProFormSelect, | ||||
|  |     ProFormText, | ||||
|  |     ProFormDatePicker | ||||
|  | } from '@ant-design/pro-form'; | ||||
|  | import moment from 'moment'; | ||||
|  | export default (props) => { | ||||
|  |     const { title, triggerRender, editData = null, onFinish, devices } = props; | ||||
|  |     const formItemLayout = { labelCol: { span: 6 }, wrapperCol: { span: 16 } }; | ||||
|  |     const initialValues = editData ? { | ||||
|  |         ...editData, | ||||
|  |     } : {}; | ||||
|  |     const [form] = Form.useForm(); | ||||
|  |     const formRef = useRef(); | ||||
|  |     const disabledDate = (value) => { | ||||
|  |         return value.valueOf() > moment().startOf('d').add(1, 'd').valueOf(); | ||||
|  |     } | ||||
|  |     return ( | ||||
|  |         <ModalForm | ||||
|  |             formRef={formRef} | ||||
|  |             title={title || ''} | ||||
|  |             initialValues={initialValues} | ||||
|  |             trigger={ | ||||
|  |                 triggerRender ? triggerRender : <Button type="primary" > | ||||
|  |                     {title || ''} | ||||
|  |                 </Button> | ||||
|  |             } | ||||
|  |             layout="horizontal" | ||||
|  |             grid={true} | ||||
|  |             {...formItemLayout} | ||||
|  |             modalProps={{ | ||||
|  |                 destroyOnClose: true, | ||||
|  |                 onCancel: () => { }, | ||||
|  |             }} | ||||
|  |             onFinish={async (values) => { | ||||
|  |                 return onFinish && await onFinish(values, editData, form) | ||||
|  |                 // return true;
 | ||||
|  |             }} | ||||
|  |             width={500} | ||||
|  |         > | ||||
|  | 
 | ||||
|  | 
 | ||||
|  |             <ProFormText | ||||
|  |                 rules={[ | ||||
|  |                     { required: true, message: '请输入设备名称' }, | ||||
|  |                     { max: 255, message: '设备名称长度不能大于255个字符' }, | ||||
|  |                 ]} | ||||
|  |                 name="name" | ||||
|  |                 label="设备名称" | ||||
|  |             /> | ||||
|  | 
 | ||||
|  |             <ProFormSelect | ||||
|  |                 rules={[{ required: true, message: '请选择设备类型' }]} | ||||
|  |                 options={ | ||||
|  |                     DEVICE_TYPES | ||||
|  |                         .map(s => { | ||||
|  |                             return { label: s, value: s } | ||||
|  |                         }) | ||||
|  |                 } | ||||
|  |                 name="type" | ||||
|  |                 label="设备类型" | ||||
|  |             /> | ||||
|  | 
 | ||||
|  |             <ProFormText | ||||
|  |                 rules={[ | ||||
|  |                     { required: true, message: '请输入规格型号' }, | ||||
|  |                     { max: 20, message: '规格型号长度不能大于20个字符' }, | ||||
|  |                 ]} | ||||
|  |                 name="specification" | ||||
|  |                 label="规格型号" | ||||
|  |             /> | ||||
|  | 
 | ||||
|  |             <ProFormDatePicker | ||||
|  |                 rules={[{ required: true, message: '请输入生产日期' }]} | ||||
|  |                 name="dateProduced" | ||||
|  |                 label="生产日期" | ||||
|  |                 fieldProps={ | ||||
|  |                     { disabledDate: disabledDate } | ||||
|  |                 } | ||||
|  | 
 | ||||
|  |             /> | ||||
|  |             <ProFormDatePicker | ||||
|  |                 rules={[{ required: true, message: '请输入安装日期' }]} | ||||
|  |                 name="dateInstall" | ||||
|  |                 label="安装日期" | ||||
|  |                 fieldProps={ | ||||
|  |                     { disabledDate: disabledDate } | ||||
|  |                 } | ||||
|  | 
 | ||||
|  |             /> | ||||
|  |             <ProFormDatePicker | ||||
|  |                 rules={[{ required: true, message: '请输入质保期' }]} | ||||
|  |                 name="dateGuarantee" | ||||
|  |                 label="质保期" | ||||
|  |             /> | ||||
|  |             <ProFormDatePicker | ||||
|  |                 rules={[{ required: true, message: '请输入维保期' }]} | ||||
|  |                 name="dateMainten" | ||||
|  |                 label="维保期" | ||||
|  |             /> | ||||
|  | 
 | ||||
|  |         </ModalForm> | ||||
|  |     ); | ||||
|  | }; | ||||
|  | 
 | ||||
|  | export const DEVICE_TYPES = ['安防系统', '厨房系统', '电梯', '供电系统', '空调', '排水系统', '水系统', '通道门禁', | ||||
|  |     '通风系统', '通信系统', '显示视频', '消防系统', '照明系统'] | ||||
| @ -0,0 +1,254 @@ | |||||
|  | import React, { useEffect, useState } from 'react' | ||||
|  | import { Spin, Popconfirm, message, Button, Input } from 'antd'; | ||||
|  | import { connect } from 'react-redux'; | ||||
|  | import ProTable from '@ant-design/pro-table'; | ||||
|  | import DeviceModal from '../components/modelModal' | ||||
|  | import moment from 'moment'; | ||||
|  | import ImportDeviceModal from '../components/importDevicesModal' | ||||
|  | function DeviceManagement(props) { | ||||
|  |     const { loading, clientHeight, actions, dispatch, devices } = props; | ||||
|  |     const [pageSize, setPageSize] = useState(10); | ||||
|  |     const [currentPage, setCurrentPage] = useState(1); | ||||
|  |     const [rowSelected, setRowSelected] = useState([]) | ||||
|  |     const [showImportModal, setShowImportModal] = useState(false); | ||||
|  |     const [name, setName] = useState(); | ||||
|  | 
 | ||||
|  |     const queryData = (search) => { | ||||
|  |         const query = { | ||||
|  |             limit: search ? 10 : pageSize || 10, | ||||
|  |             page: search ? 1 : currentPage || 1, | ||||
|  |             name: name | ||||
|  |         } | ||||
|  |         dispatch(actions.deviceManage.getDeviceList(query)); | ||||
|  |     } | ||||
|  | 
 | ||||
|  |     useEffect(() => { | ||||
|  |         queryData(); | ||||
|  |     }, [pageSize, currentPage]); | ||||
|  | 
 | ||||
|  |     const handleDelete = (id) => { | ||||
|  |         dispatch(actions.deviceManage.deleteDevice(id)).then(() => { | ||||
|  |             queryData(); | ||||
|  |             setRowSelected([]) | ||||
|  |         }); | ||||
|  |     }; | ||||
|  | 
 | ||||
|  |     const onFinish = async (values, editData) => { | ||||
|  |         if (editData) { | ||||
|  |             const dataToSave = { ...values } | ||||
|  |             return dispatch( | ||||
|  |                 actions.deviceManage.modifyDevice(editData.id, dataToSave, values?.msg || ''), | ||||
|  |             ).then((res) => { | ||||
|  |                 if (res.success) { | ||||
|  |                     queryData(); | ||||
|  |                     return true; | ||||
|  |                 } else { | ||||
|  |                     return false; | ||||
|  |                 } | ||||
|  |             }); | ||||
|  |         } | ||||
|  | 
 | ||||
|  |         return dispatch(actions.deviceManage.addDevice({ | ||||
|  |             ...values, | ||||
|  |         })).then(res => { | ||||
|  |             if (res.success) { | ||||
|  |                 queryData(); | ||||
|  |                 return true; | ||||
|  |             } else { | ||||
|  |                 return false; | ||||
|  |             } | ||||
|  |         }); | ||||
|  |     }; | ||||
|  | 
 | ||||
|  |     const columns = [ | ||||
|  |         { | ||||
|  |             title: '设备名称', | ||||
|  |             dataIndex: 'name', | ||||
|  |             ellipsis: true, | ||||
|  |         }, | ||||
|  |         { | ||||
|  |             title: '设备类型', | ||||
|  |             dataIndex: 'type', | ||||
|  |             ellipsis: true, | ||||
|  |         }, | ||||
|  |         { | ||||
|  |             title: '规格型号', | ||||
|  |             dataIndex: 'specification', | ||||
|  |             ellipsis: true, | ||||
|  |         }, | ||||
|  |         { | ||||
|  |             title: '生产日期', | ||||
|  |             dataIndex: 'dateProduced', | ||||
|  |             ellipsis: true, | ||||
|  |         }, | ||||
|  |         { | ||||
|  |             title: '安装时间', | ||||
|  |             dataIndex: 'dateInstall', | ||||
|  |             ellipsis: true, | ||||
|  |         }, | ||||
|  |         { | ||||
|  |             title: '质保期', | ||||
|  |             dataIndex: 'dateGuarantee', | ||||
|  |             ellipsis: true, | ||||
|  |             search: false, | ||||
|  |         }, | ||||
|  |         { | ||||
|  |             title: '维保期', | ||||
|  |             dataIndex: 'dateMainten', | ||||
|  |             ellipsis: true, | ||||
|  |         }, | ||||
|  |         { | ||||
|  |             title: '设备投入使用时长', | ||||
|  |             dataIndex: 'length', | ||||
|  |             ellipsis: true, | ||||
|  |             render: (text, record) => { | ||||
|  |                 const start = moment(record?.dateInstall); | ||||
|  |                 const end = moment(); | ||||
|  |                 const days = end.diff(start, 'days'); | ||||
|  | 
 | ||||
|  |                 return days + '天' | ||||
|  |             } | ||||
|  | 
 | ||||
|  |         }, | ||||
|  |         { | ||||
|  |             title: '操作', | ||||
|  |             width: 160, | ||||
|  |             key: 'option', | ||||
|  |             valueType: 'option', | ||||
|  |             render: (text, record) => { | ||||
|  |                 const options = []; | ||||
|  |                 options.push(<DeviceModal | ||||
|  |                     triggerRender={<a>编辑</a>} | ||||
|  |                     editData={record} | ||||
|  |                     title="编辑设备" | ||||
|  |                     onFinish={onFinish} | ||||
|  |                     key="editModel" | ||||
|  |                 />) | ||||
|  | 
 | ||||
|  |                 options.push( | ||||
|  |                     <Popconfirm | ||||
|  |                         key="del" | ||||
|  |                         placement="top" | ||||
|  |                         title="是否确认删除该设备?" | ||||
|  |                         onConfirm={() => handleDelete(record.id)} | ||||
|  |                         okText="是" | ||||
|  |                         cancelText="否" | ||||
|  |                     > | ||||
|  |                         <a>删除</a> | ||||
|  |                     </Popconfirm>) | ||||
|  | 
 | ||||
|  |                 return options; | ||||
|  | 
 | ||||
|  |             }, | ||||
|  |         }, | ||||
|  |     ]; | ||||
|  | 
 | ||||
|  |     return <div id='patrol-record' className='global-main'> | ||||
|  |         <Spin spinning={loading}> | ||||
|  |             <div style={{ marginBottom: 19 }}> | ||||
|  |                 <div className='top' style={{ marginBottom: 19 }}> | ||||
|  |                     <div className='title'> | ||||
|  |                         <span className='line'></span> | ||||
|  |                         <span className='cn'>设备管理</span> | ||||
|  |                         <span className='en'> DEVICE</span> | ||||
|  |                     </div> | ||||
|  |                     <div> | ||||
|  |                         <DeviceModal | ||||
|  |                             triggerRender={<Button type='primary'>新建</Button>} | ||||
|  |                             title="新建设备" | ||||
|  |                             onFinish={onFinish} | ||||
|  |                             key="addModel" | ||||
|  |                         /> | ||||
|  |                         <Button type="primary" style={{ marginRight: 10, marginLeft: 10 }} onClick={() => { setShowImportModal(true) }}>批量新增</Button> | ||||
|  |                         <Popconfirm title="确认删除?" onConfirm={() => { | ||||
|  |                             rowSelected?.length > 0 ? handleDelete(rowSelected?.toString()) : message.warning('请先选择要删除的设备') | ||||
|  |                         }}> | ||||
|  |                             <Button>批量删除</Button> | ||||
|  |                         </Popconfirm> | ||||
|  | 
 | ||||
|  |                         <Input onChange={e => setName(e?.target?.value)} style={{ width: '13vw', marginLeft: 20, marginRight: 10 }} /> | ||||
|  |                         <Button type="primary" onClick={() => { | ||||
|  |                             setPageSize(10) | ||||
|  |                             setCurrentPage(1) | ||||
|  |                             queryData(true) | ||||
|  |                         }}>查询</Button> | ||||
|  |                     </div> | ||||
|  |                 </div> | ||||
|  |             </div> | ||||
|  |             <ProTable | ||||
|  |                 columns={columns} | ||||
|  |                 rowKey="id" | ||||
|  | 
 | ||||
|  |                 dateFormatter="string" | ||||
|  |                 scroll={ | ||||
|  |                     { | ||||
|  |                         scrollToFirstRowOnChange: true, | ||||
|  |                         y: clientHeight - 260 | ||||
|  |                     } | ||||
|  |                 } | ||||
|  |                 pagination={{ | ||||
|  |                     size: 'large', | ||||
|  |                     total: devices?.count, | ||||
|  |                     showSizeChanger: true, | ||||
|  |                     // showQuickJumper: true,
 | ||||
|  |                     current: currentPage, | ||||
|  |                     pageSize: pageSize || 10, | ||||
|  |                     pageSizeOptions: [10, 20, 50], | ||||
|  |                     showTotal: (total) => { | ||||
|  |                         return <span style={{ fontSize: 15 }}>{`共${Math.ceil(total / pageSize)}页,${total}项`}</span> | ||||
|  |                     }, | ||||
|  |                     onShowSizeChange: (currentPage, pageSize) => { | ||||
|  |                         setCurrentPage(currentPage); | ||||
|  |                         setPageSize(pageSize); | ||||
|  |                     }, | ||||
|  |                     onChange: (page, pageSize) => { | ||||
|  |                         setCurrentPage(page); | ||||
|  |                         setPageSize(pageSize); | ||||
|  |                     } | ||||
|  |                 }} | ||||
|  |                 dataSource={devices?.rows || []} | ||||
|  |                 rowSelection={{ | ||||
|  |                     selectedRowKeys: rowSelected, | ||||
|  |                     onChange: (selectedRowKeys) => { | ||||
|  |                         setRowSelected(selectedRowKeys); | ||||
|  |                     }, | ||||
|  |                     getCheckboxProps: (record) => { | ||||
|  |                         return { | ||||
|  |                             disabled: record.username === 'SuperAdmin', | ||||
|  |                         } | ||||
|  |                     } | ||||
|  |                 }} | ||||
|  |                 options={false} | ||||
|  |                 search={false} | ||||
|  |             /> | ||||
|  |             {showImportModal && <ImportDeviceModal | ||||
|  |                 devices={devices?.rows || []} | ||||
|  |                 onCancel={() => { | ||||
|  |                     setShowImportModal(false) | ||||
|  |                 }} | ||||
|  |                 onOk={() => { | ||||
|  |                     setShowImportModal(false) | ||||
|  |                     queryData() | ||||
|  |                 }} | ||||
|  |             />} | ||||
|  |         </Spin> | ||||
|  |     </div> | ||||
|  | 
 | ||||
|  | 
 | ||||
|  | } | ||||
|  | 
 | ||||
|  | function mapStateToProps(state) { | ||||
|  |     const { | ||||
|  |         auth, global, device | ||||
|  |     } = state; | ||||
|  |     return { | ||||
|  |         loading: device.isRequesting, | ||||
|  |         clientHeight: global.clientHeight, | ||||
|  |         actions: global.actions, | ||||
|  |         devices: device?.data || {} | ||||
|  |     }; | ||||
|  | } | ||||
|  | 
 | ||||
|  | export default connect(mapStateToProps)(DeviceManagement); | ||||
|  | 
 | ||||
|  | 
 | ||||
| @ -0,0 +1,5 @@ | |||||
|  | 'use strict'; | ||||
|  | 
 | ||||
|  | import DeviceManage from './deviceManage' | ||||
|  | 
 | ||||
|  | export { DeviceManage }; | ||||
| @ -0,0 +1,15 @@ | |||||
|  | 'use strict'; | ||||
|  | 
 | ||||
|  | import reducers from './reducers'; | ||||
|  | import routes from './routes'; | ||||
|  | import actions from './actions'; | ||||
|  | import { getNavItem } from './nav-item'; | ||||
|  | 
 | ||||
|  | export default { | ||||
|  |     key: 'deviceManage', | ||||
|  |     name: '设备管理', | ||||
|  |     reducers: reducers, | ||||
|  |     routes: routes, | ||||
|  |     actions: actions, | ||||
|  |     getNavItem: getNavItem | ||||
|  | }; | ||||
| @ -0,0 +1,13 @@ | |||||
|  | import React from 'react'; | ||||
|  | import { Link } from 'react-router-dom'; | ||||
|  | import { Menu } from 'antd'; | ||||
|  | import { Func } from '$utils'; | ||||
|  | export function getNavItem(user, dispatch) { | ||||
|  |     return ( | ||||
|  |         <Menu.Item icon={<img src='/assets/images/menu/device.png' style={{ width: 24, height: 24 }} />} | ||||
|  |             key="deviceManage"> | ||||
|  |             <Link to="/deviceManage">设备管理</Link> | ||||
|  |         </Menu.Item> | ||||
|  | 
 | ||||
|  |     ); | ||||
|  | } | ||||
| @ -0,0 +1,5 @@ | |||||
|  | 'use strict'; | ||||
|  | 
 | ||||
|  | export default { | ||||
|  | 
 | ||||
|  | } | ||||
| @ -0,0 +1,13 @@ | |||||
|  | 'use strict'; | ||||
|  | import { DeviceManage } from './containers'; | ||||
|  | 
 | ||||
|  | export default [{ | ||||
|  |     type: 'inner', | ||||
|  |     route: { | ||||
|  |         path: '/deviceManage', | ||||
|  |         key: 'deviceManage', | ||||
|  |         breadcrumb: '设备管理', | ||||
|  |         component: DeviceManage, | ||||
|  | 
 | ||||
|  |     } | ||||
|  | }]; | ||||