Commit 1a1e18c68473e2d078a01f9f80c7f7bc4b1874a7

Authored by fengtao
1 parent 4fd21827

fix:修改设备实时数据传keys和历史数据传参加上limit

1 // 获取某个Key的历史数据 1 // 获取某个Key的历史数据
  2 +const getUrlParams = (params) => {
  3 + return Object.keys(params).reduce((prev, next, currentIndex) => {
  4 + if (params[next]) {
  5 + return prev += `${!currentIndex ? '?' : '&'}${next}=${params[next]}`
  6 + }
  7 + return prev
  8 + }, '')
  9 +}
  10 +
2 export function getHistoryData(params) { 11 export function getHistoryData(params) {
3 - const {  
4 - entityId,  
5 - keys,  
6 - startTs,  
7 - endTs,  
8 - interval 12 + let {
  13 + entityId
9 } = params 14 } = params
  15 + params = getUrlParams(params)
10 return uni.$u.http.get( 16 return uni.$u.http.get(
11 - `/plugins/telemetry/DEVICE/${entityId}/values/timeseries?keys=${keys}&startTs=${startTs}&endTs=${endTs}&interval=${interval}` 17 + `/plugins/telemetry/DEVICE/${entityId}/values/timeseries${params}`
12 ); 18 );
13 } 19 }
14 20
  21 +
  22 +
15 // 获取当前设备的key 23 // 获取当前设备的key
16 export function getDeviceKeys(id) { 24 export function getDeviceKeys(id) {
17 return uni.$u.http.get(`/plugins/telemetry/DEVICE/${id}/keys/timeseries`); 25 return uni.$u.http.get(`/plugins/telemetry/DEVICE/${id}/keys/timeseries`);
18 }; 26 };
19 27
20 export function issueCommand(type, tbDeviceId, data) { 28 export function issueCommand(type, tbDeviceId, data) {
21 - console.log(type,tbDeviceId) 29 + console.log(type, tbDeviceId)
22 return uni.$u.http.post(`/rpc/${type==='OneWay'?'oneway':'twoway'}/${tbDeviceId}`, data) 30 return uni.$u.http.post(`/rpc/${type==='OneWay'?'oneway':'twoway'}/${tbDeviceId}`, data)
23 } 31 }
1 <template> 1 <template>
2 - <view class="device-detail-page">  
3 - <!-- 公共组件-每个页面必须引入 -->  
4 - <public-module></public-module>  
5 - <u-sticky bgColor="#fff">  
6 - <u-tabs  
7 - :list="list"  
8 - :current="currentTab"  
9 - @click="handleTabClick"  
10 - :activeStyle="{ 2 + <view class="device-detail-page">
  3 + <!-- 公共组件-每个页面必须引入 -->
  4 + <public-module></public-module>
  5 + <u-sticky bgColor="#fff">
  6 + <u-tabs :list="list" :current="currentTab" @click="handleTabClick" :activeStyle="{
11 fontWeight: 'bold', 7 fontWeight: 'bold',
12 color: '#333', 8 color: '#333',
13 - }"  
14 - :inactiveStyle="{ 9 + }" :inactiveStyle="{
15 color: '#999', 10 color: '#999',
16 - }"  
17 - :scrollable="isScrollable"  
18 - />  
19 - </u-sticky>  
20 - <view style="margin-top: 30rpx">  
21 - <basicInfo v-show="currentTab == 0" :deviceDetail="deviceDetail" />  
22 - <realTimeData v-show="currentTab === 1" :recordList="recordList" />  
23 - <historyData  
24 - v-if="currentTab === 2"  
25 - :keys="keys"  
26 - :yesterday="yesterday"  
27 - :today="today"  
28 - :timeDiff="timeDiff"  
29 - :historyData="historyData"  
30 - :entityId="entityId"  
31 - :start="startTs"  
32 - :end="endTs"  
33 - @update="handleUpdate"  
34 - />  
35 - <alarmHistory v-show="currentTab === 3" :deviceId="deviceId" />  
36 - <commondRecord v-if="currentTab === 4" :tbDeviceId="entityId" />  
37 - </view>  
38 - </view> 11 + }" :scrollable="isScrollable" />
  12 + </u-sticky>
  13 + <view style="margin-top: 30rpx">
  14 + <basicInfo v-show="currentTab == 0" :deviceDetail="deviceDetail" />
  15 + <realTimeData v-show="currentTab === 1" :recordList="recordList" />
  16 + <historyData v-if="currentTab === 2" :keys="keys" :yesterday="yesterday" :today="today" :timeDiff="timeDiff"
  17 + :historyData="historyData" :entityId="entityId" :start="startTs" :end="endTs" @update="handleUpdate" />
  18 + <alarmHistory v-show="currentTab === 3" :deviceId="deviceId" />
  19 + <commondRecord v-if="currentTab === 4" :tbDeviceId="entityId" />
  20 + </view>
  21 + </view>
39 </template> 22 </template>
40 23
41 <script> 24 <script>
42 -import fTabbar from "@/components/module/f-tabbar/f-tabbar";  
43 -import basicInfo from "./tabDetail/basicInfo.vue";  
44 -import realTimeData from "./tabDetail/realtimeData.vue";  
45 -import alarmHistory from "./tabDetail/alarmHistory.vue";  
46 -import historyData from "./tabDetail/historyData.vue";  
47 -import commondRecord from "./tabDetail/CommandRecord.vue";  
48 -import { getDeviceKeys, getHistoryData } from "./api/index.js";  
49 -import { formatToDate } from "@/plugins/utils.js";  
50 -import MescrollCompMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mixins/mescroll-comp.js";  
51 -import moment from "moment";  
52 -import base from "@/config/baseUrl.js"; 25 + import fTabbar from "@/components/module/f-tabbar/f-tabbar";
  26 + import basicInfo from "./tabDetail/basicInfo.vue";
  27 + import realTimeData from "./tabDetail/realtimeData.vue";
  28 + import alarmHistory from "./tabDetail/alarmHistory.vue";
  29 + import historyData from "./tabDetail/historyData.vue";
  30 + import commondRecord from "./tabDetail/CommandRecord.vue";
  31 + import {
  32 + getDeviceKeys,
  33 + getHistoryData
  34 + } from "./api/index.js";
  35 + import {
  36 + formatToDate
  37 + } from "@/plugins/utils.js";
  38 + import MescrollCompMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mixins/mescroll-comp.js";
  39 + import moment from "moment";
  40 + import base from "@/config/baseUrl.js";
