Commit 0f18827df80a2e9c8f4cc0e16a01979e47d3d27f

Authored by sqy
1 parent 0b83e8b9

fix:修改设备的页面

1 1 // 获取某个Key的历史数据
2 2 export function getHistroyData(params) {
3   - const {entityId,keys,startTs,endTs} = params
  3 + const {entityId,keys,startTs,endTs,interval} = params
4 4 return uni.$u.http.get(
5   - `/plugins/telemetry/DEVICE/${params.entityId}/values/timeseries?keys=${params.keys}&startTs=${params.startTs}&endTs=${params.endTs}`);
  5 + `/plugins/telemetry/DEVICE/${entityId}/values/timeseries?keys=${keys}&startTs=${startTs}&endTs=${endTs}&interval=${interval}`);
6 6 }
7 7
8 8 // 获取当前设备的key
... ...
... ... @@ -4,11 +4,22 @@
4 4 <public-module></public-module>
5 5 <u-sticky bgColor="#fff"><u-tabs :list="list" :current="currentTab" @click="handleTabClick"></u-tabs></u-sticky>
6 6 <view style="margin-top:30rpx;">
7   - <basicInfo v-if="currentTab == 0" :deviceDetail="deviceDetail" />
8   - <realTimeData v-if="currentTab === 1" />
9   - <historyData v-if="currentTab === 2" :keys="keys" :yesterday="yesterday" :today="today" :timeDiff="timeDiff" :historyData="historyData" :entityId="entityId" @update="handleUpdate" />
10   - <alarmHistory v-if="currentTab === 3" />
11   - <commondRecord v-if="currentTab === 4" />
  7 + <basicInfo v-show="currentTab == 0" :deviceDetail="deviceDetail" />
  8 + <realTimeData v-show="currentTab === 1" :recordList="recordList" />
  9 + <historyData
  10 + v-if="currentTab === 2"
  11 + :keys="keys"
  12 + :yesterday="yesterday"
  13 + :today="today"
  14 + :timeDiff="timeDiff"
  15 + :historyData="historyData"
  16 + :entityId="entityId"
  17 + @update="handleUpdate"
  18 + :start="startTs"
  19 + :end="endTs"
  20 + />
  21 + <alarmHistory v-show="currentTab === 3" :deviceId="deviceId" />
  22 + <commondRecord v-show="currentTab === 4" :deviceId="deviceId" />
12 23 </view>
13 24 <f-tabbar></f-tabbar>
14 25 </view>
... ... @@ -20,8 +31,8 @@ import basicInfo from './tabDetail/basicInfo.vue';
20 31 import realTimeData from './tabDetail/realtimeData.vue';
21 32 import alarmHistory from './tabDetail/alarmHistory.vue';
22 33 import historyData from './tabDetail/historyData.vue';
23   -import commondRecord from './tabDetail/commondRecord.vue';
24   -import { getDeviceKeys, getHistroyData } from '@/pages/device/api/index.js';
  34 +import commondRecord from './tabDetail/CommandRecord.vue';
  35 +import { getDeviceKeys, getHistroyData } from './api/index.js';
