Commit 594624ad5577a667a045be4df644859a275f81c8

Authored by fengwotao
1 parent 5d828370

pref: app、mp端 优化告警和设备代码

1 <script> 1 <script>
2 import store from '@/store'; 2 import store from '@/store';
3 - // import {  
4 - // scene  
5 - // } from '@/config/common';  
6 3
7 export default { 4 export default {
8 //设置全局变量,解绑时从这里取 5 //设置全局变量,解绑时从这里取
@@ -10,27 +7,12 @@ @@ -10,27 +7,12 @@
10 openId: '' 7 openId: ''
11 }, 8 },
12 onLaunch(e) { 9 onLaunch(e) {
13 - //取出缓存数据  
14 - // store.commit('setCacheData');  
15 - //获取二维码信息  
16 - // scene(e);  
17 // #ifdef APP-PLUS 10 // #ifdef APP-PLUS
18 uni.reLaunch({ 11 uni.reLaunch({
19 url: '/pages/index/splash' 12 url: '/pages/index/splash'
20 }) 13 })
21 // #endif 14 // #endif
22 }, 15 },
23 - onShow(e) {  
24 - // #ifdef MP  
25 - // mpUpData(); //检测小程序更新  
26 - // #endif  
27 - // #ifdef APP-PLUS  
28 - // uni.reLaunch({  
29 - // url: '/pages/index/splash'  
30 - // })  
31 - // #endif  
32 - },  
33 - onHide() {},  
34 onUnload(){ 16 onUnload(){
35 uni.setStorageSync('getConfiguration', { 17 uni.setStorageSync('getConfiguration', {
36 isConfiguration: false 18 isConfiguration: false
@@ -4,59 +4,17 @@ @@ -4,59 +4,17 @@
4 <public-module></public-module> 4 <public-module></public-module>
5 <view class="alarm-detail-column"> 5 <view class="alarm-detail-column">
6 <view class="u-flex detail-column"> 6 <view class="u-flex detail-column">
7 - <view class="u-flex column">  
8 - <text  
9 - class="text-clip device-name text-org-bold">{{ list.deviceName == null ? '暂无数据' : list.deviceName }}</text>  
10 - <image class="image" src="/static/alarm-device.png"></image>  
11 - </view>  
12 - <view class="column">  
13 - <text class="text-org-bold ">告警级别:</text>  
14 - <text class="text-device-muted" style="color:#DE4437">  
15 - {{  
16 - list.severity == 'CRITICAL'  
17 - ? '危险'  
18 - : list.severity == 'MAJOR'  
19 - ? '重要'  
20 - : list.severity == 'MINOR'  
21 - ? '次要'  
22 - : list.severity == 'WARNING'  
23 - ? '警告'  
24 - : '不确定'  
25 - }}  
26 - </text>  
27 - </view>  
28 - <view class="column">  
29 - <text class="text-org-bold">所属组织:</text>  
30 - <text  
31 - class="text-device-muted">{{ list.organizationName == null ? '暂无数据' : list.organizationName }}</text>  
32 - </view>  
33 - <view class="column">  
34 - <text class="text-org-bold">告警值:</text>  
35 - <text  
36 - class="text-device-muted text-clip">{{ list.details == null ? '暂无数据' : formatDetailText(list.details.data) }}</text>  
37 - </view>  
38 - <view class="column">  
39 - <text class="text-org-bold">告警场景:</text>  
40 - <text  
41 - class="text-device-muted text-clip">{{ list.type == null ? '暂无数据' : list.type }}</text>  
42 - </view>  
43 - <view class="column">  
44 - <text class="text-org-bold">告警时间:</text>  
45 - <text class="text-device-muted">{{ list.createdTime }}</text>  
46 - </view>  
47 - <view class="column">  
48 - <text class="text-org-bold">告警状态:</text>  
49 - <text class="text-device-muted" style="color: #DE4437;">  
50 - {{  
51 - list.status == 'CLEARED_UNACK'  
52 - ? '清除未确认'  
53 - : list.status == 'ACTIVE_UNACK'  
54 - ? '激活未确认'  
55 - : list.status == 'CLEARED_ACK'  
56 - ? '清除已确认'  
57 - : '激活已确认'  
58 - }}  
59 - </text> 7 + <view class="column-line" v-for="(item,index) in alarmDetail" :key="index">
  8 + <view class="column">
  9 + <text class="text-org-bold">{{item.label}}</text>
  10 + <text class="text-device-muted text-clip alarm-text"
  11 + :style="{color:hasColor.includes(item.label)?'#DE4437':''}">
  12 + {{item.label===hasColor[0]? setAlarmStatus(item.value):item.label===hasColor[1]?setAlarmSeverity(item.value):
  13 + item.label==='告警值:'?formatAlarmValueText:item.label==='告警条件:'?formatAlarmConditionText
  14 + :item.label==='告警设备:'?formatDeviceText:item.value}}
  15 + </text>
  16 + </view>
  17 + <view class="bottom-line"></view>
60 </view> 18 </view>
61 </view> 19 </view>
62 </view> 20 </view>
@@ -83,17 +41,11 @@ @@ -83,17 +41,11 @@
83 </view> 41 </view>
84 </view> 42 </view>
85 <!-- #endif --> 43 <!-- #endif -->
86 - <view style="margin-top: 44rpx;display: flex;align-items: center;justify-content: space-between;">  
87 - <view :style="[  
88 - { position: list.status !== 'CLEARED_ACK' && list.status !== 'ACTIVE_ACK' ? 'relative' : '' },  
89 - { right: list.status !== 'CLEARED_ACK' && list.status !== 'ACTIVE_ACK' ? '-210rpx' : '' }  
90 - ]" v-if="list.status !== 'CLEARED_ACK' && list.status !== 'ACTIVE_ACK'" class="u-flex" style="width: 260rpx"> 44 + <view class="bottom-button">
  45 + <view v-if="handleText.includes(alarmDetail[7].value)" class="u-flex button-item">
91 <u-button @click="handleSubmit" type="primary" shape="circle" text="处理"></u-button> 46 <u-button @click="handleSubmit" type="primary" shape="circle" text="处理"></u-button>
92 </view> 47 </view>
93 - <view style="width: 30rpx;"></view>  
94 - <view  
95 - :style="[{ position: list.status == 'ACTIVE_ACK' ? 'relative' : '' }, { right: list.status == 'ACTIVE_ACK' ? '207rpx' : '' }]"  
96 - v-if="list.status == 'ACTIVE_ACK'" class="u-flex" style="width: 260rpx"> 48 + <view v-if="clearText.includes(alarmDetail[7].value)" class="u-flex button-item">
97 <u-button @click="handleRemove" type="error" shape="circle" text="清除"></u-button> 49 <u-button @click="handleRemove" type="error" shape="circle" text="清除"></u-button>
98 </view> 50 </view>
99 </view> 51 </view>
@@ -105,61 +57,124 @@ @@ -105,61 +57,124 @@
105 mapActions 57 mapActions
106 } from 'vuex' 58 } from 'vuex'
107 import api from '@/api/index.js' 59 import api from '@/api/index.js'
  60 + import {
  61 + alarmSeverity,
  62 + alarmStatus,
  63 + operationNumberOrDate,
  64 + operationString,
  65 + operationBoolean
  66 + } from '@/pages/alarm/config/data.js';
  67 + import {
  68 + useShowToast,
  69 + useNavigateBack
  70 + } from '@/plugins/utils.js'
108 71
109 export default { 72 export default {
110 data() { 73 data() {
111 return { 74 return {
  75 + handleText: ['ACTIVE_UNACK', 'CLEARED_UNACK'],
  76 + clearText: ['ACTIVE_UNACK', 'ACTIVE_ACK'],
  77 + hasColor: ['告警级别:', '告警状态:'],
  78 + alarmSeverity,
  79 + alarmStatus,
  80 + operationNumberOrDate,
  81 + operationString,
  82 + operationBoolean,
112 formModel: { 83 formModel: {
113 result: '' 84 result: ''
114 }, 85 },
115 - list: {} 86 + detailId: '',
  87 + alarmDetail: [],
  88 + formatDeviceText: '',
  89 + formatAlarmValueText: '',
  90 + formatAlarmConditionText: '',
116 }; 91 };
117 }, 92 },
118 onLoad(e) { 93 onLoad(e) {
119 if (e.data !== null) { 94 if (e.data !== null) {
120 - let params = JSON.parse(e.data);  
121 - this.list = params; 95 + let params = JSON.parse(decodeURIComponent(e.data));
  96 + const {
  97 + deviceName,
  98 + severity,
  99 + organizationName,
  100 + details,
  101 + type,
  102 + createdTime,
  103 + status,
  104 + id
  105 + } = params
  106 + this.detailId = id
  107 + this.alarmDetail = [{
  108 + label: '告警场景:',
  109 + value: type
  110 + },
  111 + {
  112 + label: '告警级别:',
  113 + value: severity
  114 + },
  115 + {
  116 + label: '所属组织:',
  117 + value: organizationName
  118 + },
  119 + {
  120 + label: '告警设备:',
  121 + value: ''
  122 + },
  123 + {
  124 + label: '告警条件:',
  125 + value: ''
  126 + },
  127 + {
  128 + label: '告警值:',
  129 + value: ''
  130 + },
  131 + {
  132 + label: '告警时间:',
  133 + value: createdTime
  134 + },
  135 + {
  136 + label: '告警状态:',
  137 + value: status
  138 + },
  139 + ]
  140 + this.formatAlarmDevice(details)
  141 + this.formatAlarmValue(details)
  142 + this.formatAlarmCondition(details)
122 } 143 }
123 // 隐藏原生的tabbar 144 // 隐藏原生的tabbar
124 uni.hideTabBar(); 145 uni.hideTabBar();
125 }, 146 },
126 methods: { 147 methods: {
127 - //处理 148 + ...mapActions(['updateBadgeTotal']),
  149 + setAlarmStatus(value) {
  150 + return this.alarmSeverity.find(item => item.value === value).label
  151 + },
  152 + setAlarmSeverity(value) {
  153 + return this.alarmStatus.find(item => item.value === value).label
  154 + },
  155 + returnPrevPage(title) {
  156 + useShowToast(title)
  157 + let pages = getCurrentPages(); //获取所有页面栈实例列表
  158 + let nowPage = pages[pages.length - 1]; //当前页页面实例
  159 + let prevPage = pages[pages.length - 2]; //上一页页面实例
  160 + prevPage.$vm.detailStatus = true;
  161 + },
128 async handleSubmit() { 162 async handleSubmit() {
129 if (this.formModel.result == '') return uni.$u.toast('请输入处理结果'); 163 if (this.formModel.result == '') return uni.$u.toast('请输入处理结果');
130 - const res = await api.alarmApi.postAlarmAckApi(this.list.id) 164 + const res = await api.alarmApi.postAlarmAckApi(this.detailId)
131 if (res == '') { 165 if (res == '') {
132 - uni.showToast({  
133 - title: '处理成功~',  
134 - icon: 'none'  
135 - });  
136 - let pages = getCurrentPages(); //获取所有页面栈实例列表  
137 - let nowPage = pages[pages.length - 1]; //当前页页面实例  
138 - let prevPage = pages[pages.length - 2]; //上一页页面实例  
139 - prevPage.$vm.detailStatus = true; 166 + this.returnPrevPage('处理成功~')
140 setTimeout(() => { 167 setTimeout(() => {
141 - uni.navigateBack({  
142 - delta: 1  
143 - }); 168 + useNavigateBack(1)
144 }, 500); 169 }, 500);
145 } 170 }
146 }, 171 },
147 - // 清除  
148 async handleRemove() { 172 async handleRemove() {
149 - const res = await api.alarmApi.postAlarmClearApi(this.list.id) 173 + const res = await api.alarmApi.postAlarmClearApi(this.detailId)
150 if (res == '') { 174 if (res == '') {
151 - uni.showToast({  
152 - title: '清除成功~',  
153 - icon: 'none'  
154 - });  
155 - let pages = getCurrentPages(); //获取所有页面栈实例列表  
156 - let nowPage = pages[pages.length - 1]; //当前页页面实例  
157 - let prevPage = pages[pages.length - 2]; //上一页页面实例  
158 - prevPage.$vm.detailStatus = true; 175 + this.returnPrevPage('清除成功~')
159 setTimeout(async () => { 176 setTimeout(async () => {
160 - uni.navigateBack({  
161 - delta: 1  
162 - }); 177 + useNavigateBack(1)
163 const res = await uni.$u.http.get('/yt/homepage/app?login=true'); 178 const res = await uni.$u.http.get('/yt/homepage/app?login=true');
164 if (res) { 179 if (res) {
165 //异步实时更新告警徽标数 180 //异步实时更新告警徽标数
@@ -168,13 +183,74 @@ @@ -168,13 +183,74 @@
168 }, 500); 183 }, 500);
169 } 184 }
170 }, 185 },
171 - ...mapActions(['updateBadgeTotal']),  
172 - formatDetailText(e) {  
173 - //去除字符串双引号  
174 - const jsonStr = JSON.stringify(e);  
175 - const str = jsonStr.substring(1, jsonStr.length - 1);  
176 - const newStr = str.replace(/\"/g, '');  
177 - return newStr.slice(0,26); 186 + async formatAlarmValue(e) {
  187 + const keys = Object.keys(e)
  188 + const dataFormat = await this.handleAlarmDetailFormat(keys);
  189 + const values = keys.reduce((acc, curr) => {
  190 + dataFormat.forEach((dataItem => {
  191 + if (dataItem.tbDeviceId === curr) {
  192 + const findAttribute = dataItem.attribute.find(findItem => findItem
  193 + .identifier === e[curr].key)
  194 + acc.push(
  195 + `${findAttribute.name}:${e[curr].realValue}${findAttribute.detail?.dataType?.specs?.unit?.key}`
  196 + )
  197 + }
  198 + }))
  199 + return acc
  200 + }, [])
  201 + this.formatAlarmValueText = values.join(',')
  202 + },
  203 + formatAlarmCondition(e) {
  204 + const keys = Object.keys(e)
  205 + const values = keys.reduce((acc, curr) => {
  206 + acc.push({
  207 + login: e[curr].logic,
  208 + logicValue: e[curr].logicValue
  209 + })
  210 + return acc
  211 + }, [])
  212 + const operation = [...operationNumberOrDate, ...operationString, ...operationBoolean]
  213 + const format = values.map(item => {
  214 + const findOperation = operation.find(findItem => findItem.value === item.login)?.symbol
  215 + return findOperation + item.logicValue
  216 + })
  217 + this.formatAlarmConditionText = format
  218 + },
  219 + async formatAlarmDevice(e) {
  220 + const keys = Object.keys(e)
  221 + const dataFormat = await this.handleAlarmDetailFormat(keys);
  222 + this.formatDeviceText = dataFormat.map(item => item.name).join(',')
  223 + },
  224 + async handleAlarmDetailFormat(keys) {
  225 + const temp = [];
  226 + for (let item of keys) {
  227 + if (item === 'key' || item === 'data') return; //旧数据则终止
  228 + const deviceDetailRes = await api.deviceApi.getDeviceDetail(item);
  229 + const {
  230 + deviceProfileId
  231 + } = deviceDetailRes;
  232 + if (!deviceProfileId) return;
  233 + const attributeRes = await api.deviceApi.getAttribute(deviceProfileId);
  234 + const dataFormat = this.handleDataFormat(deviceDetailRes, attributeRes);
  235 + temp.push(dataFormat);
  236 + }
  237 + return temp;
  238 + },
  239 + handleDataFormat(deviceDetail, attributes) {
  240 + const {
  241 + name,
  242 + tbDeviceId
  243 + } = deviceDetail;
  244 + const attribute = attributes.map((item) => ({
  245 + identifier: item.identifier,
  246 + name: item.name,
  247 + detail: item.detail
  248 + }));
  249 + return {
  250 + name,
  251 + tbDeviceId,
  252 + attribute,
  253 + };
178 } 254 }
179 } 255 }
180 }; 256 };
@@ -187,4 +263,4 @@ @@ -187,4 +263,4 @@
187 background-color: #377dff !important; 263 background-color: #377dff !important;
188 border-color: #377dff !important; 264 border-color: #377dff !important;
189 } 265 }
190 -</style> 266 +</style>
@@ -6,57 +6,67 @@ @@ -6,57 +6,67 @@
6 .alarm-detail-column { 6 .alarm-detail-column {
7 border-radius: 10px; 7 border-radius: 10px;
8 width: 688rpx; 8 width: 688rpx;
9 - height: 573rpx; 9 + height: 688rpx;
10 background-color: #ffffff; 10 background-color: #ffffff;
11 .detail-column { 11 .detail-column {
12 - height: 573rpx;  
13 - justify-content: space-between; 12 + width:750rpx;
14 flex-direction: column; 13 flex-direction: column;
15 align-items: center; 14 align-items: center;
16 - .column {  
17 - flex-direction: row; 15 + .column-line{
18 display:flex; 16 display:flex;
19 - // justify-content: space-between;  
20 - margin-top: 10rpx;  
21 - line-height: 68rpx;  
22 - width: 614rpx;  
23 - height: 90rpx;  
24 - text-align: left;  
25 - border-bottom: 0.1rpx solid #f0f0f0;  
26 - .device-name{  
27 - width:222rpx;  
28 - }  
29 - .text {  
30 - color: #333333;  
31 - font-size: 15px;  
32 - }  
33 - .image {  
34 - width: 30rpx;  
35 - height: 30rpx;  
36 - }  
37 - .text-alarm-level {  
38 - color: #333333;  
39 - font-size: 14px;  
40 - }  
41 - .text-alarm-level-lg {  
42 - color: #333333;  
43 - font-size: 15px;  
44 - }  
45 - .text-alarm-lg {  
46 - color: #666666;  
47 - font-size: 14px;  
48 - }  
49 - .text-alarm-status {  
50 - color: #de4437;  
51 - font-size: 14px; 17 + flex-direction: column;
  18 + .column {
  19 + display:flex;
  20 + margin-top: 10rpx;
  21 + line-height: 68rpx;
  22 + width:700rpx;
  23 + height: 74rpx;
  24 + align-items: center;
  25 + .device-name{
  26 + width:222rpx;
  27 + }
  28 + .alarm-text{
  29 + width:460rpx;
  30 + overflow-x: scroll;
  31 + }
  32 +
  33 + .text {
  34 + color: #333333;
  35 + font-size: 15px;
  36 + }
  37 + .image {
  38 + width: 30rpx;
  39 + height: 30rpx;
  40 + }
  41 + .text-alarm-level {
  42 + color: #333333;
  43 + font-size: 14px;
  44 + }
  45 + .text-alarm-level-lg {
  46 + color: #333333;
  47 + font-size: 15px;
  48 + }
  49 + .text-alarm-lg {
  50 + color: #666666;
  51 + font-size: 14px;
  52 + }
  53 + .text-alarm-status {
  54 + color: #de4437;
  55 + font-size: 14px;
  56 + }
52 } 57 }
  58 + .bottom-line{
  59 + border-bottom: 0.1rpx solid #f0f0f0;
  60 + width:650rpx;
  61 + }
53 } 62 }
  63 +
54 } 64 }
55 } 65 }
56 .handle-result { 66 .handle-result {
57 color: #333333; 67 color: #333333;
58 font-size: 15px; 68 font-size: 15px;
59 - margin-top: 20rpx; 69 + margin-top: 32rpx;
60 } 70 }
61 .hanle-main { 71 .hanle-main {
62 margin-top: 30rpx; 72 margin-top: 30rpx;
@@ -65,3 +75,13 @@ @@ -65,3 +75,13 @@
65 height: 273rpx; 75 height: 273rpx;
66 background-color: #ffffff; 76 background-color: #ffffff;
67 } 77 }
  78 +.bottom-button{
  79 + margin-top: 44rpx;
  80 + display: flex;
  81 + align-items: center;
  82 + gap:40rpx;
  83 + justify-content: center;
  84 + .button-item{
  85 + width: 260rpx;
  86 + }
  87 +}
@@ -11,6 +11,19 @@ const getDeviceApi = (urlParams, data) => { @@ -11,6 +11,19 @@ const getDeviceApi = (urlParams, data) => {
11 return uni.$u.http.post(`/yt/device?page=${page}&pageSize=${pageSize}`, data); 11 return uni.$u.http.post(`/yt/device?page=${page}&pageSize=${pageSize}`, data);
12 }; 12 };
13 13
  14 +// 设备详情
  15 +const getDeviceDetail = (id) => {
  16 + return uni.$u.http.get(`/yt/device/${id}`);
  17 +};
  18 +
  19 +//设备属性
  20 + const getAttribute = (deviceProfileId) => {
  21 + return uni.$u.http.get(`/yt/device/attributes/${deviceProfileId}`);
  22 +};
  23 +
  24 +
14 export default { 25 export default {
15 - getDeviceApi 26 + getDeviceApi,
  27 + getDeviceDetail,
  28 + getAttribute
16 } 29 }
  1 +<template>
  2 + <view class="header-org">
  3 + <view @click="$emit('openOrg')" class="org-item">
  4 + <view class="u-flex org-contact"><text class="text">组织关系</text></view>
  5 + <view class="u-flex org-device">
  6 + <image class="device-image" :src="imageSrc"></image>
  7 + <text class="device-text">摄像头数:{{ total }}</text>
  8 + </view>
  9 + </view>
  10 + <view class="org-item">
  11 + <image class="image" src="/static/arrow-right.png"></image>
  12 + </view>
  13 + </view>
  14 +</template>
  15 +
  16 +<script>
  17 + export default {
  18 + props: {
  19 + total: Number,
  20 + imageSrc: String
  21 + }
  22 + }
  23 +</script>
  24 +
  25 +<style lang="scss" scoped>
  26 + .header-org {
  27 + width: 750rpx;
  28 + height: 150rpx;
  29 + margin-top: 1rpx;
  30 + background-color: #fff;
  31 + display: flex;
  32 + flex-direction: row;
  33 + justify-content: space-between;
  34 + position: fixed;
  35 + z-index: 999999;
  36 + top: -1rpx;
  37 +
  38 + .org-item {
  39 + width: 350rpx;
  40 + height: 200rpx;
  41 +
  42 + .org-contact {
  43 + flex-direction: row;
  44 + margin-top: 26rpx;
  45 + margin-left: 15rpx;
  46 +
  47 + .text {
  48 + color: #333333;
  49 + font-size: 15px;
  50 + margin-left: 14rpx;
  51 + }
  52 + }
  53 +
  54 + .org-device {
  55 + margin-top: 23rpx;
  56 + margin-left: 15rpx;
  57 + flex-direction: row;
  58 +
  59 + .device-image {
  60 + margin-left: 14rpx;
  61 + width: 30rpx;
  62 + height: 30rpx;
  63 + }
  64 +
  65 + .device-text {
  66 + margin-left: 10rpx;
  67 + color: #666666;
  68 + font-size: 12px;
  69 + }
  70 + }
  71 +
  72 + .image {
  73 + width: 6px;
  74 + height: 10px;
  75 + float: right;
  76 + margin-right: 34rpx;
  77 + margin-top: 37rpx;
  78 + }
  79 + }
  80 + }
  81 +</style>
  1 +<template>
  2 + <u-sticky>
  3 + <view class="device-top">
  4 + <view class="search">
  5 + <view>
  6 + <view class="search-left">
  7 + <slot></slot>
  8 + </view>
  9 + </view>
  10 + <view @click="$emit('openSearchDialog')" class="search-right">
  11 + <text>筛选</text>
  12 + <image src="../../static/shaixuan.png" />
  13 + </view>
  14 + </view>
  15 + <u-line />
  16 + <view class="org">
  17 + <u-cell @click="$emit('openOrg')" isLink title="组织关系" :border="false">
  18 + <view slot="label" class="label" style="display: flex; align-items: center;margin-top: 20rpx;">
  19 + <image src="../../static/org.png" style="width: 24rpx;height: 28rpx;"></image>
  20 + <view style="margin-left: 10rpx; color: #666;">
  21 + {{totalText}}
  22 + <text style="margin-left: 20rpx;">{{ total }}</text>
  23 + </view>
  24 + </view>
  25 + </u-cell>
  26 + </view>
  27 + </view>
  28 + </u-sticky>
  29 +</template>
  30 +
  31 +<script>
  32 + export default {
  33 + props: {
  34 + total: Number,
  35 + totalText:[Number,String]
  36 + }
  37 + }
  38 +</script>
  39 +
  40 +<style lang="scss" scoped>
  41 +
  42 + /deep/ .u-button--primary {
  43 + background-color: #377dff !important;
  44 + border-color: #377dff !important;
  45 + }
  46 +
  47 + /deep/ .u-button--info {
  48 + background-color: #e3e3e5 !important;
  49 + border-color: #e3e3e5 !important;
  50 + }
  51 +
  52 + /deep/ .u-cell__right-icon-wrap {
  53 + margin-top: -55rpx !important;
  54 + }
  55 +
  56 + /deep/ .uni-calendar--fixed {
  57 + bottom: 172rpx !important;
  58 + }
  59 +
  60 + .pop-no-scroll {
  61 + overflow: hidden;
  62 + position: fixed;
  63 + height: 100%;
  64 + width: 100%;
  65 + }
  66 +
  67 + .device-top {
  68 + padding: 10rpx 30rpx;
  69 + background-color: #fff;
  70 +
  71 + .search {
  72 + display: flex;
  73 + justify-content: space-between;
  74 + padding-bottom: 10rpx;
  75 +
  76 + .search-left {
  77 + width: 580rpx;
  78 + background-color: #f8f9fa;
  79 + border-radius: 200rpx;
  80 + }
  81 +
  82 + .search-right {
  83 + display: flex;
  84 + align-items: center;
  85 +
  86 + text {
  87 + color: #333;
  88 + font-size: 14px;
  89 + }
  90 +
  91 + image {
  92 + width: 40rpx;
  93 + height: 40rpx;
  94 + }
  95 + }
  96 + }
  97 + }
  98 +</style>
@@ -228,7 +228,6 @@ export default { @@ -228,7 +228,6 @@ export default {
228 if (pageLen == 1 && !mainPagePath.includes(currentPages[0].route)) { 228 if (pageLen == 1 && !mainPagePath.includes(currentPages[0].route)) {
229 this.firstPage = true; 229 this.firstPage = true;
230 this.iconLeft = 'home'; 230 this.iconLeft = 'home';
231 - console.log(this.firstPage, 'this.firstPage');  
232 } 231 }
233 }, 232 },
234 methods: { 233 methods: {
@@ -273,7 +272,6 @@ export default { @@ -273,7 +272,6 @@ export default {
273 //设置手机状态栏颜色 272 //设置手机状态栏颜色
274 settingColor() { 273 settingColor() {
275 let navColor = this.navFontColor; 274 let navColor = this.navFontColor;
276 - console.log(navColor, 'settingColor');  
277 let frontColor = '#000000'; 275 let frontColor = '#000000';
278 if (whiteList.includes(navColor)) { 276 if (whiteList.includes(navColor)) {
279 frontColor = '#ffffff'; 277 frontColor = '#ffffff';
@@ -9,10 +9,10 @@ import { @@ -9,10 +9,10 @@ import {
9 * socketPrefix websocket前缀 ((https, wss),( http, ws)) 9 * socketPrefix websocket前缀 ((https, wss),( http, ws))
10 */ 10 */
11 11
12 -const baseUrl = "https://demo.thingskit.com/api";  
13 -const baseDrawioUrl = "https://demo.thingskit.com/thingskit-scada";  
14 -const baseWebSocketUrl = "demo.thingskit.com";  
15 -const socketPrefix = "wss"; 12 +const baseUrl = "http://222.180.200.114:48080/api";
  13 +const baseDrawioUrl = "http://222.180.200.114:9527/thingskit-scada";
  14 +const baseWebSocketUrl = "222.180.200.114:48080";
  15 +const socketPrefix = "ws";
16 16
17 let systemInfo = { 17 let systemInfo = {
18 ...getTabbarHeight(), 18 ...getTabbarHeight(),
@@ -51,4 +51,4 @@ const courtConfig = { @@ -51,4 +51,4 @@ const courtConfig = {
51 sk: "", 51 sk: "",
52 }, 52 },
53 }; 53 };
54 -export default Object.assign({}, courtConfig); 54 +export default Object.assign({}, courtConfig);
@@ -74,7 +74,7 @@ @@ -74,7 +74,7 @@
74 </view> 74 </view>
75 </template> 75 </template>
76 <script> 76 <script>
77 - import FilterItem from '@/pages/device/FilterItem.vue'; 77 + import FilterItem from '@/pages/device/components/query-item.vue';
78 import MescrollMixin from '@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js'; 78 import MescrollMixin from '@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js';
79 import { 79 import {
80 formatToDate 80 formatToDate
@@ -97,7 +97,7 @@ @@ -97,7 +97,7 @@
97 </view> 97 </view>
98 </template> 98 </template>
99 <script> 99 <script>
100 -import FilterItem from '@/pages/device/FilterItem.vue'; 100 +import FilterItem from '@/pages/device/components/query-item.vue';
101 import MescrollMixin from '@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js'; 101 import MescrollMixin from '@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js';
102 export default { 102 export default {
103 mixins: [MescrollMixin], 103 mixins: [MescrollMixin],
@@ -4,7 +4,7 @@ import App from './App' @@ -4,7 +4,7 @@ import App from './App'
4 // 工具 4 // 工具
5 import '@/plugins/utils.js'; 5 import '@/plugins/utils.js';
6 6
7 -//权限配置中心 7 +//服务端路径配置中心
8 import base from '@/config/baseUrl' 8 import base from '@/config/baseUrl'
9 Vue.prototype.$base = base; 9 Vue.prototype.$base = base;
10 10
@@ -22,13 +22,15 @@ import f_show_modal from '@/components/module/show_modal/f_show_modal.js' @@ -22,13 +22,15 @@ import f_show_modal from '@/components/module/show_modal/f_show_modal.js'
22 Vue.use(f_show_modal) 22 Vue.use(f_show_modal)
23 // #endif 23 // #endif
24 24
25 -// uview 25 +// uview
26 import uView from '@/uni_modules/uview-ui' 26 import uView from '@/uni_modules/uview-ui'
27 Vue.use(uView) 27 Vue.use(uView)
28 28
29 -// 公共组件 29 +// 公共组件注册
30 import publicModule from "@/components/common/public-module.vue"; 30 import publicModule from "@/components/common/public-module.vue";
31 Vue.component("public-module", publicModule); 31 Vue.component("public-module", publicModule);
  32 +import headerSearch from "@/components/common/header-search.vue";
  33 +Vue.component("header-search", headerSearch);
32 34
33 Vue.config.productionTip = false 35 Vue.config.productionTip = false
34 App.mpType = 'app' 36 App.mpType = 'app'
@@ -26,24 +26,12 @@ @@ -26,24 +26,12 @@
26 } 26 }
27 }, 27 },
28 { 28 {
29 - "path": "pages/device/org/org",  
30 - "style": {  
31 - "navigationBarTitleText": "组织筛选"  
32 - }  
33 - },  
34 - {  
35 "path": "pages/alarm/alarm", 29 "path": "pages/alarm/alarm",
36 "style": { 30 "style": {
37 "navigationBarTitleText": "告警" 31 "navigationBarTitleText": "告警"
38 } 32 }
39 }, 33 },
40 { 34 {
41 - "path": "pages/alarm/org/org",  
42 - "style": {  
43 - "navigationBarTitleText": "组织筛选"  
44 - }  
45 - },  
46 - {  
47 "path": "pages/personal/personal", 35 "path": "pages/personal/personal",
48 "style": { 36 "style": {
49 "navigationBarTitleText": "个人中心", 37 "navigationBarTitleText": "个人中心",
@@ -57,11 +45,6 @@ @@ -57,11 +45,6 @@
57 } 45 }
58 }, 46 },
59 { 47 {
60 - "path": "pages/index/camera/org/org",  
61 - "style": {  
62 - "navigationBarTitleText": "组织筛选"  
63 - }  
64 - }, {  
65 "path": "pages/index/configuration/configuration", 48 "path": "pages/index/configuration/configuration",
66 "style": { 49 "style": {
67 "navigationBarTitleText": "查看组态" 50 "navigationBarTitleText": "查看组态"
@@ -73,6 +56,12 @@ @@ -73,6 +56,12 @@
73 "style": { 56 "style": {
74 "navigationBarTitleText": "组态详情" 57 "navigationBarTitleText": "组态详情"
75 } 58 }
  59 + },
  60 + {
  61 + "path": "pages/organization/organization",
  62 + "style": {
  63 + "navigationBarTitleText": "组织筛选"
  64 + }
76 } 65 }
77 ], 66 ],
78 "subPackages": [{ 67 "subPackages": [{
@@ -206,4 +195,4 @@ @@ -206,4 +195,4 @@
206 } 195 }
207 ] 196 ]
208 } 197 }
209 -} 198 +}
1 -<template>  
2 - <view class="alert-page" :class="show ? 'pop-no-scroll' : ''">  
3 - <!-- 公共组件-每个页面必须引入 -->  
4 - <public-module></public-module>  
5 - <!-- 吸顶组件 -->  
6 - <u-sticky>  
7 - <view class="device-top">  
8 - <view class="search">  
9 - <view>  
10 - <view class="search-left">  
11 - <u--input prefixIcon="search" placeholder="请输入告警设备" shape="circle" @change="inputChanged">  
12 - </u--input>  
13 - </view>  
14 - </view>  
15 - <view @click="openSearchDialog" class="search-right">  
16 - <text>筛选</text>  
17 - <image src="../../static/shaixuan.png" />  
18 - </view>  
19 - </view>  
20 - <u-line />  
21 - <view class="org">  
22 - <u-cell @click="openOrg" isLink title="组织关系" :border="false">  
23 - <view slot="label" class="label" style="display: flex; align-items: center;margin-top: 20rpx;">  
24 - <image src="../../static/org.png" style="width: 24rpx;height: 28rpx;"></image>  
25 - <view style="margin-left: 10rpx; color: #666;">  
26 - 告警数:  
27 - <text style="margin-left: 20rpx;">{{ alertTotal }}</text>  
28 - </view>  
29 - </view>  
30 - </u-cell>  
31 - </view>  
32 - </view>  
33 - </u-sticky>  
34 - <!-- 吸顶组件 -->  
35 - <!-- 自带分页组件 -->  
36 - <mescroll-body ref="mescrollRef" :up="upOption" @init="mescrollInit" :down="downOption" @down="downCallback"  
37 - @up="upCallback">  
38 - <view class="device-list">  
39 - <view @click="openAlertDetail(item)" class="list-item" v-for="(item, index) in list" :key="index">  
40 - <view class="u-flex item">  
41 - <view class="item-text text-clip">  
42 - <text class="text-bold">{{ item.deviceName == null ? '暂无数据' : item.deviceName }}</text>  
43 - </view>  
44 - <view class="item-text text-clip">  
45 - <text  
46 - class="text-muted">{{ item.details == null ? '暂无数据' : formatDetailText(item.details.data) }}</text>  
47 - </view>  
48 - <view class="item-text">  
49 - <text class="text-muted">  
50 - 告警状态:{{  
51 - item.status == 'CLEARED_UNACK'  
52 - ? '清除未确认'  
53 - : item.status == 'ACTIVE_UNACK'  
54 - ? '激活未确认'  
55 - : item.status == 'CLEARED_ACK'  
56 - ? '清除已确认'  
57 - : '激活已确认'  
58 - }}  
59 - </text>  
60 - </view>  
61 - <view class="item-text">  
62 - <text class="text-secondary">{{ item.createdTime }}</text>  
63 - </view>  
64 - </view>  
65 - <view class="item">  
66 - <view class="u-flex item-right">  
67 - <image class="right-image" :src="bindImageUrl(item.severity)"></image>  
68 - <view class="right-text">  
69 - <text class="text-no-color" :style="[  
70 - item.severity == 'CRITICAL'  
71 - ? { color: '#DE4437' }  
72 - : item.severity == 'MAJOR'  
73 - ? { color: '#DE7337' }  
74 - : item.severity == 'MINOR'  
75 - ? { color: '#FFC107' }  
76 - : item.severity == 'WARNING'  
77 - ? { color: '#DE4437' }  
78 - : { color: '#00C9A7' }  
79 - ]">  
80 - {{  
81 - item.severity == 'CRITICAL'  
82 - ? '危险'  
83 - : item.severity == 'MAJOR'  
84 - ? '重要'  
85 - : item.severity == 'MINOR'  
86 - ? '次要'  
87 - : item.severity == 'WARNING'  
88 - ? '警告'  
89 - : '不确定'  
90 - }}  
91 - </text>  
92 - </view>  
93 - </view>  
94 - </view>  
95 - </view>  
96 - </view>  
97 - <mescroll-empty v-if="!list.length" />  
98 - </mescroll-body>  
99 - <!-- 自带分页组件 -->  
100 - <view style="height: 20rpx"></view>  
101 - <!-- 告警筛选-->  
102 - <u-popup @close="close" closeable bgColor="transparent" :overlay="true" :show="show" mode="bottom">  
103 - <view class="popup-page">  
104 - <view class="popup-text"><text class="text">告警筛选</text></view>  
105 - <view class="popup-alarm-page u-flex">  
106 - <view>  
107 - <view class="popup-alarm-text"><text class="text">告警状态</text></view>  
108 - <view class="u-flex popup-alarm-child">  
109 - <view class="alarm-text" @click="getAlertStatus(item, index)"  
110 - :style="[index == current1 ? { background: 'rgba(55, 125, 255, 0.05)', border: '1rpx solid rgba(55, 125, 255, 0.3)' } : { background: '#F6F6F6' }]"  
111 - v-for="(item, index) in alertStatus" :key="index">  
112 - <text :class="[index == current1 ? 'select-text' : 'un-select-text']"  
113 - class="text">{{ item.name }}</text>  
114 - </view>  
115 - </view>  
116 - <view style="margin-top: 169rpx;">  
117 - <view class="popup-alarm-text"><text class="text">设备类型</text></view>  
118 - <view class="u-flex popup-alarm-child">  
119 - <view class="alarm-text" @click="getTypeStatus(item, index)" :style="[  
120 - index == current2 ? { background: 'rgba(55, 125, 255, 0.05)', border: '1rpx solid rgba(55, 125, 255, 0.3)' } : { background: '#F6F6F6' }  
121 - ]" v-for="(item, index) in deviceType" :key="index">  
122 - <text :class="[index == current2 ? 'select-text' : 'un-select-text']"  
123 - class="text">{{ item.name }}</text>  
124 - </view>  
125 - </view>  
126 -  
127 - <view style="margin-top: 169rpx;">  
128 - <view class="popup-alarm-text"><text class="text">告警等级</text></view>  
129 - <view class="u-flex popup-alarm-child">  
130 - <view class="alarm-text" @click="getLevelStatus(item, index)" :style="[  
131 - index == current3 ? { background: 'rgba(55, 125, 255, 0.05)', border: '1rpx solid rgba(55, 125, 255, 0.3)' } : { background: '#F6F6F6' }  
132 - ]" v-for="(item, index) in alertLevel" :key="index">  
133 - <text :class="[index == current3 ? 'select-text' : 'un-select-text']"  
134 - class="text">{{ item.name }}</text>  
135 - </view>  
136 - </view>  
137 - <view style="margin-top: 169rpx;">  
138 - <view class="popup-alarm-text"><text class="text">选择时间</text></view>  
139 - <view class="u-flex popup-alarm-child">  
140 - <view class="alarm-text" @click="getTimeStatus(item, index)" :style="[  
141 - index == current4  
142 - ? { background: 'rgba(55, 125, 255, 0.05)', border: '1rpx solid rgba(55, 125, 255, 0.3)' }  
143 - : { background: '#F6F6F6' }  
144 - ]" v-for="(item, index) in timeArea" :key="index">  
145 - <text :class="[index == current4 ? 'select-text' : 'un-select-text']"  
146 - class="text">{{ item.name }}</text>  
147 - </view>  
148 - </view>  
149 - <view style="margin-top: 169rpx;margin-left: 22rpx;">  
150 - <view class="u-flex popup-alarm-child">  
151 - <view class="home-text-muted">选择日期</view>  
152 - <view  
153 - style="width: 623rpx;margin-left: 5rpx;margin-right: 70rpx;margin-top: 35rpx;">  
154 - <uni-datetime-picker v-model="range" type="datetimerange"  
155 - rangeSeparator="至" />  
156 - </view>  
157 - </view>  
158 - </view>  
159 - <view style="height: 130rpx;"></view>  
160 - <view class="u-flex"  
161 - style="position: fixed;bottom: 10rpx;z-index: 9999;flex-direction: row; margin-top: 128rpx; margin-left: 10rpx">  
162 - <view style="width: 300rpx">  
163 - <u-button @click="resetData" type="info" shape="circle" text="重置">  
164 - </u-button>  
165 - </view>  
166 - <view style="width: 300rpx; margin-left: 46rpx">  
167 - <u-button @click="queryData" type="primary" shape="circle" text="确认">  
168 - </u-button>  
169 - </view>  
170 - </view>  
171 - <view style="height: 90rpx;"></view>  
172 - </view>  
173 - </view>  
174 - </view>  
175 - </view>  
176 - </view>  
177 - </view>  
178 - </u-popup>  
179 - <f-tabbar></f-tabbar>  
180 - </view>  
181 -</template>  
182 -  
183 -<script>  
184 - import fTabbar from '@/components/module/f-tabbar/f-tabbar';  
185 - import MescrollMixin from '@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js';  
186 - import {  
187 - alertStatus,  
188 - deviceType,  
189 - alertLevel,  
190 - timeArea  
191 - } from './static/data.js';  
192 - import api from '@/api/index.js'  
193 -  
194 - export default {  
195 - mixins: [MescrollMixin], // 使用mixin (在main.js注册全局组件)  
196 - components: {  
197 - fTabbar  
198 - },  
199 - data() {  
200 - return {  
201 - range: [],  
202 - alertStatusVal: '',  
203 - deviceTypeVal: '',  
204 - alertLevelVal: '',  
205 - selectTimeVal: '',  
206 - current1: 0,  
207 - current2: 0,  
208 - current3: 0,  
209 - current4: 0,  
210 - page: {  
211 - num: 0,  
212 - size: 10  
213 - },  
214 - downOption: {  
215 - auto: false //是否在初始化后,自动执行downCallback; 默认true  
216 - },  
217 - upOption: {  
218 - auto: false // 不自动加载  
219 - },  
220 - timeData: {  
221 - selectTime: [],  
222 - getTimeGapS: '',  
223 - getTimeGapE: ''  
224 - },  
225 - show: false,  
226 - list: [],  
227 - alertStatus,  
228 - deviceType,  
229 - alertLevel,  
230 - timeArea,  
231 - ordId: '',  
232 - detailStatus: false,  
233 - alertTotal: 0,  
234 - searchAlarmText: '',  
235 - startTimeVa: '',  
236 - endTimeVa: '',  
237 - startTimeArea: '',  
238 - endTimeArea: '',  
239 - type: null  
240 - };  
241 - },  
242 - onShow() {  
243 - this.page.num = 1;  
244 - if(getApp().getBindNot()){  
245 - return  
246 - }  
247 - if (this.detailStatus) {  
248 - this.loadData(1, null, null, null, null, null, null);  
249 - }  
250 - if (this.ordId) {  
251 - this.loadData(1, null, null, null, null, null, this.ordId);  
252 - }  
253 - },  
254 - onHide() {  
255 - this.ordId = '';  
256 - this.detailStatus = false;  
257 - this.type = null;  
258 - },  
259 - onLoad(e) {  
260 - // 隐藏原生的tabbar  
261 - uni.hideTabBar();  
262 - if(getApp().getBindNot()){  
263 - return  
264 - }  
265 - if (e.type == undefined) {  
266 - this.loadData(1, null, null, null, null, null, null);  
267 - } else {  
268 - let params = JSON.parse(e.type);  
269 - if (Array.isArray(params)) {  
270 - this.type = params.join(',');  
271 - } else {  
272 - this.type = params;  
273 - }  
274 - this.loadData(1, this.type, null, null, null, null, null);  
275 - }  
276 - },  
277 - watch: {  
278 - range(newval) {  
279 - this.timeData.selectTime = this.range;  
280 - }  
281 - },  
282 - methods: {  
283 - moveHandle() {  
284 - return false;  
285 - },  
286 - inputChanged(e) {  
287 - this.resetData();  
288 - this.topBack();  
289 - this.searchAlarmText = e;  
290 - this.page.num = 1;  
291 - this.loadData(1, null, null, null, null, null, null, e);  
292 - },  
293 - getAlertStatus(e, i) {  
294 - this.current1 = i;  
295 - this.alertStatusVal = e.value;  
296 - },  
297 - getTypeStatus(e, i) {  
298 - this.current2 = i;  
299 - this.deviceTypeVal = e.value;  
300 - },  
301 - getLevelStatus(e, i) {  
302 - this.current3 = i;  
303 - this.alertLevelVal = e.value;  
304 - },  
305 - getTimeStatus(e, i) {  
306 - this.current4 = i;  
307 - this.selectTimeVal = e.value;  
308 - let curTime = new Date();  
309 - const formatS = curTime.getTime();  
310 - let addMinute = new Date(curTime.setMinutes(curTime.getMinutes() - this.selectTimeVal));  
311 - const formatE = addMinute.getTime();  
312 - this.timeData.getTimeGapS = i>0?formatS:'';  
313 - this.timeData.getTimeGapE = i>0?formatE:'';  
314 - console.log(this.timeData.getTimeGapS,'this.timeData.getTimeGapS',this.timeData.getTimeGapE)  
315 - },  
316 - queryData() {  
317 - this.topBack();  
318 - this.page.num = 1;  
319 - let date1 = new Date(this.timeData.selectTime[0]);  
320 - let date2 = new Date(this.timeData.selectTime[1]);  
321 - if (this.timeData.selectTime.length == 0) {  
322 - this.startTimeVa = '';  
323 - this.endTimeVa = '';  
324 - } else {  
325 - this.startTimeVa = date1.getTime();  
326 - this.endTimeVa = date2.getTime();  
327 - }  
328 - if (this.timeData.getTimeGapS == '') {  
329 - this.startTimeArea = '';  
330 - this.endTimeArea = '';  
331 - } else {  
332 - this.startTimeArea = this.timeData.getTimeGapE;  
333 - this.endTimeArea = this.timeData.getTimeGapS;  
334 - }  
335 - this.loadData(  
336 - 1,  
337 - this.alertStatusVal,  
338 - this.startTimeVa ? this.startTimeVa : this.startTimeArea,  
339 - this.endTimeVa ? this.endTimeVa : this.endTimeArea,  
340 - this.alertLevelVal,  
341 - this.deviceTypeVal  
342 - );  
343 - this.show = false;  
344 - },  
345 - resetData() {  
346 - this.current1 = 0;  
347 - this.alertStatusVal = '';  
348 - this.current2 = 0;  
349 - this.deviceTypeVal = '';  
350 - this.current3 = 0;  
351 - this.alertLevelVal = '';  
352 - this.current4 = 0;  
353 - this.selectTimeVal = '';  
354 - this.timeData.selectTime = [];  
355 - this.timeData.getTimeGapS = '';  
356 - this.timeData.getTimeGapE = '';  
357 - this.range = [];  
358 - this.searchAlarmText = '';  
359 - this.startTimeVa = '';  
360 - this.endTimeVa = '';  
361 - this.startTimeArea = '';  
362 - this.endTimeArea = '';  
363 - this.ordId = '';  
364 - this.type = null;  
365 - },  
366 - bindImageUrl(e) {  
367 - switch (e) {  
368 - case 'CRITICAL':  
369 - return '../../static/danger.png';  
370 - break;  
371 - case 'MAJOR':  
372 - return '../../static/major.png';  
373 - break;  
374 - case 'MINOR':  
375 - return '../../static/secondary.png';  
376 - break;  
377 - case 'WARNING':  
378 - return '../../static/danger.png';  
379 - break;  
380 - case 'INDETERMINATE':  
381 - return '../../static/noshue.png';  
382 - break;  
383 - default:  
384 - return '';  
385 - break;  
386 - }  
387 - },  
388 - //筛选数据让它回到顶部  
389 - topBack() {  
390 - uni.pageScrollTo({  
391 - scrollTop: 0, // 滚动到页面的目标位置 这个是滚动到顶部, 0  
392 - duration: 10 // 滚动动画的时长  
393 - });  
394 - },  
395 - /*下拉刷新的回调 */  
396 - downCallback() {  
397 - //联网加载数据  
398 - this.list.length = 0;  
399 - this.page.num = 1;  
400 - this.loadData(this.page.num, null, null, null, null, null, null, null);  
401 - this.resetData();  
402 - },  
403 - /*上拉加载的回调: 其中page.num:当前页 从1开始, page.size:每页数据条数,默认10 */  
404 - upCallback() {  
405 - if (  
406 - this.type != null ||  
407 - this.alertStatusVal != '' ||  
408 - this.searchAlarmText != '' ||  
409 - this.deviceTypeVal != '' ||  
410 - this.alertLevelVal != '' ||  
411 - this.startTimeVa != '' ||  
412 - this.startTimeArea != '' ||  
413 - this.ordId != ''  
414 - ) {  
415 - //联网加载数据  
416 - this.page.num += 1;  
417 - this.loadData(  
418 - this.page.num,  
419 - this.alertStatusVal ? this.alertStatusVal : this.type,  
420 - this.startTimeVa,  
421 - this.endTimeVa,  
422 - this.alertLevelVal,  
423 - this.deviceTypeVal,  
424 - this.ordId,  
425 - this.searchAlarmText  
426 - );  
427 - } else {  
428 - //联网加载数据  
429 - this.page.num += 1;  
430 - this.loadData(this.page.num);  
431 - }  
432 - },  
433 - async loadData(pageNo, statusV, startTimeV, endTimeV, severityV, deviceTypeV, organizationV, alarmName) {  
434 - let that = this;  
435 - let httpData = {  
436 - page: pageNo,  
437 - pageSize: 10,  
438 - status: statusV,  
439 - startTime: startTimeV,  
440 - endTime: endTimeV,  
441 - severity: severityV,  
442 - deviceType: deviceTypeV,  
443 - organizationId: organizationV,  
444 - deviceName: alarmName  
445 - };  
446 - if (statusV == '') {  
447 - delete httpData.status;  
448 - }  
449 - if (severityV == '') {  
450 - delete httpData.severity;  
451 - }  
452 - const res = await api.alarmApi.getAlarmApi({  
453 - params: httpData,  
454 - custom: {  
455 - load: false  
456 - }  
457 - })  
458 - if (res) {  
459 - uni.stopPullDownRefresh();  
460 - that.mescroll.endByPage(res.items.length, res.total); //必传参数(当前页的数据个数, 总页数)  
461 - that.alertTotal = res.total;  
462 - if (pageNo == 1) {  
463 - that.list = res.items;  
464 - } else {  
465 - that.list = that.list.concat(res.items);  
466 - }  
467 - }  
468 - },  
469 - openOrg() {  
470 - uni.navigateTo({  
471 - url: './org/org'  
472 - });  
473 - },  
474 - close() {  
475 - this.show = false;  
476 - },  
477 - openSearchDialog() {  
478 - this.show = true;  
479 - this.resetData();  
480 - },  
481 - //跳转告警详情  
482 - openAlertDetail(e) {  
483 - let obj = {  
484 - id: e.id,  
485 - deviceName: e.deviceName,  
486 - severity: e.severity,  
487 - organizationName: e.organizationName,  
488 - details: e.details,  
489 - createdTime: e.createdTime,  
490 - status: e.status,  
491 - type: e.type  
492 - };  
493 - uni.navigateTo({  
494 - url: '/alarmSubPage/alarmDetailPage/alarmDetail?data=' + JSON.stringify(obj)  
495 - });  
496 - },  
497 - formatDetailText(e) {  
498 - //去除字符串双引号  
499 - const jsonStr = JSON.stringify(e);  
500 - const str = jsonStr.substring(1, jsonStr.length - 1);  
501 - const newStr = str.replace(/\"/g, '');  
502 - return newStr;  
503 - }  
504 - }  
505 - };  
506 -</script>  
507 -  
508 -<style lang="scss" scoped>  
509 - @import './static/alarm.scss';  
510 -  
511 - /deep/ .u-button--primary {  
512 - background-color: #377dff !important;  
513 - border-color: #377dff !important;  
514 - }  
515 -  
516 - /deep/ .u-button--info {  
517 - background-color: #e3e3e5 !important;  
518 - border-color: #e3e3e5 !important;  
519 - }  
520 -  
521 - /deep/ .u-cell__right-icon-wrap {  
522 - margin-top: -55rpx !important;  
523 - }  
524 -  
525 - /deep/ .uni-calendar--fixed {  
526 - bottom: 172rpx !important;  
527 - }  
528 -  
529 - .pop-no-scroll {  
530 - overflow: hidden;  
531 - position: fixed;  
532 - height: 100%;  
533 - width: 100%;  
534 - }  
535 -  
536 - .device-top {  
537 - padding: 10rpx 30rpx;  
538 - background-color: #fff;  
539 -  
540 - .search {  
541 - display: flex;  
542 - justify-content: space-between;  
543 - padding-bottom: 10rpx;  
544 -  
545 - .search-left {  
546 - width: 580rpx;  
547 - background-color: #f8f9fa;  
548 - border-radius: 200rpx;  
549 - }  
550 -  
551 - .search-right {  
552 - display: flex;  
553 - align-items: center;  
554 -  
555 - text {  
556 - color: #333;  
557 - font-size: 14px;  
558 - }  
559 -  
560 - image {  
561 - width: 40rpx;  
562 - height: 40rpx;  
563 - }  
564 - }  
565 - }  
566 - }  
567 -</style> 1 +<template>
  2 + <view class="alert-page" :class="pageDisableScroll">
  3 + <!-- 公共组件-每个页面必须引入 -->
  4 + <public-module></public-module>
  5 + <!-- 告警头部 -->
  6 + <header-search @openOrg="openOrg" @openSearchDialog="openSearchDialog" :total="alarmTotal"
  7 + :totalText="totalText">
  8 + <!-- 不能写在封装组件里传placeholder,mp-wenxin端编译要报错 -->
  9 + <u--input prefixIcon="search" placeholder="请输入告警设备" shape="circle" @change="inputChanged">
  10 + </u--input>
  11 + </header-search>
  12 + <!-- 告警分页 -->
  13 + <mescroll-body ref="mescrollRef" :up="upOption" @init="mescrollInit" :down="downOption" @down="downCallback"
  14 + @up="upCallback">
  15 + <alarm-item :list="list" @openAlertDetail="openAlertDetail"></alarm-item>
  16 + <mescroll-empty v-if="!list.length" />
  17 + </mescroll-body>
  18 + <view style="height: 20rpx"></view>
  19 + <!-- 告警筛选-->
  20 + <alarm-popup ref="alarmPopupRef" :show="show" @close="close" @queryCondition="getQueryCondition"></alarm-popup>
  21 + <f-tabbar></f-tabbar>
  22 + </view>
  23 +</template>
  24 +
  25 +<script>
  26 + import fTabbar from '@/components/module/f-tabbar/f-tabbar';
  27 + import MescrollMixin from '@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js';
  28 + import api from '@/api/index.js'
  29 + import alarmItem from './components/alarm-item.vue'
  30 + import alarmPopup from './components/alarm-popup.vue'
  31 + import {
  32 + usePageScrollTo,
  33 + useNavigateTo
  34 + } from '@/plugins/utils.js'
  35 +
  36 +
  37 + export default {
  38 + mixins: [MescrollMixin], // 使用mixin (在main.js注册全局组件)
  39 + components: {
  40 + fTabbar,
  41 + alarmItem,
  42 + alarmPopup
  43 + },
  44 + data() {
  45 + return {
  46 + totalText: '告警数:',
  47 + page: {
  48 + num: 0,
  49 + size: 10
  50 + },
  51 + downOption: {
  52 + auto: false //是否在初始化后,自动执行downCallback; 默认true
  53 + },
  54 + upOption: {
  55 + auto: false // 不自动加载
  56 + },
  57 + show: false,
  58 + list: [],
  59 + alarmTotal: 0,
  60 + queryCondition: {
  61 + searchAlarmText: '',
  62 + },
  63 + conditions: {},
  64 + ordId: '',
  65 + };
  66 + },
  67 + onShow() {
  68 + if (getApp().getBindNot()) {
  69 + return
  70 + }
  71 + if (this.ordId) {
  72 + this.loadData(1, {
  73 + organizationId: this.ordId
  74 + });
  75 + this.conditions = {
  76 + organizationId: this.ordId
  77 + }
  78 + }
  79 + },
  80 + onHide() {
  81 + this.ordId = ''
  82 + },
  83 + onLoad(e) {
  84 + if (!e.type) {
  85 + this.loadData(1);
  86 + } else {
  87 + let params = JSON.parse(e.type);
  88 + let status = null
  89 + if (Array.isArray(params)) {
  90 + status = params.join(',');
  91 + } else {
  92 + status = params;
  93 + }
  94 + this.conditions = {
  95 + status
  96 + }
  97 + this.loadData(1, {
  98 + status
  99 + });
  100 + }
  101 + // 隐藏原生的tabbar
  102 + uni.hideTabBar();
  103 + if (getApp().getBindNot()) {
  104 + return
  105 + }
  106 + },
  107 + computed: {
  108 + pageDisableScroll() {
  109 + return this.show ? 'pop-no-scroll' : ''
  110 + }
  111 + },
  112 + methods: {
  113 + inputChanged(e) {
  114 + this.resetQuery();
  115 + this.topBack();
  116 + this.queryCondition.searchAlarmText = e;
  117 + this.page.num = 1;
  118 + this.conditions = {
  119 + deviceName: e
  120 + }
  121 + this.loadData(1, {
  122 + deviceName: e
  123 + });
  124 + },
  125 + getQueryCondition(value) {
  126 + this.loadData(1, value);
  127 + this.conditions = value
  128 + this.close()
  129 + },
  130 + resetQuery() {
  131 + this.queryCondition.searchAlarmText = '';
  132 + this.page.num = 1;
  133 + this.$refs.alarmPopupRef.resetQuery()
  134 + this.conditions = {}
  135 + },
  136 + topBack() {
  137 + usePageScrollTo(0, 10)
  138 + },
  139 + //下拉刷新
  140 + downCallback() {
  141 + this.list.length = 0;
  142 + this.page.num = 1;
  143 + this.loadData(this.page.num);
  144 + this.resetQuery();
  145 + },
  146 + //上拉加载
  147 + upCallback() {
  148 + const condition = Object.values(this.conditions)
  149 + if (condition.length === 0) {
  150 + this.page.num += 1;
  151 + this.loadData(this.page.num);
  152 + } else if (condition.filter(Boolean).length > 0) {
  153 + this.page.num += 1;
  154 + this.loadData(this.page.num, this.conditions);
  155 + } else {
  156 + this.page.num += 1;
  157 + this.loadData(this.page.num);
  158 + }
  159 + },
  160 + async loadData(page, param) {
  161 + let that = this;
  162 + let params = {
  163 + page,
  164 + pageSize: 10,
  165 + ...param
  166 + };
  167 + const res = await api.alarmApi.getAlarmApi({
  168 + params,
  169 + custom: {
  170 + load: false
  171 + }
  172 + })
  173 + if (!res) return
  174 + uni.stopPullDownRefresh();
  175 + that.mescroll.endByPage(res.items.length, res.total); //必传参数(当前页的数据个数, 总页数)
  176 + that.alarmTotal = res.total;
  177 + if (page == 1) {
  178 + that.list = res.items;
  179 + } else {
  180 + that.list = that.list.concat(res.items);
  181 + }
  182 + },
  183 + close() {
  184 + this.show = false;
  185 + },
  186 + openSearchDialog() {
  187 + this.show = true;
  188 + this.resetQuery();
  189 + },
  190 + openOrg() {
  191 + useNavigateTo('/pages/organization/organization')
  192 + },
  193 + //跳转告警详情
  194 + openAlertDetail(e) {
  195 + useNavigateTo('/alarmSubPage/alarmDetailPage/alarmDetail?data=', e)
  196 + },
  197 + }
  198 + };
  199 +</script>
  200 +
  201 +<style lang="scss" scoped>
  202 + @import './static/alarm.scss';
  203 +
  204 + /deep/ .u-button--primary {
  205 + background-color: #377dff !important;
  206 + border-color: #377dff !important;
  207 + }
  208 +
  209 + /deep/ .u-button--info {
  210 + background-color: #e3e3e5 !important;
  211 + border-color: #e3e3e5 !important;
  212 + }
  213 +
  214 + /deep/ .u-cell__right-icon-wrap {
  215 + margin-top: -55rpx !important;
  216 + }
  217 +
  218 + /deep/ .uni-calendar--fixed {
  219 + bottom: 172rpx !important;
  220 + }
  221 +
  222 + .pop-no-scroll {
  223 + overflow: hidden;
  224 + position: fixed;
  225 + height: 100%;
  226 + width: 100%;
  227 + }
  228 +</style>
  1 +<template>
  2 + <view class="device-list">
  3 + <view @click="$emit('openAlertDetail',item)" class="list-item" v-for="(item, index) in list" :key="index">
  4 + <view class="u-flex item">
  5 + <view class="item-text text-clip">
  6 + <text class="text-bold">{{ item.deviceName == null ? '暂无数据' : item.deviceName }}</text>
  7 + </view>
  8 + <view class="item-text text-clip">
  9 + <text class="text-muted">{{ item.details == null ? '暂无数据' : formatDetailText(item.details) }}</text>
  10 + </view>
  11 + <view class="item-text">
  12 + <text class="text-muted">
  13 + 告警状态:{{item.status | setAlarmStatus(alarmStatus)}}
  14 + </text>
  15 + </view>
  16 + <view class="item-text">
  17 + <text class="text-secondary">{{ item.createdTime }}</text>
  18 + </view>
  19 + </view>
  20 + <view class="item">
  21 + <view class="u-flex item-right">
  22 + <image class="right-image" :src="bindImageUrl(item.severity)"></image>
  23 + <view class="right-text">
  24 + <text class="text-no-color" :style="[setAlarmSeverityColor(item.severity,alarmSeverity)]">
  25 + {{item.severity | setAlarmSeverity(alarmSeverity)}}
  26 + </text>
  27 + </view>
  28 + </view>
  29 + </view>
  30 + </view>
  31 + </view>
  32 +</template>
  33 +
  34 +<script>
  35 + import {
  36 + alarmSeverity,
  37 + alarmStatus
  38 + } from '../config/data.js';
  39 +
  40 + export default {
  41 + props: {
  42 + list: {
  43 + type: Array,
  44 + default: []
  45 + }
  46 + },
  47 + data() {
  48 + return {
  49 + alarmSeverity,
  50 + alarmStatus
  51 + }
  52 + },
  53 + filters: {
  54 + setAlarmStatus(value, list) {
  55 + return list.find(item => item.value === value).label
  56 + },
  57 + setAlarmSeverity(value, list) {
  58 + return list.find(item => item.value === value).label
  59 + }
  60 + },
  61 + methods: {
  62 + setAlarmSeverityColor(value, list) {
  63 + return {
  64 + color: list.find(item => item.value === value).color
  65 + }
  66 + },
  67 + bindImageUrl(e) {
  68 + return this.alarmSeverity.find(item => item.value === e).icon
  69 + },
  70 + formatDetailText(e) {
  71 + const keys = Object.keys(e)
  72 + const values = keys.reduce((acc, curr) => {
  73 + acc.push(`${!e[curr].key?'暂无数据':e[curr].key}:${!e[curr].realValue?'暂无数据':e[curr].realValue}`)
  74 + return acc
  75 + }, [])
  76 + return values.join(',')
  77 + }
  78 + }
  79 + }
  80 +</script>
  81 +
  82 +<style lang="scss" scoped>
  83 + .device-list {
  84 + display: flex;
  85 + flex-direction: column;
  86 + padding-left: 18rpx;
  87 + justify-content: flex-start;
  88 +
  89 + .list-item {
  90 + width: 713rpx;
  91 + height: 233rpx;
  92 + background-color: #fff;
  93 + margin-top: 24rpx;
  94 + display: flex;
  95 + flex-direction: row;
  96 + border-radius: 10px;
  97 + justify-content: space-between;
  98 +
  99 + .item {
  100 + justify-content: flex-start;
  101 + flex-direction: column;
  102 + align-items: center;
  103 + height: 211rpx;
  104 + margin-top: 8rpx;
  105 + margin-left: 37rpx;
  106 +
  107 + .item-text {
  108 + width: 400rpx;
  109 + text-align: left;
  110 + margin-top: 13rpx;
  111 + line-height: 40rpx;
  112 +
  113 + .text {
  114 + color: #666666;
  115 + font-size: 15px;
  116 + }
  117 +
  118 + .text-three {
  119 + color: #333333;
  120 + font-size: 15px;
  121 + }
  122 +
  123 + .text-nine {
  124 + color: #999999;
  125 + font-size: 15px;
  126 + }
  127 + }
  128 +
  129 + .item-right {
  130 + flex-direction: row;
  131 + margin-top: -3rpx;
  132 + margin-right: 25rpx;
  133 +
  134 + .right-image {
  135 + width: 30rpx;
  136 + height: 30rpx;
  137 + margin-top: 20rpx;
  138 + margin-right: 5rpx;
  139 + }
  140 +
  141 + .right-text {
  142 + color: #333333;
  143 + font-size: 13px;
  144 + margin-left: 5rpx;
  145 + margin-top: 20rpx;
  146 + }
  147 + }
  148 + }
  149 + }
  150 + }
  151 +</style>
  1 +<template>
  2 + <u-popup @close="$emit('close')" closeable bgColor="transparent" :overlay="true" :show="show" mode="bottom">
  3 + <view class="popup-page">
  4 + <view class="popup-text"><text class="text">告警筛选</text></view>
  5 + <view class="popup-alarm-page u-flex">
  6 + <view>
  7 + <query-item ref="queryItemAlarmStatusRef" :leftText="leftAlarmStatusText" :queryStatus="alertStatus"
  8 + @currentClick="getAlarmStatus"></query-item>
  9 + <query-item ref="queryDeviceTypeStatusRef" :leftText="leftDeviceTypeText" :queryStatus="deviceType"
  10 + @currentClick="getDeviceType"></query-item>
  11 + <query-item ref="queryItemAlarmLevelRef" :leftText="leftAlarmLevelText" :queryStatus="alertLevel"
  12 + @currentClick="getAlarmLevel"></query-item>
  13 + <query-item ref="queryItemSelectTimeRef" :leftText="leftSelectTimeText" :queryStatus="timeArea"
  14 + @currentClick="getSelectTime"></query-item>
  15 + <view class="select-date">
  16 + <view class="home-text-muted">选择日期</view>
  17 + <view class="datetime-picker">
  18 + <uni-datetime-picker return-type="timestamp" v-model="range" type="datetimerange"
  19 + rangeSeparator="至" />
  20 + </view>
  21 + </view>
  22 + <view class="u-flex bottom-button">
  23 + <view class="button-item">
  24 + <u-button @click="resetQuery" type="info" shape="circle" text="重置">
  25 + </u-button>
  26 + </view>
  27 + <view class="button-item" style="margin-left: 46rpx">
  28 + <u-button @click="confirmQuery" type="primary" shape="circle" text="确认">
  29 + </u-button>
  30 + </view>
  31 + </view>
  32 + <view style="height: 90rpx;"></view>
  33 + </view>
  34 + </view>
  35 + </view>
  36 + </u-popup>
  37 +</template>
  38 +
  39 +<script>
  40 + import {
  41 + alertStatus,
  42 + deviceType,
  43 + alertLevel,
  44 + timeArea
  45 + } from '../config/data.js';
  46 + import queryItem from './query-item.vue'
  47 +
  48 + export default {
  49 + components: {
  50 + queryItem
  51 + },
  52 + props: {
  53 + show: Boolean
  54 + },
  55 + data() {
  56 + return {
  57 + totalText: '告警数:',
  58 + leftAlarmStatusText: '告警状态',
  59 + leftDeviceTypeText: '设备类型',
  60 + leftAlarmLevelText: '告警等级',
  61 + leftSelectTimeText: '选择时间',
  62 + range: [],
  63 + alertStatus,
  64 + deviceType,
  65 + alertLevel,
  66 + timeArea,
  67 + queryCondition: {
  68 + status: '',
  69 + deviceType: '',
  70 + severity: '',
  71 + startTime: 0,
  72 + endTime: 0,
  73 + },
  74 +
  75 + };
  76 + },
  77 + computed: {
  78 + hignLightColor() {
  79 + return `background: 'rgba(55, 125, 255, 0.05)', border: '1rpx solid rgba(55, 125, 255, 0.3)'`
  80 + },
  81 + unHighlightColor() {
  82 + return `background: '#F6F6F6'`
  83 + }
  84 + },
  85 + methods: {
  86 + getAlarmStatus(e) {
  87 + this.queryCondition.status = e.value;
  88 + },
  89 + getDeviceType(e) {
  90 + this.queryCondition.deviceType = e.value;
  91 + },
  92 + getAlarmLevel(e) {
  93 + this.queryCondition.severity = e.value;
  94 + },
  95 + getSelectTime(e, i) {
  96 + const curTime = new Date();
  97 + const getStartTs = curTime.getTime();
  98 + const calcDate = new Date(curTime.setMinutes(curTime.getMinutes() - e.value));
  99 + const getEndTs = calcDate.getTime();
  100 + this.queryCondition.startTime = getEndTs
  101 + this.queryCondition.endTime = getStartTs
  102 + },
  103 + confirmQuery() {
  104 + if (Array.isArray(this.range) && this.range.length > 0) {
  105 + this.queryCondition.startTime = this.range[0]
  106 + this.queryCondition.endTime = this.range[1]
  107 + }
  108 + this.$emit('queryCondition', this.queryCondition)
  109 + },
  110 + resetQuery() {
  111 + for (let i in this.queryCondition) Reflect.set(this.queryCondition, i, '')
  112 + this.range = []
  113 + this.$refs.queryItemAlarmStatusRef.reset()
  114 + this.$refs.queryDeviceTypeStatusRef.reset()
  115 + this.$refs.queryItemAlarmLevelRef.reset()
  116 + this.$refs.queryItemSelectTimeRef.reset()
  117 + },
  118 + }
  119 + };
  120 +</script>
  121 +
  122 +
  123 +<style lang="scss" scoped>
  124 + .popup-page {
  125 + height: 1100rpx;
  126 + background: #ffffff;
  127 + border-radius: 20rpx;
  128 + overflow-y: scroll;
  129 + overflow-x: hidden;
  130 +
  131 + .popup-text {
  132 + text-align: center;
  133 + position: relative;
  134 + top: 68rpx;
  135 + margin-top: -40rpx;
  136 +
  137 + .text {
  138 + font-size: 16px;
  139 + color: #333333;
  140 + }
  141 + }
  142 +
  143 + .popup-alarm-page {
  144 + margin-top: 97rpx;
  145 + margin-left: 98rpx;
  146 + flex-direction: column;
  147 + justify-content: space-between;
  148 +
  149 + .select-date {
  150 + display: flex;
  151 + flex-direction: column;
  152 + justify-content: space-between;
  153 + }
  154 +
  155 + .datetime-picker {
  156 + width: 640rpx;
  157 + margin-left: 5rpx;
  158 + margin-right: 70rpx;
  159 + margin-top: 35rpx;
  160 + }
  161 +
  162 + .bottom-button {
  163 + position: fixed;
  164 + bottom: 10rpx;
  165 + z-index: 9999;
  166 + flex-direction: row;
  167 + margin-top: 128rpx;
  168 + margin-left: 10rpx;
  169 +
  170 + .button-item {
  171 + width: 300rpx
  172 + }
  173 + }
  174 + }
  175 + }
  176 +</style>
  1 +<template>
  2 + <view>
  3 + <view class="popup-alarm-text"><text class="text">{{leftText}}</text></view>
  4 + <view class="u-flex popup-alarm-child">
  5 + <view v-for="(item, index) in queryStatus" :key="index" class="alarm-text" @click="currentClick(item,index)"
  6 + :style="[index == currentIndex ? { hignLightColor } : { unHighlightColor }]">
  7 + <text :class="[index == currentIndex ? 'select-text' : 'un-select-text']"
  8 + class="text">{{ item.name }}</text>
  9 + </view>
  10 + </view>
  11 + <view style="height:180rpx"></view>
  12 + </view>
  13 +</template>
  14 +
  15 +<script>
  16 + export default {
  17 + props: {
  18 + leftText: String,
  19 + queryStatus: Array
  20 + },
  21 + data() {
  22 + return {
  23 + currentIndex: 0,
  24 + }
  25 + },
  26 + computed: {
  27 + hignLightColor() {
  28 + return `background: 'rgba(55, 125, 255, 0.05)', border: '1rpx solid rgba(55, 125, 255, 0.3)'`
  29 + },
  30 + unHighlightColor() {
  31 + return `background: '#F6F6F6'`
  32 + }
  33 + },
  34 + methods: {
  35 + currentClick(item, index) {
  36 + this.currentIndex = index
  37 + this.$emit('currentClick', item, index)
  38 + },
  39 + reset() {
  40 + this.currentIndex = 0
  41 + }
  42 + }
  43 + }
  44 +</script>
  45 +
  46 +<style lang="scss" scoped>
  47 + .popup-alarm-text {
  48 + width: 750rpx;
  49 + margin-left: 14rpx;
  50 +
  51 + .text {
  52 + color: #333333;
  53 + font-size: 14px;
  54 + }
  55 + }
  56 +
  57 + .popup-alarm-child {
  58 + margin-top: 15rpx;
  59 + width: 750rpx;
  60 + height: 60rpx;
  61 + flex-wrap: wrap;
  62 + margin-left: -10rpx;
  63 +
  64 + .alarm-text {
  65 + margin: 25rpx;
  66 + line-height: 50rpx;
  67 + text-align: center;
  68 + width: 180rpx;
  69 + height: 60rpx;
  70 + background-color: #f6f6f6;
  71 + border-radius: 32px;
  72 +
  73 + .text {
  74 + color: #333333;
  75 + font-size: 13px;
  76 + }
  77 + }
  78 + }
  79 +</style>
pages/alarm/config/data.js renamed from pages/alarm/static/data.js
@@ -143,9 +143,141 @@ const timeArea = [{ @@ -143,9 +143,141 @@ const timeArea = [{
143 textColor: '#F6F6F6' 143 textColor: '#F6F6F6'
144 } 144 }
145 ] 145 ]
  146 +
  147 +const alarmSeverity = [{
  148 + label: '危险',
  149 + value: 'CRITICAL',
  150 + color: '#DE4437',
  151 + icon: '/static/danger.png',
  152 + },
  153 + {
  154 + label: '重要',
  155 + value: 'MAJOR',
  156 + color: '#DE7337',
  157 + icon: '/static/major.png',
  158 + },
  159 + {
  160 + label: '次要',
  161 + value: 'MINOR',
  162 + color: '#FFC107',
  163 + icon: '/static/secondary.png',
  164 + },
  165 + {
  166 + label: '警告',
  167 + value: 'WARNING',
  168 + color: '#DE4437',
  169 + icon: '/static/danger.png',
  170 + },
  171 + {
  172 + label: '不确定',
  173 + value: 'INDETERMINATE',
  174 + color: '#00C9A7',
  175 + icon: '/static/noshue.png',
  176 + },
  177 +]
  178 +
  179 +const alarmStatus = [{
  180 + label: '清除未确认',
  181 + value: 'CLEARED_UNACK'
  182 + },
  183 + {
  184 + label: '激活未确认',
  185 + value: 'ACTIVE_UNACK'
  186 + },
  187 + {
  188 + label: '清除已确认',
  189 + value: 'CLEARED_ACK'
  190 + },
  191 + {
  192 + label: '激活已确认',
  193 + value: 'ACTIVE_ACK'
  194 + },
  195 +]
  196 +
  197 +const operationNumberOrDate = [{
  198 + label: '等于',
  199 + value: 'EQUAL',
  200 + symbol: '='
  201 + },
  202 + {
  203 + label: '不等于',
  204 + value: 'NOT_EQUAL',
  205 + symbol: '!='
  206 + },
  207 + {
  208 + label: '小于',
  209 + value: 'LESS',
  210 + symbol: '<'
  211 + },
  212 + {
  213 + label: '小于等于',
  214 + value: 'LESS_OR_EQUAL',
  215 + symbol: '<='
  216 + },
  217 + {
  218 + label: '大于',
  219 + value: 'GREATER',
  220 + symbol: '>'
  221 + },
  222 + {
  223 + label: '大于等于',
  224 + value: 'GREATER_OR_EQUAL',
  225 + symbol: '>='
  226 + },
  227 +];
  228 +
  229 +const operationString = [{
  230 + label: '等于',
  231 + value: 'EQUAL',
  232 + symbol: '='
  233 + },
  234 + {
  235 + label: '不等于',
  236 + value: 'NOT_EQUAL',
  237 + symbol: '!='
  238 + },
  239 + {
  240 + label: '开始于',
  241 + value: 'STARTS_WITH',
  242 + symbol: '开始于'
  243 + },
  244 + {
  245 + label: '结束于',
  246 + value: 'ENDS_WITH',
  247 + symbol: '结束于'
  248 + },
  249 + {
  250 + label: '包含',
  251 + value: 'CONTAINS',
  252 + symbol: '包含'
  253 + },
  254 + {
  255 + label: '不包含',
  256 + value: 'NOT_CONTAINS',
  257 + symbol: '不包含'
  258 + },
  259 +];
  260 +
  261 +const operationBoolean = [{
  262 + label: '等于',
  263 + value: 'EQUAL',
  264 + symbol: '='
  265 + },
  266 + {
  267 + label: '不等于',
  268 + value: 'NOT_EQUAL',
  269 + symbol: '!='
  270 + },
  271 +];
  272 +
146 export { 273 export {
147 alertStatus, 274 alertStatus,
148 deviceType, 275 deviceType,
149 alertLevel, 276 alertLevel,
150 - timeArea  
151 -} 277 + timeArea,
  278 + alarmSeverity,
  279 + alarmStatus,
  280 + operationNumberOrDate,
  281 + operationString,
  282 + operationBoolean
  283 +}
@@ -109,129 +109,8 @@ @@ -109,129 +109,8 @@
109 } 109 }
110 } 110 }
111 111
112 -.device-list {  
113 - display: flex;  
114 - flex-direction: column;  
115 - padding-left: 18rpx;  
116 - justify-content: flex-start;  
117 -  
118 - .list-item {  
119 - width: 713rpx;  
120 - height: 233rpx;  
121 - background-color: #fff;  
122 - margin-top: 24rpx;  
123 - display: flex;  
124 - flex-direction: row;  
125 - border-radius: 10px;  
126 - justify-content: space-between;  
127 -  
128 - .item {  
129 - justify-content: flex-start;  
130 - flex-direction: column;  
131 - align-items: center;  
132 - height: 211rpx;  
133 - margin-top: 8rpx;  
134 - margin-left: 37rpx;  
135 -  
136 - .item-text {  
137 - width: 400rpx;  
138 - text-align: left;  
139 - margin-top: 13rpx;  
140 - line-height: 40rpx;  
141 -  
142 - .text {  
143 - color: #666666;  
144 - font-size: 15px;  
145 - }  
146 -  
147 - .text-three {  
148 - color: #333333;  
149 - font-size: 15px;  
150 - }  
151 112
152 - .text-nine {  
153 - color: #999999;  
154 - font-size: 15px;  
155 - }  
156 - }  
157 113
158 - .item-right {  
159 - flex-direction: row;  
160 - margin-top: -3rpx;  
161 - margin-right: 25rpx;  
162 -  
163 - .right-image {  
164 - width: 30rpx;  
165 - height: 30rpx;  
166 - margin-top: 20rpx;  
167 - margin-right: 5rpx;  
168 - }  
169 -  
170 - .right-text {  
171 - color: #333333;  
172 - font-size: 13px;  
173 - margin-left: 5rpx;  
174 - margin-top: 20rpx;  
175 - }  
176 - }  
177 - }  
178 - }  
179 -}  
180 -  
181 -.popup-page {  
182 - height: 1100rpx;  
183 - background: #ffffff;  
184 - border-radius: 20rpx;  
185 - overflow-y: scroll;  
186 - overflow-x: hidden;  
187 -  
188 - .popup-text {  
189 - text-align: center;  
190 - position: relative;  
191 - top: 68rpx;  
192 - margin-top: -40rpx;  
193 -  
194 - .text {  
195 - font-size: 16px;  
196 - color: #333333;  
197 - }  
198 - }  
199 -  
200 - .popup-alarm-page {  
201 - margin-top: 97rpx;  
202 - margin-left: 98rpx;  
203 - flex-direction: column;  
204 - justify-content: space-between;  
205 - .popup-alarm-text {  
206 - width: 750rpx;  
207 - margin-left: 14rpx;  
208 - .text {  
209 - color: #333333;  
210 - font-size: 14px;  
211 - }  
212 - }  
213 - .popup-alarm-child {  
214 - margin-top: 15rpx;  
215 - width: 750rpx;  
216 - height: 60rpx;  
217 - flex-wrap: wrap;  
218 - margin-left: -10rpx;  
219 - .alarm-text {  
220 - margin: 25rpx;  
221 - line-height: 50rpx;  
222 - text-align: center;  
223 - width: 180rpx;  
224 - height: 60rpx;  
225 - background-color: #f6f6f6;  
226 - border-radius: 32px;  
227 - .text {  
228 - color: #333333;  
229 - font-size: 13px;  
230 - }  
231 - }  
232 - }  
233 - }  
234 -}  
235 114
236 .u-form { 115 .u-form {
237 width: 618rpx !important; 116 width: 618rpx !important;
  1 +<template>
  2 + <view class="device-list">
  3 + <view @click="$emit('openDeviceDetail',item.id, item.alarmStatus, item.lastOnlineTime, item.tbDeviceId)"
  4 + class="list-item" v-for="item in list" :key="item.id">
  5 + <view class="u-flex item">
  6 + <view class="item-text text-clip">
  7 + <view>
  8 + <text class="text-span-bold">{{ item.alias ? item.alias : item.name }}</text>
  9 + </view>
  10 + </view>
  11 + <view class="item-text text-clip">
  12 + <view class="text-container">
  13 + 设备编号:
  14 + <text class="text-span">{{ item.sn }}</text>
  15 + </view>
  16 + </view>
  17 + <view class="item-text text-clip">
  18 + <view class="text-container">
  19 + 所属组织:
  20 + <text class="text-span">{{ item.organizationDTO.name }}</text>
  21 + </view>
  22 + </view>
  23 + </view>
  24 + <view class="item right-item">
  25 + <view class="u-flex" style="margin-top: -6rpx">
  26 + <image class="right-image" :src="formatRightImage(item.deviceState)" />
  27 + <view>
  28 + <text class="right-text" :style="{ color:formatColor(item.deviceState) }">
  29 + {{ formatText(item.deviceState) }}
  30 + </text>
  31 + </view>
  32 + </view>
  33 + </view>
  34 + </view>
  35 + </view>
  36 +</template>
  37 +
  38 +<script>
  39 + export default {
  40 + props: {
  41 + list: {
  42 + type: Array,
  43 + default: []
  44 + }
  45 + },
  46 + methods: {
  47 + formatRightImage(deviceState) {
  48 + return deviceState === 'ONLINE' ?
  49 + '/static/online.png' :
  50 + deviceState === 'INACTIVE' ?
  51 + '/static/unonline.png' :
  52 + '/static/baojing.png'
  53 + },
  54 + formatText(deviceState) {
  55 + return deviceState === 'ONLINE' ? '在线' : deviceState === 'INACTIVE' ? '待激活' : '离线'
  56 + },
  57 + formatColor(deviceState) {
  58 + return deviceState === 'ONLINE' ? '#377DFF' : deviceState === 'INACTIVE' ? '#666666' : '#DE4437'
  59 + }
  60 + }
  61 + }
  62 +</script>
  63 +
  64 +<style lang="scss" scoped>
  65 + .device-list {
  66 + display: flex;
  67 + flex-direction: column;
  68 + padding-left: 20rpx;
  69 +
  70 + .list-item {
  71 + width: 713rpx;
  72 + height: 200rpx;
  73 + background-color: #fff;
  74 + margin-top: 24rpx;
  75 + display: flex;
  76 + border-radius: 10px;
  77 + justify-content: space-between;
  78 +
  79 + .item {
  80 + margin: 30rpx;
  81 + flex-direction: column;
  82 + justify-content: space-between;
  83 +
  84 + .item-text {
  85 + width: 450rpx;
  86 +
  87 + .text-container {
  88 + display: flex;
  89 +
  90 + .text-span {
  91 + color: #666;
  92 + font-size: 14px;
  93 + display: flex;
  94 + margin-left: 20rpx;
  95 + }
  96 + }
  97 +
  98 +
  99 +
  100 + .text-span-bold {
  101 + color: #333;
  102 + font-size: 15px;
  103 + font-weight: bold;
  104 + }
  105 + }
  106 + }
  107 +
  108 + .right-item {
  109 + .right-image {
  110 + width: 30rpx;
  111 + height: 30rpx;
  112 + margin-top: 5rpx;
  113 + margin-right: 5rpx;
  114 + }
  115 +
  116 + .right-text {
  117 + color: #377dff;
  118 + font-size: 13px;
  119 + margin-left: 5rpx;
  120 + margin-top: 20rpx;
  121 + }
  122 + }
  123 + }
  124 + }
  125 +</style>
  1 +<template>
  2 + <u-popup @close="$emit('close')" closeable bgColor="#fff" :show="show" mode="bottom" :round="20"
  3 + @touchmove.stop.prevent="disabledScroll">
  4 + <view class="filter" @touchmove.stop.prevent="disabledScroll">
  5 + <view class="filter-title"><text>筛选条件</text></view>
  6 + <query-item :filterList="deviceStatus" title="设备状态"
  7 + @clickTag="currentIndex => handleClickTag(currentIndex, deviceStatus)"></query-item>
  8 + <query-item :filterList="alarmStatus" title="告警状态"
  9 + @clickTag="currentIndex => handleClickTag(currentIndex, alarmStatus)"></query-item>
  10 + <query-item :filterList="typeStatus" title="设备类型"
  11 + @clickTag="currentIndex => handleClickTag(currentIndex, typeStatus)"></query-item>
  12 + <view class="button-group">
  13 + <view>
  14 + <u-button :customStyle="{ color: '#333' }" color="#e3e3e5" shape="circle" text="重置"
  15 + @click="resetFilter"></u-button>
  16 + </view>
  17 + <view>
  18 + <u-button color="#3388ff" shape="circle" text="确认" @click="confirmFilter"></u-button>
  19 + </view>
  20 + </view>
  21 + </view>
  22 + </u-popup>
  23 +</template>
  24 +
  25 +<script>
  26 + import queryItem from './query-item.vue'
  27 + import {
  28 + deviceStatus,
  29 + alarmStatus,
  30 + typeStatus
  31 + } from '../config/data.js'
  32 +
  33 + export default {
  34 + components: {
  35 + queryItem
  36 + },
  37 + props: {
  38 + show: Boolean
  39 + },
  40 + data() {
  41 + return {
  42 + deviceStatus,
  43 + alarmStatus,
  44 + typeStatus
  45 + }
  46 + },
  47 + methods: {
  48 + disabledScroll() {
  49 + return;
  50 + },
  51 + handleClickTag(currentIndex, list) {
  52 + list.map((item, index) => {
  53 + item.checked = index === currentIndex;
  54 + });
  55 + },
  56 + resetFilter() {
  57 + const {
  58 + deviceStatus,
  59 + alarmStatus,
  60 + typeStatus
  61 + } = this;
  62 + [deviceStatus, alarmStatus, typeStatus].forEach(item => item.map((item, index) => (item.checked = index ===
  63 + 0)));
  64 + },
  65 + confirmFilter() {
  66 + const deviceState = this.deviceStatus.find(item => item.checked);
  67 + const alarmStatus = this.alarmStatus.find(item => item.checked);
  68 + const deviceType = this.typeStatus.find(item => item.checked);
  69 + this.$emit('queryCondition', {
  70 + deviceState: deviceState.type ? deviceState.type : undefined,
  71 + deviceType: deviceType.type ? deviceType.type : undefined,
  72 + alarmStatus: alarmStatus.type === 0 || alarmStatus.type === 1 ? alarmStatus.type : undefined
  73 +
  74 + })
  75 + },
  76 + }
  77 + }
  78 +</script>
  79 +
  80 +<style lang="scss" scoped>
  81 + .filter {
  82 + padding: 0 30rpx;
  83 +
  84 + .filter-title {
  85 + text-align: center;
  86 + margin-top: 14px;
  87 + font-size: 16px;
  88 + font-weight: 700;
  89 + }
  90 +
  91 + .button-group {
  92 + display: flex;
  93 + margin-top: 40rpx;
  94 + justify-content: space-between;
  95 +
  96 + view {
  97 + width: 330rpx;
  98 + }
  99 + }
  100 + }
  101 +</style>
pages/device/components/query-item.vue renamed from pages/device/FilterItem.vue
1 -<template>  
2 - <view class="filter-item">  
3 - <view class="filter-title">  
4 - <text>{{ title }}</text>  
5 - </view>  
6 - <view class="filter-list">  
7 - <view v-for="(item, index) in filterList" :key="index" @click="radioClick(index)" :class="['tag-item', { checked: item.checked, 'mr-30': (index + 1) % 3 !== 0 }]">  
8 - {{ item.name }}  
9 - </view>  
10 - </view>  
11 - </view>  
12 -</template>  
13 -  
14 -<script>  
15 -export default {  
16 - props: {  
17 - title: {  
18 - type: String,  
19 - default: ''  
20 - },  
21 - filterList: {  
22 - type: Array,  
23 - default: () => []  
24 - }  
25 - },  
26 - methods: {  
27 - radioClick(currentIndex) {  
28 - this.$emit('clickTag', currentIndex);  
29 - }  
30 - }  
31 -};  
32 -</script>  
33 -  
34 -<style lang="scss" scoped>  
35 -.filter-item {  
36 - margin-top: 40rpx;  
37 - .filter-title {  
38 - color: #333;  
39 - font-size: 14px;  
40 - font-weight: 700;  
41 - }  
42 - .filter-list {  
43 - display: flex;  
44 - flex-wrap: wrap;  
45 - .tag-item {  
46 - margin-top: 30rpx;  
47 - width: 210rpx;  
48 - height: 68rpx;  
49 - border-radius: 32rpx;  
50 - display: flex;  
51 - justify-content: center;  
52 - align-items: center;  
53 - color: #333;  
54 - font-size: 13px;  
55 - border: 1px solid #fff;  
56 - background-color: #f6f6f6;  
57 - }  
58 - .checked {  
59 - border: 1px solid #377dff4d;  
60 - background-color: #377dff0d;  
61 - color: #377dffff;  
62 - }  
63 - .mr-30 {  
64 - margin-right: 30rpx;  
65 - }  
66 - }  
67 -}  
68 -</style> 1 +<template>
  2 + <view class="query-item">
  3 + <view class="query-title">
  4 + <text>{{ title }}</text>
  5 + </view>
  6 + <view class="query-list">
  7 + <view v-for="(item, index) in filterList" :key="index" @click="itemClick(index)"
  8 + :class="['tag-item', { checked: item.checked, 'mr-30': (index + 1) % 3 !== 0 }]">
  9 + {{ item.name }}
  10 + </view>
  11 + </view>
  12 + </view>
  13 +</template>
  14 +
  15 +<script>
  16 + export default {
  17 + props: {
  18 + title: {
  19 + type: String,
  20 + default: ''
  21 + },
  22 + filterList: {
  23 + type: Array,
  24 + default: () => []
  25 + }
  26 + },
  27 + methods: {
  28 + itemClick(currentIndex) {
  29 + this.$emit('clickTag', currentIndex);
  30 + }
  31 + }
  32 + };
  33 +</script>
  34 +
  35 +<style lang="scss" scoped>
  36 + .query-item {
  37 + margin-top: 40rpx;
  38 +
  39 + .query-title {
  40 + color: #333;
  41 + font-size: 14px;
  42 + font-weight: 700;
  43 + }
  44 +
  45 + .query-list {
  46 + display: flex;
  47 + flex-wrap: wrap;
  48 +
  49 + .tag-item {
  50 + margin-top: 30rpx;
  51 + width: 210rpx;
  52 + height: 68rpx;
  53 + border-radius: 32rpx;
  54 + display: flex;
  55 + justify-content: center;
  56 + align-items: center;
  57 + color: #333;
  58 + font-size: 13px;
  59 + border: 1px solid #fff;
  60 + background-color: #f6f6f6;
  61 + }
  62 +
  63 + .checked {
  64 + border: 1px solid #377dff4d;
  65 + background-color: #377dff0d;
  66 + color: #377dffff;
  67 + }
  68 +
  69 + .mr-30 {
  70 + margin-right: 30rpx;
  71 + }
  72 + }
  73 + }
  74 +</style>
  1 +const deviceStatus = [{
  2 + checked: true,
  3 + name: '全部',
  4 + type: ''
  5 + },
  6 + {
  7 + checked: false,
  8 + name: '在线',
  9 + type: 'ONLINE'
  10 + },
  11 + {
  12 + checked: false,
  13 + name: '离线',
  14 + type: 'OFFLINE'
  15 + },
  16 + {
  17 + checked: false,
  18 + name: '待激活',
  19 + type: 'INACTIVE'
  20 + }
  21 +]
  22 +const alarmStatus = [{
  23 + checked: true,
  24 + name: '全部',
  25 + type: ''
  26 + },
  27 + {
  28 + checked: false,
  29 + name: '告警',
  30 + type: 1
  31 + },
  32 + {
  33 + checked: false,
  34 + name: '正常',
  35 + type: 0
  36 + }
  37 +]
  38 +const typeStatus = [{
  39 + checked: true,
  40 + name: '全部',
  41 + type: ''
  42 + },
  43 +
  44 + {
  45 + checked: false,
  46 + name: '直连设备',
  47 + type: 'DIRECT_CONNECTION'
  48 + },
  49 + {
  50 + checked: false,
  51 + name: '网关设备',
  52 + type: 'GATEWAY'
  53 + },
  54 + {
  55 + checked: false,
  56 + name: '网关子设备',
  57 + type: 'SENSOR'
  58 + }
  59 +]
  60 +
  61 +export {
  62 + deviceStatus,
  63 + alarmStatus,
  64 + typeStatus
  65 +}
1 <template> 1 <template>
2 <view class="device-page"> 2 <view class="device-page">
3 - <u-sticky>  
4 - <view class="device-top">  
5 - <view class="search">  
6 - <view>  
7 - <view class="search-left">  
8 - <u--input prefixIcon="search" placeholder="输入设备SN或名称搜索" shape="circle"  
9 - @change="inputChanged"></u--input>  
10 - </view>  
11 - </view>  
12 - <view @click="openSearchDialog" class="search-right">  
13 - <text>筛选</text>  
14 - <image src="../../static/shaixuan.png" />  
15 - </view>  
16 - </view>  
17 - <u-line />  
18 - <view class="org">  
19 - <u-cell @click="openOrg" isLink title="组织关系" :border="false">  
20 - <view slot="label" class="label" style="display: flex; align-items: center;margin-top: 20rpx;">  
21 - <image src="../../static/org.png" style="width: 24rpx;height: 28rpx;"></image>  
22 - <view style="margin-left: 10rpx; color: #666;">  
23 - 设备数:  
24 - <text style="margin-left: 20rpx;">{{ total }}</text>  
25 - </view>  
26 - </view>  
27 - </u-cell>  
28 - </view>  
29 - </view>  
30 - </u-sticky> 3 + <!-- 设备头部 -->
  4 + <header-search @openOrg="openOrg" @openSearchDialog="openSearchDialog" :total="total" :totalText="totalText">
  5 + <!-- 不能写在封装组件里传placeholder,mp-wenxin端编译要报错 -->
  6 + <u--input prefixIcon="search" placeholder="请输入设备SN或名称搜索" shape="circle" @change="inputChanged">
  7 + </u--input>
  8 + </header-search>
  9 + <!-- 设备分页 -->
31 <mescroll-body ref="mescrollRef" @init="mescrollInit" :up="upOption" :down="downOption" @down="downCallback" 10 <mescroll-body ref="mescrollRef" @init="mescrollInit" :up="upOption" :down="downOption" @down="downCallback"
32 @up="upCallback"> 11 @up="upCallback">
33 - <view class="device-list">  
34 - <view @click="openDeviceDetail(item.id, item.alarmStatus, item.lastOnlineTime, item.tbDeviceId)"  
35 - class="list-item" v-for="item in list" :key="item.id">  
36 - <view class="u-flex item" style="  
37 - justify-content: flex-start;  
38 - flex-direction: column;  
39 - align-items: center;  
40 - ">  
41 - <view style="width: 450rpx; text-align: left">  
42 - <view class="text-clip" style="width:450rpx">  
43 - <text class=""  
44 - style="color: #333; font-size: 15px;font-weight: bold;">{{ item.alias ? item.alias : item.name }}</text>  
45 - </view>  
46 -  
47 - </view>  
48 - <view style="width: 450rpx; text-align: left; margin-top: 10rpx">  
49 - <view style="color: #666; font-size: 14px;display: flex;">  
50 - 设备编号:  
51 - <view style="margin-left:16rpx">{{ item.sn }}</view>  
52 - </view>  
53 - </view>  
54 - <view style="width: 450rpx; text-align: left; margin-top: 10rpx">  
55 - <view style="color: #666; font-size: 14px;display: flex;">  
56 - 所属组织:  
57 - <view style="margin-left:16rpx">{{ item.organizationDTO.name }}</view>  
58 - </view>  
59 - </view>  
60 - </view>  
61 - <view class="item">  
62 - <view class="u-flex" style="margin-top: -6rpx">  
63 - <image style="  
64 - width: 30rpx;  
65 - height: 30rpx;  
66 - margin-top: 5rpx;  
67 - margin-right: 5rpx;  
68 - " :src="  
69 - item.deviceState === 'ONLINE'  
70 - ? '../../static/online.png'  
71 - : item.deviceState === 'INACTIVE'  
72 - ? '../../static/unonline.png'  
73 - : '../../static/baojing.png'  
74 - " />  
75 -  
76 - <view>  
77 - <text style="  
78 - color: #377dff;  
79 - font-size: 13px;  
80 - margin-left: 5rpx;  
81 - margin-top: 20rpx;  
82 - " :style="{ color: item.deviceState === 'ONLINE' ? '#377DFF' : item.deviceState === 'INACTIVE' ? '#666666' : '#DE4437' }">  
83 - {{ item.deviceState === 'ONLINE' ? '在线' : item.deviceState === 'INACTIVE' ? '待激活' : '离线' }}  
84 - </text>  
85 - </view>  
86 - </view>  
87 - </view>  
88 - </view>  
89 - </view> 12 + <device-item :list="list" @openDeviceDetail="openDeviceDetail"></device-item>
90 </mescroll-body> 13 </mescroll-body>
91 <!-- 设备筛选 --> 14 <!-- 设备筛选 -->
92 - <u-popup @close="close" closeable bgColor="#fff" :show="show" mode="bottom" :round="20"  
93 - @touchmove.stop.prevent="disabledScroll">  
94 - <view class="filter" @touchmove.stop.prevent="disabledScroll">  
95 - <view class="filter-title"><text>筛选条件</text></view>  
96 - <FilterItem :filterList="deviceStatus" title="设备状态"  
97 - @clickTag="currentIndex => handleClickTag(currentIndex, deviceStatus)"></FilterItem>  
98 - <FilterItem :filterList="alarmStatus" title="告警状态"  
99 - @clickTag="currentIndex => handleClickTag(currentIndex, alarmStatus)"></FilterItem>  
100 - <FilterItem :filterList="typeStatus" title="设备类型"  
101 - @clickTag="currentIndex => handleClickTag(currentIndex, typeStatus)"></FilterItem>  
102 - <view class="button-group">  
103 - <view>  
104 - <u-button :customStyle="{ color: '#333' }" color="#e3e3e5" shape="circle" text="重置"  
105 - @click="resetFilter"></u-button>  
106 - </view>  
107 - <view>  
108 - <u-button color="#3388ff" shape="circle" text="确认" @click="confirmFilter"></u-button>  
109 - </view>  
110 - </view>  
111 - </view>  
112 - </u-popup> 15 + <device-popup ref="devicePopupRef" :show="show" @close="close"
  16 + @queryCondition="getQueryCondition"></device-popup>
113 <f-tabbar></f-tabbar> 17 <f-tabbar></f-tabbar>
114 </view> 18 </view>
115 </template> 19 </template>
116 20
117 <script> 21 <script>
118 import fTabbar from '@/components/module/f-tabbar/f-tabbar'; 22 import fTabbar from '@/components/module/f-tabbar/f-tabbar';
119 - import FilterItem from './FilterItem.vue';  
120 import MescrollMixin from '@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js'; 23 import MescrollMixin from '@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js';
121 - import {  
122 - debounce  
123 - } from '@/plugins/throttle.js';  
124 import api from '@/api/index.js' 24 import api from '@/api/index.js'
  25 + import {
  26 + useNavigateTo
  27 + } from '@/plugins/utils.js'
  28 + import deviceItem from './components/device-item.vue'
  29 + import devicePopup from './components/device-popup.vue'
125 30
126 export default { 31 export default {
127 mixins: [MescrollMixin], // 使用mixin (在main.js注册全局组件) 32 mixins: [MescrollMixin], // 使用mixin (在main.js注册全局组件)
128 components: { 33 components: {
129 fTabbar, 34 fTabbar,
130 - FilterItem 35 + deviceItem,
  36 + devicePopup
131 }, 37 },
132 data() { 38 data() {
133 return { 39 return {
  40 + totalText: '设备数',
134 downOption: { 41 downOption: {
135 auto: false //是否在初始化后,自动执行downCallback; 默认true 42 auto: false //是否在初始化后,自动执行downCallback; 默认true
136 }, 43 },
@@ -139,143 +46,91 @@ @@ -139,143 +46,91 @@
139 auto: false // 不自动加载 46 auto: false // 不自动加载
140 }, 47 },
141 show: false, 48 show: false,
142 - deviceStatus: [{  
143 - checked: true,  
144 - name: '全部',  
145 - type: ''  
146 - },  
147 - {  
148 - checked: false,  
149 - name: '在线',  
150 - type: 'ONLINE'  
151 - },  
152 - {  
153 - checked: false,  
154 - name: '离线',  
155 - type: 'OFFLINE'  
156 - },  
157 - {  
158 - checked: false,  
159 - name: '待激活',  
160 - type: 'INACTIVE'  
161 - }  
162 - ],  
163 - alarmStatus: [{  
164 - checked: true,  
165 - name: '全部',  
166 - type: ''  
167 - },  
168 - {  
169 - checked: false,  
170 - name: '告警',  
171 - type: 1  
172 - },  
173 - {  
174 - checked: false,  
175 - name: '正常',  
176 - type: 0  
177 - }  
178 - ],  
179 - typeStatus: [{  
180 - checked: true,  
181 - name: '全部',  
182 - type: ''  
183 - },  
184 -  
185 - {  
186 - checked: false,  
187 - name: '直连设备',  
188 - type: 'DIRECT_CONNECTION'  
189 - },  
190 - {  
191 - checked: false,  
192 - name: '网关设备',  
193 - type: 'GATEWAY'  
194 - },  
195 - {  
196 - checked: false,  
197 - name: '网关子设备',  
198 - type: 'SENSOR'  
199 - }  
200 - ],  
201 total: 0, 49 total: 0,
202 list: [], 50 list: [],
203 page: { 51 page: {
204 num: 0, 52 num: 0,
205 size: 10 53 size: 10
206 }, 54 },
207 - deviceState: '',  
208 - deviceName: '' 55 + deviceName: '',
  56 + ordId: '',
  57 + conditions: {}
209 }; 58 };
210 }, 59 },
211 - async onLoad(options) { 60 + onLoad(e) {
212 // 隐藏原生的tabbar 61 // 隐藏原生的tabbar
213 uni.hideTabBar(); 62 uni.hideTabBar();
214 - if(getApp().getBindNot()){ 63 + if (getApp().getBindNot()) {
215 return 64 return
216 } 65 }
217 - this.page.num = 1;  
218 - const {  
219 - deviceState  
220 - } = options;  
221 - this.deviceState = deviceState;  
222 - if (deviceState) {  
223 - this.deviceStatus.forEach(item => {  
224 - item.type === deviceState ? (item.checked = true) : (item.checked = false);  
225 - });  
226 - await this.loadData(1, {  
227 - deviceState  
228 - }); 66 + if (!e.deviceState) {
  67 + this.loadData(1);
229 } else { 68 } else {
230 - await this.loadData(1);  
231 - }  
232 - if (!this.list.length) {  
233 - this.mescroll.showEmpty(); 69 + let params = JSON.parse(e.deviceState);
  70 + this.conditions = {
  71 + deviceState: params
  72 + }
  73 + this.loadData(1, {
  74 + deviceState: params
  75 + });
234 } 76 }
235 }, 77 },
236 onShow() { 78 onShow() {
237 - if(getApp().getBindNot()){ 79 + if (getApp().getBindNot()) {
238 return 80 return
239 } 81 }
240 - if (this.orgId) { 82 + if (this.ordId) {
241 this.loadData(1, { 83 this.loadData(1, {
242 - organizationId: this.orgId 84 + organizationId: this.ordId
243 }); 85 });
  86 + this.conditions = {
  87 + organizationId: this.ordId
  88 + }
244 } 89 }
245 }, 90 },
246 methods: { 91 methods: {
247 - disabledScroll() {  
248 - return; 92 + inputChanged(e) {
  93 + this.page.num = 1;
  94 + this.deviceName = e;
  95 + this.conditions = {
  96 + deviceName: e
  97 + }
  98 + this.loadData(1, {
  99 + name: this.deviceName
  100 + });
  101 + },
  102 + resetQuery() {
  103 + this.$refs.devicePopupRef.resetFilter()
  104 + this.ordId = ''
  105 + this.deviceName = ''
  106 + this.conditions = {}
  107 + },
  108 + getQueryCondition(value) {
  109 + const condition = Object.values(value)
  110 + this.page.num = 1;
  111 + this.loadData(this.page.num, value);
  112 + this.conditions = value
  113 + this.close()
249 }, 114 },
250 - /*下拉刷新的回调 */  
251 downCallback() { 115 downCallback() {
252 - this.deviceName = '';  
253 - this.orgId = '';  
254 - //联网加载数据  
255 this.list = []; 116 this.list = [];
256 this.page.num = 1; 117 this.page.num = 1;
257 - //联网加载数据  
258 - this.resetFilter();  
259 this.loadData(this.page.num); 118 this.loadData(this.page.num);
  119 + this.resetQuery();
260 }, 120 },
261 -  
262 - /*上拉加载的回调: 其中page.num:当前页 从1开始, page.size:每页数据条数,默认10 */  
263 upCallback() { 121 upCallback() {
264 - //联网加载数据  
265 - this.page.num += 1;  
266 - const deviceState = this.deviceStatus.find(item => item.checked);  
267 - const alarmStatus = this.alarmStatus.find(item => item.checked);  
268 - const deviceType = this.typeStatus.find(item => item.checked);  
269 - this.loadData(this.page.num, {  
270 - deviceState: deviceState.type ? deviceState.type : undefined,  
271 - deviceType: deviceType.type ? deviceType.type : undefined,  
272 - alarmStatus: alarmStatus.type === 0 || alarmStatus.type === 1 ? alarmStatus.type :  
273 - undefined,  
274 - name: this.deviceName == null ? null : this.deviceName,  
275 - organizationId: this.orgId == null ? null : this.orgId  
276 - }); 122 + const condition = Object.values(this.conditions)
  123 + if (condition.length === 0) {
  124 + this.page.num += 1;
  125 + this.loadData(this.page.num);
  126 + } else if (condition.filter(Boolean).length > 0) {
  127 + this.page.num += 1;
  128 + this.loadData(this.page.num, this.conditions);
  129 + } else {
  130 + this.page.num += 1;
  131 + this.loadData(this.page.num);
  132 + }
277 }, 133 },
278 -  
279 //获取设备 134 //获取设备
280 async loadData(pageNo, params = {}) { 135 async loadData(pageNo, params = {}) {
281 try { 136 try {
@@ -307,54 +162,20 @@ @@ -307,54 +162,20 @@
307 } 162 }
308 }, 163 },
309 openOrg() { 164 openOrg() {
310 - uni.navigateTo({  
311 - url: './org/org'  
312 - }); 165 + useNavigateTo('/pages/organization/organization')
313 }, 166 },
314 close() { 167 close() {
315 this.show = false; 168 this.show = false;
316 }, 169 },
317 openSearchDialog() { 170 openSearchDialog() {
318 this.show = true; 171 this.show = true;
  172 + this.resetQuery()
319 }, 173 },
320 openDeviceDetail(id, alarmStatus, lastOnlineTime, tbDeviceId) { 174 openDeviceDetail(id, alarmStatus, lastOnlineTime, tbDeviceId) {
321 uni.navigateTo({ 175 uni.navigateTo({
322 url: `/deviceSubPage/deviceDetailPage/deviceDetail?id=${id}&alarmStatus=${alarmStatus}&lastOnlineTime=${lastOnlineTime}&tbDeviceId=${tbDeviceId}` 176 url: `/deviceSubPage/deviceDetailPage/deviceDetail?id=${id}&alarmStatus=${alarmStatus}&lastOnlineTime=${lastOnlineTime}&tbDeviceId=${tbDeviceId}`
323 }); 177 });
324 }, 178 },
325 - handleClickTag(currentIndex, list) {  
326 - list.map((item, index) => {  
327 - item.checked = index === currentIndex;  
328 - });  
329 - },  
330 - resetFilter() {  
331 - const {  
332 - deviceStatus,  
333 - alarmStatus,  
334 - typeStatus  
335 - } = this;  
336 - [deviceStatus, alarmStatus, typeStatus].forEach(item => item.map((item, index) => (item.checked = index ===  
337 - 0)));  
338 - },  
339 - confirmFilter() {  
340 - const deviceState = this.deviceStatus.find(item => item.checked);  
341 - const alarmStatus = this.alarmStatus.find(item => item.checked);  
342 - const deviceType = this.typeStatus.find(item => item.checked);  
343 - this.loadData(1, {  
344 - deviceState: deviceState.type ? deviceState.type : undefined,  
345 - deviceType: deviceType.type ? deviceType.type : undefined,  
346 - alarmStatus: alarmStatus.type === 0 || alarmStatus.type === 1 ? alarmStatus.type :  
347 - undefined  
348 - });  
349 - this.show = false;  
350 - },  
351 - inputChanged(e) {  
352 - this.page.num = 1;  
353 - this.deviceName = e;  
354 - this.loadData(1, {  
355 - name: this.deviceName  
356 - });  
357 - }  
358 } 179 }
359 }; 180 };
360 </script> 181 </script>
@@ -396,45 +217,4 @@ @@ -396,45 +217,4 @@
396 } 217 }
397 } 218 }
398 } 219 }
399 -  
400 - .device-list {  
401 - display: flex;  
402 - flex-direction: column;  
403 - padding-left: 20rpx;  
404 -  
405 - .list-item {  
406 - width: 713rpx;  
407 - height: 200rpx;  
408 - background-color: #fff;  
409 - margin-top: 24rpx;  
410 - display: flex;  
411 - border-radius: 10px;  
412 - justify-content: space-between;  
413 -  
414 - .item {  
415 - margin: 30rpx;  
416 - }  
417 - }  
418 - }  
419 -  
420 - .filter {  
421 - padding: 0 30rpx;  
422 -  
423 - .filter-title {  
424 - text-align: center;  
425 - margin-top: 14px;  
426 - font-size: 16px;  
427 - font-weight: 700;  
428 - }  
429 -  
430 - .button-group {  
431 - display: flex;  
432 - margin-top: 40rpx;  
433 - justify-content: space-between;  
434 -  
435 - view {  
436 - width: 330rpx;  
437 - }  
438 - }  
439 - }  
440 -</style> 220 +</style>
1 -<template>  
2 - <view class="org-content">  
3 - <!-- 公共组件-每个页面必须引入 -->  
4 - <public-module></public-module>  
5 - <view>  
6 - <luyj-tree @sendValue="confirm" :is-check="isCheck" search-placeholder="请输入搜索内容" :search-if="true" v-slot:default="{ item }" :max="max" :trees="tree" :nodes="false">  
7 - <view>  
8 - <view class="content-item">  
9 - <view class="word">{{ item.name }}</view>  
10 - </view>  
11 - </view>  
12 - </luyj-tree>  
13 - <mescroll-empty v-if="!tree.length" />  
14 - </view>  
15 - </view>  
16 -</template>  
17 -  
18 -<script>  
19 -import fTabbar from '@/components/module/f-tabbar/f-tabbar';  
20 -import { transOrgFunc } from '@/config/common.js';  
21 -export default {  
22 - components: {  
23 - fTabbar  
24 - },  
25 - data() {  
26 - return {  
27 - isCheck: true, // 是否可选  
28 - tree: [],  
29 - max: 5,  
30 - id: ''  
31 - };  
32 - },  
33 - onLoad(e) {  
34 - // 隐藏原生的tabbar  
35 - uni.hideTabBar();  
36 - this.loadData();  
37 - },  
38 - methods: {  
39 - loadData() {  
40 - uni.$u.http  
41 - .get('/yt/organization/me/list')  
42 - .then(res => {  
43 - if (res) {  
44 - const list = transOrgFunc(res);  
45 - this.tree = list;  
46 - }  
47 - })  
48 - .catch(e => {  
49 - // uni.$u.toast(e.data.message);  
50 - });  
51 - },  
52 - confirm(val) {  
53 - this.id = val[0].id;  
54 - let pages = getCurrentPages(); //获取所有页面栈实例列表  
55 - let nowPage = pages[pages.length - 1]; //当前页页面实例  
56 - let prevPage = pages[pages.length - 2]; //上一页页面实例  
57 - prevPage.$vm.orgId = this.id;  
58 - uni.navigateBack({  
59 - delta: 1  
60 - });  
61 - }  
62 - }  
63 -};  
64 -</script>  
65 -  
66 -<style lang="scss" scoped>  
67 -.org-content {  
68 - padding: 0 10rpx;  
69 -}  
70 -</style>  
@@ -2,18 +2,7 @@ @@ -2,18 +2,7 @@
2 <view class="camera-page"> 2 <view class="camera-page">
3 <!-- 公共组件-每个页面必须引入 --> 3 <!-- 公共组件-每个页面必须引入 -->
4 <public-module></public-module> 4 <public-module></public-module>
5 - <view class="org-sty">  
6 - <view @click="openOrg" class="org-item">  
7 - <view class="u-flex org-contact"><text class="text">组织关系</text></view>  
8 - <view @click="openOrg" class="u-flex org-device">  
9 - <image class="device-image" src="../../../static/org.png"></image>  
10 - <text class="device-text">摄像头数:{{ cameraTotal }}</text>  
11 - </view>  
12 - </view>  
13 - <view @click="openOrg" class="org-item">  
14 - <image class="image" src="../../../static/arrow-right.png"></image>  
15 - </view>  
16 - </view> 5 + <header-org @openOrg="openOrg" :total="cameraTotal" :imageSrc="imageSrc"></header-org>
17 <view style="height: 150rpx;"></view> 6 <view style="height: 150rpx;"></view>
18 <!-- 自带分页组件 --> 7 <!-- 自带分页组件 -->
19 <mescroll-body ref="mescrollRef" :up="upOption" @init="mescrollInit" :down="downOption" @down="downCallback" 8 <mescroll-body ref="mescrollRef" :up="upOption" @init="mescrollInit" :down="downOption" @down="downCallback"
@@ -22,8 +11,8 @@ @@ -22,8 +11,8 @@
22 <view class="container-item"> 11 <view class="container-item">
23 <view v-for="(item, index) in list" :key="item.id" class="item"> 12 <view v-for="(item, index) in list" :key="item.id" class="item">
24 <video :data-id="item.id" :data-accessMode="item.accessMode" :key="item.id" preload="none" 13 <video :data-id="item.id" :data-accessMode="item.accessMode" :key="item.id" preload="none"
25 - :id="'video' + item.id" class="video" :src="item.videoUrl || commonVideoUrl" controls  
26 - :title="item.name" x5-video-player-type="h5" x5-video-orientation="portraint" show-mute-btn 14 + :id="'video' + item.id" class="video" :src="item.videoUrl" controls :title="item.name"
  15 + x5-video-player-type="h5" x5-video-orientation="portraint" show-mute-btn