53 41
54 -export default {  
55 - mixins: [MescrollCompMixin],  
56 - components: {  
57 - fTabbar,  
58 - basicInfo,  
59 - realTimeData,  
60 - alarmHistory,  
61 - historyData,  
62 - commondRecord,  
63 - },  
64 - data() {  
65 - return {  
66 - list: [  
67 - {  
68 - name: "基础信息",  
69 - },  
70 - {  
71 - name: "实时数据",  
72 - },  
73 - {  
74 - name: "历史数据",  
75 - },  
76 - {  
77 - name: "告警记录",  
78 - },  
79 - ],  
80 - currentTab: 0,  
81 - deviceId: "",  
82 - deviceDetail: {},  
83 - keys: [],  
84 - yesterday: "",  
85 - today: "",  
86 - timeDiff: "",  
87 - historyData: [],  
88 - entityId: "",  
89 - startTs: "",  
90 - endTs: "",  
91 - recordList: [],  
92 - isScrollable: false,  
93 - };  
94 - },  
95 - onUnload() {  
96 - // 页面关闭时,销毁webSocket连接,否则第二次会存在连接不到的情况  
97 - uni.closeSocket();  
98 - },  
99 - async onLoad(options) {  
100 - const { id, alarmStatus, lastOnlineTime, tbDeviceId } = options;  
101 - this.deviceId = id;  
102 - const res = await uni.$u.http.get(`/yt/device/${id}`);  
103 - this.deviceDetail = {  
104 - ...res,  
105 - alarmStatus,  
106 - lastOnlineTime,  
107 - }; 42 + export default {
  43 + mixins: [MescrollCompMixin],
  44 + components: {
  45 + fTabbar,
  46 + basicInfo,
  47 + realTimeData,
  48 + alarmHistory,
  49 + historyData,
  50 + commondRecord,
  51 + },
  52 + data() {
  53 + return {
  54 + list: [{
  55 + name: "基础信息",
  56 + },
  57 + {
  58 + name: "实时数据",
  59 + },
  60 + {
  61 + name: "历史数据",
  62 + },
  63 + {
  64 + name: "告警记录",
  65 + },
  66 + ],
  67 + currentTab: 0,
  68 + deviceId: "",
  69 + deviceDetail: {},
  70 + keys: [],
  71 + yesterday: "",
  72 + today: "",
  73 + timeDiff: "",
  74 + historyData: [],
  75 + entityId: "",
  76 + startTs: "",
  77 + endTs: "",
  78 + recordList: [],
  79 + isScrollable: false,
  80 + attrList: []
  81 + };
  82 + },
  83 + onUnload() {
  84 + // 页面关闭时,销毁webSocket连接,否则第二次会存在连接不到的情况
  85 + uni.closeSocket();
  86 + },
  87 + async onLoad(options) {
  88 + const {
  89 + id,
  90 + alarmStatus,
  91 + lastOnlineTime,
  92 + tbDeviceId,
  93 + deviceProfileId
  94 + } =
  95 + options;
  96 + this.deviceId = id;
  97 + const res = await uni.$u.http.get(`/yt/device/${id}`);
  98 + this.deviceDetail = {
  99 + ...res,
  100 + alarmStatus,
  101 + lastOnlineTime,
  102 + };
108 103
109 - // 设备类型不是网关子设备的添加一个命令记录的选项卡  
110 - if (this.deviceDetail.deviceType !== "SENSOR") {  
111 - this.list.push({  
112 - name: "命令记录",  
113 - });  
114 - }  
115 - this.isScrollable = this.list.length > 4;  
116 - // 连接webSockte  
117 - const socketTask = uni.connectSocket({  
118 - url:  
119 - `${base.socketPrefix}://${base.baseWebSocketUrl}/api/ws/plugins/telemetry?token=` +  
120 - uni.getStorageSync("userInfo").isToken, //仅为示例,并非真实接口地址。  
121 - complete: () => {},  
122 - });  
123 - uni.onSocketOpen((header) => {  
124 - socketTask.send({  
125 - data: JSON.stringify({  
126 - attrSubCmds: [],  
127 - tsSubCmds: [  
128 - {  
129 - entityType: "DEVICE",  
130 - entityId: tbDeviceId,  
131 - scope: "LATEST_TELEMETRY",  
132 - cmdId: 1,  
133 - },  
134 - ],  
135 - historyCmds: [],  
136 - entityDataCmds: [],  
137 - entityDataUnsubscribeCmds: [],  
138 - alarmDataCmds: [],  
139 - alarmDataUnsubscribeCmds: [],  
140 - entityCountCmds: [],  
141 - entityCountUnsubscribeCmds: [],  
142 - }),  
143 - success() {},  
144 - });  
145 - });  
146 - socketTask.onMessage((msg) => {  
147 - const { data } = JSON.parse(msg.data);  
148 - const newArray = [];  
149 - for (const key in data) {  
150 - const [time, value] = data[key].flat(1);  
151 - let obj = {  
152 - key,  
153 - time,  
154 - value,  
155 - };  
156 - if (this.recordList.length === 0) {  
157 - this.recordList.unshift(obj);  
158 - } else {  
159 - newArray.push(obj);  
160 - }  
161 - }  
162 - newArray.forEach((item) => {  
163 - let flag = false;  
164 - this.recordList.forEach((item1) => {  
165 - if (item1.key === item.key) {  
166 - item1.value = item.value;  
167 - item1.time = item.time;  
168 - flag = true;  
169 - }  
170 - });  
171 - if (!flag) {  
172 - this.recordList.unshift(item);  
173 - }  
174 - });  
175 - this.recordList = this.recordList.map((item) => {  
176 - return {  
177 - ...item,  
178 - time: formatToDate(item.time, "YYYY-MM-DD HH:mm:ss"),  
179 - };  
180 - });  
181 - }); 104 + // 设备类型不是网关子设备的添加一个命令记录的选项卡
  105 + if (this.deviceDetail.deviceType !== "SENSOR") {
  106 + this.list.push({
  107 + name: "命令记录",
  108 + });
  109 + }
  110 + this.isScrollable = this.list.length > 4;
  111 + if (res.deviceProfileId) {
  112 + const getAttrList = await uni.$u.http.get(
  113 + `/yt/device/attributes/${res.deviceProfileId}`
  114 + );
  115 + if (Array.isArray(getAttrList)) {
  116 + this.attrList = getAttrList.map(m => {
  117 + return m.identifier
  118 + })
  119 + }
  120 + }
  121 + // 连接webSockte
  122 + const socketTask = uni.connectSocket({
  123 + url: `${base.socketPrefix}://${base.baseWebSocketUrl}/api/ws/plugins/telemetry?token=` +
  124 + uni.getStorageSync("userInfo").isToken, //仅为示例,并非真实接口地址。
  125 + complete: () => {},
  126 + });
  127 + uni.onSocketOpen((header) => {
  128 + socketTask.send({
  129 + data: JSON.stringify({
  130 + attrSubCmds: [],
  131 + tsSubCmds: [{
  132 + entityType: "DEVICE",
  133 + entityId: tbDeviceId,
  134 + scope: "LATEST_TELEMETRY",
  135 + cmdId: 1,
  136 + keys: this.attrList.join(','),
  137 + }, ],
  138 + historyCmds: [],
  139 + entityDataCmds: [],
  140 + entityDataUnsubscribeCmds: [],
  141 + alarmDataCmds: [],
  142 + alarmDataUnsubscribeCmds: [],
  143 + entityCountCmds: [],
  144 + entityCountUnsubscribeCmds: [],
  145 + }),
  146 + success() {},
  147 + });
  148 + });
  149 + socketTask.onMessage((msg) => {
  150 + const {
  151 + data
  152 + } = JSON.parse(msg.data);
  153 + const newArray = [];
  154 + for (const key in data) {
  155 + const [time, value] = data[key].flat(1);
  156 + let obj = {
  157 + key,
  158 + time,
  159 + value,
  160 + };
  161 + if (this.recordList.length === 0) {
  162 + this.recordList.unshift(obj);
  163 + } else {
  164 + newArray.push(obj);
  165 + }
  166 + }
  167 + newArray.forEach((item) => {
  168 + let flag = false;
  169 + this.recordList.forEach((item1) => {
  170 + if (item1.key === item.key) {
  171 + item1.value = item.value;
  172 + item1.time = item.time;
  173 + flag = true;
  174 + }
  175 + });
  176 + if (!flag) {
  177 + this.recordList.unshift(item);
  178 + }
  179 + });
  180 + this.recordList = this.recordList.map((item) => {
  181 + return {
  182 + ...item,
  183 + time: formatToDate(item.time, "YYYY-MM-DD HH:mm:ss"),
  184 + };
  185 + });
  186 + });
182 187
183 - const keys = await getDeviceKeys(tbDeviceId);  
184 - this.keys = [keys];  
185 - // 昨天  
186 - this.yesterday = moment().subtract(1, "days").format("YYYY-MM-DD");  
187 - // 今天  
188 - this.today = moment().format("YYYY-MM-DD");  
189 - // 开始时间  
190 - this.startTs = moment().subtract(1, "days").format("x");  
191 - // 结束时间  
192 - this.endTs = moment().format("x");  
193 - this.entityId = tbDeviceId; 188 + const keys = await getDeviceKeys(tbDeviceId);
  189 + this.keys = [keys];
  190 + // 昨天
  191 + this.yesterday = moment().subtract(1, "days").format("YYYY-MM-DD");
  192 + // 今天
  193 + this.today = moment().format("YYYY-MM-DD");
  194 + // 开始时间
  195 + this.startTs = moment().subtract(1, "days").format("x");
  196 + // 结束时间
  197 + this.endTs = moment().format("x");
  198 + this.entityId = tbDeviceId;
194 199
195 - const data = await getHistoryData({  
196 - entityId: tbDeviceId,  
197 - startTs: this.startTs,  
198 - endTs: this.endTs,  
199 - keys: keys[0],  
200 - interval: 1800000,  
201 - });  
202 - this.timeDiff = "30分钟";  
203 - if (!Object.keys(data).length) return; 200 + const data = await getHistoryData({
  201 + entityId: tbDeviceId,
  202 + startTs: this.startTs,
  203 + endTs: this.endTs,
  204 + keys: keys[0],
  205 + // interval: 1800000,
  206 + limit: 7,
  207 + agg: 'NONE'
  208 + });
  209 + this.timeDiff = "30分钟";
  210 + if (!Object.keys(data).length) return;
204 211
205 - this.historyData = data[keys[0]].map((item) => {  
206 - return {  
207 - value: item.value,  
208 - ts: formatToDate(item.ts, "YYYY-MM-DD HH:mm:ss"),  
209 - };  
210 - });  
211 - },  
212 - methods: {  
213 - handleTabClick({ index }) {  
214 - this.currentTab = index;  
215 - },  
216 - handleUpdate(data) {  
217 - if (!Array.isArray(data)) {  
218 - this.historyData = [];  
219 - return;  
220 - }  
221 - this.historyData = data.map((item) => {  
222 - return {  
223 - value: item.value,  
224 - ts: formatToDate(item.ts, "YYYY-MM-DD HH:mm:ss"),  
225 - };  
226 - });  
227 - },  
228 - },  
229 -}; 212 + this.historyData = data[keys[0]].map((item) => {
  213 + return {
  214 + value: item.value,
  215 + ts: formatToDate(item.ts, "YYYY-MM-DD HH:mm:ss"),
  216 + };
  217 + });
  218 + },
  219 + methods: {
  220 + handleTabClick({
  221 + index
  222 + }) {
  223 + this.currentTab = index;
  224 + },
  225 + handleUpdate(data, e) {
  226 + if (!Array.isArray(data)) {
  227 + this.historyData = [];
  228 + return;
  229 + }
  230 + this.historyData = data.map((item) => {
  231 + return {
  232 + value: item.value,
  233 + ts: formatToDate(item.ts, "YYYY-MM-DD HH:mm:ss"),
  234 + };
  235 + });
  236 + },
  237 + },
  238 + };