25 36 import { formatToDate } from '@/plugins/utils.js';
26 37 export default {
27 38 components: {
... ... @@ -35,58 +46,88 @@ export default {
35 46 data() {
36 47 return {
37 48 list: [{ name: '基础信息' }, { name: '实时数据' }, { name: '历史数据' }, { name: '告警记录' }, { name: '命令记录' }],
38   - currentTab: 2,
39   - id: '',
  49 + currentTab: 3,
  50 + deviceId: '',
40 51 deviceDetail: {},
41 52 keys: [],
42 53 yesterday: '',
43 54 today: '',
44 55 timeDiff: '',
45 56 historyData: [],
46   - entityId: ''
  57 + entityId: '',
  58 + startTs: '',
  59 + endTs: '',
  60 + recordList: []
47 61 };
48 62 },
49 63 async onLoad(options) {
50 64 const { id, alarmStatus, lastOnlineTime, tbDeviceId } = options;
  65 + this.deviceId = id;
  66 + console.log(this.deviceId);
51 67 const res = await uni.$u.http.get(`/yt/device/${id}`);
52 68 this.deviceDetail = { ...res, alarmStatus, lastOnlineTime };
  69 + const socketTask = uni.connectSocket({
  70 + url: 'wss://dev.thingskit.com/api/ws/plugins/telemetry?token=' + uni.getStorageSync('userInfo').isToken, //仅为示例,并非真实接口地址。
  71 + complete: () => {}
  72 + });
  73 + uni.onSocketOpen(header => {
  74 + socketTask.send({
  75 + data: JSON.stringify({
  76 + attrSubCmds: [],
  77 + tsSubCmds: [
  78 + {
  79 + entityType: 'DEVICE',
  80 + entityId: tbDeviceId,
  81 + scope: 'LATEST_TELEMETRY',
  82 + cmdId: 1
  83 + }
  84 + ],
  85 + historyCmds: [],
  86 + entityDataCmds: [],
  87 + entityDataUnsubscribeCmds: [],
  88 + alarmDataCmds: [],
  89 + alarmDataUnsubscribeCmds: [],
  90 + entityCountCmds: [],
  91 + entityCountUnsubscribeCmds: []
  92 + }),
  93 + success() {}
  94 + });
  95 + });
  96 + socketTask.onMessage(msg => {
  97 + const { data } = JSON.parse(msg.data);
  98 + const newArray = [];
  99 + for (const key in data) {
  100 + const [time, value] = data[key].flat(1);
  101 + let obj = { key, time, value };
  102 + if (this.recordList.length === 0) {
  103 + this.recordList.unshift(obj);
  104 + } else {
  105 + newArray.push(obj);
  106 + }
  107 + }
  108 + newArray.forEach(item => {
  109 + let flag = false;
  110 + this.recordList.forEach(item1 => {
  111 + if (item1.key === item.key) {
  112 + item1.value = item.value;
  113 + item1.time = item.time;
  114 + flag = true;
  115 + }
  116 + });
  117 + if (!flag) {
  118 + this.recordList.unshift(item);
  119 + }
  120 + });
53 121
54   - // var socketTask = uni.connectSocket({
55   - // url: 'wss://dev.thingskit.com:8080/api/ws/plugins/telemetry?token=' + uni.getStorageSync('userInfo').isToken, //仅为示例,并非真实接口地址。
56   - // complete: ()=> {}
57   - // });
58   - // uni.onSocketOpen((header)=>{
59   - // console.log('连接成功',header)
60   - // })
61   - // // socketTask.onMessage(function(data) {
62   - // // console.log('收到消息了', data);
63   - // // });
64   - // socketTask.send({
65   - // data: JSON.stringify({
66   - // attrSubCmds: [],
67   - // tsSubCmds: [
68   - // {
69   - // entityType: 'DEVICE',
70   - // entityId: id,
71   - // scope: 'LATEST_TELEMETRY',
72   - // cmdId: 1
73   - // }
74   - // ],
75   - // historyCmds: [],
76   - // entityDataCmds: [],
77   - // entityDataUnsubscribeCmds: [],
78   - // alarmDataCmds: [],
79   - // alarmDataUnsubscribeCmds: [],
80   - // entityCountCmds: [],
81   - // entityCountUnsubscribeCmds: []
82   - // }),
83   - // success() {
84   - // console.log('发送成功了');
85   - // }
86   - // });
  122 + this.recordList = this.recordList.map(item => {
  123 + return {
  124 + ...item,
  125 + time: formatToDate(item.time, 'YYYY-MM-DD HH:mm:ss')
  126 + };
  127 + });
  128 + });
87 129
88 130 const keys = await getDeviceKeys(tbDeviceId);
89   - // 隐藏原生的tabbar'
90 131 this.keys = [keys];
91 132 const date = new Date();
92 133 const year = date.getFullYear(); //获取完整的年份(4位)
... ... @@ -96,12 +137,15 @@ export default {
96 137 const today = `${year}-${month}-${day + 1}`;
97 138 this.yesterday = yesterday;
98 139 this.today = today;
99   - this.entityId = tbDeviceId
  140 + this.startTs = formatToDate(yesterday, 'x');
  141 + this.endTs = formatToDate(today, 'x');
  142 + this.entityId = tbDeviceId;
100 143 const data = await getHistroyData({
101 144 entityId: tbDeviceId,
102 145 startTs: formatToDate(yesterday, 'x'),
103 146 endTs: formatToDate(today, 'x'),
104   - keys: keys[0]
  147 + keys: keys[0],
  148 + interval: 1800000
105 149 });
106 150
107 151 this.historyData = data[keys[0]].map(item => {
... ... @@ -111,13 +155,16 @@ export default {
111 155 };
112 156 });
113 157 this.timeDiff = '30分钟';
114   - uni.hideTabBar();
115 158 },
116 159 methods: {
117 160 handleTabClick({ index }) {
118 161 this.currentTab = index;
119 162 },
120   - handleUpdate(data){
  163 + handleUpdate(data) {
  164 + if (!Array.isArray(data)) {
  165 + this.historyData = [];
  166 + return;
  167 + }
121 168 this.historyData = data.map(item => {
122 169 return {
123 170 value: item.value,
... ...
  1 +<template>
  2 + <view class="command-detail">
  3 + <view class="detail-top">网关设备1</view>
  4 + <view class="detail">
  5 + <view class="detail-item">
  6 + <view class="detail-label">设备类型</view>
  7 + <view class="detail-value">网关子设备</view>
  8 + </view>
  9 + <u-line length="90%" margin="0 auto"></u-line>
  10 + <view class="detail-item">
  11 + <view class="detail-label">设备编号</view>
  12 + <view class="detail-value">SN98489123471829</view>
  13 + </view>
  14 + <u-line length="90%" margin="0 auto"></u-line>
  15 + <view class="detail-item">
  16 + <view class="detail-label">所属组织</view>
  17 + <view class="detail-value">云腾汽车</view>
  18 + </view>
  19 + <u-line length="90%" margin="0 auto"></u-line>
  20 + <view class="detail-item">
  21 + <view class="detail-label">命令下发时间</view>
  22 + <view class="detail-value">2022-01-25 12:44:22</view>
  23 + </view>
  24 + <u-line length="90%" margin="0 auto"></u-line>
  25 + <view class="detail-item">
  26 + <view class="detail-label">命令类型</view>
  27 + <view class="detail-value">Mqtt命令</view>
  28 + </view>
  29 + <u-line length="90%" margin="0 auto"></u-line>
  30 + <view class="detail-item">
  31 + <view class="detail-label">响应类型</view>
  32 + <view class="detail-value">OneWay</view>
  33 + </view>
  34 + <u-line length="90%" margin="0 auto"></u-line>
  35 + <view class="detail-item">
  36 + <view class="detail-label">下发结果</view>
  37 + <view class="detail-value">成功</view>
  38 + </view>
  39 + <u-line length="90%" margin="0 auto"></u-line>
  40 + <view class="detail-item">
  41 + <view class="detail-label">响应结果</view>
  42 + <view class="detail-value">成功</view>
  43 + </view>
  44 + </view>
  45 + <view class="command">命令内容</view>
  46 + <u-textarea></u-textarea>
  47 + </view>
  48 +</template>
  49 +
  50 +<script></script>
  51 +
  52 +<style lang="scss" scoped>
  53 +.command-detail {
  54 + padding: 0 30rpx;
  55 + .detail-top {
  56 + height: 118rpx;
  57 + width: 690rpx;
  58 + display: flex;
  59 + align-items: center;
  60 + background-color: #fff;
  61 + color: #333;
  62 + border-radius: 20rpx;
  63 + font-size: 30rpx;
  64 + margin-top: 30rpx;
  65 + padding: 30rpx;
  66 + }
  67 + .detail {
  68 + background-color: #fff;
  69 + margin-top: 30rpx;
  70 + border-radius: 20rpx;
  71 + width: 690rpx;
  72 + .detail-item {
  73 + padding: 30rpx;
  74 + display: flex;
  75 + align-items: center;
  76 + .detail-label {
  77 + color: #333;
  78 + font-size: 30rpx;
  79 + }
  80 + .detail-value {
  81 + color: #666;
  82 + font-size: 28rpx;
  83 + margin-left: 30rpx;
  84 + }
  85 + }
  86 + }
  87 + .command{
  88 + margin: 30rpx 0;
  89 + }
  90 +}
  91 +</style>
... ...
  1 +<template>
  2 + <view class="alert-page">
  3 + <!-- 公共组件-每个页面必须引入 -->
  4 + <public-module></public-module>
  5 + <mescroll-body ref="mescrollRef" @init="mescrollInit" :down="downOption" @down="downCallback" @up="upCallback">
  6 + <view @click="openDeviceDetail(item)" class="list-item" v-for="(item, index) in list" :key="index">
  7 + <view class="item">
  8 + <view class="item-first">
  9 + <text>{{ item.deviceName }}</text>
  10 + <view class="item-right">响应成功</view>
  11 + </view>
  12 + <view>
  13 + 命令类型:<text style="margin-left: 16rpx;">MQTT命令</text>
  14 + </view>
  15 + <view>
  16 + 命令状态:<text style="margin-left: 16rpx;">下发成功</text>
  17 + </view>
  18 + <view class="time">{{ item.createdTime }}</view>
  19 + </view>
  20 + </view>
  21 + </mescroll-body>
  22 + <!-- 告警筛选 -->
  23 + <u-popup @close="close" closeable :overlay="true" :show="show" mode="bottom" bgColor="#fff">
  24 + <view>
  25 + <view style="text-align: center; margin-top: 28rpx"><text>筛选条件</text></view>
  26 + <FilterItem :filterList="alarmStatus" title="告警状态" @clickTag="currentIndex => handleClickTag(currentIndex, alarmStatus)"></FilterItem>
  27 + <FilterItem :filterList="typeStatus" title="设备类型" @clickTag="currentIndex => handleClickTag(currentIndex, typeStatus)"></FilterItem>
  28 + <FilterItem :filterList="alarmLevelStatus" title="告警等级" @clickTag="currentIndex => handleClickTag(currentIndex, alarmLevelStatus)"></FilterItem>
  29 + <FilterItem :filterList="timeStatus" title="选择时间" @clickTag="currentIndex => handleClickTag(currentIndex, timeStatus)"></FilterItem>
  30 + <view class="u-flex" style="margin-top: 40rpx; margin-left: 55rpx">
  31 + <view style="width: 300rpx"><u-button type="info" shape="circle" text="重置" @click="resetFilter"></u-button></view>
  32 + <view style="width: 300rpx; margin-left: 46rpx"><u-button type="primary" shape="circle" text="确认" @click="confirmFilter"></u-button></view>
  33 + </view>
  34 + </view>
  35 + </u-popup>
  36 + <u-calendar
  37 + :show="showCalendar"
  38 + mode="range"
  39 + @confirm="calendarConfirm"
  40 + @close="calendarClose"
  41 + startText="开始时间"
  42 + endText="结束时间"
  43 + confirmDisabledText="请选择日期"
  44 + :formatter="formatter"
  45 + ></u-calendar>
  46 + </view>
  47 +</template>
  48 +<script>
  49 +import FilterItem from '@/pages/device/FilterItem.vue';
  50 +import MescrollMixin from '@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js';
  51 +export default {
  52 + mixins: [MescrollMixin],
  53 + components: {
  54 + FilterItem
  55 + },
  56 + props: {
  57 + deviceId: {
  58 + type: String,
  59 + default: ''
  60 + }
  61 + },
  62 + mounted() {
  63 + this.loadData(1, {
  64 + deviceId: this.deviceId
  65 + });
  66 + },
  67 + data() {
  68 + return {
  69 + show: false,
  70 + list: [],
  71 + total: '',
  72 + timeData: {
  73 + selectTime: '',
  74 + getTimeGap: ''
  75 + },
  76 + showCalendar: false,
  77 + alarmStatus: [
  78 + {
  79 + checked: true,
  80 + name: '全部',
  81 + type: ''
  82 + },
  83 + {
  84 + checked: false,
  85 + name: '激活未确认',
  86 + type: 'ACTIVE_UNACK'
  87 + },
  88 + {
  89 + checked: false,
  90 + name: '激活已确认',
  91 + type: 'ACTIVE_ACK'
  92 + },
  93 + {
  94 + checked: false,
  95 + name: '清除未确认',
  96 + type: 'CLEARED_UNACK'
  97 + },
  98 + {
  99 + checked: false,
  100 + name: '清除已确认',
  101 + type: 'CLEARED_ACK'
  102 + }
  103 + ],
  104 + typeStatus: [
  105 + {
  106 + checked: true,
  107 + name: '全部',
  108 + type: ''
  109 + },
  110 + {
  111 + checked: false,
  112 + name: '网关设备',
  113 + type: 'GATEWAY'
  114 + },
  115 + {
  116 + checked: false,
  117 + name: '网关子设备',
  118 + type: 'SENSOR'
  119 + },
  120 + {
  121 + checked: false,
  122 + name: '直连设备',
  123 + type: 'DIRECT_CONNECTION'
  124 + }
  125 + ],
  126 + alarmLevelStatus: [
  127 + {
  128 + checked: true,
  129 + name: '全部',
  130 + type: ''
  131 + },
  132 + {
  133 + checked: false,
  134 + name: '危险',
  135 + type: 'CRITICAL'
  136 + },
  137 + {
  138 + checked: false,
  139 + name: '重要',
  140 + type: 'MAJOR'
  141 + },
  142 + {
  143 + checked: false,
  144 + name: '次要',
  145 + type: 'MINOR'
  146 + },
  147 + {
  148 + checked: false,
  149 + name: '警告',
  150 + type: 'WARNING'
  151 + },
  152 + {
  153 + checked: false,
  154 + name: '不确定',
  155 + type: 'INDETERMINATE'
  156 + }
  157 + ],
  158 + timeStatus: [
  159 + {
  160 + checked: true,
  161 + name: '全部',
  162 + type: ''
  163 + },
  164 + {
  165 + checked: false,
  166 + name: '30分钟',
  167 + type: '1800000'
  168 + },
  169 + {
  170 + checked: false,
  171 + name: '一小时',
  172 + type: '3600000'
  173 + },
  174 + {
  175 + checked: false,
  176 + name: '2小时',
  177 + type: '7200000'
  178 + },
  179 + {
  180 + checked: false,
  181 + name: '近一天',
  182 + type: '1440000'
  183 + }
  184 + ],
  185 + downOption: {
  186 + auto: false //是否在初始化后,自动执行downCallback; 默认true
  187 + },
  188 + page:{
  189 + num:0,
  190 + sizie:10
  191 + }
  192 + };
  193 + },
  194 + methods: {
  195 + /*下拉刷新的回调 */
  196 + downCallback() {
  197 + //联网加载数据
  198 + this.list = [];
  199 + this.page.num = 1;
  200 + this.loadData(this.page.num, {
  201 + deviceId: this.deviceId
  202 + });
  203 + },
  204 + /*上拉加载的回调: 其中page.num:当前页 从1开始, page.size:每页数据条数,默认10 */
  205 + upCallback() {
  206 + //联网加载数据
  207 + this.page.num += 1;
  208 + this.loadData(this.page.num, {
  209 + deviceId: this.deviceId
  210 + });
  211 + },
  212 + //获取告警数据
  213 + loadData(pageNo, params = {}) {
  214 + let httpData = {
  215 + ...params,
  216 + page: pageNo,
  217 + pageSize: 10
  218 + };
  219 + uni.$u.http
  220 + .get('/yt/alarm', {
  221 + params: httpData,
  222 + custom: {
  223 + load: false
  224 + }
  225 + })
  226 + .then(res => {
  227 + this.total = res.total;
  228 + uni.stopPullDownRefresh();
  229 + console.log('获取后端数据', res);
  230 + //方法一(推荐): 后台接口有返回列表的总页数 totalPage
  231 + this.mescroll.endByPage(res.items.length,res.total); //必传参数(当前页的数据个数, 总页数)
  232 + if (pageNo == 1) {
  233 + this.list = res.items;
  234 + } else {
  235 + this.list = this.list.concat(res.items);
  236 + }
  237 + })
  238 + .catch(() => {
  239 + //联网失败, 结束加载
  240 + this.mescroll.endErr();
  241 + });
  242 + },
  243 + handleClickTag(currentIndex, list) {
  244 + list.map((item, index) => {
  245 + item.checked = index === currentIndex;
  246 + });
  247 + },
  248 + resetFilter() {
  249 + const { alarmStatus, typeStatus, alarmLevelStatus, timeStatus } = this;
  250 + [alarmStatus, typeStatus, alarmLevelStatus, timeStatus].forEach(item => item.map((item, index) => (item.checked = index === 0)));
  251 + },
  252 + close() {
  253 + this.show = false;
  254 + },
  255 + openSearchDialog() {
  256 + this.show = true;
  257 + },
  258 + hideKeyboard() {
  259 + uni.hideKeyboard();
  260 + },
  261 + calendarConfirm(e) {
  262 + this.showCalendar = false;
  263 + this.timeData.selectTime = `${e[0]} / ${e[e.length - 1]}`;
  264 + },
  265 + confirmFilter() {
  266 + const alarmState = this.alarmStatus.find(item => item.checked);
  267 + const typeState = this.typeStatus.find(item => item.checked);
  268 + const alarmLevelState = this.alarmLevelStatus.find(item => item.checked);
  269 + const timeState = this.timeStatus.find(item => item.checked);
  270 + const endTs = Date.now();
  271 + const startTs = endTs - timeState.type;
  272 + this.loadData(1, {
  273 + status: alarmState.type ? alarmState.type : undefined,
  274 + deviceType: typeState.type ? typeState.type : undefined,
  275 + alarmType: alarmLevelState.type ? alarmLevelState.type : undefined,
  276 + startTime: timeState.type ? startTs : undefined,
  277 + endTime: timeState.type ? endTs : undefined,
  278 + deviceId: this.deviceId
  279 + });
  280 + this.show = false;
  281 + },
  282 + calendarClose() {
  283 + this.showCalendar = false;
  284 + },
  285 + openDeviceDetail(item) {
  286 + const { id, deviceName, severity, originatorType, details, createdTime, status } = item;
  287 + let obj = {
  288 + id,
  289 + deviceName,
  290 + severity,
  291 + originatorType,
  292 + details,
  293 + createdTime,
  294 + status
  295 + };
  296 + console.log(123)
  297 + uni.navigateTo({
  298 + url:'/deviceSubPage/deviceDetailPage/tabDetail/CommandDetail'
  299 + });
  300 + }
  301 + }
  302 +};
  303 +</script>
  304 +
  305 +<style lang="scss" scoped>
  306 +.alert-page {
  307 + padding: 20rpx;
  308 + .list-item {
  309 + width: 690rpx;
  310 + height: 262rpx;
  311 + background-color: #fff;
  312 + border-radius: 20rpx;
  313 + margin: 20rpx auto;
  314 + color: #333;
  315 + .item {
  316 + padding: 30rpx;
  317 + view {
  318 + font-size: 28rpx;
  319 + margin-bottom: 10rpx;
  320 + }
  321 + .time {
  322 + color: #999;
  323 + }
  324 + .item-first {
  325 + display: flex;
  326 + justify-content: space-between;
  327 + align-items: center;
  328 + font-size: 30rpx;
  329 + font-weight: 500;
  330 + align-items: center;
  331 + .item-right {
  332 + display: flex;
  333 + justify-content: center;
  334 + align-items: center;
  335 + color: #00c9a7;
  336 + width: 104rpx;
  337 + height: 36rpx;
  338 + font-size: 20rpx;
  339 + background-color: #00c9a725;
  340 + border-radius: 20rpx;
  341 + }
  342 + }
  343 + }
  344 + }
  345 +}
  346 +</style>
... ...
... ... @@ -2,134 +2,68 @@
2 2 <view class="alert-page">
3 3 <!-- 公共组件-每个页面必须引入 -->
4 4 <public-module></public-module>
5   - <view style="width: 192rpx;margin: 19rpx;"><u-button @click="openSearchDialog" shape="circle" type="info" icon="search" text="筛选"></u-button></view>
6   - <view class="device-list">
7   - <view @click="openDeviceDetail(item.id)" class="list-item" v-for="(item, index) in list" :key="index">
8   - <view class="u-flex item" style="justify-content: flex-start;flex-direction: column;align-items: center;">
9   - <view style="width: 400rpx;text-align: left;">
10   - <text style="color:#333;font-size: 15px;">{{ item.name1 }}</text>
11   - </view>
12   - <view style="width: 400rpx;text-align: left;">
13   - <text style="color:#666;font-size: 15px;">{{ item.name2 }}</text>
14   - </view>
15   - <view style="width: 400rpx;text-align: left;">
16   - <text style="color:#666;font-size: 15px;">{{ item.name3 }}</text>
17   - </view>
18   - <view style="width: 400rpx;text-align: left;">
19   - <text style="color:#999;font-size: 15px;">{{ item.time }}</text>
20   - </view>
21   - </view>
  5 + <mescroll-body ref="mescrollRef" @init="mescrollInit" :down="downOption" @down="downCallback" @up="upCallback">
  6 + <view style="width: 192rpx;"><u-button @click="openSearchDialog" shape="circle" type="info" icon="search" text="筛选"></u-button></view>
  7 + <view @click="openDeviceDetail(item)" class="list-item" v-for="(item, index) in list" :key="index">
22 8 <view class="item">
23   - <view class="u-flex" style="margin-top: -6rpx;">
24   - <image style="width: 30rpx;height: 30rpx;margin-top: 5rpx;margin-right: 5rpx;" :src="item.name4" mode=""></image>
25   - <view>
26   - <text style="color: #377DFF;font-size: 13px;margin-left: 5rpx;margin-top: 20rpx;">{{ item.name5 }}</text>
  9 + <view class="item-first">
  10 + <text>{{ item.deviceName }}</text>
  11 + <view class="item-right">
  12 + <image
  13 + :src="
  14 + item.severity === 'CRITICAL'
  15 + ? '../../../static/danger.png'
  16 + : item.severity === 'MAJOR'
  17 + ? '../../../static/major.png'
  18 + : item.severity === 'MINOR'
  19 + ? '../../../static/secondary.png'
  20 + : item.severity === 'WARNING'
  21 + ? '../../../static/warn.png'
  22 + : '../../../static/noshue.png'
  23 + "
  24 + ></image>
  25 + <text
  26 + :style="{
  27 + color:
  28 + item.severity === 'CRITICAL'
  29 + ? '#DE4437'
  30 + : item.severity === 'MAJOR'
  31 + ? '#DE7337'
  32 + : item.severity === 'MINOR'
  33 + ? '#FFC107'
  34 + : item.severity === 'WARNING'
  35 + ? '#FF1E0B'
  36 + : '#00C9A7'
  37 + }"
  38 + >
  39 + {{
  40 + item.severity === 'CRITICAL' ? '危险' : item.severity === 'MAJOR' ? '重要' : item.severity === 'MINOR' ? '次要' : item.severity === 'WARNING' ? '警告' : '不确定'
  41 + }}
  42 + </text>
27 43 </view>
28 44 </view>
  45 + <view>{{ Object.entries(item.details.data)[0][0] }} : {{ Object.entries(item.details.data)[0][1] }}</view>
  46 + <view v-if="item.status">
  47 + 告警状态:{{
  48 + item.status === 'CLEARED_UNACK' ? '清除未确认' : item.status === 'CLEARED_ACK' ? '清除已确认' : item.status === 'ACTIVE_UNACK' ? '激活未确认' : '激活已确认'
  49 + }}
  50 + </view>
  51 + <view class="time">{{ item.createdTime }}</view>
29 52 </view>
30 53 </view>
31   - </view>
32   - <view style="height: 30rpx;"></view>
  54 + </mescroll-body>
33 55 <!-- 告警筛选 -->
34   - <u-popup @close="close" closeable bgColor="transparent" :overlay="true" :show="show" mode="bottom">
35   - <view style="height: 1100rpx;background:#fff;border-radius: 20rpx;overflow-y: scroll;">
36   - <view style="text-align: center;position: relative;top: 68rpx;margin-top: -40rpx;"><text style="font-size: 16px;color: #333333;">筛选条件</text></view>
37   - <view style="margin-top: 97rpx;margin-left: 43rpx;">
38   - <view style="width: 750rpx;margin-left: 14rpx;"><text style="color: #333333;font-size: 14px;">告警状态</text></view>
39   - <view
40   - class="u-flex"
41   - style="margin-top: 15rpx;width:650rpx;height: 60rpx;
42   - flex-wrap: wrap;justify-content: space-between; align-content: space-between;"
43   - >
44   - <view
45   - v-for="(item, index) in alertStatus"
46   - :key="index"
47   - style="margin: 10rpx;line-height: 50rpx;text-align: center;
48   - width:180rpx;height: 60rpx;
49   - background-color:#F6F6F6;border-radius:32px"
50   - >
51   - <text style="color:#333333;font-size: 13px;">{{ item.name }}</text>
52   - </view>
53   - </view>
  56 + <u-popup @close="close" closeable :overlay="true" :show="show" mode="bottom" bgColor="#fff">
  57 + <view>
  58 + <view style="text-align: center; margin-top: 28rpx"><text>筛选条件</text></view>
  59 + <FilterItem :filterList="alarmStatus" title="告警状态" @clickTag="currentIndex => handleClickTag(currentIndex, alarmStatus)"></FilterItem>
  60 + <FilterItem :filterList="typeStatus" title="设备类型" @clickTag="currentIndex => handleClickTag(currentIndex, typeStatus)"></FilterItem>
  61 + <FilterItem :filterList="alarmLevelStatus" title="告警等级" @clickTag="currentIndex => handleClickTag(currentIndex, alarmLevelStatus)"></FilterItem>
  62 + <FilterItem :filterList="timeStatus" title="选择时间" @clickTag="currentIndex => handleClickTag(currentIndex, timeStatus)"></FilterItem>
  63 + <view class="u-flex" style="margin-top: 40rpx; margin-left: 55rpx">
  64 + <view style="width: 300rpx"><u-button type="info" shape="circle" text="重置" @click="resetFilter"></u-button></view>
  65 + <view style="width: 300rpx; margin-left: 46rpx"><u-button type="primary" shape="circle" text="确认" @click="confirmFilter"></u-button></view>
54 66 </view>
55   - <view style="margin-top: 145rpx;margin-left: 43rpx;">
56   - <view style="width: 750rpx;margin-left: 14rpx;"><text style="color: #333333;font-size: 14px;">设备类型</text></view>
57   - <view
58   - class="u-flex"
59   - style="margin-top: 15rpx;width:650rpx;height: 60rpx;
60   - flex-wrap: wrap;justify-content: space-between; align-content: space-between;"
61   - >
62   - <view
63   - v-for="(item, index) in deviceType"
64   - :key="index"
65   - style="margin: 10rpx;line-height: 50rpx;text-align: center;
66   - width:180rpx;height: 60rpx;
67   - background-color:#F6F6F6;border-radius:32px"
68   - >
69   - <text style="color:#333;font-size: 13px;">{{ item.name }}</text>
70   - </view>
71   - </view>
72   - </view>
73   - <view style="margin-top: 136rpx;margin-left: 43rpx;">
74   - <view style="width: 750rpx;margin-left: 14rpx;"><text style="color: #333;font-size: 14px;">告警等级</text></view>
75   - <view
76   - class="u-flex"
77   - style="margin-top: 15rpx;width:650rpx;height: 60rpx;
78   - flex-wrap: wrap;justify-content: space-between; align-content: space-between;"
79   - >
80   - <view
81   - v-for="(item, index) in alertLevel"
82   - :key="index"
83   - style="margin: 10rpx;line-height: 50rpx;text-align: center;
84   - width:180rpx;height: 60rpx;
85   - background-color:#F6F6F6;border-radius:32px"
86   - >
87   - <text style="color:#333333;font-size: 13px;">{{ item.name }}</text>
88   - </view>
89   - </view>
90   - </view>
91   - <view style="margin-top: 136rpx;margin-left: 43rpx;">
92   - <view style="width: 750rpx;margin-left: 14rpx;"><text style="color: #333333;font-size: 14px;">选择时间</text></view>
93   - <view
94   - class="u-flex"
95   - style="margin-top: 15rpx;width:650rpx;height: 60rpx;
96   - flex-wrap: wrap;justify-content: space-between; align-content: space-between;"
97   - >
98   - <view
99   - v-for="(item, index) in timeArea"
100   - :key="index"
101   - style="margin: 10rpx;line-height: 50rpx;text-align: center;
102   - width:180rpx;height: 60rpx;
103   - background-color:#F6F6F6;border-radius:32px"
104   - >
105   - <text style="color:#333333;font-size: 13px;">{{ item.name }}</text>
106   - </view>
107   - </view>
108   - </view>
109   - <view style="margin-top: 136rpx;margin-left: 43rpx;">
110   - <view class="u-flex" style="margin-left: 10rpx;margin-top: 15rpx;width:750rpx;height: 60rpx;">
111   - <u--form labelPosition="left" :model="timeData" :rules="rules" ref="form1" style="padding-left: 26rpx;width: 617rpx!important;">
112   - <u-form-item
113   - style="font-size: 14px;"
114   - label="选择日期"
115   - prop="selectTime"
116   - labelWidth="80"
117   - borderBottom
118   - @click="
119   - showCalendar = true;
120   - hideKeyboard();
121   - "
122   - >
123   - <u--input v-model="timeData.selectTime" placeholder="请选择日期" border="none"></u--input>
124   - </u-form-item>
125   - </u--form>
126   - </view>
127   - </view>
128   - <view class="u-flex" style="margin-top: 128rpx;margin-left: 55rpx;">
129   - <view style="width: 300rpx"><u-button type="info" shape="circle" text="重置"></u-button></view>
130   - <view style="width: 300rpx;margin-left:46rpx ;"><u-button type="primary" shape="circle" text="确认"></u-button></view>
131   - </view>
132   - <view style="height: 30rpx;"></view>
133 67 </view>
134 68 </u-popup>
135 69 <u-calendar
... ... @@ -142,225 +76,212 @@
142 76 confirmDisabledText="请选择日期"
143 77 :formatter="formatter"
144 78 ></u-calendar>
145   -
146 79 </view>
147 80 </template>
148   -
149 81 <script>
150   -import fTabbar from '@/components/module/f-tabbar/f-tabbar';
  82 +import FilterItem from '@/pages/device/FilterItem.vue';
  83 +import MescrollMixin from '@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js';
151 84 export default {
  85 + mixins: [MescrollMixin],
152 86 components: {
153   - fTabbar
  87 + FilterItem
  88 + },
  89 + props: {
  90 + deviceId: {
  91 + type: String,
  92 + default: ''
  93 + }
  94 + },
  95 + mounted() {
  96 + this.loadData(1, {
  97 + deviceId: this.deviceId
  98 + });
154 99 },
155 100 data() {
156 101 return {
157 102 show: false,
  103 + list: [],
  104 + total: '',
158 105 timeData: {
159 106 selectTime: '',
160 107 getTimeGap: ''
161 108 },
162 109 showCalendar: false,
163   - alertStatus: [
  110 + alarmStatus: [
164 111 {
165   - index: 1,
  112 + checked: true,
166 113 name: '全部',
167   - bgColor: '#377DFF',
168   - textColor: '#377DFF'
  114 + type: ''
169 115 },
170 116 {
171   - index: 2,
  117 + checked: false,
172 118 name: '激活未确认',
173   - bgColor: '#F6F6F6',
174   - textColor: '#F6F6F6'
  119 + type: 'ACTIVE_UNACK'
175 120 },
176 121 {
177   - index: 3,
  122 + checked: false,
178 123 name: '激活已确认',
179   - bgColor: '#F6F6F6',
180   - textColor: '#F6F6F6'
  124 + type: 'ACTIVE_ACK'
181 125 },
182 126 {
183   - index: 4,
  127 + checked: false,
184 128 name: '清除未确认',
185   - bgColor: '#F6F6F6',
186   - textColor: '#F6F6F6'
  129 + type: 'CLEARED_UNACK'
187 130 },
188 131 {
189   - index: 5,
  132 + checked: false,
190 133 name: '清除已确认',
191   - bgColor: '#F6F6F6',
192   - textColor: '#F6F6F6'
193   - },
194   - {
195   - index: 6,
196   - name: '清除已确认',
197   - bgColor: '#F6F6F6',
198   - textColor: '#F6F6F6'
  134 + type: 'CLEARED_ACK'
199 135 }
200 136 ],
201   - deviceType: [
  137 + typeStatus: [
202 138 {
203   - index: 1,
  139 + checked: true,
204 140 name: '全部',
205   - bgColor: '#377DFF',
206   - textColor: '#377DFF'
  141 + type: ''
207 142 },
208 143 {
209   - index: 2,
  144 + checked: false,
210 145 name: '网关设备',
211   - bgColor: '#F6F6F6',
212   - textColor: '#F6F6F6'
  146 + type: 'GATEWAY'
213 147 },
214 148 {
215   - index: 3,
  149 + checked: false,
216 150 name: '网关子设备',
217   - bgColor: '#F6F6F6',
218   - textColor: '#F6F6F6'
  151 + type: 'SENSOR'
219 152 },
220 153 {
221   - index: 4,
  154 + checked: false,
222 155 name: '直连设备',
223   - bgColor: '#F6F6F6',
224   - textColor: '#F6F6F6'
  156 + type: 'DIRECT_CONNECTION'
225 157 }
226 158 ],
227   - alertLevel: [
  159 + alarmLevelStatus: [
228 160 {
229   - index: 1,
  161 + checked: true,
230 162 name: '全部',
231   - bgColor: '#377DFF',
232   - textColor: '#377DFF'
  163 + type: ''
233 164 },
234 165 {
235   - index: 2,
  166 + checked: false,
236 167 name: '危险',
237   - bgColor: '#F6F6F6',
238   - textColor: '#F6F6F6'
  168 + type: 'CRITICAL'
239 169 },
240 170 {
241   - index: 3,
  171 + checked: false,
242 172 name: '重要',
243   - bgColor: '#F6F6F6',
244   - textColor: '#F6F6F6'
  173 + type: 'MAJOR'
245 174 },
246 175 {
247   - index: 4,
  176 + checked: false,
248 177 name: '次要',
249   - bgColor: '#F6F6F6',
250   - textColor: '#F6F6F6'
  178 + type: 'MINOR'
251 179 },
252 180 {
253   - index: 4,
  181 + checked: false,
254 182 name: '警告',
255   - bgColor: '#F6F6F6',
256   - textColor: '#F6F6F6'
  183 + type: 'WARNING'
257 184 },
258 185 {
259   - index: 4,
  186 + checked: false,
260 187 name: '不确定',
261   - bgColor: '#F6F6F6',
262   - textColor: '#F6F6F6'
  188 + type: 'INDETERMINATE'
263 189 }
264 190 ],
265   - timeArea: [
  191 + timeStatus: [
266 192 {
267   - index: 1,
  193 + checked: true,
268 194 name: '全部',
269   - value: '全部',
270   - bgColor: '#F6F6F6',
271   - textColor: '#F6F6F6'
  195 + type: ''
272 196 },
273 197 {
274   - index: 2,
  198 + checked: false,
275 199 name: '30分钟',
276   - value: '30',
277   - bgColor: '#F6F6F6',
278   - textColor: '#F6F6F6'
  200 + type: '1800000'
279 201 },
280 202 {
281   - index: 3,
282   - name: '1小时',
283   - value: '30',
284   - bgColor: '#F6F6F6',
285   - textColor: '#F6F6F6'
  203 + checked: false,
  204 + name: '一小时',
  205 + type: '3600000'
286 206 },
287 207 {
288   - index: 4,
  208 + checked: false,
289 209 name: '2小时',
290   - value: '120',
291   - bgColor: '#F6F6F6',
292   - textColor: '#F6F6F6'
  210 + type: '7200000'
293 211 },
294 212 {
295   - index: 5,
  213 + checked: false,
296 214 name: '近一天',
297   - value: '24',
298   - bgColor: '#F6F6F6',
299   - textColor: '#F6F6F6'
300   - },
301   - {
302   - index: 6,
303   - name: '',
304   - value: '',
305   - bgColor: '#F6F6F6',
306   - textColor: '#F6F6F6'
  215 + type: '1440000'
307 216 }
308 217 ],
309   - list: [
310   - {
311   - name1: '1号楼1楼三单元水表',
312   - name2: 'CO₂:65.32',
313   - name3: '告警状态:清除已确认',
314   - name4: '../../../static/danger.png',
315   - name5: '危险',
316   - time: '2022-04-01 02:12:23',
317   - id: 'xx1'
318   - },
319   - {
320   - name1: '2号楼1楼三单元水表',
321   - name2: 'PH:9.8',
322   - name3: '告警状态:激活未确认',
323   - name4: '../../../static/major.png',
324   - name5: '重要',
325   - time: '2022-04-01 02:12:23',
326   - id: 'xx2'
327   - },
328   - {
329   - name1: '3号楼1楼三单元水表',
330   - name2: 'NH3:600',
331   - name3: '告警状态:激活未确认',
332   - name4: '../../../static/secondary.png',
333   - name5: '次要',
334   - time: '2022-04-01 02:12:23',
335   - id: 'xx3'
336   - },
337   - {
338   - name1: '4号楼1楼三单元水表',
339   - name2: '水深:1.4',
340   - name3: '告警状态:激活未确认',
341   - name4: '../../../static/secondary.png',
342   - name5: '次要',
343   - time: '2022-04-01 02:12:23',
344   - id: 'xx4'
345   - },
346   - {
347   - name1: '5号楼1楼三单元水表',
348   - name2: 'COD:125',
349   - name3: '告警状态:激活未确认',
350   - name4: '../../../static/noshue.png',
351   - name5: '不确定',
352   - time: '2022-04-01 02:12:23',
353   - id: 'xx5'
354   - }
355   - ]
  218 + downOption: {
  219 + auto: false //是否在初始化后,自动执行downCallback; 默认true
  220 + },
  221 + page: {
  222 + num: 0,
  223 + size: 10
  224 + }
356 225 };
357 226 },
358   - onLoad(e) {
359   - // 隐藏原生的tabbar
360   - uni.hideTabBar();
361   - },
362 227 methods: {
363   - open() {},
  228 + /*下拉刷新的回调 */
  229 + downCallback() {
  230 + //联网加载数据
  231 + this.list = [];
  232 + this.page.num = 1;
  233 + this.loadData(this.page.num, {
  234 + deviceId: this.deviceId
  235 + });
  236 + },
  237 + /*上拉加载的回调: 其中page.num:当前页 从1开始, page.size:每页数据条数,默认10 */
  238 + upCallback() {
  239 + //联网加载数据
  240 + this.page.num += 1;
  241 + this.loadData(this.page.num, {
  242 + deviceId: this.deviceId
  243 + });
  244 + },
  245 + //获取告警数据
  246 + loadData(pageNo, params = {}) {
  247 + let httpData = {
  248 + ...params,
  249 + page: pageNo,
  250 + pageSize: 10
  251 + };
  252 + uni.$u.http
  253 + .get('/yt/alarm', {
  254 + params: httpData,
  255 + custom: {
  256 + load: false
  257 + }
  258 + })
  259 + .then(res => {
  260 + this.total = res.total;
  261 + uni.stopPullDownRefresh();
  262 + console.log('获取后端数据', res);
  263 + //方法一(推荐): 后台接口有返回列表的总页数 totalPage
  264 + this.mescroll.endByPage(res.items.length, res.total); //必传参数(当前页的数据个数, 总页数)
  265 + if (pageNo == 1) {
  266 + this.list = res.items;
  267 + } else {
  268 + this.list = this.list.concat(res.items);
  269 + }
  270 + })
  271 + .catch(() => {
  272 + //联网失败, 结束加载
  273 + this.mescroll.endErr();
  274 + });
  275 + },
  276 + handleClickTag(currentIndex, list) {
  277 + list.map((item, index) => {
  278 + item.checked = index === currentIndex;
  279 + });
  280 + },
  281 + resetFilter() {
  282 + const { alarmStatus, typeStatus, alarmLevelStatus, timeStatus } = this;
  283 + [alarmStatus, typeStatus, alarmLevelStatus, timeStatus].forEach(item => item.map((item, index) => (item.checked = index === 0)));
  284 + },
364 285 close() {
365 286 this.show = false;
366 287 },
... ... @@ -374,8 +295,41 @@ export default {
374 295 this.showCalendar = false;
375 296 this.timeData.selectTime = `${e[0]} / ${e[e.length - 1]}`;
376 297 },
  298 + confirmFilter() {
  299 + const alarmState = this.alarmStatus.find(item => item.checked);
  300 + const typeState = this.typeStatus.find(item => item.checked);
  301 + const alarmLevelState = this.alarmLevelStatus.find(item => item.checked);
  302 + const timeState = this.timeStatus.find(item => item.checked);
  303 + const endTs = Date.now();
  304 + const startTs = endTs - timeState.type;
  305 + this.loadData(1, {
  306 + status: alarmState.type ? alarmState.type : undefined,
  307 + deviceType: typeState.type ? typeState.type : undefined,
  308 + alarmType: alarmLevelState.type ? alarmLevelState.type : undefined,
  309 + startTime: timeState.type ? startTs : undefined,
  310 + endTime: timeState.type ? endTs : undefined,
  311 + deviceId: this.deviceId
  312 + });
  313 + this.show = false;
  314 + },
377 315 calendarClose() {
378 316 this.showCalendar = false;
  317 + },
  318 + openDeviceDetail(item) {
  319 + const { id, deviceName, severity, originatorType, details, createdTime, status } = item;
  320 + let obj = {
  321 + id,
  322 + deviceName,
  323 + severity,
  324 + originatorType,
  325 + details,
  326 + createdTime,
  327 + status
  328 + };
  329 + uni.navigateTo({
  330 + url: '/alarmSubPage/alarmDetailPage/alarmDetail?data=' + JSON.stringify(obj)
  331 + // url: '/' + JSON.stringify(obj)
  332 + });
379 333 }
380 334 }
381 335 };
... ... @@ -383,24 +337,39 @@ export default {
383 337
384 338 <style lang="scss" scoped>
385 339 .alert-page {
386   - margin-top: -39rpx;
387   -}
388   -.device-list {
389   - display: flex;
390   - flex-direction: column;
391   - padding-left: 18rpx;
392   - margin-top: -18rpx;
  340 + padding: 20rpx;
393 341 .list-item {
394   - width: 713rpx;
395   - height: 233rpx;
  342 + width: 690rpx;
  343 + height: 262rpx;
396 344 background-color: #fff;
397   - margin-top: 24rpx;
398   - display: flex;
399   -
400   - border-radius: 10px;
401   - justify-content: space-between;
  345 + border-radius: 20rpx;
  346 + margin: 20rpx auto;
  347 + color: #333;
402 348 .item {
403   - margin: 30rpx;
  349 + padding: 30rpx;
  350 + view {
  351 + font-size: 28rpx;
  352 + margin-bottom: 10rpx;
  353 + }
  354 + .time {
  355 + color: #999;
  356 + }
  357 + .item-first {
  358 + display: flex;
  359 + justify-content: space-between;
  360 + font-size: 30rpx;
  361 + font-weight: 500;
  362 + align-items: center;
  363 + .item-right {
  364 + display: flex;
  365 + align-items: center;
  366 + image {
  367 + width: 28rpx;
  368 + height: 28rpx;
  369 + margin-right: 10rpx;
  370 + }
  371 + }
  372 + }
404 373 }
405 374 }
406 375 }
... ...
... ... @@ -2,103 +2,148 @@
2 2 <view class="basic-page">
3 3 <!-- 公共组件-每个页面必须引入 -->
4 4 <public-module />
5   - <view class="u-flex" style="justify-content: space-between;height: 140rpx;background-color: #fff;border-radius: 18px;">
  5 + <view class="basic-title">
6 6 <view class="u-flex">
7   - <view style="margin-left: 20rpx;">
8   - {{deviceDetail.name}}
  7 + <view style="margin-left: 20rpx;">{{ deviceDetail.name }}</view>
  8 + <view
  9 + style="margin-left: 20rpx; font-size: 14px;"
  10 + :style="{ color: deviceDetail.deviceState === 'INACTIVE' ? '#666' : deviceDetail.deviceState === 'ONLINE' ? '#377DFF' : '#DE4437' }"
  11 + >
  12 + {{ deviceDetail.deviceState === 'INACTIVE' ? '待激活' : deviceDetail.deviceState === 'ONLINE' ? '在线' : '离线' }}
9 13 </view>
10   - <view style="margin-left: 20rpx; font-size: 14px;" :style="{color:deviceDetail.deviceState==='INACTIVE'?'#666':deviceDetail.deviceState==='ONLINE'?'#377DFF':'#DE4437'}">
11   - {{deviceDetail.deviceState==='INACTIVE'?'待激活':deviceDetail.deviceState==='ONLINE'?'在线':'离线'}}
12   - </view>
13   - </view>
14   - <view style="margin-right: 20rpx;">
15   - <u-button type="primary" shape="circle" size="mini" text="下发命令" @click="showModal"/>
16 14 </view>
  15 + <view style="margin-right: 20rpx;"><u-button type="primary" shape="circle" size="mini" text="下发命令" @click="showModal" /></view>
17 16 </view>
18   - <view style="margin-top: 40rpx;height: 577rpx;background-color: #fff;border-radius: 20px;">
19   - <u-list>
20   - <u-list-item>
21   -
22   - <u-cell :title="deviceDetail.sn">
23   - <view slot="icon">设备编号</view>
24   - </u-cell>
25   - </u-list-item>
26   - <u-list-item>
27   - <u-cell :title="deviceType">
28   - <view slot="icon">设备类型</view>
29   - </u-cell>
30   - </u-list-item>
31   - <u-list-item>
32   - <u-cell :title="deviceDetail.organizationDTO.name">
33   - <view slot="icon">所属组织</view>
34   - </u-cell>
35   - </u-list-item>
36   - <u-list-item>
37   - <u-cell :title="formatLastOnlineTime">
38   - <view slot="icon">最后连接时间</view>
39   - </u-cell>
40   - </u-list-item>
41   - <u-list-item>
42   - <u-cell :title="alarmStatus">
43   - <view slot="icon">是否告警</view>
44   - </u-cell>
45   - </u-list-ite>
46   - <u-cell :title="deviceDetail.description">
47   - <view slot="icon">设备描述</view>
48   - </u-cell>
49   - </u-list-item>
50   - </u-list>
  17 + <view class="detail">
  18 + <view class="detail-item">
  19 + <view class="detail-label">设备编号</view>
  20 + <view class="detail-value">{{ deviceDetail.sn }}</view>
  21 + </view>
  22 + <u-line length="90%" margin="0 auto"></u-line>
  23 + <view class="detail-item">
  24 + <view class="detail-label">设备类型</view>
  25 + <view class="detail-value">{{ deviceType }}</view>
  26 + </view>
  27 + <u-line length="90%" margin="0 auto"></u-line>
  28 + <view class="detail-item">
  29 + <view class="detail-label">所属组织</view>
  30 + <view class="detail-value">{{ deviceDetail.organizationDTO.name }}</view>
  31 + </view>
  32 + <u-line length="90%" margin="0 auto"></u-line>
  33 + <view class="detail-item">
  34 + <view class="detail-label">最后连接时间</view>
  35 + <view class="detail-value">{{ formatLastOnlineTime }}</view>
  36 + </view>
  37 + <u-line length="90%" margin="0 auto"></u-line>
  38 + <view class="detail-item">
  39 + <view class="detail-label">是否告警</view>
  40 + <view class="detail-value">{{ alarmStatus }}</view>
  41 + </view>
  42 + <u-line length="90%" margin="0 auto"></u-line>
  43 + <view class="detail-item">
  44 + <view class="detail-label">设备描述</view>
  45 + <view class="detail-value">{{ deviceDetail.description }}</view>
  46 + </view>
51 47 </view>
52   - <!-- 下发指令 -->
53   - <u-modal :show="showModel" title="命令下发" closeOnClickOverlay showCancelButton @close="hiddenModal" @cancel="hiddenModal" @confirm="handleConfirm" >
54   - <u--textarea placeholder="请输入命令内容" v-model="formModel.intro" count />
  48 +
  49 + <!-- 下发命令 -->
  50 + <u-modal :show="showModel" closeOnClickOverlay showCancelButton width="375px" @close="hiddenModal" @cancel="hiddenModal" @confirm="handleConfirm">
  51 + <view>
  52 + <view class="u-flex" style="align-items: center;">
  53 + <text style="color: #333; font-size: 28rpx;margin-right: 10rpx;">下发类型:</text>
  54 + <u-radio-group v-model="value" placement="row" style="margin-left: 10rpx;" size="20">
  55 + <u-radio activeColor="#3388FF" label="OneWay"></u-radio>
  56 + <u-radio activeColor="#3388FF" label="TwoWay"></u-radio>
  57 + </u-radio-group>
  58 + </view>
  59 + <view style="margin-top: 28rpx;"><u--textarea placeholder="请输入命令内容" v-model="formModel.intro" /></view>
  60 + </view>
55 61 </u-modal>
56 62 </view>
57 63 </template>
58 64
59 65 <script>
60   -import {formatToDate} from '@/plugins/utils.js';
  66 +import { formatToDate } from '@/plugins/utils.js';
61 67 export default {
62   - props:{
63   - deviceDetail:{
64   - type:Object,
65   - default:()=>({}),
  68 + props: {
  69 + deviceDetail: {
  70 + type: Object,
  71 + default: () => ({})
66 72 }
67 73 },
68 74 data() {
69 75 return {
70   - showModel: false,
  76 + showModel: false
71 77 };
72 78 },
73   - computed:{
74   - deviceType(){
75   - return this.deviceDetail.deviceType==='DIRECT_CONNECTION'?'直连设备':this.deviceDetail.deviceType==='GATEWAY'?'网关设备':this.deviceDetail.deviceType==='SENSOR'?'网关子设备':''
  79 + computed: {
  80 + deviceType() {
  81 + return this.deviceDetail.deviceType === 'DIRECT_CONNECTION'
  82 + ? '直连设备'
  83 + : this.deviceDetail.deviceType === 'GATEWAY'
  84 + ? '网关设备'
  85 + : this.deviceDetail.deviceType === 'SENSOR'
  86 + ? '网关子设备'
  87 + : '';
76 88 },
77   - alarmStatus(){
78   - return this.deviceDetail.alarmStatus === '0'?'否':'是'
  89 + alarmStatus() {
  90 + return this.deviceDetail.alarmStatus === '0' ? '否' : '是';
79 91 },
80   - formatLastOnlineTime(){
81   - return formatToDate(Number(this.deviceDetail.lastOnlineTime),'YYYY-MM-DD HH:mm:ss')
  92 + formatLastOnlineTime() {
  93 + return formatToDate(Number(this.deviceDetail.lastOnlineTime), 'YYYY-MM-DD HH:mm:ss');
82 94 }
83 95 },
84 96 onLoad(e) {
85 97 // 隐藏原生的tabbar
86 98 uni.hideTabBar();
87 99 },
88   - onMounted(){
89   - console.log(this.deviceDetail)
90   -
  100 + onMounted() {
  101 + console.log(this.deviceDetail);
91 102 },
92 103 methods: {
93 104 showModal() {
94 105 this.showModel = true;
95 106 },
96   - hiddenModal(){
  107 + hiddenModal() {
97 108 this.showModel = false;
98 109 },
99   - handleConfirm(){
100   - console.log('确定')
  110 + handleConfirm() {
  111 + console.log('确定');
101 112 }
102 113 }
103 114 };
104 115 </script>
  116 +
  117 +<style lang="scss" scoped>
  118 +.basic-page {
  119 + padding: 0 30rpx;
  120 + .basic-title {
  121 + display: flex;
  122 + justify-content: space-between;
  123 + align-items: center;
  124 + height: 140rpx;
  125 + background-color: #fff;
  126 + border-radius: 20rpx;
  127 + }
  128 + .detail {
  129 + background-color: #fff;
  130 + margin-top: 30rpx;
  131 + border-radius: 20rpx;
  132 + width: 690rpx;
  133 + .detail-item {
  134 + padding: 30rpx;
  135 + display: flex;
  136 + align-items: center;
  137 + .detail-label {
  138 + color: #333;
  139 + font-size: 30rpx;
  140 + }
  141 + .detail-value {
  142 + color: #666;
  143 + font-size: 28rpx;
  144 + margin-left: 30rpx;
  145 + }
  146 + }
  147 + }
  148 +}
  149 +</style>
... ...
1   -<template>
2   - <view class="alert-page">
3   - <view style="width: 192rpx;margin: 19rpx;"><u-button @click="openSearchDialog" shape="circle" type="info" icon="search" text="筛选"></u-button></view>
4   - <!-- 公共组件-每个页面必须引入 -->
5   - <public-module></public-module>
6   - <view class="device-list">
7   - <view @click="openAlertDetail(item.id)" class="list-item" v-for="(item, index) in list" :key="index">
8   - <view class="u-flex item" style="margin-top: 48rpx;justify-content: flex-start;flex-direction: column;align-items: center;">
9   - <view style="width: 400rpx;text-align: left;">
10   - <text style="color:#333333;font-size: 15px;">{{ item.name1 }}</text>
11   - </view>
12   - <view style="width: 400rpx;text-align: left;">
13   - <text style="color:#666666;font-size: 15px;">{{ item.name2 }}</text>
14   - </view>
15   - <view style="width: 400rpx;text-align: left;">
16   - <text style="color:#999999;font-size: 15px;">{{ item.time }}</text>
17   - </view>
18   - </view>
19   - <view class="item">
20   - <view class="u-flex" style="margin-top: 28rpx;flex-direction: column;justify-content: space-between;">
21   - <view style="text-align:center;line-height:30rpx;width: 100rpx;height: 40rpx;background-color: #377DFF;">
22   - <text style="color: #FFFFFF;font-size: 11px;">{{ item.name3 }}</text>
23   - </view>
24   - <view style="text-align:center;line-height:30rpx;margin-top: 10rpx;width: 100rpx;height: 40rpx;background-color: #377DFF;">
25   - <text style="color: #FFFFFF;font-size: 11px;">{{ item.name4 }}</text>
26   - </view>
27   - </view>
28   - </view>
29   - </view>
30   - </view>
31   - <view style="height: 20rpx;"></view>
32   - <!-- 告警筛选 -->
33   - <u-popup @close="close" closeable bgColor="transparent" :overlay="true" :show="show" mode="bottom">
34   - <view style="height: 1100rpx;background:#FFFFFF;border-radius: 20rpx;overflow-y: scroll;">
35   - <view style="text-align: center;position: relative;top: 68rpx;margin-top: -40rpx;"><text style="font-size: 16px;color: #333333;">筛选条件</text></view>
36   - <view style="margin-top: 97rpx;margin-left: 43rpx;">
37   - <view style="width: 750rpx;margin-left: 14rpx;" class=""><text style="color: #333333;font-size: 14px;">告警状态</text></view>
38   - <view
39   - class="u-flex"
40   - style="margin-top: 15rpx;width:650rpx;height: 60rpx;flex-direction: row;
41   - flex-wrap: wrap;justify-content: space-between; align-content: space-between;"
42   - >
43   - <view
44   - v-for="(item, index) in alertStatus"
45   - :key="index"
46   - style="margin: 10rpx;line-height: 50rpx;text-align: center;
47   - width:180rpx;height: 60rpx;
48   - background-color:#F6F6F6;border-radius:32px"
49   - >
50   - <text style="color:#333333;font-size: 13px;">{{ item.name }}</text>
51   - </view>
52   - </view>
53   - </view>
54   - <view style="margin-top: 145rpx;margin-left: 43rpx;">
55   - <view style="width: 750rpx;margin-left: 14rpx;" class=""><text style="color: #333333;font-size: 14px;">设备类型</text></view>
56   - <view
57   - class="u-flex"
58   - style="margin-top: 15rpx;width:650rpx;height: 60rpx;flex-direction: row;
59   - flex-wrap: wrap;justify-content: space-between; align-content: space-between;"
60   - >
61   - <view
62   - v-for="(item, index) in deviceType"
63   - :key="index"
64   - style="margin: 10rpx;line-height: 50rpx;text-align: center;
65   - width:180rpx;height: 60rpx;
66   - background-color:#F6F6F6;border-radius:32px"
67   - >
68   - <text style="color:#333333;font-size: 13px;">{{ item.name }}</text>
69   - </view>
70   - </view>
71   - </view>
72   - <view style="margin-top: 136rpx;margin-left: 43rpx;">
73   - <view style="width: 750rpx;margin-left: 14rpx;" class=""><text style="color: #333333;font-size: 14px;">告警等级</text></view>
74   - <view
75   - class="u-flex"
76   - style="margin-top: 15rpx;width:650rpx;height: 60rpx;flex-direction: row;
77   - flex-wrap: wrap;justify-content: space-between; align-content: space-between;"
78   - >
79   - <view
80   - v-for="(item, index) in alertLevel"
81   - :key="index"
82   - style="margin: 10rpx;line-height: 50rpx;text-align: center;
83   - width:180rpx;height: 60rpx;
84   - background-color:#F6F6F6;border-radius:32px"
85   - >
86   - <text style="color:#333333;font-size: 13px;">{{ item.name }}</text>
87   - </view>
88   - </view>
89   - </view>
90   - <view style="margin-top: 136rpx;margin-left: 43rpx;">
91   - <view style="width: 750rpx;margin-left: 14rpx;" class=""><text style="color: #333333;font-size: 14px;">选择时间</text></view>
92   - <view
93   - class="u-flex"
94   - style="margin-top: 15rpx;width:650rpx;height: 60rpx;flex-direction: row;
95   - flex-wrap: wrap;justify-content: space-between; align-content: space-between;"
96   - >
97   - <view
98   - v-for="(item, index) in timeArea"
99   - :key="index"
100   - style="margin: 10rpx;line-height: 50rpx;text-align: center;
101   - width:180rpx;height: 60rpx;
102   - background-color:#F6F6F6;border-radius:32px"
103   - >
104   - <text style="color:#333333;font-size: 13px;">{{ item.name }}</text>
105   - </view>
106   - </view>
107   - </view>
108   - <view style="margin-top: 136rpx;margin-left: 43rpx;">
109   - <view class="u-flex" style="margin-left: 10rpx;margin-top: 15rpx;width:750rpx;height: 60rpx;flex-direction: row;">
110   - <u--form labelPosition="left" :model="timeData" :rules="rules" ref="form1" style="padding-left: 26rpx;width: 617rpx!important;">
111   - <u-form-item
112   - style="font-size: 14px;"
113   - label="选择日期"
114   - prop="selectTime"
115   - labelWidth="80"
116   - borderBottom
117   - @click="
118   - showCalendar = true;
119   - hideKeyboard();
120   - "
121   - >
122   - <u--input v-model="timeData.selectTime" placeholder="请选择日期" border="none"></u--input>
123   - </u-form-item>
124   - </u--form>
125   - </view>
126   - </view>
127   - <view class="u-flex" style="flex-direction: row;margin-top: 128rpx;margin-left: 55rpx;">
128   - <view style="width: 300rpx"><u-button type="info" shape="circle" text="重置"></u-button></view>
129   - <view style="width: 300rpx;margin-left:46rpx ;"><u-button type="primary" shape="circle" text="确认"></u-button></view>
130   - </view>
131   - <view style="height: 30rpx;"></view>
132   - </view>
133   - </u-popup>
134   - <u-calendar
135   - :show="showCalendar"
136   - mode="range"
137   - @confirm="calendarConfirm"
138   - @close="calendarClose"
139   - startText="开始时间"
140   - endText="结束时间"
141   - confirmDisabledText="请选择日期"
142   - :formatter="formatter"
143   - ></u-calendar>
144   -
145   - </view>
146   -</template>
147   -
148   -<script>
149   -import fTabbar from '@/components/module/f-tabbar/f-tabbar';
150   -
151   -export default {
152   - components: {
153   - fTabbar
154   - },
155   - data() {
156   - return {
157   - show: false,
158   - timeData: {
159   - selectTime: '',
160   - getTimeGap: ''
161   - },
162   - showCalendar: false,
163   - show: false,
164   - alertStatus: [
165   - {
166   - index: 1,
167   - name: '全部',
168   - bgColor: '#377DFF',
169   - textColor: '#377DFF'
170   - },
171   - {
172   - index: 2,
173   - name: '激活未确认',
174   - bgColor: '#F6F6F6',
175   - textColor: '#F6F6F6'
176   - },
177   - {
178   - index: 3,
179   - name: '激活已确认',
180   - bgColor: '#F6F6F6',
181   - textColor: '#F6F6F6'
182   - },
183   - {
184   - index: 4,
185   - name: '清除未确认',
186   - bgColor: '#F6F6F6',
187   - textColor: '#F6F6F6'
188   - },
189   - {
190   - index: 5,
191   - name: '清除已确认',
192   - bgColor: '#F6F6F6',
193   - textColor: '#F6F6F6'
194   - },
195   - {
196   - index: 6,
197   - name: '清除已确认',
198   - bgColor: '#F6F6F6',
199   - textColor: '#F6F6F6'
200   - }
201   - ],
202   - deviceType: [
203   - {
204   - index: 1,
205   - name: '全部',
206   - bgColor: '#377DFF',
207   - textColor: '#377DFF'
208   - },
209   - {
210   - index: 2,
211   - name: '网关设备',
212   - bgColor: '#F6F6F6',
213   - textColor: '#F6F6F6'
214   - },
215   - {
216   - index: 3,
217   - name: '网关子设备',
218   - bgColor: '#F6F6F6',
219   - textColor: '#F6F6F6'
220   - },
221   - {
222   - index: 4,
223   - name: '直连设备',
224   - bgColor: '#F6F6F6',
225   - textColor: '#F6F6F6'
226   - }
227   - ],
228   - alertLevel: [
229   - {
230   - index: 1,
231   - name: '全部',
232   - bgColor: '#377DFF',
233   - textColor: '#377DFF'
234   - },
235   - {
236   - index: 2,
237   - name: '危险',
238   - bgColor: '#F6F6F6',
239   - textColor: '#F6F6F6'
240   - },
241   - {
242   - index: 3,
243   - name: '重要',
244   - bgColor: '#F6F6F6',
245   - textColor: '#F6F6F6'
246   - },
247   - {
248   - index: 4,
249   - name: '次要',
250   - bgColor: '#F6F6F6',
251   - textColor: '#F6F6F6'
252   - },
253   - {
254   - index: 4,
255   - name: '警告',
256   - bgColor: '#F6F6F6',
257   - textColor: '#F6F6F6'
258   - },
259   - {
260   - index: 4,
261   - name: '不确定',
262   - bgColor: '#F6F6F6',
263   - textColor: '#F6F6F6'
264   - }
265   - ],
266   - timeArea: [
267   - {
268   - index: 1,
269   - name: '全部',
270   - value: '全部',
271   - bgColor: '#F6F6F6',
272   - textColor: '#F6F6F6'
273   - },
274   - {
275   - index: 2,
276   - name: '30分钟',
277   - value: '30',
278   - bgColor: '#F6F6F6',
279   - textColor: '#F6F6F6'
280   - },
281   - {
282   - index: 3,
283   - name: '1小时',
284   - value: '30',
285   - bgColor: '#F6F6F6',
286   - textColor: '#F6F6F6'
287   - },
288   - {
289   - index: 4,
290   - name: '2小时',
291   - value: '120',
292   - bgColor: '#F6F6F6',
293   - textColor: '#F6F6F6'
294   - },
295   - {
296   - index: 5,
297   - name: '近一天',
298   - value: '24',
299   - bgColor: '#F6F6F6',
300   - textColor: '#F6F6F6'
301   - },
302   - {
303   - index: 6,
304   - name: '',
305   - value: '',
306   - bgColor: '#F6F6F6',
307   - textColor: '#F6F6F6'
308   - }
309   - ],
310   - list: [
311   - {
312   - name1: '1号楼1楼三单元水表',
313   - name2: '下发命令:MQTT命令',
314   - time: '2022-04-01 02:12:23',
315   - id: 'xx1',
316   - name3: '下发成功',
317   - name4: '响应成功'
318   - },
319   - {
320   - name1: '1号楼1楼三单元水表',
321   - name2: '下发命令:MQTT命令',
322   - time: '2022-04-01 02:12:23',
323   - id: 'xx1',
324   - name3: '下发成功',
325   - name4: '响应成功'
326   - },
327   - {
328   - name1: '1号楼1楼三单元水表',
329   - name2: '下发命令:MQTT命令',
330   - time: '2022-04-01 02:12:23',
331   - id: 'xx1',
332   - name3: '下发成功',
333   - name4: '响应成功'
334   - },
335   - {
336   - name1: '1号楼1楼三单元水表',
337   - name2: '下发命令:MQTT命令',
338   - time: '2022-04-01 02:12:23',
339   - id: 'xx1',
340   - name3: '下发成功',
341   - name4: '响应成功'
342   - },
343   - {
344   - name1: '1号楼1楼三单元水表',
345   - name2: '下发命令:MQTT命令',
346   - time: '2022-04-01 02:12:23',
347   - id: 'xx1',
348   - name3: '下发成功',
349   - name4: '响应成功'
350   - }
351   - ]
352   - };
353   - },
354   - onLoad(e) {
355   - // 隐藏原生的tabbar
356   - uni.hideTabBar();
357   - },
358   - methods: {
359   - open() {},
360   - close() {
361   - this.show = false;
362   - },
363   - openSearchDialog() {
364   - this.show = true;
365   - },
366   - hideKeyboard() {
367   - uni.hideKeyboard();
368   - },
369   - calendarConfirm(e) {
370   - this.showCalendar = false;
371   - this.timeData.selectTime = `${e[0]} / ${e[e.length - 1]}`;
372   - },
373   - calendarClose() {
374   - this.showCalendar = false;
375   - }
376   - }
377   -};
378   -</script>
379   -
380   -<style lang="scss" scoped>
381   -.alert-page {
382   - margin-top: 5rpx;
383   -}
384   -.device-list {
385   - display: flex;
386   - flex-direction: column;
387   - padding-left: 18rpx;
388   - .list-item {
389   - width: 713rpx;
390   - height: 233rpx;
391   - background-color: #fff;
392   - margin-top: 24rpx;
393   - display: flex;
394   - flex-direction: row;
395   - border-radius: 10px;
396   - justify-content: space-between;
397   - .item {
398   - margin: 30rpx;
399   - }
400   - }
401   -}
402   -</style>
... ... @@ -20,7 +20,13 @@
20 20 </u-form-item>
21 21 <u-form-item @click="openType"><u-input shape="circle" v-model="timeData.getType" placeholder="请选择属性" disabled disabledColor="#377DFF0D" /></u-form-item>
22 22 </u-form>
23   - <view class="charts-box"><qiun-data-charts type="area" :chartData="chartData" :opts="{ xAxis: { disabled: true }, legend: { show: false } }" /></view>
  23 + <view class="charts-box" v-if="historyData.length"><qiun-data-charts type="area" :chartData="chartData" :opts="{ xAxis: { disabled: true }, legend: { show: false } }" /></view>
  24 + <view v-else style="display: flex;justify-content: center; align-items: center;">
  25 + <view>
  26 + <image src="../../../static/empty.png" style="width: 160rpx;height: 160rpx;" />
  27 + <view style="text-align: center; color:#e8e8e8;padding-bottom: 30rpx;">暂无数据</view>
  28 + </view>
  29 + </view>
24 30 </view>
25 31 <view class="historyData-bottom">
26 32 <view class="table">
... ... @@ -28,10 +34,16 @@
28 34 <view class="th">变量值</view>
29 35 <view class="th">更新时间</view>
30 36 </view>
31   - <view class="tr bg-g" v-for="(item, index) in historyData" :key="index">
  37 + <view class="tr bg-g" :class="{ odd: index % 2 === 1 }" v-for="(item, index) in historyData" :key="index">
32 38 <view class="td">{{ item.value }}</view>
33 39 <view class="td">{{ item.ts }}</view>
34 40 </view>
  41 + <view v-if="!historyData.length" style="display: flex;justify-content: center">
  42 + <view>
  43 + <image src="../../../static/empty.png" style="width: 160rpx;height: 160rpx;" />
  44 + <view style="text-align: center; color:#e8e8e8;padding-bottom: 30rpx;">暂无数据</view>
  45 + </view>
  46 + </view>
35 47 </view>
36 48 </view>
37 49 <u-calendar
... ... @@ -64,7 +76,7 @@
64 76 <script>
65 77 import fTabbar from '@/components/module/f-tabbar/f-tabbar';
66 78 import qiunDataCharts from '@/uni_modules/qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue';
67   -import { getHistroyData } from '@/pages/device/api/index.js';
  79 +import { getHistroyData } from '../api/index.js';
68 80 import { formatToDate } from '@/plugins/utils.js';
69 81 const d = new Date();
70 82 const year = d.getFullYear();
... ... @@ -100,12 +112,20 @@ export default {
100 112 entityId: {
101 113 type: String,
102 114 required: true
  115 + },
  116 + start: {
  117 + type: String,
  118 + required: true
  119 + },
  120 + end: {
  121 + type: String,
  122 + required: true
103 123 }
104 124 },
105 125 data() {
106 126 return {
107   - startTs: '',
108   - endTs: '',
  127 + startTs: this.start,
  128 + endTs: this.end,
109 129 showCalendar: false,
110 130 showTimeGap: false,
111 131 showSelectType: false,
... ... @@ -156,10 +176,21 @@ export default {
156 176 }
157 177 };
158 178 },
159   - onReady() {
160   - setTimeout(() => {
161   - console.log(this.chartData);
162   - });
  179 + watch: {
  180 + historyData(newValue) {
  181 + if (!newValue.length) {
  182 + this.chartData.categories = [];
  183 + this.chartData.series = [];
  184 + } else {
  185 + this.chartData.categories = newValue.map(item => item.ts);
  186 + this.chartData.series = [
  187 + {
  188 + name: this.keys[0][0],
  189 + data: this.historyData.map(item => Number(item.value))
  190 + }
  191 + ];
  192 + }
  193 + }
163 194 },
164 195 methods: {
165 196 // 动态生成Columns
... ...
1   -<template>
2   - <view class="realtime-page">
3   - <!-- 公共组件-每个页面必须引入 -->
4   - <public-module></public-module>
5   - <view class="u-flex" style="margin-top: -44rpx;flex-direction: column;justify-content: space-between; align-content: space-between;">
6   - <view
7   - class="u-flex"
8   - v-for="(item, index) in list"
9   - :key="index"
10   - style="border-radius: 20px;flex-direction: row;justify-content: space-between;margin: 15rpx;
11   - background-color: #fff;height: 200rpx;width: 698rpx;"
12   - >
13   - <view style="margin: 20rpx;">
14   - <view style="margin-top: 4rpx;">
15   - <text style="color:#333333;font-size: 16px;">{{ item.name }}</text>
16   - </view>
17   - <view style="margin-top: 14rpx;">
18   - <text style="color:#999999;font-size: 13px;">{{ item.time }}</text>
19   - </view>
20   - </view>
21   - <view style="margin-right: 30rpx;margin-top: -58rpx;">
22   - <text style="color:#333333;font-size: 17px;">{{ item.value }}</text>
23   - </view>
24   - </view>
25   - </view>
26   - </view>
27   -</template>
28   -
29   -<script>
30   -import fTabbar from '@/components/module/f-tabbar/f-tabbar';
31   -export default {
32   - components: {
33   - fTabbar
34   - },
35   - data() {
36   - return {
37   - list: [
38   - {
39   - name: 'CO2',
40   - time: '2021-12-25 14:25:52',
41   - value: '85.6'
42   - },
43   - {
44   - name: 'PH',
45   - time: '2021-12-25 14:25:52',
46   - value: '10'
47   - },
48   - {
49   - name: 'NH3',
50   - time: '2021-12-25 14:25:52',
51   - value: '635'
52   - },
53   - {
54   - name: '水深',
55   - time: '2021-12-25 14:25:52',
56   - value: '2.21'
57   - }
58   - ]
59   - };
60   - },
61   - onLoad(e) {
62   - // 隐藏原生的tabbar
63   - uni.hideTabBar();
64   - }
65   -};
66   -</script>
67   -
68   -<style lang="scss" scoped>
69   -.realtime-page {
70   - padding: 20rpx;
71   -}
  1 +<template>
  2 + <view class="realtime-page">
  3 + <view class="item" v-for="(item, index) in recordList" :key="index">
  4 + <view class="item-top">
  5 + <view>{{ item.key }}</view>
  6 + <view>{{ item.value }}</view>
  7 + </view>
  8 + <view class="item-time">{{ item.time }}</view>
  9 + </view>
  10 + </view>
  11 +</template>
  12 +
  13 +<script>
  14 +export default {
  15 + props: {
  16 + recordList: {
  17 + type: Array,
  18 + default: () => []
  19 + }
  20 + }
  21 +};
  22 +</script>
  23 +
  24 +<style lang="scss" scoped>
  25 +.realtime-page {
  26 + .item {
  27 + margin: 30rpx;
  28 + padding: 30rpx;
  29 + border-radius: 20rpx;
  30 + background-color: #fff;
  31 + height: 160rpx;
  32 + width: 690rpx;
  33 + .item-top {
  34 + display: flex;
  35 + justify-content: space-between;
  36 + color: #333;
  37 + font-size: 32rpx;
  38 + font-family: PingFangSC-Medium, PingFang SC;
  39 + font-weight: 500;
  40 + }
  41 + .item-time {
  42 + margin-top: 4rpx;
  43 + font-size: 26rpx;
  44 + color: #999;
  45 + }
  46 + }
  47 +}
72 48 </style>
... ...
... ... @@ -3,10 +3,7 @@
3 3 "version": "1.0.0",
4 4 "description": "### 项目结构",
5 5 "main": "main.js",
6   - "scripts": {
7   - "test": "echo \"Error: no test specified\" && exit 1",
8   - "dev:mp-wenxin": "cross-env NODE_ENV=development UNI_PLATFORM=mp-weixin vue-cli-service uni-build --watch --minimize"
9   - },
  6 + "scripts": {},
10 7 "repository": {
11 8 "type": "git",
12 9 "url": "http://git.yuntengiot.com/huang/thingskit-app.git"
... ...
... ... @@ -14,12 +14,6 @@
14 14 "navigationBarTitleText": "设备"
15 15 }
16 16 },
17   - // {
18   - // "path": "pages/device/deviceDetail",
19   - // "style": {
20   - // "navigationBarTitleText": "设备详情"
21   - // }
22   - // },
23 17 {
24 18 "path": "pages/device/org/org",
25 19 "style": {
... ... @@ -85,6 +79,12 @@
85 79 "style": {
86 80 "navigationBarTitleText": "设备详情"
87 81 }
  82 + },
  83 + {
  84 + "path": "deviceDetailPage/tabDetail/CommandDetail",
  85 + "style": {
  86 + "navigationBarTitleText": "命令详情"
  87 + }
88 88 }]
89 89 },
90 90 {
... ...
1 1 <template>
2   - <view class="device-page">
3   - <f-navbar>
4   - <view slot="left">
5   - <view style="width: 580rpx"
6   - ><u--input
7   - prefixIcon="search"
8   - placeholder="输入设备SN或名称搜索"
9   - border="surround"
10   - shape="circle"
11   - @change="inputChanged"
12   - ></u--input
13   - ></view>
14   - </view>
15   - <view @click="openSearchDialog" slot="right" class="u-flex">
16   - <text style="color: #333; font-size: 14px">筛选</text>
17   - <image
18   - style="width: 40rpx; height: 40rpx"
19   - src="../../static/shaixuan.png"
20   - />
21   - </view>
22   - </f-navbar>
23   - <!-- 公共组件-每个页面必须引入 -->
24   - <public-module></public-module>
25   - <view class="org-sty" @click="openOrg">
26   - <view class="org-item">
27   - <view class="u-flex" style="margin-top: 26rpx; margin-left: 15rpx"
28   - ><text style="color: #333; font-size: 15px; margin-left: 14rpx"
29   - >组织关系</text
30   - ></view
31   - >
32   - <view
33   - style="margin-top: 20rpx; margin-left: 15rpx"
34   - class="u-flex"
35   - v-if="total"
36   - >
37   - <image
38   - style="margin-left: 14rpx; width: 30rpx; height: 30rpx"
39   - src="../../static/org.png"
40   - />
41   - <text style="margin-left: 10rpx; color: #666; font-size: 12px"
42   - >设备数 : {{ total }}</text
43   - >
44   - </view>
45   - </view>
46   - <view class="org-item">
47   - <image
48   - style="
  2 + <view class="device-page">
  3 + <f-navbar>
  4 + <view slot="left">
  5 + <view style="width: 580rpx"><u--input prefixIcon="search" placeholder="输入设备SN或名称搜索" border="surround" shape="circle" @change="inputChanged"></u--input></view>
  6 + </view>
  7 + <view @click="openSearchDialog" slot="right" class="u-flex">
  8 + <text style="color: #333; font-size: 14px">筛选</text>
  9 + <image style="width: 40rpx; height: 40rpx" src="../../static/shaixuan.png" />
  10 + </view>
  11 + </f-navbar>
  12 + <!-- 公共组件-每个页面必须引入 -->
  13 + <public-module></public-module>
  14 + <view class="org-sty" @click="openOrg">
  15 + <view class="org-item">
  16 + <view class="u-flex" style="margin-top: 26rpx; margin-left: 15rpx"><text style="color: #333; font-size: 15px; margin-left: 14rpx">组织关系</text></view>
  17 + <view style="margin-top: 20rpx; margin-left: 15rpx" class="u-flex" v-if="total">
  18 + <image style="margin-left: 14rpx; width: 30rpx; height: 30rpx" src="../../static/org.png" />
  19 + <text style="margin-left: 10rpx; color: #666; font-size: 12px">设备数 : {{ total }}</text>
  20 + </view>
  21 + </view>
  22 + <view class="org-item">
  23 + <image
  24 + style="
49 25 width: 6px;
50 26 height: 10px;
51 27 float: right;
52 28 margin-right: 34rpx;
53 29 margin-top: 58rpx;
54 30 "
55   - src="../../static/right-arrow.png"
56   - />
57   - </view>
58   - </view>
59   - <mescroll-body
60   - ref="mescrollRef"
61   - @init="mescrollInit"
62   - :down="downOption"
63   - @down="downCallback"
64   - @up="upCallback"
65   - >
66   - <view class="device-list">
67   - <view
68   - @click="
69   - openDeviceDetail(
70   - item.id,
71   - item.alarmStatus,
72   - item.lastOnlineTime,
73   - item.tbDeviceId
74   - )
75   - "
76   - class="list-item"
77   - v-for="item in list"
78   - :key="item.id"
79   - >
80   - <view
81   - class="u-flex item"
82   - style="
  31 + src="../../static/right-arrow.png"
  32 + />
  33 + </view>
  34 + </view>
  35 + <mescroll-body ref="mescrollRef" @init="mescrollInit" :down="downOption" @down="downCallback" @up="upCallback">
  36 + <view class="device-list">
  37 + <view @click="openDeviceDetail(item.id, item.alarmStatus, item.lastOnlineTime, item.tbDeviceId)" class="list-item" v-for="item in list" :key="item.id">
  38 + <view
  39 + class="u-flex item"
  40 + style="
83 41 justify-content: flex-start;
84 42 flex-direction: column;
85 43 align-items: center;
86 44 "
87   - >
88   - <view style="width: 450rpx; text-align: left">
89   - <text style="color: #333; font-size: 15px">{{
90   - item.name ? `设备名称:${item.name}` : ""
91   - }}</text>
92   - </view>
93   - <view style="width: 450rpx; text-align: left; margin-top: 10rpx">
94   - <text style="color: #666; font-size: 15px">{{
95   - item.sn ? `设备编号:${item.sn}` : ""
96   - }}</text>
97   - </view>
98   - <view style="width: 450rpx; text-align: left; margin-top: 10rpx">
99   - <text style="color: #666; font-size: 15px">{{
100   - item.organizationDTO.name
101   - ? `所属组织:${item.organizationDTO.name}`
102   - : ""
103   - }}</text>
104   - </view>
105   - </view>
106   - <view class="item">
107   - <view class="u-flex" style="margin-top: -6rpx">
108   - <image
109   - style="
  45 + >
  46 + <view style="width: 450rpx; text-align: left">
  47 + <text style="color: #333; font-size: 15px">{{ item.name }}</text>
  48 + </view>
  49 + <view style="width: 450rpx; text-align: left; margin-top: 10rpx">
  50 + <view style="color: #666; font-size: 15px;display: flex;">
  51 + 设备编号:
  52 + <view style="margin-left:16rpx">{{ item.sn }}</view>
  53 + </view>
  54 + </view>
  55 + <view style="width: 450rpx; text-align: left; margin-top: 10rpx">
  56 + <view style="color: #666; font-size: 15px;display: flex;">
  57 + 所属组织:
  58 + <view style="margin-left:16rpx">{{ item.organizationDTO.name }}</view>
  59 + </view>
  60 + </view>
  61 + </view>
  62 + <view class="item">
  63 + <view class="u-flex" style="margin-top: -6rpx">
  64 + <image
  65 + style="
110 66 width: 30rpx;
111 67 height: 30rpx;
112 68 margin-top: 5rpx;
113 69 margin-right: 5rpx;
114 70 "
115   - :src="
116   - item.deviceState === 'ONLINE'
117   - ? '../../static/online.png'
118   - : item.deviceState === 'INACTIVE'
119   - ? '../../static/secondary.png'
120   - : '../../static/baojing.png'
121   - "
122   - />
  71 + :src="item.deviceState === 'ONLINE' ? '../../static/online.png' : item.deviceState === 'INACTIVE' ? '../../static/unonline.png' : '../../static/baojing.png'"
  72 + />
123 73
124   - <view>
125   - <text
126   - style="
  74 + <view>
  75 + <text
  76 + style="
127 77 color: #377dff;
128 78 font-size: 13px;
129 79 margin-left: 5rpx;
130 80 margin-top: 20rpx;
131 81 "
132   - >
133   - {{
134   - item.deviceState === "ONLINE"
135   - ? "在线"
136   - : item.deviceState === "INACTIVE"
137   - ? "待激活"
138   - : "离线"
139   - }}
140   - </text>
141   - </view>
142   - </view>
143   - </view>
144   - </view>
145   - </view>
146   - </mescroll-body>
147   - <!-- 设备筛选 -->
148   - <u-popup
149   - @close="close"
150   - closeable
151   - bgColor="#fff"
152   - :show="show"
153   - mode="bottom"
154   - :round="20"
155   - >
156   - <view>
157   - <view style="text-align: center; margin-top: 28rpx"
158   - ><text>筛选条件</text></view
159   - >
  82 + :style="{ color: item.deviceState === 'ONLINE' ? '#377DFF' : item.deviceState === 'INACTIVE' ? '#666666' : '#DE4437' }"
  83 + >
  84 + {{ item.deviceState === 'ONLINE' ? '在线' : item.deviceState === 'INACTIVE' ? '待激活' : '离线' }}
  85 + </text>
  86 + </view>
  87 + </view>
  88 + </view>
  89 + </view>
  90 + </view>
  91 + </mescroll-body>
  92 + <!-- 设备筛选 -->
  93 + <u-popup @close="close" closeable bgColor="#fff" :show="show" mode="bottom" :round="20">
  94 + <view>
  95 + <view style="text-align: center; margin-top: 28rpx"><text>筛选条件</text></view>
160 96
161   - <FilterItem
162   - :filterList="deviceStatus"
163   - title="设备状态"
164   - @clickTag="
165   - (currentIndex) => handleClickTag(currentIndex, deviceStatus)
166   - "
167   - ></FilterItem>
168   - <FilterItem
169   - :filterList="alarmStatus"
170   - title="告警状态"
171   - @clickTag="
172   - (currentIndex) => handleClickTag(currentIndex, alarmStatus)
173   - "
174   - ></FilterItem>
175   - <FilterItem
176   - :filterList="typeStatus"
177   - title="设备类型"
178   - @clickTag="(currentIndex) => handleClickTag(currentIndex, typeStatus)"
179   - ></FilterItem>
180   - <view class="u-flex" style="margin-top: 40rpx; margin-left: 55rpx">
181   - <view style="width: 300rpx"
182   - ><u-button
183   - type="info"
184   - shape="circle"
185   - text="重置"
186   - @click="resetFilter"
187   - ></u-button
188   - ></view>
189   - <view style="width: 300rpx; margin-left: 46rpx"
190   - ><u-button
191   - type="primary"
192   - shape="circle"
193   - text="确认"
194   - @click="confirmFilter"
195   - ></u-button
196   - ></view>
197   - </view>
198   - </view>
199   - </u-popup>
200   - <f-tabbar></f-tabbar>
201   - </view>
  97 + <FilterItem :filterList="deviceStatus" title="设备状态" @clickTag="currentIndex => handleClickTag(currentIndex, deviceStatus)"></FilterItem>
  98 + <FilterItem :filterList="alarmStatus" title="告警状态" @clickTag="currentIndex => handleClickTag(currentIndex, alarmStatus)"></FilterItem>
  99 + <FilterItem :filterList="typeStatus" title="设备类型" @clickTag="currentIndex => handleClickTag(currentIndex, typeStatus)"></FilterItem>
  100 + <view class="u-flex" style="margin-top: 40rpx; margin-left: 55rpx">
  101 + <view style="width: 300rpx"><u-button type="info" shape="circle" text="重置" @click="resetFilter"></u-button></view>
  102 + <view style="width: 300rpx; margin-left: 46rpx"><u-button type="primary" shape="circle" text="确认" @click="confirmFilter"></u-button></view>
  103 + </view>
  104 + </view>
  105 + </u-popup>
  106 + <f-tabbar></f-tabbar>
  107 + </view>
202 108 </template>
203 109
204 110 <script>
205   -import fTabbar from "@/components/module/f-tabbar/f-tabbar";
206   -import fNavbar from "@/components/module/f-navbar/f-navbar";
207   -import FilterItem from "./FilterItem.vue";
208   -import MescrollMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js";
209   -import { debounce } from "@/plugins/throttle.js";
  111 +import fTabbar from '@/components/module/f-tabbar/f-tabbar';
  112 +import fNavbar from '@/components/module/f-navbar/f-navbar';
  113 +import FilterItem from './FilterItem.vue';
  114 +import MescrollMixin from '@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js';
  115 +import { debounce } from '@/plugins/throttle.js';
210 116 export default {
211   - mixins: [MescrollMixin], // 使用mixin (在main.js注册全局组件)
212   - components: {
213   - fTabbar,
214   - fNavbar,
215   - FilterItem,
216   - },
217   - data() {
218   - return {
219   - downOption: {
220   - auto: false, //是否在初始化后,自动执行downCallback; 默认true
221   - },
222   - show: false,
223   - deviceStatus: [
224   - {
225   - checked: true,
226   - name: "全部",
227   - type: "",
228   - },
229   - {
230   - checked: false,
231   - name: "在线",
232   - type: "ONLINE",
233   - },
234   - {
235   - checked: false,
236   - name: "离线",
237   - type: "OFFLINE",
238   - },
239   - {
240   - checked: false,
241   - name: "待激活",
242   - type: "INACTIVE",
243   - },
244   - ],
245   - alarmStatus: [
246   - {
247   - checked: true,
248   - name: "全部",
249   - type: "",
250   - },
251   - {
252   - checked: false,
253   - name: "告警",
254   - type: "1",
255   - },
256   - {
257   - checked: false,
258   - name: "正常",
259   - type: "0",
260   - },
261   - ],
262   - typeStatus: [
263   - {
264   - checked: true,
265   - name: "全部",
266   - type: "",
267   - },
268   - {
269   - checked: false,
270   - name: "直连设备",
271   - type: "DIRECT_CONNECTION",
272   - },
273   - {
274   - checked: false,
275   - name: "网关设备",
276   - type: "GATEWAY",
277   - },
278   - {
279   - checked: false,
280   - name: "网关子设备",
281   - type: "SENSOR",
282   - },
283   - ],
284   - total: 0,
285   - list: [],
286   - };
287   - },
288   - onLoad() {
289   - // 隐藏原生的tabbar
290   - uni.hideTabBar();
291   - },
292   - onShow() {
293   - if (this.orgId) {
294   - this.loadData(1, {
295   - organizationId: this.orgId,
296   - });
297   - }
298   - },
299   - methods: {
300   - /*下拉刷新的回调 */
301   - downCallback() {
302   - //联网加载数据
303   - this.loadData(1);
304   - },
305   - /*上拉加载的回调: 其中page.num:当前页 从1开始, page.size:每页数据条数,默认10 */
306   - upCallback(page) {
307   - //联网加载数据
308   - console.log(page);
309   - this.loadData(page.num);
310   - },
  117 + mixins: [MescrollMixin], // 使用mixin (在main.js注册全局组件)
  118 + components: {
  119 + fTabbar,
  120 + fNavbar,
  121 + FilterItem
  122 + },
  123 + data() {
  124 + return {
  125 + downOption: {
  126 + auto: false //是否在初始化后,自动执行downCallback; 默认true
  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'
  161 + },
  162 + {
  163 + checked: false,
  164 + name: '正常',
  165 + type: '0'
  166 + }
  167 + ],
  168 + typeStatus: [
  169 + {
  170 + checked: true,
  171 + name: '全部',
  172 + type: ''
  173 + },
  174 + {
  175 + checked: false,
  176 + name: '直连设备',
  177 + type: 'DIRECT_CONNECTION'
  178 + },
  179 + {
  180 + checked: false,
  181 + name: '网关设备',
  182 + type: 'GATEWAY'
  183 + },
  184 + {
  185 + checked: false,
  186 + name: '网关子设备',
  187 + type: 'SENSOR'
  188 + }
  189 + ],
  190 + total: 0,
  191 + list: [],
  192 + page: {
  193 + num: 0,
  194 + size: 10
  195 + }
  196 + };
  197 + },
  198 + onLoad() {
  199 + // 隐藏原生的tabbar
  200 + uni.hideTabBar();
  201 + },
  202 + onShow() {
  203 + if (this.orgId) {
  204 + this.loadData(1, {
  205 + organizationId: this.orgId
  206 + });
  207 + }
  208 + },
  209 + methods: {
  210 + /*下拉刷新的回调 */
  211 + downCallback() {
  212 + //联网加载数据
  213 + this.list = [];
  214 + this.page.num = 1;
  215 + //联网加载数据
  216 + this.loadData(this.page.num);
  217 + },
  218 +
  219 + /*上拉加载的回调: 其中page.num:当前页 从1开始, page.size:每页数据条数,默认10 */
  220 + upCallback() {
  221 + //联网加载数据
  222 + this.page.num += 1;
  223 + this.loadData(this.page.num);
  224 + },
311 225
312   - //获取设备
313   - loadData(pageNo, params = {}) {
314   - let httpData = {
315   - page: pageNo,
316   - pageSize: 10,
317   - ...params,
318   - };
319   - uni.$u.http
320   - .get("/yt/device", {
321   - params: httpData,
322   - custom: {
323   - load: false,
324   - },
325   - })
326   - .then((res) => {
327   - this.total = res.total;
328   - uni.stopPullDownRefresh();
329   - console.log("获取后端数据", res);
330   - //方法一(推荐): 后台接口有返回列表的总页数 totalPage
331   - this.mescroll.endByPage(res.total, Math.ceil(res.total / 10)); //必传参数(当前页的数据个数, 总页数)
332   - if (pageNo == 1) {
333   - this.list = res.items;
334   - } else {
335   - this.list = this.list.concat(res.items);
336   - }
337   - })
338   - .catch(() => {
339   - //联网失败, 结束加载
340   - this.mescroll.endErr();
341   - });
342   - },
343   - openOrg() {
344   - uni.navigateTo({
345   - url: "./org/org",
346   - });
347   - },
348   - close() {
349   - this.resetFilter();
350   - this.show = false;
351   - },
352   - openSearchDialog() {
353   - this.show = true;
354   - },
355   - openDeviceDetail(id, alarmStatus, lastOnlineTime, tbDeviceId) {
356   - uni.navigateTo({
357   - url: `/deviceSubPage/deviceDetailPage/deviceDetail?id=${id}&alarmStatus=${alarmStatus}&lastOnlineTime=${lastOnlineTime}&tbDeviceId=${tbDeviceId}`,
358   - });
359   - },
360   - handleClickTag(currentIndex, list) {
361   - list.map((item, index) => {
362   - item.checked = index === currentIndex;
363   - });
364   - },
365   - resetFilter() {
366   - const { deviceStatus, alarmStatus, typeStatus } = this;
367   - [deviceStatus, alarmStatus, typeStatus].forEach((item) =>
368   - item.map((item, index) => (item.checked = index === 0))
369   - );
370   - },
371   - confirmFilter() {
372   - const deviceState = this.deviceStatus.find((item) => item.checked);
373   - const alarmStatus = this.alarmStatus.find((item) => item.checked);
374   - const deviceType = this.typeStatus.find((item) => item.checked);
375   - this.loadData(1, {
376   - deviceState: deviceState.type ? deviceState.type : undefined,
377   - deviceType: deviceType.type ? deviceType.type : undefined,
378   - alarmStatus:
379   - alarmStatus.type === "0" || alarmStatus.type === "1"
380   - ? alarmStatus.type
381   - : undefined,
382   - });
383   - this.show = false;
384   - },
385   - inputChanged: debounce(function (name) {
386   - this.loadData(1, {
387   - name,
388   - });
389   - }, 500),
390   - },
  226 + //获取设备
  227 + loadData(pageNo, params = {}) {
  228 + let httpData = {
  229 + page: pageNo,
  230 + pageSize: 10,
  231 + ...params
  232 + };
  233 + uni.$u.http
  234 + .get('/yt/device', {
  235 + params: httpData,
  236 + custom: {
  237 + load: false
  238 + }
  239 + })
  240 + .then(res => {
  241 + this.total = res.total;
  242 + uni.stopPullDownRefresh();
  243 + console.log('获取后端数据', res);
  244 + //方法一(推荐): 后台接口有返回列表的总页数 totalPage
  245 + this.mescroll.endByPage(res.items.length, res.total); //必传参数(当前页的数据个数, 总页数)
  246 + if (pageNo == 1) {
  247 + this.list = res.items;
  248 + } else {
  249 + this.list = this.list.concat(res.items);
  250 + }
  251 + })
  252 + .catch(() => {
  253 + //联网失败, 结束加载
  254 + this.mescroll.endErr();
  255 + });
  256 + },
  257 + openOrg() {
  258 + uni.navigateTo({
  259 + url: './org/org'
  260 + });
  261 + },
  262 + close() {
  263 + this.resetFilter();
  264 + this.show = false;
  265 + },
  266 + openSearchDialog() {
  267 + this.show = true;
  268 + },
  269 + openDeviceDetail(id, alarmStatus, lastOnlineTime, tbDeviceId) {
  270 + uni.navigateTo({
  271 + url: `/deviceSubPage/deviceDetailPage/deviceDetail?id=${id}&alarmStatus=${alarmStatus}&lastOnlineTime=${lastOnlineTime}&tbDeviceId=${tbDeviceId}`
  272 + });
  273 + },
  274 + handleClickTag(currentIndex, list) {
  275 + list.map((item, index) => {
  276 + item.checked = index === currentIndex;
  277 + });
  278 + },
  279 + resetFilter() {
  280 + const { deviceStatus, alarmStatus, typeStatus } = this;
  281 + [deviceStatus, alarmStatus, typeStatus].forEach(item => item.map((item, index) => (item.checked = index === 0)));
  282 + },
  283 + confirmFilter() {
  284 + const deviceState = this.deviceStatus.find(item => item.checked);
  285 + const alarmStatus = this.alarmStatus.find(item => item.checked);
  286 + const deviceType = this.typeStatus.find(item => item.checked);
  287 + this.loadData(1, {
  288 + deviceState: deviceState.type ? deviceState.type : undefined,
  289 + deviceType: deviceType.type ? deviceType.type : undefined,
  290 + alarmStatus: alarmStatus.type === '0' || alarmStatus.type === '1' ? alarmStatus.type : undefined
  291 + });
  292 + this.show = false;
  293 + },
  294 + inputChanged: debounce(function(name) {
  295 + this.loadData(1, {
  296 + name
  297 + });
  298 + }, 500)
  299 + }
391 300 };
392 301 </script>
393 302
394 303 <style lang="scss" scoped>
395 304 .device-page {
396   - min-height: 100vh;
397   - background-color: #f8f9fa;
  305 + min-height: 100vh;
  306 + background-color: #f8f9fa;
398 307 }
399 308
400 309 .org-sty {
401   - width: 750rpx;
402   - height: 150rpx;
403   - margin-top: 1rpx;
404   - background-color: #fff;
405   - display: flex;
406   - justify-content: space-between;
  310 + width: 750rpx;
  311 + height: 150rpx;
  312 + margin-top: 1rpx;
  313 + background-color: #fff;
  314 + display: flex;
  315 + justify-content: space-between;
407 316
408   - .org-item {
409   - width: 350rpx;
410   - height: 200rpx;
411   - }
  317 + .org-item {
  318 + width: 350rpx;
  319 + height: 200rpx;
  320 + }
412 321 }
413 322
414 323 .device-list {
415   - display: flex;
416   - flex-direction: column;
417   - padding-left: 20rpx;
  324 + display: flex;
  325 + flex-direction: column;
  326 + padding-left: 20rpx;
418 327
419   - .list-item {
420   - width: 713rpx;
421   - height: 200rpx;
422   - background-color: #fff;
423   - margin-top: 24rpx;
424   - display: flex;
425   - border-radius: 10px;
426   - justify-content: space-between;
  328 + .list-item {
  329 + width: 713rpx;
  330 + height: 200rpx;
  331 + background-color: #fff;
  332 + margin-top: 24rpx;
  333 + display: flex;
  334 + border-radius: 10px;
  335 + justify-content: space-between;
427 336
428   - .item {
429   - margin: 30rpx;
430   - }
431   - }
  337 + .item {
  338 + margin: 30rpx;
  339 + }
  340 + }
432 341 }
433   -</style>
  342 +</style>
... ...
1   -<template>
2   - <view class="org-content">
3   - <!-- 公共组件-每个页面必须引入 -->
4   - <public-module></public-module>
5   - <view>
6   - <luyj-tree @sendValue="confirm" :is-check="isCheck" search-placeholder="请输入搜索内容" :search-if="true" v-slot:default="{ item }" :max="max" :trees="tree" :nodes="false">
7   - <view>
8   - <view class="content-item">
9   - <view class="word">{{ item.name }}</view>
10   - </view>
11   - </view>
12   - </luyj-tree>
13   - </view>
14   - </view>
15   -</template>
16   -
17   -<script>
18   -import fTabbar from '@/components/module/f-tabbar/f-tabbar';
19   -import { transOrgFunc } from '@/config/common.js';
20   -export default {
21   - components: {
22   - fTabbar
23   - },
24   - data() {
25   - return {
26   - isCheck: true, // 是否可选
27   - tree: [],
28   - max: 5,
29   - id: ''
30   - };
31   - },
32   - onLoad(e) {
33   - // 隐藏原生的tabbar
34   - uni.hideTabBar();
35   - this.loadData();
36   - },
37   - methods: {
38   - loadData() {
39   - uni.$u.http
40   - .get('/yt/organization/me/list')
41   - .then(res => {
42   - if (res) {
43   - const list = transOrgFunc(res);
44   - this.tree = list;
45   - }
46   - })
47   - .catch(e => {
48   - uni.$u.toast(e.data.message);
49   - });
50   - },
51   - confirm(val) {
52   - this.id = val[0].id;
53   - let pages = getCurrentPages(); //获取所有页面栈实例列表
54   - let nowPage = pages[pages.length - 1]; //当前页页面实例
55   - let prevPage = pages[pages.length - 2]; //上一页页面实例
56   - prevPage.$vm.orgId = this.id;
57   - uni.navigateBack({
58   - delta: 1
59   - });
60   - }
61   - }
62   -};
63   -</script>
64   -
65   -<style lang="scss" scoped>
66   -.org-content {
67   - padding: 0 10rpx;
68   -}
  1 +<template>
  2 + <view class="org-content">
  3 + <!-- 公共组件-每个页面必须引入 -->
  4 + <public-module></public-module>
  5 + <view>
  6 + <luyj-tree @sendValue="confirm" :is-check="isCheck" search-placeholder="请输入搜索内容" :search-if="true" v-slot:default="{ item }" :max="max" :trees="tree" :nodes="false">
  7 + <view>
  8 + <view class="content-item">
  9 + <view class="word">{{ item.name }}</view>
  10 + </view>
  11 + </view>
  12 + </luyj-tree>
  13 + </view>
  14 + </view>
  15 +</template>
  16 +
  17 +<script>
  18 +import fTabbar from '@/components/module/f-tabbar/f-tabbar';
  19 +import { transOrgFunc } from '@/config/common.js';
  20 +export default {
  21 + components: {
  22 + fTabbar
  23 + },
  24 + data() {
  25 + return {
  26 + isCheck: true, // 是否可选
  27 + tree: [],
  28 + max: 5,
  29 + id: ''
  30 + };
  31 + },
  32 + onLoad(e) {
  33 + // 隐藏原生的tabbar
  34 + uni.hideTabBar();
  35 + this.loadData();
  36 + },
  37 + methods: {
  38 + loadData() {
  39 + uni.$u.http
  40 + .get('/yt/organization/me/list')
  41 + .then(res => {
  42 + if (res) {
  43 + const list = transOrgFunc(res);
  44 + this.tree = list;
  45 + }
  46 + })
  47 + .catch(e => {
  48 + uni.$u.toast(e.data.message);
  49 + });
  50 + },
  51 + confirm(val) {
  52 + this.id = val[0].id;
  53 + let pages = getCurrentPages(); //获取所有页面栈实例列表
  54 + let nowPage = pages[pages.length - 1]; //当前页页面实例
  55 + let prevPage = pages[pages.length - 2]; //上一页页面实例
  56 + prevPage.$vm.orgId = this.id;
  57 + uni.navigateBack({
  58 + delta: 1
  59 + });
  60 + }
  61 + }
  62 +};
  63 +</script>
  64 +
  65 +<style lang="scss" scoped>
  66 +.org-content {
  67 + padding: 0 10rpx;
  68 +}
69 69 </style>
... ...

1004 Bytes