Showing
3 changed files
with
597 additions
and
323 deletions
| 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="{ | ||
| 11 | - fontWeight: 'bold', | ||
| 12 | - color: '#333' | ||
| 13 | - }" | ||
| 14 | - :inactiveStyle="{ | ||
| 15 | - 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> | 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="{ | ||
| 11 | + fontWeight: 'bold', | ||
| 12 | + color: '#333', | ||
| 13 | + }" | ||
| 14 | + :inactiveStyle="{ | ||
| 15 | + 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> | ||
| 39 | </template> | 39 | </template> |
| 40 | 40 | ||
| 41 | <script> | 41 | <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'; | 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"; | 50 | import MescrollCompMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mixins/mescroll-comp.js"; |
| 51 | -import moment from 'moment'; | ||
| 52 | -export default { | ||
| 53 | - mixins: [MescrollCompMixin], | ||
| 54 | - components: { | ||
| 55 | - fTabbar, | ||
| 56 | - basicInfo, | ||
| 57 | - realTimeData, | ||
| 58 | - alarmHistory, | ||
| 59 | - historyData, | ||
| 60 | - commondRecord | ||
| 61 | - }, | ||
| 62 | - data() { | ||
| 63 | - return { | ||
| 64 | - list: [{ name: '基础信息' }, { name: '实时数据' }, { name: '历史数据' }, { name: '告警记录' }], | ||
| 65 | - currentTab: 0, | ||
| 66 | - deviceId: '', | ||
| 67 | - deviceDetail: {}, | ||
| 68 | - keys: [], | ||
| 69 | - yesterday: '', | ||
| 70 | - today: '', | ||
| 71 | - timeDiff: '', | ||
| 72 | - historyData: [], | ||
| 73 | - entityId: '', | ||
| 74 | - startTs: '', | ||
| 75 | - endTs: '', | ||
| 76 | - recordList: [], | ||
| 77 | - isScrollable: false | ||
| 78 | - }; | ||
| 79 | - }, | ||
| 80 | - onUnload() { | ||
| 81 | - // 页面关闭时,销毁webSocket连接,否则第二次会存在连接不到的情况 | ||
| 82 | - uni.closeSocket(); | ||
| 83 | - }, | ||
| 84 | - async onLoad(options) { | ||
| 85 | - const { id, alarmStatus, lastOnlineTime, tbDeviceId } = options; | ||
| 86 | - this.deviceId = id; | ||
| 87 | - const res = await uni.$u.http.get(`/yt/device/${id}`); | ||
| 88 | - this.deviceDetail = { ...res, alarmStatus, lastOnlineTime }; | 51 | +import moment from "moment"; |
| 52 | +import base from "@/config/baseUrl.js"; | ||
| 89 | 53 | ||
| 90 | - // 设备类型不是网关子设备的添加一个命令记录的选项卡 | ||
| 91 | - if (this.deviceDetail.deviceType !== 'SENSOR') { | ||
| 92 | - this.list.push({ | ||
| 93 | - name: '命令记录' | ||
| 94 | - }); | ||
| 95 | - } | ||
| 96 | - this.isScrollable = this.list.length > 4; | ||
| 97 | - // 连接webSockte | ||
| 98 | - const socketTask = uni.connectSocket({ | ||
| 99 | - url: 'wss://dev.thingskit.com/api/ws/plugins/telemetry?token=' + uni.getStorageSync('userInfo').isToken, //仅为示例,并非真实接口地址。 | ||
| 100 | - complete: () => {} | ||
| 101 | - }); | ||
| 102 | - uni.onSocketOpen(header => { | ||
| 103 | - socketTask.send({ | ||
| 104 | - data: JSON.stringify({ | ||
| 105 | - attrSubCmds: [], | ||
| 106 | - tsSubCmds: [ | ||
| 107 | - { | ||
| 108 | - entityType: 'DEVICE', | ||
| 109 | - entityId: tbDeviceId, | ||
| 110 | - scope: 'LATEST_TELEMETRY', | ||
| 111 | - cmdId: 1 | ||
| 112 | - } | ||
| 113 | - ], | ||
| 114 | - historyCmds: [], | ||
| 115 | - entityDataCmds: [], | ||
| 116 | - entityDataUnsubscribeCmds: [], | ||
| 117 | - alarmDataCmds: [], | ||
| 118 | - alarmDataUnsubscribeCmds: [], | ||
| 119 | - entityCountCmds: [], | ||
| 120 | - entityCountUnsubscribeCmds: [] | ||
| 121 | - }), | ||
| 122 | - success() {} | ||
| 123 | - }); | ||
| 124 | - }); | ||
| 125 | - socketTask.onMessage(msg => { | ||
| 126 | - const { data } = JSON.parse(msg.data); | ||
| 127 | - const newArray = []; | ||
| 128 | - for (const key in data) { | ||
| 129 | - const [time, value] = data[key].flat(1); | ||
| 130 | - let obj = { key, time, value }; | ||
| 131 | - if (this.recordList.length === 0) { | ||
| 132 | - this.recordList.unshift(obj); | ||
| 133 | - } else { | ||
| 134 | - newArray.push(obj); | ||
| 135 | - } | ||
| 136 | - } | ||
| 137 | - newArray.forEach(item => { | ||
| 138 | - let flag = false; | ||
| 139 | - this.recordList.forEach(item1 => { | ||
| 140 | - if (item1.key === item.key) { | ||
| 141 | - item1.value = item.value; | ||
| 142 | - item1.time = item.time; | ||
| 143 | - flag = true; | ||
| 144 | - } | ||
| 145 | - }); | ||
| 146 | - if (!flag) { | ||
| 147 | - this.recordList.unshift(item); | ||
| 148 | - } | ||
| 149 | - }); | ||
| 150 | - this.recordList = this.recordList.map(item => { | ||
| 151 | - return { | ||
| 152 | - ...item, | ||
| 153 | - time: formatToDate(item.time, 'YYYY-MM-DD HH:mm:ss') | ||
| 154 | - }; | ||
| 155 | - }); | ||
| 156 | - }); | 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 | + }; | ||
| 157 | 108 | ||
| 158 | - const keys = await getDeviceKeys(tbDeviceId); | ||
| 159 | - this.keys = [keys]; | ||
| 160 | - // 昨天 | ||
| 161 | - this.yesterday = moment() | ||
| 162 | - .subtract(1, 'days') | ||
| 163 | - .format('YYYY-MM-DD'); | ||
| 164 | - // 今天 | ||
| 165 | - this.today = moment().format('YYYY-MM-DD'); | ||
| 166 | - // 开始时间 | ||
| 167 | - this.startTs = moment() | ||
| 168 | - .subtract(1, 'days') | ||
| 169 | - .format('x'); | ||
| 170 | - // 结束时间 | ||
| 171 | - this.endTs = moment().format('x'); | ||
| 172 | - this.entityId = tbDeviceId; | 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 | + }); | ||
| 173 | 182 | ||
| 174 | - const data = await getHistoryData({ | ||
| 175 | - entityId: tbDeviceId, | ||
| 176 | - startTs: this.startTs, | ||
| 177 | - endTs: this.endTs, | ||
| 178 | - keys: keys[0], | ||
| 179 | - interval: 1800000 | ||
| 180 | - }); | ||
| 181 | - this.timeDiff = '30分钟'; | ||
| 182 | - if (!Object.keys(data).length) return; | 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; | ||
| 183 | 194 | ||
| 184 | - this.historyData = data[keys[0]] | ||
| 185 | - .map(item => { | ||
| 186 | - return { | ||
| 187 | - value: item.value, | ||
| 188 | - ts: formatToDate(item.ts, 'YYYY-MM-DD HH:mm:ss') | ||
| 189 | - }; | ||
| 190 | - }) | 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; | ||
| 191 | 204 | ||
| 192 | - }, | ||
| 193 | - methods: { | ||
| 194 | - handleTabClick({ index }) { | ||
| 195 | - this.currentTab = index; | ||
| 196 | - }, | ||
| 197 | - handleUpdate(data) { | ||
| 198 | - if (!Array.isArray(data)) { | ||
| 199 | - this.historyData = []; | ||
| 200 | - return; | ||
| 201 | - } | ||
| 202 | - this.historyData = data | ||
| 203 | - .map(item => { | ||
| 204 | - return { | ||
| 205 | - value: item.value, | ||
| 206 | - ts: formatToDate(item.ts, 'YYYY-MM-DD HH:mm:ss') | ||
| 207 | - }; | ||
| 208 | - }) | ||
| 209 | - } | ||
| 210 | - } | 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 | + }, | ||
| 211 | }; | 229 | }; |
| 212 | </script> | 230 | </script> |
| 213 | 231 | ||
| 214 | <style lang="scss" scoped> | 232 | <style lang="scss" scoped> |
| 215 | .device-detail-page { | 233 | .device-detail-page { |
| 216 | - height: 100vh; | ||
| 217 | - background-color: #f8f9fa; | 234 | + height: 100vh; |
| 235 | + background-color: #f8f9fa; | ||
| 218 | } | 236 | } |
| 219 | -</style> | 237 | +</style> |
| 1 | +.cu-modal { | ||
| 2 | + position: fixed; | ||
| 3 | + top: 0; | ||
| 4 | + right: 0; | ||
| 5 | + bottom: 0; | ||
| 6 | + left: 0; | ||
| 7 | + z-index: 1110; | ||
| 8 | + opacity: 0; | ||
| 9 | + outline: 0; | ||
| 10 | + text-align: center; | ||
| 11 | + -ms-transform: scale(1.185); | ||
| 12 | + transform: scale(1.185); | ||
| 13 | + backface-visibility: hidden; | ||
| 14 | + perspective: 2000upx; | ||
| 15 | + background: rgba(0, 0, 0, 0.6); | ||
| 16 | + transition: all 0.3s ease-in-out 0s; | ||
| 17 | + pointer-events: none; | ||
| 18 | +} | ||
| 19 | + | ||
| 20 | +.cu-modal::before { | ||
| 21 | + content: "\200B"; | ||
| 22 | + display: inline-block; | ||
| 23 | + height: 100%; | ||
| 24 | + vertical-align: middle; | ||
| 25 | +} | ||
| 26 | + | ||
| 27 | +.cu-modal.show { | ||
| 28 | + opacity: 1; | ||
| 29 | + transition-duration: 0.3s; | ||
| 30 | + -ms-transform: scale(1); | ||
| 31 | + transform: scale(1); | ||
| 32 | + overflow-x: hidden; | ||
| 33 | + overflow-y: auto; | ||
| 34 | + pointer-events: auto; | ||
| 35 | +} | ||
| 36 | + | ||
| 37 | +.cu-dialog { | ||
| 38 | + position: relative; | ||
| 39 | + display: inline-block; | ||
| 40 | + vertical-align: middle; | ||
| 41 | + margin-left: auto; | ||
| 42 | + margin-right: auto; | ||
| 43 | + width: 680upx; | ||
| 44 | + max-width: 100%; | ||
| 45 | + background-color: #f8f8f8; | ||
| 46 | + border-radius: 10upx; | ||
| 47 | + overflow: hidden; | ||
| 48 | +} | ||
| 49 | + | ||
| 50 | +.cu-modal.bottom-modal::before { | ||
| 51 | + vertical-align: bottom; | ||
| 52 | +} | ||
| 53 | + | ||
| 54 | +.cu-modal.bottom-modal .cu-dialog { | ||
| 55 | + width: 100%; | ||
| 56 | + border-radius: 0; | ||
| 57 | +} | ||
| 58 | + | ||
| 59 | +.cu-modal.bottom-modal { | ||
| 60 | + margin-bottom: -1000upx; | ||
| 61 | +} | ||
| 62 | + | ||
| 63 | +.cu-modal.bottom-modal.show { | ||
| 64 | + margin-bottom: 0; | ||
| 65 | +} | ||
| 66 | + | ||
| 67 | +.cu-modal.drawer-modal { | ||
| 68 | + transform: scale(1); | ||
| 69 | + display: flex; | ||
| 70 | +} | ||
| 71 | + | ||
| 72 | +.cu-modal.drawer-modal .cu-dialog { | ||
| 73 | + height: 100%; | ||
| 74 | + min-width: 200upx; | ||
| 75 | + border-radius: 0; | ||
| 76 | + margin: initial; | ||
| 77 | + transition-duration: 0.3s; | ||
| 78 | +} | ||
| 79 | + | ||
| 80 | +.cu-modal.drawer-modal.justify-start .cu-dialog { | ||
| 81 | + transform: translateX(-100%); | ||
| 82 | +} | ||
| 83 | + | ||
| 84 | +.cu-modal.drawer-modal.justify-end .cu-dialog { | ||
| 85 | + transform: translateX(100%); | ||
| 86 | +} | ||
| 87 | + | ||
| 88 | +.cu-modal.drawer-modal.show .cu-dialog { | ||
| 89 | + transform: translateX(0%); | ||
| 90 | +} | ||
| 91 | + | ||
| 92 | +.cu-modal .cu-dialog>.cu-bar:first-child .action { | ||
| 93 | + min-width: 100rpx; | ||
| 94 | + margin-right: 0; | ||
| 95 | + min-height: 100rpx; | ||
| 96 | +} |
| @@ -4,17 +4,26 @@ | @@ -4,17 +4,26 @@ | ||
| 4 | <public-module /> | 4 | <public-module /> |
| 5 | <view class="basic-title"> | 5 | <view class="basic-title"> |
| 6 | <view class="u-flex"> | 6 | <view class="u-flex"> |
| 7 | - <view style="padding-left: 32rpx;"><u-icon v-if="deviceDetail.deviceInfo.longitude !== ''" @click="handleClick" name="map-fill"></u-icon></view> | 7 | + <view style="padding-left: 32rpx;"> |
| 8 | + <u-icon v-if="deviceDetail.deviceInfo.longitude !== ''" @click="handleClick" name="map-fill"> | ||
| 9 | + </u-icon> | ||
| 10 | + </view> | ||
| 8 | <view style="margin-left: 20rpx;">{{ deviceDetail.name }}</view> | 11 | <view style="margin-left: 20rpx;">{{ deviceDetail.name }}</view> |
| 9 | - <view | ||
| 10 | - style="margin-left: 20rpx; font-size: 14px;" | ||
| 11 | - :style="{ color: deviceDetail.deviceState === 'INACTIVE' ? '#666' : deviceDetail.deviceState === 'ONLINE' ? '#377DFF' : '#DE4437' }" | ||
| 12 | - > | 12 | + <view style="margin-left: 20rpx; font-size: 14px;" |
| 13 | + :style="{ color: deviceDetail.deviceState === 'INACTIVE' ? '#666' : deviceDetail.deviceState === 'ONLINE' ? '#377DFF' : '#DE4437' }"> | ||
| 13 | {{ deviceDetail.deviceState === 'INACTIVE' ? '待激活' : deviceDetail.deviceState === 'ONLINE' ? '在线' : '离线' }} | 14 | {{ deviceDetail.deviceState === 'INACTIVE' ? '待激活' : deviceDetail.deviceState === 'ONLINE' ? '在线' : '离线' }} |
| 14 | </view> | 15 | </view> |
| 15 | </view> | 16 | </view> |
| 16 | - <view style="margin-right: 20rpx;" v-if="deviceDetail.deviceState === 'ONLINE' && deviceDetail.deviceType !== 'SENSOR'"> | ||
| 17 | - <u-button type="primary" shape="circle" size="mini" text="下发命令" @click="showModal" /> | 17 | + <view style="margin-right: 20rpx;" |
| 18 | + v-if="deviceDetail.deviceState === 'ONLINE' && deviceDetail.deviceType !== 'SENSOR'"> | ||
| 19 | + <!-- #ifdef MP --> | ||
| 20 | + <u-button type="primary" shape="circle" size="mini" text="下发命令" @click="showModalBtn" /> | ||
| 21 | + <!-- #endif --> | ||
| 22 | + <!-- #ifdef APP-PLUS --> | ||
| 23 | + <view class="cu-item" @tap="showModal" data-target="Modal"> | ||
| 24 | + <text>下发命令</text> | ||
| 25 | + </view> | ||
| 26 | + <!-- #endif --> | ||
| 18 | </view> | 27 | </view> |
| 19 | </view> | 28 | </view> |
| 20 | <view class="detail"> | 29 | <view class="detail"> |
| @@ -48,9 +57,60 @@ | @@ -48,9 +57,60 @@ | ||
| 48 | <view class="detail-value">{{ deviceDetail.description }}</view> | 57 | <view class="detail-value">{{ deviceDetail.description }}</view> |
| 49 | </view> | 58 | </view> |
| 50 | </view> | 59 | </view> |
| 51 | - | ||
| 52 | <!-- 下发命令 --> | 60 | <!-- 下发命令 --> |
| 53 | - <u-modal :show="showModel" closeOnClickOverlay :showConfirmButton="false" width="720rpx" @close="hiddenModal" @touchmove.stop.prevent="disabledScroll"> | 61 | + <!-- #ifdef APP-PLUS --> |
| 62 | + <view v-show="showNodal" class="cu-modal" :class="modalName=='Modal'?'show':''"> | ||
| 63 | + <view class="cu-dialog" style=""> | ||
| 64 | + <view class="modal_main"> | ||
| 65 | + <view class='nav-list margin-top'> | ||
| 66 | + <view style="width: 100%; padding: 0 30rpx;"> | ||
| 67 | + <view style="text-align: center; font-weight:700;margin-top: 40rpx;">命令下发</view> | ||
| 68 | + <view style="height: 20rpx;"></view> | ||
| 69 | + <view class="u-flex"> | ||
| 70 | + <text | ||
| 71 | + style="color: #333; font-size: 14px;font-weight:700;margin-right: 30rpx;">下发类型:</text> | ||
| 72 | + <view> | ||
| 73 | + <radio-group style="display: flex;" @change="radioChange"> | ||
| 74 | + <label class="uni-list-cell uni-list-cell-pd" v-for="(item, index) in items" | ||
| 75 | + :key="item.value"> | ||
| 76 | + <view style="display: flex"> | ||
| 77 | + <view style="margin-left: 10rpx;"> | ||
| 78 | + <radio :value="item.value" :checked="index === current" /> | ||
| 79 | + </view> | ||
| 80 | + <view style="width:10rpx"></view> | ||
| 81 | + <view style="margin-left: 10rpx;">{{item.name}}</view> | ||
| 82 | + </view> | ||
| 83 | + </label> | ||
| 84 | + </radio-group> | ||
| 85 | + </view> | ||
| 86 | + </view> | ||
| 87 | + <view style="margin-top: 15rpx"> | ||
| 88 | + <view class="cusAppplusContent"> | ||
| 89 | + <textarea v-model="inputCommandVal" placeholder="请输入下发内容(json格式)" /> | ||
| 90 | + </view> | ||
| 91 | + </view> | ||
| 92 | + <view class="button-group"> | ||
| 93 | + <view> | ||
| 94 | + <view class="cusAppplusCancelBtn" @click="cancelCommand"><text | ||
| 95 | + style="color: #333333">取消</text> | ||
| 96 | + </view> | ||
| 97 | + </view> | ||
| 98 | + <view> | ||
| 99 | + <view class="cusAppplusConfrimBtn" @click="confirmCommand"> | ||
| 100 | + <text style="color:white">确认</text> | ||
| 101 | + </view> | ||
| 102 | + </view> | ||
| 103 | + </view> | ||
| 104 | + <view style="height:30rpx"></view> | ||
| 105 | + </view> | ||
| 106 | + </view> | ||
| 107 | + </view> | ||
| 108 | + </view> | ||
| 109 | + </view> | ||
| 110 | + <!-- #endif --> | ||
| 111 | + <!-- #ifdef MP --> | ||
| 112 | + <u-modal :show="showModel" closeOnClickOverlay :showConfirmButton="false" width="720rpx" @close="hiddenModal" | ||
| 113 | + @touchmove.stop.prevent="disabledScroll"> | ||
| 54 | <view style="width: 100%; padding: 0 30rpx;"> | 114 | <view style="width: 100%; padding: 0 30rpx;"> |
| 55 | <view style="text-align: center; font-weight:700;margin-bottom: 40rpx;">命令下发</view> | 115 | <view style="text-align: center; font-weight:700;margin-bottom: 40rpx;">命令下发</view> |
| 56 | <view class="u-flex"> | 116 | <view class="u-flex"> |
| @@ -62,144 +122,244 @@ | @@ -62,144 +122,244 @@ | ||
| 62 | <u-radio activeColor="#3388FF" label="双向" name="TwoWay"></u-radio> | 122 | <u-radio activeColor="#3388FF" label="双向" name="TwoWay"></u-radio> |
| 63 | </u-radio-group> | 123 | </u-radio-group> |
| 64 | </view> | 124 | </view> |
| 65 | - <view style="margin-top: 28rpx;width: 100%;"><u--textarea placeholder="请输入下发内容(json格式)" v-model="inputCommandVal" /></view> | 125 | + <view style="margin-top: 28rpx;width: 100%;"> |
| 126 | + <u--textarea placeholder="请输入下发内容(json格式)" v-model="inputCommandVal" /> | ||
| 127 | + </view> | ||
| 66 | 128 | ||
| 67 | <view class="button-group"> | 129 | <view class="button-group"> |
| 68 | - <view><u-button :customStyle="{ color: '#333' }" color="#e3e3e5" shape="circle" text="取消" @click="cancelCommand"></u-button></view> | ||
| 69 | - <view><u-button color="#3388ff" shape="circle" text="确认" @click="confirmCommand"></u-button></view> | 130 | + <view> |
| 131 | + <u-button :customStyle="{ color: '#333' }" color="#e3e3e5" shape="circle" text="取消" | ||
| 132 | + @click="cancelCommand"></u-button> | ||
| 133 | + </view> | ||
| 134 | + <view> | ||
| 135 | + <u-button color="#3388ff" shape="circle" text="确认" @click="confirmCommand"></u-button> | ||
| 136 | + </view> | ||
| 70 | </view> | 137 | </view> |
| 71 | </view> | 138 | </view> |
| 72 | </u-modal> | 139 | </u-modal> |
| 140 | + <!-- #endif --> | ||
| 73 | </view> | 141 | </view> |
| 74 | </template> | 142 | </template> |
| 75 | 143 | ||
| 76 | <script> | 144 | <script> |
| 77 | -import { formatToDate } from '@/plugins/utils.js'; | ||
| 78 | -import { issueCommand } from '../api/index.js'; | ||
| 79 | -export default { | ||
| 80 | - props: { | ||
| 81 | - deviceDetail: { | ||
| 82 | - type: Object, | ||
| 83 | - default: () => ({}) | ||
| 84 | - } | ||
| 85 | - }, | ||
| 86 | - data() { | ||
| 87 | - return { | ||
| 88 | - showModel: false, | ||
| 89 | - commandType: 'OneWay', | ||
| 90 | - commandValue: {}, | ||
| 91 | - inputCommandVal: '' | ||
| 92 | - }; | ||
| 93 | - }, | ||
| 94 | - computed: { | ||
| 95 | - deviceType() { | ||
| 96 | - return this.deviceDetail.deviceType === 'DIRECT_CONNECTION' | ||
| 97 | - ? '直连设备' | ||
| 98 | - : this.deviceDetail.deviceType === 'GATEWAY' | ||
| 99 | - ? '网关设备' | ||
| 100 | - : this.deviceDetail.deviceType === 'SENSOR' | ||
| 101 | - ? '网关子设备' | ||
| 102 | - : ''; | ||
| 103 | - }, | ||
| 104 | - alarmStatus() { | ||
| 105 | - return this.deviceDetail.alarmStatus === '0' ? '否' : '是'; | 145 | + import { |
| 146 | + formatToDate | ||
| 147 | + } from '@/plugins/utils.js'; | ||
| 148 | + import { | ||
| 149 | + issueCommand | ||
| 150 | + } from '../api/index.js'; | ||
| 151 | + export default { | ||
| 152 | + props: { | ||
| 153 | + deviceDetail: { | ||
| 154 | + type: Object, | ||
| 155 | + default: () => ({}) | ||
| 156 | + } | ||
| 106 | }, | 157 | }, |
| 107 | - formatLastOnlineTime() { | ||
| 108 | - return formatToDate(Number(this.deviceDetail.lastOnlineTime), 'YYYY-MM-DD HH:mm:ss'); | ||
| 109 | - } | ||
| 110 | - }, | ||
| 111 | - onLoad(e) { | ||
| 112 | - // 隐藏原生的tabbar | ||
| 113 | - uni.hideTabBar(); | ||
| 114 | - }, | ||
| 115 | - mounted() {}, | ||
| 116 | - methods: { | ||
| 117 | - handleClick() { | ||
| 118 | - const data = { | ||
| 119 | - longitude: this.deviceDetail.deviceInfo.longitude || 0, | ||
| 120 | - latitude: this.deviceDetail.deviceInfo.latitude || 0 | 158 | + data() { |
| 159 | + return { | ||
| 160 | + showNodal: false, | ||
| 161 | + items: [{ | ||
| 162 | + value: 'OneWay', | ||
| 163 | + name: '单向', | ||
| 164 | + checked: 'true' | ||
| 165 | + }, | ||
| 166 | + { | ||
| 167 | + value: 'TwoWay', | ||
| 168 | + name: '双向' | ||
| 169 | + }, | ||
| 170 | + ], | ||
| 171 | + current: 0, | ||
| 172 | + modalName: null, | ||
| 173 | + showModel: false, | ||
| 174 | + commandType: 'OneWay', | ||
| 175 | + commandValue: {}, | ||
| 176 | + inputCommandVal: '' | ||
| 121 | }; | 177 | }; |
| 122 | - uni.navigateTo({ | ||
| 123 | - url: '/deviceSubPage/deviceDetailPage/devicePosition?data=' + JSON.stringify(data) | ||
| 124 | - }); | ||
| 125 | }, | 178 | }, |
| 126 | - showModal() { | ||
| 127 | - this.showModel = true; | ||
| 128 | - this.inputCommandVal = ''; | 179 | + computed: { |
| 180 | + deviceType() { | ||
| 181 | + return this.deviceDetail.deviceType === 'DIRECT_CONNECTION' ? | ||
| 182 | + '直连设备' : | ||
| 183 | + this.deviceDetail.deviceType === 'GATEWAY' ? | ||
| 184 | + '网关设备' : | ||
| 185 | + this.deviceDetail.deviceType === 'SENSOR' ? | ||
| 186 | + '网关子设备' : | ||
| 187 | + ''; | ||
| 188 | + }, | ||
| 189 | + alarmStatus() { | ||
| 190 | + return this.deviceDetail.alarmStatus === '0' ? '否' : '是'; | ||
| 191 | + }, | ||
| 192 | + formatLastOnlineTime() { | ||
| 193 | + return formatToDate(Number(this.deviceDetail.lastOnlineTime), 'YYYY-MM-DD HH:mm:ss'); | ||
| 194 | + } | ||
| 129 | }, | 195 | }, |
| 130 | - disabledScroll() { | ||
| 131 | - return; | 196 | + onLoad(e) { |
| 197 | + // 隐藏原生的tabbar | ||
| 198 | + uni.hideTabBar(); | ||
| 132 | }, | 199 | }, |
| 133 | - hiddenModal() { | ||
| 134 | - this.showModel = false; | 200 | + mounted() {}, |
| 201 | + beforeCreate() { | ||
| 202 | + this.modalName = null | ||
| 135 | }, | 203 | }, |
| 136 | - async confirmCommand() { | ||
| 137 | - try { | ||
| 138 | - const commandJsonValue = JSON.parse(this.inputCommandVal); | ||
| 139 | - this.commandValue.persistent = true; | ||
| 140 | - this.commandValue.additionalInfo = { | ||
| 141 | - cmdType: 'API' | ||
| 142 | - }; | ||
| 143 | - this.commandValue.method = 'methodThingskit'; | ||
| 144 | - this.commandValue.params = { | ||
| 145 | - params: commandJsonValue | 204 | + methods: { |
| 205 | + radioChange: function(evt) { | ||
| 206 | + for (let i = 0; i < this.items.length; i++) { | ||
| 207 | + if (this.items[i].value === evt.detail.value) { | ||
| 208 | + this.current = i; | ||
| 209 | + break; | ||
| 210 | + } | ||
| 211 | + } | ||
| 212 | + this.commandType = evt.detail.value | ||
| 213 | + }, | ||
| 214 | + handleClick() { | ||
| 215 | + const data = { | ||
| 216 | + longitude: this.deviceDetail.deviceInfo.longitude || 0, | ||
| 217 | + latitude: this.deviceDetail.deviceInfo.latitude || 0 | ||
| 146 | }; | 218 | }; |
| 147 | - await issueCommand(this.commandType, this.deviceDetail.tbDeviceId, this.commandValue); | 219 | + uni.navigateTo({ |
| 220 | + url: '/deviceSubPage/deviceDetailPage/devicePosition?data=' + JSON.stringify(data) | ||
| 221 | + }); | ||
| 222 | + }, | ||
| 223 | + showModal(e) { | ||
| 224 | + this.modalName = e.currentTarget.dataset.target | ||
| 225 | + this.showNodal = true | ||
| 226 | + }, | ||
| 227 | + showModalBtn() { | ||
| 228 | + this.showModel = true; | ||
| 229 | + this.inputCommandVal = ''; | ||
| 230 | + }, | ||
| 231 | + disabledScroll() { | ||
| 232 | + return; | ||
| 233 | + }, | ||
| 234 | + hiddenModal() { | ||
| 235 | + this.showModel = false; | ||
| 236 | + this.inputCommandVal = ''; | ||
| 237 | + // #ifdef APP-PLUS | ||
| 238 | + this.modalName = null | ||
| 239 | + this.showNodal = false | ||
| 240 | + // #endif | ||
| 241 | + }, | ||
| 242 | + async confirmCommand() { | ||
| 243 | + try { | ||
| 244 | + const commandJsonValue = JSON.parse(this.inputCommandVal); | ||
| 245 | + this.commandValue.persistent = true; | ||
| 246 | + this.commandValue.additionalInfo = { | ||
| 247 | + cmdType: 'API' | ||
| 248 | + }; | ||
| 249 | + this.commandValue.method = 'methodThingskit'; | ||
| 250 | + this.commandValue.params = { | ||
| 251 | + params: commandJsonValue | ||
| 252 | + }; | ||
| 253 | + await issueCommand(this.commandType, this.deviceDetail.tbDeviceId, this.commandValue); | ||
| 254 | + this.hiddenModal(); | ||
| 255 | + uni.$u.toast('下发成功~'); | ||
| 256 | + } catch (e) { | ||
| 257 | + uni.$u.toast('下发失败~'); | ||
| 258 | + } | ||
| 259 | + }, | ||
| 260 | + cancelCommand() { | ||
| 148 | this.hiddenModal(); | 261 | this.hiddenModal(); |
| 149 | - uni.$u.toast('下发成功~'); | ||
| 150 | - } catch (e) { | ||
| 151 | - uni.$u.toast('下发失败~'); | 262 | + // #ifdef APP-PLUS |
| 263 | + this.modalName = null | ||
| 264 | + this.showNodal = false | ||
| 265 | + // #endif | ||
| 152 | } | 266 | } |
| 153 | - }, | ||
| 154 | - cancelCommand() { | ||
| 155 | - this.hiddenModal(); | ||
| 156 | } | 267 | } |
| 157 | - } | ||
| 158 | -}; | 268 | + }; |
| 159 | </script> | 269 | </script> |
| 160 | 270 | ||
| 161 | <style lang="scss" scoped> | 271 | <style lang="scss" scoped> |
| 162 | -.basic-page { | ||
| 163 | - padding: 0 30rpx; | ||
| 164 | - .basic-title { | ||
| 165 | - display: flex; | ||
| 166 | - justify-content: space-between; | ||
| 167 | - align-items: center; | ||
| 168 | - height: 140rpx; | ||
| 169 | - background-color: #fff; | ||
| 170 | - border-radius: 20rpx; | 272 | + @import url('../styles/modal.css'); |
| 273 | + | ||
| 274 | + .cusAppplusContent { | ||
| 275 | + width: 625rpx; | ||
| 276 | + height: 400rpx; | ||
| 277 | + background: #FFFFFF; | ||
| 278 | + box-shadow: 2px 2px 4px 0px rgba(0, 0, 0, 0.03); | ||
| 279 | + border-radius: 10px; | ||
| 280 | + | ||
| 281 | + } | ||
| 282 | + | ||
| 283 | + .cusAppplusCancelBtn { | ||
| 284 | + background: #e3e3e5; | ||
| 285 | + border-radius: 38rpx; | ||
| 286 | + height: 85rpx; | ||
| 287 | + line-height: 85rpx | ||
| 288 | + } | ||
| 289 | + | ||
| 290 | + .cusAppplusConfrimBtn { | ||
| 291 | + background: #3388ff; | ||
| 292 | + border-radius: 38rpx; | ||
| 293 | + height: 85rpx; | ||
| 294 | + line-height: 85rpx | ||
| 295 | + } | ||
| 296 | + | ||
| 297 | + .cu-item { | ||
| 298 | + background: #3388FF; | ||
| 299 | + border-radius: 12px; | ||
| 300 | + width: 120rpx; | ||
| 301 | + height: 48rpx; | ||
| 302 | + text-align: center; | ||
| 303 | + line-height: 40rpx; | ||
| 304 | + | ||
| 305 | + text { | ||
| 306 | + font-size: 12px; | ||
| 307 | + font-family: PingFangSC-Regular, PingFang SC; | ||
| 308 | + font-weight: 400; | ||
| 309 | + color: #FFFFFF; | ||
| 310 | + } | ||
| 171 | } | 311 | } |
| 172 | - .detail { | ||
| 173 | - background-color: #fff; | ||
| 174 | - margin-top: 30rpx; | ||
| 175 | - border-radius: 20rpx; | ||
| 176 | - width: 690rpx; | ||
| 177 | - .detail-item { | ||
| 178 | - padding: 30rpx; | 312 | + |
| 313 | + | ||
| 314 | + | ||
| 315 | + .basic-page { | ||
| 316 | + padding: 0 30rpx; | ||
| 317 | + | ||
| 318 | + .basic-title { | ||
| 179 | display: flex; | 319 | display: flex; |
| 320 | + justify-content: space-between; | ||
| 180 | align-items: center; | 321 | align-items: center; |
| 181 | - .detail-label { | ||
| 182 | - color: #333; | ||
| 183 | - font-size: 15px; | ||
| 184 | - } | ||
| 185 | - .detail-value { | ||
| 186 | - color: #666; | ||
| 187 | - font-size: 14px; | ||
| 188 | - margin-left: 30rpx; | 322 | + height: 140rpx; |
| 323 | + background-color: #fff; | ||
| 324 | + border-radius: 20rpx; | ||
| 325 | + } | ||
| 326 | + | ||
| 327 | + .detail { | ||
| 328 | + background-color: #fff; | ||
| 329 | + margin-top: 30rpx; | ||
| 330 | + border-radius: 20rpx; | ||
| 331 | + width: 690rpx; | ||
| 332 | + | ||
| 333 | + .detail-item { | ||
| 334 | + padding: 30rpx; | ||
| 335 | + display: flex; | ||
| 336 | + align-items: center; | ||
| 337 | + | ||
| 338 | + .detail-label { | ||
| 339 | + color: #333; | ||
| 340 | + font-size: 15px; | ||
| 341 | + } | ||
| 342 | + | ||
| 343 | + .detail-value { | ||
| 344 | + color: #666; | ||
| 345 | + font-size: 14px; | ||
| 346 | + margin-left: 30rpx; | ||
| 347 | + } | ||
| 189 | } | 348 | } |
| 190 | } | 349 | } |
| 191 | } | 350 | } |
| 192 | -} | ||
| 193 | -/deep/ .u-modal__content { | ||
| 194 | - padding: 30rpx 0 !important; | ||
| 195 | -} | ||
| 196 | - | ||
| 197 | -.button-group { | ||
| 198 | - display: flex; | ||
| 199 | - margin-top: 40rpx; | ||
| 200 | - justify-content: space-between; | ||
| 201 | - view { | ||
| 202 | - width: 300rpx; | 351 | + |
| 352 | + /deep/ .u-modal__content { | ||
| 353 | + padding: 30rpx 0 !important; | ||
| 354 | + } | ||
| 355 | + | ||
| 356 | + .button-group { | ||
| 357 | + display: flex; | ||
| 358 | + margin-top: 40rpx; | ||
| 359 | + justify-content: space-between; | ||
| 360 | + | ||
| 361 | + view { | ||
| 362 | + width: 300rpx; | ||
| 363 | + } | ||
| 203 | } | 364 | } |
| 204 | -} | ||
| 205 | </style> | 365 | </style> |