230 </script> 239 </script>
231 240
232 <style lang="scss" scoped> 241 <style lang="scss" scoped>
233 -.device-detail-page {  
234 - height: 100vh;  
235 - background-color: #f8f9fa;  
236 -}  
237 -</style> 242 + .device-detail-page {
  243 + height: 100vh;
  244 + background-color: #f8f9fa;
  245 + }
  246 +</style>
@@ -5,33 +5,42 @@ @@ -5,33 +5,42 @@
5 <view class="historyData-top"> 5 <view class="historyData-top">
6 <u-form :label-style="{ 'font-size': '0rpx' }"> 6 <u-form :label-style="{ 'font-size': '0rpx' }">
7 <u-form-item @click="openCalendar"> 7 <u-form-item @click="openCalendar">
8 - <u-input v-model="timeData.selectTime" disabled disabledColor="#fff" placeholder="请选择日期" border="none" suffixIcon="arrow-down"> 8 + <u-input v-model="timeData.selectTime" disabled disabledColor="#fff" placeholder="请选择日期"
  9 + border="none" suffixIcon="arrow-down">
9 <template slot="prefix"> 10 <template slot="prefix">
10 <image class="icon" src="../../../static/can-der.png"></image> 11 <image class="icon" src="../../../static/can-der.png"></image>
11 </template> 12 </template>
12 </u-input> 13 </u-input>
13 </u-form-item> 14 </u-form-item>
14 <u-form-item @click="openTimeGap"> 15 <u-form-item @click="openTimeGap">
15 - <u-input v-model="timeData.getTimeGap" disabled disabledColor="#fff" placeholder="请选择时间区间" border="none" suffixIcon="arrow-down"> 16 + <u-input v-model="timeData.getTimeGap" disabled disabledColor="#fff" placeholder="请选择时间区间"
  17 + border="none" suffixIcon="arrow-down">
16 <template slot="prefix"> 18 <template slot="prefix">
17 <image class="icon" src="../../../static/time.png"></image> 19 <image class="icon" src="../../../static/time.png"></image>
18 </template> 20 </template>
19 </u-input> 21 </u-input>
20 </u-form-item> 22 </u-form-item>
  23 + <u-form-item @click="openAvg">
  24 + <u-input shape="circle" v-model="aggText" placeholder="请选择数据聚合功能" disabled disabledColor="#377DFF0D"
  25 + suffixIcon="arrow-down" />
  26 + </u-form-item>
  27 + <u-form-item @click="openTimeGap" v-if="limitFlag">
  28 + <view class="u-flex">
  29 + <text>最大条数</text>
  30 + <u-number-box style="margin-left:30rpx" class="ml-10" v-model="timeData.limit" :min="7"
  31 + :max="50000"></u-number-box>
  32 + </view>
  33 + </u-form-item>
21 <u-form-item @click="openType"> 34 <u-form-item @click="openType">
22 - <u-input shape="circle" v-model="timeData.getType" placeholder="请选择属性" disabled disabledColor="#377DFF0D" suffixIcon="arrow-down" /> 35 + <u-input shape="circle" v-model="timeData.getType" placeholder="请选择属性" disabled
  36 + disabledColor="#377DFF0D" suffixIcon="arrow-down" />
23 </u-form-item> 37 </u-form-item>
24 </u-form> 38 </u-form>
25 39
26 <view class="charts-box" v-show="historyData.length"> 40 <view class="charts-box" v-show="historyData.length">
27 - <qiun-data-charts  
28 - type="area"  
29 - canvas2d  
30 - canvasId="daskujdhasljkdcnzjkdfhuoqwlqwjhkdsamjczxnmdasd123321"  
31 - :chartData="chartData"  
32 - :ontouch="true"  
33 - :opts="{ xAxis: { disabled: true, itemCount: 6, scrollShow: true }, legend: { show: false }, enableScroll: true }"  
34 - /> 41 + <qiun-data-charts type="area" canvas2d canvasId="daskujdhasljkdcnzjkdfhuoqwlqwjhkdsamjczxnmdasd123321"
  42 + :chartData="chartData" :ontouch="true"
  43 + :opts="{ xAxis: { disabled: true, itemCount: 6, scrollShow: true }, legend: { show: false }, enableScroll: true }" />
35 </view> 44 </view>
36 <mescroll-empty v-if="!historyData.length" /> 45 <mescroll-empty v-if="!historyData.length" />
37 </view> 46 </view>
@@ -41,166 +50,125 @@ @@ -41,166 +50,125 @@
41 <view class="th">变量值</view> 50 <view class="th">变量值</view>
42 <view class="th">更新时间</view> 51 <view class="th">更新时间</view>
43 </view> 52 </view>
44 - <view class="tr bg-g" :class="{ odd: index % 2 === 0 }" v-for="(item, index) in historyData" :key="index"> 53 + <view class="tr bg-g" :class="{ odd: index % 2 === 0 }" v-for="(item, index) in historyData"
  54 + :key="index">
45 <view class="td">{{ item.value }}</view> 55 <view class="td">{{ item.value }}</view>
46 <view class="td">{{ item.ts }}</view> 56 <view class="td">{{ item.ts }}</view>
47 </view> 57 </view>
48 </view> 58 </view>
49 </view> 59 </view>
50 - <u-calendar  
51 - :show="showCalendar"  
52 - :defaultDate="defaultDate"  
53 - closeOnClickOverlay  
54 - mode="range"  
55 - startText="开始时间"  
56 - endText="结束时间"  
57 - confirmDisabledText="请选择日期"  
58 - :minDate="minDate"  
59 - :maxDate="maxDate"  
60 - @confirm="calendarConfirm"  
61 - @close="calendarClose"  
62 - ></u-calendar>  
63 - <u-picker  
64 - :show="showTimeGap"  
65 - :columns="columns"  
66 - keyName="label"  
67 - closeOnClickOverlay  
68 - @confirm="confirmTimeGap"  
69 - @cancel="cancelTimeGap"  
70 - @close="cancelTimeGap"  
71 - :defaultIndex="[3]"  
72 - ></u-picker>  
73 - <u-picker :show="showSelectType" :columns="keys" closeOnClickOverlay @confirm="confirmTypeGap" @cancel="cancelTypeGap" @close="cancelTypeGap"></u-picker> 60 + <u-calendar :show="showCalendar" :defaultDate="defaultDate" closeOnClickOverlay mode="range" startText="开始时间"
  61 + endText="结束时间" confirmDisabledText="请选择日期" :minDate="minDate" :maxDate="maxDate" @confirm="calendarConfirm"
  62 + @close="calendarClose"></u-calendar>
  63 + <u-picker :show="showTimeGap" :columns="columns" keyName="label" closeOnClickOverlay @confirm="confirmTimeGap"
  64 + @cancel="cancelTimeGap" @close="cancelTimeGap" :defaultIndex="[3]"></u-picker>
  65 + <u-picker :show="showSelectType" :columns="keys" closeOnClickOverlay @confirm="confirmTypeGap"
  66 + @cancel="cancelTypeGap" @close="cancelTypeGap"></u-picker>
  67 + <u-picker :show="showSelectAvg" :columns="avgColumns" keyName="label" closeOnClickOverlay
  68 + @confirm="confirmAvgGap" @cancel="showSelectAvg=false" @close="showSelectAvg=false"></u-picker>