27 :poster="item.avatar" @play="playVideo"></video> 16 :poster="item.avatar" @play="playVideo"></video>
28 <view style="width:300rpx" class="bottom-text text-clip"> 17 <view style="width:300rpx" class="bottom-text text-clip">
29 <text class="text">{{ item.name }}</text> 18 <text class="text">{{ item.name }}</text>
@@ -41,11 +30,19 @@ @@ -41,11 +30,19 @@
41 <script> 30 <script>
42 import MescrollMixin from '@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js'; 31 import MescrollMixin from '@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js';
43 import api from '@/api/index.js' 32 import api from '@/api/index.js'
  33 + import {
  34 + useNavigateTo
  35 + } from '@/plugins/utils.js'
  36 + import headerOrg from '@/components/common/header-org.vue'
44 37
45 export default { 38 export default {
46 mixins: [MescrollMixin], // 使用mixin (在main.js注册全局组件) 39 mixins: [MescrollMixin], // 使用mixin (在main.js注册全局组件)
  40 + components:{
  41 + headerOrg
  42 + },
47 data() { 43 data() {
48 return { 44 return {
  45 + imageSrc:'/static/org.png',
49 page: { 46 page: {
50 num: 0, 47 num: 0,
51 size: 10 48 size: 10
@@ -60,17 +57,15 @@ @@ -60,17 +57,15 @@
60 cameraTotal: 0, 57 cameraTotal: 0,
61 list: [], 58 list: [],
62 ordId: '', 59 ordId: '',
63 - commonVideoUrl: 'http://playertest.longtailvideo.com/adaptive/bipbop/gear4/prog_index.m3u8'  
64 }; 60 };
65 }, 61 },
66 onShow() { 62 onShow() {
67 - if (this.ordId == '') {} else { 63 + if (this.ordId) {
68 this.loadData(1, this.ordId); 64 this.loadData(1, this.ordId);
69 } 65 }
70 }, 66 },
71 onHide() { 67 onHide() {
72 this.ordId = ''; 68 this.ordId = '';
73 - this.loadData(1, null);  
74 }, 69 },
75 onLoad() { 70 onLoad() {
76 // 隐藏原生的tabbar 71 // 隐藏原生的tabbar
@@ -167,9 +162,7 @@ @@ -167,9 +162,7 @@
167 }); 162 });
168 }, 163 },
169 openOrg() { 164 openOrg() {
170 - uni.navigateTo({  
171 - url: './org/org'  
172 - }); 165 + useNavigateTo('/pages/organization/organization')
173 } 166 }
174 } 167 }
175 }; 168 };
@@ -177,4 +170,4 @@ @@ -177,4 +170,4 @@
177 170
178 <style lang="scss" scoped> 171 <style lang="scss" scoped>
179 @import '../static/camera.scss'; 172 @import '../static/camera.scss';
180 -</style> 173 +</style>
1 -<template>  
2 - <view class="org-content">  
3 - <!-- 公共组件-每个页面必须引入 -->  
4 - <public-module></public-module>  
5 - <view>  
6 - <luyj-tree @sendValue="confirm" :is-check="isCheck" search-placeholder="请输入搜索内容" :search-if="true" v-slot:default="{ item }" :max="max" :trees="tree">  
7 - <view>  
8 - <view class="content-item">  
9 - <view class="word">{{ item.name }}</view>  
10 - </view>  
11 - </view>  
12 - </luyj-tree>  
13 - </view>  
14 - </view>  
15 -</template>  
16 -  
17 -<script>  
18 -import { transOrgFunc } from '@/config/common.js';  
19 -  
20 -export default {  
21 - data() {  
22 - return {  
23 - isCheck: true, // 是否可选  
24 - tree: [],  
25 - max: 5,  
26 - id: ''  
27 - };  
28 - },  
29 - onLoad(e) {  
30 - // 隐藏原生的tabbar  
31 - uni.hideTabBar();  
32 - this.loadData();  
33 - },  
34 - methods: {  
35 - loadData() {  
36 - uni.$u.http  
37 - .get('/yt/organization/me/list')  
38 - .then(res => {  
39 - if (res) {  
40 - const list = transOrgFunc(res);  
41 - this.tree = list;  
42 - }  
43 - })  
44 - .catch(e => {});  
45 - },  
46 - confirm(val) {  
47 - this.id = val[0].id;  
48 - let pages = getCurrentPages(); //获取所有页面栈实例列表  
49 - let nowPage = pages[pages.length - 1]; //当前页页面实例  
50 - let prevPage = pages[pages.length - 2]; //上一页页面实例  
51 - prevPage.$vm.ordId = this.id;  
52 - uni.navigateBack({  
53 - delta: 1  
54 - });  
55 - }  
56 - }  
57 -};  
58 -</script>  
59 -  
60 -<style lang="scss" scoped>  
61 -.org-content {  
62 - padding: 0 10rpx;  
63 -}  
64 -</style>  
  1 +const basicGridList = [{
  2 + event: 'openCamera',
  3 + icon: '/static/camer.png',
  4 + text: '摄像头管理'
  5 + },
  6 + {
  7 + event: 'openConfiguration',
  8 + icon: '/static/status.png',
  9 + text: '组态'
  10 + },
  11 +]
  12 +
  13 +const basicStatistics = [{
  14 + text: '设备统计',
  15 + icon: '/static/device-total.png',
  16 + leftParam: 'ONLINE',
  17 + centerParam: 'OFFLINE',
  18 + rightParam: 'INACTIVE',
  19 + value: {
  20 + leftValue: 0,
  21 + centerValue: 0,
  22 + rightrValue: 0
  23 + },
  24 + label: {
  25 + leftText: "在线",
  26 + centerText: "离线",
  27 + rightText: "待激活"
  28 + }
  29 + },
  30 + {
  31 + text: '告警统计',
  32 + icon: '/static/alert.png',
  33 + leftParam: ['ACTIVE_ACK'],
  34 + centerParam: 'CLEARED_ACK',
  35 + rightParam: 'CLEARED_UNACK',
  36 + value: {
  37 + leftValue: 0,
  38 + centerValue: 0,
  39 + rightrValue: 0
  40 + },
  41 + label: {
  42 + leftText: "未处理",
  43 + centerText: "已处理",
  44 + rightText: "误报"
  45 + }
  46 + },
  47 +]
  48 +
  49 +export {
  50 + basicGridList,
  51 + basicStatistics
  52 +}