74 </view> 69 </view>
75 </template> 70 </template>
76 71
77 <script> 72 <script>
78 -import fTabbar from '@/components/module/f-tabbar/f-tabbar';  
79 -import qiunDataCharts from '@/uni_modules/qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue';  
80 -import { getHistoryData } from '../api/index.js';  
81 -import { formatToDate } from '@/plugins/utils.js';  
82 -const d = new Date();  
83 -const year = d.getFullYear();  
84 -let month = d.getMonth() + 1;  
85 -month = month < 10 ? `0${month}` : month;  
86 -const date = d.getDate();  
87 -export default {  
88 - components: {  
89 - fTabbar,  
90 - qiunDataCharts  
91 - },  
92 - props: {  
93 - keys: {  
94 - type: Array,  
95 - default: () => []  
96 - },  
97 - yesterday: {  
98 - type: String,  
99 - default: ''  
100 - },  
101 - today: {  
102 - type: String,  
103 - default: ''  
104 - },  
105 - timeDiff: {  
106 - type: String,  
107 - default: ''  
108 - },  
109 - historyData: {  
110 - type: Array,  
111 - default: () => []  
112 - },  
113 - entityId: {  
114 - type: String,  
115 - required: true  
116 - },  
117 - start: {  
118 - type: String,  
119 - required: true 73 + import fTabbar from '@/components/module/f-tabbar/f-tabbar';
  74 + import qiunDataCharts from '@/uni_modules/qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue';
  75 + import {
  76 + getHistoryData
  77 + } from '../api/index.js';
  78 + import {
  79 + formatToDate
  80 + } from '@/plugins/utils.js';
  81 + const d = new Date();
  82 + const year = d.getFullYear();
  83 + let month = d.getMonth() + 1;
  84 + month = month < 10 ? `0${month}` : month;
  85 + const date = d.getDate();
  86 + export default {
  87 + components: {
  88 + fTabbar,
  89 + qiunDataCharts
120 }, 90 },
121 - end: {  
122 - type: String,  
123 - required: true  
124 - }  
125 - },  
126 - data() {  
127 - return {  
128 - startTs: this.start,  
129 - endTs: this.end,  
130 - showCalendar: false,  
131 - showTimeGap: false,  
132 - showSelectType: false,  
133 - minDate: `${year}-${month - 1}-${date}`,  
134 - maxDate: `${year}-${month}-${date + 1}`,  
135 - defaultDate: [this.yesterday, this.today],  
136 - chartData: {  
137 - categories: this.historyData.length && this.historyData.map(item => item.ts),  
138 - series: [  
139 - {  
140 - name: this.keys[0][0],  
141 - data: this.historyData.length && this.historyData.map(item => Number(item.value))  
142 - }  
143 - ] 91 + props: {
  92 + keys: {
  93 + type: Array,
  94 + default: () => []
144 }, 95 },
145 - columns: [  
146 - [  
147 - {  
148 - label: '5分钟',  
149 - value: 300000  
150 - },  
151 - {  
152 - label: '10分钟',  
153 - value: 600000  
154 - },  
155 - {  
156 - label: '15分钟',  
157 - value: 900000  
158 - },  
159 - {  
160 - label: '30分钟',  
161 - value: 1800000  
162 - },  
163 - {  
164 - label: '1小时',  
165 - value: 3600000  
166 - },  
167 - {  
168 - label: '2小时',  
169 - value: 7200000  
170 - }  
171 - ]  
172 - ],  
173 - timeData: {  
174 - selectTime: this.yesterday + ' 至 ' + this.today,  
175 - getTimeGap: this.timeDiff,  
176 - getType: this.keys[0][0]  
177 - }  
178 - };  
179 - },  
180 - watch: {  
181 - historyData(newValue) {  
182 - if (!newValue.length) {  
183 - this.chartData.categories = [];  
184 - this.chartData.series = [];  
185 - } else {  
186 - this.chartData.categories = newValue.map(item => item.ts);  
187 - this.chartData.series = [  
188 - {  
189 - name: this.keys[0][0],  
190 - data: newValue.map(item => Number(item.value))  
191 - }  
192 - ]; 96 + yesterday: {
  97 + type: String,
  98 + default: ''
  99 + },
  100 + today: {
  101 + type: String,
  102 + default: ''
  103 + },
  104 + timeDiff: {
  105 + type: String,
  106 + default: ''
  107 + },
  108 + historyData: {
  109 + type: Array,
  110 + default: () => []
  111 + },
  112 + entityId: {
  113 + type: String,
  114 + required: true
  115 + },
  116 + start: {
  117 + type: String,
  118 + required: true
  119 + },
  120 + end: {
  121 + type: String,
  122 + required: true
193 } 123 }
194 - }  
195 - },  
196 - methods: {  
197 - // 动态生成Columns  
198 - generateColumns(value) {  
199 - if (value < 604800000) {  
200 - // 小于7天  
201 - return [  
202 - [ 124 + },
  125 + data() {
  126 + return {
  127 + limitFlag: true,
  128 + avgColumns: [
  129 + [{
  130 + label: '最小值',
  131 + value: 'MIN'
  132 + }, {
  133 + label: '最大值',
  134 + value: 'MAX'
  135 + },
  136 + {
  137 + label: '平均值',
  138 + value: 'AVG'
  139 + },
  140 + {
  141 + label: '求和',
  142 + value: 'SUM'
  143 + },
  144 + {
  145 + label: '计数',
  146 + value: 'COUNT'
  147 + },
203 { 148 {
  149 + label: '空',
  150 + value: 'NONE'
  151 + },
  152 + ]
  153 + ],
  154 + startTs: this.start,
  155 + endTs: this.end,
  156 + showCalendar: false,
  157 + showTimeGap: false,
  158 + showSelectType: false,
  159 + showSelectAvg: false,
  160 + minDate: `${year}-${month - 1}-${date}`,
  161 + maxDate: `${year}-${month}-${date + 1}`,
  162 + defaultDate: [this.yesterday, this.today],
  163 + chartData: {
  164 + categories: this.historyData.length && this.historyData.map(item => item.ts),
  165 + series: [{
  166 + name: this.keys[0][0],
  167 + data: this.historyData.length && this.historyData.map(item => Number(item.value))
  168 + }]
  169 + },
  170 + columns: [
  171 + [{
204 label: '5分钟', 172 label: '5分钟',
205 value: 300000 173 value: 300000
206 }, 174 },
@@ -225,173 +193,253 @@ export default { @@ -225,173 +193,253 @@ export default {
225 value: 7200000 193 value: 7200000
226 } 194 }
227 ] 195 ]
228 - ];  
229 - } else if (value < 2592000000) {  
230 - // 小于30天  
231 - return [  
232 - [  
233 - {  
234 - label: '30分钟',  
235 - value: 1800000  
236 - },  
237 - {  
238 - label: '1小时',  
239 - value: 3600000  
240 - },  
241 - {  
242 - label: '2小时',  
243 - value: 7200000  
244 - },  
245 - {  
246 - label: '5小时',  
247 - value: 18000000  
248 - },  
249 - {  
250 - label: '10小时',  
251 - value: 36000000  
252 - },  
253 - {  
254 - label: '12小时',  
255 - value: 43200000  
256 - },  
257 - {  
258 - label: '1天',  
259 - value: 86400000  
260 - }  
261 - ]  
262 - ];  
263 - } else if (value >= 2592000000) {  
264 - // 大于30天  
265 - return [  
266 - [  
267 - {  
268 - label: '2小时',  
269 - value: 7200000  
270 - },  
271 - {  
272 - label: '5小时',  
273 - value: 18000000  
274 - },  
275 - {  
276 - label: '10小时',  
277 - value: 36000000  
278 - },  
279 - {  
280 - label: '12小时',  
281 - value: 43200000  
282 - },  
283 - {  
284 - label: '1天',  
285 - value: 86400000  
286 - }  
287 - ]  
288 - ];  
289 - }  
290 - },  
291 - openCalendar() {  
292 - this.showCalendar = true;  
293 - },  
294 - openTimeGap() {  
295 - this.showTimeGap = true; 196 + ],
  197 + timeData: {
  198 + selectTime: this.yesterday + ' 至 ' + this.today,
  199 + getTimeGap: this.timeDiff,
  200 + getType: this.keys[0][0],
  201 + limit: 7,
  202 + agg: 'NONE'
  203 + },
  204 + aggText: '空'
  205 + };
296 }, 206 },
297 - openType() {  
298 - this.showSelectType = true;  
299 - },  
300 - calendarConfirm(date) {  
301 - this.showCalendar = false;  
302 - this.timeData.selectTime = `${date[0]} 至 ${date[date.length - 1]}`;  
303 - // 选择的日期时间差(时间戳)  
304 - const timeDiff = formatToDate(date[date.length - 1], 'x') - formatToDate(date[0], 'x');  
305 - const genColumns = this.generateColumns(timeDiff);  
306 - this.columns = genColumns;  
307 - this.timeData.getTimeGap = '';  
308 - this.timeData.getType = '';  
309 - this.startTs = formatToDate(date[0], 'x');  
310 - // 最后时间的最后一秒  
311 - this.endTs = formatToDate(`${date[date.length - 1]} 23:59:59`, 'x');  
312 - },  
313 - calendarClose() {  
314 - this.showCalendar = false;  
315 - },  
316 - confirmTimeGap(time) {  
317 - this.showTimeGap = false;  
318 - this.timeData.getTimeGap = time.value[0].label;  
319 - this.timeData.getType = ''; 207 + watch: {
  208 + historyData(newValue) {
  209 + if (!newValue.length) {
  210 + this.chartData.categories = [];
  211 + this.chartData.series = [];
  212 + } else {
  213 + this.chartData.categories = newValue.map(item => item.ts);
  214 + this.chartData.series = [{
  215 + name: this.keys[0][0],
  216 + data: newValue.map(item => Number(item.value))
  217 + }];
  218 + }
  219 + }
320 }, 220 },
  221 + methods: {
  222 + // 动态生成Columns
  223 + generateColumns(value) {
  224 + if (value < 604800000) {
  225 + // 小于7天
  226 + return [
  227 + [{
  228 + label: '5分钟',
  229 + value: 300000
  230 + },
  231 + {
  232 + label: '10分钟',
  233 + value: 600000
  234 + },
  235 + {
  236 + label: '15分钟',
  237 + value: 900000
  238 + },
  239 + {
  240 + label: '30分钟',
  241 + value: 1800000
  242 + },
  243 + {
  244 + label: '1小时',
  245 + value: 3600000
  246 + },
  247 + {
  248 + label: '2小时',
  249 + value: 7200000
  250 + }
  251 + ]
  252 + ];
  253 + } else if (value < 2592000000) {
  254 + // 小于30天
  255 + return [
  256 + [{
  257 + label: '30分钟',
  258 + value: 1800000
  259 + },
  260 + {
  261 + label: '1小时',
  262 + value: 3600000
  263 + },
  264 + {
  265 + label: '2小时',
  266 + value: 7200000
  267 + },
  268 + {
  269 + label: '5小时',
  270 + value: 18000000
  271 + },
  272 + {
  273 + label: '10小时',
  274 + value: 36000000
  275 + },
  276 + {
  277 + label: '12小时',
  278 + value: 43200000
  279 + },
  280 + {
  281 + label: '1天',
  282 + value: 86400000
  283 + }
  284 + ]
  285 + ];
  286 + } else if (value >= 2592000000) {
  287 + // 大于30天
  288 + return [
  289 + [{
  290 + label: '2小时',
  291 + value: 7200000
  292 + },
  293 + {
  294 + label: '5小时',
  295 + value: 18000000
  296 + },
  297 + {
  298 + label: '10小时',
  299 + value: 36000000
  300 + },
  301 + {
  302 + label: '12小时',
  303 + value: 43200000
  304 + },
  305 + {
  306 + label: '1天',
  307 + value: 86400000
  308 + }
  309 + ]
  310 + ];
  311 + }
  312 + },
  313 + openCalendar() {
  314 + this.showCalendar = true;
  315 + },
  316 + openTimeGap() {
  317 + this.showTimeGap = true;
  318 + },
  319 + openType() {
  320 + this.showSelectType = true;
  321 + },
  322 + openAvg() {
  323 + this.showSelectAvg = true
  324 + },
  325 + calendarConfirm(date) {
  326 + this.showCalendar = false;
  327 + this.timeData.selectTime = `${date[0]} 至 ${date[date.length - 1]}`;
  328 + // 选择的日期时间差(时间戳)
  329 + const timeDiff = formatToDate(date[date.length - 1], 'x') - formatToDate(date[0], 'x');
  330 + const genColumns = this.generateColumns(timeDiff);
  331 + this.columns = genColumns;
  332 + this.timeData.getTimeGap = '';
  333 + this.timeData.getType = '';
  334 + this.startTs = formatToDate(date[0], 'x');
  335 + // 最后时间的最后一秒
  336 + this.endTs = formatToDate(`${date[date.length - 1]} 23:59:59`, 'x');
  337 + },
  338 + calendarClose() {
  339 + this.showCalendar = false;
  340 + },
  341 + confirmTimeGap(time) {
  342 + this.showTimeGap = false;
  343 + this.timeData.getTimeGap = time.value[0].label;
  344 + this.timeData.getType = '';
  345 + },
321 346
322 - cancelTimeGap() {  
323 - this.showTimeGap = false;  
324 - },  
325 - async confirmTypeGap(time) {  
326 - this.showSelectType = false;  
327 - this.timeData.getType = time.value[0];  
328 - const interval = this.columns[0].find(item => item.label === this.timeData.getTimeGap);  
329 - const data = await getHistoryData({  
330 - startTs: this.startTs,  
331 - endTs: this.endTs,  
332 - keys: this.timeData.getType,  
333 - interval: interval.value,  
334 - entityId: this.entityId  
335 - });  
336 - this.$emit('update', data[this.timeData.getType]);  
337 - },  
338 - cancelTypeGap() {  
339 - this.showSelectType = false; 347 + cancelTimeGap() {
  348 + this.showTimeGap = false;
  349 + },
  350 + confirmAvgGap(e) {
  351 + this.timeData.agg = e.value[0].value
  352 + this.aggText = e.value[0].label
  353 + if (e.value[0].value === 'NONE') {
  354 + this.limitFlag = true
  355 + this.timeData.limit = 7
  356 + } else {
  357 + this.timeData.limit = null
  358 + this.limitFlag = false
  359 + }
  360 + this.showSelectAvg = false
  361 + },
  362 + async confirmTypeGap(time) {
  363 + this.showSelectType = false;
  364 + this.timeData.getType = time.value[0];
  365 + const interval = this.columns[0].find(item => item.label === this.timeData.getTimeGap);
  366 + const data = await getHistoryData({
  367 + startTs: this.startTs,
  368 + endTs: this.endTs,
  369 + keys: this.timeData.getType,
  370 + interval: this.limitFlag ? null : interval.value,
  371 + entityId: this.entityId,
  372 + limit: this.timeData.limit,
  373 + agg: this.timeData.agg
  374 + });
  375 + this.$emit('update', data[this.timeData.getType]);
  376 + },
  377 + cancelTypeGap() {
  378 + this.showSelectType = false;
  379 + }
340 } 380 }
341 - }  
342 -}; 381 + };
343 </script> 382 </script>
344 383
345 <style lang="scss" scoped> 384 <style lang="scss" scoped>
346 -.charts-box {  
347 - width: 100%;  
348 - height: 550rpx;  
349 -}  
350 -.historyData {  
351 - margin: 30rpx;  
352 - .historyData-top {  
353 - padding: 30rpx;  
354 - background-color: #fff;  
355 - // height: 870rpx;  
356 - border-radius: 20rpx;  
357 - .icon {  
358 - width: 28rpx;  
359 - height: 28rpx;  
360 - margin-right: 15rpx;  
361 - } 385 + .charts-box {
  386 + width: 100%;
  387 + height: 550rpx;
362 } 388 }
363 - .historyData-bottom {  
364 - margin-top: 30rpx;  
365 - background-color: #fff;  
366 - border-radius: 20rpx;  
367 - .table {  
368 - border: 0px solid darkgray;  
369 - .tr {  
370 - display: flex;  
371 - width: 100%;  
372 - justify-content: center;  
373 - height: 3rem;  
374 - align-items: center;  
375 - .th { 389 +
  390 + .historyData {
  391 + margin: 30rpx;
  392 +
  393 + .historyData-top {
  394 + padding: 30rpx;
  395 + background-color: #fff;
  396 + // height: 870rpx;
  397 + border-radius: 20rpx;
  398 +
  399 + .icon {
  400 + width: 28rpx;
  401 + height: 28rpx;
  402 + margin-right: 15rpx;
  403 + }
  404 + }
  405 +
  406 + .historyData-bottom {
  407 + margin-top: 30rpx;
  408 + background-color: #fff;
  409 + border-radius: 20rpx;
  410 +
  411 + .table {
  412 + border: 0px solid darkgray;
  413 +
  414 + .tr {
376 display: flex; 415 display: flex;
  416 + width: 100%;
377 justify-content: center; 417 justify-content: center;
  418 + height: 3rem;
378 align-items: center; 419 align-items: center;
379 - width: 50%;  
380 - color: #333;  
381 - font-weight: 500;  
382 - }  
383 - .td {  
384 - color: #999;  
385 - width: 50%;  
386 - display: flex;  
387 - justify-content: center;  
388 - text-align: center; 420 +
  421 + .th {
  422 + display: flex;
  423 + justify-content: center;
  424 + align-items: center;
  425 + width: 50%;
  426 + color: #333;
  427 + font-weight: 500;
  428 + }
  429 +
  430 + .td {
  431 + color: #999;
  432 + width: 50%;
  433 + display: flex;
  434 + justify-content: center;
  435 + text-align: center;
  436 + }
389 } 437 }
390 } 438 }
391 } 439 }
392 } 440 }
393 -}  
394 -.odd {  
395 - background-color: #f9fcff;  
396 -} 441 +
  442 + .odd {
  443 + background-color: #f9fcff;
  444 + }
397 </style> 445 </style>
@@ -4,7 +4,10 @@ @@ -4,7 +4,10 @@
4 <view class="device-top"> 4 <view class="device-top">
5 <view class="search"> 5 <view class="search">
6 <view> 6 <view>
7 - <view class="search-left"><u--input prefixIcon="search" placeholder="输入设备SN或名称搜索" shape="circle" @change="inputChanged"></u--input></view> 7 + <view class="search-left">
  8 + <u--input prefixIcon="search" placeholder="输入设备SN或名称搜索" shape="circle"
  9 + @change="inputChanged"></u--input>
  10 + </view>
8 </view> 11 </view>
9 <view @click="openSearchDialog" class="search-right"> 12 <view @click="openSearchDialog" class="search-right">
10 <text>筛选</text> 13 <text>筛选</text>
@@ -25,19 +28,19 @@ @@ -25,19 +28,19 @@
25 </view> 28 </view>
26 </view> 29 </view>
27 </u-sticky> 30 </u-sticky>
28 - <mescroll-body ref="mescrollRef" @init="mescrollInit" :up="upOption" :down="downOption" @down="downCallback" @up="upCallback"> 31 + <mescroll-body ref="mescrollRef" @init="mescrollInit" :up="upOption" :down="downOption" @down="downCallback"
  32 + @up="upCallback">