@@ -64,6 +64,10 @@ @@ -64,6 +64,10 @@
64 import { 64 import {
65 useNavigateTo 65 useNavigateTo
66 } from '@/plugins/utils.js' 66 } from '@/plugins/utils.js'
  67 + import {
  68 + basicGridList,
  69 + basicStatistics
  70 + } from './config/data.js'
67 71
68 export default { 72 export default {
69 components: { 73 components: {
@@ -71,52 +75,8 @@ @@ -71,52 +75,8 @@
71 }, 75 },
72 data() { 76 data() {
73 return { 77 return {
74 - basicGridList: [{  
75 - event: 'openCamera',  
76 - icon: '/static/camer.png',  
77 - text: '摄像头管理'  
78 - },  
79 - {  
80 - event: 'openConfiguration',  
81 - icon: '/static/status.png',  
82 - text: '组态'  
83 - },  
84 - ],  
85 - basicStatistics: [{  
86 - text: '设备统计',  
87 - icon: '/static/device-total.png',  
88 - leftParam: 'ONLINE',  
89 - centerParam: 'OFFLINE',  
90 - rightParam: 'INACTIVE',  
91 - value: {  
92 - leftValue: 0,  
93 - centerValue: 0,  
94 - rightrValue: 0  
95 - },  
96 - label: {  
97 - leftText: "在线",  
98 - centerText: "离线",  
99 - rightText: "待激活"  
100 - }  
101 - },  
102 - {  
103 - text: '告警统计',  
104 - icon: '/static/alert.png',  
105 - leftParam: ['ACTIVE_UNACK'],  
106 - centerParam: 'CLEARED_ACK',  
107 - rightParam: 'CLEARED_UNACK',  
108 - value: {  
109 - leftValue: 0,  
110 - centerValue: 0,  
111 - rightrValue: 0  
112 - },  
113 - label: {  
114 - leftText: "未处理",  
115 - centerText: "已处理",  
116 - rightText: "误报"  
117 - }  
118 - },  
119 - ] 78 + basicGridList,
  79 + basicStatistics,
120 }; 80 };
121 }, 81 },
122 onLoad() { 82 onLoad() {
@@ -185,7 +145,7 @@ @@ -185,7 +145,7 @@
185 //设备状态查询 145 //设备状态查询
186 navigatorDeviceStatus(e) { 146 navigatorDeviceStatus(e) {
187 uni.reLaunch({ 147 uni.reLaunch({
188 - url: `../device/device?deviceState=${e}` 148 + url: '../device/device?deviceState=' + JSON.stringify(e)
189 }); 149 });
190 } 150 }
191 } 151 }
@@ -2,54 +2,6 @@ @@ -2,54 +2,6 @@
2 min-height: 100vh; 2 min-height: 100vh;
3 background-color: #f0f2f5; 3 background-color: #f0f2f5;
4 } 4 }
5 -.org-sty {  
6 - width: 750rpx;  
7 - height: 150rpx;  
8 - margin-top: 1rpx;  
9 - background-color: #fff;  
10 - display: flex;  
11 - flex-direction: row;  
12 - justify-content: space-between;  
13 - position: fixed;  
14 - z-index: 999999;  
15 - top: -1rpx;  
16 - .org-item {  
17 - width: 350rpx;  
18 - height: 200rpx;  
19 - .org-contact {  
20 - flex-direction: row;  
21 - margin-top: 26rpx;  
22 - margin-left: 15rpx;  
23 - .text {  
24 - color: #333333;  
25 - font-size: 15px;  
26 - margin-left: 14rpx;  
27 - }  
28 - }  
29 - .org-device {  
30 - margin-top: 23rpx;  
31 - margin-left: 15rpx;  
32 - flex-direction: row;  
33 - .device-image {  
34 - margin-left: 14rpx;  
35 - width: 30rpx;  
36 - height: 30rpx;  
37 - }  
38 - .device-text {  
39 - margin-left: 10rpx;  
40 - color: #666666;  
41 - font-size: 12px;  
42 - }  
43 - }  
44 - .image {  
45 - width: 6px;  
46 - height: 10px;  
47 - float: right;  
48 - margin-right: 34rpx;  
49 - margin-top: 37rpx;  
50 - }  
51 - }  
52 -}  
53 .camera-item { 5 .camera-item {
54 height: 200rpx; 6 height: 200rpx;
55 border: 0.1px solid gray; 7 border: 0.1px solid gray;
pages/personal/components/bind-account-modal.vue renamed from pages/personal/components/bindAccountModal.vue
@@ -75,7 +75,7 @@ @@ -75,7 +75,7 @@
75 <script> 75 <script>
76 import fTabbar from '@/components/module/f-tabbar/f-tabbar'; 76 import fTabbar from '@/components/module/f-tabbar/f-tabbar';
77 import fNavbar from '@/components/module/f-navbar/f-navbar'; 77 import fNavbar from '@/components/module/f-navbar/f-navbar';
78 - import bindAccountModal from './components/bindAccountModal.vue' 78 + import bindAccountModal from './components/bind-account-modal.vue'
79 import { 79 import {
80 mapState, 80 mapState,
81 mapMutations 81 mapMutations
@@ -10,7 +10,8 @@ const DATE_TIME_FORMAT = "YYYY-MM-DD HH:mm:ss"; @@ -10,7 +10,8 @@ const DATE_TIME_FORMAT = "YYYY-MM-DD HH:mm:ss";
10 必须包含1个大写字母 10 必须包含1个大写字母
11 必须包含1个特殊字符 11 必须包含1个特殊字符
12 */ 12 */
13 -export const loginPasswordReg = /^.*(?=.{6,16})(?=.*\d)(?=.*[A-Z]{1,})(?=.*[a-z]{1,})(?=.*[_!@#$%^&*?\(\)]).*$/; 13 +export const loginPasswordReg =
  14 + /^.*(?=.{6,16})(?=.*\d)(?=.*[A-Z]{1,})(?=.*[a-z]{1,})(?=.*[_!@#$%^&*?\(\)]).*$/;
14 15
15 //手机号中间4位为* 16 //手机号中间4位为*
16 Vue.filter("phone", function(val) { 17 Vue.filter("phone", function(val) {
@@ -146,38 +147,38 @@ export function formatToDate(date = undefined, format = DATE_TIME_FORMAT) { @@ -146,38 +147,38 @@ export function formatToDate(date = undefined, format = DATE_TIME_FORMAT) {
146 147
147 //封装uniapp跳转 navigateTo 148 //封装uniapp跳转 navigateTo
148 export const useNavigateTo = (path, param) => { 149 export const useNavigateTo = (path, param) => {
149 - if (!path) return 150 + if (!path) return;
150 if (param) { 151 if (param) {
151 uni.navigateTo({ 152 uni.navigateTo({
152 - url: path + encodeURIComponent(JSON.stringify(param)) 153 + url: path + encodeURIComponent(JSON.stringify(param)),
153 }); 154 });
154 } else { 155 } else {
155 uni.navigateTo({ 156 uni.navigateTo({
156 - url: path 157 + url: path,
157 }); 158 });
158 } 159 }
159 -} 160 +};
160 161
161 //封装uniapp跳转 reLaunch 162 //封装uniapp跳转 reLaunch
162 export const useReLaunch = (path, param) => { 163 export const useReLaunch = (path, param) => {
163 - if (!path) return 164 + if (!path) return;
164 if (param) { 165 if (param) {
165 uni.reLaunch({ 166 uni.reLaunch({
166 - url: path + encodeURIComponent(JSON.stringify(param)) 167 + url: path + encodeURIComponent(JSON.stringify(param)),
167 }); 168 });
168 } else { 169 } else {
169 uni.reLaunch({ 170 uni.reLaunch({
170 - url: path 171 + url: path,
171 }); 172 });
172 } 173 }
173 -} 174 +};
174 175
175 //封装uniapp showToast 176 //封装uniapp showToast
176 export const useShowToast = (title, duration = 500, mask = false) => { 177 export const useShowToast = (title, duration = 500, mask = false) => {
177 return new Promise((resolve, reject) => { 178 return new Promise((resolve, reject) => {
178 uni.showToast({ 179 uni.showToast({
179 title: title, 180 title: title,
180 - icon: 'none', 181 + icon: "none",
181 duration, 182 duration,
182 mask, 183 mask,
183 success: (res) => { 184 success: (res) => {
@@ -185,10 +186,10 @@ export const useShowToast = (title, duration = 500, mask = false) => { @@ -185,10 +186,10 @@ export const useShowToast = (title, duration = 500, mask = false) => {
185 }, 186 },
186 fail: (err) => { 187 fail: (err) => {
187 reject(err); 188 reject(err);
188 - }  
189 - })  
190 - })  
191 -} 189 + },
  190 + });
  191 + });
  192 +};
192 193
193 //封装uniapp showModal 194 //封装uniapp showModal
194 export const useShowModal = (content, title = "提示", confirmText = "确定") => { 195 export const useShowModal = (content, title = "提示", confirmText = "确定") => {
@@ -202,13 +203,19 @@ export const useShowModal = (content, title = "提示", confirmText = "确定") @@ -202,13 +203,19 @@ export const useShowModal = (content, title = "提示", confirmText = "确定")
202 }, 203 },
203 fail: (err) => { 204 fail: (err) => {
204 reject(err); 205 reject(err);
205 - }  
206 - })  
207 - })  
208 -} 206 + },
  207 + });
  208 + });
  209 +};
209 210
210 //封装uniapp uni.uploadFile 211 //封装uniapp uni.uploadFile
211 -export const useUploadFile = (url, filePath, name = "file", formData, header) => { 212 +export const useUploadFile = (
  213 + url,
  214 + filePath,
  215 + name = "file",
  216 + formData,
  217 + header
  218 +) => {
212 return new Promise(function(resolve, reject) { 219 return new Promise(function(resolve, reject) {
213 uni.uploadFile({ 220 uni.uploadFile({
214 url, //请求接口地址 221 url, //请求接口地址
@@ -221,42 +228,57 @@ export const useUploadFile = (url, filePath, name = "file", formData, header) => @@ -221,42 +228,57 @@ export const useUploadFile = (url, filePath, name = "file", formData, header) =>
221 }, 228 },
222 fail(err) { 229 fail(err) {
223 reject(res); 230 reject(res);
224 - }  
225 - })  
226 - })  
227 -} 231 + },
  232 + });
  233 + });
  234 +};
228 235
229 //封装uniapp uniapp.chooseImage 236 //封装uniapp uniapp.chooseImage
230 export const useChooseImage = (data) => { 237 export const useChooseImage = (data) => {
231 return new Promise((resolve, reject) => { 238 return new Promise((resolve, reject) => {
232 uni.chooseImage({ 239 uni.chooseImage({
233 count: data.count || 1, //默认1 240 count: data.count || 1, //默认1
234 - sizeType: data.sizeType || ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有  
235 - sourceType: data.sourceType || ['album', 'camera'], //从相册选择 241 + sizeType: data.sizeType || ["original", "compressed"], //可以指定是原图还是压缩图,默认二者都有
  242 + sourceType: data.sourceType || ["album", "camera"], //从相册选择
236 success: function(res) { 243 success: function(res) {
237 resolve(res.tempFiles); 244 resolve(res.tempFiles);
238 }, 245 },
239 - fail: err => { 246 + fail: (err) => {
240 reject({ 247 reject({
241 errMsg: err.errMsg, 248 errMsg: err.errMsg,
242 errCode: err.errCode, 249 errCode: err.errCode,
243 statusCode: 0, 250 statusCode: 0,
244 }); 251 });
245 - } 252 + },
246 }); 253 });
247 }); 254 });
248 -} 255 +};
249 256
250 //文件上传校验 257 //文件上传校验
251 export const useFileValidate = (file, fileSize) => { 258 export const useFileValidate = (file, fileSize) => {
252 if (file.size > fileSize) { 259 if (file.size > fileSize) {
253 - useShowToast('上传的图片大小不能超过5M', 2000, true)  
254 - throw Error("上传的图片大小不能超过5M") 260 + useShowToast("上传的图片大小不能超过5M", 2000, true);
  261 + throw Error("上传的图片大小不能超过5M");
255 } 262 }
256 - const fileTxt = file.path.split('.').pop();  
257 - const fileTypeList = ['jpg', 'jpeg', 'png'] 263 + const fileTxt = file.path.split(".").pop();
  264 + const fileTypeList = ["jpg", "jpeg", "png"];
258 if (!fileTypeList.includes(fileTxt)) { 265 if (!fileTypeList.includes(fileTxt)) {
259 - useShowToast('请上传指定图片类型(jpg、jpeg、png)', 2000, true)  
260 - throw Error("请上传指定图片类型(jpg、jpeg、png)") 266 + useShowToast("请上传指定图片类型(jpg、jpeg、png)", 2000, true);
  267 + throw Error("请上传指定图片类型(jpg、jpeg、png)");
261 } 268 }
262 -}  
  269 +};
  270 +
  271 +//封装uniapp uni.pageScrollTo
  272 +export const usePageScrollTo = (scrollTop, duration) => {
  273 + uni.pageScrollTo({
  274 + scrollTop, // 滚动到页面的目标位置 这个是滚动到顶部, 0
  275 + duration, // 滚动动画的时长
  276 + });
  277 +};
  278 +
  279 +//封装uniapp跳转 navigateBack
  280 +export const useNavigateBack = (delta) => {
  281 + uni.navigateBack({
  282 + delta
  283 + });
  284 +};
@@ -112,7 +112,7 @@ @@ -112,7 +112,7 @@
112 useShowToast('登录成功~').then(async (res) => { 112 useShowToast('登录成功~').then(async (res) => {
113 this.saveUserInfo(); 113 this.saveUserInfo();
114 await this.getAlarmTotalData(); 114 await this.getAlarmTotalData();
115 - useReLaunch("/pages/personal/personal") 115 + useReLaunch("/pages/index/index")
116 }); 116 });
117 } 117 }
118 }, 118 },
@@ -132,7 +132,7 @@ @@ -132,7 +132,7 @@
132 useShowToast(toastText).then(async (res) => { 132 useShowToast(toastText).then(async (res) => {
133 this.saveUserInfo(); 133 this.saveUserInfo();
134 await this.getAlarmTotalData(); 134 await this.getAlarmTotalData();
135 - useReLaunch("/pages/personal/personal") 135 + useReLaunch("/pages/index/index")
136 }); 136 });
137 }, 137 },
138 //微信授权登录 138 //微信授权登录
@@ -161,7 +161,7 @@ @@ -161,7 +161,7 @@
161 this.setUserInfo(userInfo); 161 this.setUserInfo(userInfo);
162 //设置全局变量openId 162 //设置全局变量openId
163 getApp().globalData.openId = res.thirdUserId; 163 getApp().globalData.openId = res.thirdUserId;
164 - useReLaunch("/pages/personal/personal") 164 + useReLaunch("/pages/index/index")
165 } else { 165 } else {
166 // 不需要绑定,直接第三方登录使用 166 // 不需要绑定,直接第三方登录使用
167 this.saveLoginInfo(res,true,null,"第三方账号登录成功") 167 this.saveLoginInfo(res,true,null,"第三方账号登录成功")