29 <view class="device-list"> 33 <view class="device-list">
30 - <view @click="openDeviceDetail(item.id, item.alarmStatus, item.lastOnlineTime, item.tbDeviceId)" class="list-item" v-for="item in list" :key="item.id">  
31 - <view  
32 - class="u-flex item"  
33 - style=" 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="
34 justify-content: flex-start; 37 justify-content: flex-start;
35 flex-direction: column; 38 flex-direction: column;
36 align-items: center; 39 align-items: center;
37 - "  
38 - > 40 + ">
39 <view style="width: 450rpx; text-align: left"> 41 <view style="width: 450rpx; text-align: left">
40 - <text style="color: #333; font-size: 15px;font-weight: bold;">{{ item.name }}</text> 42 + <text
  43 + style="color: #333; font-size: 15px;font-weight: bold;">{{ item.alias?item.alias:item.name }}</text>
41 </view> 44 </view>
42 <view style="width: 450rpx; text-align: left; margin-top: 10rpx"> 45 <view style="width: 450rpx; text-align: left; margin-top: 10rpx">
43 <view style="color: #666; font-size: 14px;display: flex;"> 46 <view style="color: #666; font-size: 14px;display: flex;">
@@ -54,32 +57,26 @@ @@ -54,32 +57,26 @@
54 </view> 57 </view>
55 <view class="item"> 58 <view class="item">
56 <view class="u-flex" style="margin-top: -6rpx"> 59 <view class="u-flex" style="margin-top: -6rpx">
57 - <image  
58 - style=" 60 + <image style="
59 width: 30rpx; 61 width: 30rpx;
60 height: 30rpx; 62 height: 30rpx;
61 margin-top: 5rpx; 63 margin-top: 5rpx;
62 margin-right: 5rpx; 64 margin-right: 5rpx;
63 - "  
64 - :src=" 65 + " :src="
65 item.deviceState === 'ONLINE' 66 item.deviceState === 'ONLINE'
66 ? '../../static/online.png' 67 ? '../../static/online.png'
67 : item.deviceState === 'INACTIVE' 68 : item.deviceState === 'INACTIVE'
68 ? '../../static/unonline.png' 69 ? '../../static/unonline.png'
69 : '../../static/baojing.png' 70 : '../../static/baojing.png'
70 - "  
71 - /> 71 + " />
72 72
73 <view> 73 <view>
74 - <text  
75 - style=" 74 + <text style="
76 color: #377dff; 75 color: #377dff;
77 font-size: 13px; 76 font-size: 13px;
78 margin-left: 5rpx; 77 margin-left: 5rpx;
79 margin-top: 20rpx; 78 margin-top: 20rpx;
80 - "  
81 - :style="{ color: item.deviceState === 'ONLINE' ? '#377DFF' : item.deviceState === 'INACTIVE' ? '#666666' : '#DE4437' }"  
82 - > 79 + " :style="{ color: item.deviceState === 'ONLINE' ? '#377DFF' : item.deviceState === 'INACTIVE' ? '#666666' : '#DE4437' }">
83 {{ item.deviceState === 'ONLINE' ? '在线' : item.deviceState === 'INACTIVE' ? '待激活' : '离线' }} 80 {{ item.deviceState === 'ONLINE' ? '在线' : item.deviceState === 'INACTIVE' ? '待激活' : '离线' }}
84 </text> 81 </text>
85 </view> 82 </view>
@@ -89,15 +86,24 @@ @@ -89,15 +86,24 @@
89 </view> 86 </view>
90 </mescroll-body> 87 </mescroll-body>
91 <!-- 设备筛选 --> 88 <!-- 设备筛选 -->
92 - <u-popup @close="close" closeable bgColor="#fff" :show="show" mode="bottom" :round="20" @touchmove.stop.prevent="disabledScroll"> 89 + <u-popup @close="close" closeable bgColor="#fff" :show="show" mode="bottom" :round="20"
  90 + @touchmove.stop.prevent="disabledScroll">
93 <view class="filter" @touchmove.stop.prevent="disabledScroll"> 91 <view class="filter" @touchmove.stop.prevent="disabledScroll">
94 <view class="filter-title"><text>筛选条件</text></view> 92 <view class="filter-title"><text>筛选条件</text></view>
95 - <FilterItem :filterList="deviceStatus" title="设备状态" @clickTag="currentIndex => handleClickTag(currentIndex, deviceStatus)"></FilterItem>  
96 - <FilterItem :filterList="alarmStatus" title="告警状态" @clickTag="currentIndex => handleClickTag(currentIndex, alarmStatus)"></FilterItem>  
97 - <FilterItem :filterList="typeStatus" title="设备类型" @clickTag="currentIndex => handleClickTag(currentIndex, typeStatus)"></FilterItem> 93 + <FilterItem :filterList="deviceStatus" title="设备状态"
  94 + @clickTag="currentIndex => handleClickTag(currentIndex, deviceStatus)"></FilterItem>
  95 + <FilterItem :filterList="alarmStatus" title="告警状态"
  96 + @clickTag="currentIndex => handleClickTag(currentIndex, alarmStatus)"></FilterItem>
  97 + <FilterItem :filterList="typeStatus" title="设备类型"
  98 + @clickTag="currentIndex => handleClickTag(currentIndex, typeStatus)"></FilterItem>
98 <view class="button-group"> 99 <view class="button-group">
99 - <view><u-button :customStyle="{ color: '#333' }" color="#e3e3e5" shape="circle" text="重置" @click="resetFilter"></u-button></view>  
100 - <view><u-button color="#3388ff" shape="circle" text="确认" @click="confirmFilter"></u-button></view> 100 + <view>
  101 + <u-button :customStyle="{ color: '#333' }" color="#e3e3e5" shape="circle" text="重置"
  102 + @click="resetFilter"></u-button>
  103 + </view>
  104 + <view>
  105 + <u-button color="#3388ff" shape="circle" text="确认" @click="confirmFilter"></u-button>
  106 + </view>
101 </view> 107 </view>
102 </view> 108 </view>
103 </u-popup> 109 </u-popup>
@@ -106,295 +112,317 @@ @@ -106,295 +112,317 @@
106 </template> 112 </template>
107 113
108 <script> 114 <script>
109 -import fTabbar from '@/components/module/f-tabbar/f-tabbar';  
110 -import FilterItem from './FilterItem.vue';  
111 -import MescrollMixin from '@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js';  
112 -import { debounce } from '@/plugins/throttle.js';  
113 -export default {  
114 - mixins: [MescrollMixin], // 使用mixin (在main.js注册全局组件)  
115 - components: {  
116 - fTabbar,  
117 - FilterItem  
118 - },  
119 - data() {  
120 - return {  
121 - downOption: {  
122 - auto: false //是否在初始化后,自动执行downCallback; 默认true  
123 - },  
124 - upOption: {  
125 - isBounce: false,  
126 - auto: false // 不自动加载  
127 - },  
128 - show: false,  
129 - deviceStatus: [  
130 - {  
131 - checked: true,  
132 - name: '全部',  
133 - type: ''  
134 - },  
135 - {  
136 - checked: false,  
137 - name: '在线',  
138 - type: 'ONLINE'  
139 - },  
140 - {  
141 - checked: false,  
142 - name: '离线',  
143 - type: 'OFFLINE'  
144 - },  
145 - {  
146 - checked: false,  
147 - name: '待激活',  
148 - type: 'INACTIVE'  
149 - }  
150 - ],  
151 - alarmStatus: [  
152 - {  
153 - checked: true,  
154 - name: '全部',  
155 - type: ''  
156 - },  
157 - {  
158 - checked: false,  
159 - name: '告警',  
160 - type: '1' 115 + import fTabbar from '@/components/module/f-tabbar/f-tabbar';
  116 + import FilterItem from './FilterItem.vue';
  117 + import MescrollMixin from '@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js';
  118 + import {
  119 + debounce
  120 + } from '@/plugins/throttle.js';
  121 + export default {
  122 + mixins: [MescrollMixin], // 使用mixin (在main.js注册全局组件)
  123 + components: {
  124 + fTabbar,
  125 + FilterItem
  126 + },
  127 + data() {
  128 + return {
  129 + downOption: {
  130 + auto: false //是否在初始化后,自动执行downCallback; 默认true
161 }, 131 },
162 - {  
163 - checked: false,  
164 - name: '正常',  
165 - type: '0'  
166 - }  
167 - ],  
168 - typeStatus: [  
169 - {  
170 - checked: true,  
171 - name: '全部',  
172 - type: '' 132 + upOption: {
  133 + isBounce: false,
  134 + auto: false // 不自动加载
173 }, 135 },
  136 + show: false,
  137 + deviceStatus: [{
  138 + checked: true,
  139 + name: '全部',
  140 + type: ''
  141 + },
  142 + {
  143 + checked: false,
  144 + name: '在线',
  145 + type: 'ONLINE'
  146 + },
  147 + {
  148 + checked: false,
  149 + name: '离线',
  150 + type: 'OFFLINE'
  151 + },
  152 + {
  153 + checked: false,
  154 + name: '待激活',
  155 + type: 'INACTIVE'
  156 + }
  157 + ],
  158 + alarmStatus: [{
  159 + checked: true,
  160 + name: '全部',
  161 + type: ''
  162 + },
  163 + {
  164 + checked: false,
  165 + name: '告警',
  166 + type: '1'
  167 + },
  168 + {
  169 + checked: false,
  170 + name: '正常',
  171 + type: '0'
  172 + }
  173 + ],
  174 + typeStatus: [{
  175 + checked: true,
  176 + name: '全部',
  177 + type: ''
  178 + },
174 179
175 - {  
176 - checked: false,  
177 - name: '直连设备',  
178 - type: 'DIRECT_CONNECTION'  
179 - },  
180 - {  
181 - checked: false,  
182 - name: '网关设备',  
183 - type: 'GATEWAY' 180 + {
  181 + checked: false,
  182 + name: '直连设备',
  183 + type: 'DIRECT_CONNECTION'
  184 + },
  185 + {
  186 + checked: false,
  187 + name: '网关设备',
  188 + type: 'GATEWAY'
  189 + },
  190 + {
  191 + checked: false,
  192 + name: '网关子设备',
  193 + type: 'SENSOR'
  194 + }
  195 + ],
  196 + total: 0,
  197 + list: [],
  198 + page: {
  199 + num: 0,
  200 + size: 10
184 }, 201 },
185 - {  
186 - checked: false,  
187 - name: '网关子设备',  
188 - type: 'SENSOR'  
189 - }  
190 - ],  
191 - total: 0,  
192 - list: [],  
193 - page: {  
194 - num: 0,  
195 - size: 10  
196 - },  
197 - deviceState: '',  
198 - deviceName: ''  
199 - };  
200 - },  
201 - async onLoad(options) {  
202 - // 隐藏原生的tabbar  
203 - uni.hideTabBar();  
204 - this.page.num = 1;  
205 - const { deviceState } = options;  
206 - this.deviceState = deviceState;  
207 - if (deviceState) {  
208 - this.deviceStatus.forEach(item => {  
209 - item.type === deviceState ? (item.checked = true) : (item.checked = false);  
210 - });  
211 - await this.loadData(1, {  
212 - deviceState  
213 - });  
214 - } else {  
215 - await this.loadData(1);  
216 - }  
217 - if (!this.list.length) {  
218 - this.mescroll.showEmpty();  
219 - }  
220 - },  
221 - onShow() {  
222 - if (this.orgId) {  
223 - this.loadData(1, {  
224 - organizationId: this.orgId  
225 - });  
226 - }  
227 - },  
228 - methods: {  
229 - disabledScroll() {  
230 - return; 202 + deviceState: '',
  203 + deviceName: ''
  204 + };
231 }, 205 },
232 - /*下拉刷新的回调 */  
233 - downCallback() {  
234 - this.deviceName = '';  
235 - this.orgId = '';  
236 - //联网加载数据  
237 - this.list = []; 206 + async onLoad(options) {
  207 + // 隐藏原生的tabbar
  208 + uni.hideTabBar();
238 this.page.num = 1; 209 this.page.num = 1;
239 - //联网加载数据  
240 - this.resetFilter();  
241 - this.loadData(this.page.num); 210 + const {
  211 + deviceState
  212 + } = options;
  213 + this.deviceState = deviceState;
  214 + if (deviceState) {
  215 + this.deviceStatus.forEach(item => {
  216 + item.type === deviceState ? (item.checked = true) : (item.checked = false);
  217 + });
  218 + await this.loadData(1, {
  219 + deviceState
  220 + });
  221 + } else {
  222 + await this.loadData(1);
  223 + }
  224 + if (!this.list.length) {
  225 + this.mescroll.showEmpty();
  226 + }
242 }, 227 },
243 -  
244 - /*上拉加载的回调: 其中page.num:当前页 从1开始, page.size:每页数据条数,默认10 */  
245 - upCallback() {  
246 - //联网加载数据  
247 - this.page.num += 1;  
248 - const deviceState = this.deviceStatus.find(item => item.checked);  
249 - const alarmStatus = this.alarmStatus.find(item => item.checked);  
250 - const deviceType = this.typeStatus.find(item => item.checked);  
251 - this.loadData(this.page.num, {  
252 - deviceState: deviceState.type ? deviceState.type : undefined,  
253 - deviceType: deviceType.type ? deviceType.type : undefined,  
254 - alarmStatus: alarmStatus.type === '0' || alarmStatus.type === '1' ? alarmStatus.type : undefined,  
255 - name: this.deviceName == null ? null : this.deviceName,  
256 - organizationId: this.orgId == null ? null : this.orgId  
257 - }); 228 + onShow() {
  229 + if (this.orgId) {
  230 + this.loadData(1, {
  231 + organizationId: this.orgId
  232 + });
  233 + }
258 }, 234 },
  235 + methods: {
  236 + disabledScroll() {
  237 + return;
  238 + },
  239 + /*下拉刷新的回调 */
  240 + downCallback() {
  241 + this.deviceName = '';
  242 + this.orgId = '';
  243 + //联网加载数据
  244 + this.list = [];
  245 + this.page.num = 1;
  246 + //联网加载数据
  247 + this.resetFilter();
  248 + this.loadData(this.page.num);
  249 + },
259 250
260 - //获取设备  
261 - async loadData(pageNo, params = {}) {  
262 - try {  
263 - let httpData = {  
264 - page: pageNo,  
265 - pageSize: 10,  
266 - ...params  
267 - };  
268 - const { total, items } = await uni.$u.http.get('/yt/device', {  
269 - params: httpData,  
270 - custom: {  
271 - load: false  
272 - } 251 + /*上拉加载的回调: 其中page.num:当前页 从1开始, page.size:每页数据条数,默认10 */
  252 + upCallback() {
  253 + //联网加载数据
  254 + this.page.num += 1;
  255 + const deviceState = this.deviceStatus.find(item => item.checked);
  256 + const alarmStatus = this.alarmStatus.find(item => item.checked);
  257 + const deviceType = this.typeStatus.find(item => item.checked);
  258 + this.loadData(this.page.num, {
  259 + deviceState: deviceState.type ? deviceState.type : undefined,
  260 + deviceType: deviceType.type ? deviceType.type : undefined,
  261 + alarmStatus: alarmStatus.type === '0' || alarmStatus.type === '1' ? alarmStatus.type :
  262 + undefined,
  263 + name: this.deviceName == null ? null : this.deviceName,
  264 + organizationId: this.orgId == null ? null : this.orgId
273 }); 265 });
274 - this.total = total;  
275 - uni.stopPullDownRefresh();  
276 - this.mescroll.endByPage(items.length, total); //必传参数(当前页的数据个数, 总页数)  
277 - if (pageNo == 1) {  
278 - this.list = items;  
279 - } else {  
280 - this.list = this.list.concat(items); 266 + },
  267 +
  268 + //获取设备
  269 + async loadData(pageNo, params = {}) {
  270 + try {
  271 + let httpData = {
  272 + page: pageNo,
  273 + pageSize: 10,
  274 + ...params
  275 + };
  276 + const {
  277 + total,
  278 + items
  279 + } = await uni.$u.http.get('/yt/device', {
  280 + params: httpData,
  281 + custom: {
  282 + load: false
  283 + }
  284 + });
  285 + this.total = total;
  286 + uni.stopPullDownRefresh();
  287 + this.mescroll.endByPage(items.length, total); //必传参数(当前页的数据个数, 总页数)
  288 + if (pageNo == 1) {
  289 + this.list = items;
  290 + } else {
  291 + this.list = this.list.concat(items);
  292 + }
  293 + } catch {
  294 + this.mescroll.endErr();
281 } 295 }
282 - } catch {  
283 - this.mescroll.endErr(); 296 + },
  297 + openOrg() {
  298 + uni.navigateTo({
  299 + url: './org/org'
  300 + });
  301 + },
  302 + close() {
  303 + this.show = false;
  304 + },
  305 + openSearchDialog() {
  306 + this.show = true;
  307 + },
  308 + openDeviceDetail(id, alarmStatus, lastOnlineTime, tbDeviceId) {
  309 + uni.navigateTo({
  310 + url: `/deviceSubPage/deviceDetailPage/deviceDetail?id=${id}&alarmStatus=${alarmStatus}&lastOnlineTime=${lastOnlineTime}&tbDeviceId=${tbDeviceId}`
  311 + });
  312 + },
  313 + handleClickTag(currentIndex, list) {
  314 + list.map((item, index) => {
  315 + item.checked = index === currentIndex;
  316 + });
  317 + },
  318 + resetFilter() {
  319 + const {
  320 + deviceStatus,
  321 + alarmStatus,
  322 + typeStatus
  323 + } = this;
  324 + [deviceStatus, alarmStatus, typeStatus].forEach(item => item.map((item, index) => (item.checked = index ===
  325 + 0)));
  326 + },
  327 + confirmFilter() {
  328 + const deviceState = this.deviceStatus.find(item => item.checked);
  329 + const alarmStatus = this.alarmStatus.find(item => item.checked);
  330 + const deviceType = this.typeStatus.find(item => item.checked);
  331 + this.loadData(1, {
  332 + deviceState: deviceState.type ? deviceState.type : undefined,
  333 + deviceType: deviceType.type ? deviceType.type : undefined,
  334 + alarmStatus: alarmStatus.type === '0' || alarmStatus.type === '1' ? alarmStatus.type :
  335 + undefined
  336 + });
  337 + this.show = false;
  338 + },
  339 + inputChanged(e) {
  340 + this.page.num = 1;
  341 + this.deviceName = e;
  342 + this.loadData(1, {
  343 + name: this.deviceName
  344 + });
284 } 345 }
285 - },  
286 - openOrg() {  
287 - uni.navigateTo({  
288 - url: './org/org'  
289 - });  
290 - },  
291 - close() {  
292 - this.show = false;  
293 - },  
294 - openSearchDialog() {  
295 - this.show = true;  
296 - },  
297 - openDeviceDetail(id, alarmStatus, lastOnlineTime, tbDeviceId) {  
298 - uni.navigateTo({  
299 - url: `/deviceSubPage/deviceDetailPage/deviceDetail?id=${id}&alarmStatus=${alarmStatus}&lastOnlineTime=${lastOnlineTime}&tbDeviceId=${tbDeviceId}`  
300 - });  
301 - },  
302 - handleClickTag(currentIndex, list) {  
303 - list.map((item, index) => {  
304 - item.checked = index === currentIndex;  
305 - });  
306 - },  
307 - resetFilter() {  
308 - const { deviceStatus, alarmStatus, typeStatus } = this;  
309 - [deviceStatus, alarmStatus, typeStatus].forEach(item => item.map((item, index) => (item.checked = index === 0)));  
310 - },  
311 - confirmFilter() {  
312 - const deviceState = this.deviceStatus.find(item => item.checked);  
313 - const alarmStatus = this.alarmStatus.find(item => item.checked);  
314 - const deviceType = this.typeStatus.find(item => item.checked);  
315 - this.loadData(1, {  
316 - deviceState: deviceState.type ? deviceState.type : undefined,  
317 - deviceType: deviceType.type ? deviceType.type : undefined,  
318 - alarmStatus: alarmStatus.type === '0' || alarmStatus.type === '1' ? alarmStatus.type : undefined  
319 - });  
320 - this.show = false;  
321 - },  
322 - inputChanged(e) {  
323 - this.page.num = 1;  
324 - this.deviceName = e;  
325 - this.loadData(1, {  
326 - name: this.deviceName  
327 - });  
328 } 346 }
329 - }  
330 -}; 347 + };
331 </script> 348 </script>
332 349
333 <style lang="scss" scoped> 350 <style lang="scss" scoped>
334 -.device-page {  
335 - min-height: 100vh;  
336 - background-color: #f8f9fa;  
337 -}  
338 -.device-top {  
339 - padding: 10rpx 30rpx;  
340 - background-color: #fff;  
341 - .search {  
342 - display: flex;  
343 - justify-content: space-between;  
344 - padding-bottom: 10rpx;  
345 - .search-left {  
346 - width: 580rpx;  
347 - background-color: #f8f9fa;  
348 - border-radius: 200rpx;  
349 - }  
350 - .search-right { 351 + .device-page {
  352 + min-height: 100vh;
  353 + background-color: #f8f9fa;
  354 + }
  355 +
  356 + .device-top {
  357 + padding: 10rpx 30rpx;
  358 + background-color: #fff;
  359 +
  360 + .search {
351 display: flex; 361 display: flex;
352 - align-items: center;  
353 - text {  
354 - color: #333;  
355 - font-size: 14px; 362 + justify-content: space-between;
  363 + padding-bottom: 10rpx;
  364 +
  365 + .search-left {
  366 + width: 580rpx;
  367 + background-color: #f8f9fa;
  368 + border-radius: 200rpx;
356 } 369 }
357 - image {  
358 - width: 40rpx;  
359 - height: 40rpx; 370 +
  371 + .search-right {
  372 + display: flex;
  373 + align-items: center;
  374 +
  375 + text {
  376 + color: #333;
  377 + font-size: 14px;
  378 + }
  379 +
  380 + image {
  381 + width: 40rpx;
  382 + height: 40rpx;
  383 + }
360 } 384 }
361 } 385 }
362 } 386 }
363 -}  
364 387
365 -.device-list {  
366 - display: flex;  
367 - flex-direction: column;  
368 - padding-left: 20rpx;  
369 - .list-item {  
370 - width: 713rpx;  
371 - height: 200rpx;  
372 - background-color: #fff;  
373 - margin-top: 24rpx; 388 + .device-list {
374 display: flex; 389 display: flex;
375 - border-radius: 10px;  
376 - justify-content: space-between;  
377 - .item {  
378 - margin: 30rpx; 390 + flex-direction: column;
  391 + padding-left: 20rpx;
  392 +
  393 + .list-item {
  394 + width: 713rpx;
  395 + height: 200rpx;
  396 + background-color: #fff;
  397 + margin-top: 24rpx;
  398 + display: flex;
  399 + border-radius: 10px;
  400 + justify-content: space-between;
  401 +
  402 + .item {
  403 + margin: 30rpx;
  404 + }
379 } 405 }
380 } 406 }
381 -}  
382 407
383 -.filter {  
384 - padding: 0 30rpx;  
385 - .filter-title {  
386 - text-align: center;  
387 - margin-top: 14px;  
388 - font-size: 16px;  
389 - font-weight: 700;  
390 - }  
391 - .button-group {  
392 - display: flex;  
393 - margin-top: 40rpx;  
394 - justify-content: space-between;  
395 - view {  
396 - width: 330rpx; 408 + .filter {
  409 + padding: 0 30rpx;
  410 +
  411 + .filter-title {
  412 + text-align: center;
  413 + margin-top: 14px;
  414 + font-size: 16px;
  415 + font-weight: 700;
  416 + }
  417 +
  418 + .button-group {
  419 + display: flex;
  420 + margin-top: 40rpx;
  421 + justify-content: space-between;
  422 +
  423 + view {
  424 + width: 330rpx;
  425 + }
397 } 426 }
398 } 427 }
399 -}  
400 </style> 428 </style>
@@ -48,6 +48,9 @@ button { @@ -48,6 +48,9 @@ button {
48 } 48 }
49 ///////////////////////////////////////////////////////////////小程序、app抽取公共样式///////////////////////////////////////////////////////////////////// 49 ///////////////////////////////////////////////////////////////小程序、app抽取公共样式/////////////////////////////////////////////////////////////////////
50 //通用(设备、告警、摄像头分页头部组织和设备数和设备、告警里面的详情(左边的文本) 50 //通用(设备、告警、摄像头分页头部组织和设备数和设备、告警里面的详情(左边的文本)
  51 +.ml-10{
  52 + margin-left: 10rpx;
  53 +}
51 .text-org-bold { 54 .text-org-bold {
52 width:200rpx; 55 width:200rpx;
53 color: #333333; 56 color: #333333;